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.frames;
18  
19  import org.hamcrest.MatcherAssert;
20  import org.hipparchus.complex.Complex;
21  import org.hipparchus.complex.ComplexField;
22  import org.hipparchus.geometry.euclidean.threed.Rotation;
23  import org.hipparchus.util.Binary64;
24  import org.hipparchus.util.Binary64Field;
25  import org.junit.jupiter.api.Assertions;
26  import org.junit.jupiter.api.BeforeEach;
27  import org.junit.jupiter.api.Test;
28  import org.mockito.Mockito;
29  import org.orekit.OrekitMatchers;
30  import org.orekit.Utils;
31  import org.orekit.errors.OrekitException;
32  import org.orekit.errors.OrekitMessages;
33  import org.orekit.time.AbsoluteDate;
34  import org.orekit.time.FieldAbsoluteDate;
35  import org.orekit.time.TimeScalesFactory;
36  import org.orekit.utils.IERSConventions;
37  
38  public class ITRFVersionTest {
39  
40      @Test
41      void testYears() {
42          Assertions.assertEquals(2014, ITRFVersion.ITRF_2014.getYear());
43          Assertions.assertEquals(2008, ITRFVersion.ITRF_2008.getYear());
44          Assertions.assertEquals(2005, ITRFVersion.ITRF_2005.getYear());
45          Assertions.assertEquals(2000, ITRFVersion.ITRF_2000.getYear());
46          Assertions.assertEquals(1997, ITRFVersion.ITRF_1997.getYear());
47          Assertions.assertEquals(1996, ITRFVersion.ITRF_1996.getYear());
48          Assertions.assertEquals(1994, ITRFVersion.ITRF_1994.getYear());
49          Assertions.assertEquals(1993, ITRFVersion.ITRF_1993.getYear());
50          Assertions.assertEquals(1992, ITRFVersion.ITRF_1992.getYear());
51          Assertions.assertEquals(1991, ITRFVersion.ITRF_1991.getYear());
52          Assertions.assertEquals(1990, ITRFVersion.ITRF_1990.getYear());
53          Assertions.assertEquals(1989, ITRFVersion.ITRF_1989.getYear());
54          Assertions.assertEquals(1988, ITRFVersion.ITRF_1988.getYear());
55      }
56  
57      @Test
58      void testNames() {
59          Assertions.assertEquals("ITRF-2014", ITRFVersion.ITRF_2014.getName());
60          Assertions.assertEquals("ITRF-2008", ITRFVersion.ITRF_2008.getName());
61          Assertions.assertEquals("ITRF-2005", ITRFVersion.ITRF_2005.getName());
62          Assertions.assertEquals("ITRF-2000", ITRFVersion.ITRF_2000.getName());
63          Assertions.assertEquals("ITRF-1997", ITRFVersion.ITRF_1997.getName());
64          Assertions.assertEquals("ITRF-1996", ITRFVersion.ITRF_1996.getName());
65          Assertions.assertEquals("ITRF-1994", ITRFVersion.ITRF_1994.getName());
66          Assertions.assertEquals("ITRF-1993", ITRFVersion.ITRF_1993.getName());
67          Assertions.assertEquals("ITRF-1992", ITRFVersion.ITRF_1992.getName());
68          Assertions.assertEquals("ITRF-1991", ITRFVersion.ITRF_1991.getName());
69          Assertions.assertEquals("ITRF-1990", ITRFVersion.ITRF_1990.getName());
70          Assertions.assertEquals("ITRF-1989", ITRFVersion.ITRF_1989.getName());
71          Assertions.assertEquals("ITRF-1988", ITRFVersion.ITRF_1988.getName());
72      }
73  
74      @Test
75      void testBuildFromYear() {
76          Assertions.assertEquals(ITRFVersion.ITRF_2014, ITRFVersion.getITRFVersion(2014));
77          Assertions.assertEquals(ITRFVersion.ITRF_2008, ITRFVersion.getITRFVersion(2008));
78          Assertions.assertEquals(ITRFVersion.ITRF_2005, ITRFVersion.getITRFVersion(2005));
79          Assertions.assertEquals(ITRFVersion.ITRF_2000, ITRFVersion.getITRFVersion(2000));
80          Assertions.assertEquals(ITRFVersion.ITRF_1997, ITRFVersion.getITRFVersion(1997));
81          Assertions.assertEquals(ITRFVersion.ITRF_1996, ITRFVersion.getITRFVersion(1996));
82          Assertions.assertEquals(ITRFVersion.ITRF_1994, ITRFVersion.getITRFVersion(1994));
83          Assertions.assertEquals(ITRFVersion.ITRF_1993, ITRFVersion.getITRFVersion(1993));
84          Assertions.assertEquals(ITRFVersion.ITRF_1992, ITRFVersion.getITRFVersion(1992));
85          Assertions.assertEquals(ITRFVersion.ITRF_1991, ITRFVersion.getITRFVersion(1991));
86          Assertions.assertEquals(ITRFVersion.ITRF_1990, ITRFVersion.getITRFVersion(1990));
87          Assertions.assertEquals(ITRFVersion.ITRF_1989, ITRFVersion.getITRFVersion(1989));
88          Assertions.assertEquals(ITRFVersion.ITRF_1988, ITRFVersion.getITRFVersion(1988));
89          Assertions.assertEquals(ITRFVersion.ITRF_1997, ITRFVersion.getITRFVersion(  97));
90          Assertions.assertEquals(ITRFVersion.ITRF_1996, ITRFVersion.getITRFVersion(  96));
91          Assertions.assertEquals(ITRFVersion.ITRF_1994, ITRFVersion.getITRFVersion(  94));
92          Assertions.assertEquals(ITRFVersion.ITRF_1993, ITRFVersion.getITRFVersion(  93));
93          Assertions.assertEquals(ITRFVersion.ITRF_1992, ITRFVersion.getITRFVersion(  92));
94          Assertions.assertEquals(ITRFVersion.ITRF_1991, ITRFVersion.getITRFVersion(  91));
95          Assertions.assertEquals(ITRFVersion.ITRF_1990, ITRFVersion.getITRFVersion(  90));
96          Assertions.assertEquals(ITRFVersion.ITRF_1989, ITRFVersion.getITRFVersion(  89));
97          Assertions.assertEquals(ITRFVersion.ITRF_1988, ITRFVersion.getITRFVersion(  88));
98      }
99  
100     @Test
101     void testInexistantYear() {
102         try {
103             ITRFVersion.getITRFVersion(1999);
104             Assertions.fail("an exception should have been thrown");
105         } catch (OrekitException oe) {
106             Assertions.assertEquals(OrekitMessages.NO_SUCH_ITRF_FRAME, oe.getSpecifier());
107             Assertions.assertEquals(1999, ((Integer) oe.getParts()[0]).intValue());
108         }
109     }
110 
111     @Test
112     void testBuildFromName() {
113         Assertions.assertEquals(ITRFVersion.ITRF_2014, ITRFVersion.getITRFVersion("ITRF-2014"));
114         Assertions.assertEquals(ITRFVersion.ITRF_2008, ITRFVersion.getITRFVersion("ItRf-2008"));
115         Assertions.assertEquals(ITRFVersion.ITRF_2005, ITRFVersion.getITRFVersion("iTrF-2005"));
116         Assertions.assertEquals(ITRFVersion.ITRF_2000, ITRFVersion.getITRFVersion("itrf_2000"));
117         Assertions.assertEquals(ITRFVersion.ITRF_1997, ITRFVersion.getITRFVersion("itrf 1997"));
118         Assertions.assertEquals(ITRFVersion.ITRF_1996, ITRFVersion.getITRFVersion("itrf1996"));
119         Assertions.assertEquals(ITRFVersion.ITRF_1994, ITRFVersion.getITRFVersion("itrf-1994"));
120         Assertions.assertEquals(ITRFVersion.ITRF_1993, ITRFVersion.getITRFVersion("itrf-1993"));
121         Assertions.assertEquals(ITRFVersion.ITRF_1992, ITRFVersion.getITRFVersion("itrf-1992"));
122         Assertions.assertEquals(ITRFVersion.ITRF_1991, ITRFVersion.getITRFVersion("itrf-1991"));
123         Assertions.assertEquals(ITRFVersion.ITRF_1990, ITRFVersion.getITRFVersion("itrf-1990"));
124         Assertions.assertEquals(ITRFVersion.ITRF_1989, ITRFVersion.getITRFVersion("itrf-1989"));
125         Assertions.assertEquals(ITRFVersion.ITRF_1988, ITRFVersion.getITRFVersion("itrf-1988"));
126         Assertions.assertEquals(ITRFVersion.ITRF_1997, ITRFVersion.getITRFVersion("ITRF97"));
127         Assertions.assertEquals(ITRFVersion.ITRF_1996, ITRFVersion.getITRFVersion("itrf-96"));
128         Assertions.assertEquals(ITRFVersion.ITRF_1994, ITRFVersion.getITRFVersion("itrf-94"));
129         Assertions.assertEquals(ITRFVersion.ITRF_1993, ITRFVersion.getITRFVersion("itrf-93"));
130         Assertions.assertEquals(ITRFVersion.ITRF_1992, ITRFVersion.getITRFVersion("itrf-92"));
131         Assertions.assertEquals(ITRFVersion.ITRF_1991, ITRFVersion.getITRFVersion("itrf-91"));
132         Assertions.assertEquals(ITRFVersion.ITRF_1990, ITRFVersion.getITRFVersion("itrf-90"));
133         Assertions.assertEquals(ITRFVersion.ITRF_1989, ITRFVersion.getITRFVersion("itrf-89"));
134         Assertions.assertEquals(ITRFVersion.ITRF_1988, ITRFVersion.getITRFVersion("itrf-88"));
135     }
136 
137     @Test
138     void testInexistantName() {
139         try {
140             ITRFVersion.getITRFVersion("itrf-99");
141             Assertions.fail("an exception should have been thrown");
142         } catch (OrekitException oe) {
143             Assertions.assertEquals(OrekitMessages.NO_SUCH_ITRF_FRAME, oe.getSpecifier());
144             Assertions.assertEquals("itrf-99", oe.getParts()[0]);
145         }
146     }
147 
148     @Test
149     void testMalformedName() {
150         try {
151             ITRFVersion.getITRFVersion("YTRF-2014");
152             Assertions.fail("an exception should have been thrown");
153         } catch (OrekitException oe) {
154             Assertions.assertEquals(OrekitMessages.NO_SUCH_ITRF_FRAME, oe.getSpecifier());
155             Assertions.assertEquals("YTRF-2014", oe.getParts()[0]);
156         }
157     }
158 
159     @Test
160     void testAllConverters() {
161 
162         // select the last supported ITRF version
163         ITRFVersion last = ITRFVersion.getLast();
164 
165         // for this test, we arbitrarily assume FramesFactory provides an ITRF in last supported version
166         Frame itrfLast = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
167 
168         for (final ITRFVersion origin : ITRFVersion.values()) {
169             for (final ITRFVersion destination : ITRFVersion.values()) {
170                 ITRFVersion.Converter converter = ITRFVersion.getConverter(origin, destination);
171                 Assertions.assertEquals(origin,      converter.getOrigin());
172                 Assertions.assertEquals(destination, converter.getDestination());
173                 Frame originFrame      = origin == last ?
174                                          itrfLast :
175                                          HelmertTransformation.Predefined.selectPredefined(last.getYear(), origin.getYear()).
176                                          createTransformedITRF(itrfLast, origin.toString());
177                 Frame destinationFrame = destination == last ?
178                                          itrfLast :
179                                          HelmertTransformation.Predefined.selectPredefined(last.getYear(), destination.getYear()).
180                                          createTransformedITRF(itrfLast, destination.toString());
181                 for (int year = 2000; year < 2007; ++year) {
182 
183                     AbsoluteDate date = new AbsoluteDate(year, 4, 17, 12, 0, 0, TimeScalesFactory.getTT());
184                     Transform looped =
185                            new Transform(date,
186                                          converter.getTransform(date),
187                                          destinationFrame.getTransformTo(originFrame, date));
188                     StaticTransform sLooped = StaticTransform.compose(
189                                     date,
190                                     converter.getStaticTransform(date),
191                                     destinationFrame.getStaticTransformTo(originFrame, date));
192                     if (origin != last && destination != last) {
193                         // if we use two old ITRF, as internally the pivot frame is the last one
194                         // one side of the transform is computed as f -> itrf-1 -> itrf-last, and on
195                         // the other side as f -> itrf-last and we get some inversion in between.
196                         // the errors are not strictly zero (but they are very small) because
197                         // Helmert transformations are a translation plus a rotation. If we do
198                         // t1 -> r1 -> t2 -> r2, it is not the same as t1 -> t2 -> r1 -> r2
199                         // which would correspond to simply add the offsets, velocities, rotations and rate,
200                         // which is what is done in the reference documents.
201                         // Anyway, the non-commutativity errors are well below models accuracy
202                         Assertions.assertEquals(0, looped.getTranslation().getNorm(),  3.0e-06);
203                         Assertions.assertEquals(0, looped.getVelocity().getNorm(),     9.0e-23);
204                         Assertions.assertEquals(0, looped.getRotation().getAngle(),    8.0e-13);
205                         Assertions.assertEquals(0, looped.getRotationRate().getNorm(), 2.0e-32);
206                     } else {
207                         // if we always stay in the ITRF last branch, we do the right conversions
208                         // and errors are at numerical noise level
209                         Assertions.assertEquals(0, looped.getTranslation().getNorm(),  2.0e-17);
210                         Assertions.assertEquals(0, looped.getVelocity().getNorm(),     4.0e-26);
211                         Assertions.assertEquals(0, looped.getRotation().getAngle(),    1.0e-50);
212                         Assertions.assertEquals(0, looped.getRotationRate().getNorm(), 2.0e-32);
213                     }
214                     MatcherAssert.assertThat(
215                             sLooped.getTranslation(),
216                             OrekitMatchers.vectorCloseTo(looped.getTranslation(), 0));
217                     MatcherAssert.assertThat(
218                             Rotation.distance(sLooped.getRotation(), looped.getRotation()),
219                             OrekitMatchers.closeTo(0, 0));
220 
221                     FieldAbsoluteDate<Binary64> date64 = new FieldAbsoluteDate<>(Binary64Field.getInstance(), date);
222                     FieldTransform<Binary64> looped64 =
223                                     new FieldTransform<>(date64,
224                                                          converter.getTransform(date64),
225                                                          destinationFrame.getTransformTo(originFrame, date64));
226                              if (origin != last && destination != last) {
227                                  // if we use two old ITRF, as internally the pivot frame is the last one
228                                  // one side of the transform is computed as f -> itrf-1 -> itrf-last, and on
229                                  // the other side as f -> itrf-last and we get some inversion in between.
230                                  // the errors are not strictly zero (but they are very small) because
231                                  // Helmert transformations are a translation plus a rotation. If we do
232                                  // t1 -> r1 -> t2 -> r2, it is not the same as t1 -> t2 -> r1 -> r2
233                                  // which would correspond to simply add the offsets, velocities, rotations and rate,
234                                  // which is what is done in the reference documents.
235                                  // Anyway, the non-commutativity errors are well below models accuracy
236                                  Assertions.assertEquals(0, looped64.getTranslation().getNorm().getReal(),  3.0e-06);
237                                  Assertions.assertEquals(0, looped64.getVelocity().getNorm().getReal(),     9.0e-23);
238                                  Assertions.assertEquals(0, looped64.getRotation().getAngle().getReal(),    8.0e-13);
239                                  Assertions.assertEquals(0, looped64.getRotationRate().getNorm().getReal(), 2.0e-32);
240                              } else {
241                                  // if we always stay in the ITRF last branch, we do the right conversions
242                                  // and errors are at numerical noise level
243                                  Assertions.assertEquals(0, looped64.getTranslation().getNorm().getReal(),  2.0e-17);
244                                  Assertions.assertEquals(0, looped64.getVelocity().getNorm().getReal(),     4.0e-26);
245                                  Assertions.assertEquals(0, looped64.getRotation().getAngle().getReal(),    1.0e-50);
246                                  Assertions.assertEquals(0, looped64.getRotationRate().getNorm().getReal(), 2.0e-32);
247                              }
248                 }
249             }
250         }
251     }
252 
253     @Test
254     void testConverterGetKinematicTransform() {
255         // GIVEN
256         final TransformProvider mockedProvider = Mockito.mock(TransformProvider.class);
257         final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
258         final KinematicTransform expectedTransform = Mockito.mock(KinematicTransform.class);
259         Mockito.when(mockedProvider.getKinematicTransform(date)).thenReturn(expectedTransform);
260         final ITRFVersion.Converter converter = new ITRFVersion.Converter(null, null, mockedProvider);
261         // WHEN
262         final KinematicTransform actualTransform = converter.getKinematicTransform(date);
263         // THEN
264         Assertions.assertEquals(expectedTransform, actualTransform);
265     }
266 
267     @Test
268     @SuppressWarnings("unchecked")
269     void testConverterFieldGetKinematicTransform() {
270         // GIVEN
271         final TransformProvider mockedProvider = Mockito.mock(TransformProvider.class);
272         final FieldAbsoluteDate<Complex> date = new FieldAbsoluteDate<>(ComplexField.getInstance(),
273                 AbsoluteDate.ARBITRARY_EPOCH);
274         final FieldKinematicTransform<Complex> expectedTransform = Mockito.mock(FieldKinematicTransform.class);
275         Mockito.when(mockedProvider.getKinematicTransform(date)).thenReturn(expectedTransform);
276         final ITRFVersion.Converter converter = new ITRFVersion.Converter(null, null, mockedProvider);
277         // WHEN
278         final FieldKinematicTransform<Complex> actualTransform = converter.getKinematicTransform(date);
279         // THEN
280         Assertions.assertEquals(expectedTransform, actualTransform);
281     }
282 
283     @Test
284     @SuppressWarnings("unchecked")
285     void testConverterFieldGetStaticTransform() {
286         // GIVEN
287         final TransformProvider mockedProvider = Mockito.mock(TransformProvider.class);
288         final FieldAbsoluteDate<Complex> date = new FieldAbsoluteDate<>(ComplexField.getInstance(),
289                 AbsoluteDate.ARBITRARY_EPOCH);
290         final FieldStaticTransform<Complex> expectedTransform = Mockito.mock(FieldStaticTransform.class);
291         Mockito.when(mockedProvider.getStaticTransform(date)).thenReturn(expectedTransform);
292         final ITRFVersion.Converter converter = new ITRFVersion.Converter(null, null, mockedProvider);
293         // WHEN
294         final FieldStaticTransform<Complex> actualTransform = converter.getStaticTransform(date);
295         // THEN
296         Assertions.assertEquals(expectedTransform, actualTransform);
297     }
298 
299     @BeforeEach
300     public void setUp() {
301         Utils.setDataRoot("compressed-data");
302     }
303 
304 }