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 @Override
410 public void clearMatricesComputation() {
411 final List<AdditionalDataProvider<?>> copiedProviders = new ArrayList<>(getAdditionalDataProviders());
412 copiedProviders.stream().filter(AbstractAnalyticalMatricesHarvester.class::isInstance)
413 .forEach(provider -> removeAdditionalDataProvider(provider.getName()));
414 super.clearMatricesComputation();
415 }
416
417
418
419
420
421
422 protected List<String> getJacobiansColumnsNames() {
423 return Collections.emptyList();
424 }
425
426
427 private class LocalPVProvider implements PVCoordinatesProvider {
428
429
430 public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate date, final Frame frame) {
431 return propagateOrbit(date).getPVCoordinates(frame);
432 }
433
434 }
435
436
437 private class BoundedPropagatorView extends AbstractAnalyticalPropagator implements BoundedPropagator {
438
439
440 private final AbsoluteDate minDate;
441
442
443 private final AbsoluteDate maxDate;
444
445
446
447
448
449 BoundedPropagatorView(final AbsoluteDate startDate, final AbsoluteDate endDate) {
450 super(AbstractAnalyticalPropagator.this.getAttitudeProvider());
451 super.resetInitialState(AbstractAnalyticalPropagator.this.getInitialState());
452 if (startDate.compareTo(endDate) <= 0) {
453 minDate = startDate;
454 maxDate = endDate;
455 } else {
456 minDate = endDate;
457 maxDate = startDate;
458 }
459
460 try {
461
462 for (AdditionalDataProvider<?> provider : AbstractAnalyticalPropagator.this.getAdditionalDataProviders()) {
463 addAdditionalDataProvider(provider);
464 }
465 } catch (OrekitException oe) {
466
467
468 throw new OrekitInternalError(null);
469 }
470
471 }
472
473
474 public AbsoluteDate getMinDate() {
475 return minDate;
476 }
477
478
479 public AbsoluteDate getMaxDate() {
480 return maxDate;
481 }
482
483
484 public Orbit propagateOrbit(final AbsoluteDate target) {
485 return AbstractAnalyticalPropagator.this.propagateOrbit(target);
486 }
487
488
489 public double getMass(final AbsoluteDate date) {
490 return AbstractAnalyticalPropagator.this.getMass(date);
491 }
492
493
494 @Override
495 public void resetInitialState(final SpacecraftState state) {
496 super.resetInitialState(state);
497 AbstractAnalyticalPropagator.this.resetInitialState(state);
498 }
499
500
501 protected void resetIntermediateState(final SpacecraftState state, final boolean forward) {
502 AbstractAnalyticalPropagator.this.resetIntermediateState(state, forward);
503 }
504
505
506 @Override
507 public SpacecraftState getInitialState() {
508 return AbstractAnalyticalPropagator.this.getInitialState();
509 }
510
511
512 @Override
513 public Frame getFrame() {
514 return AbstractAnalyticalPropagator.this.getFrame();
515 }
516
517 }
518
519
520 private class BasicStepInterpolator implements OrekitStepInterpolator {
521
522
523 private final SpacecraftState previousState;
524
525
526 private final SpacecraftState currentState;
527
528
529 private final boolean forward;
530
531
532
533
534
535
536 BasicStepInterpolator(final boolean isForward,
537 final SpacecraftState previousState,
538 final SpacecraftState currentState) {
539 this.forward = isForward;
540 this.previousState = previousState;
541 this.currentState = currentState;
542 }
543
544
545 @Override
546 public SpacecraftState getPreviousState() {
547 return previousState;
548 }
549
550
551 @Override
552 public boolean isPreviousStateInterpolated() {
553
554 return false;
555 }
556
557
558 @Override
559 public SpacecraftState getCurrentState() {
560 return currentState;
561 }
562
563
564 @Override
565 public boolean isCurrentStateInterpolated() {
566
567 return false;
568 }
569
570
571 @Override
572 public SpacecraftState getInterpolatedState(final AbsoluteDate date) {
573
574
575 final SpacecraftState basicState = basicPropagate(date);
576
577
578 return updateAdditionalData(basicState);
579
580 }
581
582
583 @Override
584 public boolean isForward() {
585 return forward;
586 }
587
588
589 @Override
590 public BasicStepInterpolator restrictStep(final SpacecraftState newPreviousState,
591 final SpacecraftState newCurrentState) {
592 return new BasicStepInterpolator(forward, newPreviousState, newCurrentState);
593 }
594
595 }
596
597 }