1   /* Copyright 2002-2025 Joseph Reed
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    * Joseph Reed 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.utils;
18  
19  import org.hipparchus.geometry.euclidean.threed.Vector3D;
20  import org.junit.jupiter.api.Assertions;
21  import org.junit.jupiter.api.BeforeEach;
22  import org.junit.jupiter.api.Test;
23  import org.mockito.ArgumentMatchers;
24  import org.mockito.Mockito;
25  import org.orekit.TestUtils;
26  import org.orekit.Utils;
27  import org.orekit.errors.OrekitException;
28  import org.orekit.errors.OrekitMessages;
29  import org.orekit.frames.FramesFactory;
30  import org.orekit.orbits.Orbit;
31  import org.orekit.time.AbsoluteDate;
32  
33  /** Unit tests for {@link AggregatedPVCoordinatesProvider}. */
34  public class AggregatedPVCoordinatesProviderTest {
35      
36      private final PVCoordinatesProvider pv1 = Mockito.mock(PVCoordinatesProvider.class);
37      
38      private final PVCoordinatesProvider pv2 = Mockito.mock(PVCoordinatesProvider.class);
39      
40      private final PVCoordinatesProvider pv3 = Mockito.mock(PVCoordinatesProvider.class);
41      
42      private final TimeStampedPVCoordinates pv = Mockito.mock(TimeStampedPVCoordinates.class);
43      private AbsoluteDate date1;
44      private AbsoluteDate date2;
45      private AbsoluteDate date3;
46      private AbsoluteDate date4;
47  
48      /** Set up test data. */
49      @BeforeEach
50      public void setup() {
51          Utils.setDataRoot("regular-data");
52  
53          date1 = AbsoluteDate.J2000_EPOCH;
54          date2 = date1.shiftedBy(86400);
55          date3 = date2.shiftedBy(86400);
56          date4 = date3.shiftedBy(86400);
57      }
58  
59      @Test
60      void testGetPosition() {
61          // GIVEN
62          final Orbit orbit = TestUtils.getDefaultOrbit(AbsoluteDate.ARBITRARY_EPOCH);
63          final TimeSpanMap<PVCoordinatesProvider> map = new TimeSpanMap<>(null);
64          map.addValidBetween(orbit, AbsoluteDate.PAST_INFINITY, AbsoluteDate.FUTURE_INFINITY);
65          final AggregatedPVCoordinatesProvider provider = new AggregatedPVCoordinatesProvider(map);
66          // WHEN
67          final Vector3D position = provider.getPosition(orbit.getDate(), orbit.getFrame());
68          // THEN
69          Assertions.assertArrayEquals(orbit.getPosition().toArray(), position.toArray(), 1e-12);
70      }
71  
72      @Test
73      void testGetVelocity() {
74          // GIVEN
75          final Orbit orbit = TestUtils.getDefaultOrbit(AbsoluteDate.ARBITRARY_EPOCH);
76          final TimeSpanMap<PVCoordinatesProvider> map = new TimeSpanMap<>(null);
77          map.addValidBetween(orbit, AbsoluteDate.PAST_INFINITY, AbsoluteDate.FUTURE_INFINITY);
78          final AggregatedPVCoordinatesProvider provider = new AggregatedPVCoordinatesProvider(map);
79          // WHEN
80          final Vector3D velocity = provider.getVelocity(orbit.getDate(), orbit.getFrame());
81          // THEN
82          Assertions.assertArrayEquals(orbit.getVelocity().toArray(), velocity.toArray(), 1e-12);
83      }
84  
85      @Test
86      void invalidPVProviderVelocityTooEarly() {
87          Assertions.assertThrows(OrekitException.class, () -> {
88              final PVCoordinatesProvider pvProv = new AggregatedPVCoordinatesProvider.InvalidPVProvider();
89              pvProv.getVelocity(AbsoluteDate.PAST_INFINITY, FramesFactory.getGCRF());
90          });
91      }
92  
93      @Test
94      void invalidPVProviderVelocityTooLate() {
95          Assertions.assertThrows(OrekitException.class, () -> {
96              final PVCoordinatesProvider pvProv = new AggregatedPVCoordinatesProvider.InvalidPVProvider();
97              pvProv.getVelocity(AbsoluteDate.FUTURE_INFINITY, FramesFactory.getGCRF());
98          });
99      }
100 
101     @Test
102     void invalidPVProviderPositionTooEarly() {
103         Assertions.assertThrows(OrekitException.class, () -> {
104             final PVCoordinatesProvider pvProv = new AggregatedPVCoordinatesProvider.InvalidPVProvider();
105             pvProv.getPosition(AbsoluteDate.PAST_INFINITY, FramesFactory.getGCRF());
106         });
107     }
108 
109     @Test
110     void invalidPVProviderPositionTooLate() {
111         Assertions.assertThrows(OrekitException.class, () -> {
112             final PVCoordinatesProvider pvProv = new AggregatedPVCoordinatesProvider.InvalidPVProvider();
113             pvProv.getPosition(AbsoluteDate.FUTURE_INFINITY, FramesFactory.getGCRF());
114         });
115     }
116 
117     @Test
118     public void invalidPVProvider() {
119         Assertions.assertThrows(OrekitException.class, () -> {
120             final PVCoordinatesProvider pvProv = new AggregatedPVCoordinatesProvider.InvalidPVProvider();
121             pvProv.getPVCoordinates(date1, FramesFactory.getGCRF());
122         });
123     }
124 
125     @Test
126     public void nominalCase() {
127         final AggregatedPVCoordinatesProvider pvProv = new AggregatedPVCoordinatesProvider.Builder()
128             .addPVProviderAfter(date1, pv1, false)
129             .addPVProviderAfter(date2, pv2, false)
130             .addPVProviderAfter(date3, pv3, false)
131             .invalidAfter(date4)
132             .build();
133 
134         Mockito.when(pv1.getPVCoordinates(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(pv);
135 
136         Assertions.assertEquals(date1, pvProv.getMinDate());
137         Assertions.assertEquals(date4, pvProv.getMaxDate());
138 
139         // check start date
140         Assertions.assertSame(pv, pvProv.getPVCoordinates(date1, FramesFactory.getGCRF()));
141         // check middle date
142         Assertions.assertSame(pv, pvProv.getPVCoordinates(date1.shiftedBy(43200), FramesFactory.getGCRF()));
143 
144         Mockito.verify(pv1, Mockito.times(2)).getPVCoordinates(ArgumentMatchers.any(),
145                 ArgumentMatchers.eq(FramesFactory.getGCRF()));
146         Mockito.verifyNoMoreInteractions(pv1, pv2, pv3);
147     }
148 
149     @Test
150     public void alwaysValid() {
151         final AggregatedPVCoordinatesProvider pvProv = new AggregatedPVCoordinatesProvider.Builder(pv1).build();
152 
153         pvProv.getPVCoordinates(date1.shiftedBy(-1.), FramesFactory.getGCRF());
154         pvProv.getPVCoordinates(date1, FramesFactory.getGCRF());
155         pvProv.getPVCoordinates(date4, FramesFactory.getGCRF());
156 
157         Assertions.assertEquals(AbsoluteDate.PAST_INFINITY, pvProv.getMinDate());
158         Assertions.assertEquals(AbsoluteDate.FUTURE_INFINITY, pvProv.getMaxDate());
159 
160         Mockito.verify(pv1, Mockito.times(3)).getPVCoordinates(ArgumentMatchers.any(),
161                 ArgumentMatchers.eq(FramesFactory.getGCRF()));
162     }
163 
164     @Test
165     public void alwaysValidAfter() {
166         final AggregatedPVCoordinatesProvider pvProv = new AggregatedPVCoordinatesProvider.Builder(pv1)
167                 .invalidBefore(date1)
168                 .addPVProviderBefore(date2, pv2, false)
169                 .build();
170 
171         pvProv.getPVCoordinates(date1, FramesFactory.getGCRF());
172         pvProv.getPVCoordinates(date3, FramesFactory.getGCRF());
173 
174         try {
175             pvProv.getPVCoordinates(date1.shiftedBy(-1.), FramesFactory.getGCRF());
176             Assertions.fail("expected exception not thrown");
177         } catch (final OrekitException ex) {
178             Assertions.assertEquals(OrekitMessages.OUT_OF_RANGE_DATE, ex.getSpecifier());
179         }
180 
181         Assertions.assertEquals(date1, pvProv.getMinDate());
182         Assertions.assertEquals(AbsoluteDate.FUTURE_INFINITY, pvProv.getMaxDate());
183 
184         Mockito.verify(pv1).getPVCoordinates(ArgumentMatchers.eq(date3),
185                 ArgumentMatchers.eq(FramesFactory.getGCRF()));
186         Mockito.verify(pv2).getPVCoordinates(ArgumentMatchers.eq(date1),
187                 ArgumentMatchers.eq(FramesFactory.getGCRF()));
188     }
189 
190     @Test
191     public void invalidBefore() {
192         Assertions.assertThrows(OrekitException.class, () -> {
193             final PVCoordinatesProvider pvProv = new AggregatedPVCoordinatesProvider.Builder()
194                     .addPVProviderAfter(date1, pv1, false)
195                     .addPVProviderAfter(date2, pv2, false)
196                     .addPVProviderAfter(date3, pv3, false)
197                     .invalidAfter(date4)
198                     .build();
199             pvProv.getPVCoordinates(date1.shiftedBy(-1.), FramesFactory.getGCRF());
200         });
201     }
202 
203     @Test
204     public void invalidAfter() {
205         Assertions.assertThrows(OrekitException.class, () -> {
206             final PVCoordinatesProvider pvProv = new AggregatedPVCoordinatesProvider.Builder()
207                     .addPVProviderAfter(date1, pv1, false)
208                     .addPVProviderAfter(date2, pv2, false)
209                     .addPVProviderAfter(date3, pv3, false)
210                     .invalidAfter(date4)
211                     .build();
212             pvProv.getPVCoordinates(date4.shiftedBy(1.), FramesFactory.getGCRF());
213         });
214     }
215 }