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.ode.events.Action;
21  import org.hipparchus.ode.nonstiff.AdaptiveStepsizeIntegrator;
22  import org.hipparchus.ode.nonstiff.DormandPrince853Integrator;
23  import org.junit.jupiter.api.AfterEach;
24  import org.junit.jupiter.api.Assertions;
25  import org.junit.jupiter.api.BeforeEach;
26  import org.junit.jupiter.api.Test;
27  import org.mockito.Mockito;
28  import org.orekit.Utils;
29  import org.orekit.errors.OrekitException;
30  import org.orekit.frames.FramesFactory;
31  import org.orekit.orbits.EquinoctialOrbit;
32  import org.orekit.orbits.Orbit;
33  import org.orekit.propagation.SpacecraftState;
34  import org.orekit.propagation.events.handlers.EventHandler;
35  import org.orekit.propagation.events.handlers.StopOnEvent;
36  import org.orekit.propagation.numerical.NumericalPropagator;
37  import org.orekit.time.AbsoluteDate;
38  import org.orekit.time.TimeScalesFactory;
39  import org.orekit.utils.PVCoordinates;
40  
41  import java.util.concurrent.atomic.AtomicInteger;
42  
43  class DetectorModifierTest {
44  
45      private double maxCheck;
46      private double threshold;
47      private double dt;
48      private Orbit iniOrbit;
49      private AbsoluteDate iniDate;
50      private NumericalPropagator propagator;
51  
52      @Test
53      void testGetDetectionSettings() {
54          // GIVEN
55          final EventDetector detector = Mockito.mock(EventDetector.class);
56          final EventDetectionSettings detectionSettings = Mockito.mock(EventDetectionSettings.class);
57          Mockito.when(detector.getDetectionSettings()).thenReturn(detectionSettings);
58          final DetectorModifier detectorModifier = new TestDetectorModifier(detector);
59          // WHEN
60          final EventDetectionSettings actualSettings = detectorModifier.getDetectionSettings();
61          // THEN
62          Assertions.assertEquals(detectionSettings, actualSettings);
63      }
64  
65      @Test
66      void testGetHandler() {
67          // GIVEN
68          final EventDetector detector = Mockito.mock(EventDetector.class);
69          final EventHandler handler = Mockito.mock(EventHandler.class);
70          Mockito.when(detector.getHandler()).thenReturn(handler);
71          final DetectorModifier detectorModifier = new TestDetectorModifier(detector);
72          // WHEN
73          final EventHandler actualHandler = detectorModifier.getHandler();
74          // THEN
75          Assertions.assertEquals(handler, actualHandler);
76      }
77  
78      @Test
79      void testInit() {
80          // GIVEN
81          final EventDetector detector = Mockito.mock(EventDetector.class);
82          Mockito.when(detector.getHandler()).thenReturn(new StopOnEvent());
83          final SpacecraftState mockedState = Mockito.mock(SpacecraftState.class);
84          final AbsoluteDate mockedDate = Mockito.mock(AbsoluteDate.class);
85          final DetectorModifier detectorModifier = new TestDetectorModifier(detector);
86          // WHEN
87          detectorModifier.init(mockedState, mockedDate);
88          // THEN
89          Mockito.verify(detector).init(mockedState, mockedDate);
90      }
91  
92      @Test
93      void testReset() {
94          // GIVEN
95          final EventDetector detector = Mockito.mock(EventDetector.class);
96          final SpacecraftState mockedState = Mockito.mock(SpacecraftState.class);
97          final AbsoluteDate mockedDate = Mockito.mock(AbsoluteDate.class);
98          final DetectorModifier detectorModifier = new TestDetectorModifier(detector);
99          // WHEN
100         detectorModifier.reset(mockedState, mockedDate);
101         // THEN
102         Mockito.verify(detector).reset(mockedState, mockedDate);
103     }
104 
105     @Test
106     void testG() {
107         // GIVEN
108         final EventDetector detector = Mockito.mock(EventDetector.class);
109         final SpacecraftState mockedState = Mockito.mock(SpacecraftState.class);
110         final double expectedG = 10.;
111         Mockito.when(detector.g(mockedState)).thenReturn(expectedG);
112         final DetectorModifier detectorModifier = new TestDetectorModifier(detector);
113         // WHEN
114         final double actualG = detectorModifier.g(mockedState);
115         // THEN
116         Assertions.assertEquals(expectedG, actualG);
117     }
118 
119     @Test
120     void testFinish() {
121         // GIVEN
122         final EventDetector detector = Mockito.mock(EventDetector.class);
123         Mockito.when(detector.getHandler()).thenReturn(new StopOnEvent());
124         final SpacecraftState mockedState = Mockito.mock(SpacecraftState.class);
125         final DetectorModifier detectorModifier = new TestDetectorModifier(detector);
126         // WHEN
127         detectorModifier.finish(mockedState);
128         // THEN
129         Mockito.verify(detector).finish(mockedState);
130     }
131 
132     @Test
133     void testSimpleTimer() {
134         DateDetector dateDetector = new DateDetector(iniDate.shiftedBy(2.0*dt)).
135                                     withMaxCheck(maxCheck).
136                                     withThreshold(threshold);
137         DetectorModifier adapter = new TestDetectorModifier(dateDetector);
138         Assertions.assertSame(dateDetector, adapter.getDetector());
139         Assertions.assertEquals(2 * dt, dateDetector.getDate().durationFrom(iniDate), 1.0e-10);
140         propagator.addEventDetector(adapter);
141         final SpacecraftState finalState = propagator.propagate(iniDate.shiftedBy(100.*dt));
142 
143         Assertions.assertEquals(2.0*dt, finalState.getDate().durationFrom(iniDate), threshold);
144     }
145 
146     @Test
147     void testOverrideHandler() {
148         AtomicInteger count = new AtomicInteger(0);
149         DateDetector dateDetector = new DateDetector(iniDate.shiftedBy(2.0*dt)).
150                                     withMaxCheck(maxCheck).
151                                     withThreshold(threshold);
152         DetectorModifier adapter = new TestDetectorModifier(dateDetector) {
153             /** {@inheritDoc} */
154             @Override
155             public EventHandler getHandler() {
156                 return new EventHandler() {
157                     /** {@inheritDoc} */
158                     @Override
159                     public Action eventOccurred(final SpacecraftState s, final EventDetector detector, final boolean increasing) {
160                         count.incrementAndGet();
161                         return Action.RESET_STATE;
162                     }
163                 };
164             }
165         };
166         Assertions.assertSame(dateDetector, adapter.getDetector());
167         Assertions.assertEquals(2 * dt, dateDetector.getDate().durationFrom(iniDate), 1.0e-10);
168         propagator.addEventDetector(adapter);
169         Assertions.assertEquals(0, count.get());
170         final SpacecraftState finalState = propagator.propagate(iniDate.shiftedBy(100.*dt));
171         Assertions.assertEquals(1, count.get());
172 
173         Assertions.assertEquals(100.0*dt, finalState.getDate().durationFrom(iniDate), threshold);
174     }
175 
176     @Deprecated
177     @Test
178     void testAdapterDetector() {
179         // GIVEN
180         final DateDetector detector = new DateDetector();
181         // WHEN
182         final AdapterDetector adapterDetector = new AdapterDetector(detector);
183         // THEN
184         final TestDetectorModifier detectorModifier = new TestDetectorModifier(detector);
185         Assertions.assertEquals(detectorModifier.getDetector(), adapterDetector.getDetector());
186     }
187     
188     private static class TestDetectorModifier implements DetectorModifier {
189 
190         private final EventDetector detector;
191 
192         TestDetectorModifier(final EventDetector detector) {
193             this.detector = detector;
194         }
195 
196         @Override
197         public EventDetector getDetector() {
198             return detector;
199         }
200     }
201 
202     @BeforeEach
203     public void setUp() {
204         try {
205             Utils.setDataRoot("regular-data");
206             final double mu = 3.9860047e14;
207             final Vector3D position  = new Vector3D(-6142438.668, 3492467.560, -25767.25680);
208             final Vector3D velocity  = new Vector3D(505.8479685, 942.7809215, 7435.922231);
209             iniDate  = new AbsoluteDate(1969, 7, 28, 4, 0, 0.0, TimeScalesFactory.getTT());
210             iniOrbit = new EquinoctialOrbit(new PVCoordinates(position, velocity),
211                                             FramesFactory.getEME2000(), iniDate, mu);
212             SpacecraftState initialState = new SpacecraftState(iniOrbit);
213             double[] absTolerance = {
214                 0.001, 1.0e-9, 1.0e-9, 1.0e-6, 1.0e-6, 1.0e-6, 0.001
215             };
216             double[] relTolerance = {
217                 1.0e-7, 1.0e-4, 1.0e-4, 1.0e-7, 1.0e-7, 1.0e-7, 1.0e-7
218             };
219             AdaptiveStepsizeIntegrator integrator =
220                 new DormandPrince853Integrator(0.001, 1000, absTolerance, relTolerance);
221             integrator.setInitialStepSize(60);
222             propagator = new NumericalPropagator(integrator);
223             propagator.setInitialState(initialState);
224             dt = 60.;
225             maxCheck  = 10.;
226             threshold = 10.e-10;
227         } catch (OrekitException oe) {
228             Assertions.fail(oe.getLocalizedMessage());
229         }
230     }
231 
232     @AfterEach
233     public void tearDown() {
234         iniDate = null;
235         propagator = null;
236     }
237 
238 }