1   /* Copyright 2022-2025 Romain Serra
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.orbits;
18  
19  import org.hipparchus.complex.Complex;
20  import org.hipparchus.complex.ComplexField;
21  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
22  import org.hipparchus.geometry.euclidean.threed.Vector3D;
23  import org.junit.jupiter.api.Assertions;
24  import org.junit.jupiter.api.Test;
25  import org.orekit.frames.FramesFactory;
26  import org.orekit.time.AbsoluteDate;
27  import org.orekit.utils.FieldPVCoordinates;
28  import org.orekit.utils.PVCoordinates;
29  
30  class KeplerianMotionCartesianUtilityTest {
31  
32      private static final double TOLERANCE_DISTANCE = 1e-14;
33      private static final double TOLERANCE_SPEED = 1e-15;
34  
35      @Test
36      void testPredictPositionVelocityElliptic() {
37          // GIVEN
38          final double mu = 1.;
39          final Vector3D position = new Vector3D(10., 1., 0.);
40          final Vector3D velocity = new Vector3D(0., 0.1, 0.2);
41          // WHEN & THEN
42          for (double dt = -10.; dt <= 10.; dt += 0.1) {
43              final PVCoordinates actualPV = KeplerianMotionCartesianUtility.predictPositionVelocity(dt, position,
44                      velocity, mu);
45              final CartesianOrbit orbit = new CartesianOrbit(new PVCoordinates(position, velocity), FramesFactory.getGCRF(),
46                      AbsoluteDate.ARBITRARY_EPOCH, mu);
47              final EquinoctialOrbit equinoctialOrbit = new EquinoctialOrbit(orbit);
48              final PVCoordinates expectedPV = equinoctialOrbit.shiftedBy(dt).getPVCoordinates();
49              comparePV(expectedPV, actualPV);
50          }
51      }
52  
53      @Test
54      void testPredictPositionVelocityHyperbolic() {
55          // GIVEN
56          final double mu = 1.;
57          final Vector3D position = new Vector3D(10., 1., 0.);
58          final Vector3D velocity = new Vector3D(0., 0.1, 1.);
59          // WHEN & THEN
60          for (double dt = -10.; dt <= 10.; dt += 0.1) {
61              final PVCoordinates actualPV = KeplerianMotionCartesianUtility.predictPositionVelocity(dt, position,
62                      velocity, mu);
63              final CartesianOrbit orbit = new CartesianOrbit(new PVCoordinates(position, velocity), FramesFactory.getGCRF(),
64                      AbsoluteDate.ARBITRARY_EPOCH, mu);
65              final KeplerianOrbit keplerianOrbit = new KeplerianOrbit(orbit);
66              final PVCoordinates expectedPV = keplerianOrbit.shiftedBy(dt).getPVCoordinates();
67              comparePV(expectedPV, actualPV);
68          }
69      }
70  
71      private void comparePV(final PVCoordinates pvCoordinates, final PVCoordinates otherPVCoordinates) {
72          final double expectedValue = 0.;
73          final PVCoordinates relativePV = new PVCoordinates(pvCoordinates, otherPVCoordinates);
74          Assertions.assertEquals(expectedValue, relativePV.getPosition().getNorm(), TOLERANCE_DISTANCE);
75          Assertions.assertEquals(expectedValue, relativePV.getVelocity().getNorm(), TOLERANCE_SPEED);
76      }
77  
78      @Test
79      void testPredictPositionVelocityEllipticField() {
80          // GIVEN
81          final ComplexField field = ComplexField.getInstance();
82          final double mu = 1.;
83          final Vector3D position = new Vector3D(6., 0., 1.);
84          final Vector3D velocity = new Vector3D(0.01, 0.1, 0.);
85          final Complex fieldMu = new Complex(mu);
86          final FieldVector3D<Complex> fieldPosition = new FieldVector3D<>(field, position);
87          final FieldVector3D<Complex> fieldVelocity = new FieldVector3D<>(field, velocity);
88          // WHEN & THEN
89          for (double dt = -10.; dt <= 10.; dt += 0.1) {
90              final FieldPVCoordinates<Complex> actualPV = KeplerianMotionCartesianUtility.predictPositionVelocity(new Complex(dt),
91                      fieldPosition, fieldVelocity, fieldMu);
92              final PVCoordinates expectedPV = KeplerianMotionCartesianUtility.predictPositionVelocity(dt, position,
93                      velocity, mu);
94              comparePV(expectedPV, actualPV.toPVCoordinates());
95          }
96      }
97  
98      @Test
99      void testPredictPositionVelocityHyperbolicField() {
100         // GIVEN
101         final ComplexField field = ComplexField.getInstance();
102         final double mu = 1.;
103         final Vector3D position = new Vector3D(6., 0., 2.);
104         final Vector3D velocity = new Vector3D(0.01, 1, 0.);
105         final Complex fieldMu = new Complex(mu);
106         final FieldVector3D<Complex> fieldPosition = new FieldVector3D<>(field, position);
107         final FieldVector3D<Complex> fieldVelocity = new FieldVector3D<>(field, velocity);
108         // WHEN & THEN
109         for (double dt = -10.; dt <= 10.; dt += 0.1) {
110             final FieldPVCoordinates<Complex> actualPV = KeplerianMotionCartesianUtility.predictPositionVelocity(new Complex(dt),
111                     fieldPosition, fieldVelocity, fieldMu);
112             final PVCoordinates expectedPV = KeplerianMotionCartesianUtility.predictPositionVelocity(dt, position,
113                     velocity, mu);
114             comparePV(expectedPV, actualPV.toPVCoordinates());
115         }
116     }
117 
118 }