1   /* Copyright 2002-2020 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.analytical;
18  
19  
20  import org.hipparchus.Field;
21  import org.hipparchus.RealFieldElement;
22  import org.hipparchus.exception.DummyLocalizable;
23  import org.hipparchus.exception.LocalizedCoreFormats;
24  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
25  import org.hipparchus.geometry.euclidean.threed.Vector3D;
26  import org.hipparchus.stat.descriptive.rank.Max;
27  import org.hipparchus.stat.descriptive.rank.Min;
28  import org.hipparchus.util.Decimal64Field;
29  import org.hipparchus.util.FastMath;
30  import org.hipparchus.util.MathUtils;
31  import org.hipparchus.util.Tuple;
32  import org.junit.After;
33  import org.junit.Assert;
34  import org.junit.Before;
35  import org.junit.Test;
36  import org.orekit.Utils;
37  import org.orekit.attitudes.Attitude;
38  import org.orekit.attitudes.AttitudeProvider;
39  import org.orekit.attitudes.FieldAttitude;
40  import org.orekit.attitudes.InertialProvider;
41  import org.orekit.bodies.BodyShape;
42  import org.orekit.bodies.FieldGeodeticPoint;
43  import org.orekit.bodies.GeodeticPoint;
44  import org.orekit.bodies.OneAxisEllipsoid;
45  import org.orekit.errors.OrekitException;
46  import org.orekit.frames.Frame;
47  import org.orekit.frames.FramesFactory;
48  import org.orekit.frames.TopocentricFrame;
49  import org.orekit.orbits.FieldCartesianOrbit;
50  import org.orekit.orbits.FieldCircularOrbit;
51  import org.orekit.orbits.FieldEquinoctialOrbit;
52  import org.orekit.orbits.FieldKeplerianOrbit;
53  import org.orekit.orbits.FieldOrbit;
54  import org.orekit.orbits.KeplerianOrbit;
55  import org.orekit.orbits.OrbitType;
56  import org.orekit.orbits.PositionAngle;
57  import org.orekit.propagation.FieldBoundedPropagator;
58  import org.orekit.propagation.FieldPropagator;
59  import org.orekit.propagation.FieldSpacecraftState;
60  import org.orekit.propagation.events.FieldAbstractDetector;
61  import org.orekit.propagation.events.FieldAltitudeDetector;
62  import org.orekit.propagation.events.FieldApsideDetector;
63  import org.orekit.propagation.events.FieldDateDetector;
64  import org.orekit.propagation.events.FieldElevationDetector;
65  //import org.orekit.propagation.events.AltitudeDetector;
66  //import org.orekit.propagation.events.ApsideDetector;
67  //import org.orekit.propagation.events.DateDetector;
68  //import org.orekit.propagation.events.ElevationDetector;
69  import org.orekit.propagation.events.FieldNodeDetector;
70  import org.orekit.propagation.events.handlers.FieldContinueOnEvent;
71  import org.orekit.propagation.sampling.FieldOrekitFixedStepHandler;
72  import org.orekit.propagation.sampling.FieldOrekitStepHandler;
73  import org.orekit.propagation.sampling.FieldOrekitStepHandlerMultiplexer;
74  import org.orekit.propagation.sampling.FieldOrekitStepInterpolator;
75  import org.orekit.time.AbsoluteDate;
76  import org.orekit.time.FieldAbsoluteDate;
77  import org.orekit.time.TimeScale;
78  import org.orekit.time.TimeScalesFactory;
79  import org.orekit.utils.Constants;
80  import org.orekit.utils.FieldPVCoordinates;
81  import org.orekit.utils.FieldPVCoordinatesProvider;
82  import org.orekit.utils.IERSConventions;
83  import org.orekit.utils.PVCoordinatesProvider;
84  import org.orekit.utils.TimeStampedFieldPVCoordinates;
85  import org.orekit.utils.TimeStampedPVCoordinates;
86  
87  
88  public class FieldKeplerianPropagatorTest {
89  
90      // Body mu
91      private double mu;
92  
93      @Test
94      public void testTuple() {
95  
96          AbsoluteDate initDate = AbsoluteDate.J2000_EPOCH.shiftedBy(584.);
97          KeplerianOrbit k0 = new KeplerianOrbit(7209668.0, 0.5e-4, 1.7, 2.1, 2.9,
98                                                  6.2, PositionAngle.TRUE,
99                                                  FramesFactory.getEME2000(), initDate, mu);
100         TimeStampedPVCoordinates pv0 = k0.getPVCoordinates();
101         TimeStampedPVCoordinates pv1 = new TimeStampedPVCoordinates(pv0.getDate(),
102                                                                     pv0.getPosition(),
103                                                                     pv0.getVelocity().add(new Vector3D(2.0, pv0.getVelocity().normalize())));
104         KeplerianOrbit k1 = new KeplerianOrbit(pv1, k0.getFrame(), k0.getMu());
105         FieldOrbit<Tuple> twoOrbits =
106                         new FieldKeplerianOrbit<>(new Tuple(k0.getA(),                             k1.getA()),
107                                                   new Tuple(k0.getE(),                             k1.getE()),
108                                                   new Tuple(k0.getI(),                             k1.getI()),
109                                                   new Tuple(k0.getPerigeeArgument(),               k1.getPerigeeArgument()),
110                                                   new Tuple(k0.getRightAscensionOfAscendingNode(), k1.getRightAscensionOfAscendingNode()),
111                                                   new Tuple(k0.getMeanAnomaly(),                   k1.getMeanAnomaly()),
112                                                   PositionAngle.MEAN,
113                                                   FramesFactory.getEME2000(),
114                                                   new FieldAbsoluteDate<>(initDate, new Tuple(0.0, 0.0)),
115                                                   new Tuple(mu, mu));
116         Field<Tuple> field = twoOrbits.getDate().getField();
117         FieldPropagator<Tuple> propagator = new FieldKeplerianPropagator<>(twoOrbits);
118         Min minTangential = new Min();
119         Max maxTangential = new Max();
120         Min minRadial     = new Min();
121         Max maxRadial     = new Max();
122         propagator.setMasterMode(field.getZero().add(10.0),
123                                  (s, isLast) -> {
124                                      FieldVector3D<Tuple> p = s.getPVCoordinates().getPosition();
125                                      FieldVector3D<Tuple> v = s.getPVCoordinates().getVelocity();
126                                      Vector3D p0 = new Vector3D(p.getX().getComponent(0),
127                                                                 p.getY().getComponent(0),
128                                                                 p.getZ().getComponent(0));
129                                      Vector3D v0 = new Vector3D(v.getX().getComponent(0),
130                                                                 v.getY().getComponent(0),
131                                                                 v.getZ().getComponent(0));
132                                      Vector3D t  = v0.normalize();
133                                      Vector3D r  = Vector3D.crossProduct(v0, Vector3D.crossProduct(p0, v0)).normalize();
134                                      Vector3D p1 = new Vector3D(p.getX().getComponent(1),
135                                                                 p.getY().getComponent(1),
136                                                                 p.getZ().getComponent(1));
137                                      double dT = Vector3D.dotProduct(p1.subtract(p0), t);
138                                      double dR = Vector3D.dotProduct(p1.subtract(p0), r);
139                                      minTangential.increment(dT);
140                                      maxTangential.increment(dT);
141                                      minRadial.increment(dR);
142                                      maxRadial.increment(dR);
143                                  });
144         propagator.propagate(twoOrbits.getDate().shiftedBy(Constants.JULIAN_DAY / 8));
145         Assert.assertEquals(-72525.685, minTangential.getResult(), 1.0e-3);
146         Assert.assertEquals(   926.046, maxTangential.getResult(), 1.0e-3);
147         Assert.assertEquals(   -92.800, minRadial.getResult(),     1.0e-3);
148         Assert.assertEquals(  7739.532, maxRadial.getResult(),     1.0e-3);
149         
150     }
151 
152     @Test
153     public void testSameDateCartesian() {
154         doTestSameDateCartesian(Decimal64Field.getInstance());
155     }
156 
157 
158     @Test
159     public void testSameDateKeplerian() {
160         doTestSameDateKeplerian(Decimal64Field.getInstance());
161     }
162 
163 
164     @Test
165     public void testPropagatedCartesian() {
166         doTestPropagatedCartesian(Decimal64Field.getInstance());
167     }
168 
169 
170     @Test
171     public void testPropagatedKeplerian() {
172         doTestPropagatedKeplerian(Decimal64Field.getInstance());
173     }
174 
175 
176     @Test
177     public void testAscendingNode() {
178         doTestAscendingNode(Decimal64Field.getInstance());
179     }
180 
181 
182     @Test
183     public void testStopAtTargetDate() {
184         doTestStopAtTargetDate(Decimal64Field.getInstance());
185     }
186 
187 
188     @Test
189     public void testFixedStep() {
190         doTestFixedStep(Decimal64Field.getInstance());
191     }
192 
193 
194     @Test
195     public void testVariableStep() {
196         doTestVariableStep(Decimal64Field.getInstance());
197     }
198 
199 
200     @Test
201     public void testEphemeris() {
202         doTestEphemeris(Decimal64Field.getInstance());}
203 
204 
205     @Test
206     public void testIssue14() {
207         doTestIssue14(Decimal64Field.getInstance());
208     }
209 
210 
211     @Test
212     public void testIssue107() {
213         doTestIssue107(Decimal64Field.getInstance());
214     }
215 
216 
217     @Test
218     public void testMu() {
219         doTestMu(Decimal64Field.getInstance());
220     }
221 
222     @Test
223     public void testNoDerivatives() {
224         doTestNoDerivatives(Decimal64Field.getInstance());
225     }
226 
227     @Test(expected = OrekitException.class)
228     public void testWrongAttitude() {
229         doTestWrongAttitude(Decimal64Field.getInstance());
230     }
231 
232     @Test(expected = OrekitException.class)
233     public void testStepException() {
234         doTestStepException(Decimal64Field.getInstance());
235     }
236 
237     @Test(expected = OrekitException.class)
238     public void testWrappedAttitudeException() {
239         doTestWrappedAttitudeException(Decimal64Field.getInstance());
240     }
241 
242     @Test
243     public void testPerigee() {
244         doTestPerigee(Decimal64Field.getInstance());
245     }
246 
247     @Test
248     public void testAltitude() {
249         doTestAltitude(Decimal64Field.getInstance());
250     }
251 
252     @Test
253     public void testDate() {
254         doTestDate(Decimal64Field.getInstance());
255     }
256 
257     @Test
258     public void testSetting() {
259         doTestSetting(Decimal64Field.getInstance());
260     }
261 
262     @Test
263     public void testDefaultLaw() {
264         Assert.assertSame(InertialProvider.EME2000_ALIGNED, FieldPropagator.DEFAULT_LAW);
265     }
266 
267     private <T extends RealFieldElement<T>> void doTestSameDateCartesian(Field<T> field) {
268         T zero = field.getZero();
269         // Definition of initial conditions with position and velocity
270         //------------------------------------------------------------
271         FieldVector3D<T> position = new FieldVector3D<>(zero.add(7.0e6), zero.add(1.0e6), zero.add(4.0e6));
272         FieldVector3D<T> velocity = new FieldVector3D<>(zero.add(-500.0), zero.add(8000.0), zero.add(1000.0));
273 
274         FieldAbsoluteDate<T> initDate = new FieldAbsoluteDate<>(field).shiftedBy(584.);
275         FieldOrbit<T> initialOrbit = new FieldEquinoctialOrbit<>(new FieldPVCoordinates<>(position, velocity),
276                                                                  FramesFactory.getEME2000(), initDate, zero.add(mu));
277 
278         // Extrapolator definition
279         // -----------------------
280         FieldKeplerianPropagator<T> extrapolator = new FieldKeplerianPropagator<>(initialOrbit);
281 
282         // Extrapolation at the initial date
283         // ---------------------------------
284         T delta_t = zero; // extrapolation duration in seconds
285         FieldAbsoluteDate<T> extrapDate = initDate.shiftedBy(delta_t);
286 
287         FieldSpacecraftState<T> finalOrbit = extrapolator.propagate(extrapDate);
288 
289         T a = finalOrbit.getA();
290         // another way to compute n
291         T n = a.pow(3).reciprocal().multiply(finalOrbit.getMu()).sqrt();
292 
293         Assert.assertEquals(n.getReal()*delta_t.getReal(),
294                             finalOrbit.getLM().getReal() - initialOrbit.getLM().getReal(),
295                             Utils.epsilonTest * FastMath.abs(n.getReal()*delta_t.getReal()));
296         Assert.assertEquals(MathUtils.normalizeAngle(finalOrbit.getLM().getReal(), initialOrbit.getLM().getReal()), initialOrbit.getLM().getReal(),
297                             Utils.epsilonAngle * FastMath.abs(initialOrbit.getLM().getReal()));
298 
299         Assert.assertEquals(finalOrbit.getA().getReal(), initialOrbit.getA().getReal(),
300                             Utils.epsilonTest * initialOrbit.getA().getReal());
301         Assert.assertEquals(finalOrbit.getE().getReal(), initialOrbit.getE().getReal(),
302                             Utils.epsilonE * initialOrbit.getE().getReal());
303         Assert.assertEquals(MathUtils.normalizeAngle(finalOrbit.getI().getReal(), initialOrbit.getI().getReal()),
304                             initialOrbit.getI().getReal(), Utils.epsilonAngle * FastMath.abs(initialOrbit.getI().getReal()));
305 
306     }
307 
308     private <T extends RealFieldElement<T>> void doTestSameDateKeplerian(Field<T> field) {
309         T zero = field.getZero();
310         // Definition of initial conditions with Keplerian parameters
311         //-----------------------------------------------------------
312         FieldAbsoluteDate<T> initDate = new FieldAbsoluteDate<>(field).shiftedBy(584.);
313         FieldOrbit<T> initialOrbit = new FieldKeplerianOrbit<>(zero.add(7209668.0), zero.add(0.5e-4), zero.add(1.7), zero.add(2.1), zero.add(2.9),
314                                                                zero.add(6.2), PositionAngle.TRUE,
315                                                                FramesFactory.getEME2000(), initDate, zero.add(mu));
316 
317         // Extrapolator definition
318         // -----------------------
319         FieldKeplerianPropagator<T> extrapolator = new FieldKeplerianPropagator<>(initialOrbit);
320 
321         // Extrapolation at the initial date
322         // ---------------------------------
323         T delta_t = zero; // extrapolation duration in seconds
324         FieldAbsoluteDate<T> extrapDate = initDate.shiftedBy(delta_t);
325 
326         FieldSpacecraftState<T> finalOrbit = extrapolator.propagate(extrapDate);
327 
328         T a = finalOrbit.getA();
329         // another way to compute n
330         T n = a.pow(3).reciprocal().multiply(finalOrbit.getMu()).sqrt();
331 
332         Assert.assertEquals(n.getReal()*delta_t.getReal(),
333                      finalOrbit.getLM().getReal() - initialOrbit.getLM().getReal(),
334                      Utils.epsilonTest * FastMath.max(100., FastMath.abs(n.getReal()*delta_t.getReal())));
335         Assert.assertEquals(MathUtils.normalizeAngle(finalOrbit.getLM().getReal(), initialOrbit.getLM().getReal()),
336                             initialOrbit.getLM().getReal(), Utils.epsilonAngle * FastMath.abs(initialOrbit.getLM().getReal()));
337 
338         Assert.assertEquals(finalOrbit.getA().getReal(), initialOrbit.getA().getReal(),
339                             Utils.epsilonTest * initialOrbit.getA().getReal());
340         Assert.assertEquals(finalOrbit.getE().getReal(), initialOrbit.getE().getReal(),
341                             Utils.epsilonE * initialOrbit.getE().getReal());
342         Assert.assertEquals(MathUtils.normalizeAngle(finalOrbit.getI().getReal(), initialOrbit.getI().getReal()),
343                             initialOrbit.getI().getReal(),
344                             Utils.epsilonAngle * FastMath.abs(initialOrbit.getI().getReal()));
345 
346     }
347 
348     private <T extends RealFieldElement<T>> void doTestPropagatedCartesian(Field<T> field) {
349         T zero = field.getZero();
350         // Definition of initial conditions with position and velocity
351         //------------------------------------------------------------
352         FieldVector3D<T> position = new FieldVector3D<>(zero.add(7.0e6), zero.add(1.0e6), zero.add(4.0e6));
353         FieldVector3D<T> velocity = new FieldVector3D<>(zero.add(-500.0), zero.add(8000.0), zero.add(1000.0));
354         double mu = 3.9860047e14;
355 
356         FieldAbsoluteDate<T> initDate = new FieldAbsoluteDate<>(field).shiftedBy(584.);
357         FieldOrbit<T> initialOrbit = new FieldEquinoctialOrbit<>(new FieldPVCoordinates<>(position, velocity),
358                                                                  FramesFactory.getEME2000(), initDate, zero.add(mu));
359 
360         // Extrapolator definition
361         // -----------------------
362         FieldKeplerianPropagator<T> extrapolator = new FieldKeplerianPropagator<>(initialOrbit);
363 
364         // Extrapolation at a final date different from initial date
365         // ---------------------------------------------------------
366         T delta_t = zero.add(100000.0); // extrapolation duration in seconds
367         FieldAbsoluteDate<T> extrapDate = initDate.shiftedBy(delta_t);
368 
369         FieldSpacecraftState<T> finalOrbit = extrapolator.propagate(extrapDate);
370 
371 
372         // computation of (M final - M initial) with another method
373         T a = finalOrbit.getA();
374         // another way to compute n
375         T n = a.pow(3).reciprocal().multiply(finalOrbit.getMu()).sqrt();
376 
377         Assert.assertEquals(n.getReal() * delta_t.getReal(),
378                             finalOrbit.getLM().getReal() - initialOrbit.getLM().getReal(),
379                             Utils.epsilonAngle);
380 
381         // computation of M final orbit
382         T LM = finalOrbit.getLE().subtract(
383         finalOrbit.getEquinoctialEx().multiply(finalOrbit.getLE().sin())).add(
384         finalOrbit.getEquinoctialEy().multiply(finalOrbit.getLE().cos()));
385 
386         Assert.assertEquals(LM.getReal() , finalOrbit.getLM().getReal() , Utils.epsilonAngle);
387 
388         // test of tan ((LE - Lv)/2) :
389         Assert.assertEquals(FastMath.tan((finalOrbit.getLE().getReal() - finalOrbit.getLv().getReal())/2.),
390                             tangLEmLv(finalOrbit.getLv(), finalOrbit.getEquinoctialEx(), finalOrbit.getEquinoctialEy()).getReal(),
391                             Utils.epsilonAngle);
392 
393         // test of evolution of M vs E: LM = LE - ex*sin(LE) + ey*cos(LE)
394         // with ex and ey the same for initial and final orbit
395         T deltaM = finalOrbit.getLM().subtract(initialOrbit.getLM());
396         T deltaE = finalOrbit.getLE().subtract(initialOrbit.getLE());
397         T delta  = finalOrbit.getEquinoctialEx().multiply(finalOrbit.getLE().sin().subtract(initialOrbit.getLE().sin())).subtract(
398                    finalOrbit.getEquinoctialEy().multiply(finalOrbit.getLE().cos().subtract(initialOrbit.getLE().cos())));
399 
400         Assert.assertEquals(deltaM.getReal(), deltaE.getReal() - delta.getReal(), Utils.epsilonAngle);
401 
402         // the orbital elements except for Mean/True/Eccentric latitude arguments are the same
403         Assert.assertEquals(finalOrbit.getA().getReal(), initialOrbit.getA().getReal(), Utils.epsilonTest * initialOrbit.getA().getReal());
404         Assert.assertEquals(finalOrbit.getEquinoctialEx().getReal(), initialOrbit.getEquinoctialEx().getReal(), Utils.epsilonE);
405         Assert.assertEquals(finalOrbit.getEquinoctialEy().getReal(), initialOrbit.getEquinoctialEy().getReal(), Utils.epsilonE);
406         Assert.assertEquals(finalOrbit.getHx().getReal(), initialOrbit.getHx().getReal(), Utils.epsilonAngle);
407         Assert.assertEquals(finalOrbit.getHy().getReal(), initialOrbit.getHy().getReal(), Utils.epsilonAngle);
408 
409         // for final orbit
410         T ex = finalOrbit.getEquinoctialEx();
411         T ey = finalOrbit.getEquinoctialEy();
412         T hx = finalOrbit.getHx();
413         T hy = finalOrbit.getHy();
414         T LE = finalOrbit.getLE();
415 
416         T ex2 = ex.multiply(ex);
417         T ey2 = ey.multiply(ey);
418         T hx2 = hx.multiply(hx);
419         T hy2 = hy.multiply(hy);
420         T h2p1 = hx2.add(1.).add(hy2);
421         T beta = ex2.negate().add(1.).subtract(ey2).sqrt().add(1.).reciprocal();
422 
423         T x3 = ex.negate().add(beta.negate().multiply(ey2).add(1.).multiply(LE.cos())).add(beta.multiply(ex).multiply(ey).multiply(LE.sin()));
424         T y3 = ey.negate().add(beta.negate().multiply(ex2).add(1.).multiply(LE.sin())).add(beta.multiply(ex).multiply(ey).multiply(LE.cos()));
425         // ey.negate.add(beta.negate().multiply(ex2).add(1.).multiply(LE.sin())).add(beta.multiply(ex).multiply(ey).multiply(LE.cos()));
426 
427         FieldVector3D<T> U = new FieldVector3D<>(hx2.add(1.).subtract(hy2).divide(h2p1),
428                                                  hx.multiply(2.).multiply(hy).divide(h2p1),
429                                                  hy.multiply(-2.).divide(h2p1));
430 
431         FieldVector3D<T> V = new FieldVector3D<>(hx.multiply(2.).multiply(hy).divide(h2p1),
432                                                  hy2.subtract(hx2).add(1).divide(h2p1),
433                                                  hx.multiply(2.).divide(h2p1));
434 
435         FieldVector3D<T> r = new FieldVector3D<>(finalOrbit.getA(), new FieldVector3D<>(x3, U, y3, V));
436 
437         Assert.assertEquals(finalOrbit.getPVCoordinates().getPosition().getNorm().getReal(), r.getNorm().getReal(), Utils.epsilonTest * r.getNorm().getReal());
438 
439     }
440 
441     private <T extends RealFieldElement<T>> void doTestPropagatedKeplerian(Field<T> field) {
442         T zero = field.getZero();
443         // Definition of initial conditions with Keplerian parameters
444         //-----------------------------------------------------------
445         FieldAbsoluteDate<T> initDate = new FieldAbsoluteDate<>(field).shiftedBy(584.);
446         FieldOrbit<T> initialOrbit = new FieldKeplerianOrbit<>(zero.add(7209668.0), zero.add(0.5e-4), zero.add(1.7), zero.add(2.1), zero.add(2.9),
447                                                                zero.add(6.2), PositionAngle.TRUE,
448                                                                FramesFactory.getEME2000(), initDate, zero.add(mu));
449 
450         // Extrapolator definition
451         // -----------------------
452         FieldKeplerianPropagator<T> extrapolator = new FieldKeplerianPropagator<>(initialOrbit);
453 
454         // Extrapolation at a final date different from initial date
455         // ---------------------------------------------------------
456         T delta_t = zero.add(100000.0); // extrapolation duration in seconds
457         FieldAbsoluteDate<T> extrapDate = initDate.shiftedBy(delta_t);
458 
459         FieldSpacecraftState<T> finalOrbit = extrapolator.propagate(extrapDate);
460         Assert.assertEquals(6092.3362422560844633, finalOrbit.getKeplerianPeriod().getReal(), 1.0e-12);
461         Assert.assertEquals(0.001031326088602888358, finalOrbit.getKeplerianMeanMotion().getReal(), 1.0e-16);
462 
463         // computation of (M final - M initial) with another method
464         T a = finalOrbit.getA();
465         // another way to compute n
466         T n = a.pow(3).reciprocal().multiply(finalOrbit.getMu()).sqrt();
467 
468         Assert.assertEquals(n.getReal() * delta_t.getReal(),
469                      finalOrbit.getLM().getReal() - initialOrbit.getLM().getReal(),
470                      Utils.epsilonAngle);
471 
472         // computation of M final orbit
473         T LM = finalOrbit.getLE().subtract(
474                finalOrbit.getEquinoctialEx().multiply(finalOrbit.getLE().sin())).add(
475                finalOrbit.getEquinoctialEy().multiply(finalOrbit.getLE().cos()));
476 
477         Assert.assertEquals(LM.getReal() , finalOrbit.getLM().getReal() , Utils.epsilonAngle);
478 
479         // test of tan ((LE - Lv)/2) :
480         Assert.assertEquals(FastMath.tan((finalOrbit.getLE().getReal() - finalOrbit.getLv().getReal())/2.),
481                      tangLEmLv(finalOrbit.getLv(), finalOrbit.getEquinoctialEx(), finalOrbit.getEquinoctialEy()).getReal(),
482                      Utils.epsilonAngle);
483 
484         // test of evolution of M vs E: LM = LE - ex*sin(LE) + ey*cos(LE)
485         // with ex and ey the same for initial and final orbit
486         T deltaM = finalOrbit.getLM().subtract(initialOrbit.getLM());
487         T deltaE = finalOrbit.getLE().subtract(initialOrbit.getLE());
488         T delta  = finalOrbit.getEquinoctialEx().multiply(finalOrbit.getLE().sin().subtract(initialOrbit.getLE().sin())).subtract(
489                    finalOrbit.getEquinoctialEy().multiply(finalOrbit.getLE().cos().subtract(initialOrbit.getLE().cos())));
490 
491         Assert.assertEquals(deltaM.getReal(), deltaE.getReal() - delta.getReal(), Utils.epsilonAngle);
492 
493         // the orbital elements except for Mean/True/Eccentric latitude arguments are the same
494         Assert.assertEquals(finalOrbit.getA().getReal(), initialOrbit.getA().getReal(), Utils.epsilonTest * initialOrbit.getA().getReal());
495         Assert.assertEquals(finalOrbit.getEquinoctialEx().getReal(), initialOrbit.getEquinoctialEx().getReal(), Utils.epsilonE);
496         Assert.assertEquals(finalOrbit.getEquinoctialEy().getReal(), initialOrbit.getEquinoctialEy().getReal(), Utils.epsilonE);
497         Assert.assertEquals(finalOrbit.getHx().getReal(), initialOrbit.getHx().getReal(), Utils.epsilonAngle);
498         Assert.assertEquals(finalOrbit.getHy().getReal(), initialOrbit.getHy().getReal(), Utils.epsilonAngle);
499 
500         // for final orbit
501         T ex = finalOrbit.getEquinoctialEx();
502         T ey = finalOrbit.getEquinoctialEy();
503         T hx = finalOrbit.getHx();
504         T hy = finalOrbit.getHy();
505         T LE = finalOrbit.getLE();
506 
507         T ex2 = ex.multiply(ex);
508         T ey2 = ey.multiply(ey);
509         T hx2 = hx.multiply(hx);
510         T hy2 = hy.multiply(hy);
511         T h2p1 = hx2.add(hy2).add(1.);
512         T beta = ex2.negate().add(1.).subtract(ey2).sqrt().add(1.).reciprocal();
513 
514         T x3 = ex.negate().add(beta.negate().multiply(ey2).add(1.).multiply(LE.cos())).add(beta.multiply(ex).multiply(ey).multiply(LE.sin()));
515         T y3 = ey.negate().add(beta.negate().multiply(ex2).add(1.).multiply(LE.sin())).add(beta.multiply(ex).multiply(ey).multiply(LE.cos()));
516 
517         FieldVector3D<T> U = new FieldVector3D<>(hx2.add(1.).subtract(hy2).divide(h2p1),
518                                                  hx.multiply(2.).multiply(hy).divide(h2p1),
519                                                  hy.multiply(-2).divide(h2p1));
520 
521         FieldVector3D<T> V = new FieldVector3D<>(hx.multiply(2).multiply(hy).divide(h2p1),
522                                                  hy2.subtract(hx2).add(1.).divide(h2p1),
523                                                  hx.multiply(2).divide(h2p1));
524 
525         FieldVector3D<T> r = new FieldVector3D<>(finalOrbit.getA(), new FieldVector3D<>(x3, U, y3, V));
526 
527         Assert.assertEquals(finalOrbit.getPVCoordinates().getPosition().getNorm().getReal(), r.getNorm().getReal(), Utils.epsilonTest * r.getNorm().getReal());
528 
529     }
530 
531     private <T extends RealFieldElement<T>> void doTestWrongAttitude(Field<T> field) {
532         T zero = field.getZero();
533         FieldKeplerianOrbit<T> orbit =
534             new FieldKeplerianOrbit<>(zero.add(1.0e10), zero.add(1.0e-4), zero.add(1.0e-2), zero, zero, zero, PositionAngle.TRUE,
535                                       FramesFactory.getEME2000(), new FieldAbsoluteDate<>(field), zero.add(3.986004415e14));
536         AttitudeProvider wrongLaw = new AttitudeProvider() {
537             @Override
538             public Attitude getAttitude(PVCoordinatesProvider pvProv, AbsoluteDate date, Frame frame) {
539                 throw new OrekitException(new DummyLocalizable("gasp"), new RuntimeException());
540             }
541             @Override
542             public <Q extends RealFieldElement<Q>> FieldAttitude<Q> getAttitude(FieldPVCoordinatesProvider<Q> pvProv,
543                                                                                 FieldAbsoluteDate<Q> date,
544                                                                                 Frame frame) {
545                 throw new OrekitException(new DummyLocalizable("gasp"), new RuntimeException());
546             }
547         };
548         FieldKeplerianPropagator<T> propagator = new FieldKeplerianPropagator<>(orbit, wrongLaw);
549         propagator.propagate(new FieldAbsoluteDate<>(field).shiftedBy(10.0));
550     }
551 
552     private <T extends RealFieldElement<T>> void doTestStepException(Field<T> field) {
553         T zero = field.getZero();
554         final FieldKeplerianOrbit<T> orbit =
555             new FieldKeplerianOrbit<>(zero.add(7.8e6), zero.add(0.032), zero.add(0.4), zero.add(0.1), zero.add(0.2), zero.add(0.3), PositionAngle.TRUE,
556                                       FramesFactory.getEME2000(), new FieldAbsoluteDate<>(field), zero.add(3.986004415e14));
557         FieldKeplerianPropagator<T> propagator = new FieldKeplerianPropagator<>(orbit);
558         FieldOrekitStepHandlerMultiplexer<T> multiplexer = new FieldOrekitStepHandlerMultiplexer<>();
559         propagator.setMasterMode(multiplexer);
560         multiplexer.add(new FieldOrekitStepHandler<T>() {
561             public void init(FieldSpacecraftState<T> s0, FieldAbsoluteDate<T> t) {
562             }
563             public void handleStep(FieldOrekitStepInterpolator<T> interpolator,
564                                    boolean isLast) {
565                 if (isLast) {
566                     throw new OrekitException((Throwable) null, new DummyLocalizable("dummy error"));
567                 }
568             }
569         });
570 
571         propagator.propagate(orbit.getDate().shiftedBy(-3600));
572 
573     }
574 
575     private <T extends RealFieldElement<T>> void doTestWrappedAttitudeException(Field<T> field) {
576         T zero = field.getZero();
577         final FieldKeplerianOrbit<T> orbit =
578             new FieldKeplerianOrbit<>(zero.add(7.8e6), zero.add(0.032), zero.add(0.4), zero.add(0.1), zero.add(0.2), zero.add(0.3), PositionAngle.TRUE,
579                                       FramesFactory.getEME2000(), new FieldAbsoluteDate<>(field), zero.add(3.986004415e14));
580         FieldKeplerianPropagator<T> propagator = new FieldKeplerianPropagator<>(orbit,
581                         new AttitudeProvider() {
582             public Attitude getAttitude(PVCoordinatesProvider pvProv, AbsoluteDate date, Frame frame) {
583                 throw new OrekitException((Throwable) null, new DummyLocalizable("dummy error"));
584             }
585             public <Q extends RealFieldElement<Q>> FieldAttitude<Q> getAttitude(FieldPVCoordinatesProvider<Q> pvProv,
586                                                                                 FieldAbsoluteDate<Q> date,
587                                                                                 Frame frame) {
588                 throw new OrekitException((Throwable) null, new DummyLocalizable("dummy error"));
589             }
590         });
591         propagator.propagate(orbit.getDate().shiftedBy(10.09));
592     }
593 
594     private <T extends RealFieldElement<T>> void doTestAscendingNode(Field<T> field) {
595         T zero = field.getZero();
596         final FieldKeplerianOrbit<T> orbit =
597             new FieldKeplerianOrbit<>(zero.add(7.8e6), zero.add(0.032), zero.add(0.4), zero.add(0.1), zero.add(0.2), zero.add(0.3), PositionAngle.TRUE,
598                                       FramesFactory.getEME2000(), new FieldAbsoluteDate<>(field), zero.add(3.986004415e14));
599         FieldKeplerianPropagator<T> propagator = new FieldKeplerianPropagator<>(orbit);
600         propagator.addEventDetector(new FieldNodeDetector<>(orbit, FramesFactory.getITRF(IERSConventions.IERS_2010, true)));
601         FieldAbsoluteDate<T> farTarget = new FieldAbsoluteDate<>(field).shiftedBy(10000.0);
602         FieldSpacecraftState<T> propagated = propagator.propagate(farTarget);
603         FieldPVCoordinates<T> pv = propagated.getPVCoordinates(FramesFactory.getITRF(IERSConventions.IERS_2010, true));
604         Assert.assertTrue(farTarget.durationFrom(propagated.getDate()).getReal() > 3500.0);
605         Assert.assertTrue(farTarget.durationFrom(propagated.getDate()).getReal() < 4000.0);
606         Assert.assertEquals(0, pv.getPosition().getZ().getReal(), 2.0e-6);
607         Assert.assertTrue(pv.getVelocity().getZ().getReal() > 0);
608     }
609 
610     private <T extends RealFieldElement<T>> void doTestStopAtTargetDate(Field<T> field) {
611         T zero = field.getZero();
612         final FieldKeplerianOrbit<T> orbit =
613             new FieldKeplerianOrbit<>(zero.add(7.8e6), zero.add(0.032), zero.add(0.4), zero.add(0.1), zero.add(0.2), zero.add(0.3), PositionAngle.TRUE,
614                                       FramesFactory.getEME2000(), new FieldAbsoluteDate<>(field), zero.add(3.986004415e14));
615         FieldKeplerianPropagator<T> propagator = new FieldKeplerianPropagator<>(orbit);
616         Frame itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
617         propagator.addEventDetector(new FieldNodeDetector<>(orbit, itrf).withHandler(new FieldContinueOnEvent<FieldNodeDetector<T>, T>()));
618         FieldAbsoluteDate<T> farTarget = orbit.getDate().shiftedBy(10000.0);
619         FieldSpacecraftState<T> propagated = propagator.propagate(farTarget);
620         Assert.assertEquals(0.0, FastMath.abs(farTarget.durationFrom(propagated.getDate()).getReal()), 1.0e-3);
621     }
622 
623     private <T extends RealFieldElement<T>> void doTestPerigee(Field<T> field) {
624         T zero = field.getZero();
625         final FieldKeplerianOrbit<T> orbit =
626             new FieldKeplerianOrbit<>(zero.add(7.8e6), zero.add(0.032), zero.add(0.4), zero.add(0.1), zero.add(0.2), zero.add(0.3), PositionAngle.TRUE,
627                                       FramesFactory.getEME2000(), new FieldAbsoluteDate<>(field), zero.add(3.986004415e14));
628         FieldKeplerianPropagator<T> propagator = new FieldKeplerianPropagator<>(orbit);
629         propagator.addEventDetector(new FieldApsideDetector<>(orbit));
630         FieldAbsoluteDate<T> farTarget = new FieldAbsoluteDate<>(field).shiftedBy(10000.0);
631         FieldSpacecraftState<T> propagated = propagator.propagate(farTarget);
632         FieldPVCoordinates<T> pv = propagated.getPVCoordinates(FramesFactory.getITRF(IERSConventions.IERS_2010, true));
633         Assert.assertTrue(farTarget.durationFrom(propagated.getDate()).getReal() > 3000.0);
634         Assert.assertTrue(farTarget.durationFrom(propagated.getDate()).getReal() < 3500.0);
635         Assert.assertEquals(orbit.getA().getReal() * (1.0 - orbit.getE().getReal()), pv.getPosition().getNorm().getReal(), 1.0e-6);
636     }
637 
638     private <T extends RealFieldElement<T>> void doTestAltitude(Field<T> field) {
639         T zero = field.getZero();
640         final FieldKeplerianOrbit<T> orbit =
641             new FieldKeplerianOrbit<>(zero.add(7.8e6), zero.add(0.032), zero.add(0.4), zero.add(0.1), zero.add(0.2), zero.add(0.3), PositionAngle.TRUE,
642                                       FramesFactory.getEME2000(), new FieldAbsoluteDate<>(field), zero.add(3.986004415e14));
643         FieldKeplerianPropagator<T> propagator = new FieldKeplerianPropagator<>(orbit);
644         BodyShape bodyShape =
645             new OneAxisEllipsoid(6378137.0, 1.0 / 298.257222101, FramesFactory.getITRF(IERSConventions.IERS_2010, true));
646         FieldAltitudeDetector<T> detector =
647             new FieldAltitudeDetector<>(orbit.getKeplerianPeriod().multiply(0.05),
648                                         zero.add(1500000), bodyShape);
649         Assert.assertEquals(1500000, detector.getAltitude().getReal(), 1.0e-12);
650         propagator.addEventDetector(detector);
651         FieldAbsoluteDate<T> farTarget = new FieldAbsoluteDate<>(field).shiftedBy(10000.0);
652         FieldSpacecraftState<T> propagated = propagator.propagate(farTarget);
653         Assert.assertTrue(farTarget.durationFrom(propagated.getDate()).getReal() > 5400.0);
654         Assert.assertTrue(farTarget.durationFrom(propagated.getDate()).getReal() < 5500.0);
655         FieldGeodeticPoint<T> gp = bodyShape.transform(propagated.getPVCoordinates().getPosition(),
656                                                        propagated.getFrame(), propagated.getDate());
657         Assert.assertEquals(1500000, gp.getAltitude().getReal(), 0.1);
658     }
659 
660     private <T extends RealFieldElement<T>> void doTestDate(Field<T> field) {
661         T zero = field.getZero();
662         final FieldKeplerianOrbit<T> orbit =
663             new FieldKeplerianOrbit<>(zero.add(7.8e6), zero.add(0.032), zero.add(0.4), zero.add(0.1), zero.add(0.2), zero.add(0.3), PositionAngle.TRUE,
664                                       FramesFactory.getEME2000(), new FieldAbsoluteDate<>(field), zero.add(3.986004415e14));
665         FieldKeplerianPropagator<T> propagator = new FieldKeplerianPropagator<>(orbit);
666         final FieldAbsoluteDate<T> stopDate = new FieldAbsoluteDate<>(field).shiftedBy(500.0);
667         propagator.addEventDetector(new FieldDateDetector<>(stopDate));
668         FieldAbsoluteDate<T> farTarget = new FieldAbsoluteDate<>(field).shiftedBy(10000.0);
669         FieldSpacecraftState<T> propagated = propagator.propagate(farTarget);
670         Assert.assertEquals(0, stopDate.durationFrom(propagated.getDate()).getReal(), 1.0e-10);
671     }
672 
673     private <T extends RealFieldElement<T>> void doTestSetting(Field<T> field) {
674         T zero = field.getZero();
675         final FieldKeplerianOrbit<T> orbit =
676             new FieldKeplerianOrbit<>(zero.add(7.8e6), zero.add(0.032), zero.add(0.4), zero.add(0.1), zero.add(0.2), zero.add(0.3), PositionAngle.TRUE,
677                                       FramesFactory.getEME2000(), new FieldAbsoluteDate<>(field), zero.add(3.986004415e14));
678         FieldKeplerianPropagator<T> propagator = new FieldKeplerianPropagator<>(orbit);
679         final OneAxisEllipsoid earthShape =
680             new OneAxisEllipsoid(6378136.460, 1 / 298.257222101, FramesFactory.getITRF(IERSConventions.IERS_2010, true));
681         final TopocentricFrame topo =
682             new TopocentricFrame(earthShape, new GeodeticPoint(0.389, -2.962, 0), null);
683         propagator.addEventDetector(new FieldElevationDetector<>(zero.add(60),
684                                                                  zero.add(FieldAbstractDetector.DEFAULT_THRESHOLD),
685                                                                  topo).withConstantElevation(0.09));
686         FieldAbsoluteDate<T> farTarget = new FieldAbsoluteDate<>(field).shiftedBy(10000.0);
687         FieldSpacecraftState<T> propagated = propagator.propagate(farTarget);
688         final double elevation = topo.getElevation(propagated.getPVCoordinates().getPosition().toVector3D(),
689                                                    propagated.getFrame(),
690                                                    propagated.getDate().toAbsoluteDate());
691         final T zVelocity = propagated.getPVCoordinates(topo).getVelocity().getZ();
692         Assert.assertTrue(farTarget.durationFrom(propagated.getDate()).getReal() > 7800.0);
693         Assert.assertTrue(farTarget.durationFrom(propagated.getDate()).getReal() < 7900.0);
694         Assert.assertEquals(0.09, elevation, 1.0e-9);
695         Assert.assertTrue(zVelocity.getReal() < 0);
696     }
697 
698     private <T extends RealFieldElement<T>> void doTestFixedStep(Field<T> field) {
699         T zero = field.getZero();
700         final FieldKeplerianOrbit<T> orbit =
701             new FieldKeplerianOrbit<>(zero.add(7.8e6), zero.add(0.032), zero.add(0.4), zero.add(0.1), zero.add(0.2), zero.add(0.3), PositionAngle.TRUE,
702                                       FramesFactory.getEME2000(), new FieldAbsoluteDate<>(field), zero.add(3.986004415e14));
703         FieldKeplerianPropagator<T> propagator = new FieldKeplerianPropagator<>(orbit);
704         final T step = zero.add(100.0);
705         propagator.setMasterMode(step, new FieldOrekitFixedStepHandler<T>() {
706             private FieldAbsoluteDate<T> previous;
707             public void handleStep(FieldSpacecraftState<T> currentState, boolean isLast)
708             {
709                 if (previous != null) {
710                     Assert.assertEquals(step.getReal(), currentState.getDate().durationFrom(previous).getReal(), 1.0e-10);
711                 }
712                 previous = currentState.getDate();
713             }
714         });
715         FieldAbsoluteDate<T> farTarget = new FieldAbsoluteDate<>(field).shiftedBy(10000.0);
716         propagator.propagate(farTarget);
717     }
718 
719     private <T extends RealFieldElement<T>> void doTestVariableStep(Field<T> field) {
720         T zero = field.getZero();
721         final FieldKeplerianOrbit<T> orbit =
722             new FieldKeplerianOrbit<>(zero.add(7.8e6), zero.add(0.032), zero.add(0.4), zero.add(0.1), zero.add(0.2), zero.add(0.3), PositionAngle.TRUE,
723                                       FramesFactory.getEME2000(), new FieldAbsoluteDate<>(field), zero.add(3.986004415e14));
724         FieldKeplerianPropagator<T> propagator = new FieldKeplerianPropagator<>(orbit);
725         final T step = orbit.getKeplerianPeriod().divide(100);
726         propagator.setMasterMode(new FieldOrekitStepHandler<T>() {
727             private FieldAbsoluteDate<T> previous;
728             public void init(FieldSpacecraftState<T> s0, FieldAbsoluteDate<T> t) {
729             }
730             public void handleStep(FieldOrekitStepInterpolator<T> interpolator,
731                                    boolean isLast) {
732                 if ((previous != null) && !isLast) {
733                     Assert.assertEquals(step.getReal(), interpolator.getCurrentState().getDate().durationFrom(previous).getReal(), 1.0e-10);
734                 }
735                 previous = interpolator.getCurrentState().getDate();
736             }
737         });
738         FieldAbsoluteDate<T> farTarget = new FieldAbsoluteDate<>(field).shiftedBy(10000.0);
739         propagator.propagate(farTarget);
740     }
741 
742     private <T extends RealFieldElement<T>> void doTestEphemeris(Field<T> field) {
743         T zero = field.getZero();
744         final FieldKeplerianOrbit<T> orbit =
745             new FieldKeplerianOrbit<>(zero.add(7.8e6), zero.add(0.032), zero.add(0.4), zero.add(0.1), zero.add(0.2), zero.add(0.3), PositionAngle.TRUE,
746                                       FramesFactory.getEME2000(), new FieldAbsoluteDate<>(field), zero.add(3.986004415e14));
747         FieldKeplerianPropagator<T> propagator = new FieldKeplerianPropagator<>(orbit);
748         propagator.setEphemerisMode();
749         FieldAbsoluteDate<T> farTarget = new FieldAbsoluteDate<>(field).shiftedBy(10000.0);
750         propagator.setEphemerisMode();
751         propagator.propagate(farTarget);
752         FieldBoundedPropagator<T> ephemeris = propagator.getGeneratedEphemeris();
753         Assert.assertEquals(0.0, ephemeris.getMinDate().durationFrom(orbit.getDate()).getReal(), 1.0e-10);
754         Assert.assertEquals(0.0, ephemeris.getMaxDate().durationFrom(farTarget).getReal(), 1.0e-10);
755     }
756 
757     private <T extends RealFieldElement<T>> void doTestIssue14(Field<T> field) {
758         T zero = field.getZero();
759         FieldAbsoluteDate<T> initialDate = new FieldAbsoluteDate<>(field);
760         final FieldKeplerianOrbit<T> initialOrbit =
761             new FieldKeplerianOrbit<>(zero.add(7.8e6), zero.add(0.032), zero.add(0.4), zero.add(0.1), zero.add(0.2), zero.add(0.3), PositionAngle.TRUE,
762                                       FramesFactory.getEME2000(), initialDate, zero.add(3.986004415e14));
763         FieldKeplerianPropagator<T> propagator = new FieldKeplerianPropagator<>(initialOrbit);
764 
765         propagator.setEphemerisMode();
766         propagator.propagate(initialDate.shiftedBy(initialOrbit.getKeplerianPeriod()));
767         FieldPVCoordinates<T> pv1 = propagator.getPVCoordinates(initialDate, FramesFactory.getEME2000());
768 
769         propagator.setEphemerisMode();
770         propagator.propagate(initialDate.shiftedBy(initialOrbit.getKeplerianPeriod()));
771         FieldPVCoordinates<T> pv2 = propagator.getGeneratedEphemeris().getPVCoordinates(initialDate, FramesFactory.getEME2000());
772 
773         Assert.assertEquals(0.0, pv1.getPosition().subtract(pv2.getPosition()).getNorm().getReal(), 1.0e-15);
774         Assert.assertEquals(0.0, pv1.getVelocity().subtract(pv2.getVelocity()).getNorm().getReal(), 1.0e-15);
775 
776     }
777 
778     private <T extends RealFieldElement<T>> void doTestIssue107(Field<T> field) {
779         T zero = field.getZero();
780         final TimeScale utc = TimeScalesFactory.getUTC();
781         final FieldVector3D<T> position = new FieldVector3D<>(zero.add(-6142438.668), zero.add(3492467.56), zero.add(-25767.257));
782         final FieldVector3D<T> velocity = new FieldVector3D<>(zero.add(505.848), zero.add( 942.781), zero.add(7435.922));
783         final FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, 2003, 9, 16, utc);
784         final FieldOrbit<T> orbit = new FieldCircularOrbit<>(new FieldPVCoordinates<>(position,  velocity),
785                                                              FramesFactory.getEME2000(), date, zero.add(mu));
786 
787         FieldPropagator<T> propagator = new FieldKeplerianPropagator<T>(orbit) {
788             FieldAbsoluteDate<T> lastDate = FieldAbsoluteDate.getPastInfinity(field);
789 
790             protected FieldSpacecraftState<T> basicPropagate(final FieldAbsoluteDate<T> date) {
791                 if (date.compareTo(lastDate) < 0) {
792                     throw new OrekitException(LocalizedCoreFormats.SIMPLE_MESSAGE,
793                                                    "no backward propagation allowed");
794                 }
795                 lastDate = date;
796                 return super.basicPropagate(date);
797             }
798         };
799 
800         FieldSpacecraftState<T> finalState = propagator.propagate(date.shiftedBy(3600.0));
801         Assert.assertEquals(3600.0, finalState.getDate().durationFrom(date).getReal(), 1.0e-15);
802 
803     }
804 
805     private <T extends RealFieldElement<T>> void doTestMu(Field<T> field) {
806         T zero = field.getZero();
807         final FieldKeplerianOrbit<T> orbit1 =
808                 new FieldKeplerianOrbit<>(zero.add(7.8e6), zero.add(0.032), zero.add(0.4), zero.add(0.1), zero.add(0.2), zero.add(0.3), PositionAngle.TRUE,
809                                           FramesFactory.getEME2000(), new FieldAbsoluteDate<>(field),
810                                           zero.add(Constants.WGS84_EARTH_MU));
811         final FieldKeplerianOrbit<T> orbit2 =
812                 new FieldKeplerianOrbit<>(zero.add(7.8e6), zero.add(0.032), zero.add(0.4), zero.add(0.1), zero.add(0.2), zero.add(0.3), PositionAngle.TRUE,
813                                           FramesFactory.getEME2000(), new FieldAbsoluteDate<>(field),
814                                           zero.add(Constants.EIGEN5C_EARTH_MU));
815         final FieldAbsoluteDate<T> target = orbit1.getDate().shiftedBy(10000.0);
816         FieldPVCoordinates<T> pv1       = new FieldKeplerianPropagator<>(orbit1).propagate(target).getPVCoordinates();
817         FieldPVCoordinates<T> pv2       = new FieldKeplerianPropagator<>(orbit2).propagate(target).getPVCoordinates();
818         FieldPVCoordinates<T> pvWithMu1 = new FieldKeplerianPropagator<>(orbit2, orbit1.getMu()).propagate(target).getPVCoordinates();
819         Assert.assertEquals(0.026054, FieldVector3D.distance(pv1.getPosition(), pv2.getPosition()).getReal(),       1.0e-6);
820         Assert.assertEquals(0.0,      FieldVector3D.distance(pv1.getPosition(), pvWithMu1.getPosition()).getReal(), 1.0e-15);
821     }
822 
823     private <T extends RealFieldElement<T>> void doTestNoDerivatives(Field<T> field) {
824         T zero = field.getZero();
825         for (OrbitType type : OrbitType.values()) {
826 
827             // create an initial orbit with non-Keplerian acceleration
828             final FieldAbsoluteDate<T> date         = new FieldAbsoluteDate<>(field, 2003, 9, 16, TimeScalesFactory.getUTC());
829             final FieldVector3D<T>     position     = new FieldVector3D<>(zero.add(-6142438.668),
830                                                                           zero.add(3492467.56),
831                                                                           zero.add(-25767.257));
832             final FieldVector3D<T>     velocity     = new FieldVector3D<>(zero.add(505.848),
833                                                                           zero.add(942.781),
834                                                                           zero.add(7435.922));
835             final FieldVector3D<T>     keplerAcceleration = new FieldVector3D<>(position.getNormSq().reciprocal().multiply(zero.add(mu).negate()),
836                                                                                position.normalize());
837             final FieldVector3D<T>     nonKeplerAcceleration = new FieldVector3D<>(zero.add(0.001),
838                                                                                    zero.add(0.002),
839                                                                                    zero.add(0.003));
840             final FieldVector3D<T>     acceleration = keplerAcceleration.add(nonKeplerAcceleration);
841             final TimeStampedFieldPVCoordinates<T> pva = new TimeStampedFieldPVCoordinates<>(date, position, velocity, acceleration);
842             final FieldOrbit<T> initial = type.convertType(new FieldCartesianOrbit<>(pva, FramesFactory.getEME2000(), zero.add(mu)));
843             Assert.assertEquals(type, initial.getType());
844 
845             // the derivatives are available at this stage
846             checkDerivatives(initial, true);
847 
848             FieldKeplerianPropagator<T> propagator = new FieldKeplerianPropagator<>(initial);
849             Assert.assertEquals(type, propagator.getInitialState().getOrbit().getType());
850 
851             // non-Keplerian derivatives are explicitly removed when building the Keplerian-only propagator
852             checkDerivatives(propagator.getInitialState().getOrbit(), false);
853 
854             FieldPVCoordinates<T> initPV = propagator.getInitialState().getOrbit().getPVCoordinates();
855             Assert.assertEquals(nonKeplerAcceleration.getNorm().getReal(),
856                                 FieldVector3D.distance(acceleration, initPV.getAcceleration()).getReal(),
857                                 2.0e-15);
858             Assert.assertEquals(0.0,
859                                 FieldVector3D.distance(keplerAcceleration, initPV.getAcceleration()).getReal(),
860                                 5.0e-15);
861 
862             T dt = initial.getKeplerianPeriod().multiply(0.2);
863             FieldOrbit<T> orbit = propagator.propagateOrbit(initial.getDate().shiftedBy(dt));
864             Assert.assertEquals(type, orbit.getType());
865 
866             // at the end, we don't have non-Keplerian derivatives
867             checkDerivatives(orbit, false);
868 
869             // using shiftedBy on the initial orbit, non-Keplerian derivatives would have been preserved
870             checkDerivatives(initial.shiftedBy(dt), true);
871 
872         }
873     }
874 
875     private <T extends RealFieldElement<T>> void checkDerivatives(final FieldOrbit<T> orbit,
876                                                                   final boolean expectedDerivatives) {
877         Assert.assertEquals(expectedDerivatives, orbit.hasDerivatives());
878         if (expectedDerivatives) {
879             Assert.assertNotNull(orbit.getADot());
880             Assert.assertNotNull(orbit.getEquinoctialExDot());
881             Assert.assertNotNull(orbit.getEquinoctialEyDot());
882             Assert.assertNotNull(orbit.getHxDot());
883             Assert.assertNotNull(orbit.getHyDot());
884             Assert.assertNotNull(orbit.getLEDot());
885             Assert.assertNotNull(orbit.getLvDot());
886             Assert.assertNotNull(orbit.getLMDot());
887             Assert.assertNotNull(orbit.getEDot());
888             Assert.assertNotNull(orbit.getIDot());
889         } else {
890             Assert.assertNull(orbit.getADot());
891             Assert.assertNull(orbit.getEquinoctialExDot());
892             Assert.assertNull(orbit.getEquinoctialEyDot());
893             Assert.assertNull(orbit.getHxDot());
894             Assert.assertNull(orbit.getHyDot());
895             Assert.assertNull(orbit.getLEDot());
896             Assert.assertNull(orbit.getLvDot());
897             Assert.assertNull(orbit.getLMDot());
898             Assert.assertNull(orbit.getEDot());
899             Assert.assertNull(orbit.getIDot());
900         }
901     }
902 
903     private <T extends RealFieldElement<T>> T tangLEmLv(T Lv, T ex, T ey){
904         // tan ((LE - Lv) /2)) =
905         return ey.multiply(Lv.cos()).subtract(ex.multiply(Lv.sin())).divide(
906                ex.multiply(Lv.cos()).add(1.).add(ey.multiply(Lv.sin())).add( ex.multiply(ex).negate().add(1.).subtract(ey.multiply(ey)).sqrt()));
907     }
908 
909     @Before
910     public void setUp() {
911         Utils.setDataRoot("regular-data");
912         mu  = 3.9860047e14;
913     }
914 
915     @After
916     public void tearDown() {
917         mu   = Double.NaN;
918     }
919 
920 }
921