1   /* Copyright 2002-2025 CS GROUP
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.propagation;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.Field;
21  import org.hipparchus.analysis.polynomials.PolynomialFunction;
22  import org.hipparchus.complex.Complex;
23  import org.hipparchus.complex.ComplexField;
24  import org.hipparchus.exception.LocalizedCoreFormats;
25  import org.hipparchus.exception.MathIllegalStateException;
26  import org.hipparchus.geometry.euclidean.threed.FieldRotation;
27  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
28  import org.hipparchus.geometry.euclidean.threed.Rotation;
29  import org.hipparchus.geometry.euclidean.threed.Vector3D;
30  import org.hipparchus.ode.FieldODEIntegrator;
31  import org.hipparchus.ode.events.Action;
32  import org.hipparchus.ode.nonstiff.DormandPrince853FieldIntegrator;
33  import org.hipparchus.util.Binary64;
34  import org.hipparchus.util.Binary64Field;
35  import org.hipparchus.util.FastMath;
36  import org.hipparchus.util.MathArrays;
37  import org.junit.jupiter.api.Assertions;
38  import org.junit.jupiter.api.BeforeEach;
39  import org.junit.jupiter.api.Test;
40  import org.orekit.TestUtils;
41  import org.orekit.Utils;
42  import org.orekit.attitudes.BodyCenterPointing;
43  import org.orekit.attitudes.FieldAttitude;
44  import org.orekit.bodies.OneAxisEllipsoid;
45  import org.orekit.errors.OrekitException;
46  import org.orekit.errors.OrekitIllegalArgumentException;
47  import org.orekit.errors.OrekitMessages;
48  import org.orekit.frames.FieldStaticTransform;
49  import org.orekit.frames.FieldTransform;
50  import org.orekit.frames.FramesFactory;
51  import org.orekit.frames.Transform;
52  import org.orekit.orbits.FieldCartesianOrbit;
53  import org.orekit.orbits.FieldKeplerianOrbit;
54  import org.orekit.orbits.FieldOrbit;
55  import org.orekit.orbits.KeplerianOrbit;
56  import org.orekit.orbits.Orbit;
57  import org.orekit.orbits.PositionAngleType;
58  import org.orekit.propagation.analytical.FieldEcksteinHechlerPropagator;
59  import org.orekit.propagation.analytical.FieldKeplerianPropagator;
60  import org.orekit.propagation.events.FieldDateDetector;
61  import org.orekit.propagation.events.FieldEventDetector;
62  import org.orekit.propagation.events.handlers.FieldEventHandler;
63  import org.orekit.propagation.numerical.FieldNumericalPropagator;
64  import org.orekit.time.AbsoluteDate;
65  import org.orekit.time.DateComponents;
66  import org.orekit.time.FieldAbsoluteDate;
67  import org.orekit.time.TimeComponents;
68  import org.orekit.time.TimeScalesFactory;
69  import org.orekit.utils.*;
70  
71  
72  class FieldSpacecraftStateTest {
73  
74      @Test
75      public void testToFieldSpacecraftStateWithStringAdditionalData() {
76          final Binary64Field field = Binary64Field.getInstance();
77          final SpacecraftState state = new SpacecraftState(TestUtils.getDefaultOrbit(AbsoluteDate.ARBITRARY_EPOCH)).addAdditionalData("test-string", "hello");
78          final FieldSpacecraftState<Binary64> fieldState = new FieldSpacecraftState<>(field, state);
79          Assertions.assertTrue(fieldState.hasAdditionalData("test-string"));
80          Assertions.assertEquals("hello", fieldState.getAdditionalData("test-string"));
81      }
82  
83      @Test
84      void testWithAttitudeAndOrbit() {
85          // GIVEN
86          final SpacecraftState state = new SpacecraftState(TestUtils.getDefaultOrbit(AbsoluteDate.ARBITRARY_EPOCH));
87          final Binary64Field field = Binary64Field.getInstance();
88          final FieldSpacecraftState<Binary64> fieldState = new FieldSpacecraftState<>(field, state);
89          final FieldAttitude<Binary64> attitude = new FieldAttitude<>(fieldState.getDate(), state.getFrame(),
90                  new FieldAngularCoordinates<>(FieldRotation.getIdentity(field), FieldVector3D.getMinusI(field)));
91          // WHEN
92          final FieldSpacecraftState<Binary64> fieldStateWithAttitude = fieldState.withAttitude(attitude);
93          // THEN
94          Assertions.assertEquals(attitude, fieldStateWithAttitude.getAttitude());
95          Assertions.assertEquals(fieldState.getMass(), fieldStateWithAttitude.getMass());
96          Assertions.assertEquals(fieldState.getOrbit(), fieldStateWithAttitude.getOrbit());
97      }
98  
99      @Test
100     void testWithMassAndOrbit() {
101         // GIVEN
102         final SpacecraftState state = new SpacecraftState(TestUtils.getDefaultOrbit(AbsoluteDate.ARBITRARY_EPOCH));
103         final Binary64Field field = Binary64Field.getInstance();
104         final FieldSpacecraftState<Binary64> fieldState = new FieldSpacecraftState<>(field, state);
105         final Binary64 expectedMass = new Binary64(123);
106         // WHEN
107         final FieldSpacecraftState<Binary64> fieldStateWithMass = fieldState.withMass(expectedMass);
108         // THEN
109         Assertions.assertEquals(expectedMass, fieldStateWithMass.getMass());
110         Assertions.assertEquals(fieldState.getAttitude(), fieldStateWithMass.getAttitude());
111         Assertions.assertEquals(fieldState.getOrbit(), fieldStateWithMass.getOrbit());
112     }
113 
114     @Test
115     void testWithAttitudeAndAbsolutePV() {
116         // GIVEN
117         final AbsolutePVCoordinates absolutePVCoordinates = new AbsolutePVCoordinates(FramesFactory.getEME2000(),
118                 AbsoluteDate.ARBITRARY_EPOCH, new PVCoordinates());
119         final SpacecraftState state = new SpacecraftState(absolutePVCoordinates);
120         final Binary64Field field = Binary64Field.getInstance();
121         final FieldSpacecraftState<Binary64> fieldState = new FieldSpacecraftState<>(field, state);
122         final FieldAttitude<Binary64> attitude = new FieldAttitude<>(fieldState.getDate(), state.getFrame(),
123                 new FieldAngularCoordinates<>(FieldRotation.getIdentity(field), FieldVector3D.getMinusI(field)));
124         // WHEN
125         final FieldSpacecraftState<Binary64> fieldStateWithAttitude = fieldState.withAttitude(attitude);
126         // THEN
127         Assertions.assertEquals(attitude, fieldStateWithAttitude.getAttitude());
128         Assertions.assertEquals(fieldState.getMass(), fieldStateWithAttitude.getMass());
129         Assertions.assertEquals(fieldState.getAbsPVA(), fieldStateWithAttitude.getAbsPVA());
130     }
131 
132     @Test
133     void testWithMassAndAbsolutePV() {
134         // GIVEN
135         final AbsolutePVCoordinates absolutePVCoordinates = new AbsolutePVCoordinates(FramesFactory.getEME2000(),
136                 AbsoluteDate.ARBITRARY_EPOCH, new PVCoordinates());
137         final SpacecraftState state = new SpacecraftState(absolutePVCoordinates);
138         final Binary64Field field = Binary64Field.getInstance();
139         final FieldSpacecraftState<Binary64> fieldState = new FieldSpacecraftState<>(field, state);
140         final Binary64 expectedMass = new Binary64(123);
141         // WHEN
142         final FieldSpacecraftState<Binary64> fieldStateWithMass = fieldState.withMass(expectedMass);
143         // THEN
144         Assertions.assertEquals(expectedMass, fieldStateWithMass.getMass());
145         Assertions.assertEquals(fieldState.getAttitude(), fieldStateWithMass.getAttitude());
146         Assertions.assertEquals(fieldState.getAbsPVA(), fieldStateWithMass.getAbsPVA());
147     }
148 
149     @Test
150     void testFieldVSReal() {
151         doTestFieldVsReal(Binary64Field.getInstance());
152     }
153 
154     @Test
155     void testShiftVsEcksteinHechlerError() {
156         doTestShiftVsEcksteinHechlerError(Binary64Field.getInstance());
157     }
158 
159     @Test
160     void testDatesConsistency() {
161         Assertions.assertThrows(IllegalArgumentException.class, () -> doTestDatesConsistency(Binary64Field.getInstance()));
162     }
163 
164     @Test
165     void testDateConsistencyClose() {
166         doTestDateConsistencyClose(Binary64Field.getInstance());
167     }
168 
169     @Test
170     void testFramesConsistency() {
171         Assertions.assertThrows(IllegalArgumentException.class, () -> doTestFramesConsistency(Binary64Field.getInstance()));
172     }
173 
174     @Test
175     void testGetAdditionalStateBadType() {
176         doTestGetAdditionalStateBadType(Binary64Field.getInstance());
177     }
178 
179     @Test
180     void testTransform() {
181         doTestTransform(Binary64Field.getInstance());
182     }
183 
184     @Test
185     void testAdditionalStates() {
186         doTestAdditionalStates(Binary64Field.getInstance());
187     }
188 
189     @Test
190     void testAdditionalStatesDerivatives() {
191         doTestAdditionalStatesDerivatives(Binary64Field.getInstance());
192     }
193 
194     @Test
195     void testFieldVSRealAbsPV() {
196         doTestFieldVsRealAbsPV(Binary64Field.getInstance());
197     }
198 
199     @Test
200     void testDateConsistencyCloseAbsPV() {
201         doTestDateConsistencyCloseAbsPV(Binary64Field.getInstance());
202     }
203 
204     @Test
205     void testFramesConsistencyAbsPV() {
206         Assertions.assertThrows(IllegalArgumentException.class,
207                                 () -> doTestFramesConsistencyAbsPV(Binary64Field.getInstance()));
208     }
209 
210     @Test
211     void testAdditionalStatesAbsPV() {
212         doTestAdditionalStatesAbsPV(Binary64Field.getInstance());
213     }
214 
215     @Test
216     void testAdditionalStatesDerivativesAbsPV() {
217         doTestAdditionalStatesDerivativesAbsPV(Binary64Field.getInstance());
218     }
219 
220     @Test
221     void testResetOnEventAnalytical() {
222         doTestAdditionalTestResetOnEventAnalytical(Binary64Field.getInstance());
223     }
224 
225     @Test
226     void testResetOnEventNumerical() {
227         doTestAdditionalTestResetOnEventNumerical(Binary64Field.getInstance());
228     }
229 
230     @Test
231     void testShiftAdditionalDerivativesDouble() {
232         doTestShiftAdditionalDerivativesDouble(Binary64Field.getInstance());
233     }
234 
235     @Test
236     void testShiftAdditionalDerivativesField() {
237         doTestShiftAdditionalDerivativesField(Binary64Field.getInstance());
238     }
239 
240     @Test
241     void testToTransform() {
242         // GIVEN
243         final ComplexField field = ComplexField.getInstance();
244         final FieldOrbit<Complex> orbit = new FieldCartesianOrbit<>(field, rOrbit);
245         final TimeStampedAngularCoordinates angularCoordinates = new TimeStampedAngularCoordinates(
246                 orbit.getDate().toAbsoluteDate(), Rotation.IDENTITY, Vector3D.ZERO, Vector3D.ZERO);
247         final FieldAttitude<Complex> attitude = new FieldAttitude<>(orbit.getFrame(),
248                 new TimeStampedFieldAngularCoordinates<>(field, angularCoordinates));
249         final FieldSpacecraftState<Complex> state = new FieldSpacecraftState<>(orbit, attitude);
250         // WHEN
251         final FieldTransform<Complex> fieldTransform = state.toTransform();
252         // THEN
253         final Transform expectedTransform = state.toSpacecraftState().toTransform();
254         Assertions.assertEquals(expectedTransform.getDate(), fieldTransform.getDate());
255         final double tolerance = 1e-10;
256         Assertions.assertEquals(expectedTransform.getTranslation().getX(),
257                 fieldTransform.getTranslation().getX().getReal(), tolerance);
258         Assertions.assertEquals(expectedTransform.getTranslation().getY(),
259                 fieldTransform.getTranslation().getY().getReal(), tolerance);
260         Assertions.assertEquals(expectedTransform.getTranslation().getZ(),
261                 fieldTransform.getTranslation().getZ().getReal(), tolerance);
262         Assertions.assertEquals(0., Rotation.distance(expectedTransform.getRotation(),
263                 fieldTransform.getRotation().toRotation()));
264     }
265     
266     @Test
267     void testToStaticTransform() {
268         // GIVEN
269         final ComplexField field = ComplexField.getInstance();
270         final FieldOrbit<Complex> orbit = new FieldCartesianOrbit<>(field, rOrbit);
271         final TimeStampedAngularCoordinates angularCoordinates = new TimeStampedAngularCoordinates(
272                 orbit.getDate().toAbsoluteDate(), Rotation.IDENTITY, Vector3D.ZERO, Vector3D.ZERO);
273         final FieldAttitude<Complex> attitude = new FieldAttitude<>(orbit.getFrame(),
274                 new TimeStampedFieldAngularCoordinates<>(field, angularCoordinates));
275         final FieldSpacecraftState<Complex> state = new FieldSpacecraftState<>(orbit, attitude);
276         // WHEN
277         final FieldStaticTransform<Complex> actualStaticTransform = state.toStaticTransform();
278         // THEN
279         final FieldStaticTransform<Complex> expectedStaticTransform = state.toTransform();
280         Assertions.assertEquals(expectedStaticTransform.getDate(), actualStaticTransform.getDate());
281         final double tolerance = 1e-10;
282         Assertions.assertEquals(expectedStaticTransform.getTranslation().getX().getReal(),
283                 actualStaticTransform.getTranslation().getX().getReal(), tolerance);
284         Assertions.assertEquals(expectedStaticTransform.getTranslation().getY().getReal(),
285                 actualStaticTransform.getTranslation().getY().getReal(), tolerance);
286         Assertions.assertEquals(expectedStaticTransform.getTranslation().getZ().getReal(),
287                 actualStaticTransform.getTranslation().getZ().getReal(), tolerance);
288         Assertions.assertEquals(0., Rotation.distance(expectedStaticTransform.getRotation().toRotation(),
289                 actualStaticTransform.getRotation().toRotation()));
290     }
291 
292     private <T extends CalculusFieldElement<T>> void doTestFieldVsReal(final Field<T> field) {
293         T zero = field.getZero();
294 
295         double mu = 3.9860047e14;
296 
297         T a_f     = zero.add(150000);
298         T e_f     = zero.add(     0);
299         T i_f     = zero.add(     0);
300         T pa_f    = zero.add(     0);
301         T raan_f  = zero.add(     0);
302         T m_f     = zero.add(     0);
303 
304         FieldAbsoluteDate<T> t_f = new FieldAbsoluteDate<>(field);
305 
306         double a_r = a_f.getReal();
307         double e_r = e_f.getReal();
308         double i_r = i_f.getReal();
309         double pa_r = pa_f.getReal();
310         double raan_r = raan_f.getReal();
311         double m_r = m_f.getReal();
312 
313         AbsoluteDate t_r = t_f.toAbsoluteDate();
314 
315 
316         KeplerianOrbit      kep_r = new KeplerianOrbit(a_r, e_r, i_r, pa_r, raan_r, m_r, PositionAngleType.ECCENTRIC, FramesFactory.getEME2000(), t_r, mu);
317         FieldKeplerianOrbit<T> kep_f = new FieldKeplerianOrbit<>(a_f, e_f, i_f, pa_f, raan_f, m_f, PositionAngleType.ECCENTRIC, FramesFactory.getEME2000(), t_f, zero.add(mu));
318 
319         SpacecraftState ScS_r = new SpacecraftState(kep_r);
320         FieldSpacecraftState<T> ScS_f = new FieldSpacecraftState<>(kep_f);
321 
322         for (double dt = 0; dt < 500; dt+=100){
323             SpacecraftState control_r = ScS_r.shiftedBy(dt);
324             FieldSpacecraftState<T> control_f = ScS_f.shiftedBy(zero.add(dt));
325 
326 
327             Assertions.assertEquals(control_r.getOrbit().getA(), control_f.getOrbit().getA().getReal(), 1e-10);
328             Assertions.assertEquals(control_r.getOrbit().getE(), control_f.getOrbit().getE().getReal(), 1e-10);
329             Assertions.assertEquals(control_r.getOrbit().getEquinoctialEx(), control_f.getOrbit().getEquinoctialEx().getReal(), 1e-10);
330             Assertions.assertEquals(control_r.getOrbit().getEquinoctialEy(), control_f.getOrbit().getEquinoctialEy().getReal(), 1e-10);
331             Assertions.assertEquals(control_r.getPosition().getX(), control_f.getPVCoordinates().toPVCoordinates().getPosition().getX(), 1e-10);
332             Assertions.assertEquals(control_r.getPosition().getY(), control_f.getPVCoordinates().toPVCoordinates().getPosition().getY(), 1e-10);
333             Assertions.assertEquals(control_r.getPosition().getZ(), control_f.getPVCoordinates().toPVCoordinates().getPosition().getZ(), 1e-10);
334             Assertions.assertEquals(control_r.getPVCoordinates().getVelocity().getX(), control_f.getPVCoordinates().toPVCoordinates().getVelocity().getX(), 1e-10);
335             Assertions.assertEquals(control_r.getPVCoordinates().getVelocity().getY(), control_f.getPVCoordinates().toPVCoordinates().getVelocity().getY(), 1e-10);
336             Assertions.assertEquals(control_r.getPVCoordinates().getVelocity().getZ(), control_f.getPVCoordinates().toPVCoordinates().getVelocity().getZ(), 1e-10);
337             Assertions.assertEquals(control_r.getPVCoordinates().getAcceleration().getX(), control_f.getPVCoordinates().toPVCoordinates().getAcceleration().getX(), 1e-10);
338             Assertions.assertEquals(control_r.getPVCoordinates().getAcceleration().getY(), control_f.getPVCoordinates().toPVCoordinates().getAcceleration().getY(), 1e-10);
339             Assertions.assertEquals(control_r.getPVCoordinates().getAcceleration().getZ(), control_f.getPVCoordinates().toPVCoordinates().getAcceleration().getZ(), 1e-10);
340             Assertions.assertEquals(control_r.getAttitude().getOrientation().getRotation().getQ0(), control_f.getAttitude().getOrientation().getRotation().getQ0().getReal(), 1e-10);
341             Assertions.assertEquals(control_r.getAttitude().getOrientation().getRotation().getQ1(), control_f.getAttitude().getOrientation().getRotation().getQ1().getReal(), 1e-10);
342             Assertions.assertEquals(control_r.getAttitude().getOrientation().getRotation().getQ2(), control_f.getAttitude().getOrientation().getRotation().getQ2().getReal(), 1e-10);
343             Assertions.assertEquals(control_r.getAttitude().getOrientation().getRotation().getQ3(), control_f.getAttitude().getOrientation().getRotation().getQ3().getReal(), 1e-10);
344 
345             Assertions.assertEquals(control_r.getAttitude().getSpin().getAlpha(), control_f.getAttitude().getSpin().getAlpha().getReal(), 1e-10);
346             Assertions.assertEquals(control_r.getAttitude().getSpin().getDelta(), control_f.getAttitude().getSpin().getDelta().getReal(), 1e-10);
347             Assertions.assertEquals(control_r.getAttitude().getSpin().getNorm(), control_f.getAttitude().getSpin().getNorm().getReal(), 1e-10);
348 
349             Assertions.assertEquals(control_r.getAttitude().getReferenceFrame().isPseudoInertial(), control_f.getAttitude().getReferenceFrame().isPseudoInertial());
350             Assertions.assertEquals(control_r.getAttitude().getDate().durationFrom(AbsoluteDate.J2000_EPOCH), control_f.getAttitude().getDate().durationFrom(AbsoluteDate.J2000_EPOCH).getReal(), 1e-10);
351 
352 
353         }
354 
355     }
356 
357     private <T extends CalculusFieldElement<T>>  void doTestShiftVsEcksteinHechlerError(final Field<T> field)
358         {
359 
360         T zero = field.getZero();
361         T mass = zero.add(2500.);
362         T a = zero.add(rOrbit.getA());
363         T e = zero.add(rOrbit.getE());
364         T i = zero.add(rOrbit.getI());
365         T pa = zero.add(1.9674147913622104);
366         T raan = zero.add(FastMath.toRadians(261));
367         T lv = zero.add(0);
368         final double ae  = 6.378137e6;
369         final double c20 = -1.08263e-3;
370         final double c30 =  2.54e-6;
371         final double c40 =  1.62e-6;
372         final double c50 =  2.3e-7;
373         final double c60 =  -5.5e-7;
374 
375 
376         // polynomial models for interpolation error in position, velocity, acceleration and attitude
377         // these models grow as follows
378         //   interpolation time (s)    position error (m)   velocity error (m/s)   acceleration error (m/s²)  attitude error (°)
379         //           60                        2                    0.07                  0.002               0.00002
380         //          120                       12                    0.3                   0.005               0.00009
381         //          300                      170                    1.6                   0.012               0.0009
382         //          600                     1200                    5.7                   0.024               0.006
383         //          900                     3600                   10.6                   0.034               0.02
384         // the expected maximum residuals with respect to these models are about 0.4m, 0.5mm/s, 8μm/s² and 3e-6°
385         PolynomialFunction pModel = new PolynomialFunction(new double[] {
386             1.5664070631933846e-01,  7.5504722733047560e-03, -8.2460562451009510e-05,
387             6.9546332080305580e-06, -1.7045365367533077e-09, -4.2187860791066264e-13
388         });
389         PolynomialFunction vModel = new PolynomialFunction(new double[] {
390            -3.5472364019908720e-04,  1.6568103861124980e-05,  1.9637913327830596e-05,
391            -3.4248792843039766e-09, -5.6565135131014254e-12,  1.4730170946808630e-15
392         });
393         PolynomialFunction aModel = new PolynomialFunction(new double[] {
394             3.0731707577766896e-06,  3.9770746399850350e-05,  1.9779039254538660e-09,
395             8.0263328220724900e-12, -1.5600835252366078e-14,  1.1785257001549687e-18
396         });
397         PolynomialFunction rModel = new PolynomialFunction(new double[] {
398            -2.7689062063188115e-06,  1.7406542538258334e-07,  2.5109795349592287e-09,
399             2.0399322661074575e-11,  9.9126348912426750e-15, -3.5015638905729510e-18
400         });
401 
402         FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, new DateComponents(2004, 01, 01),
403                                                             TimeComponents.H00,
404                                                             TimeScalesFactory.getUTC());
405 
406         FieldKeplerianOrbit<T> orbit = new FieldKeplerianOrbit<>(a, e, i, pa, raan, lv, PositionAngleType.TRUE,
407                                                                  FramesFactory.getEME2000(), date, zero.add(mu));
408 
409         BodyCenterPointing attitudeLaw = new BodyCenterPointing(orbit.getFrame(), earth);
410 
411         FieldPropagator<T> propagator =
412             new FieldEcksteinHechlerPropagator<>(orbit, attitudeLaw, mass,
413                                                  ae, zero.add(mu), c20, c30, c40, c50, c60);
414 
415         FieldAbsoluteDate<T> centerDate = orbit.getDate().shiftedBy(100.0);
416 
417         FieldSpacecraftState<T> centerState = propagator.propagate(centerDate);
418 
419         double maxResidualP = 0;
420         double maxResidualV = 0;
421         double maxResidualA = 0;
422         double maxResidualR = 0;
423         for (T dt = field.getZero(); dt.getReal() < 900.0; dt = dt.add(5)) {
424 
425             FieldSpacecraftState<T> shifted = centerState.shiftedBy(dt);
426             FieldSpacecraftState<T> propagated = propagator.propagate(centerDate.shiftedBy(dt));
427             FieldPVCoordinates<T> dpv = new FieldPVCoordinates<>(propagated.getPVCoordinates(), shifted.getPVCoordinates());
428 
429 
430             double residualP = pModel.value(dt.getReal()) - dpv.getPosition().getNorm().getReal();
431             double residualV = vModel.value(dt.getReal()) - dpv.getVelocity().getNorm().getReal();
432             double residualA = aModel.value(dt.getReal()) - dpv.getAcceleration().getNorm().getReal();
433             double residualR = rModel.value(dt.getReal()) -
434                                FastMath.toDegrees(FieldRotation.distance(shifted.getAttitude().getRotation(),
435                                                                          propagated.getAttitude().getRotation()).getReal());
436             maxResidualP = FastMath.max(maxResidualP, FastMath.abs(residualP));
437             maxResidualV = FastMath.max(maxResidualV, FastMath.abs(residualV));
438             maxResidualA = FastMath.max(maxResidualA, FastMath.abs(residualA));
439             maxResidualR = FastMath.max(maxResidualR, FastMath.abs(residualR));
440 
441         }
442 
443         Assertions.assertEquals(0.40,   maxResidualP, 0.01);
444         Assertions.assertEquals(4.9e-4, maxResidualV, 1.0e-5);
445         Assertions.assertEquals(2.8e-6, maxResidualR, 1.0e-1);
446 
447     }
448 
449     private <T extends CalculusFieldElement<T>> void doTestDatesConsistency(final Field<T> field) {
450 
451         T zero = field.getZero();
452         T a = zero.add(rOrbit.getA());
453         T e = zero.add(rOrbit.getE());
454         T i = zero.add(rOrbit.getI());
455         T pa = zero.add(1.9674147913622104);
456         T raan = zero.add(FastMath.toRadians(261));
457         T lv = zero.add(0);
458 
459 
460         FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, new DateComponents(2004, 01, 01),
461                                                             TimeComponents.H00,
462                                                             TimeScalesFactory.getUTC());
463 
464         FieldKeplerianOrbit<T> orbit = new FieldKeplerianOrbit<>(a, e, i, pa, raan, lv, PositionAngleType.TRUE,
465                                                                  FramesFactory.getEME2000(), date, zero.add(mu));
466         BodyCenterPointing attitudeLaw = new BodyCenterPointing(orbit.getFrame(), earth);
467 
468         new FieldSpacecraftState<>(orbit, attitudeLaw.getAttitude(orbit.shiftedBy(zero.add(10.0)),
469                                                                   orbit.getDate().shiftedBy(10.0),
470                                                                   orbit.getFrame()));
471     }
472 
473     /**
474      * Check orbit and attitude dates can be off by a few ulps. I see this when using
475      * FixedRate attitude provider.
476      */
477     private <T extends CalculusFieldElement<T>> void doTestDateConsistencyClose(final Field<T> field) {
478 
479 
480         //setup
481         T zero = field.getZero();
482         T one  = field.getOne();
483         T a = zero.add(rOrbit.getA());
484         T e = zero.add(rOrbit.getE());
485         T i = zero.add(rOrbit.getI());
486         T pa = zero.add(1.9674147913622104);
487         T raan = zero.add(FastMath.toRadians(261));
488         T lv = zero.add(0);
489 
490         FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, new DateComponents(2004, 01, 01),
491                                                             TimeComponents.H00,
492                                                             TimeScalesFactory.getUTC());
493         FieldKeplerianOrbit<T> orbit = new FieldKeplerianOrbit<>(a, e, i, pa, raan, lv, PositionAngleType.TRUE,
494                                                                  FramesFactory.getEME2000(), date, zero.add(mu));
495 
496         FieldKeplerianOrbit<T> orbit10Shifts = orbit;
497         for (int ii = 0; ii < 10; ii++) {
498             orbit10Shifts = orbit10Shifts.shiftedBy(zero.add(0.1));
499         }
500         final FieldOrbit<T> orbit1Shift = orbit.shiftedBy(one);
501 
502         BodyCenterPointing attitudeLaw = new BodyCenterPointing(orbit.getFrame(), earth);
503 
504         FieldAttitude<T> shiftedAttitude = attitudeLaw
505                 .getAttitude(orbit1Shift, orbit1Shift.getDate(), orbit.getFrame());
506 
507         // since Orekit 13, dates are equal
508         Assertions.assertEquals(shiftedAttitude.getDate(), orbit10Shifts.getDate());
509 
510         //action + verify no exception is thrown
511         new FieldSpacecraftState<>(orbit10Shifts, shiftedAttitude);
512     }
513 
514     // 
515     private <T extends CalculusFieldElement<T>> void doTestFramesConsistency(final Field<T> field) {
516 
517         T zero = field.getZero();
518         T a = zero.add(rOrbit.getA());
519         T e = zero.add(rOrbit.getE());
520         T i = zero.add(rOrbit.getI());
521         T pa = zero.add(1.9674147913622104);
522         T raan = zero.add(FastMath.toRadians(261));
523         T lv = zero.add(0);
524 
525         FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, new DateComponents(2004, 01, 01),
526                                                             TimeComponents.H00,
527                                                             TimeScalesFactory.getUTC());
528         FieldKeplerianOrbit<T> orbit = new FieldKeplerianOrbit<>(a, e, i, pa, raan, lv, PositionAngleType.TRUE,
529                                                                  FramesFactory.getEME2000(), date, zero.add(mu));
530 
531         new FieldSpacecraftState<>(orbit,
532                             new FieldAttitude<>(orbit.getDate(),
533                                                 FramesFactory.getGCRF(),
534                                                 Rotation.IDENTITY,
535                                                 Vector3D.ZERO,
536                                                 Vector3D.ZERO,
537                                                 field));
538     }
539 
540     private <T extends CalculusFieldElement<T>> void doTestTransform(final Field<T> field) {
541 
542         T zero = field.getZero();
543         T a = zero.add(rOrbit.getA());
544         T e = zero.add(rOrbit.getE());
545         T i = zero.add(rOrbit.getI());
546         T pa = zero.add(1.9674147913622104);
547         T raan = zero.add(FastMath.toRadians(261));
548         T lv = zero.add(0);
549         T mass = zero.add(2500);
550 
551         FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, new DateComponents(2004, 01, 01),
552                         TimeComponents.H00,
553                         TimeScalesFactory.getUTC());
554 
555         FieldKeplerianOrbit<T> orbit = new FieldKeplerianOrbit<>(a, e, i, pa, raan, lv, PositionAngleType.TRUE,
556                                                                  FramesFactory.getEME2000(), date, zero.add(mu));
557 
558         BodyCenterPointing attitudeLaw = new BodyCenterPointing(orbit.getFrame(), earth);
559 
560         FieldKeplerianPropagator<T> propagator =
561                         new FieldKeplerianPropagator<>(orbit, attitudeLaw, zero.add(mu), mass);
562 
563         double maxDP = 0;
564         double maxDV = 0;
565         double maxDA = 0;
566         for (double t = 0; t < orbit.getKeplerianPeriod().getReal(); t += 60) {
567             final FieldSpacecraftState<T> state = propagator.propagate(orbit.getDate().shiftedBy(zero.add(t)));
568             final Transform transform = state.toSpacecraftState().toTransform().getInverse();
569             PVCoordinates pv = transform.transformPVCoordinates(PVCoordinates.ZERO);
570             PVCoordinates dPV = new PVCoordinates(pv, state.getPVCoordinates().toPVCoordinates());
571             Vector3D mZDirection = transform.transformVector(Vector3D.MINUS_K);
572             double alpha = Vector3D.angle(mZDirection, state.getPosition().toVector3D());
573             maxDP = FastMath.max(maxDP, dPV.getPosition().getNorm());
574             maxDV = FastMath.max(maxDV, dPV.getVelocity().getNorm());
575             maxDA = FastMath.max(maxDA, FastMath.toDegrees(alpha));
576         }
577         Assertions.assertEquals(0.0, maxDP, 1.0e-6);
578         Assertions.assertEquals(0.0, maxDV, 1.0e-9);
579         Assertions.assertEquals(0.0, maxDA, 8.1e-10);
580 
581     }
582 
583     private <T extends CalculusFieldElement<T>> void doTestAdditionalStates(final Field<T> field) {
584 
585         T zero = field.getZero();
586         T a = zero.add(rOrbit.getA());
587         T e = zero.add(rOrbit.getE());
588         T i = zero.add(rOrbit.getI());
589         T pa = zero.add(1.9674147913622104);
590         T raan = zero.add(FastMath.toRadians(261));
591         T lv = zero.add(0);
592         T mass = zero.add(2500);
593 
594         FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, new DateComponents(2004, 01, 01),
595                                                             TimeComponents.H00,
596                                                             TimeScalesFactory.getUTC());
597 
598         FieldKeplerianOrbit<T> orbit = new FieldKeplerianOrbit<>(a, e, i, pa, raan, lv, PositionAngleType.TRUE,
599                                                                  FramesFactory.getEME2000(), date, zero.add(mu));
600 
601         BodyCenterPointing attitudeLaw = new BodyCenterPointing(orbit.getFrame(), earth);
602 
603         FieldKeplerianPropagator<T> propagator =
604                         new FieldKeplerianPropagator<>(orbit, attitudeLaw, zero.add(mu), mass);
605 
606 
607 
608 
609         final FieldSpacecraftState<T> state = propagator.propagate(orbit.getDate().shiftedBy(60));
610         T[] add = MathArrays.buildArray(field, 2);
611         add[0] = zero.add(1.);
612         add[1] = zero.add(2.);
613         final FieldSpacecraftState<T> extended =
614                 state.
615                         addAdditionalData("test-1", add).
616                         addAdditionalData("test-2", zero.add(42.0)).
617                         addAdditionalData("test-string", "hello");
618         Assertions.assertEquals(0, state.getAdditionalDataValues().size());
619         Assertions.assertFalse(state.hasAdditionalData("test-1"));
620         try {
621             state.getAdditionalData("test-1");
622             Assertions.fail("an exception should have been thrown");
623         } catch (OrekitException oe) {
624             Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
625             Assertions.assertEquals(oe.getParts()[0], "test-1");
626         }
627         try {
628             state.ensureCompatibleAdditionalStates(extended);
629             Assertions.fail("an exception should have been thrown");
630         } catch (OrekitException oe) {
631             Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
632             Assertions.assertTrue(oe.getParts()[0].toString().startsWith("test-"));
633         }
634         try {
635             extended.ensureCompatibleAdditionalStates(state);
636             Assertions.fail("an exception should have been thrown");
637         } catch (OrekitException oe) {
638             Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
639             Assertions.assertTrue(oe.getParts()[0].toString().startsWith("test-"));
640         }
641         try {
642             T[] kk = MathArrays.buildArray(field, 7);
643             extended.ensureCompatibleAdditionalStates(extended.addAdditionalData("test-2", kk));
644             Assertions.fail("an exception should have been thrown");
645         } catch (MathIllegalStateException mise) {
646             Assertions.assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, mise.getSpecifier());
647             Assertions.assertEquals(7, ((Integer) mise.getParts()[0]).intValue());
648         }
649         extended.ensureCompatibleAdditionalStates(extended.addAdditionalData("test-string", "hello"));
650         Assertions.assertEquals(3, extended.getAdditionalDataValues().size());
651         Assertions.assertTrue(extended.hasAdditionalData("test-1"));
652         Assertions.assertTrue(extended.hasAdditionalData("test-2"));
653         Assertions.assertEquals( 1.0, extended.getAdditionalState("test-1")[0].getReal(), 1.0e-15);
654         Assertions.assertEquals( 2.0, extended.getAdditionalState("test-1")[1].getReal(), 1.0e-15);
655         Assertions.assertEquals(42.0, extended.getAdditionalState("test-2")[0].getReal(), 1.0e-15);
656         Assertions.assertEquals("hello", extended.getAdditionalData("test-string"));
657 
658         // test various constructors
659         T[] dd = MathArrays.buildArray(field, 1);
660         dd[0] = zero.add(-6.0);
661         FieldDataDictionary<T> dictionary = new FieldDataDictionary<>(field);
662         dictionary.put("test-3", dd);
663         FieldSpacecraftState<T> sO = state.withAdditionalData(dictionary);
664         FieldSpacecraftState<T> sFromDouble = new FieldSpacecraftState<>(field, sO.toSpacecraftState());
665         Assertions.assertEquals(-6.0, sFromDouble.getAdditionalState("test-3")[0].getReal(), 1.0e-15);
666 
667     }
668 
669     private <T extends CalculusFieldElement<T>> void doTestAdditionalStatesDerivatives(final Field<T> field) {
670 
671         T zero = field.getZero();
672         T a = zero.add(rOrbit.getA());
673         T e = zero.add(rOrbit.getE());
674         T i = zero.add(rOrbit.getI());
675         T pa = zero.add(1.9674147913622104);
676         T raan = zero.add(FastMath.toRadians(261));
677         T lv = zero.add(0);
678         T mass = zero.add(2500);
679 
680         FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, new DateComponents(2004, 01, 01),
681                                                             TimeComponents.H00,
682                                                             TimeScalesFactory.getUTC());
683 
684         FieldKeplerianOrbit<T> orbit = new FieldKeplerianOrbit<>(a, e, i, pa, raan, lv, PositionAngleType.TRUE,
685                                                                  FramesFactory.getEME2000(), date, zero.add(mu));
686 
687         BodyCenterPointing attitudeLaw = new BodyCenterPointing(orbit.getFrame(), earth);
688 
689         FieldKeplerianPropagator<T> propagator =
690                         new FieldKeplerianPropagator<>(orbit, attitudeLaw, zero.add(mu), mass);
691 
692 
693 
694 
695         final FieldSpacecraftState<T> state = propagator.propagate(orbit.getDate().shiftedBy(60));
696         T[] add = MathArrays.buildArray(field, 2);
697         add[0] = zero.add(1.);
698         add[1] = zero.add(2.);
699         final FieldSpacecraftState<T> extended =
700                 state.
701                  addAdditionalStateDerivative("test-1", add).
702                   addAdditionalStateDerivative("test-2", zero.add(42.0));
703         Assertions.assertEquals(0, state.getAdditionalStatesDerivatives().size());
704         Assertions.assertFalse(state.hasAdditionalStateDerivative("test-1"));
705         try {
706             state.getAdditionalStateDerivative("test-1");
707             Assertions.fail("an exception should have been thrown");
708         } catch (OrekitException oe) {
709             Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
710             Assertions.assertEquals(oe.getParts()[0], "test-1");
711         }
712         try {
713             state.ensureCompatibleAdditionalStates(extended);
714             Assertions.fail("an exception should have been thrown");
715         } catch (OrekitException oe) {
716             Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
717             Assertions.assertTrue(oe.getParts()[0].toString().startsWith("test-"));
718         }
719         try {
720             extended.ensureCompatibleAdditionalStates(state);
721             Assertions.fail("an exception should have been thrown");
722         } catch (OrekitException oe) {
723             Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
724             Assertions.assertTrue(oe.getParts()[0].toString().startsWith("test-"));
725         }
726         try {
727             T[] kk = MathArrays.buildArray(field, 7);
728             extended.ensureCompatibleAdditionalStates(extended.addAdditionalStateDerivative("test-2", kk));
729             Assertions.fail("an exception should have been thrown");
730         } catch (MathIllegalStateException mise) {
731             Assertions.assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, mise.getSpecifier());
732             Assertions.assertEquals(7, ((Integer) mise.getParts()[0]).intValue());
733         }
734         Assertions.assertEquals(2, extended.getAdditionalStatesDerivatives().size());
735         Assertions.assertTrue(extended.hasAdditionalStateDerivative("test-1"));
736         Assertions.assertTrue(extended.hasAdditionalStateDerivative("test-2"));
737         Assertions.assertEquals( 1.0, extended.getAdditionalStateDerivative("test-1")[0].getReal(), 1.0e-15);
738         Assertions.assertEquals( 2.0, extended.getAdditionalStateDerivative("test-1")[1].getReal(), 1.0e-15);
739         Assertions.assertEquals(42.0, extended.getAdditionalStateDerivative("test-2")[0].getReal(), 1.0e-15);
740 
741         // test most complete constructor
742         T[] dd = MathArrays.buildArray(field, 1);
743         dd[0] = zero.add(-6.0);
744         FieldArrayDictionary<T> dict = new FieldArrayDictionary<>(field);
745         dict.put("test-3", dd);
746         FieldSpacecraftState<T> s = new FieldSpacecraftState<>(state.getOrbit(), state.getAttitude(), state.getMass(), null, dict);
747         Assertions.assertFalse(s.hasAdditionalData("test-3"));
748         Assertions.assertEquals(-6.0, s.getAdditionalStateDerivative("test-3")[0].getReal(), 1.0e-15);
749 
750         // test conversion
751         FieldSpacecraftState<T> rebuilt = new FieldSpacecraftState<>(field, s.toSpacecraftState());
752         rebuilt.ensureCompatibleAdditionalStates(s);
753 
754     }
755 
756     private <T extends CalculusFieldElement<T>> void doTestFieldVsRealAbsPV(final Field<T> field) {
757         T zero = field.getZero();
758 
759         T x_f     = zero.add(0.8);
760         T y_f     = zero.add(0.2);
761         T z_f     = zero;
762         T vx_f    = zero;
763         T vy_f    = zero;
764         T vz_f    = zero.add(0.1);
765 
766         FieldAbsoluteDate<T> t_f = new FieldAbsoluteDate<>(field);
767 
768         FieldPVCoordinates<T> pva_f = new FieldPVCoordinates<>(new FieldVector3D<>(x_f,y_f,z_f), new FieldVector3D<>(vx_f,vy_f,vz_f));
769 
770         FieldAbsolutePVCoordinates<T> absPV_f = new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(), t_f, pva_f);
771 
772         FieldSpacecraftState<T> ScS_f = new FieldSpacecraftState<>(absPV_f);
773         FieldSpacecraftState<T> withM = new FieldSpacecraftState<>(absPV_f).withMass(zero.newInstance(1234.5));
774         Assertions.assertEquals(1234.5, withM.getMass().getReal(), 1.0e-10);
775         SpacecraftState ScS_r = ScS_f.toSpacecraftState();
776 
777         for (double dt = 0; dt < 500; dt+=100){
778             SpacecraftState control_r = ScS_r.shiftedBy(dt);
779             FieldSpacecraftState<T> control_f = ScS_f.shiftedBy(zero.add(dt));
780 
781             Assertions.assertEquals(control_r.getPosition().getX(), control_f.getPVCoordinates().toPVCoordinates().getPosition().getX(), 1e-10);
782             Assertions.assertEquals(control_r.getPosition().getY(), control_f.getPVCoordinates().toPVCoordinates().getPosition().getY(), 1e-10);
783             Assertions.assertEquals(control_r.getPosition().getZ(), control_f.getPVCoordinates().toPVCoordinates().getPosition().getZ(), 1e-10);
784             Assertions.assertEquals(control_r.getPVCoordinates().getVelocity().getX(), control_f.getPVCoordinates().toPVCoordinates().getVelocity().getX(), 1e-10);
785             Assertions.assertEquals(control_r.getPVCoordinates().getVelocity().getY(), control_f.getPVCoordinates().toPVCoordinates().getVelocity().getY(), 1e-10);
786             Assertions.assertEquals(control_r.getPVCoordinates().getVelocity().getZ(), control_f.getPVCoordinates().toPVCoordinates().getVelocity().getZ(), 1e-10);
787             Assertions.assertEquals(control_r.getPVCoordinates().getAcceleration().getX(), control_f.getPVCoordinates().toPVCoordinates().getAcceleration().getX(), 1e-10);
788             Assertions.assertEquals(control_r.getPVCoordinates().getAcceleration().getY(), control_f.getPVCoordinates().toPVCoordinates().getAcceleration().getY(), 1e-10);
789             Assertions.assertEquals(control_r.getPVCoordinates().getAcceleration().getZ(), control_f.getPVCoordinates().toPVCoordinates().getAcceleration().getZ(), 1e-10);
790             Assertions.assertEquals(control_r.getAttitude().getOrientation().getRotation().getQ0(), control_f.getAttitude().getOrientation().getRotation().getQ0().getReal(), 1e-10);
791             Assertions.assertEquals(control_r.getAttitude().getOrientation().getRotation().getQ1(), control_f.getAttitude().getOrientation().getRotation().getQ1().getReal(), 1e-10);
792             Assertions.assertEquals(control_r.getAttitude().getOrientation().getRotation().getQ2(), control_f.getAttitude().getOrientation().getRotation().getQ2().getReal(), 1e-10);
793             Assertions.assertEquals(control_r.getAttitude().getOrientation().getRotation().getQ3(), control_f.getAttitude().getOrientation().getRotation().getQ3().getReal(), 1e-10);
794 
795             Assertions.assertEquals(control_r.getAttitude().getSpin().getAlpha(), control_f.getAttitude().getSpin().getAlpha().getReal(), 1e-10);
796             Assertions.assertEquals(control_r.getAttitude().getSpin().getDelta(), control_f.getAttitude().getSpin().getDelta().getReal(), 1e-10);
797             Assertions.assertEquals(control_r.getAttitude().getSpin().getNorm(), control_f.getAttitude().getSpin().getNorm().getReal(), 1e-10);
798 
799             Assertions.assertEquals(control_r.getAttitude().getReferenceFrame().isPseudoInertial(), control_f.getAttitude().getReferenceFrame().isPseudoInertial());
800             Assertions.assertEquals(control_r.getAttitude().getDate().durationFrom(AbsoluteDate.J2000_EPOCH), control_f.getAttitude().getDate().durationFrom(AbsoluteDate.J2000_EPOCH).getReal(), 1e-10);
801 
802 
803         }
804     }
805 
806 
807     /**
808      * Check orbit and attitude dates can be off by a few ulps. I see this when using
809      * FixedRate attitude provider.
810      */
811     private <T extends CalculusFieldElement<T>> void doTestDateConsistencyCloseAbsPV(final Field<T> field) {
812 
813 
814         //setup
815         T zero = field.getZero();
816         T one  = field.getOne();
817         T x_f     = zero.add(0.8);
818         T y_f     = zero.add(0.2);
819         T z_f     = zero;
820         T vx_f    = zero;
821         T vy_f    = zero;
822         T vz_f    = zero.add(0.1);
823         FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, new DateComponents(2004, 01, 01),
824                                                             TimeComponents.H00,
825                                                             TimeScalesFactory.getUTC());
826         FieldPVCoordinates<T> pva_f = new FieldPVCoordinates<>(new FieldVector3D<>(x_f,y_f,z_f), new FieldVector3D<>(vx_f,vy_f,vz_f));
827 
828         FieldAbsolutePVCoordinates<T> absPV_f = new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(), date, pva_f);
829 
830         FieldAbsolutePVCoordinates<T> AbsolutePVCoordinates10Shifts = absPV_f;
831         for (int ii = 0; ii < 10; ii++) {
832             AbsolutePVCoordinates10Shifts = AbsolutePVCoordinates10Shifts.shiftedBy(zero.add(0.1));
833         }
834         final FieldAbsolutePVCoordinates<T> AbsolutePVCoordinates1Shift = absPV_f.shiftedBy(one);
835 
836         BodyCenterPointing attitudeLaw = new BodyCenterPointing(absPV_f.getFrame(), earth);
837 
838         FieldAttitude<T> shiftedAttitude = attitudeLaw.getAttitude(AbsolutePVCoordinates1Shift,
839                                                                    AbsolutePVCoordinates1Shift.getDate(),
840                                                                    absPV_f.getFrame());
841         // since Orekit 13, dates are equal
842         Assertions.assertEquals(shiftedAttitude.getDate(), AbsolutePVCoordinates10Shifts.getDate());
843 
844         //action + verify no exception is thrown
845         FieldSpacecraftState<T> s1 = new FieldSpacecraftState<>(AbsolutePVCoordinates10Shifts, shiftedAttitude);
846         FieldSpacecraftState<T> s2 = s1.shiftedBy(0.001);
847 
848         try {
849             // but here, the time difference is too great
850             new FieldSpacecraftState<>(AbsolutePVCoordinates10Shifts, s2.getAttitude());
851             Assertions.fail("an exception should have been thrown");
852         } catch (OrekitIllegalArgumentException oiae) {
853             Assertions.assertEquals(OrekitMessages.ORBIT_AND_ATTITUDE_DATES_MISMATCH,
854                                 oiae.getSpecifier());
855         }
856     }
857 
858     private <T extends CalculusFieldElement<T>> void doTestGetAdditionalStateBadType(final Field<T> field) {
859         final SpacecraftState state = new SpacecraftState(rOrbit);
860         final FieldSpacecraftState<T> fieldState = new FieldSpacecraftState<>(field, state).addAdditionalData("string", "hello there");
861         OrekitException exception = Assertions.assertThrows(OrekitException.class, () -> fieldState.getAdditionalState("string"));
862         Assertions.assertEquals(OrekitMessages.ADDITIONAL_STATE_BAD_TYPE, exception.getSpecifier());
863         Assertions.assertEquals("string", exception.getParts()[0]);
864     }
865 
866     private <T extends CalculusFieldElement<T>> void doTestFramesConsistencyAbsPV(final Field<T> field) {
867 
868         T zero = field.getZero();
869 
870         T x_f     = zero.add(0.8);
871         T y_f     = zero.add(0.2);
872         T z_f     = zero;
873         T vx_f    = zero;
874         T vy_f    = zero;
875         T vz_f    = zero.add(0.1);
876 
877 
878         FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, new DateComponents(2004, 01, 01),
879                         TimeComponents.H00,
880                         TimeScalesFactory.getUTC());
881 
882         FieldPVCoordinates<T> pva_f = new FieldPVCoordinates<>(new FieldVector3D<>(x_f,y_f,z_f), new FieldVector3D<>(vx_f,vy_f,vz_f));
883 
884         FieldAbsolutePVCoordinates<T> absPV_f = new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(), date, pva_f);
885 
886         new FieldSpacecraftState<>(absPV_f,
887                         new FieldAttitude<>(absPV_f.getDate(),
888                                         FramesFactory.getGCRF(),
889                                         FieldRotation.getIdentity(field),
890                                         FieldVector3D.getZero(field),
891                                         FieldVector3D.getZero(field)));
892     }
893 
894     private <T extends CalculusFieldElement<T>> void doTestAdditionalStatesAbsPV(final Field<T> field) {
895 
896         T zero = field.getZero();
897         T x_f     = zero.add(0.8);
898         T y_f     = zero.add(0.2);
899         T z_f     = zero;
900         T vx_f    = zero;
901         T vy_f    = zero;
902         T vz_f    = zero.add(0.1);
903 
904         FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, new DateComponents(2004, 01, 01),
905                                                             TimeComponents.H00,
906                                                             TimeScalesFactory.getUTC());
907 
908         FieldPVCoordinates<T> pva_f = new FieldPVCoordinates<>(new FieldVector3D<>(x_f,y_f,z_f), new FieldVector3D<>(vx_f,vy_f,vz_f));
909 
910         FieldAbsolutePVCoordinates<T> absPV_f = new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(), date, pva_f);
911 
912         FieldNumericalPropagator<T> prop = new FieldNumericalPropagator<>(field,
913                         new DormandPrince853FieldIntegrator<>(field, 0.1, 500, 0.001, 0.001));
914         prop.setOrbitType(null);
915 
916         final FieldSpacecraftState<T> initialState = new FieldSpacecraftState<>(absPV_f);
917 
918         prop.resetInitialState(initialState);
919 
920         final FieldSpacecraftState<T> state = prop.propagate(absPV_f.getDate().shiftedBy(60));
921         T[] add = MathArrays.buildArray(field, 2);
922         add[0] = zero.add(1.);
923         add[1] = zero.add(2.);
924         final FieldSpacecraftState<T> extended =
925                 state.
926                         addAdditionalData("test-1", add).
927                         addAdditionalData("test-2", zero.add(42.0));
928         Assertions.assertEquals(0, state.getAdditionalDataValues().size());
929         Assertions.assertFalse(state.hasAdditionalData("test-1"));
930         try {
931             state.getAdditionalData("test-1");
932             Assertions.fail("an exception should have been thrown");
933         } catch (OrekitException oe) {
934             Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
935             Assertions.assertEquals(oe.getParts()[0], "test-1");
936         }
937         try {
938             state.ensureCompatibleAdditionalStates(extended);
939             Assertions.fail("an exception should have been thrown");
940         } catch (OrekitException oe) {
941             Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
942             Assertions.assertTrue(oe.getParts()[0].toString().startsWith("test-"));
943         }
944         try {
945             extended.ensureCompatibleAdditionalStates(state);
946             Assertions.fail("an exception should have been thrown");
947         } catch (OrekitException oe) {
948             Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
949             Assertions.assertTrue(oe.getParts()[0].toString().startsWith("test-"));
950         }
951         try {
952             T[] kk = MathArrays.buildArray(field, 7);
953             extended.ensureCompatibleAdditionalStates(extended.addAdditionalData("test-2", kk));
954             Assertions.fail("an exception should have been thrown");
955         } catch (MathIllegalStateException mise) {
956             Assertions.assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, mise.getSpecifier());
957             Assertions.assertEquals(7, ((Integer) mise.getParts()[0]).intValue());
958         }
959         Assertions.assertEquals(2, extended.getAdditionalDataValues().size());
960         Assertions.assertTrue(extended.hasAdditionalData("test-1"));
961         Assertions.assertTrue(extended.hasAdditionalData("test-2"));
962         Assertions.assertEquals( 1.0, extended.getAdditionalState("test-1")[0].getReal(), 1.0e-15);
963         Assertions.assertEquals( 2.0, extended.getAdditionalState("test-1")[1].getReal(), 1.0e-15);
964         Assertions.assertEquals(42.0, extended.getAdditionalState("test-2")[0].getReal(), 1.0e-15);
965 
966         // test various constructors
967         T[] dd = MathArrays.buildArray(field, 1);
968         dd[0] = zero.add(-6.0);
969         FieldDataDictionary<T> map = new FieldDataDictionary<>(field);
970         map.put("test-3", dd);
971         FieldSpacecraftState<T> sO = new FieldSpacecraftState<>(state.getAbsPVA()).withAdditionalData(map);
972         Assertions.assertEquals(-6.0, sO.getAdditionalState("test-3")[0].getReal(), 1.0e-15);
973         FieldSpacecraftState<T> sFromDouble = new FieldSpacecraftState<>(field, sO.toSpacecraftState());
974         Assertions.assertEquals(-6.0, sFromDouble.getAdditionalState("test-3")[0].getReal(), 1.0e-15);
975 
976     }
977 
978     private <T extends CalculusFieldElement<T>> void doTestAdditionalStatesDerivativesAbsPV(final Field<T> field) {
979 
980         T zero = field.getZero();
981         T x_f     = zero.add(0.8);
982         T y_f     = zero.add(0.2);
983         T z_f     = zero;
984         T vx_f    = zero;
985         T vy_f    = zero;
986         T vz_f    = zero.add(0.1);
987 
988         FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, new DateComponents(2004, 01, 01),
989                                                             TimeComponents.H00,
990                                                             TimeScalesFactory.getUTC());
991 
992         FieldPVCoordinates<T> pva_f = new FieldPVCoordinates<>(new FieldVector3D<>(x_f,y_f,z_f), new FieldVector3D<>(vx_f,vy_f,vz_f));
993 
994         FieldAbsolutePVCoordinates<T> absPV_f = new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(), date, pva_f);
995 
996         FieldNumericalPropagator<T> prop = new FieldNumericalPropagator<>(field,
997                         new DormandPrince853FieldIntegrator<>(field, 0.1, 500, 0.001, 0.001));
998         prop.setOrbitType(null);
999 
1000         final FieldSpacecraftState<T> initialState = new FieldSpacecraftState<>(absPV_f);
1001 
1002         prop.resetInitialState(initialState);
1003 
1004         final FieldSpacecraftState<T> state = prop.propagate(absPV_f.getDate().shiftedBy(60));
1005         T[] add = MathArrays.buildArray(field, 2);
1006         add[0] = zero.add(1.);
1007         add[1] = zero.add(2.);
1008         final FieldSpacecraftState<T> extended =
1009                 state.
1010                  addAdditionalStateDerivative("test-1", add).
1011                   addAdditionalStateDerivative("test-2", zero.add(42.0));
1012         Assertions.assertEquals(0, state.getAdditionalStatesDerivatives().size());
1013         Assertions.assertFalse(state.hasAdditionalStateDerivative("test-1"));
1014         try {
1015             state.getAdditionalStateDerivative("test-1");
1016             Assertions.fail("an exception should have been thrown");
1017         } catch (OrekitException oe) {
1018             Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
1019             Assertions.assertEquals(oe.getParts()[0], "test-1");
1020         }
1021         try {
1022             state.ensureCompatibleAdditionalStates(extended);
1023             Assertions.fail("an exception should have been thrown");
1024         } catch (OrekitException oe) {
1025             Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
1026             Assertions.assertTrue(oe.getParts()[0].toString().startsWith("test-"));
1027         }
1028         try {
1029             extended.ensureCompatibleAdditionalStates(state);
1030             Assertions.fail("an exception should have been thrown");
1031         } catch (OrekitException oe) {
1032             Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
1033             Assertions.assertTrue(oe.getParts()[0].toString().startsWith("test-"));
1034         }
1035         try {
1036             T[] kk = MathArrays.buildArray(field, 7);
1037             extended.ensureCompatibleAdditionalStates(extended.addAdditionalStateDerivative("test-2", kk));
1038             Assertions.fail("an exception should have been thrown");
1039         } catch (MathIllegalStateException mise) {
1040             Assertions.assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, mise.getSpecifier());
1041             Assertions.assertEquals(7, ((Integer) mise.getParts()[0]).intValue());
1042         }
1043         Assertions.assertEquals(2, extended.getAdditionalStatesDerivatives().size());
1044         Assertions.assertTrue(extended.hasAdditionalStateDerivative("test-1"));
1045         Assertions.assertTrue(extended.hasAdditionalStateDerivative("test-2"));
1046         Assertions.assertEquals( 1.0, extended.getAdditionalStateDerivative("test-1")[0].getReal(), 1.0e-15);
1047         Assertions.assertEquals( 2.0, extended.getAdditionalStateDerivative("test-1")[1].getReal(), 1.0e-15);
1048         Assertions.assertEquals(42.0, extended.getAdditionalStateDerivative("test-2")[0].getReal(), 1.0e-15);
1049 
1050         // test most complete constructor
1051         T[] dd = MathArrays.buildArray(field, 1);
1052         dd[0] = zero.add(-6.0);
1053         FieldArrayDictionary<T> dictionary = new FieldArrayDictionary<T>(field);
1054         dictionary.put("test-3", dd);
1055         FieldSpacecraftState<T> s = new FieldSpacecraftState<>(state.getAbsPVA(), state.getAttitude(), state.getMass(), null, dictionary);
1056         Assertions.assertFalse(s.hasAdditionalData("test-3"));
1057         Assertions.assertEquals(-6.0, s.getAdditionalStateDerivative("test-3")[0].getReal(), 1.0e-15);
1058 
1059     }
1060 
1061     private <T extends CalculusFieldElement<T>> void doTestAdditionalTestResetOnEventAnalytical(final Field<T> field) {
1062 
1063         T zero = field.getZero();
1064 
1065         // Build orbit
1066         FieldAbsoluteDate<T> date0 = new FieldAbsoluteDate<>(field, 2000, 1, 1, TimeScalesFactory.getUTC());
1067         FieldOrbit<T> orbit = new FieldKeplerianOrbit<>(zero.add(7.1E6), zero, zero, zero, zero, zero,
1068                                          PositionAngleType.TRUE, FramesFactory.getGCRF(), date0,
1069                                          zero.add(Constants.WGS84_EARTH_MU));
1070 
1071         // Build propagator
1072         FieldKeplerianPropagator<T> propagator = new FieldKeplerianPropagator<>(orbit);
1073 
1074         // Create initial state with one additional state and add it to the propagator
1075         final String name = "A";
1076         FieldSpacecraftState<T> initialState = new FieldSpacecraftState<>(orbit).
1077                 addAdditionalData(name, zero.add(-1));
1078 
1079         propagator.resetInitialState(initialState);
1080 
1081         // Create date detector and handler
1082         FieldAbsoluteDate<T> changeDate = date0.shiftedBy(3);
1083         FieldDateDetector<T> dateDetector = new FieldDateDetector<>(field, changeDate).
1084                                     withHandler(new FieldEventHandler<T>() {
1085 
1086             @Override
1087             public Action eventOccurred(FieldSpacecraftState<T> s, FieldEventDetector<T> detector, boolean increasing) {
1088               return Action.RESET_STATE;
1089             }
1090 
1091             @Override
1092             public FieldSpacecraftState<T> resetState(FieldEventDetector<T> detector, FieldSpacecraftState<T> oldState) {
1093                 return oldState.addAdditionalData(name, zero.add(+1));
1094             }
1095 
1096         });
1097 
1098         propagator.addEventDetector(dateDetector);
1099         propagator.setStepHandler(zero.add(0.125), s -> {
1100             if (s.getDate().durationFrom(changeDate).getReal() < -0.001) {
1101                 Assertions.assertEquals(-1, s.getAdditionalState(name)[0].getReal(), 1.0e-15);
1102             } else if (s.getDate().durationFrom(changeDate).getReal() > +0.001) {
1103                 Assertions.assertEquals(+1, s.getAdditionalState(name)[0].getReal(), 1.0e-15);
1104             }
1105         });
1106         FieldSpacecraftState<T> finalState = propagator.propagate(date0, date0.shiftedBy(5));
1107         Assertions.assertEquals(+1, finalState.getAdditionalState(name)[0].getReal(), 1.0e-15);
1108 
1109     }
1110 
1111     private <T extends CalculusFieldElement<T>> void doTestAdditionalTestResetOnEventNumerical(final Field<T> field) {
1112 
1113         T zero = field.getZero();
1114 
1115         // Build orbit
1116         FieldAbsoluteDate<T> date0 = new FieldAbsoluteDate<>(field, 2000, 1, 1, TimeScalesFactory.getUTC());
1117         FieldOrbit<T> orbit = new FieldKeplerianOrbit<>(zero.add(7.1E6), zero, zero, zero, zero, zero,
1118                                          PositionAngleType.TRUE, FramesFactory.getGCRF(), date0,
1119                                          zero.add(Constants.WGS84_EARTH_MU));
1120 
1121         // Build propagator
1122         FieldODEIntegrator<T> odeIntegrator = new DormandPrince853FieldIntegrator<>(field, 1E-3, 1E3, 1E-6, 1E-6);
1123         FieldNumericalPropagator<T> propagator = new FieldNumericalPropagator<>(field, odeIntegrator);
1124 
1125         // Create initial state with one additional state and add it to the propagator
1126         final String name = "A";
1127         FieldSpacecraftState<T> initialState = new FieldSpacecraftState<>(orbit).
1128                 addAdditionalData(name, zero.add(-1));
1129 
1130         propagator.resetInitialState(initialState);
1131 
1132         // Create date detector and handler
1133         FieldAbsoluteDate<T> changeDate = date0.shiftedBy(3);
1134         FieldDateDetector<T> dateDetector = new FieldDateDetector<>(field, changeDate).
1135                                     withHandler(new FieldEventHandler<T>() {
1136 
1137             @Override
1138             public Action eventOccurred(FieldSpacecraftState<T> s, FieldEventDetector<T> detector, boolean increasing) {
1139               return Action.RESET_STATE;
1140             }
1141 
1142             @Override
1143             public FieldSpacecraftState<T> resetState(FieldEventDetector<T> detector, FieldSpacecraftState<T> oldState) {
1144                 return oldState.addAdditionalData(name, zero.add(+1));
1145             }
1146 
1147         });
1148 
1149         propagator.addEventDetector(dateDetector);
1150         propagator.setStepHandler(zero.add(0.125), s -> {
1151             if (s.getDate().durationFrom(changeDate).getReal() < -0.001) {
1152                 Assertions.assertEquals(-1, s.getAdditionalState(name)[0].getReal(), 1.0e-15);
1153             } else if (s.getDate().durationFrom(changeDate).getReal() > +0.001) {
1154                 Assertions.assertEquals(+1, s.getAdditionalState(name)[0].getReal(), 1.0e-15);
1155             }
1156         });
1157         FieldSpacecraftState<T> finalState = propagator.propagate(date0, date0.shiftedBy(5));
1158         Assertions.assertEquals(+1, finalState.getAdditionalState(name)[0].getReal(), 1.0e-15);
1159 
1160     }
1161 
1162     private <T extends CalculusFieldElement<T>> void doTestShiftAdditionalDerivativesDouble(final Field<T> field) {
1163 
1164         T zero = field.getZero();
1165 
1166         // Build orbit
1167         FieldAbsoluteDate<T> date0 = new FieldAbsoluteDate<>(field, 2000, 1, 1, TimeScalesFactory.getUTC());
1168         FieldOrbit<T> orbit = new FieldKeplerianOrbit<>(zero.add(7.1E6), zero, zero, zero, zero, zero,
1169                                          PositionAngleType.TRUE, FramesFactory.getGCRF(), date0,
1170                                          zero.add(Constants.WGS84_EARTH_MU));
1171 
1172         // Build propagator
1173         FieldKeplerianPropagator<T> propagator = new FieldKeplerianPropagator<>(orbit);
1174 
1175         final String valueAndDerivative = "value-and-derivative";
1176         final String valueOnly          = "value-only";
1177         final String derivativeOnly     = "derivative-only";
1178         final FieldSpacecraftState<T> s0 = propagator.getInitialState().
1179                 addAdditionalData(valueAndDerivative,           convert(field, new double[] { 1.0,  2.0 })).
1180                                            addAdditionalStateDerivative(valueAndDerivative, convert(field, new double[] { 3.0,  2.0 })).
1181                 addAdditionalData(valueOnly,                    convert(field, new double[] { 5.0,  4.0 })).
1182                                            addAdditionalStateDerivative(derivativeOnly,     convert(field, new double[] { 1.0, -1.0 }));
1183         Assertions.assertEquals( 1.0, s0.getAdditionalState(valueAndDerivative)[0].getReal(),           1.0e-15);
1184         Assertions.assertEquals( 2.0, s0.getAdditionalState(valueAndDerivative)[1].getReal(),           1.0e-15);
1185         Assertions.assertEquals( 3.0, s0.getAdditionalStateDerivative(valueAndDerivative)[0].getReal(), 1.0e-15);
1186         Assertions.assertEquals( 2.0, s0.getAdditionalStateDerivative(valueAndDerivative)[1].getReal(), 1.0e-15);
1187         Assertions.assertEquals( 5.0, s0.getAdditionalState(valueOnly)[0].getReal(),                    1.0e-15);
1188         Assertions.assertEquals( 4.0, s0.getAdditionalState(valueOnly)[1].getReal(),                    1.0e-15);
1189         Assertions.assertEquals( 1.0, s0.getAdditionalStateDerivative(derivativeOnly)[0].getReal(),     1.0e-15);
1190         Assertions.assertEquals(-1.0, s0.getAdditionalStateDerivative(derivativeOnly)[1].getReal(),     1.0e-15);
1191         final FieldSpacecraftState<T> s1 = s0.shiftedBy(-2.0);
1192         Assertions.assertEquals(-5.0, s1.getAdditionalState(valueAndDerivative)[0].getReal(),           1.0e-15);
1193         Assertions.assertEquals(-2.0, s1.getAdditionalState(valueAndDerivative)[1].getReal(),           1.0e-15);
1194         Assertions.assertEquals( 3.0, s1.getAdditionalStateDerivative(valueAndDerivative)[0].getReal(), 1.0e-15);
1195         Assertions.assertEquals( 2.0, s1.getAdditionalStateDerivative(valueAndDerivative)[1].getReal(), 1.0e-15);
1196         Assertions.assertEquals( 5.0, s1.getAdditionalState(valueOnly)[0].getReal(),                    1.0e-15);
1197         Assertions.assertEquals( 4.0, s1.getAdditionalState(valueOnly)[1].getReal(),                    1.0e-15);
1198         Assertions.assertEquals( 1.0, s1.getAdditionalStateDerivative(derivativeOnly)[0].getReal(),     1.0e-15);
1199         Assertions.assertEquals(-1.0, s1.getAdditionalStateDerivative(derivativeOnly)[1].getReal(),     1.0e-15);
1200 
1201     }
1202 
1203     private <T extends CalculusFieldElement<T>> void doTestShiftAdditionalDerivativesField(final Field<T> field) {
1204 
1205         T zero = field.getZero();
1206 
1207         // Build orbit
1208         FieldAbsoluteDate<T> date0 = new FieldAbsoluteDate<>(field, 2000, 1, 1, TimeScalesFactory.getUTC());
1209         FieldOrbit<T> orbit = new FieldKeplerianOrbit<>(zero.add(7.1E6), zero, zero, zero, zero, zero,
1210                                          PositionAngleType.TRUE, FramesFactory.getGCRF(), date0,
1211                                          zero.add(Constants.WGS84_EARTH_MU));
1212 
1213         // Build propagator
1214         FieldKeplerianPropagator<T> propagator = new FieldKeplerianPropagator<>(orbit);
1215 
1216         final String valueAndDerivative = "value-and-derivative";
1217         final String valueOnly          = "value-only";
1218         final String derivativeOnly     = "derivative-only";
1219         final FieldSpacecraftState<T> s0 = propagator.getInitialState().
1220                 addAdditionalData(valueAndDerivative,           convert(field, new double[] { 1.0,  2.0 })).
1221                                            addAdditionalStateDerivative(valueAndDerivative, convert(field, new double[] { 3.0,  2.0 })).
1222                 addAdditionalData(valueOnly,                    convert(field, new double[] { 5.0,  4.0 })).
1223                                            addAdditionalStateDerivative(derivativeOnly,     convert(field, new double[] { 1.0, -1.0 }));
1224         Assertions.assertEquals( 1.0, s0.getAdditionalState(valueAndDerivative)[0].getReal(),           1.0e-15);
1225         Assertions.assertEquals( 2.0, s0.getAdditionalState(valueAndDerivative)[1].getReal(),           1.0e-15);
1226         Assertions.assertEquals( 3.0, s0.getAdditionalStateDerivative(valueAndDerivative)[0].getReal(), 1.0e-15);
1227         Assertions.assertEquals( 2.0, s0.getAdditionalStateDerivative(valueAndDerivative)[1].getReal(), 1.0e-15);
1228         Assertions.assertEquals( 5.0, s0.getAdditionalState(valueOnly)[0].getReal(),                    1.0e-15);
1229         Assertions.assertEquals( 4.0, s0.getAdditionalState(valueOnly)[1].getReal(),                    1.0e-15);
1230         Assertions.assertEquals( 1.0, s0.getAdditionalStateDerivative(derivativeOnly)[0].getReal(),     1.0e-15);
1231         Assertions.assertEquals(-1.0, s0.getAdditionalStateDerivative(derivativeOnly)[1].getReal(),     1.0e-15);
1232         final FieldSpacecraftState<T> s1 = s0.shiftedBy(field.getZero().newInstance(-2.0));
1233         Assertions.assertEquals(-5.0, s1.getAdditionalState(valueAndDerivative)[0].getReal(),           1.0e-15);
1234         Assertions.assertEquals(-2.0, s1.getAdditionalState(valueAndDerivative)[1].getReal(),           1.0e-15);
1235         Assertions.assertEquals( 3.0, s1.getAdditionalStateDerivative(valueAndDerivative)[0].getReal(), 1.0e-15);
1236         Assertions.assertEquals( 2.0, s1.getAdditionalStateDerivative(valueAndDerivative)[1].getReal(), 1.0e-15);
1237         Assertions.assertEquals( 5.0, s1.getAdditionalState(valueOnly)[0].getReal(),                    1.0e-15);
1238         Assertions.assertEquals( 4.0, s1.getAdditionalState(valueOnly)[1].getReal(),                    1.0e-15);
1239         Assertions.assertEquals( 1.0, s1.getAdditionalStateDerivative(derivativeOnly)[0].getReal(),     1.0e-15);
1240         Assertions.assertEquals(-1.0, s1.getAdditionalStateDerivative(derivativeOnly)[1].getReal(),     1.0e-15);
1241 
1242     }
1243 
1244     @BeforeEach
1245     public void setUp(){
1246         try {
1247 
1248             Utils.setDataRoot("regular-data");
1249             mu  = 3.9860047e14;
1250 
1251             double a     = 7187990.1979844316;
1252             double e     = 0.5e-4;
1253             double i     = 1.7105407051081795;
1254             double omega = 1.9674147913622104;
1255             double OMEGA = FastMath.toRadians(261);
1256             double lv    =    0;
1257 
1258             rDate = new AbsoluteDate(new DateComponents(2004, 1, 1),
1259                                      TimeComponents.H00,
1260                                      TimeScalesFactory.getUTC());
1261             rOrbit = new KeplerianOrbit(a, e, i, omega, OMEGA, lv, PositionAngleType.TRUE,
1262                                         FramesFactory.getEME2000(), rDate, mu);
1263             earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
1264                                          Constants.WGS84_EARTH_FLATTENING,
1265                                          FramesFactory.getITRF(IERSConventions.IERS_2010, true));
1266         } catch (OrekitException oe) {
1267 
1268             Assertions.fail(oe.getLocalizedMessage());
1269         }
1270     }
1271 
1272     private <T extends CalculusFieldElement<T>> T[] convert(final Field<T> field, final double[] a) {
1273         final T[] converted = MathArrays.buildArray(field, a.length);
1274         for (int i = 0; i < a.length; ++i) {
1275             converted[i] = field.getZero().newInstance(a[i]);
1276         }
1277         return converted;
1278     }
1279 
1280     private AbsoluteDate rDate;
1281     private double mu;
1282     private Orbit rOrbit;
1283     private OneAxisEllipsoid earth;
1284 
1285 }
1286