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.RangeRate;
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 RangeRateTroposphericDelayModifier implements EstimationModifier<RangeRate> {
51
52
53 private final DiscreteTroposphericModel tropoModel;
54
55
56 private final double fTwoWay;
57
58
59
60
61
62
63 public RangeRateTroposphericDelayModifier(final DiscreteTroposphericModel model, final boolean tw) {
64 tropoModel = model;
65 if (tw) {
66 fTwoWay = 2.;
67 } else {
68 fTwoWay = 1.;
69 }
70 }
71
72
73
74
75
76
77 public double rangeRateErrorTroposphericModel(final GroundStation station,
78 final SpacecraftState state) {
79
80
81
82 final double dt = 10;
83
84
85 final Vector3D position = state.getPVCoordinates().getPosition();
86
87
88 final double elevation1 = station.getBaseFrame().getElevation(position,
89 state.getFrame(),
90 state.getDate());
91
92
93 if (elevation1 > 0) {
94
95 final double d1 = tropoModel.pathDelay(elevation1, station.getBaseFrame().getPoint(), tropoModel.getParameters(), state.getDate());
96
97
98 final SpacecraftState state2 = state.shiftedBy(dt);
99
100
101 final Vector3D position2 = state2.getPVCoordinates().getPosition();
102
103
104 final double elevation2 = station.getBaseFrame().getElevation(position2,
105 state2.getFrame(),
106 state2.getDate());
107
108
109 final double d2 = tropoModel.pathDelay(elevation2, station.getBaseFrame().getPoint(), tropoModel.getParameters(), state2.getDate());
110
111 return fTwoWay * (d2 - d1) / dt;
112 }
113
114 return 0;
115 }
116
117
118
119
120
121
122
123
124
125 public <T extends CalculusFieldElement<T>> T rangeRateErrorTroposphericModel(final GroundStation station,
126 final FieldSpacecraftState<T> state,
127 final T[] parameters) {
128
129 final Field<T> field = state.getDate().getField();
130 final T zero = field.getZero();
131
132
133
134
135 final double dt = 10;
136
137
138 final FieldVector3D<T> position = state.getPVCoordinates().getPosition();
139 final T elevation1 = station.getBaseFrame().getElevation(position,
140 state.getFrame(),
141 state.getDate());
142
143
144 if (elevation1.getReal() > 0) {
145
146 final T d1 = tropoModel.pathDelay(elevation1, station.getBaseFrame().getPoint(field), parameters, state.getDate());
147
148
149 final FieldSpacecraftState<T> state2 = state.shiftedBy(dt);
150
151
152 final FieldVector3D<T> position2 = state2.getPVCoordinates().getPosition();
153
154
155 final T elevation2 = station.getBaseFrame().getElevation(position2,
156 state2.getFrame(),
157 state2.getDate());
158
159
160
161 final T d2 = tropoModel.pathDelay(elevation2, station.getBaseFrame().getPoint(field), parameters, state2.getDate());
162
163 return (d2.subtract(d1)).divide(dt).multiply(fTwoWay);
164 }
165
166 return zero;
167 }
168
169
170
171
172
173
174
175
176 private double[][] rangeRateErrorJacobianState(final double[] derivatives) {
177 final double[][] finiteDifferencesJacobian = new double[1][6];
178 System.arraycopy(derivatives, 0, finiteDifferencesJacobian[0], 0, 6);
179 return finiteDifferencesJacobian;
180 }
181
182
183
184
185
186
187
188
189 private double rangeRateErrorParameterDerivative(final GroundStation station,
190 final ParameterDriver driver,
191 final SpacecraftState state) {
192
193 final ParameterFunction rangeError = new ParameterFunction() {
194
195 @Override
196 public double value(final ParameterDriver parameterDriver) {
197 return rangeRateErrorTroposphericModel(station, state);
198 }
199 };
200
201 final ParameterFunction rangeErrorDerivative =
202 Differentiation.differentiate(rangeError, 3, 10.0 * driver.getScale());
203
204 return rangeErrorDerivative.value(driver);
205
206 }
207
208
209
210
211
212
213
214
215 private double[] rangeRateErrorParameterDerivative(final double[] derivatives, final int freeStateParameters) {
216
217
218 final int dim = derivatives.length - freeStateParameters;
219 final double[] rangeError = new double[dim];
220
221 for (int i = 0; i < dim; i++) {
222 rangeError[i] = derivatives[freeStateParameters + i];
223 }
224
225 return rangeError;
226 }
227
228
229 @Override
230 public List<ParameterDriver> getParametersDrivers() {
231 return tropoModel.getParametersDrivers();
232 }
233
234
235 @Override
236 public void modify(final EstimatedMeasurement<RangeRate> estimated) {
237 final RangeRate measurement = estimated.getObservedMeasurement();
238 final GroundStation station = measurement.getStation();
239 final SpacecraftState state = estimated.getStates()[0];
240
241 final double[] oldValue = estimated.getEstimatedValue();
242
243
244 final TroposphericGradientConverter converter =
245 new TroposphericGradientConverter(state, 6, new InertialProvider(state.getFrame()));
246 final FieldSpacecraftState<Gradient> gState = converter.getState(tropoModel);
247 final Gradient[] gParameters = converter.getParameters(gState, tropoModel);
248 final Gradient gDelay = rangeRateErrorTroposphericModel(station, gState, gParameters);
249 final double[] derivatives = gDelay.getGradient();
250
251 final double[][] djac = rangeRateErrorJacobianState(derivatives);
252 final double[][] stateDerivatives = estimated.getStateDerivatives(0);
253 for (int irow = 0; irow < stateDerivatives.length; ++irow) {
254 for (int jcol = 0; jcol < stateDerivatives[0].length; ++jcol) {
255 stateDerivatives[irow][jcol] += djac[irow][jcol];
256 }
257 }
258 estimated.setStateDerivatives(0, stateDerivatives);
259
260 int index = 0;
261 for (final ParameterDriver driver : getParametersDrivers()) {
262 if (driver.isSelected()) {
263
264 double parameterDerivative = estimated.getParameterDerivatives(driver)[0];
265 final double[] dDelaydP = rangeRateErrorParameterDerivative(derivatives, converter.getFreeStateParameters());
266 parameterDerivative += dDelaydP[index];
267 estimated.setParameterDerivatives(driver, parameterDerivative);
268 index += 1;
269 }
270
271 }
272
273 for (final ParameterDriver driver : Arrays.asList(station.getClockOffsetDriver(),
274 station.getEastOffsetDriver(),
275 station.getNorthOffsetDriver(),
276 station.getZenithOffsetDriver())) {
277 if (driver.isSelected()) {
278
279 double parameterDerivative = estimated.getParameterDerivatives(driver)[0];
280 parameterDerivative += rangeRateErrorParameterDerivative(station, driver, state);
281 estimated.setParameterDerivatives(driver, parameterDerivative);
282 }
283 }
284
285
286
287 final double[] newValue = oldValue.clone();
288 newValue[0] = newValue[0] + gDelay.getReal();
289 estimated.setEstimatedValue(newValue);
290
291 }
292
293 }