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