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