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.RealFieldElement;
24 import org.hipparchus.analysis.differentiation.DerivativeStructure;
25 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
26 import org.hipparchus.geometry.euclidean.threed.Vector3D;
27 import org.orekit.estimation.measurements.EstimatedMeasurement;
28 import org.orekit.estimation.measurements.EstimationModifier;
29 import org.orekit.estimation.measurements.GroundStation;
30 import org.orekit.estimation.measurements.TurnAroundRange;
31 import org.orekit.models.earth.DiscreteTroposphericModel;
32 import org.orekit.models.earth.TroposphericModel;
33 import org.orekit.orbits.OrbitType;
34 import org.orekit.orbits.PositionAngle;
35 import org.orekit.propagation.FieldSpacecraftState;
36 import org.orekit.propagation.Propagator;
37 import org.orekit.propagation.SpacecraftState;
38 import org.orekit.utils.Differentiation;
39 import org.orekit.utils.ParameterDriver;
40 import org.orekit.utils.ParameterFunction;
41 import org.orekit.utils.StateFunction;
42
43
44
45
46
47
48
49
50
51
52
53 public class TurnAroundRangeTroposphericDelayModifier implements EstimationModifier<TurnAroundRange> {
54
55
56 private final DiscreteTroposphericModel tropoModel;
57
58
59
60
61
62 public TurnAroundRangeTroposphericDelayModifier(final DiscreteTroposphericModel model) {
63 tropoModel = model;
64 }
65
66
67
68
69
70
71 private double getStationHeightAMSL(final GroundStation station) {
72
73 final double height = station.getBaseFrame().getPoint().getAltitude();
74 return height;
75 }
76
77
78
79
80
81
82
83 private <T extends RealFieldElement<T>> T getStationHeightAMSL(final Field<T> field,
84 final GroundStation station) {
85
86 final T height = station.getBaseFrame().getPoint(field).getAltitude();
87 return height;
88 }
89
90
91
92
93
94
95 private double rangeErrorTroposphericModel(final GroundStation station, final SpacecraftState state) {
96
97 final Vector3D position = state.getPVCoordinates().getPosition();
98
99
100 final double elevation = station.getBaseFrame().getElevation(position,
101 state.getFrame(),
102 state.getDate());
103
104
105 if (elevation > 0) {
106
107 final double height = getStationHeightAMSL(station);
108
109
110 final double delay = tropoModel.pathDelay(elevation, height, tropoModel.getParameters(), state.getDate());
111
112 return delay;
113 }
114
115 return 0;
116 }
117
118
119
120
121
122
123
124
125 private <T extends RealFieldElement<T>> T rangeErrorTroposphericModel(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 final FieldVector3D<T> position = state.getPVCoordinates().getPosition();
134 final T dsElevation = station.getBaseFrame().getElevation(position,
135 state.getFrame(),
136 state.getDate());
137
138
139 if (dsElevation.getReal() > 0) {
140
141 final T height = getStationHeightAMSL(field, station);
142
143
144 final T delay = tropoModel.pathDelay(dsElevation, height, parameters, state.getDate());
145
146 return delay;
147 }
148
149 return zero;
150 }
151
152
153
154
155
156
157
158
159 private double[][] rangeErrorJacobianState(final GroundStation station, final SpacecraftState refstate) {
160 final double[][] finiteDifferencesJacobian =
161 Differentiation.differentiate(new StateFunction() {
162 public double[] value(final SpacecraftState state) {
163
164 final double value = rangeErrorTroposphericModel(station, state);
165
166 return new double[] {value };
167 }
168 }, 1, Propagator.DEFAULT_LAW, OrbitType.CARTESIAN,
169 PositionAngle.TRUE, 15.0, 3).value(refstate);
170
171 return finiteDifferencesJacobian;
172 }
173
174
175
176
177
178
179
180
181
182 private double[][] rangeErrorJacobianState(final double[] derivatives, final int freeStateParameters) {
183 final double[][] finiteDifferencesJacobian = new double[1][6];
184 for (int i = 0; i < freeStateParameters; i++) {
185
186 finiteDifferencesJacobian[0][i] = derivatives[i + 1];
187 }
188 return finiteDifferencesJacobian;
189 }
190
191
192
193
194
195
196
197
198
199 private double rangeErrorParameterDerivative(final GroundStation station,
200 final ParameterDriver driver,
201 final SpacecraftState state) {
202
203 final ParameterFunctionParameterFunction">ParameterFunction rangeError = new ParameterFunction() {
204
205 @Override
206 public double value(final ParameterDriver parameterDriver) {
207 return rangeErrorTroposphericModel(station, state);
208 }
209 };
210
211 final ParameterFunction rangeErrorDerivative = Differentiation.differentiate(rangeError, 3, 10.0 * driver.getScale());
212
213 return rangeErrorDerivative.value(driver);
214
215 }
216
217
218
219
220
221
222
223
224 private double[] rangeErrorParameterDerivative(final double[] derivatives, final int freeStateParameters) {
225
226
227
228 final int dim = derivatives.length - 1 - freeStateParameters;
229 final double[] rangeError = new double[dim];
230
231 for (int i = 0; i < dim; i++) {
232 rangeError[i] = derivatives[1 + freeStateParameters + i];
233 }
234
235 return rangeError;
236 }
237
238
239 @Override
240 public List<ParameterDriver> getParametersDrivers() {
241 return tropoModel.getParametersDrivers();
242 }
243
244
245 @Override
246 public void modify(final EstimatedMeasurement<TurnAroundRange> estimated) {
247 final TurnAroundRange measurement = estimated.getObservedMeasurement();
248 final GroundStation masterStation = measurement.getMasterStation();
249 final GroundStation slaveStation = measurement.getSlaveStation();
250 final SpacecraftState state = estimated.getStates()[0];
251
252 final double[] oldValue = estimated.getEstimatedValue();
253
254
255 final TroposphericDSConverterTroposphericDSConverter.html#TroposphericDSConverter">TroposphericDSConverter converter = new TroposphericDSConverter(state, 6, Propagator.DEFAULT_LAW);
256 final FieldSpacecraftState<DerivativeStructure> dsState = converter.getState(tropoModel);
257 final DerivativeStructure[] dsParameters = converter.getParameters(dsState, tropoModel);
258 final DerivativeStructure masterDSDelay = rangeErrorTroposphericModel(masterStation, dsState, dsParameters);
259 final DerivativeStructure slaveDSDelay = rangeErrorTroposphericModel(slaveStation, dsState, dsParameters);
260 final double[] masterDerivatives = masterDSDelay.getAllDerivatives();
261 final double[] slaveDerivatives = masterDSDelay.getAllDerivatives();
262
263 double[][] masterDjac = new double[1][6];
264 double[][] slaveDjac = new double[1][6];
265
266
267 if (tropoModel instanceof TroposphericModel) {
268 masterDjac = rangeErrorJacobianState(masterStation, state);
269 slaveDjac = rangeErrorJacobianState(slaveStation, state);
270 } else {
271 masterDjac = rangeErrorJacobianState(masterDerivatives, converter.getFreeStateParameters());
272 slaveDjac = rangeErrorJacobianState(slaveDerivatives, converter.getFreeStateParameters());
273 }
274 final double[][] stateDerivatives = estimated.getStateDerivatives(0);
275 for (int irow = 0; irow < stateDerivatives.length; ++irow) {
276 for (int jcol = 0; jcol < stateDerivatives[0].length; ++jcol) {
277 stateDerivatives[irow][jcol] += masterDjac[irow][jcol] + slaveDjac[irow][jcol];
278 }
279 }
280 estimated.setStateDerivatives(0, stateDerivatives);
281
282 int indexMaster = 0;
283 for (final ParameterDriver driver : getParametersDrivers()) {
284 if (driver.isSelected()) {
285
286 double parameterDerivative = estimated.getParameterDerivatives(driver)[0];
287 final double[] derivatives = rangeErrorParameterDerivative(masterDerivatives, converter.getFreeStateParameters());
288 parameterDerivative += derivatives[indexMaster];
289 estimated.setParameterDerivatives(driver, parameterDerivative);
290 indexMaster += 1;
291 }
292
293 }
294
295 int indexSlave = 0;
296 for (final ParameterDriver driver : getParametersDrivers()) {
297 if (driver.isSelected()) {
298
299 double parameterDerivative = estimated.getParameterDerivatives(driver)[0];
300 final double[] derivatives = rangeErrorParameterDerivative(slaveDerivatives, converter.getFreeStateParameters());
301 parameterDerivative += derivatives[indexSlave];
302 estimated.setParameterDerivatives(driver, parameterDerivative);
303 indexSlave += 1;
304 }
305
306 }
307
308
309 for (final ParameterDriver driver : Arrays.asList(masterStation.getClockOffsetDriver(),
310 masterStation.getEastOffsetDriver(),
311 masterStation.getNorthOffsetDriver(),
312 masterStation.getZenithOffsetDriver())) {
313 if (driver.isSelected()) {
314 double parameterDerivative = estimated.getParameterDerivatives(driver)[0];
315 parameterDerivative += rangeErrorParameterDerivative(masterStation, driver, state);
316 estimated.setParameterDerivatives(driver, parameterDerivative);
317 }
318 }
319
320
321 for (final ParameterDriver driver : Arrays.asList(slaveStation.getEastOffsetDriver(),
322 slaveStation.getNorthOffsetDriver(),
323 slaveStation.getZenithOffsetDriver())) {
324 if (driver.isSelected()) {
325 double parameterDerivative = estimated.getParameterDerivatives(driver)[0];
326 parameterDerivative += rangeErrorParameterDerivative(slaveStation, driver, state);
327 estimated.setParameterDerivatives(driver, parameterDerivative);
328 }
329 }
330
331
332
333 final double[] newValue = oldValue.clone();
334 newValue[0] = newValue[0] + masterDSDelay.getReal() + slaveDSDelay.getReal();
335 estimated.setEstimatedValue(newValue);
336
337 }
338
339 }