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