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      public void testNoShift() {
65          final AbsoluteDate t0    = propagator.getInitialState().getDate();
66          final AbsoluteDate start = t0.shiftedBy( 120);
67          final AbsoluteDate stop  = t0.shiftedBy(1120);
68          ParameterDrivenDateIntervalDetector detector = new ParameterDrivenDateIntervalDetector("no-shift", start, stop).
69                                                         withMaxCheck(10.0).
70                                                         withThreshold(1.0e-12).
71                                                         withHandler(new ContinueOnEvent());
72  
73          Assertions.assertEquals(10.0, detector.getMaxCheckInterval().currentInterval(null, true), 1.0e-15);
74          Assertions.assertEquals(1.0e-12, detector.getThreshold(), 1.0e-15);
75          Assertions.assertEquals(AbstractDetector.DEFAULT_MAX_ITER, detector.getMaxIterationCount());
76          Assertions.assertEquals("no-shift_START", detector.getStartDriver().getName());
77          Assertions.assertEquals("no-shift_STOP", detector.getStopDriver().getName());
78  
79  
80          EventsLogger logger = new EventsLogger();
81          propagator.addEventDetector(logger.monitorDetector(detector));
82  
83          propagator.propagate(propagator.getInitialState().getOrbit().getDate().shiftedBy(3600.0));
84  
85          Assertions.assertEquals(2, logger.getLoggedEvents().size());
86          Assertions.assertEquals(0.0, logger.getLoggedEvents().get(0).getDate().durationFrom(start), 1.0e-10);
87          Assertions.assertEquals(0.0, logger.getLoggedEvents().get(1).getDate().durationFrom(stop),  1.0e-10);
88      }
89  
90      @Test
91      public void testSmallShift() {
92          final AbsoluteDate t0    = propagator.getInitialState().getDate();
93          final AbsoluteDate start = t0.shiftedBy( 120);
94          final AbsoluteDate stop  = t0.shiftedBy(1120);
95          ParameterDrivenDateIntervalDetector detector = new ParameterDrivenDateIntervalDetector("small-shift", start, stop).
96                                                         withMaxCheck(10.0).
97                                                         withThreshold(1.0e-12).
98                                                         withHandler(new ContinueOnEvent());
99  
100         Assertions.assertEquals(10.0, detector.getMaxCheckInterval().currentInterval(null, true), 1.0e-15);
101         Assertions.assertEquals(1.0e-12, detector.getThreshold(), 1.0e-15);
102         Assertions.assertEquals(AbstractDetector.DEFAULT_MAX_ITER, detector.getMaxIterationCount());
103         Assertions.assertEquals("small-shift_START", detector.getStartDriver().getName());
104         Assertions.assertEquals("small-shift_STOP", detector.getStopDriver().getName());
105 
106         EventsLogger logger = new EventsLogger();
107         propagator.addEventDetector(logger.monitorDetector(detector));
108 
109         final double startShift = 5.5;
110         detector.getStartDriver().setValue(startShift);
111         final double stopShift  = -0.5;
112         detector.getStopDriver().setValue(stopShift);
113         propagator.propagate(propagator.getInitialState().getOrbit().getDate().shiftedBy(3600.0));
114 
115         Assertions.assertEquals(2, logger.getLoggedEvents().size());
116         Assertions.assertEquals(startShift, logger.getLoggedEvents().get(0).getDate().durationFrom(start), 1.0e-10);
117         Assertions.assertEquals(stopShift,  logger.getLoggedEvents().get(1).getDate().durationFrom(stop),  1.0e-10);
118     }
119 
120     @Test
121     public void testLargeShift() {
122         final AbsoluteDate t0       = propagator.getInitialState().getDate();
123         final AbsoluteDate start    = t0.shiftedBy( 120);
124         final AbsoluteDate stop     = t0.shiftedBy(1120);
125         final double       duration = stop.durationFrom(start);
126         final AbsoluteDate median   = start.shiftedBy(0.5 * duration);
127         ParameterDrivenDateIntervalDetector detector = new ParameterDrivenDateIntervalDetector("large-shift", median, duration).
128                                                        withMaxCheck(10.0).
129                                                        withThreshold(1.0e-12).
130                                                        withHandler(new ContinueOnEvent());
131 
132         Assertions.assertEquals(10.0, detector.getMaxCheckInterval().currentInterval(null, true), 1.0e-15);
133         Assertions.assertEquals(1.0e-12, detector.getThreshold(), 1.0e-15);
134         Assertions.assertEquals(AbstractDetector.DEFAULT_MAX_ITER, detector.getMaxIterationCount());
135         Assertions.assertEquals("large-shift_START", detector.getStartDriver().getName());
136         Assertions.assertEquals("large-shift_STOP", detector.getStopDriver().getName());
137 
138         EventsLogger logger = new EventsLogger();
139         propagator.addEventDetector(logger.monitorDetector(detector));
140 
141         final double startShift =  500.5;
142         detector.getStartDriver().setValue(startShift);
143         final double stopShift  = -500.5;
144         detector.getStopDriver().setValue(stopShift);
145         propagator.propagate(propagator.getInitialState().getOrbit().getDate().shiftedBy(3600.0));
146 
147         Assertions.assertEquals(0, logger.getLoggedEvents().size());
148 
149     }
150 
151     @Test
152     public void testSelection() {
153         final AbsoluteDate t0       = propagator.getInitialState().getDate();
154         final AbsoluteDate start    = t0.shiftedBy( 120);
155         final AbsoluteDate stop     = t0.shiftedBy(1120);
156         ParameterDrivenDateIntervalDetector detector = new ParameterDrivenDateIntervalDetector("large-shift", start, stop).
157                                                        withMaxCheck(10.0).
158                                                        withThreshold(1.0e-12).
159                                                        withHandler(new ContinueOnEvent());
160 
161         Assertions.assertFalse(detector.getStartDriver().isSelected());
162         Assertions.assertFalse(detector.getStopDriver().isSelected());
163         Assertions.assertFalse(detector.getMedianDriver().isSelected());
164         Assertions.assertFalse(detector.getDurationDriver().isSelected());
165 
166         // check all 16 possible configurations, changing one selection at a time
167         checkSelection(detector, detector.getDurationDriver(), true,  false, false, false, true,  false);
168         checkSelection(detector, detector.getMedianDriver(),   true,  false, false, true,  true,  false);
169         checkSelection(detector, detector.getDurationDriver(), false, false, false, true,  false, false);
170         checkSelection(detector, detector.getStopDriver(),     true,  false, true,  true,  false, true);
171         checkSelection(detector, detector.getDurationDriver(), true,  false, true,  true,  true,  true);
172         checkSelection(detector, detector.getMedianDriver(),   false, false, true,  false, true,  true);
173         checkSelection(detector, detector.getDurationDriver(), false, false, true,  false, false, false);
174         checkSelection(detector, detector.getStartDriver(),    true,  true,  true,  false, false, false);
175         checkSelection(detector, detector.getDurationDriver(), true,  true,  true,  false, true,  true);
176         checkSelection(detector, detector.getMedianDriver(),   true,  true,  true,  true,  true,  true);
177         checkSelection(detector, detector.getDurationDriver(), false, true,  true,  true,  false, true);
178         checkSelection(detector, detector.getStopDriver(),     false, true,  false, true,  false, true);
179         checkSelection(detector, detector.getDurationDriver(), true,  true,  false, true,  true,  true);
180         checkSelection(detector, detector.getMedianDriver(),   false, true,  false, false, true,  true);
181         checkSelection(detector, detector.getDurationDriver(), false, true,  false, false, false, false);
182         checkSelection(detector, detector.getStartDriver(),    false, false, false, false, false, false);
183 
184     }
185 
186     @Test
187     public void testStartStopToMedianDuration() {
188         final AbsoluteDate t0       = propagator.getInitialState().getDate();
189         final AbsoluteDate start    = t0.shiftedBy( 120);
190         final AbsoluteDate stop     = t0.shiftedBy(1120);
191         ParameterDrivenDateIntervalDetector detector = new ParameterDrivenDateIntervalDetector("large-shift", start, stop).
192                                                        withMaxCheck(10.0).
193                                                        withThreshold(1.0e-12).
194                                                        withHandler(new ContinueOnEvent());
195         Assertions.assertEquals(   0.0, detector.getStartDriver().getValue(),    1.0e-15);
196         Assertions.assertEquals(   0.0, detector.getStopDriver().getValue(),     1.0e-15);
197         Assertions.assertEquals(   0.0, detector.getMedianDriver().getValue(),   1.0e-15);
198         Assertions.assertEquals(1000.0, detector.getDurationDriver().getValue(), 1.0e-15);
199         detector.getStartDriver().setSelected(true);
200         detector.getStartDriver().setValue(1.0);
201         Assertions.assertEquals(   1.0, detector.getStartDriver().getValue(),    1.0e-15);
202         Assertions.assertEquals(   0.0, detector.getStopDriver().getValue(),     1.0e-15);
203         Assertions.assertEquals(   0.5, detector.getMedianDriver().getValue(),   1.0e-15);
204         Assertions.assertEquals( 999.0, detector.getDurationDriver().getValue(), 1.0e-15);
205         detector.getStopDriver().setSelected(true);
206         detector.getStopDriver().setValue(10.0);
207         Assertions.assertEquals(   1.0, detector.getStartDriver().getValue(),    1.0e-15);
208         Assertions.assertEquals(  10.0, detector.getStopDriver().getValue(),     1.0e-15);
209         Assertions.assertEquals(   5.5, detector.getMedianDriver().getValue(),   1.0e-15);
210         Assertions.assertEquals(1009.0, detector.getDurationDriver().getValue(), 1.0e-15);
211     }
212 
213     @Test
214     public void testMedianDurationToStartStop() {
215         final AbsoluteDate t0       = propagator.getInitialState().getDate();
216         final AbsoluteDate start    = t0.shiftedBy( 120);
217         final AbsoluteDate stop     = t0.shiftedBy(1120);
218         ParameterDrivenDateIntervalDetector detector = new ParameterDrivenDateIntervalDetector("large-shift", start, stop).
219                                                        withMaxCheck(10.0).
220                                                        withThreshold(1.0e-12).
221                                                        withHandler(new ContinueOnEvent());
222         Assertions.assertEquals(   0.0, detector.getStartDriver().getValue(),    1.0e-15);
223         Assertions.assertEquals(   0.0, detector.getStopDriver().getValue(),     1.0e-15);
224         Assertions.assertEquals(   0.0, detector.getMedianDriver().getValue(),   1.0e-15);
225         Assertions.assertEquals(1000.0, detector.getDurationDriver().getValue(), 1.0e-15);
226         detector.getMedianDriver().setSelected(true);
227         detector.getMedianDriver().setValue(1.0);
228         Assertions.assertEquals(   1.0, detector.getStartDriver().getValue(),    1.0e-15);
229         Assertions.assertEquals(   1.0, detector.getStopDriver().getValue(),     1.0e-15);
230         Assertions.assertEquals(   1.0, detector.getMedianDriver().getValue(),   1.0e-15);
231         Assertions.assertEquals(1000.0, detector.getDurationDriver().getValue(), 1.0e-15);
232         detector.getDurationDriver().setSelected(true);
233         detector.getDurationDriver().setValue(900.0);
234         Assertions.assertEquals(  51.0, detector.getStartDriver().getValue(),    1.0e-15);
235         Assertions.assertEquals( -49.0, detector.getStopDriver().getValue(),     1.0e-15);
236         Assertions.assertEquals(   1.0, detector.getMedianDriver().getValue(),   1.0e-15);
237         Assertions.assertEquals( 900.0, detector.getDurationDriver().getValue(), 1.0e-15);
238     }
239 
240     private void checkSelection(final ParameterDrivenDateIntervalDetector detector,
241                                 final ParameterDriver driver, final boolean selection, final boolean expectedStart,
242                                 final boolean expectedStop, final boolean expectedMedian,
243                                 final boolean expectedDuration, final boolean shouldFail) {
244         try {
245             driver.setSelected(selection);
246             if (shouldFail) {
247                 Assertions.fail("an exception should have been thrown");
248             }
249         } catch (OrekitException oe) {
250             Assertions.assertEquals(OrekitMessages.INCONSISTENT_SELECTION, oe.getSpecifier());
251         }
252         Assertions.assertEquals(selection,        driver.isSelected());
253         Assertions.assertEquals(expectedStart,    detector.getStartDriver().isSelected());
254         Assertions.assertEquals(expectedStop,     detector.getStopDriver().isSelected());
255         Assertions.assertEquals(expectedMedian,   detector.getMedianDriver().isSelected());
256         Assertions.assertEquals(expectedDuration, detector.getDurationDriver().isSelected());
257     }
258 
259     @BeforeEach
260     public void setUp() {
261         Utils.setDataRoot("regular-data");
262         final TimeScale utc = TimeScalesFactory.getUTC();
263         final Vector3D position = new Vector3D(-6142438.668, 3492467.56, -25767.257);
264         final Vector3D velocity = new Vector3D(506.0, 943.0, 7450);
265         final AbsoluteDate date = new AbsoluteDate(2003, 9, 16, utc);
266         final Orbit orbit = new CartesianOrbit(new PVCoordinates(position,  velocity),
267                                                FramesFactory.getEME2000(), date,
268                                                Constants.EIGEN5C_EARTH_MU);
269 
270         propagator =
271             new EcksteinHechlerPropagator(orbit,
272                                           Constants.EIGEN5C_EARTH_EQUATORIAL_RADIUS,
273                                           Constants.EIGEN5C_EARTH_MU,
274                                           Constants.EIGEN5C_EARTH_C20,
275                                           Constants.EIGEN5C_EARTH_C30,
276                                           Constants.EIGEN5C_EARTH_C40,
277                                           Constants.EIGEN5C_EARTH_C50,
278                                           Constants.EIGEN5C_EARTH_C60);
279     }
280 
281 }
282