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() == null ?
139 Collections.emptyList() :
140 getAttitudeProvider().getEventDetectors().map(EventState::new).collect(Collectors.toList());
141 eventStates.addAll(userEventStates);
142 for (final EventState<?> es : eventStates) {
143 es.init(state, target);
144 }
145
146
147 getMultiplexer().init(state, target);
148
149
150 statesInitialized = false;
151 isLastStep = false;
152 do {
153
154
155 final SpacecraftState previous = state;
156 final SpacecraftState current = updateAdditionalData(basicPropagate(target));
157 final OrekitStepInterpolator interpolator =
158 new BasicStepInterpolator(isForward, previous, current);
159
160
161 state = acceptStep(interpolator, target);
162
163
164
165 state = updateAdditionalData(basicPropagate(state.getDate()));
166
167 } while (!isLastStep);
168
169
170 for (final EventState<?> es : eventStates) {
171 es.finish(state);
172 }
173
174
175 lastPropagationEnd = state.getDate();
176 setStartDate(state.getDate());
177 return state;
178
179 } catch (MathRuntimeException mrte) {
180 throw OrekitException.unwrap(mrte);
181 }
182 }
183
184
185
186
187
188 private void checkStartDateIsNotInfinity(final AbsoluteDate start) {
189 if (start.isEqualTo(AbsoluteDate.PAST_INFINITY) || start.isEqualTo(AbsoluteDate.FUTURE_INFINITY)) {
190 throw new OrekitIllegalArgumentException(OrekitMessages.CANNOT_START_PROPAGATION_FROM_INFINITY);
191 }
192 }
193
194
195
196
197
198
199
200 protected SpacecraftState acceptStep(final OrekitStepInterpolator interpolator,
201 final AbsoluteDate target)
202 throws MathRuntimeException {
203
204 SpacecraftState previous = interpolator.getPreviousState();
205 final SpacecraftState current = interpolator.getCurrentState();
206 OrekitStepInterpolator restricted = interpolator;
207
208
209
210 if (!statesInitialized) {
211
212 if (!eventStates.isEmpty()) {
213
214 for (final EventState<?> state : eventStates) {
215 state.reinitializeBegin(interpolator);
216 }
217 }
218
219 statesInitialized = true;
220
221 }
222
223
224 final int orderingSign = interpolator.isForward() ? +1 : -1;
225 final Queue<EventState<?>> occurringEvents = new PriorityQueue<>(new Comparator<EventState<?>>() {
226
227 @Override
228 public int compare(final EventState<?> es0, final EventState<?> es1) {
229 return orderingSign * es0.getEventDate().compareTo(es1.getEventDate());
230 }
231 });
232
233 boolean doneWithStep = false;
234 resetEvents:
235 do {
236
237
238 occurringEvents.clear();
239 for (final EventState<?> state : eventStates) {
240 if (state.evaluateStep(interpolator)) {
241
242 occurringEvents.add(state);
243 }
244 }
245
246 do {
247
248 eventLoop:
249 while (!occurringEvents.isEmpty()) {
250
251
252 final EventState<?> currentEvent = occurringEvents.poll();
253
254
255 SpacecraftState eventState = restricted.getInterpolatedState(currentEvent.getEventDate());
256
257
258 restricted = restricted.restrictStep(previous, eventState);
259
260
261 for (final EventState<?> state : eventStates) {
262 if (state != currentEvent && state.tryAdvance(eventState, interpolator)) {
263
264
265 occurringEvents.remove(state);
266
267 occurringEvents.add(state);
268
269 occurringEvents.add(currentEvent);
270 continue eventLoop;
271 }
272 }
273
274
275
276 getMultiplexer().handleStep(restricted);
277
278
279 final EventOccurrence occurrence = currentEvent.doEvent(eventState);
280 final Action action = occurrence.getAction();
281 isLastStep = action == Action.STOP;
282
283 if (isLastStep) {
284
285
286
287
288 final SpacecraftState savedState = eventState;
289 eventState = interpolator.getInterpolatedState(occurrence.getStopDate());
290 restricted = restricted.restrictStep(savedState, eventState);
291
292
293 getMultiplexer().handleStep(restricted);
294 getMultiplexer().finish(restricted.getCurrentState());
295
296 }
297
298 if (isLastStep) {
299
300 return eventState;
301 }
302
303 if (action == Action.RESET_DERIVATIVES || action == Action.RESET_STATE) {
304
305
306 final SpacecraftState resetState = occurrence.getNewState();
307 resetIntermediateState(resetState, interpolator.isForward());
308 eventStates.forEach(es -> es.getEventDetector().reset(resetState, target));
309 return resetState;
310 }
311
312
313
314 previous = eventState;
315 restricted = new BasicStepInterpolator(restricted.isForward(), eventState, current);
316
317 if (action == Action.RESET_EVENTS) {
318 continue resetEvents;
319 }
320
321
322
323 if (currentEvent.evaluateStep(restricted)) {
324
325 occurringEvents.add(currentEvent);
326 }
327
328 }
329
330
331
332
333
334
335
336 for (final EventState<?> state : eventStates) {
337 if (state.tryAdvance(current, interpolator)) {
338 occurringEvents.add(state);
339 }
340 }
341
342 } while (!occurringEvents.isEmpty());
343
344 doneWithStep = true;
345 } while (!doneWithStep);
346
347 isLastStep = target.equals(current.getDate());
348
349
350 getMultiplexer().handleStep(restricted);
351 if (isLastStep) {
352 getMultiplexer().finish(restricted.getCurrentState());
353 }
354
355 return current;
356
357 }
358
359
360
361
362
363 protected abstract double getMass(AbsoluteDate date);
364
365
366
367
368 public PVCoordinatesProvider getPvProvider() {
369 return pvProvider;
370 }
371
372
373
374
375
376
377 protected abstract void resetIntermediateState(SpacecraftState state, boolean forward);
378
379
380
381
382
383 public abstract Orbit propagateOrbit(AbsoluteDate date);
384
385
386
387
388
389
390
391
392
393 public SpacecraftState basicPropagate(final AbsoluteDate date) {
394 try {
395
396
397 final Orbit orbit = propagateOrbit(date);
398
399
400 final Attitude attitude =
401 getAttitudeProvider().getAttitude(pvProvider, date, orbit.getFrame());
402
403
404 return new SpacecraftState(orbit, attitude).withMass(getMass(date));
405
406 } catch (OrekitException oe) {
407 throw new OrekitException(oe);
408 }
409 }
410
411 @Override
412 public void clearMatricesComputation() {
413 final List<AdditionalDataProvider<?>> copiedProviders = new ArrayList<>(getAdditionalDataProviders());
414 copiedProviders.stream().filter(AbstractAnalyticalMatricesHarvester.class::isInstance)
415 .forEach(provider -> removeAdditionalDataProvider(provider.getName()));
416 super.clearMatricesComputation();
417 }
418
419
420
421
422
423
424 protected List<String> getJacobiansColumnsNames() {
425 return Collections.emptyList();
426 }
427
428
429 private class LocalPVProvider implements PVCoordinatesProvider {
430
431
432 public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate date, final Frame frame) {
433 return propagateOrbit(date).getPVCoordinates(frame);
434 }
435
436 }
437
438
439 private class BoundedPropagatorView extends AbstractAnalyticalPropagator implements BoundedPropagator {
440
441
442 private final AbsoluteDate minDate;
443
444
445 private final AbsoluteDate maxDate;
446
447
448
449
450
451 BoundedPropagatorView(final AbsoluteDate startDate, final AbsoluteDate endDate) {
452 super(AbstractAnalyticalPropagator.this.getAttitudeProvider());
453 super.resetInitialState(AbstractAnalyticalPropagator.this.getInitialState());
454 if (startDate.compareTo(endDate) <= 0) {
455 minDate = startDate;
456 maxDate = endDate;
457 } else {
458 minDate = endDate;
459 maxDate = startDate;
460 }
461
462 try {
463
464 for (AdditionalDataProvider<?> provider : AbstractAnalyticalPropagator.this.getAdditionalDataProviders()) {
465 addAdditionalDataProvider(provider);
466 }
467 } catch (OrekitException oe) {
468
469
470 throw new OrekitInternalError(null);
471 }
472
473 }
474
475
476 public AbsoluteDate getMinDate() {
477 return minDate;
478 }
479
480
481 public AbsoluteDate getMaxDate() {
482 return maxDate;
483 }
484
485
486 public Orbit propagateOrbit(final AbsoluteDate target) {
487 return AbstractAnalyticalPropagator.this.propagateOrbit(target);
488 }
489
490
491 public double getMass(final AbsoluteDate date) {
492 return AbstractAnalyticalPropagator.this.getMass(date);
493 }
494
495
496 @Override
497 public void resetInitialState(final SpacecraftState state) {
498 super.resetInitialState(state);
499 AbstractAnalyticalPropagator.this.resetInitialState(state);
500 }
501
502
503 protected void resetIntermediateState(final SpacecraftState state, final boolean forward) {
504 AbstractAnalyticalPropagator.this.resetIntermediateState(state, forward);
505 }
506
507
508 @Override
509 public SpacecraftState getInitialState() {
510 return AbstractAnalyticalPropagator.this.getInitialState();
511 }
512
513
514 @Override
515 public Frame getFrame() {
516 return AbstractAnalyticalPropagator.this.getFrame();
517 }
518
519 }
520
521
522 private class BasicStepInterpolator implements OrekitStepInterpolator {
523
524
525 private final SpacecraftState previousState;
526
527
528 private final SpacecraftState currentState;
529
530
531 private final boolean forward;
532
533
534
535
536
537
538 BasicStepInterpolator(final boolean isForward,
539 final SpacecraftState previousState,
540 final SpacecraftState currentState) {
541 this.forward = isForward;
542 this.previousState = previousState;
543 this.currentState = currentState;
544 }
545
546
547 @Override
548 public SpacecraftState getPreviousState() {
549 return previousState;
550 }
551
552
553 @Override
554 public boolean isPreviousStateInterpolated() {
555
556 return false;
557 }
558
559
560 @Override
561 public SpacecraftState getCurrentState() {
562 return currentState;
563 }
564
565
566 @Override
567 public boolean isCurrentStateInterpolated() {
568
569 return false;
570 }
571
572
573 @Override
574 public SpacecraftState getInterpolatedState(final AbsoluteDate date) {
575
576
577 final SpacecraftState basicState = basicPropagate(date);
578
579
580 return updateAdditionalData(basicState);
581
582 }
583
584
585 @Override
586 public boolean isForward() {
587 return forward;
588 }
589
590
591 @Override
592 public BasicStepInterpolator restrictStep(final SpacecraftState newPreviousState,
593 final SpacecraftState newCurrentState) {
594 return new BasicStepInterpolator(forward, newPreviousState, newCurrentState);
595 }
596
597 }
598
599 }