1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.forces.maneuvers.trigger;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.geometry.euclidean.threed.Rotation;
22 import org.hipparchus.geometry.euclidean.threed.Vector3D;
23 import org.hipparchus.ode.nonstiff.AdaptiveStepsizeFieldIntegrator;
24 import org.hipparchus.ode.nonstiff.AdaptiveStepsizeIntegrator;
25 import org.hipparchus.ode.nonstiff.DormandPrince853FieldIntegrator;
26 import org.hipparchus.ode.nonstiff.DormandPrince853Integrator;
27 import org.hipparchus.util.Binary64Field;
28 import org.hipparchus.util.FastMath;
29 import org.hipparchus.util.MathUtils;
30 import org.junit.jupiter.api.Assertions;
31 import org.junit.jupiter.api.BeforeEach;
32 import org.junit.jupiter.api.Test;
33 import org.orekit.Utils;
34 import org.orekit.attitudes.AttitudeProvider;
35 import org.orekit.attitudes.FrameAlignedProvider;
36 import org.orekit.forces.maneuvers.Maneuver;
37 import org.orekit.forces.maneuvers.propulsion.BasicConstantThrustPropulsionModel;
38 import org.orekit.frames.FramesFactory;
39 import org.orekit.orbits.FieldKeplerianOrbit;
40 import org.orekit.orbits.FieldOrbit;
41 import org.orekit.orbits.KeplerianOrbit;
42 import org.orekit.orbits.Orbit;
43 import org.orekit.orbits.OrbitType;
44 import org.orekit.orbits.PositionAngleType;
45 import org.orekit.propagation.FieldSpacecraftState;
46 import org.orekit.propagation.SpacecraftState;
47 import org.orekit.propagation.ToleranceProvider;
48 import org.orekit.propagation.events.EventDetector;
49 import org.orekit.propagation.events.FieldEventDetector;
50 import org.orekit.propagation.numerical.FieldNumericalPropagator;
51 import org.orekit.propagation.numerical.NumericalPropagator;
52 import org.orekit.time.AbsoluteDate;
53 import org.orekit.time.DateComponents;
54 import org.orekit.time.FieldAbsoluteDate;
55 import org.orekit.time.TimeComponents;
56 import org.orekit.time.TimeScalesFactory;
57 import org.orekit.utils.Constants;
58
59 import java.util.List;
60 import java.util.stream.Collectors;
61
62 public abstract class AbstractManeuverTriggersTest<T extends AbstractManeuverTriggers> {
63
64
65 private AbsoluteDate triggerStart;
66 private AbsoluteDate triggerStop;
67
68 protected abstract T createTrigger(AbsoluteDate start, AbsoluteDate stop);
69
70 private T configureTrigger(final AbsoluteDate start, final AbsoluteDate stop) {
71 T trigger = createTrigger(start, stop);
72
73 trigger.addResetter(new Resetter());
74 trigger.addResetter(new Resetter());
75 return trigger;
76 }
77
78 private <S extends CalculusFieldElement<S>> T configureTrigger(final Field<S> field,
79 final AbsoluteDate start, final AbsoluteDate stop) {
80 T trigger = createTrigger(start, stop);
81
82 trigger.addResetter(field, new FieldResetter<>());
83 trigger.addResetter(field, new FieldResetter<>());
84 return trigger;
85 }
86
87 private class Resetter implements ManeuverTriggersResetter {
88 public void maneuverTriggered(SpacecraftState state, boolean start) {
89 if (start) {
90 triggerStart = state.getDate();
91 } else {
92 triggerStop = state.getDate();
93 }
94 }
95 public SpacecraftState resetState(SpacecraftState state) {
96 return state;
97 }
98 }
99 private class FieldResetter<S extends CalculusFieldElement<S>> implements FieldManeuverTriggersResetter<S> {
100 public void maneuverTriggered(FieldSpacecraftState<S> state, boolean start) {
101 if (start) {
102 triggerStart = state.getDate().toAbsoluteDate();
103 } else {
104 triggerStop = state.getDate().toAbsoluteDate();
105 }
106 }
107 public FieldSpacecraftState<S> resetState(FieldSpacecraftState<S> state) {
108 return state;
109 }
110 }
111 @BeforeEach
112 public void setUp() {
113 Utils.setDataRoot("regular-data");
114 triggerStart = null;
115 triggerStop = null;
116 }
117
118 @Test
119 void testRoughBehaviour() {
120
121 final AttitudeProvider attitudeProvider = buildAttitudeProvider();
122 final SpacecraftState initialState = buildInitialState(attitudeProvider);
123
124 final AbsoluteDate fireDate = new AbsoluteDate(new DateComponents(2004, 01, 02),
125 new TimeComponents(04, 15, 34.080),
126 TimeScalesFactory.getUTC());
127 final double isp = 318;
128 final double duration = 3653.99;
129 final double f = 420;
130 final Maneuver maneuver = new Maneuver(null,
131 configureTrigger(fireDate, fireDate.shiftedBy(duration)),
132 new BasicConstantThrustPropulsionModel(f, isp, Vector3D.PLUS_I, "ABM"));
133 Assertions.assertEquals(f, ((BasicConstantThrustPropulsionModel) maneuver.getPropulsionModel()).getThrustMagnitude(), 1.0e-10);
134 Assertions.assertEquals(isp, ((BasicConstantThrustPropulsionModel) maneuver.getPropulsionModel()).getIsp(), 1.0e-10);
135
136 final SpacecraftState finalorb = buildPropagator(attitudeProvider, initialState, maneuver).
137 propagate(fireDate.shiftedBy(3800));
138
139 final double flowRate = ((BasicConstantThrustPropulsionModel) maneuver.getPropulsionModel()).getFlowRate();
140 final double massTolerance = FastMath.abs(flowRate) * maneuver.getEventDetectors().findFirst().get().getThreshold();
141 Assertions.assertEquals(2007.8824544261233, finalorb.getMass(), massTolerance);
142 Assertions.assertEquals(2.6872, FastMath.toDegrees(MathUtils.normalizeAngle(finalorb.getOrbit().getI(), FastMath.PI)), 1e-4);
143 Assertions.assertEquals(28970, finalorb.getOrbit().getA()/1000, 1);
144
145 final List<EventDetector> list1 = maneuver.getManeuverTriggers().getEventDetectors().collect(Collectors.toList());
146 final List<EventDetector> list2 = maneuver.getManeuverTriggers().getEventDetectors().collect(Collectors.toList());
147 Assertions.assertEquals(list1.size(), list2.size());
148 for (int i = 0; i < list1.size(); ++i ) {
149 Assertions.assertSame(list1.get(i), list2.get(i));
150 }
151
152 Assertions.assertEquals(0.0, triggerStart.durationFrom(fireDate), 1.0e-10);
153 Assertions.assertEquals(duration, triggerStop.durationFrom(fireDate), 1.0e-10);
154
155 }
156
157 @Test
158 void testBackward() {
159
160 final AttitudeProvider attitudeProvider = buildAttitudeProvider();
161 final SpacecraftState initialState = buildInitialState(attitudeProvider);
162
163 final AbsoluteDate fireDate = new AbsoluteDate(new DateComponents(2004, 01, 02),
164 new TimeComponents(04, 15, 34.080),
165 TimeScalesFactory.getUTC());
166 final double isp = 318;
167 final double duration = 30;
168 final double f = 420;
169 final Maneuver maneuver = new Maneuver(null,
170 configureTrigger(fireDate, fireDate.shiftedBy(duration)),
171 new BasicConstantThrustPropulsionModel(f, isp, Vector3D.PLUS_I, "ABM"));
172 Assertions.assertEquals(f, ((BasicConstantThrustPropulsionModel) maneuver.getPropulsionModel()).getThrustMagnitude(), 1.0e-10);
173 Assertions.assertEquals(isp, ((BasicConstantThrustPropulsionModel) maneuver.getPropulsionModel()).getIsp(), 1.0e-10);
174
175 final SpacecraftState finalorb = buildPropagator(attitudeProvider,
176 initialState.shiftedBy(initialState.getOrbit().getKeplerianPeriod()),
177 maneuver).
178 propagate(fireDate.shiftedBy(-10));
179
180 Assertions.assertEquals(2504.040, finalorb.getMass(), 1.0e-3);
181
182 Assertions.assertEquals(0.0, triggerStart.durationFrom(fireDate), 1.0e-10);
183 Assertions.assertEquals(duration, triggerStop.durationFrom(fireDate), 1.0e-10);
184
185 }
186
187 @Test
188 void testRoughBehaviourField() {
189 doTestRoughBehaviourField(Binary64Field.getInstance());
190 }
191
192 private <S extends CalculusFieldElement<S>> void doTestRoughBehaviourField(Field<S> field) {
193 final AttitudeProvider attitudeProvider = buildAttitudeProvider();
194 final FieldSpacecraftState<S> initialState = buildInitialState(field, attitudeProvider);
195
196
197 final AbsoluteDate fireDate = new AbsoluteDate(new DateComponents(2004, 01, 02),
198 new TimeComponents(04, 15, 34.080),
199 TimeScalesFactory.getUTC());
200 final double isp = 318;
201 final double duration = 3653.99;
202 final double f = 420;
203 final Maneuver maneuver = new Maneuver(null,
204 configureTrigger(field, fireDate, fireDate.shiftedBy(duration)),
205 new BasicConstantThrustPropulsionModel(f, isp, Vector3D.PLUS_I, "ABM"));
206 Assertions.assertEquals(f, ((BasicConstantThrustPropulsionModel) maneuver.getPropulsionModel()).getThrustMagnitude(), 1.0e-10);
207 Assertions.assertEquals(isp, ((BasicConstantThrustPropulsionModel) maneuver.getPropulsionModel()).getIsp(), 1.0e-10);
208
209 final FieldSpacecraftState<S> finalorb = buildPropagator(field, attitudeProvider, initialState, maneuver).
210 propagate(new FieldAbsoluteDate<>(field, fireDate).shiftedBy(3800));
211
212 final double flowRate = ((BasicConstantThrustPropulsionModel) maneuver.getPropulsionModel()).getFlowRate();
213 final double massTolerance = FastMath.abs(flowRate) * maneuver.getEventDetectors().findFirst().get().getThreshold();
214 Assertions.assertEquals(2007.8824544261233, finalorb.getMass().getReal(), massTolerance);
215 Assertions.assertEquals(2.6872, FastMath.toDegrees(MathUtils.normalizeAngle(finalorb.getOrbit().getI(), field.getZero().newInstance(FastMath.PI))).getReal(), 1e-4);
216 Assertions.assertEquals(28970, finalorb.getOrbit().getA().divide(1000).getReal(), 1);
217
218 final List<FieldEventDetector<?>> list1 = maneuver.getManeuverTriggers().getFieldEventDetectors(field).collect(Collectors.toList());
219 final List<FieldEventDetector<?>> list2 = maneuver.getManeuverTriggers().getFieldEventDetectors(field).collect(Collectors.toList());
220 Assertions.assertEquals(list1.size(), list2.size());
221 for (int i = 0; i < list1.size(); ++i ) {
222 Assertions.assertSame(list1.get(i), list2.get(i));
223 }
224
225 Assertions.assertEquals(0.0, triggerStart.durationFrom(fireDate), 1.0e-10);
226 Assertions.assertEquals(duration, triggerStop.durationFrom(fireDate), 1.0e-10);
227
228 }
229
230 @Test
231 void testBackwardField() {
232 doTestBackwardField(Binary64Field.getInstance());
233 }
234
235 private <S extends CalculusFieldElement<S>> void doTestBackwardField(Field<S> field) {
236 final AttitudeProvider attitudeProvider = buildAttitudeProvider();
237 final FieldSpacecraftState<S> initialState = buildInitialState(field, attitudeProvider);
238
239
240 final AbsoluteDate fireDate = new AbsoluteDate(new DateComponents(2004, 01, 02),
241 new TimeComponents(04, 15, 34.080),
242 TimeScalesFactory.getUTC());
243 final double isp = 318;
244 final double duration = 30;
245 final double f = 420;
246 final Maneuver maneuver = new Maneuver(null,
247 configureTrigger(field, fireDate, fireDate.shiftedBy(duration)),
248 new BasicConstantThrustPropulsionModel(f, isp, Vector3D.PLUS_I, "ABM"));
249 Assertions.assertEquals(f, ((BasicConstantThrustPropulsionModel) maneuver.getPropulsionModel()).getThrustMagnitude(), 1.0e-10);
250 Assertions.assertEquals(isp, ((BasicConstantThrustPropulsionModel) maneuver.getPropulsionModel()).getIsp(), 1.0e-10);
251
252 final FieldSpacecraftState<S> finalorb = buildPropagator(field, attitudeProvider,
253 initialState.shiftedBy(initialState.getOrbit().getKeplerianPeriod()),
254 maneuver).
255 propagate(new FieldAbsoluteDate<>(field, fireDate).shiftedBy(-10));
256
257 Assertions.assertEquals(2504.040, finalorb.getMass().getReal(), 1.0e-3);
258
259 Assertions.assertEquals(0.0, triggerStart.durationFrom(fireDate), 1.0e-10);
260 Assertions.assertEquals(duration, triggerStop.durationFrom(fireDate), 1.0e-10);
261
262 }
263
264 private AttitudeProvider buildAttitudeProvider() {
265 final double delta = FastMath.toRadians(-7.4978);
266 final double alpha = FastMath.toRadians(351);
267 return new FrameAlignedProvider(new Rotation(new Vector3D(alpha, delta), Vector3D.PLUS_I));
268 }
269
270 private SpacecraftState buildInitialState(final AttitudeProvider attitudeProvider) {
271 final double mass = 2500;
272 final double a = 24396159;
273 final double e = 0.72831215;
274 final double i = FastMath.toRadians(7);
275 final double omega = FastMath.toRadians(180);
276 final double OMEGA = FastMath.toRadians(261);
277 final double lv = 0;
278
279 final AbsoluteDate initDate = new AbsoluteDate(new DateComponents(2004, 01, 01),
280 new TimeComponents(23, 30, 00.000),
281 TimeScalesFactory.getUTC());
282 final Orbit orbit =
283 new KeplerianOrbit(a, e, i, omega, OMEGA, lv, PositionAngleType.TRUE,
284 FramesFactory.getEME2000(), initDate, Constants.EIGEN5C_EARTH_MU);
285 return new SpacecraftState(orbit, attitudeProvider.getAttitude(orbit, orbit.getDate(), orbit.getFrame()), mass);
286 }
287
288 private <S extends CalculusFieldElement<S>> FieldSpacecraftState<S> buildInitialState(final Field<S> field,
289 final AttitudeProvider attitudeProvider) {
290 final S zero = field.getZero();
291 final S mass = zero.newInstance(2500);
292 final S a = zero.newInstance(24396159);
293 final S e = zero.newInstance(0.72831215);
294 final S i = FastMath.toRadians(zero.newInstance(7));
295 final S omega = FastMath.toRadians(zero.newInstance(180));
296 final S OMEGA = FastMath.toRadians(zero.newInstance(261));
297 final S lv = zero.newInstance(0);
298
299 final FieldAbsoluteDate<S> initDate = new FieldAbsoluteDate<>(field,
300 new DateComponents(2004, 01, 01),
301 new TimeComponents(23, 30, 00.000),
302 TimeScalesFactory.getUTC());
303 final FieldOrbit<S> orbit =
304 new FieldKeplerianOrbit<>(a, e, i, omega, OMEGA, lv, PositionAngleType.TRUE,
305 FramesFactory.getEME2000(), initDate, zero.newInstance(Constants.EIGEN5C_EARTH_MU));
306 return new FieldSpacecraftState<>(orbit, attitudeProvider.getAttitude(orbit, orbit.getDate(), orbit.getFrame()), mass);
307 }
308
309 private NumericalPropagator buildPropagator(final AttitudeProvider attitudeProvider, final SpacecraftState initialState,
310 final Maneuver maneuver) {
311 OrbitType orbitType = OrbitType.EQUINOCTIAL;
312 double[][] tol = ToleranceProvider.getDefaultToleranceProvider(1e-3).getTolerances(initialState.getOrbit(), orbitType);
313 AdaptiveStepsizeIntegrator integrator = new DormandPrince853Integrator(0.001, 1000, tol[0], tol[1]);
314 integrator.setInitialStepSize(60);
315 final NumericalPropagator propagator = new NumericalPropagator(integrator);
316 propagator.setOrbitType(orbitType);
317 propagator.setInitialState(initialState);
318 propagator.setAttitudeProvider(attitudeProvider);
319 propagator.addForceModel(maneuver);
320 return propagator;
321 }
322
323 private <S extends CalculusFieldElement<S>> FieldNumericalPropagator<S> buildPropagator(final Field<S> field,
324 final AttitudeProvider attitudeProvider,
325 final FieldSpacecraftState<S> initialState,
326 final Maneuver maneuver) {
327 OrbitType orbitType = OrbitType.EQUINOCTIAL;
328 double[][] tol = ToleranceProvider.getDefaultToleranceProvider(1e-3).getTolerances(initialState.getOrbit(), orbitType);
329 AdaptiveStepsizeFieldIntegrator<S> integrator = new DormandPrince853FieldIntegrator<>(field, 0.001, 1000, tol[0], tol[1]);
330 integrator.setInitialStepSize(60);
331 final FieldNumericalPropagator<S> propagator = new FieldNumericalPropagator<>(field, integrator);
332 propagator.setOrbitType(orbitType);
333 propagator.setInitialState(initialState);
334 propagator.setAttitudeProvider(attitudeProvider);
335 propagator.addForceModel(maneuver);
336 return propagator;
337 }
338
339 }