1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.orbits;
18
19 import java.util.function.Function;
20
21 import org.hipparchus.CalculusFieldElement;
22 import org.hipparchus.Field;
23 import org.hipparchus.analysis.differentiation.Gradient;
24 import org.hipparchus.analysis.differentiation.GradientField;
25 import org.hipparchus.complex.Complex;
26 import org.hipparchus.complex.ComplexField;
27 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
28 import org.hipparchus.geometry.euclidean.threed.Vector3D;
29 import org.hipparchus.util.Binary64;
30 import org.hipparchus.util.Binary64Field;
31 import org.hipparchus.util.MathUtils;
32 import org.junit.jupiter.api.Assertions;
33 import org.junit.jupiter.api.BeforeAll;
34 import org.junit.jupiter.api.Test;
35 import org.junit.jupiter.params.ParameterizedTest;
36 import org.junit.jupiter.params.provider.EnumSource;
37 import org.orekit.TestUtils;
38 import org.orekit.Utils;
39 import org.orekit.frames.Frame;
40 import org.orekit.frames.FramesFactory;
41 import org.orekit.frames.Predefined;
42 import org.orekit.time.AbsoluteDate;
43 import org.orekit.time.FieldAbsoluteDate;
44 import org.orekit.time.TimeScale;
45 import org.orekit.time.TimeScalesFactory;
46 import org.orekit.utils.Constants;
47 import org.orekit.utils.FieldPVCoordinates;
48 import org.orekit.utils.PVCoordinates;
49 import org.orekit.utils.TimeStampedFieldPVCoordinates;
50
51 class FieldOrbitTest {
52
53 @BeforeAll
54 static void setUp() {
55
56 Utils.setDataRoot("regular-data");
57 }
58
59 @Test
60 void testGetPosition() {
61
62 final TestFieldOrbit testFieldOrbit = new TestFieldOrbit(1.);
63 final FieldAbsoluteDate<Complex> date = testFieldOrbit.getDate().shiftedBy(0.);
64 final Frame frame = testFieldOrbit.getFrame();
65
66 final FieldVector3D<Complex> actualPosition = testFieldOrbit.getPosition(date, frame);
67
68 final FieldVector3D<Complex> expectedPosition = testFieldOrbit.getPVCoordinates(date, frame).getPosition();
69 Assertions.assertEquals(expectedPosition, actualPosition);
70 }
71
72 @ParameterizedTest
73 @EnumSource(value = Predefined.class, names = {"EME2000", "GCRF"})
74 void testGetVelocity(final Predefined predefined) {
75
76 final Orbit orbit = TestUtils.getDefaultOrbit(AbsoluteDate.ARBITRARY_EPOCH);
77 final FieldOrbit<Complex> testFieldOrbit = new FieldCartesianOrbit<>(ComplexField.getInstance(), orbit)
78 .inFrame(FramesFactory.getFrame(predefined));
79 final FieldAbsoluteDate<Complex> date = testFieldOrbit.getDate().shiftedBy(0.);
80 final Frame outputFrame = FramesFactory.getEME2000();
81
82 final FieldVector3D<Complex> actualVelocity = testFieldOrbit.getVelocity(date, outputFrame);
83
84 final FieldVector3D<Complex> expectedVelocity = testFieldOrbit.getPVCoordinates(date, outputFrame).getVelocity();
85 Assertions.assertEquals(expectedVelocity, actualVelocity);
86 }
87
88 @Test
89 void testHasNonKeplerianAccelerationDerivative() {
90
91 final GradientField field = GradientField.getField(0);
92 final Gradient mu = field.getZero().newInstance(Constants.EGM96_EARTH_MU);
93 final FieldPVCoordinates<Gradient> fieldPVCoordinates = createFieldTPVWithKeplerianAcceleration(mu);
94
95 final boolean actualResult = FieldOrbit.hasNonKeplerianAcceleration(fieldPVCoordinates, mu);
96
97 Assertions.assertFalse(actualResult);
98 }
99
100 @Test
101 void testIssue1344() {
102
103 final Binary64 mu = Binary64.ZERO.newInstance(Constants.EGM96_EARTH_MU);
104 final FieldPVCoordinates<Binary64> fieldPVCoordinates = createFieldTPVWithKeplerianAcceleration(mu);
105
106 final boolean actualResult = FieldOrbit.hasNonKeplerianAcceleration(fieldPVCoordinates, mu);
107
108 Assertions.assertFalse(actualResult);
109 }
110
111 private static <T extends CalculusFieldElement<T>> FieldPVCoordinates<T> createFieldTPVWithKeplerianAcceleration(final T mu) {
112 final Vector3D position = new Vector3D(1e6, 0, 0);
113 final Vector3D keplerianAcceleration = new Vector3D(-mu.getReal() / position.getNormSq() / position.getNorm(),
114 position);
115 return new FieldPVCoordinates<>(mu.getField(), new PVCoordinates(position, Vector3D.ZERO, keplerianAcceleration));
116 }
117
118 @Test
119 void testKeplerianMeanMotionAndPeriod() {
120
121 final double aIn = 1.;
122 final TestFieldOrbit testOrbit = new TestFieldOrbit(aIn);
123
124 final Complex meanMotion = testOrbit.getKeplerianMeanMotion();
125 final Complex period = testOrbit.getKeplerianPeriod();
126 final double actualValue = period.multiply(meanMotion).getReal();
127
128 final double expectedValue = MathUtils.TWO_PI;
129 Assertions.assertEquals(expectedValue, actualValue, 1e-10);
130 }
131
132 @Test
133 void testIsElliptical() {
134 templateTestIsElliptical(1.);
135 }
136
137 @Test
138 void testIsNotElliptical() {
139 templateTestIsElliptical(-1.);
140 }
141
142 private void templateTestIsElliptical(final double aIn) {
143
144 final TestFieldOrbit testOrbit = new TestFieldOrbit(aIn);
145
146 final boolean actualValue = testOrbit.isElliptical();
147
148 final boolean expectedValue = aIn > 0.;
149 Assertions.assertEquals(expectedValue, actualValue);
150 }
151
152 @Test
153 void testIssue1557() {
154
155 final FieldOrbit<Binary64> fakeOrbit = TestUtils.getFakeFieldOrbit();
156
157
158 final FieldVector3D<Binary64> velocity = fakeOrbit.getVelocity();
159
160
161 Assertions.assertEquals(fakeOrbit.getVelocity(), velocity);
162 }
163
164 @Test
165 void testTimeShiftIsApplied() {
166
167 final GradientField field = GradientField.getField(1);
168 final Gradient shift = Gradient.variable(1, 0, 10.);
169 final FieldAbsoluteDate<Gradient> date = new FieldAbsoluteDate<>(field, new AbsoluteDate());
170 final FieldAbsoluteDate<Gradient> shiftedDate = date.shiftedBy(shift);
171
172 final FieldOrbit<Gradient> orbit = TestUtils.getDefaultFieldOrbit(date);
173
174
175 final TimeStampedFieldPVCoordinates<Gradient>
176 pv =
177 orbit.getPVCoordinates(shiftedDate, FramesFactory.getEME2000());
178
179
180 Assertions.assertNotEquals(0, pv.getPosition().getNorm1().getGradient()[0]);
181 }
182
183 @Test
184 void testCorrectShiftedDateWithCartesianOrbit() {
185
186 final Field<Binary64> field = Binary64Field.getInstance();
187
188
189 doTestCorrectShiftedDate(TestUtils::getDefaultFieldOrbit, field);
190 }
191
192 @Test
193 void testCorrectShiftedDateWithKeplerianOrbit() {
194
195 final Field<Binary64> field = Binary64Field.getInstance();
196
197
198 doTestCorrectShiftedDate((date) -> new FieldKeplerianOrbit<>(TestUtils.getDefaultFieldOrbit(date)), field);
199 doTestCorrectShiftedDate((date) -> new FieldKeplerianOrbit<>(TestUtils.getDefaultFieldOrbitWithDerivatives(date)), field);
200 }
201
202 @Test
203 void testCorrectShiftedDateWithCircularOrbit() {
204
205 final Field<Binary64> field = Binary64Field.getInstance();
206
207
208 doTestCorrectShiftedDate((date) -> new FieldCircularOrbit<>(TestUtils.getDefaultFieldOrbit(date)), field);
209 doTestCorrectShiftedDate((date) -> new FieldCircularOrbit<>(TestUtils.getDefaultFieldOrbitWithDerivatives(date)), field);
210 }
211
212 @Test
213 void testCorrectShiftedDateWithEquinoctialOrbit() {
214
215 final Field<Binary64> field = Binary64Field.getInstance();
216
217
218 doTestCorrectShiftedDate((date) -> new FieldEquinoctialOrbit<>(TestUtils.getDefaultFieldOrbit(date)), field);
219 doTestCorrectShiftedDate((date) -> new FieldEquinoctialOrbit<>(TestUtils.getDefaultFieldOrbitWithDerivatives(date)), field);
220 }
221
222
223
224
225
226
227 public <T extends CalculusFieldElement<T>> void doTestCorrectShiftedDate(final Function<FieldAbsoluteDate<T>, FieldOrbit<T>> dateToOrbit,
228 final Field<T> field) {
229
230
231 final TimeScale utc = TimeScalesFactory.getUTC();
232 final Frame gcrf = FramesFactory.getGCRF();
233
234
235 AbsoluteDate date1 = new AbsoluteDate("2025-12-15T11:11:00.000000000000000000Z", utc);
236 AbsoluteDate date2 = new AbsoluteDate("2025-12-15T14:56:00.000000000000000000Z", utc);
237
238 FieldAbsoluteDate<T> fieldDate1 = new FieldAbsoluteDate<>(field, date1);
239 FieldAbsoluteDate<T> fieldDate2 = new FieldAbsoluteDate<>(field, date2);
240 FieldAbsoluteDate<T> fieldDate2Shifted = fieldDate2.shiftedBy(0.123456789);
241
242
243 final FieldOrbit<T> orbitAtShiftedDate = dateToOrbit.apply(fieldDate2Shifted);
244
245
246 final TimeStampedFieldPVCoordinates<T> pv =
247 orbitAtShiftedDate.getPVCoordinates(fieldDate1, gcrf);
248 final FieldAbsoluteDate<T> actualDate = pv.getDate();
249
250
251 Assertions.assertEquals(0, actualDate.durationFrom(date1).getReal());
252 }
253
254 private static class TestFieldOrbit extends FieldOrbit<Complex> {
255
256 final Complex a;
257
258 protected TestFieldOrbit(final double aIn)
259 throws IllegalArgumentException {
260 super(FramesFactory.getGCRF(), FieldAbsoluteDate.getArbitraryEpoch(ComplexField.getInstance()), Complex.ONE);
261 a = new Complex(aIn, 0.);
262 }
263
264 @Override
265 public OrbitType getType() {
266 return null;
267 }
268
269 @Override
270 public Orbit toOrbit() {
271 return null;
272 }
273
274 @Override
275 public Complex getA() {
276 return this.a;
277 }
278
279 @Override
280 public Complex getADot() {
281 return null;
282 }
283
284 @Override
285 public Complex getEquinoctialEx() {
286 return null;
287 }
288
289 @Override
290 public Complex getEquinoctialExDot() {
291 return null;
292 }
293
294 @Override
295 public Complex getEquinoctialEy() {
296 return null;
297 }
298
299 @Override
300 public Complex getEquinoctialEyDot() {
301 return null;
302 }
303
304 @Override
305 public Complex getHx() {
306 return null;
307 }
308
309 @Override
310 public Complex getHxDot() {
311 return null;
312 }
313
314 @Override
315 public Complex getHy() {
316 return null;
317 }
318
319 @Override
320 public Complex getHyDot() {
321 return null;
322 }
323
324 @Override
325 public Complex getLE() {
326 return null;
327 }
328
329 @Override
330 public Complex getLEDot() {
331 return null;
332 }
333
334 @Override
335 public Complex getLv() {
336 return null;
337 }
338
339 @Override
340 public Complex getLvDot() {
341 return null;
342 }
343
344 @Override
345 public Complex getLM() {
346 return null;
347 }
348
349 @Override
350 public Complex getLMDot() {
351 return null;
352 }
353
354 @Override
355 public Complex getE() {
356 return null;
357 }
358
359 @Override
360 public Complex getEDot() {
361 return null;
362 }
363
364 @Override
365 public Complex getI() {
366 return null;
367 }
368
369 @Override
370 public Complex getIDot() {
371 return null;
372 }
373
374 @Override
375 public boolean hasNonKeplerianAcceleration() {
376 return false;
377 }
378
379 @Override
380 protected FieldVector3D<Complex> initPosition() {
381 return new FieldVector3D<>(getField(), new Vector3D(a.getReal(), 0., 0.));
382 }
383
384 @Override
385 protected TimeStampedFieldPVCoordinates<Complex> initPVCoordinates() {
386 final FieldPVCoordinates<Complex> fieldPVCoordinates = new FieldPVCoordinates<>(initPosition(),
387 FieldVector3D.getZero(getField()));
388 return new TimeStampedFieldPVCoordinates<>(getDate(), fieldPVCoordinates);
389 }
390
391 @Override
392 public FieldOrbit<Complex> inFrame(Frame inertialFrame) {
393 return null;
394 }
395
396 @Override
397 public FieldOrbit<Complex> shiftedBy(Complex dt) {
398 return shiftedBy(dt.getReal());
399 }
400
401 @Override
402 public FieldOrbit<Complex> shiftedBy(double dt) {
403 return new TestFieldOrbit(a.getReal());
404 }
405
406 @Override
407 protected Complex[][] computeJacobianMeanWrtCartesian() {
408 return null;
409 }
410
411 @Override
412 protected Complex[][] computeJacobianEccentricWrtCartesian() {
413 return null;
414 }
415
416 @Override
417 protected Complex[][] computeJacobianTrueWrtCartesian() {
418 return null;
419 }
420
421 @Override
422 public void addKeplerContribution(PositionAngleType type, Complex gm, Complex[] pDot) {
423
424 }
425
426 }
427
428 }