1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.estimation.measurements.gnss;
18
19 import java.util.ArrayList;
20 import java.util.Comparator;
21 import java.util.List;
22 import java.util.Locale;
23
24 import org.hipparchus.stat.descriptive.moment.Mean;
25 import org.hipparchus.stat.descriptive.rank.Max;
26 import org.hipparchus.stat.descriptive.rank.Median;
27 import org.hipparchus.stat.descriptive.rank.Min;
28 import org.hipparchus.util.FastMath;
29 import org.junit.Assert;
30 import org.junit.Test;
31 import org.orekit.Utils;
32 import org.orekit.bodies.GeodeticPoint;
33 import org.orekit.bodies.OneAxisEllipsoid;
34 import org.orekit.estimation.Context;
35 import org.orekit.estimation.EstimationTestUtils;
36 import org.orekit.estimation.measurements.EstimatedMeasurement;
37 import org.orekit.estimation.measurements.GroundStation;
38 import org.orekit.estimation.measurements.ObservableSatellite;
39 import org.orekit.estimation.measurements.ObservedMeasurement;
40 import org.orekit.estimation.measurements.modifiers.PhaseIonosphericDelayModifier;
41 import org.orekit.estimation.measurements.modifiers.PhaseTroposphericDelayModifier;
42 import org.orekit.frames.FramesFactory;
43 import org.orekit.frames.TopocentricFrame;
44 import org.orekit.gnss.Frequency;
45 import org.orekit.models.earth.ionosphere.IonosphericModel;
46 import org.orekit.models.earth.ionosphere.KlobucharIonoModel;
47 import org.orekit.models.earth.troposphere.EstimatedTroposphericModel;
48 import org.orekit.models.earth.troposphere.NiellMappingFunctionModel;
49 import org.orekit.orbits.OrbitType;
50 import org.orekit.orbits.PositionAngle;
51 import org.orekit.propagation.Propagator;
52 import org.orekit.propagation.SpacecraftState;
53 import org.orekit.propagation.conversion.NumericalPropagatorBuilder;
54 import org.orekit.time.AbsoluteDate;
55 import org.orekit.utils.Constants;
56 import org.orekit.utils.Differentiation;
57 import org.orekit.utils.IERSConventions;
58 import org.orekit.utils.ParameterDriver;
59 import org.orekit.utils.ParameterFunction;
60 import org.orekit.utils.StateFunction;
61 import org.orekit.utils.TimeStampedPVCoordinates;
62
63 public class PhaseTest {
64
65
66
67
68
69 @Test
70 public void testValues() {
71 boolean printResults = false;
72 if (printResults) {
73 System.out.println("\nTest Phase Values\n");
74 }
75
76 this.genericTestValues(printResults);
77 }
78
79
80
81
82
83 @Test
84 public void testStateDerivatives() {
85
86 boolean printResults = false;
87 if (printResults) {
88 System.out.println("\nTest Range Phase Derivatives - Finite Differences Comparison\n");
89 }
90
91 double refErrorsPMedian = 5.2e-10;
92 double refErrorsPMean = 3.5e-09;
93 double refErrorsPMax = 1.5e-07;
94 double refErrorsVMedian = 2.0e-05;
95 double refErrorsVMean = 5.8e-05;
96 double refErrorsVMax = 2.1e-03;
97 this.genericTestStateDerivatives(printResults,
98 refErrorsPMedian, refErrorsPMean, refErrorsPMax,
99 refErrorsVMedian, refErrorsVMean, refErrorsVMax);
100 }
101
102
103
104
105
106 @Test
107 public void testStateDerivativesWithModifier() {
108
109 boolean printResults = false;
110 if (printResults) {
111 System.out.println("\nTest Phase State Derivatives with Modifier - Finite Differences Comparison\n");
112 }
113
114 double refErrorsPMedian = 5.2e-10;
115 double refErrorsPMean = 3.5e-09;
116 double refErrorsPMax = 1.5e-07;
117 double refErrorsVMedian = 2.0e-05;
118 double refErrorsVMean = 5.8e-05;
119 double refErrorsVMax = 2.1e-03;
120 this.genericTestStateDerivatives(printResults,
121 refErrorsPMedian, refErrorsPMean, refErrorsPMax,
122 refErrorsVMedian, refErrorsVMean, refErrorsVMax);
123 }
124
125
126
127
128
129 @Test
130 public void testParameterDerivatives() {
131
132
133 boolean printResults = false;
134
135 if (printResults) {
136 System.out.println("\nTest Phase Parameter Derivatives - Finite Differences Comparison\n");
137 }
138
139 double refErrorsMedian = 1.4e-10;
140 double refErrorsMean = 5.0e-8;
141 double refErrorsMax = 5.1e-6;
142 this.genericTestParameterDerivatives(printResults,
143 refErrorsMedian, refErrorsMean, refErrorsMax);
144
145 }
146
147
148
149
150
151 void genericTestValues(final boolean printResults) {
152
153 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
154
155 final NumericalPropagatorBuilder propagatorBuilder =
156 context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true,
157 1.0e-6, 60.0, 0.001);
158
159
160 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
161 propagatorBuilder);
162 final double groundClockOffset = 12.0e-6;
163 for (final GroundStation station : context.stations) {
164 station.getClockOffsetDriver().setValue(groundClockOffset);
165 }
166 final int ambiguity = 1234;
167 final double satClockOffset = 345.0e-6;
168 final List<ObservedMeasurement<?>> measurements =
169 EstimationTestUtils.createMeasurements(propagator,
170 new PhaseMeasurementCreator(context,
171 Frequency.E01,
172 ambiguity,
173 satClockOffset),
174 1.0, 3.0, 300.0);
175
176
177
178 final List<Double> absoluteErrors = new ArrayList<>();
179 final List<Double> relativeErrors = new ArrayList<>();
180
181
182 propagator.setStepHandler(interpolator -> {
183
184 for (final ObservedMeasurement<?> measurement : measurements) {
185
186
187 if ((measurement.getDate().durationFrom(interpolator.getPreviousState().getDate()) > 0.) &&
188 (measurement.getDate().durationFrom(interpolator.getCurrentState().getDate()) <= 0.)) {
189
190
191
192
193
194
195
196 final double meanDelay = measurement.getObservedValue()[0] / Constants.SPEED_OF_LIGHT;
197 final AbsoluteDate date = measurement.getDate().shiftedBy(-0.75 * meanDelay);
198 final SpacecraftState state = interpolator.getInterpolatedState(date);
199
200
201 final double phaseObserved = measurement.getObservedValue()[0];
202 final EstimatedMeasurement<?> estimated = measurement.estimate(0, 0, new SpacecraftState[] { state });
203
204 final TimeStampedPVCoordinates[] participants = estimated.getParticipants();
205 Assert.assertEquals(2, participants.length);
206 final double dt = participants[1].getDate().durationFrom(participants[0].getDate());
207 Assert.assertEquals(1.0e6 * Frequency.E01.getMHzFrequency() * (dt + groundClockOffset - satClockOffset) + ambiguity,
208 estimated.getEstimatedValue()[0],
209 1.0e-7);
210
211 final double phaseEstimated = estimated.getEstimatedValue()[0];
212 final double absoluteError = phaseEstimated - phaseObserved;
213 absoluteErrors.add(absoluteError);
214 relativeErrors.add(FastMath.abs(absoluteError) / FastMath.abs(phaseObserved));
215
216
217 if (printResults) {
218 final AbsoluteDate measurementDate = measurement.getDate();
219 String stationName = ((Phase) measurement).getStation().getBaseFrame().getName();
220
221 System.out.format(Locale.US, "%-15s %-23s %-23s %19.6f %19.6f %13.6e %13.6e%n",
222 stationName, measurementDate, date,
223 phaseObserved, phaseEstimated,
224 FastMath.abs(phaseEstimated - phaseObserved),
225 FastMath.abs((phaseEstimated - phaseObserved) / phaseObserved));
226 }
227
228 }
229 }
230 });
231
232
233 if (printResults) {
234 System.out.format(Locale.US, "%-15s %-23s %-23s %19s %19s %13s %13s%n",
235 "Station", "Measurement Date", "State Date",
236 "Phase observed [cycle]", "Phase estimated [cycle]",
237 "ΔPhase [cycle]", "rel ΔPhase");
238 }
239
240
241 propagator.propagate(context.initialOrbit.getDate());
242
243
244 measurements.sort(Comparator.naturalOrder());
245
246
247 propagator.propagate(measurements.get(measurements.size()-1).getDate());
248
249
250 final double[] absErrors = absoluteErrors.stream().mapToDouble(Double::doubleValue).toArray();
251 final double[] relErrors = relativeErrors.stream().mapToDouble(Double::doubleValue).toArray();
252
253
254 final double absErrorsMedian = new Median().evaluate(absErrors);
255 final double absErrorsMin = new Min().evaluate(absErrors);
256 final double absErrorsMax = new Max().evaluate(absErrors);
257 final double relErrorsMedian = new Median().evaluate(relErrors);
258 final double relErrorsMax = new Max().evaluate(relErrors);
259
260
261 if (printResults) {
262 System.out.println();
263 System.out.println("Absolute errors median: " + absErrorsMedian);
264 System.out.println("Absolute errors min : " + absErrorsMin);
265 System.out.println("Absolute errors max : " + absErrorsMax);
266 System.out.println("Relative errors median: " + relErrorsMedian);
267 System.out.println("Relative errors max : " + relErrorsMax);
268 }
269
270 Assert.assertEquals(0.0, absErrorsMedian, 1.4e-7);
271 Assert.assertEquals(0.0, absErrorsMin, 1.3e-6);
272 Assert.assertEquals(0.0, absErrorsMax, 1.5e-6);
273 Assert.assertEquals(0.0, relErrorsMedian, 9.1e-15);
274 Assert.assertEquals(0.0, relErrorsMax, 2.8e-14);
275
276
277 }
278
279 void genericTestStateDerivatives(final boolean printResults,
280 final double refErrorsPMedian, final double refErrorsPMean, final double refErrorsPMax,
281 final double refErrorsVMedian, final double refErrorsVMean, final double refErrorsVMax) {
282
283 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
284
285 final NumericalPropagatorBuilder propagatorBuilder =
286 context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true,
287 1.0e-6, 60.0, 0.001);
288
289
290 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
291 propagatorBuilder);
292 final double groundClockOffset = 12.0e-6;
293 for (final GroundStation station : context.stations) {
294 station.getClockOffsetDriver().setValue(groundClockOffset);
295 }
296 final int ambiguity = 1234;
297 final double satClockOffset = 345.0e-6;
298 final List<ObservedMeasurement<?>> measurements =
299 EstimationTestUtils.createMeasurements(propagator,
300 new PhaseMeasurementCreator(context,
301 Frequency.E01,
302 ambiguity,
303 satClockOffset),
304 1.0, 3.0, 300.0);
305
306
307
308 final List<Double> errorsP = new ArrayList<Double>();
309 final List<Double> errorsV = new ArrayList<Double>();
310
311
312 propagator.setStepHandler(interpolator -> {
313
314 for (final ObservedMeasurement<?> measurement : measurements) {
315
316
317 if ((measurement.getDate().durationFrom(interpolator.getPreviousState().getDate()) > 0.) &&
318 (measurement.getDate().durationFrom(interpolator.getCurrentState().getDate()) <= 0.)) {
319
320
321
322
323
324
325
326
327 final double meanDelay = measurement.getObservedValue()[0] / Constants.SPEED_OF_LIGHT;
328 final AbsoluteDate date = measurement.getDate().shiftedBy(-0.75 * meanDelay);
329 final SpacecraftState state = interpolator.getInterpolatedState(date);
330 final double[][] jacobian = measurement.estimate(0, 0, new SpacecraftState[] { state }).getStateDerivatives(0);
331
332
333 final double[][] jacobianRef;
334
335
336 jacobianRef = Differentiation.differentiate(new StateFunction() {
337 public double[] value(final SpacecraftState state) {
338 return measurement.estimate(0, 0, new SpacecraftState[] { state }).getEstimatedValue();
339 }
340 }, measurement.getDimension(), propagator.getAttitudeProvider(),
341 OrbitType.CARTESIAN, PositionAngle.TRUE, 2.0, 3).value(state);
342
343 Assert.assertEquals(jacobianRef.length, jacobian.length);
344 Assert.assertEquals(jacobianRef[0].length, jacobian[0].length);
345
346
347 double [][] dJacobian = new double[jacobian.length][jacobian[0].length];
348 double [][] dJacobianRelative = new double[jacobian.length][jacobian[0].length];
349 for (int i = 0; i < jacobian.length; ++i) {
350 for (int j = 0; j < jacobian[i].length; ++j) {
351 dJacobian[i][j] = jacobian[i][j] - jacobianRef[i][j];
352 dJacobianRelative[i][j] = FastMath.abs(dJacobian[i][j]/jacobianRef[i][j]);
353
354 if (j < 3) { errorsP.add(dJacobianRelative[i][j]);
355 } else { errorsV.add(dJacobianRelative[i][j]); }
356 }
357 }
358
359 if (printResults) {
360 String stationName = ((Phase) measurement).getStation().getBaseFrame().getName();
361 System.out.format(Locale.US, "%-15s %-23s %-23s " +
362 "%10.3e %10.3e %10.3e " +
363 "%10.3e %10.3e %10.3e " +
364 "%10.3e %10.3e %10.3e " +
365 "%10.3e %10.3e %10.3e%n",
366 stationName, measurement.getDate(), date,
367 dJacobian[0][0], dJacobian[0][1], dJacobian[0][2],
368 dJacobian[0][3], dJacobian[0][4], dJacobian[0][5],
369 dJacobianRelative[0][0], dJacobianRelative[0][1], dJacobianRelative[0][2],
370 dJacobianRelative[0][3], dJacobianRelative[0][4], dJacobianRelative[0][5]);
371 }
372 }
373 }
374 });
375
376
377 if (printResults) {
378 System.out.format(Locale.US, "%-15s %-23s %-23s " +
379 "%10s %10s %10s " +
380 "%10s %10s %10s " +
381 "%10s %10s %10s " +
382 "%10s %10s %10s%n",
383 "Station", "Measurement Date", "State Date",
384 "ΔdPx", "ΔdPy", "ΔdPz", "ΔdVx", "ΔdVy", "ΔdVz",
385 "rel ΔdPx", "rel ΔdPy", "rel ΔdPz",
386 "rel ΔdVx", "rel ΔdVy", "rel ΔdVz");
387 }
388
389
390 propagator.propagate(context.initialOrbit.getDate());
391
392
393 measurements.sort(Comparator.naturalOrder());
394
395
396 propagator.propagate(measurements.get(measurements.size()-1).getDate());
397
398
399 final double relErrorsP[] = errorsP.stream().mapToDouble(Double::doubleValue).toArray();
400 final double relErrorsV[] = errorsV.stream().mapToDouble(Double::doubleValue).toArray();
401
402 final double errorsPMedian = new Median().evaluate(relErrorsP);
403 final double errorsPMean = new Mean().evaluate(relErrorsP);
404 final double errorsPMax = new Max().evaluate(relErrorsP);
405 final double errorsVMedian = new Median().evaluate(relErrorsV);
406 final double errorsVMean = new Mean().evaluate(relErrorsV);
407 final double errorsVMax = new Max().evaluate(relErrorsV);
408
409
410 if (printResults) {
411 System.out.println();
412 System.out.format(Locale.US, "Relative errors dΦ/dP -> Median: %6.3e / Mean: %6.3e / Max: %6.3e%n",
413 errorsPMedian, errorsPMean, errorsPMax);
414 System.out.format(Locale.US, "Relative errors dΦ/dV -> Median: %6.3e / Mean: %6.3e / Max: %6.3e%n",
415 errorsVMedian, errorsVMean, errorsVMax);
416 }
417
418 Assert.assertEquals(0.0, errorsPMedian, refErrorsPMedian);
419 Assert.assertEquals(0.0, errorsPMean, refErrorsPMean);
420 Assert.assertEquals(0.0, errorsPMax, refErrorsPMax);
421 Assert.assertEquals(0.0, errorsVMedian, refErrorsVMedian);
422 Assert.assertEquals(0.0, errorsVMean, refErrorsVMean);
423 Assert.assertEquals(0.0, errorsVMax, refErrorsVMax);
424 }
425
426 void genericTestParameterDerivatives(final boolean printResults,
427 final double refErrorsMedian, final double refErrorsMean, final double refErrorsMax) {
428
429 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
430
431 final NumericalPropagatorBuilder propagatorBuilder =
432 context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true,
433 1.0e-6, 60.0, 0.001);
434
435
436 final double groundClockOffset = 12.0e-6;
437 for (final GroundStation station : context.stations) {
438 station.getClockOffsetDriver().setValue(groundClockOffset);
439 }
440 final int ambiguity = 1234;
441 final double satClockOffset = 345.0e-6;
442 final PhaseMeasurementCreator creator = new PhaseMeasurementCreator(context, Frequency.E01,
443 ambiguity,
444 satClockOffset);
445 creator.getSatellite().getClockOffsetDriver().setSelected(true);
446 for (final GroundStation station : context.stations) {
447 station.getClockOffsetDriver().setSelected(true);
448 station.getEastOffsetDriver().setSelected(true);
449 station.getNorthOffsetDriver().setSelected(true);
450 station.getZenithOffsetDriver().setSelected(true);
451 }
452 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
453 propagatorBuilder);
454 final List<ObservedMeasurement<?>> measurements =
455 EstimationTestUtils.createMeasurements(propagator, creator, 1.0, 3.0, 300.0);
456
457
458 final List<Double> relErrorList = new ArrayList<Double>();
459
460
461 propagator.setStepHandler(interpolator -> {
462
463 for (final ObservedMeasurement<?> measurement : measurements) {
464
465
466 if ((measurement.getDate().durationFrom(interpolator.getPreviousState().getDate()) > 0.) &&
467 (measurement.getDate().durationFrom(interpolator.getCurrentState().getDate()) <= 0.)) {
468
469
470 final GroundStation stationParameter = ((Phase) measurement).getStation();
471
472
473
474
475
476
477
478
479 final double meanDelay = measurement.getObservedValue()[0] / Constants.SPEED_OF_LIGHT;
480 final AbsoluteDate date = measurement.getDate().shiftedBy(-0.75 * meanDelay);
481 final SpacecraftState state = interpolator.getInterpolatedState(date);
482 final ParameterDriver[] drivers = new ParameterDriver[] {
483 stationParameter.getClockOffsetDriver(),
484 stationParameter.getEastOffsetDriver(),
485 stationParameter.getNorthOffsetDriver(),
486 stationParameter.getZenithOffsetDriver(),
487 measurement.getSatellites().get(0).getClockOffsetDriver()
488 };
489
490 if (printResults) {
491 String stationName = ((Phase) measurement).getStation().getBaseFrame().getName();
492 System.out.format(Locale.US, "%-15s %-23s %-23s ",
493 stationName, measurement.getDate(), date);
494 }
495
496 for (int i = 0; i < drivers.length; ++i) {
497 final double[] gradient = measurement.estimate(0, 0, new SpacecraftState[] { state }).getParameterDerivatives(drivers[i]);
498 Assert.assertEquals(1, measurement.getDimension());
499 Assert.assertEquals(1, gradient.length);
500
501
502 final ParameterFunction dMkdP =
503 Differentiation.differentiate(new ParameterFunction() {
504
505 @Override
506 public double value(final ParameterDriver parameterDriver) {
507 return measurement.estimate(0, 0, new SpacecraftState[] { state }).getEstimatedValue()[0];
508 }
509 }, 3, 20.0 * drivers[i].getScale());
510 final double ref = dMkdP.value(drivers[i]);
511
512 if (printResults) {
513 System.out.format(Locale.US, "%10.3e %10.3e ", gradient[0]-ref, FastMath.abs((gradient[0]-ref)/ref));
514 }
515
516 final double relError = FastMath.abs((ref-gradient[0])/ref);
517 relErrorList.add(relError);
518
519 }
520 if (printResults) {
521 System.out.format(Locale.US, "%n");
522 }
523
524 }
525 }
526 });
527
528
529 propagator.propagate(context.initialOrbit.getDate());
530
531
532 measurements.sort(Comparator.naturalOrder());
533
534
535 if (printResults) {
536 System.out.format(Locale.US, "%-15s %-23s %-23s " +
537 "%10s %10s %10s %10s %10s %10s %10s %10s %10s %10s%n",
538 "Station", "Measurement Date", "State Date",
539 "Δt", "rel Δt",
540 "ΔdQx", "rel ΔdQx",
541 "ΔdQy", "rel ΔdQy",
542 "ΔdQz", "rel ΔdQz",
543 "Δtsat", "rel Δtsat");
544 }
545
546
547 propagator.propagate(measurements.get(measurements.size()-1).getDate());
548
549
550 final double relErrors[] = relErrorList.stream().mapToDouble(Double::doubleValue).toArray();
551
552
553 final double relErrorsMedian = new Median().evaluate(relErrors);
554 final double relErrorsMean = new Mean().evaluate(relErrors);
555 final double relErrorsMax = new Max().evaluate(relErrors);
556
557
558 if (printResults) {
559 System.out.println();
560 System.out.format(Locale.US, "Relative errors dR/dQ -> Median: %6.3e / Mean: %6.3e / Max: %6.3e%n",
561 relErrorsMedian, relErrorsMean, relErrorsMax);
562 }
563
564 Assert.assertEquals(0.0, relErrorsMedian, refErrorsMedian);
565 Assert.assertEquals(0.0, relErrorsMean, refErrorsMean);
566 Assert.assertEquals(0.0, relErrorsMax, refErrorsMax);
567
568 }
569
570 @Test
571 public void testStateDerivativesWithTroposphericModifier() {
572
573 final boolean printResults = false;
574 final double refErrorsPMedian = 5.9e-10;
575 final double refErrorsPMean = 3.5e-9;
576 final double refErrorsPMax = 1.1e-7;
577 final double refErrorsVMedian = 2.0e-5;
578 final double refErrorsVMean = 5.8e-5;
579 final double refErrorsVMax = 2.1e-3;
580
581 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
582
583 final NumericalPropagatorBuilder propagatorBuilder =
584 context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true,
585 1.0e-6, 60.0, 0.001);
586
587
588 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
589 propagatorBuilder);
590 final double groundClockOffset = 12.0e-6;
591 for (final GroundStation station : context.stations) {
592 station.getClockOffsetDriver().setValue(groundClockOffset);
593 }
594 final int ambiguity = 1234;
595 final double satClockOffset = 345.0e-6;
596 final List<ObservedMeasurement<?>> measurements =
597 EstimationTestUtils.createMeasurements(propagator,
598 new PhaseMeasurementCreator(context,
599 Frequency.E01,
600 ambiguity,
601 satClockOffset),
602 1.0, 3.0, 300.0);
603
604
605
606 final List<Double> errorsP = new ArrayList<Double>();
607 final List<Double> errorsV = new ArrayList<Double>();
608
609
610 propagator.setStepHandler(interpolator -> {
611
612 for (final ObservedMeasurement<?> measurement : measurements) {
613
614
615 if ((measurement.getDate().durationFrom(interpolator.getPreviousState().getDate()) > 0.) &&
616 (measurement.getDate().durationFrom(interpolator.getCurrentState().getDate()) <= 0.)) {
617
618 String stationName = ((Phase) measurement).getStation().getBaseFrame().getName();
619
620
621 final NiellMappingFunctionModel mappingFunction = new NiellMappingFunctionModel();
622 final EstimatedTroposphericModel tropoModel = new EstimatedTroposphericModel(mappingFunction, 5.0);
623 final PhaseTroposphericDelayModifier modifier = new PhaseTroposphericDelayModifier(tropoModel);
624 final List<ParameterDriver> parameters = modifier.getParametersDrivers();
625 parameters.get(0).setName(stationName + "/" + EstimatedTroposphericModel.TOTAL_ZENITH_DELAY);
626 parameters.get(0).setSelected(true);
627 ((Phase) measurement).addModifier(modifier);
628
629
630
631
632
633
634
635
636 final double meanDelay = measurement.getObservedValue()[0] / Constants.SPEED_OF_LIGHT;
637 final AbsoluteDate date = measurement.getDate().shiftedBy(-0.75 * meanDelay);
638 final SpacecraftState state = interpolator.getInterpolatedState(date);
639 final double[][] jacobian = measurement.estimate(0, 0, new SpacecraftState[] { state }).getStateDerivatives(0);
640
641
642 final double[][] jacobianRef;
643
644
645 jacobianRef = Differentiation.differentiate(new StateFunction() {
646 public double[] value(final SpacecraftState state) {
647 return measurement.estimate(0, 0, new SpacecraftState[] { state }).getEstimatedValue();
648 }
649 }, measurement.getDimension(), propagator.getAttitudeProvider(),
650 OrbitType.CARTESIAN, PositionAngle.TRUE, 2.0, 3).value(state);
651
652 Assert.assertEquals(jacobianRef.length, jacobian.length);
653 Assert.assertEquals(jacobianRef[0].length, jacobian[0].length);
654
655
656 double [][] dJacobian = new double[jacobian.length][jacobian[0].length];
657 double [][] dJacobianRelative = new double[jacobian.length][jacobian[0].length];
658 for (int i = 0; i < jacobian.length; ++i) {
659 for (int j = 0; j < jacobian[i].length; ++j) {
660 dJacobian[i][j] = jacobian[i][j] - jacobianRef[i][j];
661 dJacobianRelative[i][j] = FastMath.abs(dJacobian[i][j]/jacobianRef[i][j]);
662
663 if (j < 3) { errorsP.add(dJacobianRelative[i][j]);
664 } else { errorsV.add(dJacobianRelative[i][j]); }
665 }
666 }
667
668 if (printResults) {
669 System.out.format(Locale.US, "%-15s %-23s %-23s " +
670 "%10.3e %10.3e %10.3e " +
671 "%10.3e %10.3e %10.3e " +
672 "%10.3e %10.3e %10.3e " +
673 "%10.3e %10.3e %10.3e%n",
674 stationName, measurement.getDate(), date,
675 dJacobian[0][0], dJacobian[0][1], dJacobian[0][2],
676 dJacobian[0][3], dJacobian[0][4], dJacobian[0][5],
677 dJacobianRelative[0][0], dJacobianRelative[0][1], dJacobianRelative[0][2],
678 dJacobianRelative[0][3], dJacobianRelative[0][4], dJacobianRelative[0][5]);
679 }
680 }
681 }
682 });
683
684
685 if (printResults) {
686 System.out.format(Locale.US, "%-15s %-23s %-23s " +
687 "%10s %10s %10s " +
688 "%10s %10s %10s " +
689 "%10s %10s %10s " +
690 "%10s %10s %10s%n",
691 "Station", "Measurement Date", "State Date",
692 "ΔdPx", "ΔdPy", "ΔdPz", "ΔdVx", "ΔdVy", "ΔdVz",
693 "rel ΔdPx", "rel ΔdPy", "rel ΔdPz",
694 "rel ΔdVx", "rel ΔdVy", "rel ΔdVz");
695 }
696
697
698 propagator.propagate(context.initialOrbit.getDate());
699
700
701 measurements.sort(Comparator.naturalOrder());
702
703
704 propagator.propagate(measurements.get(measurements.size()-1).getDate());
705
706
707 final double relErrorsP[] = errorsP.stream().mapToDouble(Double::doubleValue).toArray();
708 final double relErrorsV[] = errorsV.stream().mapToDouble(Double::doubleValue).toArray();
709
710 final double errorsPMedian = new Median().evaluate(relErrorsP);
711 final double errorsPMean = new Mean().evaluate(relErrorsP);
712 final double errorsPMax = new Max().evaluate(relErrorsP);
713 final double errorsVMedian = new Median().evaluate(relErrorsV);
714 final double errorsVMean = new Mean().evaluate(relErrorsV);
715 final double errorsVMax = new Max().evaluate(relErrorsV);
716
717
718 if (printResults) {
719 System.out.println();
720 System.out.format(Locale.US, "Relative errors dΦ/dP -> Median: %6.3e / Mean: %6.3e / Max: %6.3e%n",
721 errorsPMedian, errorsPMean, errorsPMax);
722 System.out.format(Locale.US, "Relative errors dΦ/dV -> Median: %6.3e / Mean: %6.3e / Max: %6.3e%n",
723 errorsVMedian, errorsVMean, errorsVMax);
724 }
725
726 Assert.assertEquals(0.0, errorsPMedian, refErrorsPMedian);
727 Assert.assertEquals(0.0, errorsPMean, refErrorsPMean);
728 Assert.assertEquals(0.0, errorsPMax, refErrorsPMax);
729 Assert.assertEquals(0.0, errorsVMedian, refErrorsVMedian);
730 Assert.assertEquals(0.0, errorsVMean, refErrorsVMean);
731 Assert.assertEquals(0.0, errorsVMax, refErrorsVMax);
732 }
733
734 @Test
735 public void testStateDerivativesWithIonosphericModifier() {
736
737 final boolean printResults = false;
738 final double refErrorsPMedian = 5.1e-10;
739 final double refErrorsPMean = 2.6e-9;
740 final double refErrorsPMax = 7.8e-8;
741 final double refErrorsVMedian = 2.0e-5;
742 final double refErrorsVMean = 6.0e-5;
743 final double refErrorsVMax = 2.1e-3;
744
745 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
746
747 final NumericalPropagatorBuilder propagatorBuilder =
748 context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true,
749 1.0e-6, 60.0, 0.001);
750
751
752 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
753 propagatorBuilder);
754 final double groundClockOffset = 12.0e-6;
755 for (final GroundStation station : context.stations) {
756 station.getClockOffsetDriver().setValue(groundClockOffset);
757 }
758 final int ambiguity = 1234;
759 final double satClockOffset = 345.0e-6;
760 final List<ObservedMeasurement<?>> measurements =
761 EstimationTestUtils.createMeasurements(propagator,
762 new PhaseMeasurementCreator(context,
763 Frequency.E01,
764 ambiguity,
765 satClockOffset),
766 1.0, 3.0, 300.0);
767
768
769
770 final List<Double> errorsP = new ArrayList<Double>();
771 final List<Double> errorsV = new ArrayList<Double>();
772
773 final IonosphericModel model = new KlobucharIonoModel(new double[]{.3820e-07, .1490e-07, -.1790e-06, 0},
774 new double[]{.1430e+06, 0, -.3280e+06, .1130e+06});
775 final double frequency = Frequency.G01.getMHzFrequency() * 1.0e6;
776 final PhaseIonosphericDelayModifier modifier = new PhaseIonosphericDelayModifier(model, frequency);
777
778
779 propagator.setStepHandler(interpolator -> {
780
781 for (final ObservedMeasurement<?> measurement : measurements) {
782
783 final Phase phase = (Phase) measurement;
784
785 if ((measurement.getDate().durationFrom(interpolator.getPreviousState().getDate()) > 0.) &&
786 (measurement.getDate().durationFrom(interpolator.getCurrentState().getDate()) <= 0.)) {
787
788
789 phase.addModifier(modifier);
790
791
792
793
794
795
796
797
798 final double meanDelay = measurement.getObservedValue()[0] / Constants.SPEED_OF_LIGHT;
799 final AbsoluteDate date = measurement.getDate().shiftedBy(-0.75 * meanDelay);
800 final SpacecraftState state = interpolator.getInterpolatedState(date);
801 final double[][] jacobian = measurement.estimate(0, 0, new SpacecraftState[] { state }).getStateDerivatives(0);
802
803
804 final double[][] jacobianRef;
805
806
807 jacobianRef = Differentiation.differentiate(new StateFunction() {
808 public double[] value(final SpacecraftState state) {
809 return measurement.estimate(0, 0, new SpacecraftState[] { state }).getEstimatedValue();
810 }
811 }, measurement.getDimension(), propagator.getAttitudeProvider(),
812 OrbitType.CARTESIAN, PositionAngle.TRUE, 2.0, 3).value(state);
813
814 Assert.assertEquals(jacobianRef.length, jacobian.length);
815 Assert.assertEquals(jacobianRef[0].length, jacobian[0].length);
816
817
818 double [][] dJacobian = new double[jacobian.length][jacobian[0].length];
819 double [][] dJacobianRelative = new double[jacobian.length][jacobian[0].length];
820 for (int i = 0; i < jacobian.length; ++i) {
821 for (int j = 0; j < jacobian[i].length; ++j) {
822 dJacobian[i][j] = jacobian[i][j] - jacobianRef[i][j];
823 dJacobianRelative[i][j] = FastMath.abs(dJacobian[i][j]/jacobianRef[i][j]);
824
825 if (j < 3) { errorsP.add(dJacobianRelative[i][j]);
826 } else { errorsV.add(dJacobianRelative[i][j]); }
827 }
828 }
829
830 if (printResults) {
831 System.out.format(Locale.US, "%-15s %-23s %-23s " +
832 "%10.3e %10.3e %10.3e " +
833 "%10.3e %10.3e %10.3e " +
834 "%10.3e %10.3e %10.3e " +
835 "%10.3e %10.3e %10.3e%n",
836 phase.getStation().getBaseFrame().getName(), measurement.getDate(), date,
837 dJacobian[0][0], dJacobian[0][1], dJacobian[0][2],
838 dJacobian[0][3], dJacobian[0][4], dJacobian[0][5],
839 dJacobianRelative[0][0], dJacobianRelative[0][1], dJacobianRelative[0][2],
840 dJacobianRelative[0][3], dJacobianRelative[0][4], dJacobianRelative[0][5]);
841 }
842 }
843 }
844 });
845
846
847 if (printResults) {
848 System.out.format(Locale.US, "%-15s %-23s %-23s " +
849 "%10s %10s %10s " +
850 "%10s %10s %10s " +
851 "%10s %10s %10s " +
852 "%10s %10s %10s%n",
853 "Station", "Measurement Date", "State Date",
854 "ΔdPx", "ΔdPy", "ΔdPz", "ΔdVx", "ΔdVy", "ΔdVz",
855 "rel ΔdPx", "rel ΔdPy", "rel ΔdPz",
856 "rel ΔdVx", "rel ΔdVy", "rel ΔdVz");
857 }
858
859
860 propagator.propagate(context.initialOrbit.getDate());
861
862
863 measurements.sort(Comparator.naturalOrder());
864
865
866 propagator.propagate(measurements.get(measurements.size()-1).getDate());
867
868
869 final double relErrorsP[] = errorsP.stream().mapToDouble(Double::doubleValue).toArray();
870 final double relErrorsV[] = errorsV.stream().mapToDouble(Double::doubleValue).toArray();
871
872 final double errorsPMedian = new Median().evaluate(relErrorsP);
873 final double errorsPMean = new Mean().evaluate(relErrorsP);
874 final double errorsPMax = new Max().evaluate(relErrorsP);
875 final double errorsVMedian = new Median().evaluate(relErrorsV);
876 final double errorsVMean = new Mean().evaluate(relErrorsV);
877 final double errorsVMax = new Max().evaluate(relErrorsV);
878
879
880 if (printResults) {
881 System.out.println();
882 System.out.format(Locale.US, "Relative errors dΦ/dP -> Median: %6.3e / Mean: %6.3e / Max: %6.3e%n",
883 errorsPMedian, errorsPMean, errorsPMax);
884 System.out.format(Locale.US, "Relative errors dΦ/dV -> Median: %6.3e / Mean: %6.3e / Max: %6.3e%n",
885 errorsVMedian, errorsVMean, errorsVMax);
886 }
887
888 Assert.assertEquals(0.0, errorsPMedian, refErrorsPMedian);
889 Assert.assertEquals(0.0, errorsPMean, refErrorsPMean);
890 Assert.assertEquals(0.0, errorsPMax, refErrorsPMax);
891 Assert.assertEquals(0.0, errorsVMedian, refErrorsVMedian);
892 Assert.assertEquals(0.0, errorsVMean, refErrorsVMean);
893 Assert.assertEquals(0.0, errorsVMax, refErrorsVMax);
894 }
895
896 @Test
897 public void testIssue734() {
898
899 Utils.setDataRoot("regular-data");
900
901
902 final OneAxisEllipsoid body = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, Constants.WGS84_EARTH_FLATTENING,
903 FramesFactory.getITRF(IERSConventions.IERS_2010, true));
904 final TopocentricFrame topo = new TopocentricFrame(body,
905 new GeodeticPoint(FastMath.toRadians(51.8), FastMath.toRadians(102.2), 811.2),
906 "BADG");
907 final GroundStation station = new GroundStation(topo);
908
909
910 final Phase phase = new Phase(station, AbsoluteDate.J2000_EPOCH, 119866527.060, Frequency.G01.getWavelength(), 0.02, 1.0, new ObservableSatellite(0));
911
912
913 Assert.assertEquals(0.0, phase.getAmbiguityDriver().getValue(), Double.MIN_VALUE);
914 Assert.assertFalse(phase.getAmbiguityDriver().isSelected());
915
916
917 phase.getAmbiguityDriver().setValue(1234.0);
918 phase.getAmbiguityDriver().setSelected(true);
919
920
921 Assert.assertEquals(1234.0, phase.getAmbiguityDriver().getValue(), Double.MIN_VALUE);
922 Assert.assertTrue(phase.getAmbiguityDriver().isSelected());
923 for (ParameterDriver driver : phase.getParametersDrivers()) {
924
925 if (driver.getName() == Phase.AMBIGUITY_NAME) {
926 Assert.assertEquals(1234.0, phase.getAmbiguityDriver().getValue(), Double.MIN_VALUE);
927 Assert.assertTrue(phase.getAmbiguityDriver().isSelected());
928 }
929 }
930
931 }
932
933 }