1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation;
18
19 import org.hipparchus.analysis.polynomials.PolynomialFunction;
20 import org.hipparchus.exception.LocalizedCoreFormats;
21 import org.hipparchus.exception.MathIllegalStateException;
22 import org.hipparchus.geometry.euclidean.threed.Rotation;
23 import org.hipparchus.geometry.euclidean.threed.Vector3D;
24 import org.hipparchus.ode.ODEIntegrator;
25 import org.hipparchus.ode.events.Action;
26 import org.hipparchus.ode.nonstiff.DormandPrince853Integrator;
27 import org.hipparchus.util.FastMath;
28 import org.junit.jupiter.api.AfterEach;
29 import org.junit.jupiter.api.Assertions;
30 import org.junit.jupiter.api.BeforeEach;
31 import org.junit.jupiter.api.Test;
32 import org.junit.jupiter.params.ParameterizedTest;
33 import org.junit.jupiter.params.provider.ValueSource;
34 import org.mockito.Mockito;
35 import org.orekit.TestUtils;
36 import org.orekit.Utils;
37 import org.orekit.attitudes.Attitude;
38 import org.orekit.attitudes.AttitudeProvider;
39 import org.orekit.attitudes.BodyCenterPointing;
40 import org.orekit.attitudes.FrameAlignedProvider;
41 import org.orekit.bodies.OneAxisEllipsoid;
42 import org.orekit.errors.OrekitException;
43 import org.orekit.errors.OrekitMessages;
44 import org.orekit.frames.FramesFactory;
45 import org.orekit.frames.StaticTransform;
46 import org.orekit.frames.Transform;
47 import org.orekit.orbits.KeplerianOrbit;
48 import org.orekit.orbits.Orbit;
49 import org.orekit.orbits.PositionAngleType;
50 import org.orekit.propagation.analytical.EcksteinHechlerPropagator;
51 import org.orekit.propagation.analytical.KeplerianPropagator;
52 import org.orekit.propagation.events.DateDetector;
53 import org.orekit.propagation.events.EventDetector;
54 import org.orekit.propagation.events.handlers.EventHandler;
55 import org.orekit.propagation.numerical.NumericalPropagator;
56 import org.orekit.time.AbsoluteDate;
57 import org.orekit.time.DateComponents;
58 import org.orekit.time.TimeComponents;
59 import org.orekit.time.TimeOffset;
60 import org.orekit.time.TimeScalesFactory;
61 import org.orekit.utils.*;
62
63 import java.text.ParseException;
64
65
66 class SpacecraftStateTest {
67
68 @Test
69 void testWithAttitudeAbsolutePV() {
70
71 final AbsolutePVCoordinates absolutePVCoordinates = new AbsolutePVCoordinates(FramesFactory.getEME2000(),
72 AbsoluteDate.ARBITRARY_EPOCH, new PVCoordinates());
73 final SpacecraftState state = new SpacecraftState(absolutePVCoordinates);
74 final Attitude attitude = Mockito.mock(Attitude.class);
75 Mockito.when(attitude.getDate()).thenReturn(state.getDate());
76 Mockito.when(attitude.getReferenceFrame()).thenReturn(state.getFrame());
77
78 final SpacecraftState stateWithAttitude = state.withAttitude(attitude);
79
80 Assertions.assertEquals(attitude, stateWithAttitude.getAttitude());
81 Assertions.assertEquals(state.getMass(), stateWithAttitude.getMass());
82 Assertions.assertEquals(state.getAbsPVA(), stateWithAttitude.getAbsPVA());
83 }
84
85 @Test
86 void testWithMassAbsolutePV() {
87
88 final AbsolutePVCoordinates absolutePVCoordinates = new AbsolutePVCoordinates(FramesFactory.getEME2000(),
89 AbsoluteDate.ARBITRARY_EPOCH, new PVCoordinates());
90 final SpacecraftState state = new SpacecraftState(absolutePVCoordinates);
91 final double expectedMass = 123;
92
93 final SpacecraftState stateWithMass = state.withMass(expectedMass);
94
95 Assertions.assertEquals(expectedMass, stateWithMass.getMass());
96 Assertions.assertEquals(state.getAttitude(), stateWithMass.getAttitude());
97 Assertions.assertEquals(state.getAbsPVA(), stateWithMass.getAbsPVA());
98 }
99
100 @Test
101 void testWithMassRateAbsolutePV() {
102
103 final AbsolutePVCoordinates absolutePVCoordinates = new AbsolutePVCoordinates(FramesFactory.getEME2000(),
104 AbsoluteDate.ARBITRARY_EPOCH, new PVCoordinates());
105 final SpacecraftState state = new SpacecraftState(absolutePVCoordinates);
106 final double expectedMassRate = 123;
107
108 final SpacecraftState stateWithMassRate = state.withMassRate(expectedMassRate);
109
110 Assertions.assertEquals(expectedMassRate, stateWithMassRate.getMassRate());
111 Assertions.assertEquals(state.getMass(), stateWithMassRate.getMass());
112 Assertions.assertEquals(state.getAttitude(), stateWithMassRate.getAttitude());
113 Assertions.assertEquals(state.getAbsPVA(), stateWithMassRate.getAbsPVA());
114 }
115
116 @Test
117 void testWithAdditionalDataAndAbsolutePV() {
118
119 final AbsolutePVCoordinates absolutePVCoordinates = new AbsolutePVCoordinates(FramesFactory.getEME2000(),
120 AbsoluteDate.ARBITRARY_EPOCH, new PVCoordinates());
121 final SpacecraftState state = new SpacecraftState(absolutePVCoordinates);
122 final DataDictionary dictionary = Mockito.mock(DataDictionary.class);
123
124 final SpacecraftState stateWithData = state.withAdditionalData(dictionary);
125
126 Assertions.assertEquals(dictionary.getData(), stateWithData.getAdditionalDataValues().getData());
127 Assertions.assertEquals(state.getMass(), stateWithData.getMass());
128 Assertions.assertEquals(state.getAttitude(), stateWithData.getAttitude());
129 Assertions.assertEquals(state.getAbsPVA(), stateWithData.getAbsPVA());
130 }
131
132 @Test
133 void testWithAdditionalStatesDerivativesAndAbsolutePV() {
134
135 final AbsolutePVCoordinates absolutePVCoordinates = new AbsolutePVCoordinates(FramesFactory.getEME2000(),
136 AbsoluteDate.ARBITRARY_EPOCH, new PVCoordinates());
137 final SpacecraftState state = new SpacecraftState(absolutePVCoordinates);
138 final DoubleArrayDictionary dictionary = Mockito.mock(DoubleArrayDictionary.class);
139
140 final SpacecraftState stateWithDerivatives = state.withAdditionalStatesDerivatives(dictionary);
141
142 Assertions.assertEquals(dictionary.getData(), stateWithDerivatives.getAdditionalStatesDerivatives().getData());
143 Assertions.assertEquals(state.getAbsPVA(), stateWithDerivatives.getAbsPVA());
144 Assertions.assertEquals(state.getAttitude(), stateWithDerivatives.getAttitude());
145 Assertions.assertEquals(state.getMass(), stateWithDerivatives.getMass());
146 }
147
148 @Test
149 void testWithAttitudeAndOrbit() {
150
151 final SpacecraftState state = new SpacecraftState(orbit);
152 final Attitude attitude = Mockito.mock(Attitude.class);
153 Mockito.when(attitude.getDate()).thenReturn(state.getDate());
154 Mockito.when(attitude.getReferenceFrame()).thenReturn(state.getFrame());
155
156 final SpacecraftState stateWithAttitude = state.withAttitude(attitude);
157
158 Assertions.assertEquals(attitude, stateWithAttitude.getAttitude());
159 Assertions.assertEquals(state.getMass(), stateWithAttitude.getMass());
160 Assertions.assertEquals(state.getOrbit(), stateWithAttitude.getOrbit());
161 }
162
163 @Test
164 void testWithMassAndOrbit() {
165
166 final SpacecraftState state = new SpacecraftState(orbit);
167 final double expectedMass = 123;
168
169 final SpacecraftState stateWithMass = state.withMass(expectedMass);
170
171 Assertions.assertEquals(expectedMass, stateWithMass.getMass());
172 Assertions.assertEquals(state.getAttitude(), stateWithMass.getAttitude());
173 Assertions.assertEquals(state.getOrbit(), stateWithMass.getOrbit());
174 }
175
176 @Test
177 void testWithMassRateAndOrbit() {
178
179 final SpacecraftState state = new SpacecraftState(orbit);
180 final double expectedMassRate = 123;
181
182 final SpacecraftState stateWithMassRate = state.withMassRate(expectedMassRate);
183
184 Assertions.assertEquals(expectedMassRate, stateWithMassRate.getMassRate());
185 Assertions.assertEquals(state.getMass(), stateWithMassRate.getMass());
186 Assertions.assertEquals(state.getAttitude(), stateWithMassRate.getAttitude());
187 Assertions.assertEquals(state.getOrbit(), stateWithMassRate.getOrbit());
188 }
189
190 @Test
191 void testWithAdditionalDataAndOrbit() {
192
193 final SpacecraftState state = new SpacecraftState(orbit);
194 final DataDictionary dictionary = Mockito.mock(DataDictionary.class);
195
196 final SpacecraftState stateWithData = state.withAdditionalData(dictionary);
197
198 Assertions.assertEquals(dictionary, stateWithData.getAdditionalDataValues());
199 Assertions.assertEquals(state.getMass(), stateWithData.getMass());
200 Assertions.assertEquals(state.getAttitude(), stateWithData.getAttitude());
201 Assertions.assertEquals(state.getOrbit(), stateWithData.getOrbit());
202 }
203
204 @Test
205 void testWithAdditionalStatesDerivativesAndOrbit() {
206
207 final SpacecraftState state = new SpacecraftState(orbit);
208 final DoubleArrayDictionary dictionary = Mockito.mock(DoubleArrayDictionary.class);
209
210 final SpacecraftState stateWithDerivatives = state.withAdditionalStatesDerivatives(dictionary);
211
212 Assertions.assertEquals(dictionary.getData(), stateWithDerivatives.getAdditionalStatesDerivatives().getData());
213 Assertions.assertEquals(state.getOrbit(), stateWithDerivatives.getOrbit());
214 Assertions.assertEquals(state.getAttitude(), stateWithDerivatives.getAttitude());
215 Assertions.assertEquals(state.getMass(), stateWithDerivatives.getMass());
216 }
217
218 @ParameterizedTest
219 @ValueSource(booleans = {true, false})
220 void testShiftedByOrbit(final boolean useTimeOffset) {
221
222 final Attitude attitude = new FrameAlignedProvider(orbit.getFrame()).getAttitude(orbit, orbit.getDate(), orbit.getFrame());
223 final SpacecraftState state = new SpacecraftState(orbit, attitude).withMassRate(1e-3);
224 final double dt = 1.;
225
226 final SpacecraftState shiftedState;
227 if (useTimeOffset) {
228 shiftedState = state.shiftedBy(new TimeOffset(dt));
229 } else {
230 shiftedState = state.shiftedBy(dt);
231 }
232
233 Assertions.assertEquals(state.getDate().shiftedBy(dt), shiftedState.getDate());
234 Assertions.assertEquals(state.getOrbit().shiftedBy(dt).getPosition(), shiftedState.getOrbit().getPosition());
235 Assertions.assertEquals(state.getAttitude().shiftedBy(dt).getSpin(), shiftedState.getAttitude().getSpin());
236 Assertions.assertEquals(state.getMass() + dt * state.getMassRate(), shiftedState.getMass());
237 Assertions.assertEquals(state.getMassRate(), shiftedState.getMassRate());
238 }
239
240 @ParameterizedTest
241 @ValueSource(booleans = {true, false})
242 void testShiftedByAbsPV(final boolean useTimeOffset) {
243
244 final AbsolutePVCoordinates absPva = new AbsolutePVCoordinates(orbit.getFrame(), orbit.getDate(),
245 orbit.getPVCoordinates());
246 final Attitude attitude = new FrameAlignedProvider(absPva.getFrame()).getAttitude(absPva, absPva.getDate(), absPva.getFrame());
247 final SpacecraftState state = new SpacecraftState(absPva, attitude).withMassRate(1e-3);
248 final double dt = 1.;
249
250 final SpacecraftState shiftedState;
251 if (useTimeOffset) {
252 shiftedState = state.shiftedBy(new TimeOffset(dt));
253 } else {
254 shiftedState = state.shiftedBy(dt);
255 }
256
257 Assertions.assertEquals(state.getDate().shiftedBy(dt), shiftedState.getDate());
258 Assertions.assertEquals(state.getAbsPVA().shiftedBy(dt).getPosition(), shiftedState.getAbsPVA().getPosition());
259 Assertions.assertEquals(state.getAttitude().shiftedBy(dt).getSpin(), shiftedState.getAttitude().getSpin());
260 Assertions.assertEquals(state.getMass() + dt * state.getMassRate(), shiftedState.getMass());
261 Assertions.assertEquals(state.getMassRate(), shiftedState.getMassRate());
262 }
263
264 @Test
265 void testToString() {
266
267 final SpacecraftState state = new SpacecraftState(orbit);
268
269 final String string = state.toString();
270
271 Assertions.assertTrue(string.contains("orbit"));
272 Assertions.assertTrue(string.contains("mass"));
273 Assertions.assertTrue(string.contains("massRate"));
274 Assertions.assertTrue(string.contains("attitude"));
275 Assertions.assertTrue(string.contains("additional"));
276 }
277
278 @Test
279 void testShiftVsEcksteinHechlerError()
280 throws OrekitException {
281
282
283
284
285
286
287
288
289
290
291
292 PolynomialFunction pModel = new PolynomialFunction(1.5664070631933846e-01, 7.5504722733047560e-03, -8.2460562451009510e-05,
293 6.9546332080305580e-06, -1.7045365367533077e-09, -4.2187860791066264e-13);
294 PolynomialFunction vModel = new PolynomialFunction(-3.5472364019908720e-04, 1.6568103861124980e-05, 1.9637913327830596e-05,
295 -3.4248792843039766e-09, -5.6565135131014254e-12, 1.4730170946808630e-15);
296 PolynomialFunction aModel = new PolynomialFunction(3.0731707577766896e-06, 3.9770746399850350e-05, 1.9779039254538660e-09,
297 8.0263328220724900e-12, -1.5600835252366078e-14, 1.1785257001549687e-18);
298 PolynomialFunction rModel = new PolynomialFunction(-2.7689062063188115e-06, 1.7406542538258334e-07, 2.5109795349592287e-09,
299 2.0399322661074575e-11, 9.9126348912426750e-15, -3.5015638905729510e-18);
300
301 AbsoluteDate centerDate = orbit.getDate().shiftedBy(100.0);
302 SpacecraftState centerState = propagator.propagate(centerDate);
303 double maxResidualP = 0;
304 double maxResidualV = 0;
305 double maxResidualA = 0;
306 double maxResidualR = 0;
307 final double dtStep = 5;
308 for (double dt = dtStep; dt < 900.0; dt += dtStep) {
309 SpacecraftState shifted = centerState.shiftedBy(dt);
310 SpacecraftState propagated = propagator.propagate(centerDate.shiftedBy(dt));
311 PVCoordinates dpv = new PVCoordinates(propagated.getPVCoordinates(), shifted.getPVCoordinates());
312 double residualP = pModel.value(dt) - dpv.getPosition().getNorm();
313 double residualV = vModel.value(dt) - dpv.getVelocity().getNorm();
314 double residualA = aModel.value(dt) - dpv.getAcceleration().getNorm();
315 double residualR = rModel.value(dt) -
316 FastMath.toDegrees(Rotation.distance(shifted.getAttitude().getRotation(),
317 propagated.getAttitude().getRotation()));
318 maxResidualP = FastMath.max(maxResidualP, FastMath.abs(residualP));
319 maxResidualV = FastMath.max(maxResidualV, FastMath.abs(residualV));
320 maxResidualA = FastMath.max(maxResidualA, FastMath.abs(residualA));
321 maxResidualR = FastMath.max(maxResidualR, FastMath.abs(residualR));
322
323 }
324
325 Assertions.assertEquals(0.40, maxResidualP, 0.01);
326 Assertions.assertEquals(4.9e-4, maxResidualV, 1.0e-5);
327 Assertions.assertEquals(7.7e-6, maxResidualA, 1.0e-7);
328 Assertions.assertEquals(2.8e-6, maxResidualR, 1.0e-1);
329
330 }
331
332 @Test
333 void testDatesConsistency() {
334 Assertions.assertThrows(IllegalArgumentException.class, () -> {
335 new SpacecraftState(orbit, attitudeLaw.getAttitude(orbit.shiftedBy(10.0),
336 orbit.getDate().shiftedBy(10.0), orbit.getFrame()));
337 });
338 }
339
340
341
342
343
344 @Test
345 void testDateConsistencyClose() {
346
347 Orbit orbit10Shifts = orbit;
348 for (int i = 0; i < 10; i++) {
349 orbit10Shifts = orbit10Shifts.shiftedBy(0.1);
350 }
351 final Orbit orbit1Shift = orbit.shiftedBy(1);
352 Attitude shiftedAttitude = attitudeLaw.getAttitude(orbit1Shift, orbit1Shift.getDate(), orbit.getFrame());
353
354
355 Assertions.assertEquals(shiftedAttitude.getDate(), orbit10Shifts.getDate());
356
357
358 new SpacecraftState(orbit10Shifts, shiftedAttitude);
359 }
360
361 @Test
362 void testFramesConsistency() {
363 Assertions.assertThrows(IllegalArgumentException.class, () -> {
364 new SpacecraftState(orbit,
365 new Attitude(orbit.getDate(),
366 FramesFactory.getGCRF(),
367 Rotation.IDENTITY, Vector3D.ZERO, Vector3D.ZERO));
368 });
369 }
370
371 @Test
372 void testTransform()
373 throws ParseException, OrekitException {
374
375 double maxDP = 0;
376 double maxDV = 0;
377 double maxDA = 0;
378 for (double t = 0; t < orbit.getKeplerianPeriod(); t += 60) {
379 final SpacecraftState state = propagator.propagate(orbit.getDate().shiftedBy(t));
380 final Transform transform = state.toTransform().getInverse();
381 PVCoordinates pv = transform.transformPVCoordinates(PVCoordinates.ZERO);
382 PVCoordinates dPV = new PVCoordinates(pv, state.getPVCoordinates());
383 Vector3D mZDirection = transform.transformVector(Vector3D.MINUS_K);
384 double alpha = Vector3D.angle(mZDirection, state.getPosition());
385 maxDP = FastMath.max(maxDP, dPV.getPosition().getNorm());
386 maxDV = FastMath.max(maxDV, dPV.getVelocity().getNorm());
387 maxDA = FastMath.max(maxDA, FastMath.toDegrees(alpha));
388 }
389 Assertions.assertEquals(0.0, maxDP, 1.0e-6);
390 Assertions.assertEquals(0.0, maxDV, 1.0e-9);
391 Assertions.assertEquals(0.0, maxDA, 1.0e-12);
392
393 }
394
395 @Test
396 void testGetAdditionalStateBadType() {
397 final SpacecraftState state = new SpacecraftState(orbit).addAdditionalData("string", "hello there");
398 OrekitException exception = Assertions.assertThrows(OrekitException.class, () -> state.getAdditionalState("string"));
399 Assertions.assertEquals(OrekitMessages.ADDITIONAL_STATE_BAD_TYPE, exception.getSpecifier());
400 Assertions.assertEquals("string", exception.getParts()[0]);
401 }
402
403 @Test
404 void testAdditionalStates() {
405 final SpacecraftState state = propagator.propagate(orbit.getDate().shiftedBy(60));
406 final SpacecraftState extended =
407 state.
408 addAdditionalData("test-1", new double[] { 1.0, 2.0 }).
409 addAdditionalData("test-2", 42.0);
410 Assertions.assertEquals(0, state.getAdditionalDataValues().size());
411 Assertions.assertFalse(state.hasAdditionalData("test-1"));
412 try {
413 state.getAdditionalState("test-1");
414 Assertions.fail("an exception should have been thrown");
415 } catch (OrekitException oe) {
416 Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
417 Assertions.assertEquals(oe.getParts()[0], "test-1");
418 }
419 try {
420 state.ensureCompatibleAdditionalStates(extended);
421 Assertions.fail("an exception should have been thrown");
422 } catch (OrekitException oe) {
423 Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
424 Assertions.assertTrue(oe.getParts()[0].toString().startsWith("test-"));
425 }
426 try {
427 extended.ensureCompatibleAdditionalStates(state);
428 Assertions.fail("an exception should have been thrown");
429 } catch (OrekitException oe) {
430 Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
431 Assertions.assertTrue(oe.getParts()[0].toString().startsWith("test-"));
432 }
433 try {
434 extended.ensureCompatibleAdditionalStates(extended.addAdditionalData("test-2", new double[7]));
435 Assertions.fail("an exception should have been thrown");
436 } catch (MathIllegalStateException mise) {
437 Assertions.assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, mise.getSpecifier());
438 Assertions.assertEquals(7, ((Integer) mise.getParts()[0]).intValue());
439 }
440 Assertions.assertEquals(2, extended.getAdditionalDataValues().getData().size());
441 Assertions.assertTrue(extended.hasAdditionalData("test-1"));
442 Assertions.assertTrue(extended.hasAdditionalData("test-2"));
443 Assertions.assertEquals( 1.0, extended.getAdditionalState("test-1")[0], 1.0e-15);
444 Assertions.assertEquals( 2.0, extended.getAdditionalState("test-1")[1], 1.0e-15);
445 Assertions.assertEquals(42.0, extended.getAdditionalState("test-2")[0], 1.0e-15);
446
447
448 DataDictionary dictionary = new DataDictionary();
449 dictionary.put("test-3", new double[] { -6.0 });
450 SpacecraftState sO = new SpacecraftState(state.getOrbit()).withAdditionalData(dictionary);
451 Assertions.assertEquals(-6.0, sO.getAdditionalState("test-3")[0], 1.0e-15);
452
453 }
454
455 @Test
456 void testAdditionalStatesDerivatives() {
457 final SpacecraftState state = propagator.propagate(orbit.getDate().shiftedBy(60));
458 final SpacecraftState extended =
459 state.
460 addAdditionalStateDerivative("test-1", new double[] { 1.0, 2.0 }).
461 addAdditionalStateDerivative("test-2", 42.0);
462 Assertions.assertEquals(0, state.getAdditionalStatesDerivatives().size());
463 Assertions.assertFalse(state.hasAdditionalStateDerivative("test-1"));
464 try {
465 state.getAdditionalStateDerivative("test-1");
466 Assertions.fail("an exception should have been thrown");
467 } catch (OrekitException oe) {
468 Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
469 Assertions.assertEquals(oe.getParts()[0], "test-1");
470 }
471 try {
472 state.ensureCompatibleAdditionalStates(extended);
473 Assertions.fail("an exception should have been thrown");
474 } catch (OrekitException oe) {
475 Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
476 Assertions.assertTrue(oe.getParts()[0].toString().startsWith("test-"));
477 }
478 try {
479 extended.ensureCompatibleAdditionalStates(state);
480 Assertions.fail("an exception should have been thrown");
481 } catch (OrekitException oe) {
482 Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
483 Assertions.assertTrue(oe.getParts()[0].toString().startsWith("test-"));
484 }
485 try {
486 extended.ensureCompatibleAdditionalStates(extended.addAdditionalStateDerivative("test-2", new double[7]));
487 Assertions.fail("an exception should have been thrown");
488 } catch (MathIllegalStateException mise) {
489 Assertions.assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, mise.getSpecifier());
490 Assertions.assertEquals(7, ((Integer) mise.getParts()[0]).intValue());
491 }
492 Assertions.assertEquals(2, extended.getAdditionalStatesDerivatives().size());
493 Assertions.assertTrue(extended.hasAdditionalStateDerivative("test-1"));
494 Assertions.assertTrue(extended.hasAdditionalStateDerivative("test-2"));
495 Assertions.assertEquals( 1.0, extended.getAdditionalStateDerivative("test-1")[0], 1.0e-15);
496 Assertions.assertEquals( 2.0, extended.getAdditionalStateDerivative("test-1")[1], 1.0e-15);
497 Assertions.assertEquals(42.0, extended.getAdditionalStateDerivative("test-2")[0], 1.0e-15);
498
499
500 DoubleArrayDictionary dictionary = new DoubleArrayDictionary();
501 dictionary.put("test-3", new double[] { -6.0 });
502 SpacecraftState s = new SpacecraftState(state.getOrbit(), state.getAttitude(), state.getMass(), null, dictionary);
503 Assertions.assertFalse(s.hasAdditionalData("test-3"));
504 Assertions.assertEquals(-6.0, s.getAdditionalStateDerivative("test-3")[0], 1.0e-15);
505
506 }
507
508 @Test
509 void testAdditionalTestResetOnEventAnalytical() {
510
511
512 AbsoluteDate date0 = new AbsoluteDate(2000, 1, 1, TimeScalesFactory.getUTC());
513 Orbit orbit = new KeplerianOrbit(7.1E6, 0, 0, 0, 0, 0,
514 PositionAngleType.TRUE, FramesFactory.getGCRF(), date0,
515 Constants.WGS84_EARTH_MU);
516
517
518 KeplerianPropagator propagator = new KeplerianPropagator(orbit);
519
520
521 final String name = "A";
522 SpacecraftState initialState = new SpacecraftState(orbit).
523 addAdditionalData(name, new double[] { -1 });
524
525 propagator.resetInitialState(initialState);
526
527
528 AbsoluteDate changeDate = date0.shiftedBy(3);
529 DateDetector dateDetector = new DateDetector(changeDate).
530 withHandler(new EventHandler() {
531
532 @Override
533 public Action eventOccurred(SpacecraftState s, EventDetector detector, boolean increasing) {
534 return Action.RESET_STATE;
535 }
536
537 @Override
538 public SpacecraftState resetState(EventDetector detector, SpacecraftState oldState) {
539 return oldState.addAdditionalData(name, new double[] { +1 });
540 }
541
542 });
543
544 propagator.addEventDetector(dateDetector);
545 propagator.setStepHandler(0.125, s -> {
546 if (s.getDate().durationFrom(changeDate) < -0.001) {
547 Assertions.assertEquals(-1, s.getAdditionalState(name)[0], 1.0e-15);
548 } else if (s.getDate().durationFrom(changeDate) > +0.001) {
549 Assertions.assertEquals(+1, s.getAdditionalState(name)[0], 1.0e-15);
550 }
551 });
552 SpacecraftState finalState = propagator.propagate(date0, date0.shiftedBy(5));
553 Assertions.assertEquals(+1, finalState.getAdditionalState(name)[0], 1.0e-15);
554
555 }
556
557 @Test
558 void testAdditionalTestResetOnEventNumerical() {
559
560
561 AbsoluteDate date0 = new AbsoluteDate(2000, 1, 1, TimeScalesFactory.getUTC());
562 Orbit orbit = new KeplerianOrbit(7.1E6, 0, 0, 0, 0, 0,
563 PositionAngleType.TRUE, FramesFactory.getGCRF(), date0,
564 Constants.WGS84_EARTH_MU);
565
566
567 ODEIntegrator odeIntegrator = new DormandPrince853Integrator(1E-3, 1E3, 1E-6, 1E-6);
568 NumericalPropagator propagator = new NumericalPropagator(odeIntegrator);
569
570
571 final String name = "A";
572 SpacecraftState initialState = new SpacecraftState(orbit).
573 addAdditionalData(name, new double[] { -1 });
574
575 propagator.setInitialState(initialState);
576
577
578 AbsoluteDate changeDate = date0.shiftedBy(3);
579 DateDetector dateDetector = new DateDetector(changeDate).
580 withHandler(new EventHandler() {
581
582 @Override
583 public Action eventOccurred(SpacecraftState s, EventDetector detector, boolean increasing) {
584 return Action.RESET_STATE;
585 }
586
587 @Override
588 public SpacecraftState resetState(EventDetector detector, SpacecraftState oldState) {
589 return oldState.addAdditionalData(name, new double[] { +1 });
590 }
591
592 });
593
594 propagator.addEventDetector(dateDetector);
595 propagator.setStepHandler(0.125, s -> {
596 if (s.getDate().durationFrom(changeDate) < -0.001) {
597 Assertions.assertEquals(-1, s.getAdditionalState(name)[0], 1.0e-15);
598 } else if (s.getDate().durationFrom(changeDate) > +0.001) {
599 Assertions.assertEquals(+1, s.getAdditionalState(name)[0], 1.0e-15);
600 }
601 });
602 SpacecraftState finalState = propagator.propagate(date0, date0.shiftedBy(5));
603 Assertions.assertEquals(+1, finalState.getAdditionalState(name)[0], 1.0e-15);
604
605 }
606
607 @Test
608 void testAdditionalStatesAbsPV() {
609
610 double x_f = 0.8;
611 double y_f = 0.2;
612 double z_f = 0;
613 double vx_f = 0;
614 double vy_f = 0;
615 double vz_f = 0.1;
616
617 AbsoluteDate date = new AbsoluteDate(new DateComponents(2004, 01, 01),
618 TimeComponents.H00,
619 TimeScalesFactory.getUTC());
620
621 PVCoordinates pva_f = new PVCoordinates(new Vector3D(x_f,y_f,z_f), new Vector3D(vx_f,vy_f,vz_f));
622
623 AbsolutePVCoordinates absPV_f = new AbsolutePVCoordinates(FramesFactory.getEME2000(), date, pva_f);
624
625 NumericalPropagator prop = new NumericalPropagator(new DormandPrince853Integrator(0.1, 500, 0.001, 0.001));
626 prop.setOrbitType(null);
627
628 final SpacecraftState initialState = new SpacecraftState(absPV_f);
629
630 prop.resetInitialState(initialState);
631
632 final SpacecraftState state = prop.propagate(absPV_f.getDate().shiftedBy(60));
633 double[] add = new double[2];
634 add[0] = 1.;
635 add[1] = 2.;
636 final SpacecraftState extended =
637 state.
638 addAdditionalData("test-1", add).
639 addAdditionalData("test-2", 42.0);
640 Assertions.assertEquals(0, state.getAdditionalDataValues().size());
641 Assertions.assertFalse(state.hasAdditionalData("test-1"));
642 try {
643 state.getAdditionalState("test-1");
644 Assertions.fail("an exception should have been thrown");
645 } catch (OrekitException oe) {
646 Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
647 Assertions.assertEquals(oe.getParts()[0], "test-1");
648 }
649 try {
650 state.ensureCompatibleAdditionalStates(extended);
651 Assertions.fail("an exception should have been thrown");
652 } catch (OrekitException oe) {
653 Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
654 Assertions.assertTrue(oe.getParts()[0].toString().startsWith("test-"));
655 }
656 try {
657 extended.ensureCompatibleAdditionalStates(state);
658 Assertions.fail("an exception should have been thrown");
659 } catch (OrekitException oe) {
660 Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
661 Assertions.assertTrue(oe.getParts()[0].toString().startsWith("test-"));
662 }
663 try {
664 double[] kk = new double[7];
665 extended.ensureCompatibleAdditionalStates(extended.addAdditionalData("test-2", kk));
666 Assertions.fail("an exception should have been thrown");
667 } catch (MathIllegalStateException mise) {
668 Assertions.assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, mise.getSpecifier());
669 Assertions.assertEquals(7, ((Integer) mise.getParts()[0]).intValue());
670 }
671 Assertions.assertEquals(2, extended.getAdditionalDataValues().size());
672 Assertions.assertTrue(extended.hasAdditionalData("test-1"));
673 Assertions.assertTrue(extended.hasAdditionalData("test-2"));
674 Assertions.assertEquals( 1.0, extended.getAdditionalState("test-1")[0], 1.0e-15);
675 Assertions.assertEquals( 2.0, extended.getAdditionalState("test-1")[1], 1.0e-15);
676 Assertions.assertEquals(42.0, extended.getAdditionalState("test-2")[0], 1.0e-15);
677
678
679 double[] dd = new double[1];
680 dd[0] = -6.0;
681 DataDictionary additional = new DataDictionary();
682 additional.put("test-3", dd);
683 SpacecraftState sO = state.withAdditionalData(additional);
684 Assertions.assertEquals(-6.0, sO.getAdditionalState("test-3")[0], 1.0e-15);
685
686 }
687
688 @Test
689 void testAdditionalStatesDerivativesAbsPV() {
690
691 double x_f = 0.8;
692 double y_f = 0.2;
693 double z_f = 0;
694 double vx_f = 0;
695 double vy_f = 0;
696 double vz_f = 0.1;
697
698 AbsoluteDate date = new AbsoluteDate(new DateComponents(2004, 01, 01),
699 TimeComponents.H00,
700 TimeScalesFactory.getUTC());
701
702 PVCoordinates pva_f = new PVCoordinates(new Vector3D(x_f,y_f,z_f), new Vector3D(vx_f,vy_f,vz_f));
703
704 AbsolutePVCoordinates absPV_f = new AbsolutePVCoordinates(FramesFactory.getEME2000(), date, pva_f);
705
706 NumericalPropagator prop = new NumericalPropagator(new DormandPrince853Integrator(0.1, 500, 0.001, 0.001));
707 prop.setOrbitType(null);
708
709 final SpacecraftState initialState = new SpacecraftState(absPV_f);
710
711 prop.resetInitialState(initialState);
712
713 final SpacecraftState state = prop.propagate(absPV_f.getDate().shiftedBy(60));
714 double[] add = new double[2];
715 add[0] = 1.;
716 add[1] = 2.;
717 final SpacecraftState extended =
718 state.
719 addAdditionalStateDerivative("test-1", add).
720 addAdditionalStateDerivative("test-2", 42.0);
721 Assertions.assertEquals(0, state.getAdditionalStatesDerivatives().getData().size());
722 Assertions.assertFalse(state.hasAdditionalStateDerivative("test-1"));
723 try {
724 state.getAdditionalStateDerivative("test-1");
725 Assertions.fail("an exception should have been thrown");
726 } catch (OrekitException oe) {
727 Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
728 Assertions.assertEquals(oe.getParts()[0], "test-1");
729 }
730 try {
731 state.ensureCompatibleAdditionalStates(extended);
732 Assertions.fail("an exception should have been thrown");
733 } catch (OrekitException oe) {
734 Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
735 Assertions.assertTrue(oe.getParts()[0].toString().startsWith("test-"));
736 }
737 try {
738 extended.ensureCompatibleAdditionalStates(state);
739 Assertions.fail("an exception should have been thrown");
740 } catch (OrekitException oe) {
741 Assertions.assertEquals(oe.getSpecifier(), OrekitMessages.UNKNOWN_ADDITIONAL_DATA);
742 Assertions.assertTrue(oe.getParts()[0].toString().startsWith("test-"));
743 }
744 try {
745 double[] kk = new double[7];
746 extended.ensureCompatibleAdditionalStates(extended.addAdditionalStateDerivative("test-2", kk));
747 Assertions.fail("an exception should have been thrown");
748 } catch (MathIllegalStateException mise) {
749 Assertions.assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, mise.getSpecifier());
750 Assertions.assertEquals(7, ((Integer) mise.getParts()[0]).intValue());
751 }
752 Assertions.assertEquals(2, extended.getAdditionalStatesDerivatives().getData().size());
753 Assertions.assertTrue(extended.hasAdditionalStateDerivative("test-1"));
754 Assertions.assertTrue(extended.hasAdditionalStateDerivative("test-2"));
755 Assertions.assertEquals( 1.0, extended.getAdditionalStateDerivative("test-1")[0], 1.0e-15);
756 Assertions.assertEquals( 2.0, extended.getAdditionalStateDerivative("test-1")[1], 1.0e-15);
757 Assertions.assertEquals(42.0, extended.getAdditionalStateDerivative("test-2")[0], 1.0e-15);
758
759
760 double[] dd = new double[1];
761 dd[0] = -6.0;
762 DoubleArrayDictionary dict = new DoubleArrayDictionary();
763 dict.put("test-3", dd);
764 SpacecraftState s = new SpacecraftState(state.getAbsPVA(), state.getAttitude(), state.getMass(), null, dict);
765 Assertions.assertEquals(-6.0, s.getAdditionalStateDerivative("test-3")[0], 1.0e-15);
766
767 }
768
769 @Test
770 void testShiftAdditionalDerivatives() {
771
772 final String valueAndDerivative = "value-and-derivative";
773 final String valueOnly = "value-only";
774 final String derivativeOnly = "derivative-only";
775 final SpacecraftState s0 = propagator.getInitialState().
776 addAdditionalData(valueAndDerivative, new double[] { 1.0, 2.0 }).
777 addAdditionalStateDerivative(valueAndDerivative, new double[] { 3.0, 2.0 }).
778 addAdditionalData(valueOnly, new double[] { 5.0, 4.0 }).
779 addAdditionalStateDerivative(derivativeOnly, new double[] { 1.0, -1.0 });
780 Assertions.assertEquals( 1.0, s0.getAdditionalState(valueAndDerivative)[0], 1.0e-15);
781 Assertions.assertEquals( 2.0, s0.getAdditionalState(valueAndDerivative)[1], 1.0e-15);
782 Assertions.assertEquals( 3.0, s0.getAdditionalStateDerivative(valueAndDerivative)[0], 1.0e-15);
783 Assertions.assertEquals( 2.0, s0.getAdditionalStateDerivative(valueAndDerivative)[1], 1.0e-15);
784 Assertions.assertEquals( 5.0, s0.getAdditionalState(valueOnly)[0], 1.0e-15);
785 Assertions.assertEquals( 4.0, s0.getAdditionalState(valueOnly)[1], 1.0e-15);
786 Assertions.assertEquals( 1.0, s0.getAdditionalStateDerivative(derivativeOnly)[0], 1.0e-15);
787 Assertions.assertEquals(-1.0, s0.getAdditionalStateDerivative(derivativeOnly)[1], 1.0e-15);
788 final SpacecraftState s1 = s0.shiftedBy(-2.0);
789 Assertions.assertEquals(-5.0, s1.getAdditionalState(valueAndDerivative)[0], 1.0e-15);
790 Assertions.assertEquals(-2.0, s1.getAdditionalState(valueAndDerivative)[1], 1.0e-15);
791 Assertions.assertEquals( 3.0, s1.getAdditionalStateDerivative(valueAndDerivative)[0], 1.0e-15);
792 Assertions.assertEquals( 2.0, s1.getAdditionalStateDerivative(valueAndDerivative)[1], 1.0e-15);
793 Assertions.assertEquals( 5.0, s1.getAdditionalState(valueOnly)[0], 1.0e-15);
794 Assertions.assertEquals( 4.0, s1.getAdditionalState(valueOnly)[1], 1.0e-15);
795 Assertions.assertEquals( 1.0, s1.getAdditionalStateDerivative(derivativeOnly)[0], 1.0e-15);
796 Assertions.assertEquals(-1.0, s1.getAdditionalStateDerivative(derivativeOnly)[1], 1.0e-15);
797
798 }
799
800 @Test
801 void testToStaticTransform() {
802
803 final SpacecraftState state = new SpacecraftState(orbit,
804 attitudeLaw.getAttitude(orbit, orbit.getDate(), orbit.getFrame()));
805
806 final StaticTransform actualStaticTransform = state.toStaticTransform();
807
808 final StaticTransform expectedStaticTransform = state.toTransform();
809 Assertions.assertEquals(expectedStaticTransform.getDate(), actualStaticTransform.getDate());
810 Assertions.assertEquals(expectedStaticTransform.getTranslation(), actualStaticTransform.getTranslation());
811 Assertions.assertEquals(0., Rotation.distance(expectedStaticTransform.getRotation(),
812 actualStaticTransform.getRotation()));
813 }
814
815 @Test
816 public void testIssue1557() {
817
818
819 final SpacecraftState orbitState = new SpacecraftState(TestUtils.getFakeOrbit());
820
821
822 final SpacecraftState pvaState = new SpacecraftState(TestUtils.getFakeAbsolutePVCoordinates());
823
824
825 final Vector3D pvaVelocity = pvaState.getVelocity();
826 final Vector3D orbitVelocity = orbitState.getVelocity();
827
828
829 Assertions.assertEquals(pvaState.getVelocity(), pvaVelocity);
830 Assertions.assertEquals(orbitState.getVelocity(), orbitVelocity);
831 }
832
833 @BeforeEach
834 public void setUp() {
835 try {
836 Utils.setDataRoot("regular-data");
837 double mu = 3.9860047e14;
838 double ae = 6.378137e6;
839 double c20 = -1.08263e-3;
840 double c30 = 2.54e-6;
841 double c40 = 1.62e-6;
842 double c50 = 2.3e-7;
843 double c60 = -5.5e-7;
844
845 mass = 2500;
846 double a = 7187990.1979844316;
847 double e = 0.5e-4;
848 double i = 1.7105407051081795;
849 double omega = 1.9674147913622104;
850 double OMEGA = FastMath.toRadians(261);
851 double lv = 0;
852
853 AbsoluteDate date = new AbsoluteDate(new DateComponents(2004, 01, 01),
854 TimeComponents.H00,
855 TimeScalesFactory.getUTC());
856 orbit = new KeplerianOrbit(a, e, i, omega, OMEGA, lv, PositionAngleType.TRUE,
857 FramesFactory.getEME2000(), date, mu);
858 OneAxisEllipsoid earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
859 Constants.WGS84_EARTH_FLATTENING,
860 FramesFactory.getITRF(IERSConventions.IERS_2010, true));
861 attitudeLaw = new BodyCenterPointing(orbit.getFrame(), earth);
862 propagator =
863 new EcksteinHechlerPropagator(orbit, attitudeLaw, mass,
864 ae, mu, c20, c30, c40, c50, c60);
865
866 } catch (OrekitException oe) {
867 Assertions.fail(oe.getLocalizedMessage());
868 }
869 }
870
871 @AfterEach
872 public void tearDown() {
873 mass = Double.NaN;
874 orbit = null;
875 attitudeLaw = null;
876 propagator = null;
877 }
878
879 private double mass;
880 private Orbit orbit;
881 private AttitudeProvider attitudeLaw;
882 private Propagator propagator;
883
884 }