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.utils;
18  
19  
20  import org.hipparchus.CalculusFieldElement;
21  import org.hipparchus.Field;
22  import org.hipparchus.analysis.differentiation.FieldDerivativeStructure;
23  import org.hipparchus.analysis.differentiation.FieldUnivariateDerivative1;
24  import org.hipparchus.analysis.differentiation.FieldUnivariateDerivative2;
25  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
26  import org.hipparchus.geometry.euclidean.threed.Vector3D;
27  import org.hipparchus.util.Binary64;
28  import org.hipparchus.util.Binary64Field;
29  import org.junit.jupiter.api.Assertions;
30  import org.junit.jupiter.api.BeforeEach;
31  import org.junit.jupiter.api.Test;
32  import org.orekit.TestUtils;
33  import org.orekit.Utils;
34  import org.orekit.errors.OrekitIllegalArgumentException;
35  import org.orekit.errors.OrekitMessages;
36  import org.orekit.frames.Frame;
37  import org.orekit.frames.FramesFactory;
38  import org.orekit.frames.Transform;
39  import org.orekit.time.FieldAbsoluteDate;
40  
41  public class FieldAbsolutePVCoordinatesTest {
42  
43      @BeforeEach
44      public void setUp() {
45          Utils.setDataRoot("regular-data");
46      }
47  
48      @Test
49      public void TestPVOnlyConstructor() {
50          doTestPVOnlyConstructor(Binary64Field.getInstance());
51      }
52  
53      @Test
54      public void testPVCoordinatesCopyConstructor() {
55          doTestPVCoordinatesCopyConstructor(Binary64Field.getInstance());
56      }
57  
58      @Test
59      public void testLinearConstructors() {
60          doTestLinearConstructors(Binary64Field.getInstance());
61      }
62  
63      @Test
64      public void testDifferentFrames() {
65          doTestDifferentFrames(Binary64Field.getInstance());
66      }
67  
68      @Test
69      public void testToDerivativeStructureVector1() {
70          doTestToDerivativeStructureVector1(Binary64Field.getInstance());
71      }
72  
73      @Test
74      public void testToDerivativeStructureVector2() {
75          doTestToDerivativeStructureVector2(Binary64Field.getInstance());
76      }
77  
78      @Test
79      public void testToUnivariateDerivative1Vector() {
80          doTestToUnivariateDerivative1Vector(Binary64Field.getInstance());
81      }
82  
83      @Test
84      public void testToUnivariateDerivative2Vector() {
85          doTestToUnivariateDerivative2Vector(Binary64Field.getInstance());
86      }
87  
88      @Test
89      public void testShift() {
90          doTestShift(Binary64Field.getInstance());
91      }
92  
93      @Test
94      public void testToString() {
95          doTestToString(Binary64Field.getInstance());
96      }
97  
98      @Test
99      public void testSamePV() {
100         doTestSamePV(Binary64Field.getInstance());
101     }
102 
103     @Test
104     public void testTaylorProvider() {
105         doTestTaylorProvider(Binary64Field.getInstance());
106     }
107 
108     @Test
109     public void testIssue1557() {
110         // GIVEN
111         final FieldAbsolutePVCoordinates<Binary64> absPV = TestUtils.getFakeFieldAbsolutePVACoordinates();
112 
113         // WHEN
114         final FieldVector3D<Binary64> velocity = absPV.getVelocity(absPV.getDate(), absPV.getFrame());
115 
116         // THEN
117         final FieldPVCoordinates<Binary64> refPV = absPV.getPVCoordinates();
118         Assertions.assertEquals(refPV.getVelocity(), velocity);
119     }
120 
121     private <T extends CalculusFieldElement<T>> void doTestPVOnlyConstructor(Field<T> field) {
122         //setup
123         FieldAbsoluteDate<T> date = FieldAbsoluteDate.getJ2000Epoch(field);
124         Frame frame = FramesFactory.getEME2000();
125         final T one = field.getOne();
126         FieldVector3D<T> p = new FieldVector3D<>(one, one.multiply(2.0), one.multiply(3.0));
127         FieldVector3D<T> v = new FieldVector3D<>(one.multiply(4.0), one.multiply(5.0), one.multiply(6.0));
128 
129         //action
130         FieldAbsolutePVCoordinates<T> actual = new FieldAbsolutePVCoordinates<>(frame, date, p, v);
131 
132         //verify
133         Assertions.assertEquals(date, actual.getDate());
134         Assertions.assertEquals(1.0, actual.getPosition().getX().getReal(), 0.0);
135         Assertions.assertEquals(2.0, actual.getPosition().getY().getReal(), 0.0);
136         Assertions.assertEquals(3.0, actual.getPosition().getZ().getReal(), 0.0);
137         Assertions.assertEquals(4.0, actual.getVelocity().getX().getReal(), 0.0);
138         Assertions.assertEquals(5.0, actual.getVelocity().getY().getReal(), 0.0);
139         Assertions.assertEquals(6.0, actual.getVelocity().getZ().getReal(), 0.0);
140         Assertions.assertEquals(FieldVector3D.getZero(field), actual.getAcceleration());
141     }
142 
143     private <T extends CalculusFieldElement<T>> void doTestPVCoordinatesCopyConstructor(Field<T> field) {
144         //setup
145         FieldAbsoluteDate<T> date = FieldAbsoluteDate.getJ2000Epoch(field);
146         Frame frame = FramesFactory.getEME2000();
147         final T one = field.getOne();
148         FieldPVCoordinates<T> pv = new FieldPVCoordinates<>(new FieldVector3D<>(one, one.multiply(2), one.multiply(3)), new FieldVector3D<>(one.multiply(4), one.multiply(5), one.multiply(6)));
149 
150         //action
151         FieldAbsolutePVCoordinates<T> actual = new FieldAbsolutePVCoordinates<>(frame, date, pv);
152 
153         //verify
154         Assertions.assertEquals(date, actual.getDate());
155         Assertions.assertEquals(1.0, actual.getPosition().getX().getReal(), 0.0);
156         Assertions.assertEquals(2.0, actual.getPosition().getY().getReal(), 0.0);
157         Assertions.assertEquals(3.0, actual.getPosition().getZ().getReal(), 0.0);
158         Assertions.assertEquals(4.0, actual.getVelocity().getX().getReal(), 0.0);
159         Assertions.assertEquals(5.0, actual.getVelocity().getY().getReal(), 0.0);
160         Assertions.assertEquals(6.0, actual.getVelocity().getZ().getReal(), 0.0);
161         Assertions.assertEquals(FieldVector3D.getZero(field), actual.getAcceleration());
162     }
163 
164     private <T extends CalculusFieldElement<T>> void doTestLinearConstructors(Field<T> field) {
165         Frame frame = FramesFactory.getEME2000();
166         final T one = field.getOne();
167         FieldAbsolutePVCoordinates<T> pv1 = new FieldAbsolutePVCoordinates<>(frame,FieldAbsoluteDate.getCCSDSEpoch(field),
168                                                               new FieldVector3D<>(one, one.multiply(0.1), one.multiply(10.0)),
169                                                               new FieldVector3D<>(one.multiply(-1.0), one.multiply(-0.1), one.multiply(-10.0)),
170                                                               new FieldVector3D<>(one.multiply(10.0), one.multiply(-1.0), one.multiply(-100.0)));
171         FieldAbsolutePVCoordinates<T> pv2 = new FieldAbsolutePVCoordinates<>(frame,FieldAbsoluteDate.getFiftiesEpoch(field),
172                                                               new FieldVector3D<>(one.multiply(2.0), one.multiply(0.2), one.multiply(20.0)),
173                                                               new FieldVector3D<>(one.multiply(-2.0), one.multiply(-0.2), one.multiply(-20.0)),
174                                                               new FieldVector3D<>(one.multiply(20.0), one.multiply(-2.0), one.multiply(-200.0)));
175         FieldAbsolutePVCoordinates<T> pv3 = new FieldAbsolutePVCoordinates<>(frame,FieldAbsoluteDate.getGalileoEpoch(field),
176                                                                 new FieldVector3D<>(one.multiply(3.0), one.multiply(0.3), one.multiply(30.0)),
177                                                                 new FieldVector3D<>(one.multiply(-3.0), one.multiply(-0.3), one.multiply(-30.0)),
178                                                                 new FieldVector3D<>(one.multiply(30.0), one.multiply(-3.0), one.multiply(-300.0)));
179         FieldAbsolutePVCoordinates<T> pv4 = new FieldAbsolutePVCoordinates<>(frame,FieldAbsoluteDate.getJulianEpoch(field),
180                                                                 new FieldVector3D<>(one.multiply(4.0), one.multiply(0.4), one.multiply(40.0)),
181                                                                 new FieldVector3D<>(one.multiply(-4.0), one.multiply(-0.4), one.multiply(-40.0)),
182                                                                 new FieldVector3D<>(one.multiply(40.0), one.multiply(-4.0), one.multiply(-400.0)));
183         checkPV(pv4, new FieldAbsolutePVCoordinates<T>(FieldAbsoluteDate.getJulianEpoch(field), one.multiply(4.0), pv1), 1.0e-15);
184         checkPV(pv2, new FieldAbsolutePVCoordinates<T>(FieldAbsoluteDate.getFiftiesEpoch(field), pv1, pv3), 1.0e-15);
185         checkPV(pv3, new FieldAbsolutePVCoordinates<T>(FieldAbsoluteDate.getGalileoEpoch(field), one, pv1, one, pv2), 1.0e-15);
186         checkPV(new FieldAbsolutePVCoordinates<T>(FieldAbsoluteDate.getJ2000Epoch(field), one.multiply(2.0), pv4),
187                 new FieldAbsolutePVCoordinates<T>(FieldAbsoluteDate.getJ2000Epoch(field), one.multiply(3.0), pv1, one, pv2, one, pv3),
188                 1.0e-15);
189         checkPV(new FieldAbsolutePVCoordinates<T>(FieldAbsoluteDate.getJ2000Epoch(field), one.multiply(3.0), pv3),
190                 new FieldAbsolutePVCoordinates<T>(FieldAbsoluteDate.getJ2000Epoch(field), one.multiply(3.0), pv1, one, pv2, one, pv4),
191                 1.0e-15);
192         checkPV(new FieldAbsolutePVCoordinates<T>(FieldAbsoluteDate.getJ2000Epoch(field), one.multiply(5.0), pv4),
193                 new FieldAbsolutePVCoordinates<T>(FieldAbsoluteDate.getJ2000Epoch(field), one.multiply(4.0), pv1, one.multiply(3.0), pv2, one.multiply(2.0), pv3, one, pv4),
194                 1.0e-15);
195     }
196 
197     private <T extends CalculusFieldElement<T>> void doTestDifferentFrames(Field<T> field) {
198         final FieldVector3D<T> zero = FieldVector3D.getZero(field);
199         FieldAbsolutePVCoordinates<T> apv1 = new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(),
200                                                                               FieldAbsoluteDate.getArbitraryEpoch(field),
201                                                                               zero, zero, zero);
202         FieldAbsolutePVCoordinates<T> apv2 = new FieldAbsolutePVCoordinates<>(FramesFactory.getGCRF(),
203                                                                               FieldAbsoluteDate.getArbitraryEpoch(field),
204                                                                               zero, zero, zero);
205         try {
206             new FieldAbsolutePVCoordinates<>(FieldAbsoluteDate.getArbitraryEpoch(field), apv1, apv2);
207             Assertions.fail("an exception should have been thrown");
208         } catch (OrekitIllegalArgumentException oe) {
209             Assertions.assertEquals(OrekitMessages.INCOMPATIBLE_FRAMES, oe.getSpecifier());
210             Assertions.assertEquals(apv1.getFrame().getName(), oe.getParts()[0]);
211             Assertions.assertEquals(apv2.getFrame().getName(), oe.getParts()[1]);
212         }
213     }
214 
215     private <T extends CalculusFieldElement<T>> void doTestToDerivativeStructureVector1(Field<T> field) {
216         final T one = field.getOne();
217         FieldVector3D<FieldDerivativeStructure<T>> fv =
218                         new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(),
219                                         FieldAbsoluteDate.getGalileoEpoch(field),
220                                         new FieldVector3D<>(one, one.multiply(0.1), one.multiply(10.0)),
221                                         new FieldVector3D<>(one.multiply(-1.0), one.multiply(-0.1), one.multiply(-10.0)),
222                                         new FieldVector3D<>(one.multiply(10.0), one.multiply(-1.0), one.multiply(-100.0))).toDerivativeStructureVector(1);
223 
224         Assertions.assertEquals(1, fv.getX().getFreeParameters());
225         Assertions.assertEquals(1, fv.getX().getOrder());
226         Assertions.assertEquals(   1.0, fv.getX().getReal(), 1.0e-10);
227         Assertions.assertEquals(   0.1, fv.getY().getReal(), 1.0e-10);
228         Assertions.assertEquals(  10.0, fv.getZ().getReal(), 1.0e-10);
229         Assertions.assertEquals(  -1.0, fv.getX().getPartialDerivative(1).getReal(), 1.0e-15);
230         Assertions.assertEquals(  -0.1, fv.getY().getPartialDerivative(1).getReal(), 1.0e-15);
231         Assertions.assertEquals( -10.0, fv.getZ().getPartialDerivative(1).getReal(), 1.0e-15);
232         checkPV(new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(),
233                         FieldAbsoluteDate.getGalileoEpoch(field),
234                         new FieldVector3D<>(one,  one.multiply(0.1), one.multiply(10.0)),
235                         new FieldVector3D<>(one.multiply(-1.0), one.multiply(-0.1), one.multiply(-10.0)),
236                         FieldVector3D.getZero(field)),
237                 new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(),
238                                 FieldAbsoluteDate.getGalileoEpoch(field), fv), 1.0e-15);
239 
240         for (double dt = 0; dt < 10; dt += 0.125) {
241             Vector3D p = new PVCoordinates(new Vector3D( 1,  0.1,  10),
242                                            new Vector3D(-1, -0.1, -10)).shiftedBy(dt).getPosition();
243             Assertions.assertEquals(p.getX(), fv.getX().taylor(dt).getReal(), 1.0e-14);
244             Assertions.assertEquals(p.getY(), fv.getY().taylor(dt).getReal(), 1.0e-14);
245             Assertions.assertEquals(p.getZ(), fv.getZ().taylor(dt).getReal(), 1.0e-14);
246         }
247 
248         FieldAbsolutePVCoordinates<T> pv =
249                         new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(),
250                                         FieldAbsoluteDate.getGalileoEpoch(field),
251                                         fv);
252         Assertions.assertEquals(   1.0, pv.getPosition().getX().getReal(), 1.0e-10);
253         Assertions.assertEquals(   0.1, pv.getPosition().getY().getReal(), 1.0e-10);
254         Assertions.assertEquals(  10.0, pv.getPosition().getZ().getReal(), 1.0e-10);
255         Assertions.assertEquals(  -1.0, pv.getVelocity().getX().getReal(), 1.0e-15);
256         Assertions.assertEquals(  -0.1, pv.getVelocity().getY().getReal(), 1.0e-15);
257         Assertions.assertEquals( -10.0, pv.getVelocity().getZ().getReal(), 1.0e-15);
258 
259     }
260 
261     private <T extends CalculusFieldElement<T>> void doTestToDerivativeStructureVector2(Field<T> field) {
262         final T one = field.getOne();
263         FieldVector3D<FieldDerivativeStructure<T>> fv =
264                         new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(),
265                                         FieldAbsoluteDate.getGalileoEpoch(field),
266                                         new FieldVector3D<>(one, one.multiply(0.1), one.multiply(10.0)),
267                                         new FieldVector3D<>(one.multiply(-1.0), one.multiply(-0.1), one.multiply(-10.0)),
268                                         new FieldVector3D<>(one.multiply(10.0), one.multiply(-1.0), one.multiply(-100.0))).toDerivativeStructureVector(2);
269 
270         Assertions.assertEquals(1, fv.getX().getFreeParameters());
271         Assertions.assertEquals(2, fv.getX().getOrder());
272         Assertions.assertEquals(   1.0, fv.getX().getReal(), 1.0e-10);
273         Assertions.assertEquals(   0.1, fv.getY().getReal(), 1.0e-10);
274         Assertions.assertEquals(  10.0, fv.getZ().getReal(), 1.0e-10);
275         Assertions.assertEquals(  -1.0, fv.getX().getPartialDerivative(1).getReal(), 1.0e-15);
276         Assertions.assertEquals(  -0.1, fv.getY().getPartialDerivative(1).getReal(), 1.0e-15);
277         Assertions.assertEquals( -10.0, fv.getZ().getPartialDerivative(1).getReal(), 1.0e-15);
278         Assertions.assertEquals(  10.0, fv.getX().getPartialDerivative(2).getReal(), 1.0e-15);
279         Assertions.assertEquals(  -1.0, fv.getY().getPartialDerivative(2).getReal(), 1.0e-15);
280         Assertions.assertEquals(-100.0, fv.getZ().getPartialDerivative(2).getReal(), 1.0e-15);
281         checkPV(new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(),
282                         FieldAbsoluteDate.getGalileoEpoch(field),
283                         new FieldVector3D<>(one,  one.multiply(0.1), one.multiply(10.0)),
284                         new FieldVector3D<>(one.multiply(-1.0), one.multiply(-0.1), one.multiply(-10.0)),
285                         new FieldVector3D<>(one.multiply(10.0), one.multiply(-1.0), one.multiply(-100.0))),
286                 new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(),
287                                 FieldAbsoluteDate.getGalileoEpoch(field), fv), 1.0e-15);
288 
289         for (double dt = 0; dt < 10; dt += 0.125) {
290             Vector3D p = new PVCoordinates(new Vector3D( 1,  0.1,  10),
291                                            new Vector3D(-1, -0.1, -10),
292                                            new Vector3D(10, -1.0, -100)).shiftedBy(dt).getPosition();
293             Assertions.assertEquals(p.getX(), fv.getX().taylor(dt).getReal(), 1.0e-14);
294             Assertions.assertEquals(p.getY(), fv.getY().taylor(dt).getReal(), 1.0e-14);
295             Assertions.assertEquals(p.getZ(), fv.getZ().taylor(dt).getReal(), 1.0e-14);
296         }
297 
298         FieldAbsolutePVCoordinates<T> pv =
299                         new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(),
300                                         FieldAbsoluteDate.getGalileoEpoch(field),
301                                         fv);
302         Assertions.assertEquals(   1.0, pv.getPosition().getX().getReal(), 1.0e-10);
303         Assertions.assertEquals(   0.1, pv.getPosition().getY().getReal(), 1.0e-10);
304         Assertions.assertEquals(  10.0, pv.getPosition().getZ().getReal(), 1.0e-10);
305         Assertions.assertEquals(  -1.0, pv.getVelocity().getX().getReal(), 1.0e-15);
306         Assertions.assertEquals(  -0.1, pv.getVelocity().getY().getReal(), 1.0e-15);
307         Assertions.assertEquals( -10.0, pv.getVelocity().getZ().getReal(), 1.0e-15);
308         Assertions.assertEquals(  10.0, pv.getAcceleration().getX().getReal(), 1.0e-15);
309         Assertions.assertEquals(  -1.0, pv.getAcceleration().getY().getReal(), 1.0e-15);
310         Assertions.assertEquals(-100.0, pv.getAcceleration().getZ().getReal(), 1.0e-15);
311 
312     }
313 
314     private <T extends CalculusFieldElement<T>> void doTestToUnivariateDerivative1Vector(Field<T> field) {
315         final T one = field.getOne();
316         FieldVector3D<FieldUnivariateDerivative1<T>> fv =
317                         new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(),
318                                         FieldAbsoluteDate.getGalileoEpoch(field),
319                                         new FieldVector3D<>(one, one.multiply(0.1), one.multiply(10.0)),
320                                         new FieldVector3D<>(one.multiply(-1.0), one.multiply(-0.1), one.multiply(-10.0)),
321                                         new FieldVector3D<>(one.multiply(10.0), one.multiply(-1.0), one.multiply(-100.0))).toUnivariateDerivative1Vector();
322 
323         Assertions.assertEquals(1, fv.getX().getFreeParameters());
324         Assertions.assertEquals(1, fv.getX().getOrder());
325         Assertions.assertEquals(   1.0, fv.getX().getReal(), 1.0e-10);
326         Assertions.assertEquals(   0.1, fv.getY().getReal(), 1.0e-10);
327         Assertions.assertEquals(  10.0, fv.getZ().getReal(), 1.0e-10);
328         Assertions.assertEquals(  -1.0, fv.getX().getPartialDerivative(1).getReal(), 1.0e-15);
329         Assertions.assertEquals(  -0.1, fv.getY().getPartialDerivative(1).getReal(), 1.0e-15);
330         Assertions.assertEquals( -10.0, fv.getZ().getPartialDerivative(1).getReal(), 1.0e-15);
331         checkPV(new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(),
332                         FieldAbsoluteDate.getGalileoEpoch(field),
333                         new FieldVector3D<>(one,  one.multiply(0.1), one.multiply(10.0)),
334                         new FieldVector3D<>(one.multiply(-1.0), one.multiply(-0.1), one.multiply(-10.0)),
335                         FieldVector3D.getZero(field)),
336                 new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(),
337                                 FieldAbsoluteDate.getGalileoEpoch(field), fv), 1.0e-15);
338 
339         for (double dt = 0; dt < 10; dt += 0.125) {
340             Vector3D p = new PVCoordinates(new Vector3D( 1,  0.1,  10),
341                                            new Vector3D(-1, -0.1, -10)).shiftedBy(dt).getPosition();
342             Assertions.assertEquals(p.getX(), fv.getX().taylor(dt).getReal(), 1.0e-14);
343             Assertions.assertEquals(p.getY(), fv.getY().taylor(dt).getReal(), 1.0e-14);
344             Assertions.assertEquals(p.getZ(), fv.getZ().taylor(dt).getReal(), 1.0e-14);
345         }
346 
347         FieldAbsolutePVCoordinates<T> pv =
348                         new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(),
349                                         FieldAbsoluteDate.getGalileoEpoch(field),
350                                         fv);
351         Assertions.assertEquals(   1.0, pv.getPosition().getX().getReal(), 1.0e-10);
352         Assertions.assertEquals(   0.1, pv.getPosition().getY().getReal(), 1.0e-10);
353         Assertions.assertEquals(  10.0, pv.getPosition().getZ().getReal(), 1.0e-10);
354         Assertions.assertEquals(  -1.0, pv.getVelocity().getX().getReal(), 1.0e-15);
355         Assertions.assertEquals(  -0.1, pv.getVelocity().getY().getReal(), 1.0e-15);
356         Assertions.assertEquals( -10.0, pv.getVelocity().getZ().getReal(), 1.0e-15);
357 
358     }
359 
360     private <T extends CalculusFieldElement<T>> void doTestToUnivariateDerivative2Vector(Field<T> field) {
361         final T one = field.getOne();
362         FieldVector3D<FieldUnivariateDerivative2<T>> fv =
363                         new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(),
364                                         FieldAbsoluteDate.getGalileoEpoch(field),
365                                         new FieldVector3D<>(one, one.multiply(0.1), one.multiply(10.0)),
366                                         new FieldVector3D<>(one.multiply(-1.0), one.multiply(-0.1), one.multiply(-10.0)),
367                                         new FieldVector3D<>(one.multiply(10.0), one.multiply(-1.0), one.multiply(-100.0))).toUnivariateDerivative2Vector();
368 
369         Assertions.assertEquals(1, fv.getX().getFreeParameters());
370         Assertions.assertEquals(2, fv.getX().getOrder());
371         Assertions.assertEquals(   1.0, fv.getX().getReal(), 1.0e-10);
372         Assertions.assertEquals(   0.1, fv.getY().getReal(), 1.0e-10);
373         Assertions.assertEquals(  10.0, fv.getZ().getReal(), 1.0e-10);
374         Assertions.assertEquals(  -1.0, fv.getX().getPartialDerivative(1).getReal(), 1.0e-15);
375         Assertions.assertEquals(  -0.1, fv.getY().getPartialDerivative(1).getReal(), 1.0e-15);
376         Assertions.assertEquals( -10.0, fv.getZ().getPartialDerivative(1).getReal(), 1.0e-15);
377         Assertions.assertEquals(  10.0, fv.getX().getPartialDerivative(2).getReal(), 1.0e-15);
378         Assertions.assertEquals(  -1.0, fv.getY().getPartialDerivative(2).getReal(), 1.0e-15);
379         Assertions.assertEquals(-100.0, fv.getZ().getPartialDerivative(2).getReal(), 1.0e-15);
380         checkPV(new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(),
381                         FieldAbsoluteDate.getGalileoEpoch(field),
382                         new FieldVector3D<>(one,  one.multiply(0.1), one.multiply(10.0)),
383                         new FieldVector3D<>(one.multiply(-1.0), one.multiply(-0.1), one.multiply(-10.0)),
384                         new FieldVector3D<>(one.multiply(10.0), one.multiply(-1.0), one.multiply(-100.0))),
385                 new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(),
386                                 FieldAbsoluteDate.getGalileoEpoch(field), fv), 1.0e-15);
387 
388         for (double dt = 0; dt < 10; dt += 0.125) {
389             Vector3D p = new PVCoordinates(new Vector3D( 1,  0.1,  10),
390                                            new Vector3D(-1, -0.1, -10),
391                                            new Vector3D(10, -1.0, -100)).shiftedBy(dt).getPosition();
392             Assertions.assertEquals(p.getX(), fv.getX().taylor(dt).getReal(), 1.0e-14);
393             Assertions.assertEquals(p.getY(), fv.getY().taylor(dt).getReal(), 1.0e-14);
394             Assertions.assertEquals(p.getZ(), fv.getZ().taylor(dt).getReal(), 1.0e-14);
395         }
396 
397         FieldAbsolutePVCoordinates<T> pv =
398                         new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(),
399                                         FieldAbsoluteDate.getGalileoEpoch(field),
400                                         fv);
401         Assertions.assertEquals(   1.0, pv.getPosition().getX().getReal(), 1.0e-10);
402         Assertions.assertEquals(   0.1, pv.getPosition().getY().getReal(), 1.0e-10);
403         Assertions.assertEquals(  10.0, pv.getPosition().getZ().getReal(), 1.0e-10);
404         Assertions.assertEquals(  -1.0, pv.getVelocity().getX().getReal(), 1.0e-15);
405         Assertions.assertEquals(  -0.1, pv.getVelocity().getY().getReal(), 1.0e-15);
406         Assertions.assertEquals( -10.0, pv.getVelocity().getZ().getReal(), 1.0e-15);
407         Assertions.assertEquals(  10.0, pv.getAcceleration().getX().getReal(), 1.0e-15);
408         Assertions.assertEquals(  -1.0, pv.getAcceleration().getY().getReal(), 1.0e-15);
409         Assertions.assertEquals(-100.0, pv.getAcceleration().getZ().getReal(), 1.0e-15);
410 
411     }
412 
413     private <T extends CalculusFieldElement<T>> void doTestShift(Field<T> field) {
414         final T one = field.getOne();
415         FieldVector3D<T> p1 = new FieldVector3D<>(one, one.multiply(0.1), one.multiply(10.0));
416         FieldVector3D<T> v1 = new FieldVector3D<>(one.multiply(-1.0), one.multiply(-0.1), one.multiply(-10));
417         FieldVector3D<T> a1 = new FieldVector3D<>(one.multiply(10.0), one, one.multiply(100.0));
418         FieldVector3D<T> p2 = new FieldVector3D<>(one.multiply(7.0), one.multiply(0.7), one.multiply(70.0));
419         FieldVector3D<T> v2 = new FieldVector3D<>(one.multiply(-11.0), one.multiply(-1.1), one.multiply(-110.0));
420         FieldVector3D<T> a2 = new FieldVector3D<>(one.multiply(10.0), one, one.multiply(100.0));
421         checkPV(new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(), FieldAbsoluteDate.getJ2000Epoch(field), p2, v2, a2),
422                 new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(), FieldAbsoluteDate.getJ2000Epoch(field).shiftedBy(1.0), p1, v1, a1).shiftedBy(one.multiply(-1.0)), 1.0e-15);
423         Assertions.assertEquals(0.0, FieldAbsolutePVCoordinates.estimateVelocity(p1, p2, -1.0).subtract(new Vector3D(-6, -0.6, -60)).getNorm().getReal(), 1.0e-15);
424     }
425 
426     private <T extends CalculusFieldElement<T>> void doTestToString(Field<T> field) {
427         final T one = field.getOne();
428         FieldAbsolutePVCoordinates<T> pv =
429                         new FieldAbsolutePVCoordinates<>(FramesFactory.getEME2000(),
430                                         FieldAbsoluteDate.getJ2000Epoch(field),
431                                         new FieldVector3D<>(one.multiply(1.0),   one.multiply(0.1),  one.multiply(10.0)),
432                                         new FieldVector3D<>(one.multiply(-1.0),  one.multiply(-0.1), one.multiply(-10.0)),
433                                         new FieldVector3D<>(one.multiply(10.0),  one.multiply(1.0),  one.multiply(100.0)));
434         Assertions.assertEquals("{2000-01-01T11:58:55.816, P(1.0, 0.1, 10.0), V(-1.0, -0.1, -10.0), A(10.0, 1.0, 100.0)}", pv.toString());
435     }
436 
437     private <T extends CalculusFieldElement<T>> void doTestSamePV(Field<T> field) {
438         //setup
439         final T one = field.getOne();
440         FieldAbsoluteDate<T> date = FieldAbsoluteDate.getJ2000Epoch(field);
441         Frame frame = FramesFactory.getEME2000();
442         Frame otherEme2000 = new Frame(frame, Transform.IDENTITY, "other-EME2000");
443         FieldVector3D<T> p = new FieldVector3D<>(one.multiply(1), one.multiply(2), one.multiply(3));
444         FieldVector3D<T> v = new FieldVector3D<>(one.multiply(4), one.multiply(5), one.multiply(6));
445 
446         //action
447         FieldAbsolutePVCoordinates<T> actual = new FieldAbsolutePVCoordinates<>(frame, date, p, v);
448 
449         //verify
450         Assertions.assertSame(actual.getPosition(), actual.getPosition(frame));
451         Assertions.assertNotSame(actual.getPosition(), actual.getPosition(otherEme2000));
452         Assertions.assertEquals(0.0,
453                                 FieldVector3D.distance(actual.getPosition(frame),
454                                                        actual.getPosition(otherEme2000)).getReal(),
455                                 1.0e-15);
456         Assertions.assertEquals(0.0,
457                                 FieldVector3D.distance(actual.getPVCoordinates(frame).getPosition(),
458                                                        actual.getPVCoordinates(date, frame).getPosition()).getReal(),
459                                 1.0e-15);
460         Assertions.assertEquals(0.0,
461                                 FieldVector3D.distance(actual.getPVCoordinates(frame).getVelocity(),
462                                                        actual.getPVCoordinates(date, frame).getVelocity()).getReal(),
463                                 1.0e-15);
464         Assertions.assertEquals(0.0,
465                                 FieldVector3D.distance(actual.getPVCoordinates(frame).getAcceleration(),
466                                                        actual.getPVCoordinates(date, frame).getAcceleration()).getReal(),
467                                 1.0e-15);
468         Assertions.assertEquals(0.0,
469                                 FieldVector3D.distance(actual.getPVCoordinates(frame).getPosition(),
470                                                        actual.getPVCoordinates(date, otherEme2000).getPosition()).getReal(),
471                                 1.0e-15);
472         Assertions.assertEquals(0.0,
473                                 FieldVector3D.distance(actual.getPVCoordinates(frame).getVelocity(),
474                                                        actual.getPVCoordinates(date, otherEme2000).getVelocity()).getReal(),
475                                 1.0e-15);
476         Assertions.assertEquals(0.0,
477                                 FieldVector3D.distance(actual.getPVCoordinates(frame).getAcceleration(),
478                                                        actual.getPVCoordinates(date, otherEme2000).getAcceleration()).getReal(),
479                                 1.0e-15);
480     }
481 
482     private <T extends CalculusFieldElement<T>> void doTestTaylorProvider(Field<T> field) {
483         //setup
484         final T one = field.getOne();
485         FieldAbsoluteDate<T> date = FieldAbsoluteDate.getJ2000Epoch(field);
486         Frame frame = FramesFactory.getEME2000();
487         FieldVector3D<T> p = new FieldVector3D<>(one.multiply(1), one.multiply(2), one.multiply(3));
488         FieldVector3D<T> v = new FieldVector3D<>(one.multiply(4), one.multiply(5), one.multiply(6));
489 
490         //action
491         FieldAbsolutePVCoordinates<T> actual = new FieldAbsolutePVCoordinates<>(frame, date, p, v);
492         final FieldPVCoordinatesProvider<T> pv = actual.toTaylorProvider();
493 
494         //verify
495         Assertions.assertEquals(0.0,
496                                 FieldVector3D.distance(actual.getPosition(date, frame), pv.getPosition(date, frame)).getReal(),
497                                 1.0e-15);
498         Assertions.assertEquals(actual.getPVCoordinates(date, frame).toString(), pv.getPVCoordinates(date, frame).toString());
499     }
500 
501     private <T extends CalculusFieldElement<T>> void checkPV(FieldAbsolutePVCoordinates<T> expected, FieldAbsolutePVCoordinates<T> real, double epsilon) {
502         Assertions.assertEquals(expected.getDate(), real.getDate());
503         Assertions.assertEquals(expected.getPosition().getX().getReal(),     real.getPosition().getX().getReal(),     epsilon);
504         Assertions.assertEquals(expected.getPosition().getY().getReal(),     real.getPosition().getY().getReal(),     epsilon);
505         Assertions.assertEquals(expected.getPosition().getZ().getReal(),     real.getPosition().getZ().getReal(),     epsilon);
506         Assertions.assertEquals(expected.getVelocity().getX().getReal(),     real.getVelocity().getX().getReal(),     epsilon);
507         Assertions.assertEquals(expected.getVelocity().getY().getReal(),     real.getVelocity().getY().getReal(),     epsilon);
508         Assertions.assertEquals(expected.getVelocity().getZ().getReal(),     real.getVelocity().getZ().getReal(),     epsilon);
509         Assertions.assertEquals(expected.getAcceleration().getX().getReal(), real.getAcceleration().getX().getReal(), epsilon);
510         Assertions.assertEquals(expected.getAcceleration().getY().getReal(), real.getAcceleration().getY().getReal(), epsilon);
511         Assertions.assertEquals(expected.getAcceleration().getZ().getReal(), real.getAcceleration().getZ().getReal(), epsilon);
512     }
513 
514 }