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