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.geometry.euclidean.threed.Vector3D;
20  import org.hipparchus.util.FastMath;
21  import org.junit.jupiter.api.Assertions;
22  import org.junit.jupiter.api.BeforeEach;
23  import org.junit.jupiter.api.Test;
24  import org.orekit.data.DirectoryCrawler;
25  import org.orekit.data.LazyLoadedDataContext;
26  import org.orekit.frames.ITRFVersionLoader.ITRFVersionConfiguration;
27  import org.orekit.time.AbsoluteDate;
28  import org.orekit.time.OffsetModel;
29  import org.orekit.time.TAIUTCDatFilesLoader.Parser;
30  import org.orekit.time.TimeScales;
31  import org.orekit.utils.Constants;
32  import org.orekit.utils.IERSConventions;
33  
34  import java.io.File;
35  import java.io.IOException;
36  import java.util.List;
37  import java.util.function.Supplier;
38  
39  /**
40   * Unit tests for methods implemented in {@link Frames}.
41   *
42   * @author Evan Ward
43   */
44  public class FramesTest {
45  
46      /** Time scales for testing. */
47      private TimeScales timeScales;
48  
49      /**
50       * Create {@link #timeScales}.
51       *
52       * @throws IOException on error.
53       */
54      @BeforeEach
55      public void setUp() throws IOException {
56          final String leapPath = "/USNO/tai-utc.dat";
57          final String eopPath = "/rapid-data-columns/finals2000A.daily";
58          final ITRFVersionConfiguration configuration = new ITRFVersionConfiguration(
59                  "", ITRFVersion.ITRF_2014, Integer.MIN_VALUE, Integer.MAX_VALUE);
60          final ItrfVersionProvider itrfVersionProvider = (name, mjd) -> configuration;
61          final List<OffsetModel> leapSeconds = new Parser().parse(
62                  this.getClass().getResourceAsStream(leapPath),
63                  leapPath);
64          this.timeScales = TimeScales.of(
65                  leapSeconds,
66                  (conventions, timeScales) -> {
67                      try {
68                          return EopHistoryLoader.Parser
69                                  .newFinalsColumnsParser(
70                                          conventions,
71                                          itrfVersionProvider,
72                                          timeScales,
73                                          true)
74                                  .parse(
75                                          this.getClass().getResourceAsStream(eopPath),
76                                          eopPath);
77                      } catch (IOException e) {
78                          throw new RuntimeException(e);
79                      }
80                  });
81      }
82  
83      /** Check {@link Frames#of(TimeScales, Supplier)}. */
84      @Test
85      public void testOf() {
86          // action
87          Frames frames = Frames.of(timeScales, () -> null);
88          Frame itrf = frames.getITRF(IERSConventions.IERS_2010, true);
89          EOPHistory eopHistory = ((ITRFProvider) itrf.getTransformProvider()).getEOPHistory();
90          Frame itrfEquinox = frames.getITRFEquinox(IERSConventions.IERS_2010, true);
91          Frame itrfFull = frames.getITRF(IERSConventions.IERS_2010, false);
92          EOPHistory eopFull = ((ITRFProvider) itrfFull.getTransformProvider()).getEOPHistory();
93  
94          // verify
95          Assertions.assertEquals(eopHistory.getConventions(), IERSConventions.IERS_2010);
96          Assertions.assertEquals(eopFull.getConventions(), IERSConventions.IERS_2010);
97          Assertions.assertEquals(eopHistory.getTimeScales(), timeScales);
98          Assertions.assertEquals(eopFull.getTimeScales(), timeScales);
99          // share EOP history when conventions and tidal corrections are the same
100         Assertions.assertSame(
101                 timeScales.getUT1(IERSConventions.IERS_2010, true).getEOPHistory(),
102                 eopHistory);
103         Assertions.assertSame(
104                 eopHistory,
105                 ((ITRFProvider) itrfEquinox.getTransformProvider()).getEOPHistory());
106         // changing tidal corrections still shares the same data, with derivatives added
107         Assertions.assertNotEquals(eopFull, eopHistory);
108         final int n = 181;
109         List<EOPEntry> entries = eopHistory.getEntries();
110         List<EOPEntry> entriesFull = eopFull.getEntries();
111         Assertions.assertEquals(n, entries.size());
112         Assertions.assertEquals(n, entriesFull.size());
113         for (int i = 0; i < n; i++) {
114             Assertions.assertEquals(entries.get(i).getMjd(),         entriesFull.get(i).getMjd());
115             Assertions.assertEquals(entries.get(i).getDate(),        entriesFull.get(i).getDate());
116             Assertions.assertEquals(entries.get(i).getUT1MinusUTC(), entriesFull.get(i).getUT1MinusUTC(), 1.0e-15);
117             Assertions.assertEquals(entries.get(i).getX(),           entriesFull.get(i).getX(),           1.0e-15);
118             Assertions.assertEquals(entries.get(i).getY(),           entriesFull.get(i).getY(),           1.0e-15);
119             Assertions.assertEquals(entries.get(i).getDdPsi(),       entriesFull.get(i).getDdPsi(),       1.0e-15);
120             Assertions.assertEquals(entries.get(i).getDdEps(),       entriesFull.get(i).getDdEps(),       1.0e-15);
121             Assertions.assertEquals(entries.get(i).getDx(),          entriesFull.get(i).getDx(),          1.0e-15);
122             Assertions.assertEquals(entries.get(i).getDy(),          entriesFull.get(i).getDy(),          1.0e-15);
123             Assertions.assertEquals(entries.get(i).getITRFType(),    entriesFull.get(i).getITRFType());
124         }
125         // ICRF
126         Assertions.assertEquals(null, frames.getICRF());
127     }
128 
129     /** Check transforms between frames from different data contexts. */
130     @Test
131     public void testComparison() {
132         // setup
133         Frames frames = Frames.of(timeScales, () -> null);
134         LazyLoadedDataContext dataContext = new LazyLoadedDataContext();
135         dataContext.getDataProvidersManager().addProvider(
136                 new DirectoryCrawler(new File("src/test/resources/regular-data")));
137         LazyLoadedFrames other = dataContext.getFrames();
138         AbsoluteDate date = new AbsoluteDate(2011, 5, 1, timeScales.getUTC());
139 
140         // verify
141         Assertions.assertSame(frames.getGCRF(), other.getGCRF());
142         Frame itrf = frames.getITRF(IERSConventions.IERS_2010, true);
143         Frame otherItrf = other.getITRF(IERSConventions.IERS_2010, true);
144         Transform transform = itrf.getTransformTo(otherItrf, date);
145         final double angle = transform.getRotation().getAngle();
146         // rough estimate based on EOP file
147         final double expected = new Vector3D(
148                 0.2449186 / Constants.JULIAN_DAY * 2 * FastMath.PI,
149                 0.341136 * Constants.ARC_SECONDS_TO_RADIANS,
150                 0.3e-3 * Constants.ARC_SECONDS_TO_RADIANS).getNorm();
151         Assertions.assertEquals(expected, angle, 1e-2 * expected);
152     }
153 
154 }