1   /* Copyright 2002-2022 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.After;
24  import org.junit.Assert;
25  import org.junit.Before;
26  import org.junit.Test;
27  import org.orekit.Utils;
28  import org.orekit.errors.OrekitException;
29  import org.orekit.frames.FramesFactory;
30  import org.orekit.orbits.EquinoctialOrbit;
31  import org.orekit.orbits.Orbit;
32  import org.orekit.orbits.OrbitType;
33  import org.orekit.propagation.SpacecraftState;
34  import org.orekit.propagation.events.handlers.ContinueOnEvent;
35  import org.orekit.propagation.events.handlers.EventHandler;
36  import org.orekit.propagation.integration.AdditionalDerivativesProvider;
37  import org.orekit.propagation.numerical.NumericalPropagator;
38  import org.orekit.propagation.sampling.OrekitStepInterpolator;
39  import org.orekit.time.AbsoluteDate;
40  import org.orekit.time.TimeScalesFactory;
41  import org.orekit.utils.PVCoordinates;
42  
43  public class DateDetectorTest {
44  
45      private int evtno = 0;
46      private double maxCheck;
47      private double threshold;
48      private double dt;
49      private Orbit iniOrbit;
50      private AbsoluteDate iniDate;
51      private AbsoluteDate nodeDate;
52      private DateDetector dateDetector;
53      private NumericalPropagator propagator;
54  
55      @Test
56      public void testSimpleTimer() {
57          DateDetector dateDetector = new DateDetector(maxCheck, threshold, iniDate.shiftedBy(2.0*dt));
58          Assert.assertEquals(2 * dt, dateDetector.getDate().durationFrom(iniDate), 1.0e-10);
59          propagator.addAdditionalDerivativesProvider(new AdditionalDerivativesProvider() {
60              public String   getName()                      { return "dummy"; }
61              public int      getDimension()                 { return 1; }
62              public double[] derivatives(SpacecraftState s) { return new double[1]; }
63          });
64          propagator.setInitialState(propagator.getInitialState().addAdditionalState("dummy", new double[1]));
65          propagator.getMultiplexer().add(interpolator -> {
66              SpacecraftState prev = interpolator.getPreviousState();
67              SpacecraftState curr = interpolator.getCurrentState();
68              double dt = curr.getDate().durationFrom(prev.getDate());
69              OrekitStepInterpolator restricted =
70                              interpolator.restrictStep(prev.shiftedBy(dt * +0.25),
71                                                        curr.shiftedBy(dt * -0.25));
72              SpacecraftState restrictedPrev = restricted.getPreviousState();
73              SpacecraftState restrictedCurr = restricted.getCurrentState();
74              double restrictedDt = restrictedCurr.getDate().durationFrom(restrictedPrev.getDate());
75              Assert.assertEquals(dt * 0.5, restrictedDt, 1.0e-10);
76          });
77          propagator.setOrbitType(OrbitType.EQUINOCTIAL);
78          propagator.addEventDetector(dateDetector);
79          final SpacecraftState finalState = propagator.propagate(iniDate.shiftedBy(100.*dt));
80  
81          Assert.assertEquals(2.0*dt, finalState.getDate().durationFrom(iniDate), threshold);
82      }
83  
84      @Test
85      public void testEmbeddedTimer() {
86          dateDetector = new DateDetector(maxCheck, threshold);
87          Assert.assertNull(dateDetector.getDate());
88          EventDetector nodeDetector = new NodeDetector(iniOrbit, iniOrbit.getFrame()).
89                  withHandler(new ContinueOnEvent<NodeDetector>() {
90                      public Action eventOccurred(SpacecraftState s, NodeDetector nd, boolean increasing)
91                          {
92                          if (increasing) {
93                              nodeDate = s.getDate();
94                              dateDetector.addEventDate(nodeDate.shiftedBy(dt));
95                          }
96                          return Action.CONTINUE;
97                      }
98                  });
99  
100         propagator.addEventDetector(nodeDetector);
101         propagator.addEventDetector(dateDetector);
102         final SpacecraftState finalState = propagator.propagate(iniDate.shiftedBy(100.*dt));
103 
104         Assert.assertEquals(dt, finalState.getDate().durationFrom(nodeDate), threshold);
105     }
106 
107     @Test
108     public void testAutoEmbeddedTimer() {
109         dateDetector = new DateDetector(maxCheck, threshold, iniDate.shiftedBy(-dt)).
110                 withHandler(new ContinueOnEvent<DateDetector>() {
111                     public Action eventOccurred(SpacecraftState s, DateDetector dd,  boolean increasing)
112                             {
113                         AbsoluteDate nextDate = s.getDate().shiftedBy(-dt);
114                         dd.addEventDate(nextDate);
115                         ++evtno;
116                         return Action.CONTINUE;
117                     }
118                 });
119         propagator.addEventDetector(dateDetector);
120         propagator.propagate(iniDate.shiftedBy(-100.*dt));
121 
122         Assert.assertEquals(100, evtno);
123     }
124 
125     @Test(expected=IllegalArgumentException.class)
126     public void testExceptionTimer() {
127         dateDetector = new DateDetector(maxCheck, threshold, iniDate.shiftedBy(dt)).
128                 withHandler(new ContinueOnEvent<DateDetector>() {
129                     public Action eventOccurred(SpacecraftState s, DateDetector dd, boolean increasing)
130                         {
131                         double step = (evtno % 2 == 0) ? 2.*maxCheck : maxCheck/2.;
132                         AbsoluteDate nextDate = s.getDate().shiftedBy(step);
133                         dd.addEventDate(nextDate);
134                         ++evtno;
135                         return Action.CONTINUE;
136                     }
137                 });
138         propagator.addEventDetector(dateDetector);
139         propagator.propagate(iniDate.shiftedBy(100.*dt));
140     }
141 
142     /**
143      * Check that a generic event handler can be used with an event detector.
144      */
145     @Test
146     public void testGenericHandler() {
147         //setup
148         dateDetector = new DateDetector(maxCheck, threshold, iniDate.shiftedBy(dt));
149         // generic event handler that works with all detectors.
150         EventHandler<EventDetector> handler = new EventHandler<EventDetector>() {
151             @Override
152             public Action eventOccurred(SpacecraftState s,
153                                         EventDetector detector,
154                                         boolean increasing)
155                     {
156                 Assert.assertSame(dateDetector, detector);
157                 return Action.STOP;
158             }
159 
160             @Override
161             public SpacecraftState resetState(EventDetector detector,
162                                               SpacecraftState oldState)
163                     {
164                 throw new RuntimeException("Should not be called");
165             }
166         };
167 
168         //action
169         dateDetector = dateDetector.withHandler(handler);
170         propagator.addEventDetector(dateDetector);
171         SpacecraftState finalState = propagator.propagate(iniDate.shiftedBy(100 * dt));
172 
173         //verify
174         Assert.assertEquals(dt, finalState.getDate().durationFrom(iniDate), threshold);
175     }
176 
177     @Before
178     public void setUp() {
179         try {
180             Utils.setDataRoot("regular-data");
181             final double mu = 3.9860047e14;
182             final Vector3D position  = new Vector3D(-6142438.668, 3492467.560, -25767.25680);
183             final Vector3D velocity  = new Vector3D(505.8479685, 942.7809215, 7435.922231);
184             iniDate  = new AbsoluteDate(1969, 7, 28, 4, 0, 0.0, TimeScalesFactory.getTT());
185             iniOrbit = new EquinoctialOrbit(new PVCoordinates(position, velocity),
186                                             FramesFactory.getEME2000(), iniDate, mu);
187             SpacecraftState initialState = new SpacecraftState(iniOrbit);
188             double[] absTolerance = {
189                 0.001, 1.0e-9, 1.0e-9, 1.0e-6, 1.0e-6, 1.0e-6, 0.001
190             };
191             double[] relTolerance = {
192                 1.0e-7, 1.0e-4, 1.0e-4, 1.0e-7, 1.0e-7, 1.0e-7, 1.0e-7
193             };
194             AdaptiveStepsizeIntegrator integrator =
195                 new DormandPrince853Integrator(0.001, 1000, absTolerance, relTolerance);
196             integrator.setInitialStepSize(60);
197             propagator = new NumericalPropagator(integrator);
198             propagator.setInitialState(initialState);
199             dt = 60.;
200             maxCheck  = 10.;
201             threshold = 10.e-10;
202             evtno = 0;
203         } catch (OrekitException oe) {
204             Assert.fail(oe.getLocalizedMessage());
205         }
206     }
207 
208     @After
209     public void tearDown() {
210         iniDate = null;
211         propagator = null;
212         dateDetector = null;
213     }
214 
215 }