1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.estimation.measurements;
18
19 import java.util.Arrays;
20 import java.util.HashMap;
21 import java.util.Map;
22
23 import org.hipparchus.Field;
24 import org.hipparchus.analysis.differentiation.DSFactory;
25 import org.hipparchus.analysis.differentiation.DerivativeStructure;
26 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
27 import org.orekit.frames.FieldTransform;
28 import org.orekit.propagation.SpacecraftState;
29 import org.orekit.time.AbsoluteDate;
30 import org.orekit.time.FieldAbsoluteDate;
31 import org.orekit.utils.Constants;
32 import org.orekit.utils.FieldPVCoordinates;
33 import org.orekit.utils.PVCoordinates;
34 import org.orekit.utils.ParameterDriver;
35 import org.orekit.utils.TimeStampedFieldPVCoordinates;
36 import org.orekit.utils.TimeStampedPVCoordinates;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public class TurnAroundRange extends AbstractMeasurement<TurnAroundRange> {
60
61
62 private final GroundStation masterStation;
63
64
65 private final GroundStation slaveStation;
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 @Deprecated
83 public TurnAroundRange(final GroundStationation.html#GroundStation">GroundStation masterStation, final GroundStation slaveStation,
84 final AbsoluteDate date, final double turnAroundRange,
85 final double sigma, final double baseWeight) {
86 this(masterStation, slaveStation, date, turnAroundRange, sigma, baseWeight, new ObservableSatellite(0));
87 }
88
89
90
91
92
93
94
95
96
97
98
99
100
101 @Deprecated
102 public TurnAroundRange(final GroundStationation.html#GroundStation">GroundStation masterStation, final GroundStation slaveStation,
103 final AbsoluteDate date, final double turnAroundRange,
104 final double sigma, final double baseWeight,
105 final int propagatorIndex) {
106 this(masterStation, slaveStation, date, turnAroundRange, sigma, baseWeight, new ObservableSatellite(propagatorIndex));
107 }
108
109
110
111
112
113
114
115
116
117
118
119 public TurnAroundRange(final GroundStationation.html#GroundStation">GroundStation masterStation, final GroundStation slaveStation,
120 final AbsoluteDate date, final double turnAroundRange,
121 final double sigma, final double baseWeight,
122 final ObservableSatellite satellite) {
123 super(date, turnAroundRange, sigma, baseWeight, Arrays.asList(satellite));
124 addParameterDriver(masterStation.getClockOffsetDriver());
125 addParameterDriver(masterStation.getEastOffsetDriver());
126 addParameterDriver(masterStation.getNorthOffsetDriver());
127 addParameterDriver(masterStation.getZenithOffsetDriver());
128 addParameterDriver(masterStation.getPrimeMeridianOffsetDriver());
129 addParameterDriver(masterStation.getPrimeMeridianDriftDriver());
130 addParameterDriver(masterStation.getPolarOffsetXDriver());
131 addParameterDriver(masterStation.getPolarDriftXDriver());
132 addParameterDriver(masterStation.getPolarOffsetYDriver());
133 addParameterDriver(masterStation.getPolarDriftYDriver());
134
135 addParameterDriver(slaveStation.getEastOffsetDriver());
136 addParameterDriver(slaveStation.getNorthOffsetDriver());
137 addParameterDriver(slaveStation.getZenithOffsetDriver());
138 addParameterDriver(slaveStation.getPrimeMeridianOffsetDriver());
139 addParameterDriver(slaveStation.getPrimeMeridianDriftDriver());
140 addParameterDriver(slaveStation.getPolarOffsetXDriver());
141 addParameterDriver(slaveStation.getPolarDriftXDriver());
142 addParameterDriver(slaveStation.getPolarOffsetYDriver());
143 addParameterDriver(slaveStation.getPolarDriftYDriver());
144 this.masterStation = masterStation;
145 this.slaveStation = slaveStation;
146 }
147
148
149
150
151 public GroundStation getMasterStation() {
152 return masterStation;
153 }
154
155
156
157
158 public GroundStation getSlaveStation() {
159 return slaveStation;
160 }
161
162
163 @Override
164 protected EstimatedMeasurement<TurnAroundRange> theoreticalEvaluation(final int iteration, final int evaluation,
165 final SpacecraftState[] states) {
166
167 final ObservableSatellite satellite = getSatellites().get(0);
168 final SpacecraftState state = states[satellite.getPropagatorIndex()];
169
170
171
172
173
174
175
176
177
178
179 int nbParams = 6;
180 final Map<String, Integer> indices = new HashMap<>();
181 for (ParameterDriver driver : getParametersDrivers()) {
182
183
184
185 if (driver.isSelected() && !indices.containsKey(driver.getName())) {
186 indices.put(driver.getName(), nbParams++);
187 }
188 }
189 final DSFactory factory = new DSFactory(nbParams, 1);
190 final Field<DerivativeStructure> field = factory.getDerivativeField();
191 final FieldVector3D<DerivativeStructure> zero = FieldVector3D.getZero(field);
192
193
194 final TimeStampedFieldPVCoordinates<DerivativeStructure> pvaDS = getCoordinates(state, 0, factory);
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217 final double delta = getDate().durationFrom(state.getDate());
218
219
220 final FieldTransform<DerivativeStructure> masterToInert =
221 masterStation.getOffsetToInertial(state.getFrame(), getDate(), factory, indices);
222 final FieldAbsoluteDate<DerivativeStructure> measurementDateDS =
223 masterToInert.getFieldDate();
224
225
226 final TimeStampedFieldPVCoordinates<DerivativeStructure> masterArrival =
227 masterToInert.transformPVCoordinates(new TimeStampedFieldPVCoordinates<>(measurementDateDS,
228 zero, zero, zero));
229
230
231 final DerivativeStructure masterTauD = signalTimeOfFlight(pvaDS, masterArrival.getPosition(), measurementDateDS);
232
233
234 final DerivativeStructure dtLeg2 = masterTauD.negate().add(delta);
235
236
237 final SpacecraftState transitStateLeg2 = state.shiftedBy(dtLeg2.getValue());
238
239
240 final TimeStampedFieldPVCoordinates<DerivativeStructure> transitStateLeg2PV = pvaDS.shiftedBy(dtLeg2);
241
242
243
244 final FieldAbsoluteDate<DerivativeStructure> approxReboundDate = measurementDateDS.shiftedBy(-delta);
245 final FieldTransform<DerivativeStructure> slaveToInertApprox =
246 slaveStation.getOffsetToInertial(state.getFrame(), approxReboundDate, factory, indices);
247
248
249 final TimeStampedFieldPVCoordinates<DerivativeStructure> QSlaveApprox =
250 slaveToInertApprox.transformPVCoordinates(new TimeStampedFieldPVCoordinates<>(approxReboundDate,
251 zero, zero, zero));
252
253
254 final DerivativeStructure slaveTauU = signalTimeOfFlight(QSlaveApprox,
255 transitStateLeg2PV.getPosition(),
256 transitStateLeg2PV.getDate());
257
258
259 final DerivativeStructure tauLeg2 = masterTauD.add(slaveTauU);
260
261
262
263
264
265 final FieldAbsoluteDate<DerivativeStructure> reboundDateDS = measurementDateDS.shiftedBy(tauLeg2.negate());
266 final FieldTransform<DerivativeStructure> slaveToInert =
267 slaveStation.getOffsetToInertial(state.getFrame(), reboundDateDS, factory, indices);
268
269
270 final TimeStampedFieldPVCoordinates<DerivativeStructure> slaveRebound =
271 slaveToInert.transformPVCoordinates(new TimeStampedFieldPVCoordinates<>(reboundDateDS,
272 FieldPVCoordinates.getZero(field)));
273
274
275 final DerivativeStructure slaveTauD = signalTimeOfFlight(transitStateLeg2PV,
276 slaveRebound.getPosition(),
277 reboundDateDS);
278
279
280
281 final DerivativeStructure dtLeg1 = dtLeg2.subtract(slaveTauU).subtract(slaveTauD);
282
283
284 final TimeStampedFieldPVCoordinates<DerivativeStructure> transitStateLeg1PV = pvaDS.shiftedBy(dtLeg1);
285
286
287
288 final FieldAbsoluteDate<DerivativeStructure> approxEmissionDate =
289 measurementDateDS.shiftedBy(-2 * (slaveTauU.getValue() + masterTauD.getValue()));
290 final FieldTransform<DerivativeStructure> masterToInertApprox =
291 masterStation.getOffsetToInertial(state.getFrame(), approxEmissionDate, factory, indices);
292
293
294 final TimeStampedFieldPVCoordinates<DerivativeStructure> QMasterApprox =
295 masterToInertApprox.transformPVCoordinates(new TimeStampedFieldPVCoordinates<>(approxEmissionDate,
296 zero, zero, zero));
297
298
299 final DerivativeStructure masterTauU = signalTimeOfFlight(QMasterApprox,
300 transitStateLeg1PV.getPosition(),
301 transitStateLeg1PV.getDate());
302
303
304 final AbsoluteDate emissionDate = transitStateLeg1PV.getDate().toAbsoluteDate().shiftedBy(-masterTauU.getValue());
305 final TimeStampedPVCoordinates masterDeparture =
306 masterToInertApprox.shiftedBy(emissionDate.durationFrom(masterToInertApprox.getDate())).
307 transformPVCoordinates(new TimeStampedPVCoordinates(emissionDate, PVCoordinates.ZERO)).
308 toTimeStampedPVCoordinates();
309
310
311 final DerivativeStructure tauLeg1 = slaveTauD.add(masterTauU);
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327 final EstimatedMeasurement<TurnAroundRange> estimated =
328 new EstimatedMeasurement<>(this, iteration, evaluation,
329 new SpacecraftState[] {
330 transitStateLeg2.shiftedBy(-slaveTauU.getValue())
331 },
332 new TimeStampedPVCoordinates[] {
333 masterDeparture,
334 transitStateLeg1PV.toTimeStampedPVCoordinates(),
335 slaveRebound.toTimeStampedPVCoordinates(),
336 transitStateLeg2.getPVCoordinates(),
337 masterArrival.toTimeStampedPVCoordinates()
338 });
339
340
341 final double cOver2 = 0.5 * Constants.SPEED_OF_LIGHT;
342 final DerivativeStructure turnAroundRange = (tauLeg2.add(tauLeg1)).multiply(cOver2);
343 estimated.setEstimatedValue(turnAroundRange.getValue());
344
345
346 final double[] derivatives = turnAroundRange.getAllDerivatives();
347 estimated.setStateDerivatives(0, Arrays.copyOfRange(derivatives, 1, 7));
348
349
350
351 for (final ParameterDriver driver : getParametersDrivers()) {
352 final Integer index = indices.get(driver.getName());
353 if (index != null) {
354 estimated.setParameterDerivatives(driver, derivatives[index + 1]);
355 }
356 }
357
358 return estimated;
359
360 }
361
362 }