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.geometry.euclidean.threed.Vector3D;
20  import org.hipparchus.util.MathUtils;
21  import org.junit.jupiter.api.Assertions;
22  import org.junit.jupiter.api.BeforeAll;
23  import org.junit.jupiter.api.Test;
24  import org.orekit.TestUtils;
25  import org.orekit.Utils;
26  import org.orekit.frames.Frame;
27  import org.orekit.frames.FramesFactory;
28  import org.orekit.time.AbsoluteDate;
29  import org.orekit.time.TimeOffset;
30  import org.orekit.time.TimeScale;
31  import org.orekit.time.TimeScalesFactory;
32  import org.orekit.utils.PVCoordinates;
33  import org.orekit.utils.TimeStampedPVCoordinates;
34  
35  import java.util.function.Function;
36  
37  
38  class OrbitTest {
39  
40      @BeforeAll
41      static void setUp() {
42          // Load orekit data
43          Utils.setDataRoot("regular-data");
44      }
45  
46      @Test
47      void testGetPosition() {
48          // GIVEN
49          final double aIn = 1.;
50          final TestOrbit testOrbit = new TestOrbit(aIn);
51          final AbsoluteDate date = testOrbit.getDate().shiftedBy(0.);
52          // WHEN
53          final Vector3D actualPosition = testOrbit.getPosition(date, testOrbit.getFrame());
54          // THEN
55          final Vector3D expectedPosition = testOrbit.getPVCoordinates(date, testOrbit.getFrame()).getPosition();
56          Assertions.assertEquals(expectedPosition, actualPosition);
57      }
58  
59      @Test
60      void testKeplerianMeanMotionAndPeriod() {
61          // GIVEN
62          final double aIn = 1.;
63          final TestOrbit testOrbit = new TestOrbit(aIn);
64          // WHEN
65          final double meanMotion = testOrbit.getKeplerianMeanMotion();
66          final double period = testOrbit.getKeplerianPeriod();
67          final double actualValue = period * meanMotion;
68          // THEN
69          final double expectedValue = MathUtils.TWO_PI;
70          Assertions.assertEquals(expectedValue, actualValue, 1e-10);
71      }
72  
73      @Test
74      void testIsElliptical() {
75          templateTestIsElliptical(1.);
76      }
77  
78      @Test
79      void testIsNotElliptical() {
80          templateTestIsElliptical(-1.);
81      }
82  
83      @Test
84      public void testIssue1557() {
85          // GIVEN
86          final Orbit fakeOrbit = TestUtils.getFakeOrbit();
87  
88          // WHEN
89          final Vector3D velocity = fakeOrbit.getVelocity();
90  
91          // THEN
92          Assertions.assertEquals(fakeOrbit.getVelocity(), velocity);
93      }
94  
95      @Test
96      void testCorrectShiftedDateWithCartesianOrbit() {
97          doTestCorrectShiftedDate(TestUtils::getDefaultOrbit);
98          doTestCorrectShiftedDate((date) -> new CartesianOrbit(TestUtils.getDefaultOrbitWithDerivatives(date)));
99      }
100 
101     @Test
102     void testCorrectShiftedDateWithKeplerianOrbit() {
103         doTestCorrectShiftedDate((date) -> new KeplerianOrbit(TestUtils.getDefaultOrbit(date)));
104         doTestCorrectShiftedDate((date) -> new KeplerianOrbit(TestUtils.getDefaultOrbitWithDerivatives(date)));
105     }
106 
107     @Test
108     void testCorrectShiftedDateWithCircularOrbit() {
109         doTestCorrectShiftedDate((date) -> new CircularOrbit(TestUtils.getDefaultOrbit(date)));
110         doTestCorrectShiftedDate((date) -> new CircularOrbit(TestUtils.getDefaultOrbitWithDerivatives(date)));
111     }
112 
113     @Test
114     void testCorrectShiftedDateWithEquinoctialOrbit() {
115        doTestCorrectShiftedDate((date) -> new EquinoctialOrbit(TestUtils.getDefaultOrbit(date)));
116         doTestCorrectShiftedDate((date) -> new EquinoctialOrbit(TestUtils.getDefaultOrbitWithDerivatives(date)));
117     }
118 
119 
120     /**
121      * Test related to issue 1883.
122      *
123      * @see <a href="https://gitlab.orekit.org/orekit/orekit/-/issues/1883">Issue 1883</a>
124      */
125     public void doTestCorrectShiftedDate(final Function<AbsoluteDate, Orbit> dateToOrbit) {
126         // GIVEN
127         // Define dates
128         final TimeScale utc  = TimeScalesFactory.getUTC();
129         final Frame     gcrf = FramesFactory.getGCRF();
130 
131         AbsoluteDate date1        = new AbsoluteDate("2025-12-15T11:11:00.000000000000000000Z", utc);
132         AbsoluteDate date2        = new AbsoluteDate("2025-12-15T14:56:00.000000000000000000Z", utc);
133         AbsoluteDate date2Shifted = date2.shiftedBy(0.123456789);
134 
135         // Define orbit
136         final Orbit orbitAtShiftedDate = dateToOrbit.apply(date2Shifted);
137 
138 
139         // WHEN
140         final TimeStampedPVCoordinates pv = orbitAtShiftedDate.getPVCoordinates(date1, gcrf);
141 
142         final AbsoluteDate actualDate = pv.getDate();
143 
144         // THEN
145         Assertions.assertEquals(0, actualDate.durationFrom(date1));
146     }
147 
148     private void templateTestIsElliptical(final double aIn) {
149         // GIVEN
150         final TestOrbit testOrbit = new TestOrbit(aIn);
151         // WHEN
152         final boolean actualValue = testOrbit.isElliptical();
153         // THEN
154         final boolean expectedValue = aIn > 0.;
155         Assertions.assertEquals(expectedValue, actualValue);
156     }
157 
158     private static class TestOrbit extends Orbit {
159 
160         final double a;
161 
162         protected TestOrbit(final double aIn) throws IllegalArgumentException {
163             super(FramesFactory.getGCRF(), AbsoluteDate.ARBITRARY_EPOCH, 1.);
164             this.a = aIn;
165         }
166 
167         @Override
168         public OrbitType getType() {
169             return null;
170         }
171 
172         @Override
173         public double getA() {
174             return this.a;
175         }
176 
177         @Override
178         public double getADot() {
179             return 0;
180         }
181 
182         @Override
183         public double getEquinoctialEx() {
184             return 0;
185         }
186 
187         @Override
188         public double getEquinoctialExDot() {
189             return 0;
190         }
191 
192         @Override
193         public double getEquinoctialEy() {
194             return 0;
195         }
196 
197         @Override
198         public double getEquinoctialEyDot() {
199             return 0;
200         }
201 
202         @Override
203         public double getHx() {
204             return 0;
205         }
206 
207         @Override
208         public double getHxDot() {
209             return 0;
210         }
211 
212         @Override
213         public double getHy() {
214             return 0;
215         }
216 
217         @Override
218         public double getHyDot() {
219             return 0;
220         }
221 
222         @Override
223         public double getLE() {
224             return 0;
225         }
226 
227         @Override
228         public double getLEDot() {
229             return 0;
230         }
231 
232         @Override
233         public double getLv() {
234             return 0;
235         }
236 
237         @Override
238         public double getLvDot() {
239             return 0;
240         }
241 
242         @Override
243         public double getLM() {
244             return 0;
245         }
246 
247         @Override
248         public double getLMDot() {
249             return 0;
250         }
251 
252         @Override
253         public double getE() {
254             return 0;
255         }
256 
257         @Override
258         public double getEDot() {
259             return 0;
260         }
261 
262         @Override
263         public double getI() {
264             return 0;
265         }
266 
267         @Override
268         public double getIDot() {
269             return 0;
270         }
271 
272         @Override
273         protected Vector3D initPosition() {
274             return new Vector3D(a, 0., 0.);
275         }
276 
277         @Override
278         protected TimeStampedPVCoordinates initPVCoordinates() {
279             return new TimeStampedPVCoordinates(getDate(), new PVCoordinates(initPosition(), Vector3D.ZERO));
280         }
281 
282         @Override
283         public Orbit inFrame(Frame inertialFrame) {
284             return null;
285         }
286 
287         @Override
288         public Orbit shiftedBy(double dt) {
289             return new TestOrbit(a);
290         }
291 
292         @Override
293         public Orbit shiftedBy(TimeOffset dt) {
294             return new TestOrbit(a);
295         }
296 
297         @Override
298         protected double[][] computeJacobianMeanWrtCartesian() {
299             return new double[0][];
300         }
301 
302         @Override
303         protected double[][] computeJacobianEccentricWrtCartesian() {
304             return new double[0][];
305         }
306 
307         @Override
308         protected double[][] computeJacobianTrueWrtCartesian() {
309             return new double[0][];
310         }
311 
312         @Override
313         public void addKeplerContribution(PositionAngleType type, double gm, double[] pDot) {
314 
315         }
316     }
317 
318 }