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 org.hipparchus.util.MathUtils;
20 import org.hipparchus.util.Precision;
21 import org.junit.jupiter.api.Assertions;
22 import org.junit.jupiter.api.Test;
23 import org.orekit.estimation.Context;
24 import org.orekit.estimation.EstimationTestUtils;
25 import org.orekit.estimation.measurements.AngularAzEl;
26 import org.orekit.estimation.measurements.AngularAzElMeasurementCreator;
27 import org.orekit.estimation.measurements.BistaticRange;
28 import org.orekit.estimation.measurements.BistaticRangeMeasurementCreator;
29 import org.orekit.estimation.measurements.BistaticRangeRate;
30 import org.orekit.estimation.measurements.BistaticRangeRateMeasurementCreator;
31 import org.orekit.estimation.measurements.EstimatedMeasurement;
32 import org.orekit.estimation.measurements.EstimatedMeasurementBase;
33 import org.orekit.estimation.measurements.GroundStation;
34 import org.orekit.estimation.measurements.ObservedMeasurement;
35 import org.orekit.estimation.measurements.Range;
36 import org.orekit.estimation.measurements.RangeRate;
37 import org.orekit.estimation.measurements.RangeRateMeasurementCreator;
38 import org.orekit.estimation.measurements.TDOA;
39 import org.orekit.estimation.measurements.TDOAMeasurementCreator;
40 import org.orekit.estimation.measurements.TurnAroundRange;
41 import org.orekit.estimation.measurements.TurnAroundRangeMeasurementCreator;
42 import org.orekit.estimation.measurements.TwoWayRangeMeasurementCreator;
43 import org.orekit.estimation.measurements.gnss.Phase;
44 import org.orekit.estimation.measurements.gnss.PhaseMeasurementCreator;
45 import org.orekit.frames.TopocentricFrame;
46 import org.orekit.gnss.PredefinedGnssSignal;
47 import org.orekit.models.earth.ITURP834AtmosphericRefraction;
48 import org.orekit.models.earth.troposphere.EstimatedModel;
49 import org.orekit.models.earth.troposphere.ModifiedSaastamoinenModel;
50 import org.orekit.models.earth.troposphere.NiellMappingFunctionModel;
51 import org.orekit.models.earth.troposphere.TroposphericModelUtils;
52 import org.orekit.orbits.OrbitType;
53 import org.orekit.orbits.PositionAngleType;
54 import org.orekit.propagation.Propagator;
55 import org.orekit.propagation.SpacecraftState;
56 import org.orekit.propagation.conversion.NumericalPropagatorBuilder;
57 import org.orekit.time.AbsoluteDate;
58 import org.orekit.utils.ParameterDriver;
59
60 import java.util.List;
61 import java.util.Map;
62
63 public class TropoModifierTest {
64
65 @Test
66 public void testRangeTropoModifier() {
67
68 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
69
70 final NumericalPropagatorBuilder propagatorBuilder =
71 context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
72 1.0e-6, 60.0, 0.001);
73
74
75 for (final GroundStation station : context.stations) {
76 station.getClockOffsetDriver().setSelected(true);
77 station.getEastOffsetDriver().setSelected(true);
78 station.getNorthOffsetDriver().setSelected(true);
79 station.getZenithOffsetDriver().setSelected(true);
80 }
81 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
82 propagatorBuilder);
83 final List<ObservedMeasurement<?>> measurements =
84 EstimationTestUtils.createMeasurements(propagator,
85 new TwoWayRangeMeasurementCreator(context),
86 1.0, 3.0, 300.0);
87 propagator.clearStepHandlers();
88
89 final RangeTroposphericDelayModifier modifier =
90 new RangeTroposphericDelayModifier(ModifiedSaastamoinenModel.getStandardModel());
91
92 for (final ObservedMeasurement<?> measurement : measurements) {
93 final AbsoluteDate date = measurement.getDate();
94
95 final SpacecraftState refState = propagator.propagate(date);
96
97 Range range = (Range) measurement;
98 EstimatedMeasurementBase<Range> evalNoMod = range.estimateWithoutDerivatives(new SpacecraftState[] { refState });
99
100
101
102 range.addModifier(modifier);
103 EstimatedMeasurement<Range> eval = range.estimate(0, 0, new SpacecraftState[] { refState });
104
105 final double diffMeters = eval.getEstimatedValue()[0] - evalNoMod.getEstimatedValue()[0];
106
107 final double epsilon = 1e-6;
108 Assertions.assertTrue(Precision.compareTo(diffMeters, 12., epsilon) < 0);
109 Assertions.assertTrue(Precision.compareTo(diffMeters, 0., epsilon) > 0);
110 Assertions.assertEquals(evalNoMod.getEstimatedValue()[0],
111 eval.getOriginalEstimatedValue()[0],
112 3.0e-14 * evalNoMod.getEstimatedValue()[0]);
113 Assertions.assertEquals(eval.getEstimatedValue()[0] - eval.getOriginalEstimatedValue()[0],
114 eval.getAppliedEffects().get(modifier)[0],
115 1.0e-15);
116 Assertions.assertEquals(1,
117 eval.getAppliedEffects().entrySet().stream().
118 filter(e -> e.getKey().getEffectName().equals("troposphere")).count());
119 }
120 }
121
122 @Test
123 public void testRangeEstimatedTropoModifier() {
124
125 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
126
127 final NumericalPropagatorBuilder propagatorBuilder =
128 context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
129 1.0e-6, 60.0, 0.001);
130
131 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
132 propagatorBuilder);
133 final List<ObservedMeasurement<?>> measurements =
134 EstimationTestUtils.createMeasurements(propagator,
135 new TwoWayRangeMeasurementCreator(context),
136 1.0, 3.0, 300.0);
137 propagator.clearStepHandlers();
138
139 for (final ObservedMeasurement<?> measurement : measurements) {
140 final AbsoluteDate date = measurement.getDate();
141
142 final SpacecraftState refState = propagator.propagate(date);
143
144 Range range = (Range) measurement;
145 EstimatedMeasurementBase<Range> evalNoMod = range.estimateWithoutDerivatives(new SpacecraftState[] { refState });
146
147
148 final GroundStation stationParameter = ((Range) measurement).getStation();
149 final TopocentricFrame baseFrame = stationParameter.getBaseFrame();
150 final NiellMappingFunctionModel mappingFunction = new NiellMappingFunctionModel();
151 final EstimatedModel tropoModel = new EstimatedModel(mappingFunction, 5.0);
152 final RangeTroposphericDelayModifier modifier = new RangeTroposphericDelayModifier(tropoModel);
153
154 final ParameterDriver parameterDriver = modifier.getParametersDrivers().get(0);
155 parameterDriver.setSelected(true);
156 parameterDriver.setName(baseFrame.getName() + EstimatedModel.TOTAL_ZENITH_DELAY);
157 range.addModifier(modifier);
158 EstimatedMeasurementBase<Range> eval = range.estimateWithoutDerivatives(new SpacecraftState[] { refState });
159
160 final double diffMeters = eval.getEstimatedValue()[0] - evalNoMod.getEstimatedValue()[0];
161
162 final double epsilon = 1e-6;
163 Assertions.assertTrue(Precision.compareTo(diffMeters, 12., epsilon) < 0);
164 Assertions.assertTrue(Precision.compareTo(diffMeters, 0., epsilon) > 0);
165 }
166 }
167
168 @Test
169 public void testPhaseTropoModifier() {
170
171 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
172
173 final NumericalPropagatorBuilder propagatorBuilder =
174 context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
175 1.0e-6, 60.0, 0.001);
176
177
178 for (final GroundStation station : context.stations) {
179 station.getClockOffsetDriver().setSelected(true);
180 station.getEastOffsetDriver().setSelected(true);
181 station.getNorthOffsetDriver().setSelected(true);
182 station.getZenithOffsetDriver().setSelected(true);
183 }
184 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
185 propagatorBuilder);
186 final int ambiguity = 1234;
187 final double groundClockOffset = 12.0e-6;
188 for (final GroundStation station : context.stations) {
189 station.getClockOffsetDriver().setValue(groundClockOffset);
190 }
191 final double satClockOffset = 345.0e-6;
192 final List<ObservedMeasurement<?>> measurements =
193 EstimationTestUtils.createMeasurements(propagator,
194 new PhaseMeasurementCreator(context,
195 PredefinedGnssSignal.G01,
196 ambiguity,
197 satClockOffset),
198 1.0, 3.0, 300.0);
199 propagator.clearStepHandlers();
200
201 final PhaseTroposphericDelayModifier modifier =
202 new PhaseTroposphericDelayModifier(ModifiedSaastamoinenModel.getStandardModel());
203
204 for (final ObservedMeasurement<?> measurement : measurements) {
205 final AbsoluteDate date = measurement.getDate();
206
207 final SpacecraftState refState = propagator.propagate(date);
208
209 Phase phase = (Phase) measurement;
210 EstimatedMeasurementBase<Phase> evalNoMod = phase.estimateWithoutDerivatives(new SpacecraftState[] { refState });
211
212
213
214 phase.addModifier(modifier);
215 EstimatedMeasurementBase<Phase> eval = phase.estimateWithoutDerivatives(new SpacecraftState[] { refState });
216
217 final double diffMeters = (eval.getEstimatedValue()[0] - evalNoMod.getEstimatedValue()[0]) * phase.getWavelength();
218
219 final double epsilon = 1e-6;
220 Assertions.assertTrue(Precision.compareTo(diffMeters, 12., epsilon) < 0);
221 Assertions.assertTrue(Precision.compareTo(diffMeters, 0., epsilon) > 0);
222 }
223 }
224
225 @Test
226 public void testPhaseEstimatedTropoModifier() {
227
228 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
229
230 final NumericalPropagatorBuilder propagatorBuilder =
231 context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
232 1.0e-6, 60.0, 0.001);
233
234 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
235 propagatorBuilder);
236 final int ambiguity = 1234;
237 final double groundClockOffset = 12.0e-6;
238 for (final GroundStation station : context.stations) {
239 station.getClockOffsetDriver().setValue(groundClockOffset);
240 }
241 final double satClockOffset = 345.0e-6;
242 final List<ObservedMeasurement<?>> measurements =
243 EstimationTestUtils.createMeasurements(propagator,
244 new PhaseMeasurementCreator(context,
245 PredefinedGnssSignal.G01,
246 ambiguity,
247 satClockOffset),
248 1.0, 3.0, 300.0);
249 propagator.clearStepHandlers();
250
251 for (final ObservedMeasurement<?> measurement : measurements) {
252 final AbsoluteDate date = measurement.getDate();
253
254 final SpacecraftState refState = propagator.propagate(date);
255
256 Phase phase = (Phase) measurement;
257 EstimatedMeasurementBase<Phase> evalNoMod = phase.estimateWithoutDerivatives(new SpacecraftState[] { refState });
258
259
260
261 final GroundStation stationParameter = phase.getStation();
262 final TopocentricFrame baseFrame = stationParameter.getBaseFrame();
263 final NiellMappingFunctionModel mappingFunction = new NiellMappingFunctionModel();
264 final EstimatedModel tropoModel = new EstimatedModel(mappingFunction, 5.0);
265 final PhaseTroposphericDelayModifier modifier = new PhaseTroposphericDelayModifier(tropoModel);
266
267 final ParameterDriver parameterDriver = modifier.getParametersDrivers().get(0);
268 parameterDriver.setSelected(true);
269 parameterDriver.setName(baseFrame.getName() + EstimatedModel.TOTAL_ZENITH_DELAY);
270 phase.addModifier(modifier);
271 EstimatedMeasurementBase<Phase> eval = phase.estimateWithoutDerivatives(new SpacecraftState[] { refState });
272
273 final double diffMeters = (eval.getEstimatedValue()[0] - evalNoMod.getEstimatedValue()[0]) * phase.getWavelength();
274
275 final double epsilon = 1e-6;
276 Assertions.assertTrue(Precision.compareTo(diffMeters, 12., epsilon) < 0);
277 Assertions.assertTrue(Precision.compareTo(diffMeters, 0., epsilon) > 0);
278 }
279 }
280
281 @Test
282 public void testTurnAroundRangeTropoModifier() {
283
284 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
285
286 final NumericalPropagatorBuilder propagatorBuilder =
287 context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
288 1.0e-6, 60.0, 0.001);
289
290
291 for (Map.Entry<GroundStation, GroundStation> entry : context.TARstations.entrySet()) {
292 final GroundStation primaryStation = entry.getKey();
293 final GroundStation secondaryStation = entry.getValue();
294 primaryStation.getClockOffsetDriver().setSelected(true);
295 primaryStation.getEastOffsetDriver().setSelected(true);
296 primaryStation.getNorthOffsetDriver().setSelected(true);
297 primaryStation.getZenithOffsetDriver().setSelected(true);
298 secondaryStation.getClockOffsetDriver().setSelected(false);
299 secondaryStation.getEastOffsetDriver().setSelected(true);
300 secondaryStation.getNorthOffsetDriver().setSelected(true);
301 secondaryStation.getZenithOffsetDriver().setSelected(true);
302 }
303 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
304 propagatorBuilder);
305 final List<ObservedMeasurement<?>> measurements =
306 EstimationTestUtils.createMeasurements(propagator,
307 new TurnAroundRangeMeasurementCreator(context),
308 1.0, 3.0, 300.0);
309 propagator.clearStepHandlers();
310
311 final TurnAroundRangeTroposphericDelayModifier modifier =
312 new TurnAroundRangeTroposphericDelayModifier(ModifiedSaastamoinenModel.getStandardModel());
313
314 for (final ObservedMeasurement<?> measurement : measurements) {
315 final AbsoluteDate date = measurement.getDate();
316
317 final SpacecraftState refState = propagator.propagate(date);
318
319 TurnAroundRange turnAroundRange = (TurnAroundRange) measurement;
320 EstimatedMeasurementBase<TurnAroundRange> evalNoMod = turnAroundRange.estimateWithoutDerivatives(new SpacecraftState[] { refState });
321
322
323 turnAroundRange.addModifier(modifier);
324
325 EstimatedMeasurement<TurnAroundRange> eval = turnAroundRange.estimate(0, 0, new SpacecraftState[] { refState });
326
327 final double diffMeters = eval.getEstimatedValue()[0] - evalNoMod.getEstimatedValue()[0];
328
329 final double epsilon = 1e-6;
330 Assertions.assertTrue(Precision.compareTo(diffMeters, 12., epsilon) < 0);
331 Assertions.assertTrue(Precision.compareTo(diffMeters, 0., epsilon) > 0);
332 }
333 }
334
335 @Test
336 public void testBistaticRangeTropoModifier() {
337
338 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
339
340 final NumericalPropagatorBuilder propagatorBuilder =
341 context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
342 1.0e-6, 60.0, 0.001);
343 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
344 propagatorBuilder);
345
346 final GroundStation emitter = context.BRRstations.getKey();
347 emitter.getClockOffsetDriver().setSelected(true);
348 emitter.getEastOffsetDriver().setSelected(true);
349 emitter.getNorthOffsetDriver().setSelected(true);
350 emitter.getZenithOffsetDriver().setSelected(true);
351 final GroundStation receiver = context.BRRstations.getValue();
352 receiver.getClockOffsetDriver().setSelected(true);
353 receiver.getEastOffsetDriver().setSelected(true);
354 receiver.getNorthOffsetDriver().setSelected(true);
355 receiver.getZenithOffsetDriver().setSelected(true);
356 final List<ObservedMeasurement<?>> measurements =
357 EstimationTestUtils.createMeasurements(propagator,
358 new BistaticRangeMeasurementCreator(context),
359 1.0, 3.0, 300.0);
360 propagator.clearStepHandlers();
361
362 final BistaticRangeTroposphericDelayModifier modifier =
363 new BistaticRangeTroposphericDelayModifier(new ModifiedSaastamoinenModel(TroposphericModelUtils.STANDARD_ATMOSPHERE_PROVIDER));
364
365 for (final ObservedMeasurement<?> measurement : measurements) {
366 BistaticRange biRange = (BistaticRange) measurement;
367 final SpacecraftState refState = propagator.propagate(biRange.getDate());
368
369
370 EstimatedMeasurementBase<BistaticRange> evalNoMod = biRange.estimateWithoutDerivatives(new SpacecraftState[] { refState });
371
372
373 biRange.addModifier(modifier);
374
375
376 EstimatedMeasurementBase<BistaticRange> eval = biRange.estimateWithoutDerivatives(new SpacecraftState[] { refState });
377
378 final double diffMeters = eval.getEstimatedValue()[0] - evalNoMod.getEstimatedValue()[0];
379
380 Assertions.assertTrue(diffMeters < 9.1);
381 Assertions.assertTrue(diffMeters > 5.8);
382 }
383 }
384
385 @Test
386 public void testBistaticRangeRateTropoModifier() {
387
388 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
389
390 final NumericalPropagatorBuilder propagatorBuilder =
391 context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
392 1.0e-6, 60.0, 0.001);
393 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
394 propagatorBuilder);
395
396 final GroundStation emitter = context.BRRstations.getKey();
397 emitter.getEastOffsetDriver().setSelected(true);
398 emitter.getNorthOffsetDriver().setSelected(true);
399 emitter.getZenithOffsetDriver().setSelected(true);
400 final GroundStation receiver = context.BRRstations.getValue();
401 receiver.getClockOffsetDriver().setSelected(true);
402 receiver.getEastOffsetDriver().setSelected(true);
403 receiver.getNorthOffsetDriver().setSelected(true);
404 receiver.getZenithOffsetDriver().setSelected(true);
405 final List<ObservedMeasurement<?>> measurements =
406 EstimationTestUtils.createMeasurements(propagator,
407 new BistaticRangeRateMeasurementCreator(context),
408 1.0, 3.0, 300.0);
409 propagator.clearStepHandlers();
410
411 final BistaticRangeRateTroposphericDelayModifier modifier =
412 new BistaticRangeRateTroposphericDelayModifier(ModifiedSaastamoinenModel.getStandardModel());
413
414 for (final ObservedMeasurement<?> measurement : measurements) {
415 BistaticRangeRate biRangeRate = (BistaticRangeRate) measurement;
416 final SpacecraftState refState = propagator.propagate(biRangeRate.getDate());
417
418
419 EstimatedMeasurementBase<BistaticRangeRate> evalNoMod = biRangeRate.estimateWithoutDerivatives(new SpacecraftState[] { refState });
420
421
422 biRangeRate.addModifier(modifier);
423
424
425 EstimatedMeasurementBase<BistaticRangeRate> eval = biRangeRate.estimateWithoutDerivatives(new SpacecraftState[] { refState });
426
427 final double diffMetersSec = eval.getEstimatedValue()[0] - evalNoMod.getEstimatedValue()[0];
428
429 final double epsilon = 5e-5;
430 Assertions.assertTrue(Precision.compareTo(diffMetersSec, 0.005, epsilon) < 0);
431 Assertions.assertTrue(Precision.compareTo(diffMetersSec, -0.007, epsilon) > 0);
432 }
433 }
434
435 @Test
436 public void testBistaticRangeRateEstimatedTropoModifier() {
437
438 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
439
440 final NumericalPropagatorBuilder propagatorBuilder =
441 context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
442 1.0e-6, 60.0, 0.001);
443 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
444 propagatorBuilder);
445
446 final GroundStation emitter = context.BRRstations.getKey();
447 emitter.getEastOffsetDriver().setSelected(true);
448 emitter.getNorthOffsetDriver().setSelected(true);
449 emitter.getZenithOffsetDriver().setSelected(true);
450 final GroundStation receiver = context.BRRstations.getValue();
451 receiver.getClockOffsetDriver().setSelected(true);
452 receiver.getEastOffsetDriver().setSelected(true);
453 receiver.getNorthOffsetDriver().setSelected(true);
454 receiver.getZenithOffsetDriver().setSelected(true);
455 final List<ObservedMeasurement<?>> measurements =
456 EstimationTestUtils.createMeasurements(propagator,
457 new BistaticRangeRateMeasurementCreator(context),
458 1.0, 3.0, 300.0);
459 propagator.clearStepHandlers();
460
461 for (final ObservedMeasurement<?> measurement : measurements) {
462 BistaticRangeRate biRangeRate = (BistaticRangeRate) measurement;
463 final SpacecraftState refState = propagator.propagate(biRangeRate.getDate());
464
465
466 EstimatedMeasurementBase<BistaticRangeRate> evalNoMod = biRangeRate.estimateWithoutDerivatives(new SpacecraftState[] { refState });
467
468
469 final NiellMappingFunctionModel mappingFunc = new NiellMappingFunctionModel();
470 final EstimatedModel tropoModel = new EstimatedModel(mappingFunc, 5.0);
471 final BistaticRangeRateTroposphericDelayModifier modifier =
472 new BistaticRangeRateTroposphericDelayModifier(tropoModel);
473
474 final TopocentricFrame baseFrame = biRangeRate.getReceiverStation().getBaseFrame();
475 final ParameterDriver parameterDriver = modifier.getParametersDrivers().get(0);
476 parameterDriver.setSelected(true);
477 parameterDriver.setName(baseFrame.getName() + EstimatedModel.TOTAL_ZENITH_DELAY);
478
479 biRangeRate.addModifier(modifier);
480
481
482 EstimatedMeasurementBase<BistaticRangeRate> eval = biRangeRate.estimateWithoutDerivatives(new SpacecraftState[] { refState });
483
484 final double diffMetersSec = eval.getEstimatedValue()[0] - evalNoMod.getEstimatedValue()[0];
485
486 final double epsilon = 1e-4;
487 Assertions.assertTrue(Precision.compareTo(diffMetersSec, 0.010, epsilon) < 0);
488 Assertions.assertTrue(Precision.compareTo(diffMetersSec, -0.014, epsilon) > 0);
489 }
490 }
491
492 @Test
493 public void testTDOATropoModifier() {
494
495 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
496
497 final NumericalPropagatorBuilder propagatorBuilder =
498 context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
499 1.0e-6, 60.0, 0.001);
500 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
501 propagatorBuilder);
502
503 final GroundStation emitter = context.TDOAstations.getKey();
504 emitter.getClockOffsetDriver().setSelected(true);
505 emitter.getEastOffsetDriver().setSelected(true);
506 emitter.getNorthOffsetDriver().setSelected(true);
507 emitter.getZenithOffsetDriver().setSelected(true);
508 final GroundStation receiver = context.TDOAstations.getValue();
509 receiver.getClockOffsetDriver().setSelected(true);
510 receiver.getEastOffsetDriver().setSelected(true);
511 receiver.getNorthOffsetDriver().setSelected(true);
512 receiver.getZenithOffsetDriver().setSelected(true);
513 final List<ObservedMeasurement<?>> measurements =
514 EstimationTestUtils.createMeasurements(propagator,
515 new TDOAMeasurementCreator(context),
516 1.0, 3.0, 300.0);
517 propagator.clearStepHandlers();
518
519 final TDOATroposphericDelayModifier modifier =
520 new TDOATroposphericDelayModifier(ModifiedSaastamoinenModel.getStandardModel());
521
522 for (final ObservedMeasurement<?> measurement : measurements) {
523 TDOA tdoa = (TDOA) measurement;
524 final SpacecraftState refState = propagator.propagate(tdoa.getDate());
525
526
527 EstimatedMeasurementBase<TDOA> evalNoMod = tdoa.estimateWithoutDerivatives(new SpacecraftState[] { refState });
528
529
530 tdoa.addModifier(modifier);
531
532
533 EstimatedMeasurementBase<TDOA> eval = tdoa.estimateWithoutDerivatives(new SpacecraftState[] { refState });
534
535 final double diffSec = eval.getEstimatedValue()[0] - evalNoMod.getEstimatedValue()[0];
536
537 final double epsilon = 1.e-11;
538 Assertions.assertTrue(Precision.compareTo(diffSec, 2.35e-9, epsilon) < 0);
539 Assertions.assertTrue(Precision.compareTo(diffSec, -1.05e-9, epsilon) > 0);
540 }
541 }
542
543 @Test
544 public void testTDOAEstimatedTropoModifier() {
545
546 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
547
548 final NumericalPropagatorBuilder propagatorBuilder =
549 context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
550 1.0e-6, 60.0, 0.001);
551 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
552 propagatorBuilder);
553
554 final GroundStation emitter = context.TDOAstations.getKey();
555 emitter.getClockOffsetDriver().setSelected(true);
556 emitter.getEastOffsetDriver().setSelected(true);
557 emitter.getNorthOffsetDriver().setSelected(true);
558 emitter.getZenithOffsetDriver().setSelected(true);
559 final GroundStation receiver = context.TDOAstations.getValue();
560 receiver.getClockOffsetDriver().setSelected(true);
561 receiver.getEastOffsetDriver().setSelected(true);
562 receiver.getNorthOffsetDriver().setSelected(true);
563 receiver.getZenithOffsetDriver().setSelected(true);
564 final List<ObservedMeasurement<?>> measurements =
565 EstimationTestUtils.createMeasurements(propagator,
566 new TDOAMeasurementCreator(context),
567 1.0, 3.0, 300.0);
568 propagator.clearStepHandlers();
569
570 for (final ObservedMeasurement<?> measurement : measurements) {
571 TDOA tdoa = (TDOA) measurement;
572 final SpacecraftState refState = propagator.propagate(tdoa.getDate());
573
574
575 EstimatedMeasurementBase<TDOA> evalNoMod = tdoa.estimateWithoutDerivatives(new SpacecraftState[] { refState });
576
577
578 final NiellMappingFunctionModel mappingFunct = new NiellMappingFunctionModel();
579 final EstimatedModel tropoModel = new EstimatedModel(mappingFunct, 5.0);
580 final TDOATroposphericDelayModifier modifier = new TDOATroposphericDelayModifier(tropoModel);
581
582 final TopocentricFrame baseFrame = tdoa.getPrimeStation().getBaseFrame();
583 final ParameterDriver parameterDriver = modifier.getParametersDrivers().get(0);
584 parameterDriver.setSelected(true);
585 parameterDriver.setName(baseFrame.getName() + EstimatedModel.TOTAL_ZENITH_DELAY);
586
587 tdoa.addModifier(modifier);
588
589
590 EstimatedMeasurement<TDOA> eval = tdoa.estimate(0, 0, new SpacecraftState[] { refState });
591
592 final double diffSec = eval.getEstimatedValue()[0] - evalNoMod.getEstimatedValue()[0];
593
594 final double epsilon = 5.e-11;
595 Assertions.assertTrue(Precision.compareTo(diffSec, 4.90e-9, epsilon) < 0);
596 Assertions.assertTrue(Precision.compareTo(diffSec, -2.21e-9, epsilon) > 0);
597 }
598 }
599
600 @Test
601 public void testRangeRateTropoModifier() {
602
603 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
604
605 final NumericalPropagatorBuilder propagatorBuilder =
606 context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
607 1.0e-6, 60.0, 0.001);
608
609
610 for (final GroundStation station : context.stations) {
611 station.getClockOffsetDriver().setSelected(true);
612 station.getEastOffsetDriver().setSelected(true);
613 station.getNorthOffsetDriver().setSelected(true);
614 station.getZenithOffsetDriver().setSelected(true);
615 }
616 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
617 propagatorBuilder);
618 final double satClkDrift = 3.2e-10;
619 final List<ObservedMeasurement<?>> measurements =
620 EstimationTestUtils.createMeasurements(propagator,
621 new RangeRateMeasurementCreator(context, false, satClkDrift),
622 1.0, 3.0, 300.0);
623 propagator.clearStepHandlers();
624
625 final RangeRateTroposphericDelayModifier modifier =
626 new RangeRateTroposphericDelayModifier(ModifiedSaastamoinenModel.getStandardModel(), false);
627
628 for (final ObservedMeasurement<?> measurement : measurements) {
629 final AbsoluteDate date = measurement.getDate();
630
631 final SpacecraftState refState = propagator.propagate(date);
632
633 RangeRate rangeRate = (RangeRate) measurement;
634 EstimatedMeasurementBase<RangeRate> evalNoMod = rangeRate.estimateWithoutDerivatives(new SpacecraftState[] { refState });
635
636
637 rangeRate.addModifier(modifier);
638
639
640 EstimatedMeasurement<RangeRate> eval = rangeRate.estimate(0, 0, new SpacecraftState[] { refState });
641
642 final double diffMetersSec = eval.getEstimatedValue()[0] - evalNoMod.getEstimatedValue()[0];
643
644 final double epsilon = 1e-6;
645 Assertions.assertTrue(Precision.compareTo(diffMetersSec, 0.01, epsilon) < 0);
646 Assertions.assertTrue(Precision.compareTo(diffMetersSec, -0.01, epsilon) > 0);
647 }
648 }
649
650 @Test
651 public void testRangeRateEstimatedTropoModifier() {
652
653 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
654
655 final NumericalPropagatorBuilder propagatorBuilder =
656 context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
657 1.0e-6, 60.0, 0.001);
658
659 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
660 propagatorBuilder);
661 final double satClkDrift = 3.2e-10;
662 final List<ObservedMeasurement<?>> measurements =
663 EstimationTestUtils.createMeasurements(propagator,
664 new RangeRateMeasurementCreator(context, false, satClkDrift),
665 1.0, 3.0, 300.0);
666 propagator.clearStepHandlers();
667
668 for (final ObservedMeasurement<?> measurement : measurements) {
669 final AbsoluteDate date = measurement.getDate();
670
671 final SpacecraftState refState = propagator.propagate(date);
672
673 RangeRate rangeRate = (RangeRate) measurement;
674 EstimatedMeasurementBase<RangeRate> evalNoMod = rangeRate.estimateWithoutDerivatives(new SpacecraftState[] { refState });
675
676
677 final GroundStation stationParameter = ((RangeRate) measurement).getStation();
678 final TopocentricFrame baseFrame = stationParameter.getBaseFrame();
679 final NiellMappingFunctionModel mappingFunction = new NiellMappingFunctionModel();
680 final EstimatedModel tropoModel = new EstimatedModel(mappingFunction, 5.0);
681 final RangeRateTroposphericDelayModifier modifier = new RangeRateTroposphericDelayModifier(tropoModel, false);
682
683 final ParameterDriver parameterDriver = modifier.getParametersDrivers().get(0);
684 parameterDriver.setSelected(true);
685 parameterDriver.setName(baseFrame.getName() + EstimatedModel.TOTAL_ZENITH_DELAY);
686 rangeRate.addModifier(modifier);
687
688
689 EstimatedMeasurementBase<RangeRate> eval = rangeRate.estimateWithoutDerivatives(new SpacecraftState[] { refState });
690
691 final double diffMetersSec = eval.getEstimatedValue()[0] - evalNoMod.getEstimatedValue()[0];
692
693 final double epsilon = 1e-6;
694 Assertions.assertTrue(Precision.compareTo(diffMetersSec, 0.01, epsilon) < 0);
695 Assertions.assertTrue(Precision.compareTo(diffMetersSec, -0.01, epsilon) > 0);
696 }
697 }
698
699 @Test
700 public void testAngularRadioRefractionModifier() {
701
702 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
703
704 final NumericalPropagatorBuilder propagatorBuilder =
705 context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
706 1.0e-6, 60.0, 0.001);
707
708
709 for (final GroundStation station : context.stations) {
710 station.getClockOffsetDriver().setSelected(true);
711 station.getEastOffsetDriver().setSelected(true);
712 station.getNorthOffsetDriver().setSelected(true);
713 station.getZenithOffsetDriver().setSelected(true);
714 }
715 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
716 propagatorBuilder);
717 final List<ObservedMeasurement<?>> measurements =
718 EstimationTestUtils.createMeasurements(propagator,
719 new AngularAzElMeasurementCreator(context),
720 1.0, 3.0, 300.0);
721 propagator.clearStepHandlers();
722
723
724
725 for (final ObservedMeasurement<?> measurement : measurements) {
726 final AbsoluteDate date = measurement.getDate();
727
728 final SpacecraftState refState = propagator.propagate(date);
729
730 AngularAzEl angular = (AngularAzEl) measurement;
731 EstimatedMeasurementBase<AngularAzEl> evalNoMod = angular.estimateWithoutDerivatives(new SpacecraftState[] { refState });
732
733
734 final double altitude = angular.getStation().getBaseFrame().getPoint().getAltitude() / 1000.;
735
736 final AngularRadioRefractionModifier modifier = new AngularRadioRefractionModifier(new ITURP834AtmosphericRefraction(altitude));
737
738 angular.addModifier(modifier);
739
740 EstimatedMeasurementBase<AngularAzEl> eval = angular.estimateWithoutDerivatives(new SpacecraftState[] { refState });
741
742 final double diffEl = MathUtils.normalizeAngle(eval.getEstimatedValue()[1], evalNoMod.getEstimatedValue()[1]) - evalNoMod.getEstimatedValue()[1];
743
744 Assertions.assertEquals(0.0, diffEl, 1.0e-3);
745 }
746 }
747
748 }