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 @SuppressWarnings("unchecked")
91 void testConstructor() {
92
93 final double period = 10.;
94 final Complex threshold = Complex.ONE;
95 final FieldOrbit<Complex> mockedFieldOrbit = Mockito.mock(FieldOrbit.class);
96 Mockito.when(mockedFieldOrbit.getKeplerianPeriod()).thenReturn(new Complex(period));
97
98 final FieldApsideDetector<Complex> fieldApsideDetector = new FieldApsideDetector<>(threshold, mockedFieldOrbit);
99
100 final Orbit mockedOrbit = Mockito.mock(Orbit.class);
101 Mockito.when(mockedOrbit.getKeplerianPeriod()).thenReturn(period);
102 final ApsideDetector apsideDetector = new ApsideDetector(threshold.getReal(), mockedOrbit);
103 Assertions.assertEquals(apsideDetector.getThreshold(), fieldApsideDetector.getThreshold().getReal());
104 }
105
106 @Test
107 void testAnomalyAwareMaxCheck() {
108 final AdaptableInterval adaptableInterval = ApsideDetectionAdaptableIntervalFactory
109 .getApsideDetectionAdaptableInterval();
110 doTestMaxcheck(Binary64Field.getInstance(), (state, isForward) -> adaptableInterval.currentInterval(state.toSpacecraftState(), true),
111 706);
112 }
113
114 private <T extends CalculusFieldElement<T>> void doTestMaxcheck(final Field<T> field,
115 final FieldAdaptableInterval<T> maxCheck,
116 int expectedCalls) {
117 final FieldPropagator<T> propagator = createPropagator(field);
118 CountingApsideDetector<T> detector = new CountingApsideDetector<>(propagator, maxCheck);
119 FieldEventsLogger<T> logger = new FieldEventsLogger<>();
120 propagator.addEventDetector(logger.monitorDetector(detector));
121 propagator.propagate(propagator.getInitialState().getOrbit().getDate().shiftedBy(Constants.JULIAN_DAY));
122 Assertions.assertEquals(30, logger.getLoggedEvents().size());
123 Assertions.assertEquals(expectedCalls, detector.count);
124 }
125
126 @BeforeEach
127 public void setUp() {
128 Utils.setDataRoot("regular-data");
129 }
130
131 private <T extends CalculusFieldElement<T>> FieldPropagator<T> createPropagator(final Field<T> field) {
132 final T zero = field.getZero();
133
134 final TimeScale utc = TimeScalesFactory.getUTC();
135 final FieldVector3D<T> position = new FieldVector3D<>(zero.add(-6142438.668), zero.add(3492467.56), zero.add(-25767.257));
136 final FieldVector3D<T> velocity = new FieldVector3D<>(zero.add(506.0), zero.add(943.0), zero.add(7450));
137 final FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, 2003, 9, 16, utc);
138 final FieldOrbit<T> orbit = new FieldCartesianOrbit<>(new FieldPVCoordinates<>(position, velocity),
139 FramesFactory.getEME2000(), date,
140 zero.add(Constants.EIGEN5C_EARTH_MU));
141 return new FieldEcksteinHechlerPropagator<>(orbit,
142 Constants.EIGEN5C_EARTH_EQUATORIAL_RADIUS,
143 zero.add(Constants.EIGEN5C_EARTH_MU),
144 Constants.EIGEN5C_EARTH_C20,
145 Constants.EIGEN5C_EARTH_C30,
146 Constants.EIGEN5C_EARTH_C40,
147 Constants.EIGEN5C_EARTH_C50,
148 Constants.EIGEN5C_EARTH_C60);
149 }
150
151 private class CountingApsideDetector<T extends CalculusFieldElement<T>> implements FieldDetectorModifier<T> {
152
153 private final FieldEventDetector<T> detector;
154 private int count;
155
156 public CountingApsideDetector(final FieldPropagator<T> propagator, final FieldAdaptableInterval<T> maxCheck) {
157 this.detector = new FieldApsideDetector<>(propagator.getInitialState().getOrbit()).
158 withMaxCheck(maxCheck).
159 withThreshold(propagator.getInitialState().getDate().getField().getZero().newInstance(1.0e-12)).
160 withHandler(new FieldContinueOnEvent<>());
161 }
162
163 @Override
164 public FieldEventDetector<T> getDetector() {
165 return detector;
166 }
167
168 public void init(final FieldSpacecraftState<T> s0, final FieldAbsoluteDate<T> t) {
169 FieldDetectorModifier.super.init(s0, t);
170 count = 0;
171 }
172
173 public T g(final FieldSpacecraftState<T> s) {
174 ++count;
175 return FieldDetectorModifier.super.g(s);
176 }
177
178 }
179
180 }
181