1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.integration;
18
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25
26 import org.apache.commons.math3.exception.MathIllegalArgumentException;
27 import org.apache.commons.math3.exception.MathIllegalStateException;
28 import org.apache.commons.math3.ode.AbstractIntegrator;
29 import org.apache.commons.math3.ode.ContinuousOutputModel;
30 import org.apache.commons.math3.ode.EquationsMapper;
31 import org.apache.commons.math3.ode.ExpandableStatefulODE;
32 import org.apache.commons.math3.ode.FirstOrderDifferentialEquations;
33 import org.apache.commons.math3.ode.SecondaryEquations;
34 import org.apache.commons.math3.ode.sampling.StepHandler;
35 import org.apache.commons.math3.ode.sampling.StepInterpolator;
36 import org.apache.commons.math3.util.Precision;
37 import org.orekit.attitudes.AttitudeProvider;
38 import org.orekit.errors.OrekitException;
39 import org.orekit.errors.OrekitExceptionWrapper;
40 import org.orekit.errors.OrekitMessages;
41 import org.orekit.errors.PropagationException;
42 import org.orekit.frames.Frame;
43 import org.orekit.orbits.Orbit;
44 import org.orekit.orbits.OrbitType;
45 import org.orekit.orbits.PositionAngle;
46 import org.orekit.propagation.AbstractPropagator;
47 import org.orekit.propagation.BoundedPropagator;
48 import org.orekit.propagation.SpacecraftState;
49 import org.orekit.propagation.events.EventDetector;
50 import org.orekit.propagation.events.handlers.EventHandler;
51 import org.orekit.propagation.sampling.OrekitStepHandler;
52 import org.orekit.propagation.sampling.OrekitStepInterpolator;
53 import org.orekit.time.AbsoluteDate;
54
55
56
57
58
59
60 public abstract class AbstractIntegratedPropagator extends AbstractPropagator {
61
62
63 private final List<EventDetector> detectors;
64
65
66 private final AbstractIntegrator integrator;
67
68
69 private ModeHandler modeHandler;
70
71
72 private List<AdditionalEquations> additionalEquations;
73
74
75 private int calls;
76
77
78 private StateMapper stateMapper;
79
80
81 private ExpandableStatefulODE mathODE;
82
83
84 private StepInterpolator mathInterpolator;
85
86
87
88
89
90
91
92 private boolean meanOrbit;
93
94
95
96
97
98 protected AbstractIntegratedPropagator(final AbstractIntegrator integrator, final boolean meanOrbit) {
99 detectors = new ArrayList<EventDetector>();
100 additionalEquations = new ArrayList<AdditionalEquations>();
101 this.integrator = integrator;
102 this.meanOrbit = meanOrbit;
103 }
104
105
106 protected void initMapper() {
107 stateMapper = createMapper(null, Double.NaN, null, null, null, null);
108 }
109
110
111 public void setAttitudeProvider(final AttitudeProvider attitudeProvider) {
112 super.setAttitudeProvider(attitudeProvider);
113 stateMapper = createMapper(stateMapper.getReferenceDate(), stateMapper.getMu(),
114 stateMapper.getOrbitType(), stateMapper.getPositionAngleType(),
115 attitudeProvider, stateMapper.getFrame());
116 }
117
118
119
120
121 protected void setOrbitType(final OrbitType orbitType) {
122 stateMapper = createMapper(stateMapper.getReferenceDate(), stateMapper.getMu(),
123 orbitType, stateMapper.getPositionAngleType(),
124 stateMapper.getAttitudeProvider(), stateMapper.getFrame());
125 }
126
127
128
129
130 protected OrbitType getOrbitType() {
131 return stateMapper.getOrbitType();
132 }
133
134
135
136
137 protected boolean isMeanOrbit() {
138 return meanOrbit;
139 }
140
141
142
143
144
145
146
147
148
149
150 protected void setPositionAngleType(final PositionAngle positionAngleType) {
151 stateMapper = createMapper(stateMapper.getReferenceDate(), stateMapper.getMu(),
152 stateMapper.getOrbitType(), positionAngleType,
153 stateMapper.getAttitudeProvider(), stateMapper.getFrame());
154 }
155
156
157
158
159 protected PositionAngle getPositionAngleType() {
160 return stateMapper.getPositionAngleType();
161 }
162
163
164
165
166 public void setMu(final double mu) {
167 stateMapper = createMapper(stateMapper.getReferenceDate(), mu,
168 stateMapper.getOrbitType(), stateMapper.getPositionAngleType(),
169 stateMapper.getAttitudeProvider(), stateMapper.getFrame());
170 }
171
172
173
174
175
176 public double getMu() {
177 return stateMapper.getMu();
178 }
179
180
181
182
183
184
185 public int getCalls() {
186 return calls;
187 }
188
189
190 @Override
191 public boolean isAdditionalStateManaged(final String name) {
192
193
194 if (super.isAdditionalStateManaged(name)) {
195 return true;
196 }
197
198
199 for (final AdditionalEquations equation : additionalEquations) {
200 if (equation.getName().equals(name)) {
201 return true;
202 }
203 }
204
205 return false;
206 }
207
208
209 @Override
210 public String[] getManagedAdditionalStates() {
211 final String[] alreadyIntegrated = super.getManagedAdditionalStates();
212 final String[] managed = new String[alreadyIntegrated.length + additionalEquations.size()];
213 System.arraycopy(alreadyIntegrated, 0, managed, 0, alreadyIntegrated.length);
214 for (int i = 0; i < additionalEquations.size(); ++i) {
215 managed[i + alreadyIntegrated.length] = additionalEquations.get(i).getName();
216 }
217 return managed;
218 }
219
220
221
222
223
224 public void addAdditionalEquations(final AdditionalEquations additional)
225 throws OrekitException {
226
227
228 if (isAdditionalStateManaged(additional.getName())) {
229
230 throw new OrekitException(OrekitMessages.ADDITIONAL_STATE_NAME_ALREADY_IN_USE,
231 additional.getName());
232 }
233
234
235 additionalEquations.add(additional);
236
237 }
238
239
240 public void addEventDetector(final EventDetector detector) {
241 detectors.add(detector);
242 }
243
244
245 public Collection<EventDetector> getEventsDetectors() {
246 return Collections.unmodifiableCollection(detectors);
247 }
248
249
250 public void clearEventsDetectors() {
251 detectors.clear();
252 }
253
254
255
256 protected void setUpUserEventDetectors() {
257 for (final EventDetector detector : detectors) {
258 setUpEventDetector(integrator, detector);
259 }
260 }
261
262
263
264
265
266 protected void setUpEventDetector(final AbstractIntegrator integ, final EventDetector detector) {
267 integ.addEventHandler(new AdaptedEventDetector(detector),
268 detector.getMaxCheckInterval(),
269 detector.getThreshold(),
270 detector.getMaxIterationCount());
271 }
272
273
274
275
276
277
278
279 public void setSlaveMode() {
280 super.setSlaveMode();
281 if (integrator != null) {
282 integrator.clearStepHandlers();
283 }
284 modeHandler = null;
285 }
286
287
288
289
290
291
292
293 public void setMasterMode(final OrekitStepHandler handler) {
294 super.setMasterMode(handler);
295 integrator.clearStepHandlers();
296 final AdaptedStepHandler wrapped = new AdaptedStepHandler(handler);
297 integrator.addStepHandler(wrapped);
298 modeHandler = wrapped;
299 }
300
301
302
303
304
305
306
307 public void setEphemerisMode() {
308 super.setEphemerisMode();
309 integrator.clearStepHandlers();
310 final EphemerisModeHandler ephemeris = new EphemerisModeHandler();
311 modeHandler = ephemeris;
312 integrator.addStepHandler(ephemeris);
313 }
314
315
316 public BoundedPropagator getGeneratedEphemeris()
317 throws IllegalStateException {
318 if (getMode() != EPHEMERIS_GENERATION_MODE) {
319 throw OrekitException.createIllegalStateException(OrekitMessages.PROPAGATOR_NOT_IN_EPHEMERIS_GENERATION_MODE);
320 }
321 return ((EphemerisModeHandler) modeHandler).getEphemeris();
322 }
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340 protected abstract StateMapper createMapper(final AbsoluteDate referenceDate, final double mu,
341 final OrbitType orbitType, final PositionAngle positionAngleType,
342 final AttitudeProvider attitudeProvider, final Frame frame);
343
344
345
346
347
348 protected abstract MainStateEquations getMainStateEquations(final AbstractIntegrator integ);
349
350
351 public SpacecraftState propagate(final AbsoluteDate target) throws PropagationException {
352 try {
353 if (getStartDate() == null) {
354 if (getInitialState() == null) {
355 throw new PropagationException(OrekitMessages.INITIAL_STATE_NOT_SPECIFIED_FOR_ORBIT_PROPAGATION);
356 }
357 setStartDate(getInitialState().getDate());
358 }
359 return propagate(getStartDate(), target);
360 } catch (OrekitException oe) {
361
362
363 for (Throwable t = oe; t != null; t = t.getCause()) {
364 if (t instanceof PropagationException) {
365 throw (PropagationException) t;
366 }
367 }
368 throw new PropagationException(oe);
369
370 }
371 }
372
373
374 public SpacecraftState propagate(final AbsoluteDate tStart, final AbsoluteDate tEnd)
375 throws PropagationException {
376 try {
377
378 if (getInitialState() == null) {
379 throw new PropagationException(OrekitMessages.INITIAL_STATE_NOT_SPECIFIED_FOR_ORBIT_PROPAGATION);
380 }
381
382 if (!tStart.equals(getInitialState().getDate())) {
383
384
385 propagate(tStart, false);
386 }
387
388
389 return propagate(tEnd, true);
390
391 } catch (OrekitException oe) {
392
393
394 for (Throwable t = oe; t != null; t = t.getCause()) {
395 if (t instanceof PropagationException) {
396 throw (PropagationException) t;
397 }
398 }
399 throw new PropagationException(oe);
400
401 }
402 }
403
404
405
406
407
408
409
410 protected SpacecraftState propagate(final AbsoluteDate tEnd, final boolean activateHandlers)
411 throws PropagationException {
412 try {
413
414 if (getInitialState().getDate().equals(tEnd)) {
415
416 return getInitialState();
417 }
418
419
420 stateMapper = createMapper(getInitialState().getDate(), stateMapper.getMu(),
421 stateMapper.getOrbitType(), stateMapper.getPositionAngleType(),
422 stateMapper.getAttitudeProvider(), getInitialState().getFrame());
423
424
425
426 final Orbit initialOrbit = stateMapper.getOrbitType().convertType(getInitialState().getOrbit());
427 if (Double.isNaN(getMu())) {
428 setMu(initialOrbit.getMu());
429 }
430
431 if (getInitialState().getMass() <= 0.0) {
432 throw new PropagationException(OrekitMessages.SPACECRAFT_MASS_BECOMES_NEGATIVE,
433 getInitialState().getMass());
434 }
435
436 integrator.clearEventHandlers();
437
438
439 setUpUserEventDetectors();
440
441
442 mathODE = createODE(integrator);
443 mathInterpolator = null;
444
445
446 if (modeHandler != null) {
447 modeHandler.initialize(activateHandlers);
448 }
449
450
451 try {
452 beforeIntegration(getInitialState(), tEnd);
453 integrator.integrate(mathODE, tEnd.durationFrom(getInitialState().getDate()));
454 afterIntegration();
455 } catch (OrekitExceptionWrapper oew) {
456 throw oew.getException();
457 }
458
459
460 SpacecraftState finalState =
461 stateMapper.mapArrayToState(mathODE.getTime(), mathODE.getPrimaryState(), meanOrbit);
462 finalState = updateAdditionalStates(finalState);
463 for (int i = 0; i < additionalEquations.size(); ++i) {
464 final double[] secondary = mathODE.getSecondaryState(i);
465 finalState = finalState.addAdditionalState(additionalEquations.get(i).getName(),
466 secondary);
467 }
468 resetInitialState(finalState);
469 setStartDate(finalState.getDate());
470
471 return finalState;
472
473 } catch (PropagationException pe) {
474 throw pe;
475 } catch (OrekitException oe) {
476 throw new PropagationException(oe);
477 } catch (MathIllegalArgumentException miae) {
478 throw PropagationException.unwrap(miae);
479 } catch (MathIllegalStateException mise) {
480 throw PropagationException.unwrap(mise);
481 }
482 }
483
484
485
486
487
488
489 private ExpandableStatefulODE createODE(final AbstractIntegrator integ)
490 throws OrekitException {
491
492
493 final double[] initialStateVector = new double[getBasicDimension()];
494 stateMapper.mapStateToArray(getInitialState(), initialStateVector);
495
496
497 final ExpandableStatefulODE ode =
498 new ExpandableStatefulODE(new ConvertedMainStateEquations(getMainStateEquations(integ)));
499 ode.setTime(0.0);
500 ode.setPrimaryState(initialStateVector);
501
502
503 for (int i = 0; i < additionalEquations.size(); ++i) {
504 final AdditionalEquations additional = additionalEquations.get(i);
505 final double[] data = getInitialState().getAdditionalState(additional.getName());
506 final SecondaryEquations secondary =
507 new ConvertedSecondaryStateEquations(additional, data.length);
508 ode.addSecondaryEquations(secondary);
509 ode.setSecondaryState(i, data);
510 }
511
512 return ode;
513
514 }
515
516
517
518
519
520
521
522
523
524 protected void beforeIntegration(final SpacecraftState initialState,
525 final AbsoluteDate tEnd)
526 throws OrekitException {
527
528 }
529
530
531
532
533
534
535
536 protected void afterIntegration()
537 throws OrekitException {
538
539 }
540
541
542
543
544 public int getBasicDimension() {
545 return 7;
546
547 }
548
549
550
551
552 protected AbstractIntegrator getIntegrator() {
553 return integrator;
554 }
555
556
557
558
559
560
561
562 private SpacecraftState getCompleteState(final double t, final double[] y)
563 throws OrekitException {
564
565
566 SpacecraftState state = stateMapper.mapArrayToState(t, y, true);
567
568
569 state = updateAdditionalStates(state);
570
571
572 if (!additionalEquations.isEmpty()) {
573
574 final EquationsMapper[] em = mathODE.getSecondaryMappers();
575 for (int i = 0; i < additionalEquations.size(); ++i) {
576 final double[] secondary = new double[em[i].getDimension()];
577 System.arraycopy(y, em[i].getFirstIndex(), secondary, 0, secondary.length);
578 state = state.addAdditionalState(additionalEquations.get(i).getName(), secondary);
579 }
580
581 }
582
583 return state;
584
585 }
586
587
588 public interface MainStateEquations {
589
590
591
592
593
594
595 double[] computeDerivatives(final SpacecraftState state) throws OrekitException;
596
597 }
598
599
600 private class ConvertedMainStateEquations implements FirstOrderDifferentialEquations {
601
602
603 private final MainStateEquations main;
604
605
606
607
608 public ConvertedMainStateEquations(final MainStateEquations main) {
609 this.main = main;
610 calls = 0;
611 }
612
613
614 public int getDimension() {
615 return getBasicDimension();
616 }
617
618
619 public void computeDerivatives(final double t, final double[] y, final double[] yDot)
620 throws OrekitExceptionWrapper {
621
622 try {
623
624
625
626 SpacecraftState currentState = stateMapper.mapArrayToState(t, y, true);
627 currentState = updateAdditionalStates(currentState);
628
629
630 final double[] mainDot = main.computeDerivatives(currentState);
631 System.arraycopy(mainDot, 0, yDot, 0, mainDot.length);
632
633 } catch (OrekitException oe) {
634 throw new OrekitExceptionWrapper(oe);
635 }
636
637
638
639 ++calls;
640
641 }
642
643 }
644
645
646 private class ConvertedSecondaryStateEquations implements SecondaryEquations {
647
648
649 private final AdditionalEquations equations;
650
651
652 private final int dimension;
653
654
655
656
657
658 public ConvertedSecondaryStateEquations(final AdditionalEquations equations,
659 final int dimension) {
660 this.equations = equations;
661 this.dimension = dimension;
662 }
663
664
665 public int getDimension() {
666 return dimension;
667 }
668
669
670 public void computeDerivatives(final double t, final double[] primary,
671 final double[] primaryDot, final double[] secondary,
672 final double[] secondaryDot)
673 throws OrekitExceptionWrapper {
674
675 try {
676
677
678
679 SpacecraftState currentState = stateMapper.mapArrayToState(t, primary, true);
680 currentState = updateAdditionalStates(currentState);
681 currentState = currentState.addAdditionalState(equations.getName(), secondary);
682
683
684 final double[] additionalMainDot =
685 equations.computeDerivatives(currentState, secondaryDot);
686 if (additionalMainDot != null) {
687
688 for (int i = 0; i < additionalMainDot.length; ++i) {
689 primaryDot[i] += additionalMainDot[i];
690 }
691 }
692
693 } catch (OrekitException oe) {
694 throw new OrekitExceptionWrapper(oe);
695 }
696
697 }
698
699 }
700
701
702
703
704
705
706 private class AdaptedEventDetector
707 implements org.apache.commons.math3.ode.events.EventHandler {
708
709
710 private final EventDetector detector;
711
712
713 private double lastT;
714
715
716 private double lastG;
717
718
719
720
721 public AdaptedEventDetector(final EventDetector detector) {
722 this.detector = detector;
723 this.lastT = Double.NaN;
724 this.lastG = Double.NaN;
725 }
726
727
728 public void init(final double t0, final double[] y0, final double t) {
729 try {
730
731 detector.init(getCompleteState(t0, y0), stateMapper.mapDoubleToDate(t));
732 this.lastT = Double.NaN;
733 this.lastG = Double.NaN;
734
735 } catch (OrekitException oe) {
736 throw new OrekitExceptionWrapper(oe);
737 }
738 }
739
740
741 public double g(final double t, final double[] y) {
742 try {
743 if (!Precision.equals(lastT, t, 1)) {
744 lastT = t;
745 lastG = detector.g(getCompleteState(t, y));
746 }
747 return lastG;
748 } catch (OrekitException oe) {
749 throw new OrekitExceptionWrapper(oe);
750 }
751 }
752
753
754 public Action eventOccurred(final double t, final double[] y, final boolean increasing) {
755 try {
756
757 final EventHandler.Action whatNext = detector.eventOccurred(getCompleteState(t, y), increasing);
758
759 switch (whatNext) {
760 case STOP :
761 return Action.STOP;
762 case RESET_STATE :
763 return Action.RESET_STATE;
764 case RESET_DERIVATIVES :
765 return Action.RESET_DERIVATIVES;
766 default :
767 return Action.CONTINUE;
768 }
769 } catch (OrekitException oe) {
770 throw new OrekitExceptionWrapper(oe);
771 }
772 }
773
774
775 public void resetState(final double t, final double[] y) {
776 try {
777 final SpacecraftState newState = detector.resetState(getCompleteState(t, y));
778
779
780 stateMapper.mapStateToArray(newState, y);
781
782
783 final EquationsMapper[] em = mathODE.getSecondaryMappers();
784 for (int i = 0; i < additionalEquations.size(); ++i) {
785 final double[] secondary =
786 newState.getAdditionalState(additionalEquations.get(i).getName());
787 System.arraycopy(secondary, 0, y, em[i].getFirstIndex(), secondary.length);
788 }
789
790 } catch (OrekitException oe) {
791 throw new OrekitExceptionWrapper(oe);
792 }
793 }
794
795 }
796
797
798
799
800
801 private class AdaptedStepHandler
802 implements OrekitStepInterpolator, StepHandler, ModeHandler {
803
804
805 private final OrekitStepHandler handler;
806
807
808 private boolean activate;
809
810
811
812
813 public AdaptedStepHandler(final OrekitStepHandler handler) {
814 this.handler = handler;
815 }
816
817
818 public void initialize(final boolean activateHandlers) {
819 this.activate = activateHandlers;
820 }
821
822
823 public void init(final double t0, final double[] y0, final double t) {
824 try {
825 handler.init(getCompleteState(t0, y0), stateMapper.mapDoubleToDate(t));
826 } catch (OrekitException oe) {
827 throw new OrekitExceptionWrapper(oe);
828 }
829 }
830
831
832 public void handleStep(final StepInterpolator interpolator, final boolean isLast) {
833 try {
834 mathInterpolator = interpolator;
835 if (activate) {
836 handler.handleStep(this, isLast);
837 }
838 } catch (PropagationException pe) {
839 throw new OrekitExceptionWrapper(pe);
840 }
841 }
842
843
844
845
846 public AbsoluteDate getCurrentDate() {
847 return stateMapper.mapDoubleToDate(mathInterpolator.getCurrentTime());
848 }
849
850
851
852
853 public AbsoluteDate getPreviousDate() {
854 return stateMapper.mapDoubleToDate(mathInterpolator.getPreviousTime());
855 }
856
857
858
859
860
861
862
863
864
865 public AbsoluteDate getInterpolatedDate() {
866 return stateMapper.mapDoubleToDate(mathInterpolator.getInterpolatedTime());
867 }
868
869
870
871
872
873
874
875
876 public void setInterpolatedDate(final AbsoluteDate date) {
877 mathInterpolator.setInterpolatedTime(stateMapper.mapDateToDouble(date));
878 }
879
880
881
882
883
884
885
886 public SpacecraftState getInterpolatedState() throws OrekitException {
887 try {
888
889 SpacecraftState s =
890 stateMapper.mapArrayToState(mathInterpolator.getInterpolatedTime(),
891 mathInterpolator.getInterpolatedState(),
892 meanOrbit);
893 s = updateAdditionalStates(s);
894 for (int i = 0; i < additionalEquations.size(); ++i) {
895 final double[] secondary = mathInterpolator.getInterpolatedSecondaryState(i);
896 s = s.addAdditionalState(additionalEquations.get(i).getName(), secondary);
897 }
898
899 return s;
900
901 } catch (OrekitExceptionWrapper oew) {
902 throw oew.getException();
903 }
904 }
905
906
907
908
909 public boolean isForward() {
910 return mathInterpolator.isForward();
911 }
912
913 }
914
915 private class EphemerisModeHandler implements ModeHandler, StepHandler {
916
917
918 private ContinuousOutputModel model;
919
920
921 private BoundedPropagator ephemeris;
922
923
924 private boolean activate;
925
926
927
928
929 public EphemerisModeHandler() {
930 }
931
932
933 public void initialize(final boolean activateHandlers) {
934 this.activate = activateHandlers;
935 this.model = new ContinuousOutputModel();
936
937
938 this.ephemeris = null;
939
940 }
941
942
943
944
945 public BoundedPropagator getEphemeris() {
946 return ephemeris;
947 }
948
949
950 public void handleStep(final StepInterpolator interpolator, final boolean isLast)
951 throws OrekitExceptionWrapper {
952 try {
953 if (activate) {
954 model.handleStep(interpolator, isLast);
955 if (isLast) {
956
957
958 final double tI = model.getInitialTime();
959 final double tF = model.getFinalTime();
960 final AbsoluteDate startDate = stateMapper.mapDoubleToDate(tI);
961 final AbsoluteDate minDate;
962 final AbsoluteDate maxDate;
963 if (tF < tI) {
964 minDate = stateMapper.mapDoubleToDate(tF);
965 maxDate = startDate;
966 } else {
967 minDate = startDate;
968 maxDate = stateMapper.mapDoubleToDate(tF);
969 }
970
971
972 final Map<String, double[]> unmanaged = new HashMap<String, double[]>();
973 for (final Map.Entry<String, double[]> initial : getInitialState().getAdditionalStates().entrySet()) {
974 if (!isAdditionalStateManaged(initial.getKey())) {
975
976
977 unmanaged.put(initial.getKey(), initial.getValue());
978 }
979 }
980
981
982 final String[] names = new String[additionalEquations.size()];
983 for (int i = 0; i < names.length; ++i) {
984 names[i] = additionalEquations.get(i).getName();
985 }
986
987
988 ephemeris = new IntegratedEphemeris(startDate, minDate, maxDate,
989 stateMapper, meanOrbit, model, unmanaged,
990 getAdditionalStateProviders(), names);
991
992 }
993 }
994 } catch (OrekitException oe) {
995 throw new OrekitExceptionWrapper(oe);
996 }
997 }
998
999
1000 public void init(final double t0, final double[] y0, final double t) {
1001 model.init(t0, y0, t);
1002 }
1003
1004 }
1005
1006 }