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.ArrayList;
20  import java.util.List;
21  
22  import org.hipparchus.geometry.euclidean.threed.Vector3D;
23  import org.hipparchus.ode.events.Action;
24  import org.hipparchus.util.FastMath;
25  import org.junit.After;
26  import org.junit.Assert;
27  import org.junit.Before;
28  import org.junit.Test;
29  import org.orekit.Utils;
30  import org.orekit.bodies.CelestialBodyFactory;
31  import org.orekit.bodies.OneAxisEllipsoid;
32  import org.orekit.errors.OrekitException;
33  import org.orekit.frames.FramesFactory;
34  import org.orekit.orbits.EquinoctialOrbit;
35  import org.orekit.orbits.Orbit;
36  import org.orekit.propagation.Propagator;
37  import org.orekit.propagation.SpacecraftState;
38  import org.orekit.propagation.analytical.EcksteinHechlerPropagator;
39  import org.orekit.propagation.events.handlers.EventHandler;
40  import org.orekit.time.AbsoluteDate;
41  import org.orekit.time.TimeScalesFactory;
42  import org.orekit.utils.IERSConventions;
43  import org.orekit.utils.PVCoordinates;
44  
45  public class EventShifterTest {
46  
47      private double           mu;
48      private AbsoluteDate     iniDate;
49      private Propagator       propagator;
50      private List<EventEntry> log;
51  
52      private double sunRadius = 696000000.;
53      private double earthRadius = 6400000.;
54  
55      @Test
56      public void testNegNeg() {
57          propagator.addEventDetector(createRawDetector("raw increasing", "raw decreasing", 1.0e-9));
58          EclipseDetector raw = createRawDetector("shifted increasing", "shifted decreasing", 1.0e-3);
59          final EventHandler<? super EclipseDetector> h = raw.getHandler();
60          raw = raw.withHandler(new EventHandler<EclipseDetector>() {
61  
62              @Override
63              public Action eventOccurred(SpacecraftState s,
64                                          EclipseDetector detector,
65                                          boolean increasing)
66                {
67                  h.eventOccurred(s, detector, increasing);
68                  return Action.RESET_STATE;
69              }
70  
71              @Override
72              public SpacecraftState resetState(EclipseDetector detector,
73                                                SpacecraftState oldState)
74                                                    {
75                  return h.resetState(detector, oldState);
76              }
77  
78          });
79          EventShifter<EclipseDetector> shifter = new EventShifter<EclipseDetector>(raw, true, -15, -20).
80                                                  withMaxIter(200);
81          Assert.assertEquals(-15, shifter.getIncreasingTimeShift(), 1.0e-15);
82          Assert.assertEquals(-20, shifter.getDecreasingTimeShift(), 1.0e-15);
83          Assert.assertEquals(200, shifter.getMaxIterationCount());
84          Assert.assertEquals(100, raw.getMaxIterationCount());
85          propagator.addEventDetector(shifter);
86          propagator.addEventDetector(new EventShifter<EclipseDetector>(createRawDetector("unshifted increasing", "unshifted decreasing", 1.0e-3),
87                                                                        false, -5, -10));
88          propagator.propagate(iniDate.shiftedBy(6000));
89          Assert.assertEquals(6, log.size());
90          log.get(0).checkExpected(log.get(2).getDT() - 20, "shifted decreasing");
91          log.get(1).checkExpected(log.get(2).getDT(),      "unshifted decreasing");
92          log.get(3).checkExpected(log.get(5).getDT() - 15, "shifted increasing");
93          log.get(4).checkExpected(log.get(5).getDT(),      "unshifted increasing");
94      }
95  
96      @Test
97      public void testNegPos() {
98          propagator.addEventDetector(createRawDetector("raw increasing", "raw decreasing", 1.0e-9));
99          propagator.addEventDetector(new EventShifter<EclipseDetector>(createRawDetector("shifted increasing", "shifted decreasing", 1.0e-3),
100                                                                       true, -15,  20));
101         propagator.addEventDetector(new EventShifter<EclipseDetector>(createRawDetector("unshifted increasing", "unshifted decreasing", 1.0e-3),
102                                                                       false, -5,  10));
103         propagator.propagate(iniDate.shiftedBy(6000));
104         Assert.assertEquals(6, log.size());
105         log.get(1).checkExpected(log.get(0).getDT(),      "unshifted decreasing");
106         log.get(2).checkExpected(log.get(0).getDT() + 20, "shifted decreasing");
107         log.get(3).checkExpected(log.get(5).getDT() - 15, "shifted increasing");
108         log.get(4).checkExpected(log.get(5).getDT(),      "unshifted increasing");
109     }
110 
111     @Test
112     public void testPosNeg() {
113         propagator.addEventDetector(createRawDetector("raw increasing", "raw decreasing", 1.0e-9));
114         propagator.addEventDetector(new EventShifter<EclipseDetector>(createRawDetector("shifted increasing", "shifted decreasing", 1.0e-3),
115                                                                       true,  15, -20));
116         propagator.addEventDetector(new EventShifter<EclipseDetector>(createRawDetector("unshifted increasing", "unshifted decreasing", 1.0e-3),
117                                                                       false,  5, -10));
118         propagator.propagate(iniDate.shiftedBy(6000));
119         Assert.assertEquals(6, log.size());
120         log.get(0).checkExpected(log.get(2).getDT() - 20, "shifted decreasing");
121         log.get(1).checkExpected(log.get(2).getDT(),      "unshifted decreasing");
122         log.get(4).checkExpected(log.get(3).getDT(),      "unshifted increasing");
123         log.get(5).checkExpected(log.get(3).getDT() + 15, "shifted increasing");
124     }
125 
126     @Test
127     public void testPosPos() {
128         propagator.addEventDetector(createRawDetector("raw increasing", "raw decreasing", 1.0e-9));
129         propagator.addEventDetector(new EventShifter<EclipseDetector>(createRawDetector("shifted increasing", "shifted decreasing", 1.0e-3),
130                                                                       true,  15,  20));
131         propagator.addEventDetector(new EventShifter<EclipseDetector>(createRawDetector("unshifted increasing", "unshifted decreasing", 1.0e-3),
132                                                                       false,  5,  10));
133         propagator.propagate(iniDate.shiftedBy(6000));
134         Assert.assertEquals(6, log.size());
135         log.get(1).checkExpected(log.get(0).getDT(),      "unshifted decreasing");
136         log.get(2).checkExpected(log.get(0).getDT() + 20, "shifted decreasing");
137         log.get(4).checkExpected(log.get(3).getDT(),      "unshifted increasing");
138         log.get(5).checkExpected(log.get(3).getDT() + 15, "shifted increasing");
139     }
140 
141     @Test
142     public void testIncreasingError() {
143         final EclipseDetector raw0000 = createRawDetector("raw increasing",    "raw decreasing", 2.0e-9);
144         final EclipseDetector raw0010 = createRawDetector("-10s increasing",   "-10s decreasing", 2.0e-3);
145         final EclipseDetector raw0100 = createRawDetector("-100s increasing",  "-100s decreasing", 3.0e-2);
146         final EclipseDetector raw1000 = createRawDetector("-1000s increasing", "-1000s decreasing", 5.0);
147         final EventShifter<EclipseDetector> shift0010 = new EventShifter<>(raw0010, true,   -10,   -10);
148         final EventShifter<EclipseDetector> shift0100 = new EventShifter<>(raw0100, true,  -100,  -100);
149         final EventShifter<EclipseDetector> shift1000 = new EventShifter<>(raw1000, true, -1000, -1000);
150         Assert.assertSame(raw0010, shift0010.getDetector());
151         Assert.assertSame(raw0100, shift0100.getDetector());
152         Assert.assertSame(raw1000, shift1000.getDetector());
153         propagator.addEventDetector(raw0000);
154         propagator.addEventDetector(shift0010);
155         propagator.addEventDetector(shift0100);
156         propagator.addEventDetector(shift1000);
157         propagator.propagate(iniDate.shiftedBy(20100));
158 
159         // the raw eclipses (not all within the propagation range) are at times:
160         // [ 2300.238,  4376.986]
161         // [ 8210.859, 10287.573]
162         // [14121.478, 16198.159]
163         // [20032.098, 22108.745]
164         // [25942.717, 28019.331]
165         // [31853.335, 33929.916]
166         // [37763.954, 39840.500]
167         Assert.assertEquals(28, log.size());
168         for (int i = 0; i < log.size() / 4; ++i) {
169             EventEntry ref = log.get(4 * i + 3);
170             String increasingOrDecreasing = ref.getName().split(" ")[1];
171             log.get(4 * i + 0).checkExpected(ref.getDT() - 1000, "-1000s " + increasingOrDecreasing);
172             log.get(4 * i + 1).checkExpected(ref.getDT() -  100, "-100s "  + increasingOrDecreasing);
173             log.get(4 * i + 2).checkExpected(ref.getDT() -   10, "-10s "   + increasingOrDecreasing);
174         }
175 
176         for (EventEntry entry : log) {
177             double error = entry.getTimeError();
178             if (entry.name.contains("10s")) {
179                 Assert.assertTrue(error > 1.0e-6);
180                 Assert.assertTrue(error < 3.0e-6);
181             } else if (entry.name.contains("100s")) {
182                 Assert.assertTrue(error > 0.001);
183                 Assert.assertTrue(error < 0.003);
184             } else if (entry.name.contains("1000s")) {
185                 Assert.assertTrue(error > 0.7);
186                 Assert.assertTrue(error < 1.1);
187             }
188         }
189     }
190 
191     private EclipseDetector createRawDetector(final String nameIncreasing, final String nameDecreasing,
192                                               final double tolerance) {
193         return new EclipseDetector(CelestialBodyFactory.getSun(), sunRadius,
194                                    new OneAxisEllipsoid(earthRadius,
195                                                         0.0,
196                                                         FramesFactory.getITRF(IERSConventions.IERS_2010, true))).
197                withMaxCheck(60.0).
198                withThreshold(1.0e-10).
199                withHandler(new EventHandler<EclipseDetector>() {
200                                        public Action eventOccurred(SpacecraftState s, EclipseDetector detector,
201                                                                    boolean increasing) {
202                                            log.add(new EventEntry(s.getDate().durationFrom(iniDate), tolerance,
203                                                                   increasing ? nameIncreasing : nameDecreasing));
204                                            return Action.CONTINUE;
205                                        }
206                                    });
207     }
208 
209     @Before
210     public void setUp() {
211         try {
212             Utils.setDataRoot("regular-data");
213             mu  = 3.9860047e14;
214             double ae  = 6.378137e6;
215             double c20 = -1.08263e-3;
216             double c30 = 2.54e-6;
217             double c40 = 1.62e-6;
218             double c50 = 2.3e-7;
219             double c60 = -5.5e-7;
220             final Vector3D position  = new Vector3D(-6142438.668, 3492467.560, -25767.25680);
221             final Vector3D velocity  = new Vector3D(505.8479685, 942.7809215, 7435.922231);
222             iniDate = new AbsoluteDate(1969, 7, 28, 4, 0, 0.0, TimeScalesFactory.getTT());
223             final Orbit orbit = new EquinoctialOrbit(new PVCoordinates(position,  velocity),
224                                                      FramesFactory.getGCRF(), iniDate, mu);
225             propagator =
226                 new EcksteinHechlerPropagator(orbit, ae, mu, c20, c30, c40, c50, c60);
227             log = new ArrayList<EventEntry>();
228         } catch (OrekitException oe) {
229             Assert.fail(oe.getLocalizedMessage());
230         }
231     }
232 
233     @After
234     public void tearDown() {
235         iniDate = null;
236         propagator = null;
237         log = null;
238     }
239 
240     private static class EventEntry {
241 
242         private final double dt;
243         private double expectedDT;
244         private final double tolerance;
245         private final String name;
246 
247         public EventEntry(final double dt, final double tolerance, final String name) {
248             this.dt         = dt;
249             this.expectedDT = Double.NaN;
250             this.tolerance  = tolerance;
251             this.name       = name;
252         }
253 
254         public void checkExpected(final double expectedDT, final String name) {
255             this.expectedDT = expectedDT;
256             Assert.assertEquals(expectedDT, dt, tolerance);
257             Assert.assertEquals(name, this.name);
258         }
259 
260         public double getDT() {
261             return dt;
262         }
263 
264         public String getName() {
265             return name;
266         }
267 
268         public double getTimeError() {
269             return FastMath.abs(dt - expectedDT);
270         }
271 
272     }
273 
274 }
275