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 java.util.List;
20  
21  import org.hipparchus.exception.MathRuntimeException;
22  import org.hipparchus.geometry.euclidean.threed.Vector3D;
23  import org.hipparchus.ode.nonstiff.AdaptiveStepsizeIntegrator;
24  import org.hipparchus.ode.nonstiff.DormandPrince853Integrator;
25  import org.hipparchus.util.FastMath;
26  import org.junit.After;
27  import org.junit.Assert;
28  import org.junit.Before;
29  import org.junit.Test;
30  import org.orekit.Utils;
31  import org.orekit.bodies.CelestialBody;
32  import org.orekit.bodies.CelestialBodyFactory;
33  import org.orekit.bodies.OneAxisEllipsoid;
34  import org.orekit.errors.OrekitException;
35  import org.orekit.errors.OrekitMessages;
36  import org.orekit.frames.FramesFactory;
37  import org.orekit.orbits.CartesianOrbit;
38  import org.orekit.orbits.EquinoctialOrbit;
39  import org.orekit.orbits.KeplerianOrbit;
40  import org.orekit.orbits.Orbit;
41  import org.orekit.orbits.OrbitType;
42  import org.orekit.orbits.PositionAngle;
43  import org.orekit.propagation.SpacecraftState;
44  import org.orekit.propagation.events.EventsLogger.LoggedEvent;
45  import org.orekit.propagation.events.handlers.ContinueOnEvent;
46  import org.orekit.propagation.events.handlers.StopOnDecreasing;
47  import org.orekit.propagation.numerical.NumericalPropagator;
48  import org.orekit.time.AbsoluteDate;
49  import org.orekit.time.TimeScalesFactory;
50  import org.orekit.utils.Constants;
51  import org.orekit.utils.IERSConventions;
52  import org.orekit.utils.PVCoordinates;
53  import org.orekit.utils.TimeStampedPVCoordinates;
54  
55  public class EclipseDetectorTest {
56  
57      private double               mu;
58      private AbsoluteDate         iniDate;
59      private SpacecraftState      initialState;
60      private NumericalPropagator  propagator;
61  
62      private CelestialBody        sun;
63      private OneAxisEllipsoid     earth;
64      private double               sunRadius;
65  
66      @Test
67      public void testPolar() {
68          final KeplerianOrbit original = (KeplerianOrbit) OrbitType.KEPLERIAN.convertType(initialState.getOrbit());
69          final KeplerianOrbit polar    = new KeplerianOrbit(original.getA(), original.getE(),
70                                                             0.5 * FastMath.PI, original.getPerigeeArgument(),
71                                                             original.getRightAscensionOfAscendingNode(),
72                                                             original.getTrueAnomaly(), PositionAngle.TRUE,
73                                                             original.getFrame(), original.getDate(),
74                                                             original.getMu());
75          propagator.resetInitialState(new SpacecraftState(polar));
76          EventsLogger logger = new EventsLogger();
77          OneAxisEllipsoid sphericalEarth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
78                                                                 0.0,
79                                                                 FramesFactory.getITRF(IERSConventions.IERS_2010,
80                                                                                       true));
81          EclipseDetector withoutFlattening = new EclipseDetector(sun, sunRadius, sphericalEarth).
82                                              withMaxCheck(60.0).
83                                              withThreshold(1.0e-3).
84                                              withHandler(new ContinueOnEvent<>()).
85                                              withUmbra();
86          OneAxisEllipsoid obateEarth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
87                                                             Constants.WGS84_EARTH_FLATTENING,
88                                                             FramesFactory.getITRF(IERSConventions.IERS_2010,
89                                                                                   true));
90          EclipseDetector withFlattening    = new EclipseDetector(sun, sunRadius, obateEarth).
91                                              withMaxCheck(60.0).
92                                              withThreshold(1.0e-3).
93                                              withHandler(new ContinueOnEvent<>()).
94                                              withUmbra();
95          propagator.addEventDetector(logger.monitorDetector(withoutFlattening));
96          propagator.addEventDetector(logger.monitorDetector(withFlattening));
97          double duration = 15000.0;
98          final SpacecraftState finalState = propagator.propagate(iniDate.shiftedBy(duration));
99          Assert.assertEquals(duration, finalState.getDate().durationFrom(iniDate), 1.0e-3);
100         final List<LoggedEvent> events = logger.getLoggedEvents();
101         Assert.assertEquals(10, events.size());
102         Assert.assertTrue(events.get(0).getEventDetector() == withoutFlattening);
103         Assert.assertFalse(events.get(0).isIncreasing());
104         Assert.assertEquals( 2274.702, events.get(0).getState().getDate().durationFrom(iniDate), 1.0e-3);
105         Assert.assertTrue(events.get(1).getEventDetector() == withFlattening);
106         Assert.assertFalse(events.get(1).isIncreasing());
107         Assert.assertEquals( 2280.427, events.get(1).getState().getDate().durationFrom(iniDate), 1.0e-3);
108         Assert.assertTrue(events.get(2).getEventDetector() == withFlattening);
109         Assert.assertTrue(events.get(2).isIncreasing());
110         Assert.assertEquals( 4310.742, events.get(2).getState().getDate().durationFrom(iniDate), 1.0e-3);
111         Assert.assertTrue(events.get(3).getEventDetector() == withoutFlattening);
112         Assert.assertTrue(events.get(3).isIncreasing());
113         Assert.assertEquals( 4317.155, events.get(3).getState().getDate().durationFrom(iniDate), 1.6e-3);
114         Assert.assertTrue(events.get(4).getEventDetector() == withoutFlattening);
115         Assert.assertFalse(events.get(4).isIncreasing());
116         Assert.assertEquals( 8189.250, events.get(4).getState().getDate().durationFrom(iniDate), 1.0e-3);
117         Assert.assertTrue(events.get(5).getEventDetector() == withFlattening);
118         Assert.assertFalse(events.get(5).isIncreasing());
119         Assert.assertEquals( 8194.978, events.get(5).getState().getDate().durationFrom(iniDate), 1.0e-3);
120         Assert.assertTrue(events.get(6).getEventDetector() == withFlattening);
121         Assert.assertTrue(events.get(6).isIncreasing());
122         Assert.assertEquals(10225.704, events.get(6).getState().getDate().durationFrom(iniDate), 1.0e-3);
123         Assert.assertTrue(events.get(7).getEventDetector() == withoutFlattening);
124         Assert.assertTrue(events.get(7).isIncreasing());
125         Assert.assertEquals(10232.115, events.get(7).getState().getDate().durationFrom(iniDate), 1.0e-3);
126         Assert.assertTrue(events.get(8).getEventDetector() == withoutFlattening);
127         Assert.assertFalse(events.get(8).isIncreasing());
128         Assert.assertEquals(14103.800, events.get(8).getState().getDate().durationFrom(iniDate), 1.0e-3);
129         Assert.assertTrue(events.get(9).getEventDetector() == withFlattening);
130         Assert.assertFalse(events.get(9).isIncreasing());
131         Assert.assertEquals(14109.530, events.get(9).getState().getDate().durationFrom(iniDate), 1.0e-3);
132 
133     }
134 
135     @Test
136     public void testEclipse() {
137         EclipseDetector e = new EclipseDetector(sun, sunRadius, earth).
138                             withMaxCheck(60.0).
139                             withThreshold(1.0e-3).
140                             withHandler(new StopOnDecreasing<EclipseDetector>()).
141                             withUmbra();
142         Assert.assertEquals(60.0, e.getMaxCheckInterval(), 1.0e-15);
143         Assert.assertEquals(1.0e-3, e.getThreshold(), 1.0e-15);
144         Assert.assertEquals(AbstractDetector.DEFAULT_MAX_ITER, e.getMaxIterationCount());
145         Assert.assertTrue(e.getTotalEclipse());
146         propagator.addEventDetector(e);
147         final SpacecraftState finalState = propagator.propagate(iniDate.shiftedBy(6000));
148         Assert.assertEquals(2303.1835, finalState.getDate().durationFrom(iniDate), 1.0e-3);
149     }
150 
151     @Test
152     public void testPenumbra() {
153         EclipseDetector e = new EclipseDetector(sun, sunRadius, earth).
154                             withMaxCheck(60.0).
155                             withThreshold(1.0e-3).
156                             withPenumbra();
157         Assert.assertFalse(e.getTotalEclipse());
158         propagator.addEventDetector(e);
159         final SpacecraftState finalState = propagator.propagate(iniDate.shiftedBy(6000));
160         Assert.assertEquals(4388.155852, finalState.getDate().durationFrom(iniDate), 2.0e-6);
161     }
162 
163     @Test
164     public void testWithMethods() {
165         EclipseDetector e = new EclipseDetector(sun, sunRadius, earth).
166                              withHandler(new StopOnDecreasing<EclipseDetector>()).
167                              withMaxCheck(120.0).
168                              withThreshold(1.0e-4).
169                              withMaxIter(12);
170         Assert.assertEquals(120.0, e.getMaxCheckInterval(), 1.0e-15);
171         Assert.assertEquals(1.0e-4, e.getThreshold(), 1.0e-15);
172         Assert.assertEquals(12, e.getMaxIterationCount());
173         propagator.addEventDetector(e);
174         final SpacecraftState finalState = propagator.propagate(iniDate.shiftedBy(6000));
175         Assert.assertEquals(2303.1835, finalState.getDate().durationFrom(iniDate), 1.0e-3);
176 
177     }
178 
179     @Test
180     public void testInsideOcculting() {
181         EclipseDetector e = new EclipseDetector(sun, sunRadius, earth);
182         SpacecraftState s = new SpacecraftState(new CartesianOrbit(new TimeStampedPVCoordinates(AbsoluteDate.J2000_EPOCH,
183                                                                                                 new Vector3D(1e6, 2e6, 3e6),
184                                                                                                 new Vector3D(1000, 0, 0)),
185                                                                    FramesFactory.getGCRF(),
186                                                                    mu));
187         try {
188             e.g(s);
189             Assert.fail("an exception should have been thrown");
190         } catch (OrekitException oe) {
191             Assert.assertEquals(OrekitMessages.POINT_INSIDE_ELLIPSOID, oe.getSpecifier());
192         }
193     }
194 
195     @Test
196     public void testInsideOcculted() {
197         EclipseDetector e = new EclipseDetector(sun, sunRadius, earth);
198         Vector3D p = sun.getPVCoordinates(AbsoluteDate.J2000_EPOCH,
199                                           FramesFactory.getGCRF()).getPosition();
200         SpacecraftState s = new SpacecraftState(new CartesianOrbit(new TimeStampedPVCoordinates(AbsoluteDate.J2000_EPOCH,
201                                                                                                 p.add(Vector3D.PLUS_I),
202                                                                                                 Vector3D.PLUS_K),
203                                                                    FramesFactory.getGCRF(),
204                                                                    mu));
205         Assert.assertEquals(FastMath.PI, e.g(s), 1.0e-15);
206     }
207 
208     @Test
209     public void testTooSmallMaxIterationCount() {
210         int n = 5;
211         EclipseDetector e = new EclipseDetector(sun, sunRadius, earth).
212                              withHandler(new StopOnDecreasing<EclipseDetector>()).
213                              withMaxCheck(120.0).
214                              withThreshold(1.0e-4).
215                              withMaxIter(n);
216        propagator.addEventDetector(e);
217         try {
218             propagator.propagate(iniDate.shiftedBy(6000));
219             Assert.fail("an exception should have been thrown");
220         } catch (OrekitException oe) {
221             Assert.assertEquals(n, ((Integer) ((MathRuntimeException) oe.getCause()).getParts()[0]).intValue());
222         }
223     }
224 
225     @Before
226     public void setUp() {
227         try {
228             Utils.setDataRoot("regular-data");
229             mu  = 3.9860047e14;
230             final Vector3D position  = new Vector3D(-6142438.668, 3492467.560, -25767.25680);
231             final Vector3D velocity  = new Vector3D(505.8479685, 942.7809215, 7435.922231);
232             iniDate = new AbsoluteDate(1969, 7, 28, 4, 0, 0.0, TimeScalesFactory.getTT());
233             final Orbit orbit = new EquinoctialOrbit(new PVCoordinates(position,  velocity),
234                                                      FramesFactory.getGCRF(), iniDate, mu);
235             initialState = new SpacecraftState(orbit);
236             double[] absTolerance = {
237                 0.001, 1.0e-9, 1.0e-9, 1.0e-6, 1.0e-6, 1.0e-6, 0.001
238             };
239             double[] relTolerance = {
240                 1.0e-7, 1.0e-4, 1.0e-4, 1.0e-7, 1.0e-7, 1.0e-7, 1.0e-7
241             };
242             AdaptiveStepsizeIntegrator integrator =
243                 new DormandPrince853Integrator(0.001, 1000, absTolerance, relTolerance);
244             integrator.setInitialStepSize(60);
245             propagator = new NumericalPropagator(integrator);
246             propagator.setInitialState(initialState);
247             sun = CelestialBodyFactory.getSun();
248             earth = new OneAxisEllipsoid(6400000., 0.0, FramesFactory.getITRF(IERSConventions.IERS_2010, true));
249             sunRadius = 696000000.;
250         } catch (OrekitException oe) {
251             Assert.fail(oe.getLocalizedMessage());
252         }
253     }
254 
255     @After
256     public void tearDown() {
257         iniDate = null;
258         initialState = null;
259         propagator = null;
260     }
261 
262 }
263