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 protected TriggerHandler() {
286
287 }
288
289
290 @Override
291 public void init(final SpacecraftState initialState, final AbsoluteDate target, final EventDetector detector) {
292 forward = target.isAfterOrEqualTo(initialState);
293 lastState = null;
294 lastResetState = null;
295 initializeResetters(initialState, target);
296 }
297
298
299
300
301
302
303
304 protected Action determineAction(final EventDetector detector, final SpacecraftState oldState) {
305 final SpacecraftState resetState = resetState(detector, oldState);
306 if (resetState == oldState) {
307 return Action.RESET_DERIVATIVES;
308 } else {
309 return Action.RESET_STATE;
310 }
311 }
312
313
314 @Override
315 public SpacecraftState resetState(final EventDetector detector, final SpacecraftState oldState) {
316 if (lastState != oldState) {
317 lastResetState = applyResetters(oldState);
318 lastState = oldState;
319 }
320 return lastResetState;
321 }
322
323
324
325
326
327 protected boolean isForward() {
328 return forward;
329 }
330 }
331
332
333
334
335
336 protected abstract class FieldTriggerHandler<S extends CalculusFieldElement<S>> implements FieldEventHandler<S> {
337
338
339 private boolean forward;
340
341
342 private FieldSpacecraftState<S> lastState;
343
344
345 private FieldSpacecraftState<S> lastResetState;
346
347
348 protected FieldTriggerHandler() {
349
350 }
351
352
353 @Override
354 public void init(final FieldSpacecraftState<S> initialState,
355 final FieldAbsoluteDate<S> target,
356 final FieldEventDetector<S> detector) {
357 forward = target.isAfterOrEqualTo(initialState);
358 lastState = null;
359 lastResetState = null;
360 initializeResetters(initialState, target);
361 }
362
363
364
365
366
367
368
369 protected Action determineAction(final FieldEventDetector<S> detector, final FieldSpacecraftState<S> oldState) {
370 final FieldSpacecraftState<S> resetState = resetState(detector, oldState);
371 if (resetState == oldState) {
372 return Action.RESET_DERIVATIVES;
373 } else {
374 return Action.RESET_STATE;
375 }
376 }
377
378
379 @Override
380 public FieldSpacecraftState<S> resetState(final FieldEventDetector<S> detector, final FieldSpacecraftState<S> oldState) {
381 if (lastState != oldState) {
382 lastResetState = applyResetters(oldState);
383 lastState = oldState;
384 }
385 return lastResetState;
386 }
387
388
389
390
391
392 protected boolean isForward() {
393 return forward;
394 }
395 }
396 }