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 java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23
24 import org.hipparchus.CalculusFieldElement;
25 import org.hipparchus.Field;
26 import org.hipparchus.ode.events.Action;
27 import org.orekit.propagation.FieldSpacecraftState;
28 import org.orekit.propagation.SpacecraftState;
29 import org.orekit.propagation.events.EventDetector;
30 import org.orekit.propagation.events.EventEnablingPredicateFilter;
31 import org.orekit.propagation.events.EventShifter;
32 import org.orekit.propagation.events.EventSlopeFilter;
33 import org.orekit.propagation.events.FieldEventDetector;
34 import org.orekit.propagation.events.FieldEventEnablingPredicateFilter;
35 import org.orekit.propagation.events.FieldEventShifter;
36 import org.orekit.propagation.events.FieldEventSlopeFilter;
37 import org.orekit.propagation.events.handlers.EventHandler;
38 import org.orekit.propagation.events.handlers.FieldContinueOnEvent;
39 import org.orekit.propagation.events.handlers.FieldEventHandler;
40 import org.orekit.time.AbsoluteDate;
41 import org.orekit.time.FieldAbsoluteDate;
42 import org.orekit.utils.TimeSpanMap;
43
44
45
46
47
48 public abstract class AbstractManeuverTriggers implements ResettableManeuverTriggers {
49
50
51 private TimeSpanMap<Boolean> firings;
52
53
54 private boolean forward;
55
56
57 private final List<ManeuverTriggersResetter> resetters;
58
59
60 private final Map<Field<? extends CalculusFieldElement<?>>, List<FieldManeuverTriggersResetter<?>>> fieldResetters;
61
62
63
64 protected AbstractManeuverTriggers() {
65 this.firings = new TimeSpanMap<>(Boolean.FALSE);
66 this.resetters = new ArrayList<>();
67 this.fieldResetters = new HashMap<>();
68 }
69
70
71 @Override
72 public void init(final SpacecraftState initialState, final AbsoluteDate target) {
73
74 forward = target.isAfterOrEqualTo(initialState);
75 firings = new TimeSpanMap<>(Boolean.FALSE);
76 initializeResetters(initialState, target);
77
78 if (isFiringOnInitialState(initialState, forward)) {
79 if (forward) {
80 firings.addValidAfter(Boolean.TRUE, initialState.getDate(), false);
81 } else {
82 firings.addValidBefore(Boolean.TRUE, initialState.getDate(), false);
83 }
84 }
85
86 }
87
88
89 @SuppressWarnings("unchecked")
90 @Override
91 public <T extends CalculusFieldElement<T>> void init(final FieldSpacecraftState<T> initialState, final FieldAbsoluteDate<T> target) {
92
93 forward = target.isAfterOrEqualTo(initialState);
94 firings = new TimeSpanMap<>(Boolean.FALSE);
95
96 final List<FieldManeuverTriggersResetter<?>> list = fieldResetters.get(initialState.getDate().getField());
97 if (list != null) {
98 for (FieldManeuverTriggersResetter<?> r : list) {
99 ((FieldManeuverTriggersResetter<T>) r).init(initialState, target);
100 }
101 }
102
103 if (isFiringOnInitialState(initialState.toSpacecraftState(), forward)) {
104 if (forward) {
105 firings.addValidAfter(Boolean.TRUE, initialState.getDate().toAbsoluteDate(), false);
106 } else {
107 firings.addValidBefore(Boolean.TRUE, initialState.getDate().toAbsoluteDate(), false);
108 }
109 }
110
111 }
112
113
114
115
116
117
118
119
120
121 protected abstract boolean isFiringOnInitialState(SpacecraftState initialState, boolean isForward);
122
123
124 @Override
125 public boolean isFiring(final AbsoluteDate date, final double[] parameters) {
126 return firings.get(date);
127 }
128
129
130 @Override
131 public <S extends CalculusFieldElement<S>> boolean isFiring(final FieldAbsoluteDate<S> date, final S[] parameters) {
132 return firings.get(date.toAbsoluteDate());
133 }
134
135
136
137
138 public TimeSpanMap<Boolean> getFirings() {
139 return firings;
140 }
141
142
143 @Override
144 public void addResetter(final ManeuverTriggersResetter resetter) {
145 resetters.add(resetter);
146 }
147
148
149 @Override
150 public <T extends CalculusFieldElement<T>> void addResetter(final Field<T> field, final FieldManeuverTriggersResetter<T> resetter) {
151
152
153 final List<FieldManeuverTriggersResetter<?>> list = fieldResetters.computeIfAbsent(field, k -> new ArrayList<>());
154
155
156 list.add(resetter);
157
158 }
159
160
161
162
163
164 protected void initializeResetters(final SpacecraftState initialState, final AbsoluteDate target) {
165 for (final ManeuverTriggersResetter r : resetters) {
166 r.init(initialState, target);
167 }
168 }
169
170
171
172
173
174 protected void notifyResetters(final SpacecraftState state, final boolean start) {
175 for (final ManeuverTriggersResetter r : resetters) {
176 r.maneuverTriggered(state, start);
177 }
178 }
179
180
181
182
183
184 protected SpacecraftState applyResetters(final SpacecraftState state) {
185 SpacecraftState reset = state;
186 for (final ManeuverTriggersResetter r : resetters) {
187 reset = r.resetState(reset);
188 }
189 return reset;
190 }
191
192
193
194
195
196
197 protected <T extends CalculusFieldElement<T>> void initializeResetters(final FieldSpacecraftState<T> initialState, final FieldAbsoluteDate<T> target) {
198 final List<FieldManeuverTriggersResetter<?>> list = fieldResetters.get(initialState.getDate().getField());
199 if (list != null) {
200 for (final FieldManeuverTriggersResetter<?> r : list) {
201 @SuppressWarnings("unchecked")
202 final FieldManeuverTriggersResetter<T> tr = (FieldManeuverTriggersResetter<T>) r;
203 tr.init(initialState, target);
204 }
205 }
206 }
207
208
209
210
211
212
213 protected <T extends CalculusFieldElement<T>> void notifyResetters(final FieldSpacecraftState<T> state, final boolean start) {
214 final List<FieldManeuverTriggersResetter<?>> list = fieldResetters.get(state.getDate().getField());
215 if (list != null) {
216 for (final FieldManeuverTriggersResetter<?> r : list) {
217 @SuppressWarnings("unchecked")
218 final FieldManeuverTriggersResetter<T> tr = (FieldManeuverTriggersResetter<T>) r;
219 tr.maneuverTriggered(state, start);
220 }
221 }
222 }
223
224
225
226
227
228
229 protected <T extends CalculusFieldElement<T>> FieldSpacecraftState<T>
230 applyResetters(final FieldSpacecraftState<T> state) {
231 FieldSpacecraftState<T> reset = state;
232 final List<FieldManeuverTriggersResetter<?>> list = fieldResetters.get(state.getDate().getField());
233 if (list != null) {
234 for (final FieldManeuverTriggersResetter<?> r : list) {
235 @SuppressWarnings("unchecked")
236 final FieldManeuverTriggersResetter<T> tr = (FieldManeuverTriggersResetter<T>) r;
237 reset = tr.resetState(reset);
238 }
239 }
240 return reset;
241 }
242
243
244
245
246
247
248
249
250
251 protected <T extends CalculusFieldElement<T>> FieldEventDetector<T> convertDetector(final Field<T> field,
252 final EventDetector detector) {
253 if (detector instanceof EventEnablingPredicateFilter predicateFilter) {
254 final FieldEventDetector<T> fieldDetector = convertDetector(field, predicateFilter.getDetector());
255 return new FieldEventEnablingPredicateFilter<>(fieldDetector, (state, fieldEventDetector, g) -> predicateFilter
256 .getPredicate().eventIsEnabled(state.toSpacecraftState(), null, g.getReal()));
257 } else if (detector instanceof EventSlopeFilter<?> eventSlopeFilter) {
258 final FieldEventDetector<T> fieldDetector = convertDetector(field, eventSlopeFilter.getDetector());
259 return new FieldEventSlopeFilter<>(fieldDetector, eventSlopeFilter.getFilterType());
260 } else if (detector instanceof EventShifter eventShifter) {
261 final FieldEventDetector<T> fieldDetector = convertDetector(field, eventShifter.getDetector());
262 final T zero = field.getZero();
263 return new FieldEventShifter<>(fieldDetector, eventShifter.isUseShiftedStates(),
264 zero.newInstance(eventShifter.getIncreasingTimeShift()), zero.newInstance(eventShifter.getDecreasingTimeShift()));
265 } else {
266 return FieldEventDetector.of(field, new FieldContinueOnEvent<>(), detector);
267 }
268 }
269
270
271
272
273 protected abstract class TriggerHandler implements EventHandler {
274
275
276 private boolean forward;
277
278
279 private SpacecraftState lastState;
280
281
282 private SpacecraftState lastResetState;
283
284
285 @Override
286 public void init(final SpacecraftState initialState, final AbsoluteDate target, final EventDetector detector) {
287 forward = target.isAfterOrEqualTo(initialState);
288 lastState = null;
289 lastResetState = null;
290 initializeResetters(initialState, target);
291 }
292
293
294
295
296
297
298
299 protected Action determineAction(final EventDetector detector, final SpacecraftState oldState) {
300 final SpacecraftState resetState = resetState(detector, oldState);
301 if (resetState == oldState) {
302 return Action.RESET_DERIVATIVES;
303 } else {
304 return Action.RESET_STATE;
305 }
306 }
307
308
309 @Override
310 public SpacecraftState resetState(final EventDetector detector, final SpacecraftState oldState) {
311 if (lastState != oldState) {
312 lastResetState = applyResetters(oldState);
313 lastState = oldState;
314 }
315 return lastResetState;
316 }
317
318
319
320
321
322 protected boolean isForward() {
323 return forward;
324 }
325 }
326
327
328
329
330
331 protected abstract class FieldTriggerHandler<S extends CalculusFieldElement<S>> implements FieldEventHandler<S> {
332
333
334 private boolean forward;
335
336
337 private FieldSpacecraftState<S> lastState;
338
339
340 private FieldSpacecraftState<S> lastResetState;
341
342
343 @Override
344 public void init(final FieldSpacecraftState<S> initialState,
345 final FieldAbsoluteDate<S> target,
346 final FieldEventDetector<S> detector) {
347 forward = target.isAfterOrEqualTo(initialState);
348 lastState = null;
349 lastResetState = null;
350 initializeResetters(initialState, target);
351 }
352
353
354
355
356
357
358
359 protected Action determineAction(final FieldEventDetector<S> detector, final FieldSpacecraftState<S> oldState) {
360 final FieldSpacecraftState<S> resetState = resetState(detector, oldState);
361 if (resetState == oldState) {
362 return Action.RESET_DERIVATIVES;
363 } else {
364 return Action.RESET_STATE;
365 }
366 }
367
368
369 @Override
370 public FieldSpacecraftState<S> resetState(final FieldEventDetector<S> detector, final FieldSpacecraftState<S> oldState) {
371 if (lastState != oldState) {
372 lastResetState = applyResetters(oldState);
373 lastState = oldState;
374 }
375 return lastResetState;
376 }
377
378
379
380
381
382 protected boolean isForward() {
383 return forward;
384 }
385 }
386 }