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