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.hipparchus.util.FastMath;
20  import org.junit.jupiter.api.Assertions;
21  import org.junit.jupiter.api.BeforeEach;
22  import org.junit.jupiter.api.Test;
23  import org.orekit.Utils;
24  import org.orekit.time.AbsoluteDate;
25  import org.orekit.time.TimeScalesFactory;
26  import org.orekit.utils.AngularDerivativesFilter;
27  import org.orekit.utils.CartesianDerivativesFilter;
28  import org.orekit.utils.Constants;
29  import org.orekit.utils.IERSConventions;
30  import org.orekit.utils.OrekitConfiguration;
31  
32  import java.util.ArrayList;
33  
34  public class CIRFProviderTest {
35  
36      @Test
37      public void testRotationRate() {
38          EOPHistory eopHistory = FramesFactory.getEOPHistory(IERSConventions.IERS_2010, true);
39          TransformProvider provider =
40                  new InterpolatingTransformProvider(new CIRFProvider(eopHistory),
41                                                     CartesianDerivativesFilter.USE_PVA,
42                                                     AngularDerivativesFilter.USE_R,
43                                                     3, 1.0, 5, Constants.JULIAN_DAY, 100.0);
44          AbsoluteDate tMin = new AbsoluteDate(2009, 4, 7, 2, 56, 33.816, TimeScalesFactory.getUTC());
45          double minRate = provider.getTransform(tMin).getRotationRate().getNorm();
46          Assertions.assertEquals(1.1e-15, minRate, 1.0e-16);
47          AbsoluteDate tMax = new AbsoluteDate(2043, 12, 16, 10, 47, 20, TimeScalesFactory.getUTC());
48          double maxRate = provider.getTransform(tMax).getRotationRate().getNorm();
49          Assertions.assertEquals(8.6e-12, maxRate, 1.0e-13);
50      }
51  
52      @Test
53      public void testShiftingAccuracyWithEOP() {
54  
55          // max shift error observed on a 2 months period with 60 seconds step
56          // the shifting step after the interpolation step induces that mainly the
57          // step size has an influence on the error. The number of points used in
58          // the lower level interpolation does affect the results but less than
59          // step size. Plotting the error curves show almost superposition of all
60          // curves with the same time step. The error curves exhibit smooth periodic
61          // pattern with a main period corresponding to the Moon period plus peaks
62          // corresponding to Runge phenomenon when EOP data changes at midnight.
63          //
64          // number of sample points    time between sample points    max error
65          //         6                         86400s / 12 = 2h00    9.56e-12 rad
66          //         6                         86400s / 18 = 1h20    6.20e-12 rad
67          //         6                         86400s / 24 = 1h00    4.60e-12 rad
68          //         6                         86400s / 48 = 0h30    2.25e-12 rad
69          //         8                         86400s / 12 = 2h00    8.21e-12 rad
70          //         8                         86400s / 18 = 1h20    5.32e-12 rad
71          //         8                         86400s / 24 = 1h00    3.94e-12 rad
72          //         8                         86400s / 48 = 0h30    1.93e-12 rad
73          //        12                         86400s / 12 = 2h00    7.09e-12 rad
74          //        12                         86400s / 18 = 1h20    4.61e-12 rad
75          //        12                         86400s / 24 = 1h00    3.42e-12 rad
76          //        12                         86400s / 48 = 0h30    1.68e-12 rad
77          EOPHistory eopHistory = FramesFactory.getEOPHistory(IERSConventions.IERS_2010, false);
78          TransformProvider nonShitfing = new CIRFProvider(eopHistory);
79          final TransformProvider shifting =
80                  new ShiftingTransformProvider(nonShitfing,
81                                                CartesianDerivativesFilter.USE_PVA,
82                                                AngularDerivativesFilter.USE_R,
83                                                6, Constants.JULIAN_DAY / 24,
84                                                OrekitConfiguration.getCacheSlotsNumber(),
85                                                Constants.JULIAN_YEAR, 30 * Constants.JULIAN_DAY);
86  
87          // the following time range is located around the maximal observed error
88          AbsoluteDate start = new AbsoluteDate(2002, 9, 12, TimeScalesFactory.getTAI());
89          AbsoluteDate end   = new AbsoluteDate(2002, 9, 14, TimeScalesFactory.getTAI());
90          double maxError = 0.0;
91          for (AbsoluteDate date = start; date.compareTo(end) < 0; date = date.shiftedBy(60)) {
92              final Transform transform =
93                      new Transform(date,
94                                    shifting.getTransform(date),
95                                    nonShitfing.getTransform(date).getInverse());
96              final double error = transform.getRotation().getAngle();
97              maxError = FastMath.max(maxError, error);
98          }
99          Assertions.assertTrue(maxError < 4.6e-12);
100 
101     }
102 
103     @Test
104     public void testShiftingAccuracyWithoutEOP() {
105 
106         // max shift error observed on a 2 months period with 60 seconds step
107         // the shifting step after the interpolation step induces that only the
108         // step size has an influence on the error. The number of points used in
109         // the lower level interpolation does not affect the results. Plotting
110         // the error curves show exact superposition of all curves with the same
111         // time step. The error curves exhibit smooth periodic pattern with a
112         // main period corresponding to the Moon period
113         //
114         // number of sample points    time between sample points    max error
115         //         6                         86400s / 12 = 2h00    9.99e-13 rad
116         //         6                         86400s / 18 = 1h20    2.96e-13 rad
117         //         6                         86400s / 24 = 1h00    1.25e-13 rad
118         //         6                         86400s / 48 = 0h30    1.56e-14 rad
119         //         8                         86400s / 12 = 2h00    9.99e-13 rad
120         //         8                         86400s / 18 = 1h20    2.96e-13 rad
121         //         8                         86400s / 24 = 1h00    1.25e-13 rad
122         //         8                         86400s / 48 = 0h30    1.56e-14 rad
123         //        12                         86400s / 12 = 2h00    9.99e-13 rad
124         //        12                         86400s / 18 = 1h20    2.96e-13 rad
125         //        12                         86400s / 24 = 1h00    1.25e-13 rad
126         //        12                         86400s / 48 = 0h30    1.56e-14 rad
127         EOPHistory eopHistory = new EOPHistory(IERSConventions.IERS_2010, EOPHistory.DEFAULT_INTERPOLATION_DEGREE,
128                                                new ArrayList<EOPEntry>(), true);
129         TransformProvider nonShifting = new CIRFProvider(eopHistory);
130         final TransformProvider shifting =
131                 new ShiftingTransformProvider(nonShifting,
132                                               CartesianDerivativesFilter.USE_PVA,
133                                               AngularDerivativesFilter.USE_R,
134                                               6, Constants.JULIAN_DAY / 24,
135                                               OrekitConfiguration.getCacheSlotsNumber(),
136                                               Constants.JULIAN_YEAR, 30 * Constants.JULIAN_DAY);
137 
138         // the following time range is located around the maximal observed error
139         AbsoluteDate start = new AbsoluteDate(2002, 9, 7, TimeScalesFactory.getTAI());
140         AbsoluteDate end   = new AbsoluteDate(2002, 9, 8, TimeScalesFactory.getTAI());
141         double maxError = 0.0;
142         for (AbsoluteDate date = start; date.compareTo(end) < 0; date = date.shiftedBy(60)) {
143             final Transform transform =
144                     new Transform(date,
145                                   shifting.getTransform(date),
146                                   nonShifting.getTransform(date).getInverse());
147             final double error = transform.getRotation().getAngle();
148             maxError = FastMath.max(maxError, error);
149         }
150         Assertions.assertTrue(maxError < 1.3e-13);
151 
152     }
153 
154     @BeforeEach
155     public void setUp() {
156         Utils.setDataRoot("compressed-data");
157     }
158 
159 }