1   /* Copyright 2002-2025 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  import java.util.stream.Collectors;
22  import java.util.stream.Stream;
23  
24  import org.hipparchus.CalculusFieldElement;
25  import org.hipparchus.Field;
26  import org.hipparchus.util.Binary64;
27  import org.hipparchus.util.Binary64Field;
28  import org.junit.jupiter.api.Assertions;
29  import org.junit.jupiter.api.Test;
30  import org.mockito.Mockito;
31  import org.orekit.propagation.SpacecraftState;
32  import org.orekit.propagation.events.handlers.FieldResetDerivativesOnEvent;
33  import org.orekit.propagation.events.handlers.ResetDerivativesOnEvent;
34  import org.orekit.propagation.events.intervals.AdaptableInterval;
35  import org.orekit.time.AbsoluteDate;
36  import org.orekit.time.FieldAbsoluteDate;
37  import org.orekit.time.FieldTimeStamped;
38  import org.orekit.time.TimeStamped;
39  import org.orekit.utils.Constants;
40  import org.orekit.utils.ParameterDriver;
41  
42  /**
43   * Unit tests for {@link EventDetectorsProvider}.
44   *
45   * @since 12.0
46   * @author Maxime Journot
47   */
48  public class EventDetectorsProviderTest {
49  
50      /** Test default methods with different {@link ParameterDriver} list.
51       * <p>
52       * 1. Empty list<p>
53       * 2. List without time-spanned drivers<p>
54       * 3. List with time-spanned drivers
55       */
56      @Test
57      public void testGetEventDetectors() {
58  
59          // Given
60          // -----
61  
62          // Define drivers
63          final List<ParameterDriver> drivers = new ArrayList<>();
64          final EventDetectorsProvider provider = getProvider(drivers);
65  
66          // When: empty drivers list
67          // ----
68  
69          List<EventDetector>                detectors      = provider.getEventDetectors().collect(Collectors.toList());
70          List<FieldEventDetector<Binary64>> fieldDetectors = provider.getFieldEventDetectors(Binary64Field.getInstance()).collect(Collectors.toList());
71  
72          // Then
73          Assertions.assertTrue(detectors.isEmpty());
74          Assertions.assertTrue(fieldDetectors.isEmpty());
75  
76  
77          // When: multiple drivers with no time-span
78          // ----
79  
80          final ParameterDriver param1 = new ParameterDriver("param-1", 0., 1., -1., 1.);
81          final ParameterDriver param2 = new ParameterDriver("param-2", 0., 1., -1., 1.);
82          final ParameterDriver param3 = new ParameterDriver("param-3", 0., 1., -1., 1.);
83          
84          drivers.add(param1);
85          drivers.add(param2);
86          drivers.add(param3);
87          
88          final Binary64Field b64Field = Binary64Field.getInstance(); 
89  
90          detectors      = provider.getEventDetectors().collect(Collectors.toList());
91          fieldDetectors = provider.getFieldEventDetectors(b64Field).collect(Collectors.toList());
92  
93  
94          // Then: detectors' list is still empty
95          Assertions.assertTrue(detectors.isEmpty());
96          Assertions.assertTrue(fieldDetectors.isEmpty());
97          
98          // When: time-spanned drivers
99          // ----
100 
101         // Add spans with different dates and steps between dates
102         final AbsoluteDate t0 = AbsoluteDate.ARBITRARY_EPOCH;
103         final double step2 = 3600.;
104         final double step3 = 5000.;
105         param2.addSpans(t0, t0.shiftedBy(Constants.JULIAN_DAY), step2);
106         param3.addSpans(t0.shiftedBy(-2. * Constants.JULIAN_DAY), t0.shiftedBy(-Constants.JULIAN_DAY), step3);
107 
108         detectors      = provider.getEventDetectors().collect(Collectors.toList());
109         fieldDetectors = provider.getFieldEventDetectors(Binary64Field.getInstance()).collect(Collectors.toList());
110 
111         // Then        
112         
113         // Detectors list not empty
114         Assertions.assertFalse(detectors.isEmpty());
115         Assertions.assertEquals(1, detectors.size());
116         Assertions.assertInstanceOf(DateDetector.class, detectors.get(0));
117         
118         Assertions.assertFalse(fieldDetectors.isEmpty());
119         Assertions.assertEquals(1, fieldDetectors.size());
120         Assertions.assertInstanceOf(FieldDateDetector.class, fieldDetectors.get(0));
121 
122         // Check dates
123         final int expectedDatesNb = 39;
124         final DateDetector       dateDetector = (DateDetector) detectors.get(0);
125         final List<TimeStamped>  dates        = dateDetector.getDates();
126                 
127         Assertions.assertEquals(expectedDatesNb, dates.size());
128         Assertions.assertEquals(0., dates.get(0).durationFrom(t0.shiftedBy(-2. * Constants.JULIAN_DAY + step3)), 0.);
129         Assertions.assertEquals(0., dates.get(expectedDatesNb-1).durationFrom(t0.shiftedBy(Constants.JULIAN_DAY - step2)), 0.);
130 
131         // Field version
132         final FieldDateDetector<Binary64> fieldDateDetector = (FieldDateDetector<Binary64>) fieldDetectors.get(0);
133         List<FieldTimeStamped<Binary64>>  fieldDates        = fieldDateDetector.getDates();
134         
135         Assertions.assertEquals(expectedDatesNb, dates.size());
136         Assertions.assertEquals(0.,
137                                 fieldDates.get(0).durationFrom(new FieldAbsoluteDate<>(b64Field,
138                                                 t0.shiftedBy(-2. * Constants.JULIAN_DAY + step3))).getReal(),
139                                 0.);
140         Assertions.assertEquals(0.,
141                                 fieldDates.get(expectedDatesNb-1).durationFrom(new FieldAbsoluteDate<>(b64Field,
142                                                 t0.shiftedBy(Constants.JULIAN_DAY - step2))).getReal(),
143                                 0.);
144     }
145 
146     @Test
147     void testGetDateDetector() {
148         // GIVEN
149         final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
150         final double shift = 10.;
151         final AbsoluteDate nextDate = date.shiftedBy(shift);
152         final EventDetectorsProvider provider = getProvider(new ArrayList<>());
153         // WHEN
154         final DateDetector detector = provider.getDateDetector(date, nextDate);
155         // THEN
156         Assertions.assertEquals(2, detector.getDates().size());
157         Assertions.assertEquals(EventDetectorsProvider.DATATION_ACCURACY, detector.getThreshold());
158         Assertions.assertInstanceOf(ResetDerivativesOnEvent.class, detector.getHandler());
159         final AdaptableInterval interval = detector.getMaxCheckInterval();
160         SpacecraftState mockedState = Mockito.mock(SpacecraftState.class);
161         for (int i = 0; i < 10; i++) {
162             Mockito.when(mockedState.getDate()).thenReturn(date.shiftedBy(i));
163             Assertions.assertTrue(interval.currentInterval(mockedState, true) >= shift / 2);
164         }
165     }
166 
167     @Test
168     void testGetFieldDateDetector() {
169         // GIVEN
170         final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
171         final AbsoluteDate nextDate = date.shiftedBy(1.);
172         final EventDetectorsProvider provider = getProvider(new ArrayList<>());
173         final Binary64Field field = Binary64Field.getInstance();
174         // WHEN
175         final FieldDateDetector<Binary64> detector = provider.getFieldDateDetector(field, date, nextDate);
176         // THEN
177         Assertions.assertEquals(2, detector.getDates().size());
178         Assertions.assertEquals(EventDetectorsProvider.DATATION_ACCURACY, detector.getThreshold().getReal());
179         Assertions.assertInstanceOf(FieldResetDerivativesOnEvent.class, detector.getHandler());
180     }
181 
182     private static EventDetectorsProvider getProvider(final List<ParameterDriver> drivers) {
183         return new EventDetectorsProvider() {
184 
185             @Override
186             public <T extends CalculusFieldElement<T>> Stream<FieldEventDetector<T>> getFieldEventDetectors(Field<T> field) {
187 
188                 return getFieldEventDetectors(field, drivers);
189             }
190 
191             @Override
192             public Stream<EventDetector> getEventDetectors() {
193                 return getEventDetectors(drivers);
194             }
195         };
196     }
197 }