1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.estimation.measurements.modifiers;
18
19 import java.util.Arrays;
20 import java.util.List;
21
22 import org.hipparchus.Field;
23 import org.hipparchus.CalculusFieldElement;
24 import org.hipparchus.analysis.differentiation.Gradient;
25 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
26 import org.hipparchus.geometry.euclidean.threed.Vector3D;
27 import org.orekit.attitudes.InertialProvider;
28 import org.orekit.estimation.measurements.EstimatedMeasurement;
29 import org.orekit.estimation.measurements.EstimationModifier;
30 import org.orekit.estimation.measurements.GroundStation;
31 import org.orekit.estimation.measurements.Range;
32 import org.orekit.models.earth.troposphere.DiscreteTroposphericModel;
33 import org.orekit.propagation.FieldSpacecraftState;
34 import org.orekit.propagation.SpacecraftState;
35 import org.orekit.utils.Differentiation;
36 import org.orekit.utils.ParameterDriver;
37 import org.orekit.utils.ParameterFunction;
38
39
40
41
42
43
44
45
46
47
48
49
50 public class RangeTroposphericDelayModifier implements EstimationModifier<Range> {
51
52
53 private final DiscreteTroposphericModel tropoModel;
54
55
56
57
58
59 public RangeTroposphericDelayModifier(final DiscreteTroposphericModel model) {
60 tropoModel = model;
61 }
62
63
64
65
66
67
68 private double rangeErrorTroposphericModel(final GroundStation station, final SpacecraftState state) {
69
70 final Vector3D position = state.getPVCoordinates().getPosition();
71
72
73 final double elevation = station.getBaseFrame().getElevation(position,
74 state.getFrame(),
75 state.getDate());
76
77
78 if (elevation > 0) {
79
80 final double delay = tropoModel.pathDelay(elevation, station.getBaseFrame().getPoint(), tropoModel.getParameters(), state.getDate());
81
82 return delay;
83 }
84
85 return 0;
86 }
87
88
89
90
91
92
93
94
95 private <T extends CalculusFieldElement<T>> T rangeErrorTroposphericModel(final GroundStation station,
96 final FieldSpacecraftState<T> state,
97 final T[] parameters) {
98
99
100 final Field<T> field = state.getDate().getField();
101 final T zero = field.getZero();
102
103
104 final FieldVector3D<T> position = state.getPVCoordinates().getPosition();
105 final T elevation = station.getBaseFrame().getElevation(position,
106 state.getFrame(),
107 state.getDate());
108
109
110
111 if (elevation.getReal() > 0) {
112
113 final T delay = tropoModel.pathDelay(elevation, station.getBaseFrame().getPoint(field), parameters, state.getDate());
114
115 return delay;
116 }
117
118 return zero;
119 }
120
121
122
123
124
125
126
127
128 private double[][] rangeErrorJacobianState(final double[] derivatives) {
129 final double[][] finiteDifferencesJacobian = new double[1][6];
130 System.arraycopy(derivatives, 0, finiteDifferencesJacobian[0], 0, 6);
131 return finiteDifferencesJacobian;
132 }
133
134
135
136
137
138
139
140
141 private double rangeErrorParameterDerivative(final GroundStation station,
142 final ParameterDriver driver,
143 final SpacecraftState state) {
144
145 final ParameterFunction rangeError = new ParameterFunction() {
146
147 @Override
148 public double value(final ParameterDriver parameterDriver) {
149 return rangeErrorTroposphericModel(station, state);
150 }
151 };
152
153 final ParameterFunction rangeErrorDerivative =
154 Differentiation.differentiate(rangeError, 3, 10.0 * driver.getScale());
155
156 return rangeErrorDerivative.value(driver);
157
158 }
159
160
161
162
163
164
165
166
167 private double[] rangeErrorParameterDerivative(final double[] derivatives, final int freeStateParameters) {
168
169
170 final int dim = derivatives.length - freeStateParameters;
171 final double[] rangeError = new double[dim];
172
173 for (int i = 0; i < dim; i++) {
174 rangeError[i] = derivatives[freeStateParameters + i];
175 }
176
177 return rangeError;
178 }
179
180
181 @Override
182 public List<ParameterDriver> getParametersDrivers() {
183 return tropoModel.getParametersDrivers();
184 }
185
186
187 @Override
188 public void modify(final EstimatedMeasurement<Range> estimated) {
189 final Range measurement = estimated.getObservedMeasurement();
190 final GroundStation station = measurement.getStation();
191 final SpacecraftState state = estimated.getStates()[0];
192
193 final double[] oldValue = estimated.getEstimatedValue();
194
195
196 final TroposphericGradientConverter converter =
197 new TroposphericGradientConverter(state, 6, new InertialProvider(state.getFrame()));
198 final FieldSpacecraftState<Gradient> gState = converter.getState(tropoModel);
199 final Gradient[] gParameters = converter.getParameters(gState, tropoModel);
200 final Gradient gDelay = rangeErrorTroposphericModel(station, gState, gParameters);
201 final double[] derivatives = gDelay.getGradient();
202
203 final double[][] djac = rangeErrorJacobianState(derivatives);
204
205 final double[][] stateDerivatives = estimated.getStateDerivatives(0);
206 for (int irow = 0; irow < stateDerivatives.length; ++irow) {
207 for (int jcol = 0; jcol < stateDerivatives[0].length; ++jcol) {
208 stateDerivatives[irow][jcol] += djac[irow][jcol];
209 }
210 }
211 estimated.setStateDerivatives(0, stateDerivatives);
212
213 int index = 0;
214 for (final ParameterDriver driver : getParametersDrivers()) {
215 if (driver.isSelected()) {
216
217 double parameterDerivative = estimated.getParameterDerivatives(driver)[0];
218 final double[] dDelaydP = rangeErrorParameterDerivative(derivatives, converter.getFreeStateParameters());
219 parameterDerivative += dDelaydP[index];
220 estimated.setParameterDerivatives(driver, parameterDerivative);
221 index = index + 1;
222 }
223
224 }
225
226 for (final ParameterDriver driver : Arrays.asList(station.getClockOffsetDriver(),
227 station.getEastOffsetDriver(),
228 station.getNorthOffsetDriver(),
229 station.getZenithOffsetDriver())) {
230 if (driver.isSelected()) {
231
232 double parameterDerivative = estimated.getParameterDerivatives(driver)[0];
233 parameterDerivative += rangeErrorParameterDerivative(station, driver, state);
234 estimated.setParameterDerivatives(driver, parameterDerivative);
235 }
236 }
237
238
239
240 final double[] newValue = oldValue.clone();
241 newValue[0] = newValue[0] + gDelay.getReal();
242 estimated.setEstimatedValue(newValue);
243
244 }
245
246 }