1   /* Copyright 2002-2025 CS GROUP
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.propagation.events;
18  
19  import org.hipparchus.geometry.euclidean.threed.Vector3D;
20  import org.hipparchus.util.FastMath;
21  import org.junit.jupiter.api.Assertions;
22  import org.junit.jupiter.api.BeforeEach;
23  import org.junit.jupiter.api.Test;
24  import org.junit.jupiter.params.ParameterizedTest;
25  import org.junit.jupiter.params.provider.ValueSource;
26  import org.mockito.Mockito;
27  import org.orekit.Utils;
28  import org.orekit.errors.OrekitException;
29  import org.orekit.errors.OrekitMessages;
30  import org.orekit.frames.FramesFactory;
31  import org.orekit.orbits.CartesianOrbit;
32  import org.orekit.orbits.Orbit;
33  import org.orekit.propagation.Propagator;
34  import org.orekit.propagation.SpacecraftState;
35  import org.orekit.propagation.analytical.EcksteinHechlerPropagator;
36  import org.orekit.propagation.events.handlers.ContinueOnEvent;
37  import org.orekit.time.AbsoluteDate;
38  import org.orekit.time.TimeScale;
39  import org.orekit.time.TimeScalesFactory;
40  import org.orekit.utils.Constants;
41  import org.orekit.utils.PVCoordinates;
42  import org.orekit.utils.ParameterDriver;
43  
44  public class ParameterDrivenDateIntervalDetectorTest {
45  
46      private Propagator propagator;
47  
48      @ParameterizedTest
49      @ValueSource(doubles = {-1e3, -1e1, 0.0, 1.0, 1e2})
50      void testGetDefaultDetectionSettings(final double timeShift) {
51          // GIVEN
52          final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
53          final SpacecraftState mockedState = Mockito.mock(SpacecraftState.class);
54          Mockito.when(mockedState.getDate()).thenReturn(date);
55          // WHEN
56          final EventDetectionSettings detectionSettings = ParameterDrivenDateIntervalDetector.getDefaultDetectionSettings(date,
57                  date.shiftedBy(timeShift));
58          // THEN
59          Assertions.assertEquals(DateDetector.DEFAULT_THRESHOLD, detectionSettings.getThreshold());
60          Assertions.assertTrue(detectionSettings.getMaxCheckInterval().currentInterval(mockedState, true) >= FastMath.abs(timeShift) / 2);
61      }
62  
63      @Test
64      void testDependsOnlyOnTime() {
65          // GIVEN
66          final ParameterDrivenDateIntervalDetector detector = new ParameterDrivenDateIntervalDetector("a",
67                  AbsoluteDate.ARBITRARY_EPOCH, AbsoluteDate.ARBITRARY_EPOCH);
68          // WHEN
69          final boolean value = detector.dependsOnTimeOnly();
70          // THEN
71          Assertions.assertTrue(value);
72      }
73  
74  
75      @Test
76      void testNoShift() {
77          final AbsoluteDate t0    = propagator.getInitialState().getDate();
78          final AbsoluteDate start = t0.shiftedBy( 120);
79          final AbsoluteDate stop  = t0.shiftedBy(1120);
80          ParameterDrivenDateIntervalDetector detector = new ParameterDrivenDateIntervalDetector("no-shift", start, stop).
81                                                         withMaxCheck(10.0).
82                                                         withThreshold(1.0e-12).
83                                                         withHandler(new ContinueOnEvent());
84  
85          Assertions.assertEquals(10.0, detector.getMaxCheckInterval().currentInterval(null, true), 1.0e-15);
86          Assertions.assertEquals(1.0e-12, detector.getThreshold(), 1.0e-15);
87          Assertions.assertEquals(AbstractDetector.DEFAULT_MAX_ITER, detector.getMaxIterationCount());
88          Assertions.assertEquals("no-shift_START", detector.getStartDriver().getName());
89          Assertions.assertEquals("no-shift_STOP", detector.getStopDriver().getName());
90  
91  
92          EventsLogger logger = new EventsLogger();
93          propagator.addEventDetector(logger.monitorDetector(detector));
94  
95          propagator.propagate(propagator.getInitialState().getOrbit().getDate().shiftedBy(3600.0));
96  
97          Assertions.assertEquals(2, logger.getLoggedEvents().size());
98          Assertions.assertEquals(0.0, logger.getLoggedEvents().get(0).getDate().durationFrom(start), 1.0e-10);
99          Assertions.assertEquals(0.0, logger.getLoggedEvents().get(1).getDate().durationFrom(stop),  1.0e-10);
100     }
101 
102     @Test
103     void testSmallShift() {
104         final AbsoluteDate t0    = propagator.getInitialState().getDate();
105         final AbsoluteDate start = t0.shiftedBy( 120);
106         final AbsoluteDate stop  = t0.shiftedBy(1120);
107         ParameterDrivenDateIntervalDetector detector = new ParameterDrivenDateIntervalDetector("small-shift", start, stop).
108                                                        withMaxCheck(10.0).
109                                                        withThreshold(1.0e-12).
110                                                        withHandler(new ContinueOnEvent());
111 
112         Assertions.assertEquals(10.0, detector.getMaxCheckInterval().currentInterval(null, true), 1.0e-15);
113         Assertions.assertEquals(1.0e-12, detector.getThreshold(), 1.0e-15);
114         Assertions.assertEquals(AbstractDetector.DEFAULT_MAX_ITER, detector.getMaxIterationCount());
115         Assertions.assertEquals("small-shift_START", detector.getStartDriver().getName());
116         Assertions.assertEquals("small-shift_STOP", detector.getStopDriver().getName());
117 
118         EventsLogger logger = new EventsLogger();
119         propagator.addEventDetector(logger.monitorDetector(detector));
120 
121         final double startShift = 5.5;
122         detector.getStartDriver().setValue(startShift);
123         final double stopShift  = -0.5;
124         detector.getStopDriver().setValue(stopShift);
125         propagator.propagate(propagator.getInitialState().getOrbit().getDate().shiftedBy(3600.0));
126 
127         Assertions.assertEquals(2, logger.getLoggedEvents().size());
128         Assertions.assertEquals(startShift, logger.getLoggedEvents().get(0).getDate().durationFrom(start), 1.0e-10);
129         Assertions.assertEquals(stopShift,  logger.getLoggedEvents().get(1).getDate().durationFrom(stop),  1.0e-10);
130     }
131 
132     @Test
133     void testLargeShift() {
134         final AbsoluteDate t0       = propagator.getInitialState().getDate();
135         final AbsoluteDate start    = t0.shiftedBy( 120);
136         final AbsoluteDate stop     = t0.shiftedBy(1120);
137         final double       duration = stop.durationFrom(start);
138         final AbsoluteDate median   = start.shiftedBy(0.5 * duration);
139         ParameterDrivenDateIntervalDetector detector = new ParameterDrivenDateIntervalDetector("large-shift", median, duration).
140                                                        withMaxCheck(10.0).
141                                                        withThreshold(1.0e-12).
142                                                        withHandler(new ContinueOnEvent());
143 
144         Assertions.assertEquals(10.0, detector.getMaxCheckInterval().currentInterval(null, true), 1.0e-15);
145         Assertions.assertEquals(1.0e-12, detector.getThreshold(), 1.0e-15);
146         Assertions.assertEquals(AbstractDetector.DEFAULT_MAX_ITER, detector.getMaxIterationCount());
147         Assertions.assertEquals("large-shift_START", detector.getStartDriver().getName());
148         Assertions.assertEquals("large-shift_STOP", detector.getStopDriver().getName());
149 
150         EventsLogger logger = new EventsLogger();
151         propagator.addEventDetector(logger.monitorDetector(detector));
152 
153         final double startShift =  500.5;
154         detector.getStartDriver().setValue(startShift);
155         final double stopShift  = -500.5;
156         detector.getStopDriver().setValue(stopShift);
157         propagator.propagate(propagator.getInitialState().getOrbit().getDate().shiftedBy(3600.0));
158 
159         Assertions.assertEquals(0, logger.getLoggedEvents().size());
160 
161     }
162 
163     @Test
164     void testSelection() {
165         final AbsoluteDate t0       = propagator.getInitialState().getDate();
166         final AbsoluteDate start    = t0.shiftedBy( 120);
167         final AbsoluteDate stop     = t0.shiftedBy(1120);
168         ParameterDrivenDateIntervalDetector detector = new ParameterDrivenDateIntervalDetector("large-shift", start, stop).
169                                                        withMaxCheck(10.0).
170                                                        withThreshold(1.0e-12).
171                                                        withHandler(new ContinueOnEvent());
172 
173         Assertions.assertFalse(detector.getStartDriver().isSelected());
174         Assertions.assertFalse(detector.getStopDriver().isSelected());
175         Assertions.assertFalse(detector.getMedianDriver().isSelected());
176         Assertions.assertFalse(detector.getDurationDriver().isSelected());
177 
178         // check all 16 possible configurations, changing one selection at a time
179         checkSelection(detector, detector.getDurationDriver(), true,  false, false, false, true,  false);
180         checkSelection(detector, detector.getMedianDriver(),   true,  false, false, true,  true,  false);
181         checkSelection(detector, detector.getDurationDriver(), false, false, false, true,  false, false);
182         checkSelection(detector, detector.getStopDriver(),     true,  false, true,  true,  false, true);
183         checkSelection(detector, detector.getDurationDriver(), true,  false, true,  true,  true,  true);
184         checkSelection(detector, detector.getMedianDriver(),   false, false, true,  false, true,  true);
185         checkSelection(detector, detector.getDurationDriver(), false, false, true,  false, false, false);
186         checkSelection(detector, detector.getStartDriver(),    true,  true,  true,  false, false, false);
187         checkSelection(detector, detector.getDurationDriver(), true,  true,  true,  false, true,  true);
188         checkSelection(detector, detector.getMedianDriver(),   true,  true,  true,  true,  true,  true);
189         checkSelection(detector, detector.getDurationDriver(), false, true,  true,  true,  false, true);
190         checkSelection(detector, detector.getStopDriver(),     false, true,  false, true,  false, true);
191         checkSelection(detector, detector.getDurationDriver(), true,  true,  false, true,  true,  true);
192         checkSelection(detector, detector.getMedianDriver(),   false, true,  false, false, true,  true);
193         checkSelection(detector, detector.getDurationDriver(), false, true,  false, false, false, false);
194         checkSelection(detector, detector.getStartDriver(),    false, false, false, false, false, false);
195 
196     }
197 
198     @Test
199     void testStartStopToMedianDuration() {
200         final AbsoluteDate t0       = propagator.getInitialState().getDate();
201         final AbsoluteDate start    = t0.shiftedBy( 120);
202         final AbsoluteDate stop     = t0.shiftedBy(1120);
203         ParameterDrivenDateIntervalDetector detector = new ParameterDrivenDateIntervalDetector("large-shift", start, stop).
204                                                        withMaxCheck(10.0).
205                                                        withThreshold(1.0e-12).
206                                                        withHandler(new ContinueOnEvent());
207         Assertions.assertEquals(   0.0, detector.getStartDriver().getValue(),    1.0e-15);
208         Assertions.assertEquals(   0.0, detector.getStopDriver().getValue(),     1.0e-15);
209         Assertions.assertEquals(   0.0, detector.getMedianDriver().getValue(),   1.0e-15);
210         Assertions.assertEquals(1000.0, detector.getDurationDriver().getValue(), 1.0e-15);
211         detector.getStartDriver().setSelected(true);
212         detector.getStartDriver().setValue(1.0);
213         Assertions.assertEquals(   1.0, detector.getStartDriver().getValue(),    1.0e-15);
214         Assertions.assertEquals(   0.0, detector.getStopDriver().getValue(),     1.0e-15);
215         Assertions.assertEquals(   0.5, detector.getMedianDriver().getValue(),   1.0e-15);
216         Assertions.assertEquals( 999.0, detector.getDurationDriver().getValue(), 1.0e-15);
217         detector.getStopDriver().setSelected(true);
218         detector.getStopDriver().setValue(10.0);
219         Assertions.assertEquals(   1.0, detector.getStartDriver().getValue(),    1.0e-15);
220         Assertions.assertEquals(  10.0, detector.getStopDriver().getValue(),     1.0e-15);
221         Assertions.assertEquals(   5.5, detector.getMedianDriver().getValue(),   1.0e-15);
222         Assertions.assertEquals(1009.0, detector.getDurationDriver().getValue(), 1.0e-15);
223     }
224 
225     @Test
226     void testMedianDurationToStartStop() {
227         final AbsoluteDate t0       = propagator.getInitialState().getDate();
228         final AbsoluteDate start    = t0.shiftedBy( 120);
229         final AbsoluteDate stop     = t0.shiftedBy(1120);
230         ParameterDrivenDateIntervalDetector detector = new ParameterDrivenDateIntervalDetector("large-shift", start, stop).
231                                                        withMaxCheck(10.0).
232                                                        withThreshold(1.0e-12).
233                                                        withHandler(new ContinueOnEvent());
234         Assertions.assertEquals(   0.0, detector.getStartDriver().getValue(),    1.0e-15);
235         Assertions.assertEquals(   0.0, detector.getStopDriver().getValue(),     1.0e-15);
236         Assertions.assertEquals(   0.0, detector.getMedianDriver().getValue(),   1.0e-15);
237         Assertions.assertEquals(1000.0, detector.getDurationDriver().getValue(), 1.0e-15);
238         detector.getMedianDriver().setSelected(true);
239         detector.getMedianDriver().setValue(1.0);
240         Assertions.assertEquals(   1.0, detector.getStartDriver().getValue(),    1.0e-15);
241         Assertions.assertEquals(   1.0, detector.getStopDriver().getValue(),     1.0e-15);
242         Assertions.assertEquals(   1.0, detector.getMedianDriver().getValue(),   1.0e-15);
243         Assertions.assertEquals(1000.0, detector.getDurationDriver().getValue(), 1.0e-15);
244         detector.getDurationDriver().setSelected(true);
245         detector.getDurationDriver().setValue(900.0);
246         Assertions.assertEquals(  51.0, detector.getStartDriver().getValue(),    1.0e-15);
247         Assertions.assertEquals( -49.0, detector.getStopDriver().getValue(),     1.0e-15);
248         Assertions.assertEquals(   1.0, detector.getMedianDriver().getValue(),   1.0e-15);
249         Assertions.assertEquals( 900.0, detector.getDurationDriver().getValue(), 1.0e-15);
250     }
251 
252     private void checkSelection(final ParameterDrivenDateIntervalDetector detector,
253                                 final ParameterDriver driver, final boolean selection, final boolean expectedStart,
254                                 final boolean expectedStop, final boolean expectedMedian,
255                                 final boolean expectedDuration, final boolean shouldFail) {
256         try {
257             driver.setSelected(selection);
258             if (shouldFail) {
259                 Assertions.fail("an exception should have been thrown");
260             }
261         } catch (OrekitException oe) {
262             Assertions.assertEquals(OrekitMessages.INCONSISTENT_SELECTION, oe.getSpecifier());
263         }
264         Assertions.assertEquals(selection,        driver.isSelected());
265         Assertions.assertEquals(expectedStart,    detector.getStartDriver().isSelected());
266         Assertions.assertEquals(expectedStop,     detector.getStopDriver().isSelected());
267         Assertions.assertEquals(expectedMedian,   detector.getMedianDriver().isSelected());
268         Assertions.assertEquals(expectedDuration, detector.getDurationDriver().isSelected());
269     }
270 
271     @BeforeEach
272     public void setUp() {
273         Utils.setDataRoot("regular-data");
274         final TimeScale utc = TimeScalesFactory.getUTC();
275         final Vector3D position = new Vector3D(-6142438.668, 3492467.56, -25767.257);
276         final Vector3D velocity = new Vector3D(506.0, 943.0, 7450);
277         final AbsoluteDate date = new AbsoluteDate(2003, 9, 16, utc);
278         final Orbit orbit = new CartesianOrbit(new PVCoordinates(position,  velocity),
279                                                FramesFactory.getEME2000(), date,
280                                                Constants.EIGEN5C_EARTH_MU);
281 
282         propagator =
283             new EcksteinHechlerPropagator(orbit,
284                                           Constants.EIGEN5C_EARTH_EQUATORIAL_RADIUS,
285                                           Constants.EIGEN5C_EARTH_MU,
286                                           Constants.EIGEN5C_EARTH_C20,
287                                           Constants.EIGEN5C_EARTH_C30,
288                                           Constants.EIGEN5C_EARTH_C40,
289                                           Constants.EIGEN5C_EARTH_C50,
290                                           Constants.EIGEN5C_EARTH_C60);
291     }
292 
293 }
294