1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.events;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.complex.Complex;
22 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
23 import org.hipparchus.util.Binary64Field;
24 import org.hipparchus.util.FastMath;
25 import org.hipparchus.util.MathUtils;
26 import org.junit.jupiter.api.Assertions;
27 import org.junit.jupiter.api.BeforeEach;
28 import org.junit.jupiter.api.Test;
29 import org.mockito.Mockito;
30 import org.orekit.Utils;
31 import org.orekit.frames.FramesFactory;
32 import org.orekit.orbits.FieldCartesianOrbit;
33 import org.orekit.orbits.FieldKeplerianOrbit;
34 import org.orekit.orbits.FieldOrbit;
35 import org.orekit.orbits.Orbit;
36 import org.orekit.orbits.OrbitType;
37 import org.orekit.propagation.FieldPropagator;
38 import org.orekit.propagation.FieldSpacecraftState;
39 import org.orekit.propagation.analytical.FieldEcksteinHechlerPropagator;
40 import org.orekit.propagation.events.FieldEventsLogger.FieldLoggedEvent;
41 import org.orekit.propagation.events.handlers.FieldContinueOnEvent;
42 import org.orekit.propagation.events.intervals.AdaptableInterval;
43 import org.orekit.propagation.events.intervals.ApsideDetectionAdaptableIntervalFactory;
44 import org.orekit.propagation.events.intervals.FieldAdaptableInterval;
45 import org.orekit.time.FieldAbsoluteDate;
46 import org.orekit.time.TimeScale;
47 import org.orekit.time.TimeScalesFactory;
48 import org.orekit.utils.Constants;
49 import org.orekit.utils.FieldPVCoordinates;
50
51 class FieldApsideDetectorTest {
52
53 @Test
54 void testSimple() {
55 doTestSimple(Binary64Field.getInstance());
56 }
57
58 private <T extends CalculusFieldElement<T>> void doTestSimple(Field<T> field) {
59
60 final FieldPropagator<T> propagator = createPropagator(field);
61 FieldEventDetector<T> detector = new FieldApsideDetector<>(propagator.getInitialState().getOrbit()).
62 withMaxCheck(600.0).
63 withThreshold(field.getZero().newInstance(1.0e-12)).
64 withHandler(new FieldContinueOnEvent<T>());
65
66 Assertions.assertEquals(600.0, detector.getMaxCheckInterval().currentInterval(null, true), 1.0e-15);
67 Assertions.assertEquals(1.0e-12, detector.getThreshold().getReal(), 1.0e-15);
68 Assertions.assertEquals(AbstractDetector.DEFAULT_MAX_ITER, detector.getMaxIterationCount());
69
70 FieldEventsLogger<T> logger = new FieldEventsLogger<>();
71 propagator.addEventDetector(logger.monitorDetector(detector));
72
73 propagator.propagate(propagator.getInitialState().getOrbit().getDate().shiftedBy(Constants.JULIAN_DAY));
74
75 Assertions.assertEquals(30, logger.getLoggedEvents().size());
76 for (FieldLoggedEvent<T> e : logger.getLoggedEvents()) {
77 FieldKeplerianOrbit<T> o = (FieldKeplerianOrbit<T>) OrbitType.KEPLERIAN.convertType(e.getState().getOrbit());
78 double expected = e.isIncreasing() ? 0.0 : FastMath.PI;
79 Assertions.assertEquals(expected, MathUtils.normalizeAngle(o.getMeanAnomaly().getReal(), expected), 4.0e-14);
80 }
81
82 }
83
84 @Test
85 void testFixedMaxCheck() {
86 doTestMaxcheck(Binary64Field.getInstance(), FieldAdaptableInterval.of(20.), 4818);
87 }
88
89 @Test
90 void testConstructor() {
91
92 final double period = 10.;
93 final Complex threshold = Complex.ONE;
94 final FieldOrbit<Complex> mockedFieldOrbit = Mockito.mock(FieldOrbit.class);
95 Mockito.when(mockedFieldOrbit.getKeplerianPeriod()).thenReturn(new Complex(period));
96
97 final FieldApsideDetector<Complex> fieldApsideDetector = new FieldApsideDetector<>(threshold, mockedFieldOrbit);
98
99 final Orbit mockedOrbit = Mockito.mock(Orbit.class);
100 Mockito.when(mockedOrbit.getKeplerianPeriod()).thenReturn(period);
101 final ApsideDetector apsideDetector = new ApsideDetector(threshold.getReal(), mockedOrbit);
102 Assertions.assertEquals(apsideDetector.getThreshold(), fieldApsideDetector.getThreshold().getReal());
103 }
104
105 @Test
106 void testAnomalyAwareMaxCheck() {
107 final AdaptableInterval adaptableInterval = ApsideDetectionAdaptableIntervalFactory
108 .getApsideDetectionAdaptableInterval();
109 doTestMaxcheck(Binary64Field.getInstance(), (state, isForward) -> adaptableInterval.currentInterval(state.toSpacecraftState(), true),
110 706);
111 }
112
113 private <T extends CalculusFieldElement<T>> void doTestMaxcheck(final Field<T> field,
114 final FieldAdaptableInterval<T> maxCheck,
115 int expectedCalls) {
116 final FieldPropagator<T> propagator = createPropagator(field);
117 CountingApsideDetector<T> detector = new CountingApsideDetector<>(propagator, maxCheck);
118 FieldEventsLogger<T> logger = new FieldEventsLogger<>();
119 propagator.addEventDetector(logger.monitorDetector(detector));
120 propagator.propagate(propagator.getInitialState().getOrbit().getDate().shiftedBy(Constants.JULIAN_DAY));
121 Assertions.assertEquals(30, logger.getLoggedEvents().size());
122 Assertions.assertEquals(expectedCalls, detector.count);
123 }
124
125 @BeforeEach
126 public void setUp() {
127 Utils.setDataRoot("regular-data");
128 }
129
130 private <T extends CalculusFieldElement<T>> FieldPropagator<T> createPropagator(final Field<T> field) {
131 final T zero = field.getZero();
132
133 final TimeScale utc = TimeScalesFactory.getUTC();
134 final FieldVector3D<T> position = new FieldVector3D<>(zero.add(-6142438.668), zero.add(3492467.56), zero.add(-25767.257));
135 final FieldVector3D<T> velocity = new FieldVector3D<>(zero.add(506.0), zero.add(943.0), zero.add(7450));
136 final FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, 2003, 9, 16, utc);
137 final FieldOrbit<T> orbit = new FieldCartesianOrbit<>(new FieldPVCoordinates<>(position, velocity),
138 FramesFactory.getEME2000(), date,
139 zero.add(Constants.EIGEN5C_EARTH_MU));
140 return new FieldEcksteinHechlerPropagator<>(orbit,
141 Constants.EIGEN5C_EARTH_EQUATORIAL_RADIUS,
142 zero.add(Constants.EIGEN5C_EARTH_MU),
143 Constants.EIGEN5C_EARTH_C20,
144 Constants.EIGEN5C_EARTH_C30,
145 Constants.EIGEN5C_EARTH_C40,
146 Constants.EIGEN5C_EARTH_C50,
147 Constants.EIGEN5C_EARTH_C60);
148 }
149
150 private class CountingApsideDetector<T extends CalculusFieldElement<T>> implements FieldDetectorModifier<T> {
151
152 private final FieldEventDetector<T> detector;
153 private int count;
154
155 public CountingApsideDetector(final FieldPropagator<T> propagator, final FieldAdaptableInterval<T> maxCheck) {
156 this.detector = new FieldApsideDetector<>(propagator.getInitialState().getOrbit()).
157 withMaxCheck(maxCheck).
158 withThreshold(propagator.getInitialState().getDate().getField().getZero().newInstance(1.0e-12)).
159 withHandler(new FieldContinueOnEvent<>());
160 }
161
162 @Override
163 public FieldEventDetector<T> getDetector() {
164 return detector;
165 }
166
167 public void init(final FieldSpacecraftState<T> s0, final FieldAbsoluteDate<T> t) {
168 FieldDetectorModifier.super.init(s0, t);
169 count = 0;
170 }
171
172 public T g(final FieldSpacecraftState<T> s) {
173 ++count;
174 return FieldDetectorModifier.super.g(s);
175 }
176
177 }
178
179 }
180