1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation;
18
19 import org.hipparchus.Field;
20 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
21 import org.hipparchus.geometry.euclidean.threed.Rotation;
22 import org.hipparchus.ode.FieldODEIntegrator;
23 import org.hipparchus.ode.nonstiff.DormandPrince853FieldIntegrator;
24 import org.hipparchus.util.Binary64;
25 import org.hipparchus.util.Binary64Field;
26 import org.hipparchus.util.FastMath;
27 import org.junit.jupiter.api.AfterEach;
28 import org.junit.jupiter.api.Assertions;
29 import org.junit.jupiter.api.BeforeEach;
30 import org.junit.jupiter.api.DisplayName;
31 import org.junit.jupiter.api.Test;
32 import org.mockito.Mockito;
33 import org.orekit.Utils;
34 import org.orekit.attitudes.AttitudeProvider;
35 import org.orekit.attitudes.BodyCenterPointing;
36 import org.orekit.attitudes.FieldAttitude;
37 import org.orekit.attitudes.FieldAttitudeInterpolator;
38 import org.orekit.bodies.CelestialBodyFactory;
39 import org.orekit.bodies.OneAxisEllipsoid;
40 import org.orekit.errors.OrekitException;
41 import org.orekit.errors.OrekitIllegalArgumentException;
42 import org.orekit.errors.OrekitInternalError;
43 import org.orekit.errors.OrekitMessages;
44 import org.orekit.forces.gravity.HolmesFeatherstoneAttractionModel;
45 import org.orekit.forces.gravity.SingleBodyAbsoluteAttraction;
46 import org.orekit.forces.gravity.potential.GravityFieldFactory;
47 import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider;
48 import org.orekit.frames.Frame;
49 import org.orekit.frames.FramesFactory;
50 import org.orekit.orbits.FieldKeplerianOrbit;
51 import org.orekit.orbits.FieldOrbit;
52 import org.orekit.orbits.FieldOrbitHermiteInterpolator;
53 import org.orekit.orbits.OrbitType;
54 import org.orekit.orbits.PositionAngleType;
55 import org.orekit.propagation.analytical.FieldEcksteinHechlerPropagator;
56 import org.orekit.propagation.numerical.FieldNumericalPropagator;
57 import org.orekit.time.AbsoluteDate;
58 import org.orekit.time.AbstractFieldTimeInterpolator;
59 import org.orekit.time.AbstractTimeInterpolator;
60 import org.orekit.time.DateComponents;
61 import org.orekit.time.FieldAbsoluteDate;
62 import org.orekit.time.FieldTimeInterpolator;
63 import org.orekit.time.FieldTimeStamped;
64 import org.orekit.time.TimeComponents;
65 import org.orekit.time.TimeScalesFactory;
66 import org.orekit.time.TimeStampedField;
67 import org.orekit.time.TimeStampedFieldHermiteInterpolator;
68 import org.orekit.utils.AngularDerivativesFilter;
69 import org.orekit.utils.CartesianDerivativesFilter;
70 import org.orekit.utils.Constants;
71 import org.orekit.utils.FieldAbsolutePVCoordinates;
72 import org.orekit.utils.FieldAbsolutePVCoordinatesHermiteInterpolator;
73 import org.orekit.utils.FieldPVCoordinates;
74 import org.orekit.utils.IERSConventions;
75
76 import java.util.ArrayList;
77 import java.util.Collections;
78 import java.util.List;
79
80 class FieldSpacecraftStateInterpolatorTest {
81
82 final private Field<Binary64> field = Binary64Field.getInstance();
83 private Binary64 mass;
84 private FieldOrbit<Binary64> orbit;
85 private FieldAbsolutePVCoordinates<Binary64> absPV;
86 private AttitudeProvider attitudeLaw;
87 private FieldPropagator<Binary64> analyticalPropagator;
88 private FieldPropagator<Binary64> absPVPropagator;
89
90 @BeforeEach
91 public void setUp() {
92 try {
93 Utils.setDataRoot("regular-data:potential/icgem-format");
94 Binary64 mu = new Binary64(3.9860047e14);
95 double ae = 6.378137e6;
96 double c20 = -1.08263e-3;
97 double c30 = 2.54e-6;
98 double c40 = 1.62e-6;
99 double c50 = 2.3e-7;
100 double c60 = -5.5e-7;
101
102 mass = new Binary64(2500);
103 Binary64 a = new Binary64(7187990.1979844316);
104 Binary64 e = new Binary64(0.5e-4);
105 Binary64 i = new Binary64(1.7105407051081795);
106 Binary64 omega = new Binary64(1.9674147913622104);
107 Binary64 OMEGA = new Binary64(FastMath.toRadians(261));
108 Binary64 lv = new Binary64(0);
109
110 FieldAbsoluteDate<Binary64> date = new FieldAbsoluteDate<>(field, new DateComponents(2004, 1, 1),
111 TimeComponents.H00,
112 TimeScalesFactory.getUTC());
113 final Frame frame = FramesFactory.getEME2000();
114
115 orbit = new FieldKeplerianOrbit<>(a, e, i, omega, OMEGA, lv, PositionAngleType.TRUE,
116 frame, date, mu);
117 OneAxisEllipsoid earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
118 Constants.WGS84_EARTH_FLATTENING,
119 FramesFactory.getITRF(IERSConventions.IERS_2010, true));
120
121 absPV = new FieldAbsolutePVCoordinates<>(frame, date, orbit.getPVCoordinates());
122
123 attitudeLaw = new BodyCenterPointing(orbit.getFrame(), earth);
124
125 analyticalPropagator =
126 new FieldEcksteinHechlerPropagator<>(orbit, attitudeLaw, mass,
127 ae, mu, c20, c30, c40, c50, c60);
128
129 absPVPropagator = setUpNumericalPropagator();
130
131 }
132 catch (OrekitException oe) {
133 Assertions.fail(oe.getLocalizedMessage());
134 }
135 }
136
137 @AfterEach
138 public void tearDown() {
139 mass = org.hipparchus.util.Binary64.NAN;
140 orbit = null;
141 attitudeLaw = null;
142 analyticalPropagator = null;
143 }
144
145 @Test
146 public void testOrbitInterpolation()
147 throws OrekitException {
148
149
150 final Frame inertialFrame = orbit.getFrame();
151
152 final FieldSpacecraftStateInterpolator<Binary64> interpolator1 =
153 new FieldSpacecraftStateInterpolator<>(2, inertialFrame);
154
155 final FieldSpacecraftStateInterpolator<Binary64> interpolator2 =
156 new FieldSpacecraftStateInterpolator<>(3, SpacecraftStateInterpolator.DEFAULT_EXTRAPOLATION_THRESHOLD_SEC, inertialFrame);
157
158 final FieldSpacecraftStateInterpolator<Binary64> interpolator3 =
159 new FieldSpacecraftStateInterpolator<>(4, SpacecraftStateInterpolator.DEFAULT_EXTRAPOLATION_THRESHOLD_SEC, inertialFrame, inertialFrame);
160
161
162 checkStandardInterpolationError(2, 106.46533, 0.40709287, 169847806.33e-9, 0.0, 450 * 450, 450 * 450, interpolator1);
163 checkStandardInterpolationError(3, 0.00353, 0.00003250, 189886.01e-9, 0.0, 0.0, 0.0, interpolator2);
164 checkStandardInterpolationError(4, 0.00002, 0.00000023, 232.25e-9, 0.0, 0.0, 0.0, interpolator3);
165
166 }
167
168 @Test
169 public void testErrorThrownWhenOneInterpolatorIsNotConsistentWithSampleSize() {
170
171 final Frame outputFrame = Mockito.mock(Frame.class);
172
173 @SuppressWarnings("unchecked")
174 final FieldTimeInterpolator<FieldOrbit<Binary64>, Binary64> orbitInterpolator =
175 Mockito.mock(FieldTimeInterpolator.class);
176 Mockito.when(orbitInterpolator.getSubInterpolators()).thenReturn(Collections.singletonList(orbitInterpolator));
177 Mockito.when(orbitInterpolator.getNbInterpolationPoints()).thenReturn(2);
178
179 @SuppressWarnings("unchecked")
180 final FieldTimeInterpolator<FieldAbsolutePVCoordinates<Binary64>, Binary64> absPVInterpolator =
181 Mockito.mock(FieldTimeInterpolator.class);
182 Mockito.when(absPVInterpolator.getSubInterpolators()).thenReturn(Collections.singletonList(absPVInterpolator));
183 Mockito.when(absPVInterpolator.getNbInterpolationPoints()).thenReturn(4);
184
185 @SuppressWarnings("unchecked")
186 final FieldTimeInterpolator<TimeStampedField<Binary64>, Binary64> massInterpolator =
187 Mockito.mock(FieldTimeInterpolator.class);
188 Mockito.when(massInterpolator.getSubInterpolators()).thenReturn(Collections.singletonList(massInterpolator));
189 Mockito.when(massInterpolator.getNbInterpolationPoints()).thenReturn(2);
190
191 final FieldSpacecraftStateInterpolator<Binary64> stateInterpolator =
192 new FieldSpacecraftStateInterpolator<>(2, 1.0e-3, outputFrame, orbitInterpolator, absPVInterpolator, massInterpolator,
193 null, null);
194
195
196 OrekitIllegalArgumentException thrown = Assertions.assertThrows(OrekitIllegalArgumentException.class, () ->
197 AbstractFieldTimeInterpolator.checkInterpolatorCompatibilityWithSampleSize(stateInterpolator, 2));
198
199 Assertions.assertEquals(OrekitMessages.NOT_ENOUGH_DATA, thrown.getSpecifier());
200 Assertions.assertEquals(2, ((Integer) thrown.getParts()[0]).intValue());
201
202 }
203
204 @Test
205 public void testErrorThrownWhenOneInterpolatorIsNotConsistentWithSampleSizeDeprecated() {
206
207 final Frame outputFrame = Mockito.mock(Frame.class);
208
209 @SuppressWarnings("unchecked")
210 final FieldTimeInterpolator<FieldOrbit<Binary64>, Binary64> orbitInterpolator =
211 Mockito.mock(FieldTimeInterpolator.class);
212 Mockito.when(orbitInterpolator.getSubInterpolators()).thenReturn(Collections.singletonList(orbitInterpolator));
213 Mockito.when(orbitInterpolator.getNbInterpolationPoints()).thenReturn(2);
214
215 @SuppressWarnings("unchecked")
216 final FieldTimeInterpolator<FieldAbsolutePVCoordinates<Binary64>, Binary64> absPVInterpolator =
217 Mockito.mock(FieldTimeInterpolator.class);
218 Mockito.when(absPVInterpolator.getSubInterpolators()).thenReturn(Collections.singletonList(absPVInterpolator));
219 Mockito.when(absPVInterpolator.getNbInterpolationPoints()).thenReturn(4);
220
221 @SuppressWarnings("unchecked")
222 final FieldTimeInterpolator<TimeStampedField<Binary64>, Binary64> massInterpolator =
223 Mockito.mock(FieldTimeInterpolator.class);
224 Mockito.when(massInterpolator.getSubInterpolators()).thenReturn(Collections.singletonList(massInterpolator));
225 Mockito.when(massInterpolator.getNbInterpolationPoints()).thenReturn(2);
226
227 final FieldSpacecraftStateInterpolator<Binary64> stateInterpolator =
228 new FieldSpacecraftStateInterpolator<>(AbstractTimeInterpolator.DEFAULT_INTERPOLATION_POINTS,
229 AbstractTimeInterpolator.DEFAULT_EXTRAPOLATION_THRESHOLD_SEC,
230 outputFrame, orbitInterpolator, absPVInterpolator, massInterpolator,
231 null, null);
232
233
234 OrekitIllegalArgumentException thrown = Assertions.assertThrows(OrekitIllegalArgumentException.class, () ->
235 AbstractFieldTimeInterpolator.checkInterpolatorCompatibilityWithSampleSize(stateInterpolator, 2));
236
237 Assertions.assertEquals(OrekitMessages.NOT_ENOUGH_DATA, thrown.getSpecifier());
238 Assertions.assertEquals(2, ((Integer) thrown.getParts()[0]).intValue());
239
240 }
241
242 @Test
243 public void testAbsPVAInterpolation()
244 throws OrekitException {
245
246
247 final int interpolationPoints1 = 2;
248 final int interpolationPoints2 = 3;
249 final int interpolationPoints3 = 4;
250
251 final Frame intertialFrame = absPV.getFrame();
252
253
254 final FieldSpacecraftStateInterpolator<Binary64>[] interpolator1 =
255 buildAllTypeOfInterpolator(interpolationPoints1, intertialFrame);
256 final FieldSpacecraftStateInterpolator<Binary64>[] interpolator2 =
257 buildAllTypeOfInterpolator(interpolationPoints2, intertialFrame);
258 final FieldSpacecraftStateInterpolator<Binary64>[] interpolator3 =
259 buildAllTypeOfInterpolator(interpolationPoints3, intertialFrame);
260
261
262 checkAbsPVInterpolationError(interpolationPoints1, 766704.6033758943, 3385.895505018284,
263 9.503905101141868, 0.0, interpolator1[0]);
264 checkAbsPVInterpolationError(interpolationPoints2, 46190.78568215623, 531.3506621730367,
265 0.5601906427491941, 0, interpolator2[0]);
266 checkAbsPVInterpolationError(interpolationPoints3, 2787.7069621834926, 55.5146607205871,
267 0.03372344505743245, 0.0, interpolator3[0]);
268
269
270 checkAbsPVInterpolationError(interpolationPoints1, 14023.999059896296, 48.022197580401084,
271 0.16984517369482555, 0.0, interpolator1[1]);
272 checkAbsPVInterpolationError(interpolationPoints2, 16.186825338590722, 0.13418685366189476,
273 1.898961129289559E-4, 0, interpolator2[1]);
274 checkAbsPVInterpolationError(interpolationPoints3, 0.025110113133073413, 3.5069332429486154E-4,
275 2.3306042475258594E-7, 0.0, interpolator3[1]);
276
277
278 checkAbsPVInterpolationError(interpolationPoints1, 108.13907262943746, 0.4134494277844817,
279 0.001389170843175492, 0.0, interpolator1[2]);
280 checkAbsPVInterpolationError(interpolationPoints2, 0.002974408269435121, 2.6937387601886076E-5,
281 2.051629855188969E-4, 0, interpolator2[2]);
282 checkAbsPVInterpolationError(interpolationPoints3, 0, 0, 1.3779131041190534E-4,
283 0.0, interpolator3[2]);
284 }
285
286 @Test
287 public void testIssue775() {
288 final Field<Binary64> field = Binary64Field.getInstance();
289 final Binary64 zero = field.getZero();
290
291
292 FieldAbsoluteDate<Binary64> initDate = new FieldAbsoluteDate<>(field, new AbsoluteDate(
293 new DateComponents(2004, 1, 1), TimeComponents.H00, TimeScalesFactory.getUTC()));
294 FieldAbsoluteDate<Binary64> finalDate = new FieldAbsoluteDate<>(field, new AbsoluteDate(
295 new DateComponents(2004, 1, 2), TimeComponents.H00, TimeScalesFactory.getUTC()));
296 Frame inertialFrame = FramesFactory.getEME2000();
297
298
299 final FieldVector3D<Binary64> position = new FieldVector3D<>(zero.add(-29536113.0),
300 zero.add(30329259.0),
301 zero.add(-100125.0));
302 final FieldVector3D<Binary64> velocity = new FieldVector3D<>(zero.add(-2194.0),
303 zero.add(-2141.0),
304 zero.add(-8.0));
305
306 final FieldPVCoordinates<Binary64> pv = new FieldPVCoordinates<>(position, velocity);
307 final FieldAbsolutePVCoordinates<Binary64> initAbsPV = new FieldAbsolutePVCoordinates<>(inertialFrame, initDate, pv);
308
309
310 int numberOfIntervals = 15;
311 Binary64 deltaT = finalDate.durationFrom(initDate).divide(numberOfIntervals);
312
313
314 List<FieldSpacecraftState<Binary64>> states = new ArrayList<>(numberOfIntervals + 1);
315 for (int j = 0; j <= numberOfIntervals; j++) {
316 states.add(new FieldSpacecraftState<>(initAbsPV).shiftedBy(deltaT.multiply(j)));
317 }
318
319
320 FieldSpacecraftState<Binary64> withoutOrbit;
321
322
323 final FieldTimeInterpolator<FieldSpacecraftState<Binary64>, Binary64> interpolator =
324 new FieldSpacecraftStateInterpolator<>(states.size(), inertialFrame);
325
326
327 withoutOrbit = interpolator.interpolate(states.get(10).getDate(), states);
328 Assertions.assertEquals(0.0, FieldVector3D.distance(withoutOrbit.getAbsPVA().getPosition(),
329 states.get(10).getAbsPVA().getPosition()).getReal(), 1.0e-10);
330 }
331
332
333
334
335
336
337
338
339
340 private FieldPropagator<Binary64> setUpNumericalPropagator() {
341
342
343 final FieldODEIntegrator<Binary64> integrator = setUpDefaultIntegrator();
344
345 final FieldNumericalPropagator<Binary64> propagator = new FieldNumericalPropagator<>(field, integrator);
346
347
348 propagator.setOrbitType(null);
349
350
351 final Frame itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
352 final NormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getNormalizedProvider(6, 6);
353 final HolmesFeatherstoneAttractionModel potential = new HolmesFeatherstoneAttractionModel(itrf, provider);
354
355 propagator.addForceModel(potential);
356 propagator.addForceModel(new SingleBodyAbsoluteAttraction(CelestialBodyFactory.getEarth()));
357
358
359 final FieldSpacecraftState<Binary64> initialState = new FieldSpacecraftState<>(absPV);
360
361 propagator.setInitialState(initialState);
362
363
364 propagator.setAttitudeProvider(attitudeLaw);
365
366 return propagator;
367 }
368
369
370
371
372
373
374 private FieldODEIntegrator<Binary64> setUpDefaultIntegrator() {
375 final Binary64 dP = new Binary64(1);
376 final double minStep = 0.001;
377 final double maxStep = 100;
378 final double[][] tolerances = ToleranceProvider.getDefaultToleranceProvider(dP.getReal()).getTolerances(orbit, OrbitType.CARTESIAN);
379
380 return new DormandPrince853FieldIntegrator<>(field, minStep, maxStep, tolerances[0], tolerances[1]);
381 }
382
383
384
385
386
387
388
389
390
391
392 private FieldSpacecraftStateInterpolator<Binary64>[] buildAllTypeOfInterpolator(final int interpolationPoints,
393 final Frame inertialFrame) {
394
395 final CartesianDerivativesFilter[] pvaFilters = CartesianDerivativesFilter.values();
396 final AngularDerivativesFilter[] angularFilters = AngularDerivativesFilter.values();
397
398 final int dim = pvaFilters.length;
399 @SuppressWarnings("unchecked")
400 final FieldSpacecraftStateInterpolator<Binary64>[] interpolators =
401 new FieldSpacecraftStateInterpolator[dim];
402
403 for (int i = 0; i < dim; i++) {
404 interpolators[i] =
405 new FieldSpacecraftStateInterpolator<>(interpolationPoints,
406 AbstractFieldTimeInterpolator.DEFAULT_EXTRAPOLATION_THRESHOLD_SEC,
407 inertialFrame, inertialFrame,
408 pvaFilters[i], angularFilters[i]);
409 }
410
411 return interpolators;
412 }
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427 private void checkStandardInterpolationError(int n, double expectedErrorP, double expectedErrorV,
428 double expectedErrorA, double expectedErrorM,
429 double expectedErrorQ, double expectedErrorD,
430 final FieldTimeInterpolator<FieldSpacecraftState<Binary64>, Binary64> interpolator) {
431 FieldAbsoluteDate<Binary64> centerDate = orbit.getDate().shiftedBy(100.0);
432 List<FieldSpacecraftState<Binary64>> sample = new ArrayList<>();
433 for (int i = 0; i < n; ++i) {
434 Binary64 dt = new Binary64(i * 900.0 / (n - 1));
435 FieldSpacecraftState<Binary64> state = analyticalPropagator.propagate(centerDate.shiftedBy(dt));
436 state = state.
437 addAdditionalData("quadratic", dt.multiply(dt)).
438 addAdditionalStateDerivative("quadratic-dot", dt.multiply(dt));
439 sample.add(state);
440 }
441
442 double maxErrorP = 0;
443 double maxErrorV = 0;
444 double maxErrorA = 0;
445 double maxErrorM = 0;
446 double maxErrorQ = 0;
447 double maxErrorD = 0;
448 for (double dt = 0; dt < 900.0; dt += 5) {
449 FieldSpacecraftState<Binary64> interpolated = interpolator.interpolate(centerDate.shiftedBy(dt), sample);
450 FieldSpacecraftState<Binary64> propagated = analyticalPropagator.propagate(centerDate.shiftedBy(dt));
451 FieldPVCoordinates<Binary64> dpv =
452 new FieldPVCoordinates<>(propagated.getPVCoordinates(), interpolated.getPVCoordinates());
453 maxErrorP = FastMath.max(maxErrorP, dpv.getPosition().getNorm().getReal());
454 maxErrorV = FastMath.max(maxErrorV, dpv.getVelocity().getNorm().getReal());
455 maxErrorA =
456 FastMath.max(maxErrorA,
457 FastMath.toDegrees(Rotation.distance(interpolated.getAttitude().getRotation().toRotation(),
458 propagated.getAttitude().getRotation().toRotation())));
459 maxErrorM =
460 FastMath.max(maxErrorM, FastMath.abs(interpolated.getMass().getReal() - propagated.getMass().getReal()));
461 maxErrorQ = FastMath.max(maxErrorQ,
462 FastMath.abs(interpolated.getAdditionalState("quadratic")[0].getReal() - dt * dt));
463 maxErrorD =
464 FastMath.max(maxErrorD,
465 FastMath.abs(interpolated.getAdditionalStateDerivative("quadratic-dot")[0].getReal()
466 - dt * dt));
467 }
468 Assertions.assertEquals(expectedErrorP, maxErrorP, 1.0e-3);
469 Assertions.assertEquals(expectedErrorV, maxErrorV, 1.0e-6);
470 Assertions.assertEquals(expectedErrorA, maxErrorA, 4.0e-10);
471 Assertions.assertEquals(expectedErrorM, maxErrorM, 1.0e-15);
472 Assertions.assertEquals(expectedErrorQ, maxErrorQ, 2.0e-10);
473 Assertions.assertEquals(expectedErrorD, maxErrorD, 2.0e-10);
474 }
475
476
477
478
479
480
481
482
483
484
485
486
487
488 private void checkAbsPVInterpolationError(int n, double expectedErrorP, double expectedErrorV,
489 double expectedErrorA, double expectedErrorM,
490 final FieldTimeInterpolator<FieldSpacecraftState<Binary64>, Binary64> interpolator) {
491 FieldAbsoluteDate<Binary64> centerDate = absPV.getDate().shiftedBy(100.0);
492 List<FieldSpacecraftState<Binary64>> sample = new ArrayList<>();
493 for (int i = 0; i < n; ++i) {
494 Binary64 dt = new Binary64(i * 900.0 / (n - 1));
495 FieldSpacecraftState<Binary64> state = absPVPropagator.propagate(centerDate.shiftedBy(dt));
496 sample.add(state);
497 }
498
499 double maxErrorP = 0;
500 double maxErrorV = 0;
501 double maxErrorA = 0;
502 double maxErrorM = 0;
503 for (double dt = 0; dt < 900.0; dt += 5) {
504 FieldSpacecraftState<Binary64> interpolated = interpolator.interpolate(centerDate.shiftedBy(dt), sample);
505 FieldSpacecraftState<Binary64> propagated = absPVPropagator.propagate(centerDate.shiftedBy(dt));
506 FieldPVCoordinates<Binary64> dpv =
507 new FieldPVCoordinates<>(propagated.getPVCoordinates(), interpolated.getPVCoordinates());
508 maxErrorP = FastMath.max(maxErrorP, dpv.getPosition().getNorm().getReal());
509 maxErrorV = FastMath.max(maxErrorV, dpv.getVelocity().getNorm().getReal());
510 maxErrorA =
511 FastMath.max(maxErrorA,
512 FastMath.toDegrees(Rotation.distance(interpolated.getAttitude().getRotation().toRotation(),
513 propagated.getAttitude().getRotation().toRotation())));
514 maxErrorM =
515 FastMath.max(maxErrorM, FastMath.abs(interpolated.getMass().getReal() - propagated.getMass().getReal()));
516 }
517 Assertions.assertEquals(expectedErrorP, maxErrorP, 1.0e-3);
518 Assertions.assertEquals(expectedErrorV, maxErrorV, 1.0e-6);
519 Assertions.assertEquals(expectedErrorA, maxErrorA, 4.0e-10);
520 Assertions.assertEquals(expectedErrorM, maxErrorM, 1.0e-15);
521 }
522
523 @Test
524 void testErrorThrownWhenInterpolatingWithNonFieldDateAndEmptySample() {
525
526 final FieldTimeInterpolator<FieldSpacecraftState<Binary64>, Binary64> interpolator =
527 new FieldSpacecraftStateInterpolator<>(FramesFactory.getEME2000());
528
529 final List<FieldSpacecraftState<Binary64>> states = new ArrayList<>();
530
531
532 OrekitIllegalArgumentException thrown = Assertions.assertThrows(OrekitIllegalArgumentException.class,
533 () -> interpolator.interpolate(new AbsoluteDate(), states.stream()));
534
535 Assertions.assertEquals(OrekitMessages.NOT_ENOUGH_DATA, thrown.getSpecifier());
536 Assertions.assertEquals(0, ((Integer) thrown.getParts()[0]).intValue());
537
538 }
539
540 @Test
541 void testGetNbInterpolationsWithMultipleSubInterpolators() {
542
543
544 final Frame frame = Mockito.mock(Frame.class);
545
546 @SuppressWarnings("unchecked")
547 final FieldTimeInterpolator<FieldOrbit<Binary64>, Binary64> orbitInterpolator =
548 Mockito.mock(FieldOrbitHermiteInterpolator.class);
549 @SuppressWarnings("unchecked")
550 final FieldTimeInterpolator<FieldAbsolutePVCoordinates<Binary64>, Binary64> absPVAInterpolator =
551 Mockito.mock(FieldAbsolutePVCoordinatesHermiteInterpolator.class);
552 @SuppressWarnings("unchecked")
553 final FieldTimeInterpolator<TimeStampedField<Binary64>, Binary64> massInterpolator =
554 Mockito.mock(TimeStampedFieldHermiteInterpolator.class);
555 @SuppressWarnings("unchecked")
556 final FieldTimeInterpolator<FieldAttitude<Binary64>, Binary64> attitudeInterpolator =
557 Mockito.mock(FieldAttitudeInterpolator.class);
558 @SuppressWarnings("unchecked")
559 final FieldTimeInterpolator<TimeStampedField<Binary64>, Binary64> additionalStateInterpolator =
560 Mockito.mock(TimeStampedFieldHermiteInterpolator.class);
561
562
563 final int orbitNbInterpolationPoints = 2;
564 final int absPVANbInterpolationPoints = 3;
565 final int massNbInterpolationPoints = 4;
566 final int AttitudeNbInterpolationPoints = 5;
567 final int AdditionalStateNbInterpolationPoints = 6;
568
569 Mockito.when(orbitInterpolator.getNbInterpolationPoints()).thenReturn(orbitNbInterpolationPoints);
570 Mockito.when(absPVAInterpolator.getNbInterpolationPoints()).thenReturn(absPVANbInterpolationPoints);
571 Mockito.when(massInterpolator.getNbInterpolationPoints()).thenReturn(massNbInterpolationPoints);
572 Mockito.when(attitudeInterpolator.getNbInterpolationPoints()).thenReturn(AttitudeNbInterpolationPoints);
573 Mockito.when(additionalStateInterpolator.getNbInterpolationPoints()).thenReturn(AdditionalStateNbInterpolationPoints);
574
575 Mockito.when(orbitInterpolator.getSubInterpolators()).thenReturn(Collections.singletonList(orbitInterpolator));
576 Mockito.when(absPVAInterpolator.getSubInterpolators()).thenReturn(Collections.singletonList(absPVAInterpolator));
577 Mockito.when(massInterpolator.getSubInterpolators()).thenReturn(Collections.singletonList(massInterpolator));
578 Mockito.when(attitudeInterpolator.getSubInterpolators()).thenReturn(Collections.singletonList(attitudeInterpolator));
579 Mockito.when(additionalStateInterpolator.getSubInterpolators()).thenReturn(Collections.singletonList(additionalStateInterpolator));
580
581 final FieldSpacecraftStateInterpolator<Binary64> stateInterpolator =
582 new FieldSpacecraftStateInterpolator<>(2, 1.0e-3, frame, orbitInterpolator, absPVAInterpolator, massInterpolator,
583 attitudeInterpolator, additionalStateInterpolator);
584
585
586 final int returnedNbInterpolationPoints = stateInterpolator.getNbInterpolationPoints();
587
588
589 Assertions.assertEquals(AdditionalStateNbInterpolationPoints, returnedNbInterpolationPoints);
590 }
591
592 @Test
593 void testGetNbInterpolationsWithMultipleSubInterpolatorsDeprecated() {
594
595
596 final Frame frame = Mockito.mock(Frame.class);
597
598 @SuppressWarnings("unchecked")
599 final FieldTimeInterpolator<FieldOrbit<Binary64>, Binary64> orbitInterpolator =
600 Mockito.mock(FieldOrbitHermiteInterpolator.class);
601 @SuppressWarnings("unchecked")
602 final FieldTimeInterpolator<FieldAbsolutePVCoordinates<Binary64>, Binary64> absPVAInterpolator =
603 Mockito.mock(FieldAbsolutePVCoordinatesHermiteInterpolator.class);
604 @SuppressWarnings("unchecked")
605 final FieldTimeInterpolator<TimeStampedField<Binary64>, Binary64> massInterpolator =
606 Mockito.mock(TimeStampedFieldHermiteInterpolator.class);
607 @SuppressWarnings("unchecked")
608 final FieldTimeInterpolator<FieldAttitude<Binary64>, Binary64> attitudeInterpolator =
609 Mockito.mock(FieldAttitudeInterpolator.class);
610 @SuppressWarnings("unchecked")
611 final FieldTimeInterpolator<TimeStampedField<Binary64>, Binary64> additionalStateInterpolator =
612 Mockito.mock(TimeStampedFieldHermiteInterpolator.class);
613
614
615 final int orbitNbInterpolationPoints = 2;
616 final int absPVANbInterpolationPoints = 3;
617 final int massNbInterpolationPoints = 4;
618 final int AttitudeNbInterpolationPoints = 5;
619 final int AdditionalStateNbInterpolationPoints = 6;
620
621 Mockito.when(orbitInterpolator.getNbInterpolationPoints()).thenReturn(orbitNbInterpolationPoints);
622 Mockito.when(absPVAInterpolator.getNbInterpolationPoints()).thenReturn(absPVANbInterpolationPoints);
623 Mockito.when(massInterpolator.getNbInterpolationPoints()).thenReturn(massNbInterpolationPoints);
624 Mockito.when(attitudeInterpolator.getNbInterpolationPoints()).thenReturn(AttitudeNbInterpolationPoints);
625 Mockito.when(additionalStateInterpolator.getNbInterpolationPoints()).thenReturn(AdditionalStateNbInterpolationPoints);
626
627 Mockito.when(orbitInterpolator.getSubInterpolators()).thenReturn(Collections.singletonList(orbitInterpolator));
628 Mockito.when(absPVAInterpolator.getSubInterpolators()).thenReturn(Collections.singletonList(absPVAInterpolator));
629 Mockito.when(massInterpolator.getSubInterpolators()).thenReturn(Collections.singletonList(massInterpolator));
630 Mockito.when(attitudeInterpolator.getSubInterpolators()).thenReturn(Collections.singletonList(attitudeInterpolator));
631 Mockito.when(additionalStateInterpolator.getSubInterpolators()).thenReturn(Collections.singletonList(additionalStateInterpolator));
632
633 final FieldSpacecraftStateInterpolator<Binary64> stateInterpolator =
634 new FieldSpacecraftStateInterpolator<>(AbstractTimeInterpolator.DEFAULT_INTERPOLATION_POINTS,
635 AbstractTimeInterpolator.DEFAULT_EXTRAPOLATION_THRESHOLD_SEC,
636 frame, orbitInterpolator, absPVAInterpolator, massInterpolator,
637 attitudeInterpolator, additionalStateInterpolator);
638
639
640 final int returnedNbInterpolationPoints = stateInterpolator.getNbInterpolationPoints();
641
642
643 Assertions.assertEquals(AdditionalStateNbInterpolationPoints, returnedNbInterpolationPoints);
644 }
645
646 @Test
647 @DisplayName("test error thrown when using different state definition")
648 void testErrorThrownWhenUsingDifferentStateDefinition() {
649
650 final Field<Binary64> field = Binary64Field.getInstance();
651 final FieldAbsoluteDate<Binary64> interpolationDate = new FieldAbsoluteDate<>(field);
652
653 @SuppressWarnings("unchecked")
654 final FieldSpacecraftState<Binary64> orbitDefinedFieldState = Mockito.mock(FieldSpacecraftState.class);
655 final SpacecraftState orbitDefinedState = Mockito.mock(SpacecraftState.class);
656
657 Mockito.when(orbitDefinedState.isOrbitDefined()).thenReturn(true);
658 Mockito.when(orbitDefinedFieldState.toSpacecraftState()).thenReturn(orbitDefinedState);
659
660 @SuppressWarnings("unchecked")
661 final FieldSpacecraftState<Binary64> absPVDefinedFieldState = Mockito.mock(FieldSpacecraftState.class);
662 final SpacecraftState absPVDefinedState = Mockito.mock(SpacecraftState.class);
663
664 Mockito.when(absPVDefinedState.isOrbitDefined()).thenReturn(false);
665 Mockito.when(absPVDefinedFieldState.toSpacecraftState()).thenReturn(absPVDefinedState);
666
667 final List<FieldSpacecraftState<Binary64>> states = new ArrayList<>();
668 states.add(orbitDefinedFieldState);
669 states.add(absPVDefinedFieldState);
670
671
672 final Frame inertialFrameMock = Mockito.mock(Frame.class);
673 Mockito.when(inertialFrameMock.isPseudoInertial()).thenReturn(true);
674
675 final FieldTimeInterpolator<FieldSpacecraftState<Binary64>, Binary64> stateInterpolator =
676 new FieldSpacecraftStateInterpolator<>(inertialFrameMock);
677
678
679 Exception thrown = Assertions.assertThrows(OrekitIllegalArgumentException.class,
680 () -> stateInterpolator.interpolate(interpolationDate, states));
681
682 Assertions.assertEquals(
683 "one state is defined using an orbit while the other is defined using an absolute position-velocity-acceleration",
684 thrown.getMessage());
685 }
686
687 @Test
688 @DisplayName("test error thrown when using no interpolator for state")
689 void testErrorThrownWhenGivingNoInterpolatorForState() {
690
691 final Frame inertialFrameMock = Mockito.mock(Frame.class);
692 Mockito.when(inertialFrameMock.isPseudoInertial()).thenReturn(true);
693
694
695 Exception thrown = Assertions.assertThrows(OrekitIllegalArgumentException.class,
696 () -> new FieldSpacecraftStateInterpolator<>(2, 1.0e-3, inertialFrameMock,
697 null, null, null, null,
698 null));
699
700 Assertions.assertEquals("creating a spacecraft state interpolator requires at least one orbit interpolator or an "
701 + "absolute position-velocity-acceleration interpolator", thrown.getMessage());
702 }
703
704 @Test
705 @DisplayName("test error thrown when using no interpolator for state")
706 void testErrorThrownWhenGivingNoInterpolatorForStateDeprecated() {
707
708 final Frame inertialFrameMock = Mockito.mock(Frame.class);
709 Mockito.when(inertialFrameMock.isPseudoInertial()).thenReturn(true);
710
711
712 Exception thrown = Assertions.assertThrows(OrekitIllegalArgumentException.class,
713 () -> new FieldSpacecraftStateInterpolator<>(AbstractTimeInterpolator.DEFAULT_INTERPOLATION_POINTS,
714 AbstractTimeInterpolator.DEFAULT_EXTRAPOLATION_THRESHOLD_SEC,
715 inertialFrameMock,
716 null, null, null, null,
717 null));
718
719 Assertions.assertEquals("creating a spacecraft state interpolator requires at least one orbit interpolator or an "
720 + "absolute position-velocity-acceleration interpolator", thrown.getMessage());
721 }
722
723 @Test
724 @DisplayName("test error thrown when giving empty sample")
725 void testErrorThrownWhenGivingEmptySample() {
726
727
728 @SuppressWarnings("unchecked")
729 final FieldAbsoluteDate<Binary64> interpolationDate = Mockito.mock(FieldAbsoluteDate.class);
730
731 final Frame inertialFrame = FramesFactory.getEME2000();
732
733 final List<FieldSpacecraftState<Binary64>> states = new ArrayList<>();
734
735
736 @SuppressWarnings("unchecked")
737 final FieldTimeInterpolator<FieldOrbit<Binary64>, Binary64> orbitInterpolatorMock =
738 Mockito.mock(FieldTimeInterpolator.class);
739
740 final FieldTimeInterpolator<FieldSpacecraftState<Binary64>, Binary64> interpolator =
741 new FieldSpacecraftStateInterpolator<>(2, 1.0e-3, inertialFrame, orbitInterpolatorMock, null, null, null, null);
742
743
744 OrekitIllegalArgumentException thrown = Assertions.assertThrows(OrekitIllegalArgumentException.class, () ->
745 interpolator.interpolate(interpolationDate, states));
746
747 Assertions.assertEquals(OrekitMessages.NOT_ENOUGH_DATA, thrown.getSpecifier());
748 Assertions.assertEquals(0, ((Integer) thrown.getParts()[0]).intValue());
749
750 }
751
752 @Test
753 @DisplayName("test error thrown when giving empty sample")
754 void testErrorThrownWhenGivingEmptySampleDeprecated() {
755
756
757 @SuppressWarnings("unchecked")
758 final FieldAbsoluteDate<Binary64> interpolationDate = Mockito.mock(FieldAbsoluteDate.class);
759
760 final Frame inertialFrame = FramesFactory.getEME2000();
761
762 final List<FieldSpacecraftState<Binary64>> states = new ArrayList<>();
763
764
765 @SuppressWarnings("unchecked")
766 final FieldTimeInterpolator<FieldOrbit<Binary64>, Binary64> orbitInterpolatorMock =
767 Mockito.mock(FieldTimeInterpolator.class);
768
769 final FieldTimeInterpolator<FieldSpacecraftState<Binary64>, Binary64> interpolator =
770 new FieldSpacecraftStateInterpolator<>(AbstractTimeInterpolator.DEFAULT_INTERPOLATION_POINTS,
771 AbstractTimeInterpolator.DEFAULT_EXTRAPOLATION_THRESHOLD_SEC,
772 inertialFrame, orbitInterpolatorMock,
773 null, null, null, null);
774
775
776 OrekitIllegalArgumentException thrown = Assertions.assertThrows(OrekitIllegalArgumentException.class, () ->
777 interpolator.interpolate(interpolationDate, states));
778
779 Assertions.assertEquals(OrekitMessages.NOT_ENOUGH_DATA, thrown.getSpecifier());
780 Assertions.assertEquals(0, ((Integer) thrown.getParts()[0]).intValue());
781
782 }
783
784 @Test
785 void testFieldSpacecraftStateInterpolatorCreation() {
786
787 final Frame inertialFrameMock = Mockito.mock(Frame.class);
788 Mockito.when(inertialFrameMock.isPseudoInertial()).thenReturn(true);
789
790 @SuppressWarnings("unchecked")
791 final FieldTimeInterpolator<FieldOrbit<Binary64>, Binary64> orbitInterpolatorMock =
792 Mockito.mock(FieldTimeInterpolator.class);
793
794 @SuppressWarnings("unchecked")
795 final FieldTimeInterpolator<FieldAbsolutePVCoordinates<Binary64>, Binary64> absPVInterpolatorMock =
796 Mockito.mock(FieldTimeInterpolator.class);
797
798 @SuppressWarnings("unchecked")
799 final FieldTimeInterpolator<TimeStampedField<Binary64>, Binary64> massInterpolatorMock =
800 Mockito.mock(FieldTimeInterpolator.class);
801
802 @SuppressWarnings("unchecked")
803 final FieldTimeInterpolator<FieldAttitude<Binary64>, Binary64> attitudeInterpolatorMock =
804 Mockito.mock(FieldTimeInterpolator.class);
805
806 @SuppressWarnings("unchecked")
807 final FieldTimeInterpolator<TimeStampedField<Binary64>, Binary64> additionalInterpolatorMock =
808 Mockito.mock(FieldTimeInterpolator.class);
809
810
811 final FieldSpacecraftStateInterpolator<Binary64> interpolator =
812 new FieldSpacecraftStateInterpolator<>(2, 1.0e-3, inertialFrameMock, orbitInterpolatorMock, absPVInterpolatorMock,
813 massInterpolatorMock, attitudeInterpolatorMock,
814 additionalInterpolatorMock);
815
816
817 Assertions.assertEquals(inertialFrameMock, interpolator.getOutputFrame());
818 Assertions.assertEquals(orbitInterpolatorMock, interpolator.getOrbitInterpolator().get());
819 Assertions.assertEquals(absPVInterpolatorMock, interpolator.getAbsPVAInterpolator().get());
820 Assertions.assertEquals(massInterpolatorMock, interpolator.getMassInterpolator().get());
821 Assertions.assertEquals(attitudeInterpolatorMock, interpolator.getAttitudeInterpolator().get());
822 Assertions.assertEquals(additionalInterpolatorMock, interpolator.getAdditionalStateInterpolator().get());
823
824 }
825
826 @Test
827 void testFieldSpacecraftStateInterpolatorCreationDeprecated() {
828
829 final Frame inertialFrameMock = Mockito.mock(Frame.class);
830 Mockito.when(inertialFrameMock.isPseudoInertial()).thenReturn(true);
831
832 @SuppressWarnings("unchecked")
833 final FieldTimeInterpolator<FieldOrbit<Binary64>, Binary64> orbitInterpolatorMock =
834 Mockito.mock(FieldTimeInterpolator.class);
835
836 @SuppressWarnings("unchecked")
837 final FieldTimeInterpolator<FieldAbsolutePVCoordinates<Binary64>, Binary64> absPVInterpolatorMock =
838 Mockito.mock(FieldTimeInterpolator.class);
839
840 @SuppressWarnings("unchecked")
841 final FieldTimeInterpolator<TimeStampedField<Binary64>, Binary64> massInterpolatorMock =
842 Mockito.mock(FieldTimeInterpolator.class);
843
844 @SuppressWarnings("unchecked")
845 final FieldTimeInterpolator<FieldAttitude<Binary64>, Binary64> attitudeInterpolatorMock =
846 Mockito.mock(FieldTimeInterpolator.class);
847
848 @SuppressWarnings("unchecked")
849 final FieldTimeInterpolator<TimeStampedField<Binary64>, Binary64> additionalInterpolatorMock =
850 Mockito.mock(FieldTimeInterpolator.class);
851
852
853 final FieldSpacecraftStateInterpolator<Binary64> interpolator =
854 new FieldSpacecraftStateInterpolator<>(AbstractTimeInterpolator.DEFAULT_INTERPOLATION_POINTS,
855 AbstractTimeInterpolator.DEFAULT_EXTRAPOLATION_THRESHOLD_SEC,
856 inertialFrameMock, orbitInterpolatorMock, absPVInterpolatorMock,
857 massInterpolatorMock, attitudeInterpolatorMock,
858 additionalInterpolatorMock);
859
860
861 Assertions.assertEquals(inertialFrameMock, interpolator.getOutputFrame());
862 Assertions.assertEquals(orbitInterpolatorMock, interpolator.getOrbitInterpolator().get());
863 Assertions.assertEquals(absPVInterpolatorMock, interpolator.getAbsPVAInterpolator().get());
864 Assertions.assertEquals(massInterpolatorMock, interpolator.getMassInterpolator().get());
865 Assertions.assertEquals(attitudeInterpolatorMock, interpolator.getAttitudeInterpolator().get());
866 Assertions.assertEquals(additionalInterpolatorMock, interpolator.getAdditionalStateInterpolator().get());
867
868 }
869
870 @Test
871 @DisplayName("Test error thrown when sub interpolator is not present")
872 void testErrorThrownWhenSubInterpolatorIsNotPresent() {
873
874 final FakeFieldStateInterpolator fakeStateInterpolator = new FakeFieldStateInterpolator();
875
876
877 Assertions.assertThrows(OrekitInternalError.class, fakeStateInterpolator::getNbInterpolationPoints);
878 }
879
880 @Test
881 @DisplayName("Test does not throw error when checking interpolator compatibility")
882 void testDoesNotThrowWhenCheckingInterpolatorCompatibility() {
883
884 final FakeFieldStateInterpolator fakeStateInterpolator = new FakeFieldStateInterpolator();
885
886
887 Assertions.assertThrows(OrekitInternalError.class, fakeStateInterpolator::getNbInterpolationPoints);
888 }
889
890 private static class FakeFieldStateInterpolator extends AbstractFieldTimeInterpolator<FieldSpacecraftState<Binary64>,Binary64> {
891
892 public FakeFieldStateInterpolator() {
893 super(AbstractTimeInterpolator.DEFAULT_INTERPOLATION_POINTS,
894 AbstractTimeInterpolator.DEFAULT_EXTRAPOLATION_THRESHOLD_SEC);
895 }
896
897 @Override
898 public List<FieldTimeInterpolator<? extends FieldTimeStamped<Binary64>, Binary64>> getSubInterpolators() {
899 return Collections.emptyList();
900 }
901
902 @Override
903 protected FieldSpacecraftState<Binary64> interpolate(AbstractFieldTimeInterpolator<FieldSpacecraftState<Binary64>, Binary64>.InterpolationData interpolationData) {
904 return null;
905 }
906 }
907 }