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.Utils;
25  import org.orekit.time.AbsoluteDate;
26  import org.orekit.time.DateComponents;
27  import org.orekit.time.TimeComponents;
28  import org.orekit.time.TimeScalesFactory;
29  import org.orekit.utils.PVCoordinates;
30  
31  
32  public class EME2000ProviderTest {
33  
34      @Test
35      public void testAASReferenceLEO() {
36  
37          // this reference test has been extracted from the following paper:
38          // Implementation Issues Surrounding the New IAU Reference Systems for Astrodynamics
39          // David A. Vallado, John H. Seago, P. Kenneth Seidelmann
40          // http://www.centerforspace.com/downloads/files/pubs/AAS-06-134.pdf
41          AbsoluteDate t0 = new AbsoluteDate(new DateComponents(2004, 04, 06),
42                                             new TimeComponents(07, 51, 28.386009),
43                                             TimeScalesFactory.getUTC());
44  
45          Transform t = FramesFactory.getGCRF().getTransformTo(FramesFactory.getEME2000(), t0);
46  
47          PVCoordinates pvGcrfIau2000A =
48              new PVCoordinates(new Vector3D(5102508.9579, 6123011.4038, 6378136.9252),
49                                new Vector3D(-4743.220156, 790.536497, 5533.755728));
50          PVCoordinates pvEME2000EqA =
51              new PVCoordinates(new Vector3D(5102509.0383, 6123011.9758, 6378136.3118),
52                                new Vector3D(-4743.219766, 790.536344, 5533.756084));
53          checkPV(pvEME2000EqA, t.transformPVCoordinates(pvGcrfIau2000A), 1.1e-4, 2.6e-7);
54  
55          PVCoordinates pvGcrfIau2000B =
56              new PVCoordinates(new Vector3D(5102508.9579, 6123011.4012, 6378136.9277),
57                                new Vector3D(-4743.220156, 790.536495, 5533.755729));
58          PVCoordinates pvEME2000EqB =
59              new PVCoordinates(new Vector3D(5102509.0383, 6123011.9733, 6378136.3142),
60                                new Vector3D(-4743.219766, 790.536342, 5533.756085));
61          checkPV(pvEME2000EqB, t.transformPVCoordinates(pvGcrfIau2000B), 7.4e-5, 2.6e-7);
62  
63      }
64  
65      @Test
66      public void testAASReferenceGEO() {
67  
68          // this reference test has been extracted from the following paper:
69          // Implementation Issues Surrounding the New IAU Reference Systems for Astrodynamics
70          // David A. Vallado, John H. Seago, P. Kenneth Seidelmann
71          // http://www.centerforspace.com/downloads/files/pubs/AAS-06-134.pdf
72          AbsoluteDate t0 = new AbsoluteDate(new DateComponents(2004, 06, 01),
73                                             TimeComponents.H00,
74                                             TimeScalesFactory.getUTC());
75  
76          Transform t = FramesFactory.getGCRF().getTransformTo(FramesFactory.getEME2000(), t0);
77  
78          PVCoordinates pvGCRFiau2000A =
79              new PVCoordinates(new Vector3D(-40588150.3617, -11462167.0397, 27143.1974),
80                                new Vector3D(834.787458, -2958.305691, -1.172993));
81          PVCoordinates pvEME2000EqA =
82              new PVCoordinates(new Vector3D(-40588149.5482, -11462169.9118, 27146.8462),
83                                new Vector3D(834.787667, -2958.305632, -1.172963));
84          checkPV(pvEME2000EqA, t.transformPVCoordinates(pvGCRFiau2000A), 5.8e-5, 6.4e-7);
85  
86          PVCoordinates pvGCRFiau2000B =
87              new PVCoordinates(new Vector3D(-40588150.3617, -11462167.0397, 27143.2125),
88                                new Vector3D(834.787458, -2958.305691, -1.172999));
89          PVCoordinates pvEME2000EqB =
90              new PVCoordinates(new Vector3D(-40588149.5481, -11462169.9118, 27146.8613),
91                                new Vector3D(834.787667, -2958.305632, -1.172968));
92          checkPV(pvEME2000EqB, t.transformPVCoordinates(pvGCRFiau2000B), 1.1e-4, 5.5e-7);
93  
94      }
95  
96      @Test
97      public void testSofaBp00() {
98  
99          // the reference value has been computed using the March 2012 version of the SOFA library
100         // http://www.iausofa.org/2012_0301_C.html, with the following code
101         //
102         //        double utc1, utc2, tai1, tai2, tt1, tt2, rb[3][3], rp[3][3], rbp[3][3];
103         //
104         //        // 2004-02-14:00:00:00Z, MJD = 53049, UT1-UTC = -0.4093509
105         //        utc1  = DJM0 + 53049.0;
106         //        utc2  = 0.0;
107         //        iauUtctai(utc1, utc2, &tai1, &tai2);
108         //        iauTaitt(tai1, tai2, &tt1, &tt2);
109         //
110         //        iauBp00(tt1, tt2, rb, rp, rbp);
111         //
112         //        printf("iauBp00(%.20g, %.20g, rb, rp, rbp)\n"
113         //               "  rb  --> %.20g %.20g %.20g\n          %.20g %.20g %.20g\n          %.20g %.20g %.20g\n"
114         //               "  rp  --> %.20g %.20g %.20g\n          %.20g %.20g %.20g\n          %.20g %.20g %.20g\n"
115         //               "  rbp --> %.20g %.20g %.20g\n          %.20g %.20g %.20g\n          %.20g %.20g %.20g\n",
116         //               tt1, tt2,
117         //               rb[0][0],  rb[0][1],  rb[0][2],
118         //               rb[1][0],  rb[1][1],  rb[1][2],
119         //               rb[2][0],  rb[2][1],  rb[2][2],
120         //               rp[0][0],  rp[0][1],  rp[0][2],
121         //               rp[1][0],  rp[1][1],  rp[1][2],
122         //               rp[2][0],  rp[2][1],  rp[2][2],
123         //               rbp[0][0], rbp[0][1], rbp[0][2],
124         //               rbp[1][0], rbp[1][1], rbp[1][2],
125         //               rbp[2][0], rbp[2][1], rbp[2][2]);
126         //
127         // the output of this test reads:
128         //        iauBp00(2453049.5, 0.00074287037037037029902, rb, rp, rbp)
129         //        rb  --> 0.99999999999999422684 -7.0782797441991980175e-08 8.0562171469761337802e-08
130         //                7.0782794778573375197e-08 0.99999999999999689138 3.3060414542221364117e-08
131         //                -8.0562173809869716745e-08 -3.3060408839805516801e-08 0.99999999999999622524
132         //        rp  --> 0.99999949573309343531 -0.00092105778423522924759 -0.00040023257863225548568
133         //                0.00092105778625203805956 0.99999957582617116092 -1.7927962069881782439e-07
134         //                0.00040023257399096032498 -1.8935780260465051583e-07 0.99999991990692216337
135         //        rbp --> 0.99999949570013624278 -0.00092112855376512230675 -0.00040015204695196122638
136         //                0.00092112856903123034591 0.99999957576097886491 -1.4614501776464880046e-07
137         //                0.00040015201181019732432 -2.2244653837776004327e-07 0.99999991993915571253
138 
139         AbsoluteDate date = new AbsoluteDate(2004, 2, 14, TimeScalesFactory.getUTC());
140         Frame eme2000 = FramesFactory.getFrame(Predefined.EME2000);
141         Frame gcrf    = FramesFactory.getFrame(Predefined.GCRF);
142         checkRotation(new double[][] {
143             {  0.99999999999999422684,    -7.0782797441991980175e-08, 8.0562171469761337802e-08 },
144             {  7.0782794778573375197e-08,  0.99999999999999689138,    3.3060414542221364117e-08 },
145             { -8.0562173809869716745e-08, -3.3060408839805516801e-08, 0.99999999999999622524    }
146 
147         }, gcrf.getTransformTo(eme2000, date), 2.5e-16);
148 
149     }
150 
151     @BeforeEach
152     public void setUp() {
153         Utils.setDataRoot("compressed-data");
154     }
155 
156     private void checkPV(PVCoordinates reference,
157                          PVCoordinates result, double positionThreshold,
158                          double velocityThreshold) {
159 
160         Vector3D dP = result.getPosition().subtract(reference.getPosition());
161         Vector3D dV = result.getVelocity().subtract(reference.getVelocity());
162         Assertions.assertEquals(0, dP.getNorm(), positionThreshold);
163         Assertions.assertEquals(0, dV.getNorm(), velocityThreshold);
164     }
165 
166     private void checkRotation(double[][] reference, Transform t, double epsilon) {
167         double[][] mat = t.getRotation().getMatrix();
168         for (int i = 0; i < 3; ++i) {
169             for (int j = 0; j < 3; ++j) {
170                 Assertions.assertEquals(reference[i][j], mat[i][j], epsilon * FastMath.abs(reference[i][j]));
171 
172             }
173         }
174     }
175 
176 }