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 org.hipparchus.geometry.euclidean.threed.Vector3D;
20 import org.hipparchus.stat.descriptive.moment.Mean;
21 import org.hipparchus.stat.descriptive.rank.Max;
22 import org.hipparchus.stat.descriptive.rank.Median;
23 import org.hipparchus.stat.descriptive.rank.Min;
24 import org.hipparchus.util.FastMath;
25 import org.junit.jupiter.api.Assertions;
26 import org.junit.jupiter.api.Test;
27 import org.orekit.estimation.Context;
28 import org.orekit.estimation.EstimationTestUtils;
29 import org.orekit.estimation.measurements.EstimatedMeasurementBase;
30 import org.orekit.estimation.measurements.ObservedMeasurement;
31 import org.orekit.orbits.CartesianOrbit;
32 import org.orekit.orbits.Orbit;
33 import org.orekit.orbits.OrbitType;
34 import org.orekit.orbits.PositionAngleType;
35 import org.orekit.propagation.BoundedPropagator;
36 import org.orekit.propagation.EphemerisGenerator;
37 import org.orekit.propagation.Propagator;
38 import org.orekit.propagation.SpacecraftState;
39 import org.orekit.propagation.conversion.NumericalPropagatorBuilder;
40 import org.orekit.time.AbsoluteDate;
41 import org.orekit.utils.Constants;
42 import org.orekit.utils.Differentiation;
43 import org.orekit.utils.PVCoordinates;
44 import org.orekit.utils.ParameterDriver;
45 import org.orekit.utils.ParameterFunction;
46 import org.orekit.utils.TimeSpanMap.Span;
47 import org.orekit.utils.TimeStampedPVCoordinates;
48
49 import java.util.ArrayList;
50 import java.util.Comparator;
51 import java.util.List;
52 import java.util.Locale;
53
54 public class InterSatellitesOneWayRangeRateTest {
55
56
57
58
59
60 @Test
61 public void testValues() {
62 boolean printResults = false;
63 if (printResults) {
64 System.out.println("\nTest inter-satellites Range Rate Values\n");
65 }
66
67 this.genericTestValues(printResults);
68 }
69
70
71
72
73
74 @Test
75 public void testStateDerivativesEmitter() {
76
77 boolean printResults = false;
78 if (printResults) {
79 System.out.println("\nTest inter-satellites Range Rate State Derivatives - Finite Differences Comparison\n");
80 }
81
82 double refErrorsPMedian = 7.1e-10;
83 double refErrorsPMean = 7.1e-09;
84 double refErrorsPMax = 1.8e-06;
85 double refErrorsVMedian = 2.4e-10;
86 double refErrorsVMean = 5.2e-10;
87 double refErrorsVMax = 2.5e-08;
88 this.genericTestStateDerivatives(printResults, 0,
89 refErrorsPMedian, refErrorsPMean, refErrorsPMax,
90 refErrorsVMedian, refErrorsVMean, refErrorsVMax);
91 }
92
93
94
95
96
97 @Test
98 public void testStateDerivativesTransit() {
99
100 boolean printResults = false;
101 if (printResults) {
102 System.out.println("\nTest inter-satellites Range Rate State Derivatives - Finite Differences Comparison\n");
103 }
104
105 double refErrorsPMedian = 7.1e-10;
106 double refErrorsPMean = 7.1e-09;
107 double refErrorsPMax = 1.8e-06;
108 double refErrorsVMedian = 2.6e-010;
109 double refErrorsVMean = 4.9e-10;
110 double refErrorsVMax = 1.1e-08;
111 this.genericTestStateDerivatives(printResults, 1,
112 refErrorsPMedian, refErrorsPMean, refErrorsPMax,
113 refErrorsVMedian, refErrorsVMean, refErrorsVMax);
114 }
115
116
117
118
119
120 @Test
121 public void testParameterDerivatives() {
122
123
124 boolean printResults = false;
125
126 if (printResults) {
127 System.out.println("\nTest Range Rate Parameter Derivatives - Finite Differences Comparison\n");
128 }
129
130 double refErrorsMedian = 2.6e-15;
131 double refErrorsMean = 1.2e-7;
132 double refErrorsMax = 2.9e-6;
133 this.genericTestParameterDerivatives(printResults,
134 refErrorsMedian, refErrorsMean, refErrorsMax);
135
136 }
137
138
139
140
141
142 void genericTestValues(final boolean printResults) {
143
144 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
145
146 final NumericalPropagatorBuilder propagatorBuilder =
147 context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
148 1.0e-6, 60.0, 0.001);
149
150
151 final TimeStampedPVCoordinates original = context.initialOrbit.getPVCoordinates();
152 final Orbit closeOrbit = new CartesianOrbit(new TimeStampedPVCoordinates(context.initialOrbit.getDate(),
153 original.getPosition().add(new Vector3D(1000, 2000, 3000)),
154 original.getVelocity().add(new Vector3D(-0.03, 0.01, 0.02))),
155 context.initialOrbit.getFrame(),
156 context.initialOrbit.getMu());
157 final Propagator closePropagator = EstimationTestUtils.createPropagator(closeOrbit,
158 propagatorBuilder);
159 final EphemerisGenerator generator = closePropagator.getEphemerisGenerator();
160 closePropagator.propagate(context.initialOrbit.getDate().shiftedBy(3.5 * closeOrbit.getKeplerianPeriod()));
161 final BoundedPropagator ephemeris = generator.getGeneratedEphemeris();
162 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
163 propagatorBuilder);
164
165 final double localClockOffset = 0.14e-06;
166 final double localClockRate = -0.12e-10;
167 final double localClockAcceleration = 1.4e-13;
168 final double remoteClockOffset = 469.0e-06;
169 final double remoteClockRate = 33.0e-10;
170 final double remoteClockAcceleration = 0.5e-13;
171 final List<ObservedMeasurement<?>> measurements =
172 EstimationTestUtils.createMeasurements(propagator,
173 new InterSatellitesOneWayRangeRateMeasurementCreator(ephemeris,
174 localClockOffset, localClockRate, localClockAcceleration,
175 remoteClockOffset, remoteClockRate, remoteClockAcceleration),
176 1.0, 3.0, 300.0);
177
178
179
180 final List<Double> absoluteErrors = new ArrayList<>();
181 final List<Double> relativeErrors = new ArrayList<>();
182
183
184 propagator.setStepHandler(interpolator -> {
185
186 for (final ObservedMeasurement<?> measurement : measurements) {
187
188
189 if (measurement.getDate().isAfter(interpolator.getPreviousState()) &&
190 measurement.getDate().isBeforeOrEqualTo(interpolator.getCurrentState())) {
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 rangeRateObserved = measurement.getObservedValue()[0];
202 final EstimatedMeasurementBase<?> estimated = measurement.estimateWithoutDerivatives(new SpacecraftState[] {
203 state,
204 ephemeris.propagate(state.getDate())
205 });
206
207 final TimeStampedPVCoordinates[] participants = estimated.getParticipants();
208 Assertions.assertEquals(2, participants.length);
209 final PVCoordinates delta = new PVCoordinates(participants[0], participants[1]);
210 final double radialVelocity = Vector3D.dotProduct(delta.getVelocity(), delta.getPosition().normalize());
211 final AbsoluteDate t0 = measurement.getSatellites().get(0).getClockOffsetDriver().getReferenceDate();
212 final double dtLocal = measurement.getDate().durationFrom(t0);
213 final double localRate = 2 * localClockAcceleration * dtLocal + localClockRate;
214 final double dtRemote = participants[0].getDate().durationFrom(t0);
215 final double remoteRate = 2 * remoteClockAcceleration * dtRemote + remoteClockRate;
216 Assertions.assertEquals(radialVelocity + Constants.SPEED_OF_LIGHT * (localRate - remoteRate),
217 estimated.getEstimatedValue()[0],
218 1.0e-7);
219
220 final double rangeRateEstimated = estimated.getEstimatedValue()[0];
221 final double absoluteError = rangeRateEstimated-rangeRateObserved;
222 absoluteErrors.add(absoluteError);
223 relativeErrors.add(FastMath.abs(absoluteError)/FastMath.abs(rangeRateObserved));
224
225
226 if (printResults) {
227 final AbsoluteDate measurementDate = measurement.getDate();
228
229 System.out.format(Locale.US, "%-23s %-23s %19.6f %19.6f %13.6e %13.6e%n",
230 measurementDate.toStringWithoutUtcOffset(context.utc, 3),
231 date.toStringWithoutUtcOffset(context.utc, 3),
232 rangeRateObserved, rangeRateEstimated,
233 FastMath.abs(rangeRateEstimated-rangeRateObserved),
234 FastMath.abs((rangeRateEstimated-rangeRateObserved)/rangeRateObserved));
235 }
236
237 }
238 }
239 });
240
241
242 if (printResults) {
243 System.out.format(Locale.US, "%-23s %-23s %19s %19s %19s %19s%n",
244 "Measurement Date", "State Date",
245 "range rate observed [m/s]", "range rate estimated [m/s]",
246 "Δrange rate [m/s]", "rel Δrange rate");
247 }
248
249
250 propagator.propagate(context.initialOrbit.getDate());
251
252
253 measurements.sort(Comparator.naturalOrder());
254
255
256 propagator.propagate(measurements.get(measurements.size()-1).getDate());
257
258
259 final double[] absErrors = absoluteErrors.stream().mapToDouble(Double::doubleValue).toArray();
260 final double[] relErrors = relativeErrors.stream().mapToDouble(Double::doubleValue).toArray();
261
262
263 final double absErrorsMedian = new Median().evaluate(absErrors);
264 final double absErrorsMin = new Min().evaluate(absErrors);
265 final double absErrorsMax = new Max().evaluate(absErrors);
266 final double relErrorsMedian = new Median().evaluate(relErrors);
267 final double relErrorsMax = new Max().evaluate(relErrors);
268
269
270 if (printResults) {
271 System.out.println();
272 System.out.println("Absolute errors median: " + absErrorsMedian);
273 System.out.println("Absolute errors min : " + absErrorsMin);
274 System.out.println("Absolute errors max : " + absErrorsMax);
275 System.out.println("Relative errors median: " + relErrorsMedian);
276 System.out.println("Relative errors max : " + relErrorsMax);
277 }
278
279 Assertions.assertEquals(0.0, absErrorsMedian, 3.7e-09);
280 Assertions.assertEquals(0.0, absErrorsMin, 2.6e-11);
281 Assertions.assertEquals(0.0, absErrorsMax, 1.5e-08);
282 Assertions.assertEquals(0.0, relErrorsMedian, 9.9e-10);
283 Assertions.assertEquals(0.0, relErrorsMax, 5.7e-8);
284
285
286 Assertions.assertEquals(InterSatellitesOneWayRangeRate.MEASUREMENT_TYPE, measurements.get(0).getMeasurementType());
287 }
288
289 void genericTestStateDerivatives(final boolean printResults, final int index,
290 final double refErrorsPMedian, final double refErrorsPMean, final double refErrorsPMax,
291 final double refErrorsVMedian, final double refErrorsVMean, final double refErrorsVMax) {
292
293 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
294
295 final NumericalPropagatorBuilder propagatorBuilder =
296 context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
297 1.0e-6, 60.0, 0.001);
298
299
300 final TimeStampedPVCoordinates original = context.initialOrbit.getPVCoordinates();
301 final Orbit closeOrbit = new CartesianOrbit(new TimeStampedPVCoordinates(context.initialOrbit.getDate(),
302 original.getPosition().add(new Vector3D(1000, 2000, 3000)),
303 original.getVelocity().add(new Vector3D(-0.03, 0.01, 0.02))),
304 context.initialOrbit.getFrame(),
305 context.initialOrbit.getMu());
306 final Propagator closePropagator = EstimationTestUtils.createPropagator(closeOrbit,
307 propagatorBuilder);
308 final EphemerisGenerator generator = closePropagator.getEphemerisGenerator();
309 closePropagator.propagate(context.initialOrbit.getDate().shiftedBy(3.5 * closeOrbit.getKeplerianPeriod()));
310 final BoundedPropagator ephemeris = generator.getGeneratedEphemeris();
311 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
312 propagatorBuilder);
313
314 final double localClockOffset = 0.14e-06;
315 final double localClockRate = -0.12e-10;
316 final double localClockAcceleration = 1.4e-13;
317 final double remoteClockOffset = 469.0e-06;
318 final double remoteClockRate = 33.0e-10;
319 final double remoteClockAcceleration = 0.5e-13;
320 final List<ObservedMeasurement<?>> measurements =
321 EstimationTestUtils.createMeasurements(propagator,
322 new InterSatellitesOneWayRangeRateMeasurementCreator(ephemeris,
323 localClockOffset, localClockRate, localClockAcceleration,
324 remoteClockOffset, remoteClockRate, remoteClockAcceleration),
325 1.0, 3.0, 300.0);
326
327
328
329 final List<Double> errorsP = new ArrayList<>();
330 final List<Double> errorsV = new ArrayList<>();
331
332
333 propagator.setStepHandler(interpolator -> {
334
335 for (final ObservedMeasurement<?> measurement : measurements) {
336
337
338 if (measurement.getDate().isAfter(interpolator.getPreviousState()) &&
339 measurement.getDate().isBeforeOrEqualTo(interpolator.getCurrentState())) {
340
341
342
343
344
345
346 final double meanDelay = measurement.getObservedValue()[0] / Constants.SPEED_OF_LIGHT;
347 final AbsoluteDate date = measurement.getDate().shiftedBy(-0.75 * meanDelay);
348 final SpacecraftState[] states = {
349 interpolator.getInterpolatedState(date),
350 ephemeris.propagate(date)
351 };
352 final double[][] jacobian = measurement.estimate(0, 0, states).getStateDerivatives(index);
353
354
355 final double[][] jacobianRef;
356
357
358 jacobianRef = Differentiation.differentiate(state -> {
359 final SpacecraftState[] s = states.clone();
360 s[index] = state;
361 return measurement.estimateWithoutDerivatives(s).getEstimatedValue();
362 }, measurement.getDimension(), propagator.getAttitudeProvider(),
363 OrbitType.CARTESIAN, PositionAngleType.TRUE, 2.0, 3).value(states[index]);
364
365 Assertions.assertEquals(jacobianRef.length, jacobian.length);
366 Assertions.assertEquals(jacobianRef[0].length, jacobian[0].length);
367
368
369 double [][] dJacobian = new double[jacobian.length][jacobian[0].length];
370 double [][] dJacobianRelative = new double[jacobian.length][jacobian[0].length];
371 for (int i = 0; i < jacobian.length; ++i) {
372 for (int j = 0; j < jacobian[i].length; ++j) {
373 dJacobian[i][j] = jacobian[i][j] - jacobianRef[i][j];
374 dJacobianRelative[i][j] = FastMath.abs(dJacobian[i][j]/jacobianRef[i][j]);
375
376 if (j < 3) {
377 errorsP.add(dJacobianRelative[i][j]);
378 } else {
379 errorsV.add(dJacobianRelative[i][j]);
380 }
381 }
382 }
383
384 if (printResults) {
385 System.out.format(Locale.US, "%-23s %-23s " +
386 "%10.3e %10.3e %10.3e " +
387 "%10.3e %10.3e %10.3e " +
388 "%10.3e %10.3e %10.3e " +
389 "%10.3e %10.3e %10.3e%n",
390 measurement.getDate().toStringWithoutUtcOffset(context.utc, 3),
391 date.toStringWithoutUtcOffset(context.utc, 3),
392 dJacobian[0][0], dJacobian[0][1], dJacobian[0][2],
393 dJacobian[0][3], dJacobian[0][4], dJacobian[0][5],
394 dJacobianRelative[0][0], dJacobianRelative[0][1], dJacobianRelative[0][2],
395 dJacobianRelative[0][3], dJacobianRelative[0][4], dJacobianRelative[0][5]);
396 }
397 }
398 }
399 });
400
401
402 if (printResults) {
403 System.out.format(Locale.US, "%-23s %-23s " +
404 "%10s %10s %10s " +
405 "%10s %10s %10s " +
406 "%10s %10s %10s " +
407 "%10s %10s %10s%n",
408 "Measurement Date", "State Date",
409 "ΔdPx", "ΔdPy", "ΔdPz", "ΔdVx", "ΔdVy", "ΔdVz",
410 "rel ΔdPx", "rel ΔdPy", "rel ΔdPz",
411 "rel ΔdVx", "rel ΔdVy", "rel ΔdVz");
412 }
413
414
415 propagator.propagate(context.initialOrbit.getDate());
416
417
418 measurements.sort(Comparator.naturalOrder());
419
420
421 propagator.propagate(measurements.get(measurements.size()-1).getDate());
422
423
424 final double[] relErrorsP = errorsP.stream().mapToDouble(Double::doubleValue).toArray();
425 final double[] relErrorsV = errorsV.stream().mapToDouble(Double::doubleValue).toArray();
426
427 final double errorsPMedian = new Median().evaluate(relErrorsP);
428 final double errorsPMean = new Mean().evaluate(relErrorsP);
429 final double errorsPMax = new Max().evaluate(relErrorsP);
430 final double errorsVMedian = new Median().evaluate(relErrorsV);
431 final double errorsVMean = new Mean().evaluate(relErrorsV);
432 final double errorsVMax = new Max().evaluate(relErrorsV);
433
434
435 if (printResults) {
436 System.out.println();
437 System.out.format(Locale.US, "Relative errors dR/dP -> Median: %6.3e / Mean: %6.3e / Max: %6.3e%n",
438 errorsPMedian, errorsPMean, errorsPMax);
439 System.out.format(Locale.US, "Relative errors dR/dV -> Median: %6.3e / Mean: %6.3e / Max: %6.3e%n",
440 errorsVMedian, errorsVMean, errorsVMax);
441 }
442
443 Assertions.assertEquals(0.0, errorsPMedian, refErrorsPMedian);
444 Assertions.assertEquals(0.0, errorsPMean, refErrorsPMean);
445 Assertions.assertEquals(0.0, errorsPMax, refErrorsPMax);
446 Assertions.assertEquals(0.0, errorsVMedian, refErrorsVMedian);
447 Assertions.assertEquals(0.0, errorsVMean, refErrorsVMean);
448 Assertions.assertEquals(0.0, errorsVMax, refErrorsVMax);
449 }
450
451 void genericTestParameterDerivatives(final boolean printResults,
452 final double refErrorsMedian, final double refErrorsMean, final double refErrorsMax) {
453
454 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
455
456 final NumericalPropagatorBuilder propagatorBuilder =
457 context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
458 1.0e-6, 60.0, 0.001);
459
460
461 final TimeStampedPVCoordinates original = context.initialOrbit.getPVCoordinates();
462 final Orbit closeOrbit = new CartesianOrbit(new TimeStampedPVCoordinates(context.initialOrbit.getDate(),
463 original.getPosition().add(new Vector3D(1000, 2000, 3000)),
464 original.getVelocity().add(new Vector3D(-0.03, 0.01, 0.02))),
465 context.initialOrbit.getFrame(),
466 context.initialOrbit.getMu());
467 final Propagator closePropagator = EstimationTestUtils.createPropagator(closeOrbit, propagatorBuilder);
468 final EphemerisGenerator generator = closePropagator.getEphemerisGenerator();
469 closePropagator.propagate(context.initialOrbit.getDate().shiftedBy(3.5 * closeOrbit.getKeplerianPeriod()));
470 final BoundedPropagator ephemeris = generator.getGeneratedEphemeris();
471
472
473 final double localClockOffset = 0.14e-06;
474 final double localClockRate = -0.12e-10;
475 final double localClockAcceleration = 1.4e-13;
476 final double remoteClockOffset = 469.0e-06;
477 final double remoteClockRate = 33.0e-10;
478 final double remoteClockAcceleration = 0.5e-13;
479 final InterSatellitesOneWayRangeRateMeasurementCreator creator =
480 new InterSatellitesOneWayRangeRateMeasurementCreator(ephemeris,
481 localClockOffset, localClockRate, localClockAcceleration,
482 remoteClockOffset, remoteClockRate, remoteClockAcceleration);
483 creator.getLocalSatellite().getClockOffsetDriver().setSelected(true);
484 creator.getLocalSatellite().getClockDriftDriver().setSelected(true);
485 creator.getLocalSatellite().getClockAccelerationDriver().setSelected(true);
486 creator.getRemoteSatellite().getClockOffsetDriver().setSelected(true);
487 creator.getRemoteSatellite().getClockDriftDriver().setSelected(true);
488 creator.getRemoteSatellite().getClockAccelerationDriver().setSelected(true);
489
490 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
491 propagatorBuilder);
492 final List<ObservedMeasurement<?>> measurements =
493 EstimationTestUtils.createMeasurements(propagator, creator, 1.0, 3.0, 300.0);
494
495
496 final List<Double> relErrorList = new ArrayList<>();
497
498
499 propagator.setStepHandler(interpolator -> {
500
501 for (final ObservedMeasurement<?> measurement : measurements) {
502
503
504 if (measurement.getDate().isAfter(interpolator.getPreviousState()) &&
505 measurement.getDate().isBeforeOrEqualTo(interpolator.getCurrentState())) {
506
507
508
509
510
511
512
513
514 final double meanDelay = measurement.getObservedValue()[0] / Constants.SPEED_OF_LIGHT;
515 final AbsoluteDate date = measurement.getDate().shiftedBy(-0.75 * meanDelay);
516 final SpacecraftState[] states = {
517 interpolator.getInterpolatedState(date),
518 ephemeris.propagate(date)
519 };
520 final ParameterDriver[] drivers = new ParameterDriver[] {
521 measurement.getSatellites().get(0).getClockOffsetDriver(),
522 measurement.getSatellites().get(0).getClockDriftDriver(),
523 measurement.getSatellites().get(0).getClockAccelerationDriver(),
524 measurement.getSatellites().get(1).getClockOffsetDriver(),
525 measurement.getSatellites().get(1).getClockDriftDriver(),
526 measurement.getSatellites().get(1).getClockAccelerationDriver()
527 };
528
529 for (final ParameterDriver driver : drivers) {
530 for (Span<String> span = driver.getNamesSpanMap().getFirstSpan(); span != null; span = span.next()) {
531 final double[] gradient = measurement.estimate(0, 0, states).getParameterDerivatives(driver, span.getStart());
532 Assertions.assertEquals(1, measurement.getDimension());
533 Assertions.assertEquals(1, gradient.length);
534
535
536 final ParameterFunction dMkdP =
537 Differentiation.differentiate(new ParameterFunction() {
538
539 @Override
540 public double value(final ParameterDriver parameterDriver, final AbsoluteDate date) {
541 return measurement.
542 estimateWithoutDerivatives(states).
543 getEstimatedValue()[0];
544 }
545 }, 3, 20.0 * driver.getScale());
546 final double ref = dMkdP.value(driver, span.getStart());
547
548 final double relError;
549 if (ref == 0.0) {
550
551
552
553 relError = ref - gradient[0];
554 } else {
555 relError = FastMath.abs((ref - gradient[0]) / ref);
556 }
557 relErrorList.add(relError);
558
559 if (printResults) {
560 System.out.format(Locale.US, "%10.3e %10.3e ", gradient[0]-ref, relError);
561 }
562
563 }
564 }
565 if (printResults) {
566 System.out.format(Locale.US, "%n");
567 }
568
569 }
570 }
571 });
572
573
574 propagator.propagate(context.initialOrbit.getDate());
575
576
577 measurements.sort(Comparator.naturalOrder());
578
579
580 if (printResults) {
581 System.out.format(Locale.US, "%-22s %-22s %-22s %-22s %-22s %-22s%n" +
582 "%10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s%n",
583 "local offset", "local rate", "local acceleration",
584 "remote offset", "remote rate", "remote acceleration",
585 "Δoₗ", "rel Δoₗ", "Δrₗ", "rel Δrₗ", "Δaₗ", "rel Δaₗ",
586 "Δoᵣ", "rel Δoᵣ", "Δrᵣ", "rel Δrᵣ", "Δaᵣ", "rel Δaᵣ");
587 }
588
589
590 propagator.propagate(measurements.get(measurements.size()-1).getDate());
591
592
593 final double[] relErrors = relErrorList.stream().mapToDouble(Double::doubleValue).toArray();
594
595
596 final double relErrorsMedian = new Median().evaluate(relErrors);
597 final double relErrorsMean = new Mean().evaluate(relErrors);
598 final double relErrorsMax = new Max().evaluate(relErrors);
599
600
601 if (printResults) {
602 System.out.println();
603 System.out.format(Locale.US, "Relative errors dR/dQ -> Median: %6.3e / Mean: %6.3e / Max: %6.3e%n",
604 relErrorsMedian, relErrorsMean, relErrorsMax);
605 }
606
607 Assertions.assertEquals(0.0, relErrorsMedian, refErrorsMedian);
608 Assertions.assertEquals(0.0, relErrorsMean, refErrorsMean);
609 Assertions.assertEquals(0.0, relErrorsMax, refErrorsMax);
610
611 }
612
613 }