1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.forces.maneuvers;
18
19 import org.hipparchus.geometry.euclidean.threed.Rotation;
20 import org.hipparchus.geometry.euclidean.threed.RotationConvention;
21 import org.hipparchus.geometry.euclidean.threed.RotationOrder;
22 import org.hipparchus.geometry.euclidean.threed.Vector3D;
23 import org.hipparchus.linear.RealMatrix;
24 import org.hipparchus.ode.events.Action;
25 import org.hipparchus.ode.nonstiff.DormandPrince853Integrator;
26 import org.hipparchus.util.FastMath;
27 import org.junit.jupiter.api.Assertions;
28 import org.junit.jupiter.api.BeforeEach;
29 import org.junit.jupiter.api.Test;
30 import org.junit.jupiter.params.ParameterizedTest;
31 import org.junit.jupiter.params.provider.EnumSource;
32 import org.mockito.Mockito;
33 import org.orekit.TestUtils;
34 import org.orekit.Utils;
35 import org.orekit.attitudes.Attitude;
36 import org.orekit.attitudes.AttitudeProvider;
37 import org.orekit.attitudes.FrameAlignedProvider;
38 import org.orekit.attitudes.LofOffset;
39 import org.orekit.bodies.CelestialBodyFactory;
40 import org.orekit.frames.Frame;
41 import org.orekit.frames.FramesFactory;
42 import org.orekit.frames.LOFType;
43 import org.orekit.orbits.CartesianOrbit;
44 import org.orekit.orbits.KeplerianOrbit;
45 import org.orekit.orbits.Orbit;
46 import org.orekit.orbits.PositionAngleType;
47 import org.orekit.propagation.MatricesHarvester;
48 import org.orekit.propagation.SpacecraftState;
49 import org.orekit.propagation.ToleranceProvider;
50 import org.orekit.propagation.analytical.KeplerianPropagator;
51 import org.orekit.propagation.events.*;
52 import org.orekit.propagation.events.handlers.EventHandler;
53 import org.orekit.propagation.events.handlers.StopOnIncreasing;
54 import org.orekit.propagation.numerical.NumericalPropagator;
55 import org.orekit.time.AbsoluteDate;
56 import org.orekit.time.DateComponents;
57 import org.orekit.time.TimeComponents;
58 import org.orekit.time.TimeScalesFactory;
59 import org.orekit.utils.AbsolutePVCoordinates;
60 import org.orekit.utils.Constants;
61 import org.orekit.utils.TimeStampedPVCoordinates;
62
63 class ImpulseManeuverTest {
64
65 @ParameterizedTest
66 @EnumSource(Action.class)
67 void testInclinationManeuver(final Action action) {
68 final Orbit initialOrbit =
69 new KeplerianOrbit(24532000.0, 0.72, 0.3, FastMath.PI, 0.4, 2.0 + 4 * FastMath.PI,
70 PositionAngleType.MEAN, FramesFactory.getEME2000(),
71 new AbsoluteDate(new DateComponents(2008, 6, 23),
72 new TimeComponents(14, 18, 37),
73 TimeScalesFactory.getUTC()),
74 3.986004415e14);
75 final double a = initialOrbit.getA();
76 final double e = initialOrbit.getE();
77 final double i = initialOrbit.getI();
78 final double mu = initialOrbit.getMu();
79 final double vApo = FastMath.sqrt(mu * (1 - e) / (a * (1 + e)));
80 double dv = 0.99 * FastMath.tan(i) * vApo;
81 KeplerianPropagator propagator = new KeplerianPropagator(initialOrbit,
82 new LofOffset(initialOrbit.getFrame(), LOFType.LVLH_CCSDS));
83 final NodeDetector trigger = new NodeDetector(initialOrbit, FramesFactory.getEME2000());
84 propagator.addEventDetector(new ImpulseManeuver(trigger.withHandler((s, detector, increasing) -> action),
85 new Vector3D(dv, Vector3D.PLUS_J), 400.0));
86 SpacecraftState propagated = propagator.propagate(initialOrbit.getDate().shiftedBy(8000));
87 Assertions.assertEquals(0.0028257, propagated.getOrbit().getI(), 1.0e-6);
88 Assertions.assertEquals(0.442476 + 6 * FastMath.PI, propagated.getOrbit().getLv(), 1.0e-6);
89 }
90
91 @Test
92 void testInertialManeuver() {
93 final double mu = CelestialBodyFactory.getEarth().getGM();
94
95 final double initialX = 7100e3;
96 final double initialY = 0.0;
97 final double initialZ = 1300e3;
98 final double initialVx = 0;
99 final double initialVy = 8000;
100 final double initialVz = 1000;
101
102 final Vector3D position = new Vector3D(initialX, initialY, initialZ);
103 final Vector3D velocity = new Vector3D(initialVx, initialVy, initialVz);
104 final AbsoluteDate epoch = new AbsoluteDate(2010, 1, 1, 0, 0, 0, TimeScalesFactory.getUTC());
105 final TimeStampedPVCoordinates state = new TimeStampedPVCoordinates(epoch, position, velocity, Vector3D.ZERO);
106 final Orbit initialOrbit = new CartesianOrbit(state, FramesFactory.getEME2000(), mu);
107
108 final double totalPropagationTime = 0.00001;
109 final double driftTimeInSec = totalPropagationTime / 2.0;
110 final double deltaX = 0.01;
111 final double deltaY = 0.02;
112 final double deltaZ = 0.03;
113 final double isp = 300;
114
115 final Vector3D deltaV = new Vector3D(deltaX, deltaY, deltaZ);
116
117 KeplerianPropagator propagator = new KeplerianPropagator(initialOrbit, new LofOffset(initialOrbit.getFrame(), LOFType.VNC));
118 DateDetector dateDetector = new DateDetector(epoch.shiftedBy(driftTimeInSec));
119 FrameAlignedProvider attitudeOverride = new FrameAlignedProvider(new Rotation(RotationOrder.XYX,
120 RotationConvention.VECTOR_OPERATOR,
121 0, 0, 0));
122 ImpulseManeuver burnAtEpoch = new ImpulseManeuver(dateDetector.withThreshold(driftTimeInSec/4), attitudeOverride, deltaV, isp);
123 Assertions.assertEquals(isp, burnAtEpoch.getIsp(), 1.0e-15);
124 Assertions.assertSame(dateDetector.getClass(), burnAtEpoch.getTrigger().getClass());
125 propagator.addEventDetector(burnAtEpoch);
126
127 SpacecraftState finalState = propagator.propagate(epoch.shiftedBy(totalPropagationTime));
128
129 final double finalVxExpected = initialVx + deltaX;
130 final double finalVyExpected = initialVy + deltaY;
131 final double finalVzExpected = initialVz + deltaZ;
132 final double maneuverTolerance = 1e-4;
133
134 final Vector3D finalVelocity = finalState.getPVCoordinates().getVelocity();
135 Assertions.assertEquals(finalVxExpected, finalVelocity.getX(), maneuverTolerance);
136 Assertions.assertEquals(finalVyExpected, finalVelocity.getY(), maneuverTolerance);
137 Assertions.assertEquals(finalVzExpected, finalVelocity.getZ(), maneuverTolerance);
138
139 }
140
141 @Test
142 void testEventOccurredEventSlopeFilter() {
143
144 final Orbit orbit = TestUtils.getDefaultOrbit(AbsoluteDate.ARBITRARY_EPOCH);
145 final ApsideDetector detector = new ApsideDetector(orbit);
146 final ImpulseManeuver maneuver = new ImpulseManeuver(new EventSlopeFilter<>(detector,
147 FilterType.TRIGGER_ONLY_INCREASING_EVENTS), Vector3D.ZERO, Double.POSITIVE_INFINITY);
148 final KeplerianPropagator propagator = new KeplerianPropagator(orbit);
149
150 propagator.addEventDetector(maneuver);
151 Assertions.assertDoesNotThrow(() -> propagator.propagate(orbit.getDate().shiftedBy(1e5)));
152 }
153
154 @Test
155 void testWithDetectionSettings() {
156
157 final DateDetector dateDetector = new DateDetector();
158 final ImpulseManeuver maneuver = new ImpulseManeuver(dateDetector, Vector3D.ZERO, 1.);
159 final EventDetectionSettings expectedSettings = new EventDetectionSettings(1., 2., 3);
160
161 final ImpulseManeuver maneuverWithSettings = maneuver.withDetectionSettings(expectedSettings);
162
163 Assertions.assertEquals(expectedSettings.getThreshold(), maneuverWithSettings.getThreshold());
164 Assertions.assertEquals(expectedSettings.getMaxIterationCount(), maneuverWithSettings.getMaxIterationCount());
165 Assertions.assertEquals(expectedSettings.getMaxCheckInterval(), maneuverWithSettings.getMaxCheckInterval());
166 }
167
168 @Test
169 void testResetStateAttitudeOverride() {
170
171 final AbsolutePVCoordinates pvCoordinates = new AbsolutePVCoordinates(FramesFactory.getEME2000(),
172 AbsoluteDate.ARBITRARY_EPOCH, new Vector3D(1., 2, 3), new Vector3D(4, 5, 6));
173 final ImpulseManeuver impulseManeuver = new ImpulseManeuver(new DateDetector(),
174 new FrameAlignedProvider(pvCoordinates.getFrame()), Vector3D.ZERO, 1.);
175 final SpacecraftState expectedSTate = new SpacecraftState(pvCoordinates);
176
177 final SpacecraftState actualSTate = impulseManeuver.getHandler().resetState(impulseManeuver, expectedSTate);
178
179 compareStates(expectedSTate, actualSTate);
180 }
181
182 @Test
183 void testResetState() {
184
185 final AbsolutePVCoordinates pvCoordinates = new AbsolutePVCoordinates(FramesFactory.getEME2000(),
186 AbsoluteDate.ARBITRARY_EPOCH, new Vector3D(1., 2, 3), new Vector3D(4, 5, 6));
187 final ImpulseManeuver impulseManeuver = new ImpulseManeuver(new DateDetector(), Vector3D.ZERO, 1.);
188 final SpacecraftState expectedSTate = new SpacecraftState(pvCoordinates);
189
190 final SpacecraftState actualSTate = impulseManeuver.getHandler().resetState(impulseManeuver, expectedSTate);
191
192 compareStates(expectedSTate, actualSTate);
193 }
194
195 private static void compareStates(final SpacecraftState expectedState, final SpacecraftState actualState) {
196 Assertions.assertEquals(expectedState.getDate(), actualState.getDate());
197 Assertions.assertEquals(expectedState.getMass(), actualState.getMass());
198 Assertions.assertEquals(expectedState.getAttitude(), actualState.getAttitude());
199 Assertions.assertEquals(expectedState.getPosition(), actualState.getPosition());
200 Assertions.assertEquals(expectedState.getPVCoordinates().getVelocity(),
201 actualState.getPVCoordinates().getVelocity());
202 }
203
204 @Test
205 void testBackward() {
206
207 final AbsoluteDate iniDate = new AbsoluteDate(2003, 5, 1, 17, 30, 0.0, TimeScalesFactory.getUTC());
208 final Orbit initialOrbit = new KeplerianOrbit(7e6, 1.0e-4, FastMath.toRadians(98.5),
209 FastMath.toRadians(87.0), FastMath.toRadians(216.1807),
210 FastMath.toRadians(319.779), PositionAngleType.MEAN,
211 FramesFactory.getEME2000(), iniDate,
212 Constants.EIGEN5C_EARTH_MU);
213 KeplerianPropagator propagator = new KeplerianPropagator(initialOrbit,
214 new LofOffset(initialOrbit.getFrame(),
215 LOFType.VNC));
216 DateDetector dateDetector = new DateDetector(iniDate.shiftedBy(-300));
217 Vector3D deltaV = new Vector3D(12.0, 1.0, -4.0);
218 final double isp = 300;
219 ImpulseManeuver maneuver =
220 new ImpulseManeuver(dateDetector.withMaxCheck(3600.0).
221 withThreshold(1.0e-6), deltaV, isp);
222 propagator.addEventDetector(maneuver);
223
224 SpacecraftState finalState = propagator.propagate(initialOrbit.getDate().shiftedBy(-900));
225
226 Assertions.assertTrue(finalState.getMass() > propagator.getInitialState().getMass());
227 Assertions.assertTrue(finalState.getDate().compareTo(propagator.getInitialState().getDate()) < 0);
228
229 }
230
231 @Test
232 void testBackAndForth() {
233
234 final AttitudeProvider lof = new LofOffset(FramesFactory.getEME2000(), LOFType.VNC);
235 final double mu = Constants.EIGEN5C_EARTH_MU;
236 final AbsoluteDate iniDate = new AbsoluteDate(2003, 5, 1, 17, 30, 0.0, TimeScalesFactory.getUTC());
237 final Orbit pastOrbit = new KeplerianOrbit(7e6, 1.0e-4, FastMath.toRadians(98.5),
238 FastMath.toRadians(87.0), FastMath.toRadians(216.1807),
239 FastMath.toRadians(319.779), PositionAngleType.MEAN,
240 FramesFactory.getEME2000(), iniDate, mu);
241 final double pastMass = 2500.0;
242 DateDetector dateDetector = new DateDetector(iniDate.shiftedBy(600));
243 Vector3D deltaV = new Vector3D(12.0, 1.0, -4.0);
244 final double isp = 300;
245 ImpulseManeuver maneuver =
246 new ImpulseManeuver(dateDetector.withMaxCheck(3600.0).
247 withThreshold(1.0e-6),
248 new FrameAlignedProvider(Rotation.IDENTITY),
249 deltaV, isp);
250
251 double span = 900.0;
252 KeplerianPropagator forwardPropagator = new KeplerianPropagator(pastOrbit, lof, mu, pastMass);
253 forwardPropagator.addEventDetector(maneuver);
254 SpacecraftState futureState = forwardPropagator.propagate(pastOrbit.getDate().shiftedBy(span));
255
256 KeplerianPropagator backwardPropagator = new KeplerianPropagator(futureState.getOrbit(), lof,
257 mu, futureState.getMass());
258 backwardPropagator.addEventDetector(maneuver);
259 SpacecraftState rebuiltPast = backwardPropagator.propagate(pastOrbit.getDate());
260 Assertions.assertEquals(0.0,
261 Vector3D.distance(pastOrbit.getPosition(),
262 rebuiltPast.getPosition()),
263 2.0e-8);
264 Assertions.assertEquals(0.0,
265 Vector3D.distance(pastOrbit.getPVCoordinates().getVelocity(),
266 rebuiltPast.getPVCoordinates().getVelocity()),
267 2.0e-11);
268 Assertions.assertEquals(pastMass, rebuiltPast.getMass(), 5.0e-13);
269
270 }
271
272 @Test
273 void testAdditionalStateKeplerian() {
274 final double mu = CelestialBodyFactory.getEarth().getGM();
275
276 final double initialX = 7100e3;
277 final double initialY = 0.0;
278 final double initialZ = 1300e3;
279 final double initialVx = 0;
280 final double initialVy = 8000;
281 final double initialVz = 1000;
282
283 final Vector3D position = new Vector3D(initialX, initialY, initialZ);
284 final Vector3D velocity = new Vector3D(initialVx, initialVy, initialVz);
285 final AbsoluteDate epoch = new AbsoluteDate(2010, 1, 1, 0, 0, 0, TimeScalesFactory.getUTC());
286 final TimeStampedPVCoordinates pv = new TimeStampedPVCoordinates(epoch, position, velocity, Vector3D.ZERO);
287 final Orbit initialOrbit = new CartesianOrbit(pv, FramesFactory.getEME2000(), mu);
288
289 final double totalPropagationTime = 10;
290 final double deltaX = 0.01;
291 final double deltaY = 0.02;
292 final double deltaZ = 0.03;
293 final double isp = 300;
294
295 final Vector3D deltaV = new Vector3D(deltaX, deltaY, deltaZ);
296
297 final AttitudeProvider attitudeProvider = new LofOffset(initialOrbit.getFrame(), LOFType.VNC);
298 final Attitude initialAttitude = attitudeProvider.getAttitude(initialOrbit, initialOrbit.getDate(), initialOrbit.getFrame());
299 final SpacecraftState initialState = new SpacecraftState(initialOrbit, initialAttitude);
300 KeplerianPropagator propagator = new KeplerianPropagator(initialOrbit);
301 propagator.resetInitialState(initialState.addAdditionalData("testOnly", -1.0));
302 DateDetector dateDetector = new DateDetector(epoch.shiftedBy(0.5 * totalPropagationTime));
303 FrameAlignedProvider attitudeOverride = new FrameAlignedProvider(new Rotation(RotationOrder.XYX,
304 RotationConvention.VECTOR_OPERATOR,
305 0, 0, 0));
306 ImpulseManeuver burnAtEpoch = new ImpulseManeuver(dateDetector.withThreshold(1.0e-3), attitudeOverride, deltaV, isp);
307 propagator.addEventDetector(burnAtEpoch);
308
309 SpacecraftState finalState = propagator.propagate(epoch.shiftedBy(totalPropagationTime));
310 Assertions.assertEquals(1, finalState.getAdditionalDataValues().size());
311 Assertions.assertEquals(-1.0, finalState.getAdditionalState("testOnly")[0], 1.0e-15);
312
313 }
314
315 @Test
316 void testAdditionalStateNumerical() {
317 final double mu = CelestialBodyFactory.getEarth().getGM();
318
319 final double initialX = 7100e3;
320 final double initialY = 0.0;
321 final double initialZ = 1300e3;
322 final double initialVx = 0;
323 final double initialVy = 8000;
324 final double initialVz = 1000;
325
326 final Vector3D position = new Vector3D(initialX, initialY, initialZ);
327 final Vector3D velocity = new Vector3D(initialVx, initialVy, initialVz);
328 final AbsoluteDate epoch = new AbsoluteDate(2010, 1, 1, 0, 0, 0, TimeScalesFactory.getUTC());
329 final TimeStampedPVCoordinates pv = new TimeStampedPVCoordinates(epoch, position, velocity, Vector3D.ZERO);
330 final Orbit initialOrbit = new CartesianOrbit(pv, FramesFactory.getEME2000(), mu);
331
332 final double totalPropagationTime = 10.0;
333 final double deltaX = 0.01;
334 final double deltaY = 0.02;
335 final double deltaZ = 0.03;
336 final double isp = 300;
337
338 final Vector3D deltaV = new Vector3D(deltaX, deltaY, deltaZ);
339
340 final AttitudeProvider attitudeProvider = new LofOffset(initialOrbit.getFrame(), LOFType.VNC);
341 final Attitude initialAttitude = attitudeProvider.getAttitude(initialOrbit, initialOrbit.getDate(), initialOrbit.getFrame());
342
343 double[][] tolerances = ToleranceProvider.getDefaultToleranceProvider(10.).getTolerances(initialOrbit, initialOrbit.getType());
344 DormandPrince853Integrator integrator = new DormandPrince853Integrator(1.0e-3, 60, tolerances[0], tolerances[1]);
345 NumericalPropagator propagator = new NumericalPropagator(integrator);
346 propagator.setOrbitType(initialOrbit.getType());
347 MatricesHarvester harvester = propagator.setupMatricesComputation("derivatives", null, null);
348 propagator.resetInitialState(new SpacecraftState(initialOrbit, initialAttitude));
349 DateDetector dateDetector = new DateDetector(epoch.shiftedBy(0.5 * totalPropagationTime));
350 FrameAlignedProvider attitudeOverride = new FrameAlignedProvider(new Rotation(RotationOrder.XYX,
351 RotationConvention.VECTOR_OPERATOR,
352 0, 0, 0));
353 ImpulseManeuver burnAtEpoch = new ImpulseManeuver(dateDetector.withThreshold(1.0e-3), attitudeOverride, deltaV, isp);
354 propagator.addEventDetector(burnAtEpoch);
355
356 SpacecraftState finalState = propagator.propagate(epoch.shiftedBy(totalPropagationTime));
357 Assertions.assertEquals(1, finalState.getAdditionalDataValues().size());
358 Assertions.assertEquals(36, finalState.getAdditionalState("derivatives").length);
359
360 RealMatrix stateTransitionMatrix = harvester.getStateTransitionMatrix(finalState);
361 for (int i = 0; i < 6; ++i) {
362 for (int j = 0; j < 6; ++j) {
363 double sIJ = stateTransitionMatrix.getEntry(i, j);
364 if (j == i) {
365
366 Assertions.assertEquals(1.0, sIJ, 2.0e-4);
367 } else if (j == i + 3) {
368
369 Assertions.assertEquals(totalPropagationTime, sIJ, 4.0e-5 * totalPropagationTime);
370 } else {
371
372 Assertions.assertEquals(0, sIJ, 1.0e-4);
373 }
374 }
375 }
376
377 }
378
379
380
381
382
383 @Test
384 void testIssue663() {
385
386
387 final Orbit initialOrbit =
388 new KeplerianOrbit(24532000.0, 0.72, 0.3, FastMath.PI, 0.4, 2.0,
389 PositionAngleType.MEAN, FramesFactory.getEME2000(),
390 new AbsoluteDate(new DateComponents(2008, 6, 23),
391 new TimeComponents(14, 18, 37),
392 TimeScalesFactory.getUTC()),
393 3.986004415e14);
394
395 final InitializationDetector trigger = new InitializationDetector();
396
397
398 final AttitudeProvider attitudeOverride = new LofOffset(FramesFactory.getEME2000(), LOFType.TNW);
399 final Vector3D deltaVSat = Vector3D.PLUS_I;
400 final double isp = 1500.0;
401 final ImpulseManeuver maneuver = new ImpulseManeuver(trigger, attitudeOverride, deltaVSat, isp);
402
403
404 KeplerianPropagator propagator = new KeplerianPropagator(initialOrbit, attitudeOverride);
405 propagator.addEventDetector(maneuver);
406
407
408 Assertions.assertFalse(trigger.initialized);
409 propagator.propagate(initialOrbit.getDate().shiftedBy(3600.0));
410 Assertions.assertTrue(trigger.initialized);
411
412 }
413
414 @Test
415 void testControl3DVectorCostType() {
416
417
418
419 final double a = Constants.EGM96_EARTH_EQUATORIAL_RADIUS + 2000.e3;
420 final double e = 1e-4;
421 final double i = 0.5;
422 final double pa = 0.;
423 final double raan = 6.;
424 final double anomaly = 1.;
425 final PositionAngleType positionAngleType = PositionAngleType.MEAN;
426 final Frame gcrf = FramesFactory.getGCRF();
427 final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
428 final double mu = Constants.EGM96_EARTH_MU;
429
430 final KeplerianOrbit orbit = new KeplerianOrbit(a, e, i, pa, raan, anomaly, positionAngleType, gcrf, date, mu);
431
432
433 final DateDetector dateDetector = new DateDetector(date.shiftedBy(1000.));
434 final AbsoluteDate endPropagationDate = dateDetector.getDate().shiftedBy(10000.);
435 final AttitudeProvider attitudeProvider = new FrameAlignedProvider(gcrf);
436 final Vector3D deltaV = new Vector3D(2., -1., 0.5);
437 final ImpulseProvider impulseProvider = ImpulseProvider.of(deltaV);
438 final double initialMass = 1000.;
439 final double isp = 100.;
440
441
442 final KeplerianPropagator propagatorNone = new KeplerianPropagator(orbit, attitudeProvider, orbit.getMu(), initialMass);
443 final KeplerianPropagator propagatorNorm1 = new KeplerianPropagator(orbit, attitudeProvider, orbit.getMu(), initialMass);
444 final KeplerianPropagator propagatorNorm2 = new KeplerianPropagator(orbit, attitudeProvider, orbit.getMu(), initialMass);
445 final KeplerianPropagator propagatorNormInf = new KeplerianPropagator(orbit, attitudeProvider, orbit.getMu(), initialMass);
446
447
448 propagatorNone.addEventDetector(new ImpulseManeuver(dateDetector, attitudeProvider, impulseProvider, isp,
449 Control3DVectorCostType.NONE));
450 propagatorNorm1.addEventDetector(new ImpulseManeuver(dateDetector, attitudeProvider, impulseProvider, isp,
451 Control3DVectorCostType.ONE_NORM));
452 propagatorNorm2.addEventDetector(new ImpulseManeuver(dateDetector, attitudeProvider, impulseProvider, isp,
453 Control3DVectorCostType.TWO_NORM));
454 propagatorNormInf.addEventDetector(new ImpulseManeuver(dateDetector, attitudeProvider, impulseProvider, isp,
455 Control3DVectorCostType.INF_NORM));
456
457
458 final double finalMassWithNone = propagatorNone.propagate(endPropagationDate).getMass();
459 final double finalMassWithNorm1 = propagatorNorm1.propagate(endPropagationDate).getMass();
460 final double finalMassWithNorm2 = propagatorNorm2.propagate(endPropagationDate).getMass();
461 final double finalMassWithNormInf = propagatorNormInf.propagate(endPropagationDate).getMass();
462
463
464
465 Assertions.assertNotEquals(finalMassWithNorm1, finalMassWithNorm2);
466 Assertions.assertNotEquals(finalMassWithNorm1, finalMassWithNormInf);
467 Assertions.assertNotEquals(finalMassWithNormInf, finalMassWithNorm2);
468
469
470 Assertions.assertEquals(initialMass, finalMassWithNone);
471 final double factorExponential = -1. / (isp * Constants.G0_STANDARD_GRAVITY);
472 Assertions.assertEquals(initialMass * FastMath.exp(deltaV.getNorm1() * factorExponential), finalMassWithNorm1);
473 Assertions.assertEquals(initialMass * FastMath.exp(deltaV.getNorm() * factorExponential), finalMassWithNorm2);
474 Assertions.assertEquals(initialMass * FastMath.exp(deltaV.getNormInf() * factorExponential), finalMassWithNormInf);
475 }
476
477 @Deprecated
478 @Test
479 void testDeprecatedConstructor() {
480
481 final double expectedIsp = 10;
482
483 final ImpulseManeuver maneuver = new ImpulseManeuver(new DateDetector(), null, Vector3D.ZERO,
484 expectedIsp, Control3DVectorCostType.NONE);
485
486 Assertions.assertEquals(expectedIsp, maneuver.getIsp());
487 }
488
489 @Test
490 void testInit() {
491
492 final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
493 final SpacecraftState mockedState = Mockito.mock(SpacecraftState.class);
494 Mockito.when(mockedState.getDate()).thenReturn(date);
495 final ImpulseProvider impulseProvider = ImpulseProvider.of(Vector3D.PLUS_I);
496 final ImpulseManeuver maneuver = new ImpulseManeuver(new DateDetector(), null, impulseProvider,
497 1, Control3DVectorCostType.NONE);
498
499 maneuver.init(mockedState, date);
500 }
501
502 @Test
503 void testFinish() {
504
505 final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
506 final SpacecraftState mockedState = Mockito.mock(SpacecraftState.class);
507 Mockito.when(mockedState.getDate()).thenReturn(date);
508 final ImpulseProvider impulseProvider = ImpulseProvider.of(Vector3D.PLUS_I);
509 final ImpulseManeuver maneuver = new ImpulseManeuver(new DateDetector(), null, impulseProvider,
510 1, Control3DVectorCostType.NONE);
511
512 maneuver.finish(mockedState);
513 }
514
515 @Test
516 void testMultipleDates() {
517
518 final Orbit initialOrbit = getOrbit();
519 final KeplerianPropagator propagator = new KeplerianPropagator(initialOrbit);
520 final AbsoluteDate[] dates = new AbsoluteDate[10];
521 for (int i = 0; i < dates.length; i++) {
522 dates[i] = initialOrbit.getDate().shiftedBy(i * 10 + 1);
523 }
524 final double isp = Double.POSITIVE_INFINITY;
525 final ImpulseManeuver maneuver = new ImpulseManeuver(new DateDetector(dates).withMaxCheck(5), null, new GrowingImpulseProvider(), isp,
526 Control3DVectorCostType.NONE);
527 propagator.addEventDetector(maneuver);
528
529 final SpacecraftState actualState = propagator.propagate(dates[dates.length - 1].shiftedBy(1));
530
531 propagator.resetInitialState(new SpacecraftState(initialOrbit));
532 propagator.clearEventsDetectors();
533 for (int i = 0; i < dates.length; i++) {
534 propagator.addEventDetector(new ImpulseManeuver(new DateDetector(dates[i]), Vector3D.PLUS_I.scalarMultiply(i + 1), isp));
535 }
536 final SpacecraftState expectedState = propagator.propagate(actualState.getDate());
537 final Vector3D relativePosition = expectedState.getPosition().subtract(actualState.getPosition());
538 Assertions.assertEquals(0., relativePosition.getNorm(), 1e-4);
539 }
540
541 private static class GrowingImpulseProvider implements ImpulseProvider {
542 int count = 0;
543
544 @Override
545 public Vector3D getImpulse(SpacecraftState state, boolean isForward) {
546 count++;
547 return Vector3D.PLUS_I.scalarMultiply(count);
548 }
549 }
550
551 private static CartesianOrbit getOrbit() {
552 final double mu = CelestialBodyFactory.getEarth().getGM();
553 final double initialX = 7100e3;
554 final double initialY = 0.0;
555 final double initialZ = 1300e3;
556 final double initialVx = 0;
557 final double initialVy = 8000;
558 final double initialVz = 1000;
559 final Vector3D position = new Vector3D(initialX, initialY, initialZ);
560 final Vector3D velocity = new Vector3D(initialVx, initialVy, initialVz);
561 final AbsoluteDate epoch = new AbsoluteDate(2010, 1, 1, 0, 0, 0, TimeScalesFactory.getUTC());
562 final TimeStampedPVCoordinates pv = new TimeStampedPVCoordinates(epoch, position, velocity, Vector3D.ZERO);
563 return new CartesianOrbit(pv, FramesFactory.getEME2000(), mu);
564 }
565
566 @BeforeEach
567 public void setUp() {
568 Utils.setDataRoot("regular-data");
569 }
570
571
572 private class InitializationDetector implements EventDetector {
573
574
575 private boolean initialized;
576
577
578 @Override
579 public void init(final SpacecraftState s0, final AbsoluteDate t) {
580 EventDetector.super.init(s0, t);
581 this.initialized = true;
582 }
583
584
585 @Override
586 public double g(SpacecraftState s) {
587 return 1;
588 }
589
590 @Override
591 public EventHandler getHandler() {
592 return new StopOnIncreasing();
593 }
594
595 }
596
597 }