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