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.sampling;
18  
19  import org.hipparchus.ode.events.Action;
20  import org.junit.jupiter.api.AfterEach;
21  import org.junit.jupiter.api.Assertions;
22  import org.junit.jupiter.api.BeforeEach;
23  import org.junit.jupiter.api.Test;
24  import org.orekit.Utils;
25  import org.orekit.frames.FramesFactory;
26  import org.orekit.orbits.KeplerianOrbit;
27  import org.orekit.orbits.Orbit;
28  import org.orekit.orbits.PositionAngleType;
29  import org.orekit.propagation.Propagator;
30  import org.orekit.propagation.SpacecraftState;
31  import org.orekit.propagation.analytical.KeplerianPropagator;
32  import org.orekit.propagation.events.DateDetector;
33  import org.orekit.time.AbsoluteDate;
34  import org.orekit.time.TimeScalesFactory;
35  import org.orekit.utils.Constants;
36  
37  public class StepHandlerMultiplexerTest {
38  
39      AbsoluteDate initDate;
40      Propagator propagator;
41  
42      @BeforeEach
43      public void setUp() {
44          Utils.setDataRoot("regular-data");
45          initDate = new AbsoluteDate(2020, 2, 28, 16, 15, 0.0, TimeScalesFactory.getUTC());
46          Orbit ic = new KeplerianOrbit(6378137 + 500e3, 1e-3, 0, 0, 0, 0,
47                                        PositionAngleType.TRUE, FramesFactory.getGCRF(), initDate, Constants.WGS84_EARTH_MU);
48          propagator = new KeplerianPropagator(ic);
49      }
50  
51      @AfterEach
52      public void tearDown() {
53          initDate   = null;
54          propagator = null;
55      }
56  
57      @Test
58      public void testMixedSteps() {
59  
60          StepHandlerMultiplexer multiplexer = propagator.getMultiplexer();
61  
62          InitCheckerHandler initHandler = new InitCheckerHandler(1.0);
63          FixedCounter    counter60  = new FixedCounter();
64          VariableCounter counterVar = new VariableCounter();
65          FixedCounter    counter10  = new FixedCounter();
66  
67          multiplexer.add(60, initHandler);
68          multiplexer.add(60, counter60);
69          multiplexer.add(counterVar);
70          multiplexer.add(10, counter10);
71          Assertions.assertEquals(4, multiplexer.getHandlers().size());
72  
73          Assertions.assertFalse(initHandler.isInitialized());
74          Assertions.assertEquals(1.0, initHandler.getExpected(), Double.MIN_VALUE);
75  
76          propagator.propagate(initDate.shiftedBy(90.0));
77  
78          // verify
79          Assertions.assertTrue(initHandler.isInitialized());
80          Assertions.assertEquals(2.0, initHandler.getExpected(), Double.MIN_VALUE);
81  
82          Assertions.assertEquals( 1,  counter60.initCount);
83          Assertions.assertEquals( 2,  counter60.handleCount);
84          Assertions.assertEquals( 1,  counter60.finishCount);
85  
86          Assertions.assertEquals( 1,  counterVar.initCount);
87          Assertions.assertEquals( 1,  counterVar.handleCount);
88          Assertions.assertEquals( 1,  counterVar.finishCount);
89  
90          Assertions.assertEquals( 1,  counter10.initCount);
91          Assertions.assertEquals(10,  counter10.handleCount);
92          Assertions.assertEquals( 1,  counter10.finishCount);
93  
94      }
95  
96      @Test
97      public void testRemove() {
98  
99          StepHandlerMultiplexer multiplexer = propagator.getMultiplexer();
100 
101         FixedCounter    counter60  = new FixedCounter();
102         VariableCounter counterVar = new VariableCounter();
103         FixedCounter    counter10  = new FixedCounter();
104 
105         multiplexer.add(60, counter60);
106         multiplexer.add(counterVar);
107         multiplexer.add(10, counter10);
108         Assertions.assertEquals(3, multiplexer.getHandlers().size());
109         Assertions.assertTrue(((OrekitStepNormalizer) multiplexer.getHandlers().get(0)).getFixedStepHandler() instanceof FixedCounter);
110         Assertions.assertEquals(60.0, ((OrekitStepNormalizer) multiplexer.getHandlers().get(0)).getFixedTimeStep(), 1.0e-15);
111         Assertions.assertTrue(((OrekitStepNormalizer) multiplexer.getHandlers().get(2)).getFixedStepHandler() instanceof FixedCounter);
112         Assertions.assertEquals(10.0, ((OrekitStepNormalizer) multiplexer.getHandlers().get(2)).getFixedTimeStep(), 1.0e-15);
113 
114         // first run with all handlers
115         propagator.propagate(initDate.shiftedBy(90.0));
116         Assertions.assertEquals( 1,    counter60.initCount);
117         Assertions.assertEquals( 2,    counter60.handleCount);
118         Assertions.assertEquals( 1,    counter60.finishCount);
119         Assertions.assertEquals(  0.0, counter60.start, 1.0e-15);
120         Assertions.assertEquals( 90.0, counter60.stop, 1.0e-15);
121         Assertions.assertEquals( 1,    counterVar.initCount);
122         Assertions.assertEquals( 1,    counterVar.handleCount);
123         Assertions.assertEquals( 1,    counterVar.finishCount);
124         Assertions.assertEquals(  0.0, counterVar.start, 1.0e-15);
125         Assertions.assertEquals( 90.0, counterVar.stop, 1.0e-15);
126         Assertions.assertEquals( 1,    counter10.initCount);
127         Assertions.assertEquals(10,    counter10.handleCount);
128         Assertions.assertEquals( 1,    counter10.finishCount);
129         Assertions.assertEquals(  0.0, counter10.start, 1.0e-15);
130         Assertions.assertEquals( 90.0, counter10.stop, 1.0e-15);
131 
132         // removing the handler at 10 seconds
133         multiplexer.remove(counter10);
134         Assertions.assertEquals(2, multiplexer.getHandlers().size());
135         propagator.propagate(initDate.shiftedBy(100.0), initDate.shiftedBy(190.0));
136         Assertions.assertEquals( 2,    counter60.initCount);
137         Assertions.assertEquals( 4,    counter60.handleCount);
138         Assertions.assertEquals( 2,    counter60.initCount);
139         Assertions.assertEquals(100.0, counter60.start, 1.0e-15);
140         Assertions.assertEquals(190.0, counter60.stop, 1.0e-15);
141         Assertions.assertEquals( 2,    counterVar.initCount);
142         Assertions.assertEquals( 2,    counterVar.handleCount);
143         Assertions.assertEquals( 2,    counterVar.finishCount);
144         Assertions.assertEquals(100.0, counterVar.start, 1.0e-15);
145         Assertions.assertEquals(190.0, counterVar.stop, 1.0e-15);
146         Assertions.assertEquals( 1,    counter10.initCount);
147         Assertions.assertEquals(10,    counter10.handleCount);
148         Assertions.assertEquals( 1,    counter10.initCount);
149         Assertions.assertEquals(  0.0, counter10.start, 1.0e-15);
150         Assertions.assertEquals( 90.0, counter10.stop, 1.0e-15);
151 
152         // attempting to remove a handler already removed
153         multiplexer.remove(counter10);
154         Assertions.assertEquals(2, multiplexer.getHandlers().size());
155         propagator.propagate(initDate.shiftedBy(200.0), initDate.shiftedBy(290.0));
156         Assertions.assertEquals( 3,    counter60.initCount);
157         Assertions.assertEquals( 6,    counter60.handleCount);
158         Assertions.assertEquals( 3,    counter60.finishCount);
159         Assertions.assertEquals(200.0, counter60.start, 1.0e-15);
160         Assertions.assertEquals(290.0, counter60.stop, 1.0e-15);
161         Assertions.assertEquals( 3,    counterVar.initCount);
162         Assertions.assertEquals( 3,    counterVar.handleCount);
163         Assertions.assertEquals( 3,    counterVar.finishCount);
164         Assertions.assertEquals(200.0, counterVar.start, 1.0e-15);
165         Assertions.assertEquals(290.0, counterVar.stop, 1.0e-15);
166         Assertions.assertEquals( 1,    counter10.initCount);
167         Assertions.assertEquals(10,    counter10.handleCount);
168         Assertions.assertEquals( 1,    counter10.finishCount);
169         Assertions.assertEquals(  0.0, counter10.start, 1.0e-15);
170         Assertions.assertEquals( 90.0, counter10.stop, 1.0e-15);
171 
172         // removing the handler with variable stepsize
173         multiplexer.remove(counterVar);
174         Assertions.assertEquals(1, multiplexer.getHandlers().size());
175         propagator.propagate(initDate.shiftedBy(300.0), initDate.shiftedBy(390.0));
176         Assertions.assertEquals( 4,    counter60.initCount);
177         Assertions.assertEquals( 8,    counter60.handleCount);
178         Assertions.assertEquals( 4,    counter60.initCount);
179         Assertions.assertEquals(300.0, counter60.start, 1.0e-15);
180         Assertions.assertEquals(390.0, counter60.stop, 1.0e-15);
181         Assertions.assertEquals( 3,    counterVar.initCount);
182         Assertions.assertEquals( 3,    counterVar.handleCount);
183         Assertions.assertEquals( 3,    counterVar.finishCount);
184         Assertions.assertEquals(200.0, counterVar.start, 1.0e-15);
185         Assertions.assertEquals(290.0, counterVar.stop, 1.0e-15);
186         Assertions.assertEquals( 1,    counter10.initCount);
187         Assertions.assertEquals(10,    counter10.handleCount);
188         Assertions.assertEquals( 1,    counter10.initCount);
189         Assertions.assertEquals(  0.0, counter10.start, 1.0e-15);
190         Assertions.assertEquals( 90.0, counter10.stop, 1.0e-15);
191 
192         // attempting to remove a handler already removed
193         multiplexer.remove(counterVar);
194         Assertions.assertEquals(1, multiplexer.getHandlers().size());
195         propagator.propagate(initDate.shiftedBy(400.0), initDate.shiftedBy(490.0));
196         Assertions.assertEquals( 5,    counter60.initCount);
197         Assertions.assertEquals(10,    counter60.handleCount);
198         Assertions.assertEquals( 5,    counter60.finishCount);
199         Assertions.assertEquals(400.0, counter60.start, 1.0e-15);
200         Assertions.assertEquals(490.0, counter60.stop, 1.0e-15);
201         Assertions.assertEquals( 3,    counterVar.initCount);
202         Assertions.assertEquals( 3,    counterVar.handleCount);
203         Assertions.assertEquals( 3,    counterVar.finishCount);
204         Assertions.assertEquals(200.0, counterVar.start, 1.0e-15);
205         Assertions.assertEquals(290.0, counterVar.stop, 1.0e-15);
206         Assertions.assertEquals( 1,    counter10.initCount);
207         Assertions.assertEquals(10,    counter10.handleCount);
208         Assertions.assertEquals( 1,    counter10.finishCount);
209         Assertions.assertEquals(  0.0, counter10.start, 1.0e-15);
210         Assertions.assertEquals( 90.0, counter10.stop, 1.0e-15);
211 
212         // removing everything
213         multiplexer.clear();
214         Assertions.assertEquals(0, multiplexer.getHandlers().size());
215         propagator.propagate(initDate.shiftedBy(500.0), initDate.shiftedBy(590.0));
216         Assertions.assertEquals( 5,    counter60.initCount);
217         Assertions.assertEquals(10,    counter60.handleCount);
218         Assertions.assertEquals( 5,    counter60.finishCount);
219         Assertions.assertEquals(400.0, counter60.start, 1.0e-15);
220         Assertions.assertEquals(490.0, counter60.stop, 1.0e-15);
221         Assertions.assertEquals( 3,    counterVar.initCount);
222         Assertions.assertEquals( 3,    counterVar.handleCount);
223         Assertions.assertEquals( 3,    counterVar.finishCount);
224         Assertions.assertEquals(200.0, counterVar.start, 1.0e-15);
225         Assertions.assertEquals(290.0, counterVar.stop, 1.0e-15);
226         Assertions.assertEquals( 1,    counter10.initCount);
227         Assertions.assertEquals(10,    counter10.handleCount);
228         Assertions.assertEquals( 1,    counter10.finishCount);
229         Assertions.assertEquals(  0.0, counter10.start, 1.0e-15);
230         Assertions.assertEquals( 90.0, counter10.stop, 1.0e-15);
231 
232     }
233 
234     @Test
235     public void testOnTheFlyChanges() {
236 
237         StepHandlerMultiplexer multiplexer = propagator.getMultiplexer();
238 
239         double          add60      =  3.0;
240         double          rem60      = 78.0;
241         FixedCounter    counter60  = new FixedCounter();
242         propagator.addEventDetector(new DateDetector(initDate.shiftedBy(add60)).
243                                     withHandler((s, d, i) -> {
244                                         multiplexer.add(60.0, counter60);
245                                         return Action.CONTINUE;
246                                     }));
247         propagator.addEventDetector(new DateDetector(initDate.shiftedBy(rem60)).
248                                     withHandler((s, d, i) -> {
249                                         multiplexer.remove(counter60);
250                                         return Action.CONTINUE;
251                                     }));
252 
253         double          addVar     =  5.0;
254         double          remVar     =  7.0;
255         VariableCounter counterVar = new VariableCounter();
256         propagator.addEventDetector(new DateDetector(initDate.shiftedBy(addVar)).
257                                     withHandler((s, d, i) -> {
258                                         multiplexer.add(counterVar);
259                                         return Action.CONTINUE;
260                                     }));
261         propagator.addEventDetector(new DateDetector(initDate.shiftedBy(remVar)).
262                                     withHandler((s, d, i) -> {
263                                         multiplexer.remove(counterVar);
264                                         return Action.CONTINUE;
265                                     }));
266 
267         double          add10      =  6.0;
268         double          rem10      = 82.0;
269         FixedCounter    counter10  = new FixedCounter();
270         propagator.addEventDetector(new DateDetector(initDate.shiftedBy(add10)).
271                                     withHandler((s, d, i) -> {
272                                         multiplexer.add(10.0, counter10);
273                                         return Action.CONTINUE;
274                                     }));
275         propagator.addEventDetector(new DateDetector(initDate.shiftedBy(rem10)).
276                                     withHandler((s, d, i) -> {
277                                         multiplexer.clear();
278                                         return Action.CONTINUE;
279                                     }));
280 
281         // full run, which will add and remove step handlers on the fly
282         propagator.propagate(initDate.shiftedBy(90.0));
283         Assertions.assertEquals( 1,     counter60.initCount);
284         Assertions.assertEquals( 2,     counter60.handleCount);
285         Assertions.assertEquals( 1,     counter60.finishCount);
286         Assertions.assertEquals(add60,  counter60.start, 1.0e-15);
287         Assertions.assertEquals(rem60,  counter60.stop, 1.0e-15);
288         Assertions.assertEquals( 1,     counterVar.initCount);
289         Assertions.assertEquals( 2,     counterVar.handleCount); // event at add10 splits the variable step in two parts
290         Assertions.assertEquals( 1,     counterVar.finishCount);
291         Assertions.assertEquals(addVar, counterVar.start, 1.0e-15);
292         Assertions.assertEquals(remVar, counterVar.stop, 1.0e-15);
293         Assertions.assertEquals( 1,     counter10.initCount);
294         Assertions.assertEquals( 8,     counter10.handleCount);
295         Assertions.assertEquals( 1,     counter10.finishCount);
296         Assertions.assertEquals(add10,  counter10.start, 1.0e-15);
297         Assertions.assertEquals(rem10,  counter10.stop, 1.0e-15);
298 
299     }
300 
301     private class InitCheckerHandler implements OrekitFixedStepHandler {
302 
303         private double expected;
304         private boolean initialized;
305 
306         public InitCheckerHandler(final double expected) {
307             this.expected    = expected;
308             this.initialized = false;
309         }
310 
311         @Override
312         public void init(SpacecraftState s0, AbsoluteDate t, double step) {
313             initialized = true;
314         }
315 
316         @Override
317         public void handleStep(SpacecraftState currentState) {
318             this.expected = 2.0;
319         }
320 
321         boolean isInitialized() {
322             return initialized;
323         }
324 
325         double getExpected() {
326             return expected;
327         }
328 
329     }
330 
331     private class FixedCounter implements OrekitFixedStepHandler {
332 
333         private int    initCount;
334         private int    handleCount;
335         private int    finishCount;
336         private double start;
337         private double stop;
338 
339         @Override
340         public void init(SpacecraftState s0, AbsoluteDate t, double step) {
341             ++initCount;
342             start = s0.getDate().durationFrom(initDate);
343         }
344 
345         @Override
346         public void handleStep(SpacecraftState currentState) {
347             ++handleCount;
348         }
349 
350         @Override
351         public void finish(SpacecraftState finalState) {
352             ++finishCount;
353             stop = finalState.getDate().durationFrom(initDate);
354         }
355 
356     }
357 
358     private class VariableCounter implements OrekitStepHandler {
359 
360         private int    initCount;
361         private int    handleCount;
362         private int    finishCount;
363         private double start;
364         private double stop;
365 
366         @Override
367         public void init(SpacecraftState s0, AbsoluteDate t) {
368             ++initCount;
369             start = s0.getDate().durationFrom(initDate);
370         }
371 
372         @Override
373         public void handleStep(OrekitStepInterpolator interpolator) {
374             ++handleCount;
375         }
376 
377         @Override
378         public void finish(SpacecraftState finalState) {
379             ++finishCount;
380             stop = finalState.getDate().durationFrom(initDate);
381         }
382 
383     }
384 
385 }