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