1   /* Copyright 2022-2025 Romain Serra
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.analytical;
18  
19  import org.hipparchus.geometry.euclidean.threed.Rotation;
20  import org.hipparchus.ode.events.Action;
21  import org.junit.jupiter.api.Assertions;
22  import org.junit.jupiter.api.Test;
23  import org.junit.jupiter.params.ParameterizedTest;
24  import org.junit.jupiter.params.provider.EnumSource;
25  import org.orekit.attitudes.FrameAlignedProvider;
26  import org.orekit.frames.FramesFactory;
27  import org.orekit.orbits.CartesianOrbit;
28  import org.orekit.orbits.KeplerianOrbit;
29  import org.orekit.orbits.Orbit;
30  import org.orekit.orbits.PositionAngleType;
31  import org.orekit.propagation.SpacecraftState;
32  import org.orekit.propagation.events.DateDetector;
33  import org.orekit.propagation.events.EventDetectionSettings;
34  import org.orekit.propagation.events.EventDetector;
35  import org.orekit.propagation.events.handlers.ContinueOnEvent;
36  import org.orekit.propagation.events.handlers.EventHandler;
37  import org.orekit.propagation.events.handlers.StopOnEvent;
38  import org.orekit.time.AbsoluteDate;
39  import org.orekit.utils.Constants;
40  
41  import java.util.stream.Stream;
42  
43  
44  class AbstractAnalyticalPropagatorTest {
45  
46      @Test
47      void testInternalEventDetector() {
48          // GIVEN
49          final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
50          final Orbit orbit = getOrbit(date);
51          final TestAnalyticalPropagator propagator = new TestAnalyticalPropagator(orbit);
52          final AbsoluteDate interruptingDate = date.shiftedBy(1);
53          propagator.setAttitudeProvider(new InterruptingAttitudeProvider(interruptingDate));
54          // WHEN
55          final SpacecraftState state = propagator.propagate(date.shiftedBy(10.));
56          // THEN
57          Assertions.assertEquals(state.getDate(), interruptingDate);
58      }
59  
60      @ParameterizedTest
61      @EnumSource(value = Action.class, names = {"RESET_STATE", "RESET_DERIVATIVES"})
62      void testReset(final Action action) {
63          // GIVEN
64          final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
65          final Orbit orbit = getOrbit(date);
66          final TestAnalyticalPropagator propagator = new TestAnalyticalPropagator(orbit);
67          final EventHandler handler = (s, detector, increasing) -> action;
68          final TestDetector detector = new TestDetector(date.shiftedBy(0.5), handler);
69          propagator.addEventDetector(detector);
70          // WHEN
71          propagator.propagate(propagator.getInitialState().getDate().shiftedBy(1.));
72          // THEN
73          Assertions.assertTrue(detector.resetted);
74      }
75  
76      private static class TestDetector extends DateDetector {
77          boolean resetted = false;
78  
79          TestDetector(final AbsoluteDate date, final EventHandler handler) {
80              super(EventDetectionSettings.getDefaultEventDetectionSettings(), handler, 1., date);
81          }
82  
83          @Override
84          public void reset(SpacecraftState state, AbsoluteDate target) {
85              resetted = true;
86          }
87      }
88  
89      @Test
90      void testFinish() {
91          // GIVEN
92          final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
93          final Orbit orbit = getOrbit(date);
94          final TestAnalyticalPropagator propagator = new TestAnalyticalPropagator(orbit);
95          final TestHandler handler = new TestHandler();
96          propagator.addEventDetector(new DateDetector().withHandler(handler));
97          // WHEN
98          propagator.propagate(propagator.getInitialState().getDate().shiftedBy(1.));
99          // THEN
100         Assertions.assertTrue(handler.isFinished);
101     }
102 
103     private static Orbit getOrbit(final AbsoluteDate date) {
104         return new KeplerianOrbit(8000000.0, 0.01, 0.87, 2.44, 0.21, -1.05,
105                 PositionAngleType.MEAN, FramesFactory.getEME2000(), date, Constants.EIGEN5C_EARTH_MU);
106     }
107 
108     private static class TestHandler extends ContinueOnEvent {
109         boolean isFinished = false;
110 
111         @Override
112         public void finish(SpacecraftState finalState, EventDetector detector) {
113             isFinished = true;
114         }
115     }
116 
117     private static class TestAnalyticalPropagator extends AbstractAnalyticalPropagator {
118 
119         private final Orbit orbit;
120 
121         protected TestAnalyticalPropagator(Orbit orbit) {
122             super(new FrameAlignedProvider(FramesFactory.getGCRF()));
123             this.orbit = orbit;
124             resetInitialState(new SpacecraftState(orbit));
125         }
126 
127         @Override
128         protected double getMass(AbsoluteDate date) {
129             return 1;
130         }
131 
132         @Override
133         protected void resetIntermediateState(SpacecraftState state, boolean forward) {
134 
135         }
136 
137         @Override
138         public Orbit propagateOrbit(AbsoluteDate date) {
139             return new CartesianOrbit(orbit.getPVCoordinates(), orbit.getFrame(), date, orbit.getMu());
140         }
141     }
142 
143     private static class InterruptingAttitudeProvider extends FrameAlignedProvider {
144 
145         private final AbsoluteDate interruptingDate;
146 
147         public InterruptingAttitudeProvider(final AbsoluteDate interruptingDate) {
148             super(Rotation.IDENTITY);
149             this.interruptingDate = interruptingDate;
150         }
151 
152         @Override
153         public Stream<EventDetector> getEventDetectors() {
154             final DateDetector detector = new DateDetector(interruptingDate).withHandler(new StopOnEvent());
155             return Stream.of(detector);
156         }
157     }
158 }