1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.analytical;
18
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.Comparator;
23 import java.util.List;
24 import java.util.PriorityQueue;
25 import java.util.Queue;
26
27 import org.hipparchus.exception.MathRuntimeException;
28 import org.hipparchus.ode.events.Action;
29 import org.orekit.attitudes.Attitude;
30 import org.orekit.attitudes.AttitudeProvider;
31 import org.orekit.errors.OrekitException;
32 import org.orekit.errors.OrekitInternalError;
33 import org.orekit.frames.Frame;
34 import org.orekit.orbits.Orbit;
35 import org.orekit.propagation.AbstractPropagator;
36 import org.orekit.propagation.AdditionalStateProvider;
37 import org.orekit.propagation.BoundedPropagator;
38 import org.orekit.propagation.EphemerisGenerator;
39 import org.orekit.propagation.SpacecraftState;
40 import org.orekit.propagation.events.EventDetector;
41 import org.orekit.propagation.events.EventState;
42 import org.orekit.propagation.events.EventState.EventOccurrence;
43 import org.orekit.propagation.sampling.OrekitStepInterpolator;
44 import org.orekit.time.AbsoluteDate;
45 import org.orekit.utils.PVCoordinatesProvider;
46 import org.orekit.utils.TimeStampedPVCoordinates;
47
48
49
50
51
52
53
54
55
56
57
58
59 public abstract class AbstractAnalyticalPropagator extends AbstractPropagator {
60
61
62 private PVCoordinatesProvider pvProvider;
63
64
65 private AbsoluteDate lastPropagationStart;
66
67
68 private AbsoluteDate lastPropagationEnd;
69
70
71 private boolean statesInitialized;
72
73
74 private boolean isLastStep;
75
76
77 private final Collection<EventState<?>> eventsStates;
78
79
80
81
82 protected AbstractAnalyticalPropagator(final AttitudeProvider attitudeProvider) {
83 setAttitudeProvider(attitudeProvider);
84 pvProvider = new LocalPVProvider();
85 lastPropagationStart = AbsoluteDate.PAST_INFINITY;
86 lastPropagationEnd = AbsoluteDate.FUTURE_INFINITY;
87 statesInitialized = false;
88 eventsStates = new ArrayList<>();
89 }
90
91
92 @Override
93 public EphemerisGenerator getEphemerisGenerator() {
94 return () -> new BoundedPropagatorView(lastPropagationStart, lastPropagationEnd);
95 }
96
97
98 public <T extends EventDetector> void addEventDetector(final T detector) {
99 eventsStates.add(new EventState<>(detector));
100 }
101
102
103 public Collection<EventDetector> getEventsDetectors() {
104 final List<EventDetector> list = new ArrayList<>();
105 for (final EventState<?> state : eventsStates) {
106 list.add(state.getEventDetector());
107 }
108 return Collections.unmodifiableCollection(list);
109 }
110
111
112 public void clearEventsDetectors() {
113 eventsStates.clear();
114 }
115
116
117 public SpacecraftState propagate(final AbsoluteDate start, final AbsoluteDate target) {
118 try {
119
120 initializePropagation();
121
122 lastPropagationStart = start;
123
124 final boolean isForward = target.compareTo(start) >= 0;
125 SpacecraftState state = updateAdditionalStates(basicPropagate(start));
126
127
128 for (final EventState<?> es : eventsStates) {
129 es.init(state, target);
130 }
131
132
133 getMultiplexer().init(state, target);
134
135
136 statesInitialized = false;
137 isLastStep = false;
138 do {
139
140
141 final SpacecraftState previous = state;
142 final SpacecraftState current = updateAdditionalStates(basicPropagate(target));
143 final OrekitStepInterpolator interpolator =
144 new BasicStepInterpolator(isForward, previous, current);
145
146
147 state = acceptStep(interpolator, target);
148
149
150
151 state = updateAdditionalStates(basicPropagate(state.getDate()));
152
153 } while (!isLastStep);
154
155
156 lastPropagationEnd = state.getDate();
157 setStartDate(state.getDate());
158 return state;
159
160 } catch (MathRuntimeException mrte) {
161 throw OrekitException.unwrap(mrte);
162 }
163 }
164
165
166
167
168
169
170
171 protected SpacecraftState acceptStep(final OrekitStepInterpolator interpolator,
172 final AbsoluteDate target)
173 throws MathRuntimeException {
174
175 SpacecraftState previous = interpolator.getPreviousState();
176 final SpacecraftState current = interpolator.getCurrentState();
177 OrekitStepInterpolator restricted = interpolator;
178
179
180
181 if (!statesInitialized) {
182
183 if (!eventsStates.isEmpty()) {
184
185 for (final EventState<?> state : eventsStates) {
186 state.reinitializeBegin(interpolator);
187 }
188 }
189
190 statesInitialized = true;
191
192 }
193
194
195 final int orderingSign = interpolator.isForward() ? +1 : -1;
196 final Queue<EventState<?>> occurringEvents = new PriorityQueue<>(new Comparator<EventState<?>>() {
197
198 @Override
199 public int compare(final EventState<?> es0, final EventState<?> es1) {
200 return orderingSign * es0.getEventDate().compareTo(es1.getEventDate());
201 }
202 });
203
204 boolean doneWithStep = false;
205 resetEvents:
206 do {
207
208
209 occurringEvents.clear();
210 for (final EventState<?> state : eventsStates) {
211 if (state.evaluateStep(interpolator)) {
212
213 occurringEvents.add(state);
214 }
215 }
216
217 do {
218
219 eventLoop:
220 while (!occurringEvents.isEmpty()) {
221
222
223 final EventState<?> currentEvent = occurringEvents.poll();
224
225
226 SpacecraftState eventState = restricted.getInterpolatedState(currentEvent.getEventDate());
227
228
229 restricted = restricted.restrictStep(previous, eventState);
230
231
232 for (final EventState<?> state : eventsStates) {
233 if (state != currentEvent && state.tryAdvance(eventState, interpolator)) {
234
235
236 occurringEvents.remove(state);
237
238 occurringEvents.add(state);
239
240 occurringEvents.add(currentEvent);
241 continue eventLoop;
242 }
243 }
244
245
246
247 getMultiplexer().handleStep(restricted);
248
249
250 final EventOccurrence occurrence = currentEvent.doEvent(eventState);
251 final Action action = occurrence.getAction();
252 isLastStep = action == Action.STOP;
253
254 if (isLastStep) {
255
256
257
258
259 final SpacecraftState savedState = eventState;
260 eventState = interpolator.getInterpolatedState(occurrence.getStopDate());
261 restricted = restricted.restrictStep(savedState, eventState);
262
263
264 getMultiplexer().handleStep(restricted);
265 getMultiplexer().finish(restricted.getCurrentState());
266
267 }
268
269 if (isLastStep) {
270
271 return eventState;
272 }
273
274 if (action == Action.RESET_DERIVATIVES || action == Action.RESET_STATE) {
275
276
277 final SpacecraftState resetState = occurrence.getNewState();
278 resetIntermediateState(resetState, interpolator.isForward());
279 return resetState;
280 }
281
282
283
284 previous = eventState;
285 restricted = new BasicStepInterpolator(restricted.isForward(), eventState, current);
286
287 if (action == Action.RESET_EVENTS) {
288 continue resetEvents;
289 }
290
291
292
293 if (currentEvent.evaluateStep(restricted)) {
294
295 occurringEvents.add(currentEvent);
296 }
297
298 }
299
300
301
302
303
304
305
306 for (final EventState<?> state : eventsStates) {
307 if (state.tryAdvance(current, interpolator)) {
308 occurringEvents.add(state);
309 }
310 }
311
312 } while (!occurringEvents.isEmpty());
313
314 doneWithStep = true;
315 } while (!doneWithStep);
316
317 isLastStep = target.equals(current.getDate());
318
319
320 getMultiplexer().handleStep(restricted);
321 if (isLastStep) {
322 getMultiplexer().finish(restricted.getCurrentState());
323 }
324
325 return current;
326
327 }
328
329
330
331
332
333 protected abstract double getMass(AbsoluteDate date);
334
335
336
337
338 public PVCoordinatesProvider getPvProvider() {
339 return pvProvider;
340 }
341
342
343
344
345
346
347 protected abstract void resetIntermediateState(SpacecraftState state, boolean forward);
348
349
350
351
352
353 protected abstract Orbit propagateOrbit(AbsoluteDate date);
354
355
356
357
358
359
360
361
362
363 protected SpacecraftState basicPropagate(final AbsoluteDate date) {
364 try {
365
366
367 final Orbit orbit = propagateOrbit(date);
368
369
370 final Attitude attitude =
371 getAttitudeProvider().getAttitude(pvProvider, date, orbit.getFrame());
372
373
374 return new SpacecraftState(orbit, attitude, getMass(date));
375
376 } catch (OrekitException oe) {
377 throw new OrekitException(oe);
378 }
379 }
380
381
382 private class LocalPVProvider implements PVCoordinatesProvider {
383
384
385 public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate date, final Frame frame) {
386 return propagateOrbit(date).getPVCoordinates(frame);
387 }
388
389 }
390
391
392 private class BoundedPropagatorView extends AbstractAnalyticalPropagator implements BoundedPropagator {
393
394
395 private final AbsoluteDate minDate;
396
397
398 private final AbsoluteDate maxDate;
399
400
401
402
403
404 BoundedPropagatorView(final AbsoluteDate startDate, final AbsoluteDate endDate) {
405 super(AbstractAnalyticalPropagator.this.getAttitudeProvider());
406 super.resetInitialState(AbstractAnalyticalPropagator.this.getInitialState());
407 if (startDate.compareTo(endDate) <= 0) {
408 minDate = startDate;
409 maxDate = endDate;
410 } else {
411 minDate = endDate;
412 maxDate = startDate;
413 }
414
415 try {
416
417 for (AdditionalStateProvider provider : AbstractAnalyticalPropagator.this.getAdditionalStateProviders()) {
418 addAdditionalStateProvider(provider);
419 }
420 } catch (OrekitException oe) {
421
422
423 throw new OrekitInternalError(null);
424 }
425
426 }
427
428
429 public AbsoluteDate getMinDate() {
430 return minDate;
431 }
432
433
434 public AbsoluteDate getMaxDate() {
435 return maxDate;
436 }
437
438
439 protected Orbit propagateOrbit(final AbsoluteDate target) {
440 return AbstractAnalyticalPropagator.this.propagateOrbit(target);
441 }
442
443
444 public double getMass(final AbsoluteDate date) {
445 return AbstractAnalyticalPropagator.this.getMass(date);
446 }
447
448
449 public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate date, final Frame frame) {
450 return propagate(date).getPVCoordinates(frame);
451 }
452
453
454 public void resetInitialState(final SpacecraftState state) {
455 super.resetInitialState(state);
456 AbstractAnalyticalPropagator.this.resetInitialState(state);
457 }
458
459
460 protected void resetIntermediateState(final SpacecraftState state, final boolean forward) {
461 AbstractAnalyticalPropagator.this.resetIntermediateState(state, forward);
462 }
463
464
465 public SpacecraftState getInitialState() {
466 return AbstractAnalyticalPropagator.this.getInitialState();
467 }
468
469
470 public Frame getFrame() {
471 return AbstractAnalyticalPropagator.this.getFrame();
472 }
473
474 }
475
476
477 private class BasicStepInterpolator implements OrekitStepInterpolator {
478
479
480 private final SpacecraftState previousState;
481
482
483 private final SpacecraftState currentState;
484
485
486 private final boolean forward;
487
488
489
490
491
492
493 BasicStepInterpolator(final boolean isForward,
494 final SpacecraftState previousState,
495 final SpacecraftState currentState) {
496 this.forward = isForward;
497 this.previousState = previousState;
498 this.currentState = currentState;
499 }
500
501
502 @Override
503 public SpacecraftState getPreviousState() {
504 return previousState;
505 }
506
507
508 @Override
509 public boolean isPreviousStateInterpolated() {
510
511 return false;
512 }
513
514
515 @Override
516 public SpacecraftState getCurrentState() {
517 return currentState;
518 }
519
520
521 @Override
522 public boolean isCurrentStateInterpolated() {
523
524 return false;
525 }
526
527
528 @Override
529 public SpacecraftState getInterpolatedState(final AbsoluteDate date) {
530
531
532 final SpacecraftState basicState = basicPropagate(date);
533
534
535 return updateAdditionalStates(basicState);
536
537 }
538
539
540 @Override
541 public boolean isForward() {
542 return forward;
543 }
544
545
546 @Override
547 public BasicStepInterpolator restrictStep(final SpacecraftState newPreviousState,
548 final SpacecraftState newCurrentState) {
549 return new BasicStepInterpolator(forward, newPreviousState, newCurrentState);
550 }
551
552 }
553
554 }