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