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.io.NotSerializableException;
20 import java.io.Serializable;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.Comparator;
25 import java.util.List;
26 import java.util.PriorityQueue;
27 import java.util.Queue;
28
29 import org.hipparchus.exception.MathRuntimeException;
30 import org.hipparchus.util.FastMath;
31 import org.orekit.attitudes.Attitude;
32 import org.orekit.attitudes.AttitudeProvider;
33 import org.orekit.errors.OrekitException;
34 import org.orekit.errors.OrekitInternalError;
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.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.events.handlers.EventHandler.Action;
45 import org.orekit.propagation.sampling.OrekitStepInterpolator;
46 import org.orekit.time.AbsoluteDate;
47 import org.orekit.utils.PVCoordinatesProvider;
48 import org.orekit.utils.TimeStampedPVCoordinates;
49
50
51
52
53
54
55
56
57
58
59
60
61 public abstract class AbstractAnalyticalPropagator extends AbstractPropagator {
62
63
64 private PVCoordinatesProvider pvProvider;
65
66
67 private AbsoluteDate lastPropagationStart;
68
69
70 private AbsoluteDate lastPropagationEnd;
71
72
73 private boolean statesInitialized;
74
75
76 private boolean isLastStep;
77
78
79 private final Collection<EventState<?>> eventsStates;
80
81
82
83
84 protected AbstractAnalyticalPropagator(final AttitudeProvider attitudeProvider) {
85 setAttitudeProvider(attitudeProvider);
86 pvProvider = new LocalPVProvider();
87 lastPropagationStart = AbsoluteDate.PAST_INFINITY;
88 lastPropagationEnd = AbsoluteDate.FUTURE_INFINITY;
89 statesInitialized = false;
90 eventsStates = new ArrayList<EventState<?>>();
91 }
92
93
94 public BoundedPropagator getGeneratedEphemeris() {
95 return new BoundedPropagatorView(lastPropagationStart, lastPropagationEnd);
96 }
97
98
99 public <T extends EventDetector> void addEventDetector(final T detector) {
100 eventsStates.add(new EventState<T>(detector));
101 }
102
103
104 public Collection<EventDetector> getEventsDetectors() {
105 final List<EventDetector> list = new ArrayList<EventDetector>();
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 AbsoluteDateAbsoluteDate">AbsoluteDate start, final AbsoluteDate target) {
119 try {
120
121 lastPropagationStart = start;
122
123 final double dt = target.durationFrom(start);
124 final double epsilon = FastMath.ulp(dt);
125 SpacecraftState state = updateAdditionalStates(basicPropagate(start));
126
127
128 final double stepSize;
129 if (getMode() == MASTER_MODE) {
130 if (Double.isNaN(getFixedStepSize())) {
131 stepSize = FastMath.copySign(state.getKeplerianPeriod() / 100, dt);
132 } else {
133 stepSize = FastMath.copySign(getFixedStepSize(), dt);
134 }
135 } else {
136 stepSize = dt;
137 }
138
139
140 for (final EventState<?> es : eventsStates) {
141 es.init(state, target);
142 }
143
144
145 if (getStepHandler() != null) {
146 getStepHandler().init(state, target);
147 }
148
149
150 statesInitialized = false;
151 isLastStep = false;
152 do {
153
154
155 final SpacecraftState previous = state;
156 AbsoluteDate t = previous.getDate().shiftedBy(stepSize);
157 if ((dt == 0) || ((dt > 0) ^ (t.compareTo(target) <= 0)) ||
158 (FastMath.abs(target.durationFrom(t)) <= epsilon)) {
159
160
161 t = target;
162 }
163 final SpacecraftState current = updateAdditionalStates(basicPropagate(t));
164 final OrekitStepInterpolator interpolator = new BasicStepInterpolator(dt >= 0, previous, current);
165
166
167
168 state = acceptStep(interpolator, target, epsilon);
169
170 } while (!isLastStep);
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
187
188
189 protected SpacecraftState acceptStep(final OrekitStepInterpolator interpolator,
190 final AbsoluteDate target, final double epsilon)
191 throws MathRuntimeException {
192
193 SpacecraftState previous = interpolator.getPreviousState();
194 final SpacecraftState current = interpolator.getCurrentState();
195
196
197 if (!statesInitialized) {
198
199 if (!eventsStates.isEmpty()) {
200
201 for (final EventState<?> state : eventsStates) {
202 state.reinitializeBegin(interpolator);
203 }
204 }
205
206 statesInitialized = true;
207
208 }
209
210
211 final int orderingSign = interpolator.isForward() ? +1 : -1;
212 final Queue<EventState<?>> occurringEvents = new PriorityQueue<>(new Comparator<EventState<?>>() {
213
214 @Override
215 public int compare(final EventState<?> es0, final EventState<?> es1) {
216 return orderingSign * es0.getEventDate().compareTo(es1.getEventDate());
217 }
218 });
219
220 for (final EventState<?> state : eventsStates) {
221 if (state.evaluateStep(interpolator)) {
222
223 occurringEvents.add(state);
224 }
225 }
226
227 OrekitStepInterpolator restricted = interpolator;
228
229 do {
230
231 eventLoop:
232 while (!occurringEvents.isEmpty()) {
233
234
235 final EventState<?> currentEvent = occurringEvents.poll();
236
237
238 SpacecraftState eventState = restricted.getInterpolatedState(currentEvent.getEventDate());
239
240
241 for (final EventState<?> state : eventsStates) {
242 if (state != currentEvent && state.tryAdvance(eventState, interpolator)) {
243
244
245 occurringEvents.remove(state);
246
247 occurringEvents.add(state);
248
249 occurringEvents.add(currentEvent);
250 continue eventLoop;
251 }
252 }
253
254
255 final EventOccurrence occurrence = currentEvent.doEvent(eventState);
256 final Action action = occurrence.getAction();
257 isLastStep = action == Action.STOP;
258
259 if (isLastStep) {
260
261
262
263 eventState = interpolator.getInterpolatedState(occurrence.getStopDate());
264 restricted = restricted.restrictStep(previous, eventState);
265 }
266
267
268 if (getStepHandler() != null) {
269 getStepHandler().handleStep(restricted, isLastStep);
270 }
271
272 if (isLastStep) {
273
274 return eventState;
275 }
276
277 if (action == Action.RESET_DERIVATIVES || action == Action.RESET_STATE) {
278
279
280 final SpacecraftState resetState = occurrence.getNewState();
281 if (resetState != null) {
282 resetIntermediateState(resetState, interpolator.isForward());
283 return resetState;
284 }
285 }
286
287
288
289 previous = eventState;
290 restricted = new BasicStepInterpolator(restricted.isForward(), eventState, current);
291
292
293 if (currentEvent.evaluateStep(restricted)) {
294
295 occurringEvents.add(currentEvent);
296 }
297
298 }
299
300
301
302
303 for (final EventState<?> state : eventsStates) {
304 if (state.tryAdvance(current, interpolator)) {
305 occurringEvents.add(state);
306 }
307 }
308
309 } while (!occurringEvents.isEmpty());
310
311 isLastStep = target.equals(current.getDate());
312
313
314 if (getStepHandler() != null) {
315 getStepHandler().handleStep(interpolator, isLastStep);
316 }
317
318 return current;
319
320 }
321
322
323
324
325
326 protected abstract double getMass(AbsoluteDate date);
327
328
329
330
331 public PVCoordinatesProvider getPvProvider() {
332 return pvProvider;
333 }
334
335
336
337
338
339
340 protected abstract void resetIntermediateState(SpacecraftState state, boolean forward);
341
342
343
344
345
346 protected abstract Orbit propagateOrbit(AbsoluteDate date);
347
348
349
350
351
352
353
354
355
356 protected SpacecraftState basicPropagate(final AbsoluteDate date) {
357 try {
358
359
360 final Orbit orbit = propagateOrbit(date);
361
362
363 final Attitude attitude =
364 getAttitudeProvider().getAttitude(pvProvider, date, orbit.getFrame());
365
366
367 return new SpacecraftState(orbit, attitude, getMass(date));
368
369 } catch (OrekitException oe) {
370 throw new OrekitException(oe);
371 }
372 }
373
374
375 private class LocalPVProvider implements PVCoordinatesProvider {
376
377
378 public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate date, final Frame frame) {
379 return propagateOrbit(date).getPVCoordinates(frame);
380 }
381
382 }
383
384
385 private class BoundedPropagatorView
386 extends AbstractAnalyticalPropagator
387 implements BoundedPropagator, Serializable {
388
389
390 private static final long serialVersionUID = 20151117L;
391
392
393 private final AbsoluteDate minDate;
394
395
396 private final AbsoluteDate maxDate;
397
398
399
400
401
402 BoundedPropagatorView(final AbsoluteDateluteDate">AbsoluteDate startDate, final AbsoluteDate endDate) {
403 super(AbstractAnalyticalPropagator.this.getAttitudeProvider());
404 if (startDate.compareTo(endDate) <= 0) {
405 minDate = startDate;
406 maxDate = endDate;
407 } else {
408 minDate = endDate;
409 maxDate = startDate;
410 }
411
412 try {
413
414 for (AdditionalStateProvider provider : AbstractAnalyticalPropagator.this.getAdditionalStateProviders()) {
415 addAdditionalStateProvider(provider);
416 }
417 } catch (OrekitException oe) {
418
419
420 throw new OrekitInternalError(null);
421 }
422
423 }
424
425
426 public AbsoluteDate getMinDate() {
427 return minDate;
428 }
429
430
431 public AbsoluteDate getMaxDate() {
432 return maxDate;
433 }
434
435
436 protected Orbit propagateOrbit(final AbsoluteDate target) {
437 return AbstractAnalyticalPropagator.this.propagateOrbit(target);
438 }
439
440
441 public double getMass(final AbsoluteDate date) {
442 return AbstractAnalyticalPropagator.this.getMass(date);
443 }
444
445
446 public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate date, final Frame frame) {
447 return propagate(date).getPVCoordinates(frame);
448 }
449
450
451 public void resetInitialState(final SpacecraftState state) {
452 AbstractAnalyticalPropagator.this.resetInitialState(state);
453 }
454
455
456 protected void resetIntermediateState(final SpacecraftState state, final boolean forward) {
457 AbstractAnalyticalPropagator.this.resetIntermediateState(state, forward);
458 }
459
460
461 public SpacecraftState getInitialState() {
462 return AbstractAnalyticalPropagator.this.getInitialState();
463 }
464
465
466 public Frame getFrame() {
467 return AbstractAnalyticalPropagator.this.getFrame();
468 }
469
470
471
472
473
474
475 private Object writeReplace() throws NotSerializableException {
476 return new DataTransferObject(minDate, maxDate, AbstractAnalyticalPropagator.this);
477 }
478
479 }
480
481
482 private static class DataTransferObject implements Serializable {
483
484
485 private static final long serialVersionUID = 20151117L;
486
487
488 private final AbsoluteDate minDate;
489
490
491 private final AbsoluteDate maxDate;
492
493
494 private final AbstractAnalyticalPropagator propagator;
495
496
497
498
499
500
501 DataTransferObject(final AbsoluteDatesoluteDate">AbsoluteDate minDate, final AbsoluteDate maxDate,
502 final AbstractAnalyticalPropagator propagator) {
503 this.minDate = minDate;
504 this.maxDate = maxDate;
505 this.propagator = propagator;
506 }
507
508
509
510
511 private Object readResolve() {
512 propagator.lastPropagationStart = minDate;
513 propagator.lastPropagationEnd = maxDate;
514 return propagator.getGeneratedEphemeris();
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 updateAdditionalStates(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 }