1   package org.orekit.propagation.events;
2   
3   import org.hipparchus.geometry.euclidean.threed.Vector3D;
4   import org.junit.jupiter.api.Assertions;
5   import org.junit.jupiter.api.BeforeEach;
6   import org.junit.jupiter.api.Test;
7   import org.mockito.Mockito;
8   import org.orekit.Utils;
9   import org.orekit.bodies.AnalyticalSolarPositionProvider;
10  import org.orekit.bodies.CelestialBodyFactory;
11  import org.orekit.bodies.OneAxisEllipsoid;
12  import org.orekit.frames.Frame;
13  import org.orekit.frames.FramesFactory;
14  import org.orekit.orbits.KeplerianOrbit;
15  import org.orekit.orbits.Orbit;
16  import org.orekit.orbits.PositionAngleType;
17  import org.orekit.propagation.SpacecraftState;
18  import org.orekit.propagation.analytical.KeplerianPropagator;
19  import org.orekit.propagation.events.handlers.ContinueOnEvent;
20  import org.orekit.propagation.events.handlers.EventHandler;
21  import org.orekit.propagation.events.handlers.RecordAndContinue;
22  import org.orekit.propagation.events.intervals.AdaptableInterval;
23  import org.orekit.time.AbsoluteDate;
24  import org.orekit.utils.*;
25  
26  class CylindricalShadowEclipseDetectorTest {
27  
28      @BeforeEach
29      public void setUp() {
30          Utils.setDataRoot("regular-data");
31      }
32  
33      @Test
34      void testConstructor() {
35          // GIVEN
36          final EventDetectionSettings settings = EventDetectionSettings.getDefaultEventDetectionSettings();
37          // WHEN
38          final CylindricalShadowEclipseDetector detector = new CylindricalShadowEclipseDetector(Mockito.mock(PVCoordinatesProvider.class),
39                  1., settings, Mockito.mock(EventHandler.class));
40          // THEN
41          Assertions.assertEquals(settings.getMaxIterationCount(), detector.getDetectionSettings().getMaxIterationCount());
42          Assertions.assertEquals(settings.getThreshold(), detector.getDetectionSettings().getThreshold());
43      }
44  
45      @Test
46      void testCreate() {
47          // GIVEN
48          final ExtendedPositionProvider sun = CelestialBodyFactory.getSun();
49          final CylindricalShadowEclipseDetector eclipseDetector = new CylindricalShadowEclipseDetector(sun,
50                  Constants.EGM96_EARTH_EQUATORIAL_RADIUS, new ContinueOnEvent());
51          final AdaptableInterval adaptableInterval = AdaptableInterval.of(1.);
52          final double expectedThreshold = 0.1;
53          final int expectedMaxIter = 10;
54          // WHEN
55          final CylindricalShadowEclipseDetector detector = eclipseDetector.create(new EventDetectionSettings(adaptableInterval, expectedThreshold,
56                  expectedMaxIter), eclipseDetector.getHandler());
57          // THEN
58          Assertions.assertEquals(expectedMaxIter, detector.getMaxIterationCount());
59          Assertions.assertEquals(expectedThreshold, detector.getThreshold());
60          Assertions.assertEquals(adaptableInterval, detector.getMaxCheckInterval());
61      }
62  
63      @Test
64      void testG0Eclipse() {
65          // GIVEN
66          final PVCoordinatesProvider sun = new TestDirectionProvider();
67          final CylindricalShadowEclipseDetector eclipseDetector = new CylindricalShadowEclipseDetector(sun,
68                  Constants.EGM96_EARTH_EQUATORIAL_RADIUS, new ContinueOnEvent());
69          final Vector3D position = new Vector3D(1., eclipseDetector.getOccultingBodyRadius(), 0.);
70          final SpacecraftState mockedState = mockState(position);
71          // WHEN
72          final double g = eclipseDetector.g(mockedState);
73          // THEN
74          Assertions.assertEquals(0., g);
75      }
76  
77      @Test
78      void testGEclipse() {
79          // GIVEN
80          final PVCoordinatesProvider sun = new TestDirectionProvider();
81          final CylindricalShadowEclipseDetector eclipseDetector = new CylindricalShadowEclipseDetector(sun,
82                  Constants.EGM96_EARTH_EQUATORIAL_RADIUS, new ContinueOnEvent());
83          final Vector3D position = new Vector3D(1e7, 0, -1e2);
84          final SpacecraftState mockedState = mockState(position);
85          // WHEN
86          final double g = eclipseDetector.g(mockedState);
87          // THEN
88          Assertions.assertTrue(g < 0.);
89      }
90  
91      @Test
92      void testGNoEclipse() {
93          // GIVEN
94          final PVCoordinatesProvider sun = new TestDirectionProvider();
95          final CylindricalShadowEclipseDetector eclipseDetector = new CylindricalShadowEclipseDetector(sun,
96                  Constants.EGM96_EARTH_EQUATORIAL_RADIUS, new ContinueOnEvent());
97          final Vector3D position = new Vector3D(0., 1e4, 0.);
98          final SpacecraftState mockedState = mockState(position);
99          // WHEN
100         final double g = eclipseDetector.g(mockedState);
101         // THEN
102         Assertions.assertTrue(g > 0.);
103     }
104 
105     @Test
106     void testGNoEclipse2() {
107         // GIVEN
108         final PVCoordinatesProvider sun = new TestDirectionProvider();
109         final CylindricalShadowEclipseDetector eclipseDetector = new CylindricalShadowEclipseDetector(sun,
110                 Constants.EGM96_EARTH_EQUATORIAL_RADIUS, new ContinueOnEvent());
111         final Vector3D position = new Vector3D(-1e6, 1e3, 0.);
112         final SpacecraftState mockedState = mockState(position);
113         // WHEN
114         final double g = eclipseDetector.g(mockedState);
115         // THEN
116         Assertions.assertTrue(g > 0.);
117     }
118 
119     private SpacecraftState mockState(final Vector3D position) {
120         final SpacecraftState mockedState = Mockito.mock(SpacecraftState.class);
121         Mockito.when(mockedState.getPosition()).thenReturn(position);
122         return mockedState;
123     }
124 
125     private static class TestDirectionProvider implements PVCoordinatesProvider {
126 
127         @Override
128         public TimeStampedPVCoordinates getPVCoordinates(AbsoluteDate date, Frame frame) {
129             return new TimeStampedPVCoordinates(date, new PVCoordinates(Vector3D.MINUS_I));
130         }
131     }
132 
133     @Test
134     void testDetections() {
135         // GIVEN
136         final ExtendedPositionProvider positionProvider = new AnalyticalSolarPositionProvider();
137         final RecordAndContinue recordAndContinue = new RecordAndContinue();
138         final CylindricalShadowEclipseDetector cylindricalShadowEclipseDetector = new CylindricalShadowEclipseDetector(positionProvider,
139                 Constants.EGM96_EARTH_EQUATORIAL_RADIUS, recordAndContinue);
140         final Orbit initialOrbit = getOrbit();
141         final KeplerianPropagator propagator = new KeplerianPropagator(initialOrbit);
142         propagator.addEventDetector(cylindricalShadowEclipseDetector);
143         final AbsoluteDate targetDate = initialOrbit.getDate().shiftedBy(initialOrbit.getKeplerianPeriod() * 200);
144         // WHEN
145         propagator.propagate(targetDate);
146         // THEN
147         propagator.clearEventsDetectors();
148         propagator.resetInitialState(new SpacecraftState(initialOrbit));
149         final RecordAndContinue recordAndContinue2 = new RecordAndContinue();
150         final EclipseDetector eclipseDetector = new EclipseDetector(positionProvider,
151                 Constants.SUN_RADIUS, new OneAxisEllipsoid(cylindricalShadowEclipseDetector.getOccultingBodyRadius(), 0., FramesFactory.getGTOD(false)));
152         propagator.addEventDetector(eclipseDetector.withPenumbra().withHandler(recordAndContinue2));
153         propagator.propagate(targetDate);
154         Assertions.assertEquals(400, recordAndContinue2.getEvents().size());
155         Assertions.assertEquals(recordAndContinue.getEvents().size(), recordAndContinue2.getEvents().size());
156         for (int i = 0; i < recordAndContinue.getEvents().size(); i++) {
157             Assertions.assertEquals(0., recordAndContinue.getEvents().get(i).getState().durationFrom(recordAndContinue2.getEvents().get(i).getState()),
158                     10.);
159         }
160     }
161 
162     private static KeplerianOrbit getOrbit() {
163         return new KeplerianOrbit(Constants.EGM96_EARTH_EQUATORIAL_RADIUS + 600e3, 0.001, 0.1, 2, 3, 4, PositionAngleType.ECCENTRIC,
164                 FramesFactory.getGCRF(), AbsoluteDate.ARBITRARY_EPOCH, Constants.EGM96_EARTH_MU);
165     }
166 
167 }