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.bodies;
18  
19  
20  import java.io.IOException;
21  
22  import org.hipparchus.geometry.euclidean.threed.Vector3D;
23  import org.junit.Assert;
24  import org.junit.Before;
25  import org.junit.Test;
26  import org.orekit.Utils;
27  import org.orekit.data.DataContext;
28  import org.orekit.frames.Frame;
29  import org.orekit.frames.FramesFactory;
30  import org.orekit.time.AbsoluteDate;
31  import org.orekit.time.TimeScalesFactory;
32  import org.orekit.utils.Constants;
33  import org.orekit.utils.PVCoordinates;
34  
35  public class JPLEphemeridesLoaderTest {
36  
37      @Test
38      public void testConstantsJPL() {
39          Utils.setDataRoot("regular-data/de405-ephemerides");
40  
41          JPLEphemeridesLoader loader =
42              new JPLEphemeridesLoader(JPLEphemeridesLoader.DEFAULT_DE_SUPPORTED_NAMES,
43                                       JPLEphemeridesLoader.EphemerisType.SUN);
44          Assert.assertEquals(149597870691.0, loader.getLoadedAstronomicalUnit(), 0.1);
45          Assert.assertEquals(81.30056, loader.getLoadedEarthMoonMassRatio(), 1.0e-8);
46          Assert.assertTrue(Double.isNaN(loader.getLoadedConstant("not-a-constant")));
47      }
48  
49      @Test
50      public void testConstantsInpop() {
51          Utils.setDataRoot("inpop");
52          JPLEphemeridesLoader loader =
53              new JPLEphemeridesLoader(JPLEphemeridesLoader.DEFAULT_INPOP_SUPPORTED_NAMES,
54                                       JPLEphemeridesLoader.EphemerisType.SUN);
55          Assert.assertEquals(149597870691.0, loader.getLoadedAstronomicalUnit(), 0.1);
56          Assert.assertEquals(81.30057, loader.getLoadedEarthMoonMassRatio(), 1.0e-8);
57      }
58  
59      @Test
60      public void testGMJPL() {
61          Utils.setDataRoot("regular-data/de405-ephemerides");
62  
63          JPLEphemeridesLoader loader =
64              new JPLEphemeridesLoader(JPLEphemeridesLoader.DEFAULT_DE_SUPPORTED_NAMES,
65                                       JPLEphemeridesLoader.EphemerisType.SUN);
66          Assert.assertEquals(22032.080e9,
67                              loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.MERCURY),
68                              1.0e6);
69          Assert.assertEquals(324858.599e9,
70                              loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.VENUS),
71                              1.0e6);
72          Assert.assertEquals(42828.314e9,
73                              loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.MARS),
74                              1.0e6);
75          Assert.assertEquals(126712767.863e9,
76                              loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.JUPITER),
77                              6.0e7);
78          Assert.assertEquals(37940626.063e9,
79                              loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.SATURN),
80                              2.0e6);
81          Assert.assertEquals(5794549.007e9,
82                              loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.URANUS),
83                              1.0e6);
84          Assert.assertEquals(6836534.064e9,
85                              loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.NEPTUNE),
86                              1.0e6);
87          Assert.assertEquals(981.601e9,
88                              loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.PLUTO),
89                              1.0e6);
90          Assert.assertEquals(132712440017.987e9,
91                              loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.SUN),
92                              1.0e6);
93          Assert.assertEquals(4902.801e9,
94                              loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.MOON),
95                              1.0e6);
96          Assert.assertEquals(403503.233e9,
97                              loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.EARTH_MOON),
98                              1.0e6);
99      }
100 
101     @Test
102     public void testGMInpop() {
103 
104         Utils.setDataRoot("inpop");
105 
106         JPLEphemeridesLoader loader =
107                 new JPLEphemeridesLoader("^inpop.*TCB.*littleendian.*\\.dat$",
108                                          JPLEphemeridesLoader.EphemerisType.SUN);
109         Assert.assertEquals(22032.081e9,
110                             loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.MERCURY),
111                             1.0e6);
112         Assert.assertEquals(324858.597e9,
113                             loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.VENUS),
114                             1.0e6);
115         Assert.assertEquals(42828.376e9,
116                             loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.MARS),
117                             1.0e6);
118         Assert.assertEquals(126712764.535e9,
119                             loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.JUPITER),
120                             6.0e7);
121         Assert.assertEquals(37940585.443e9,
122                             loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.SATURN),
123                             2.0e6);
124         Assert.assertEquals(5794549.099e9,
125                             loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.URANUS),
126                             1.0e6);
127         Assert.assertEquals(6836527.128e9,
128                             loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.NEPTUNE),
129                             1.0e6);
130         Assert.assertEquals(971.114e9,
131                             loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.PLUTO),
132                             1.0e6);
133         Assert.assertEquals(132712442110.032e9,
134                             loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.SUN),
135                             1.0e6);
136         Assert.assertEquals(4902.800e9,
137                             loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.MOON),
138                             1.0e6);
139         Assert.assertEquals(403503.250e9,
140                             loader.getLoadedGravitationalCoefficient(JPLEphemeridesLoader.EphemerisType.EARTH_MOON),
141                             1.0e6);
142     }
143 
144     @Test
145     public void testDerivative405() {
146         Utils.setDataRoot("regular-data/de405-ephemerides");
147         checkDerivative(JPLEphemeridesLoader.DEFAULT_DE_SUPPORTED_NAMES,
148                         new AbsoluteDate(1969, 6, 25, TimeScalesFactory.getTT()),
149                         691200.0);
150     }
151 
152     @Test
153     public void testDerivative406() {
154         Utils.setDataRoot("regular-data:regular-data/de406-ephemerides");
155         checkDerivative(JPLEphemeridesLoader.DEFAULT_DE_SUPPORTED_NAMES,
156                         new AbsoluteDate(2964, 9, 26, TimeScalesFactory.getTT()),
157                         1382400.0);
158     }
159 
160     @Test
161     public void testDummyEarth() {
162         Utils.setDataRoot("regular-data/de405-ephemerides");
163         JPLEphemeridesLoader loader =
164                 new JPLEphemeridesLoader(JPLEphemeridesLoader.DEFAULT_DE_SUPPORTED_NAMES,
165                                          JPLEphemeridesLoader.EphemerisType.EARTH);
166         CelestialBody body = loader.loadCelestialBody(CelestialBodyFactory.EARTH);
167         AbsoluteDate date = new AbsoluteDate(1950, 1, 12, TimeScalesFactory.getTT());
168         Frame eme2000 = FramesFactory.getEME2000();
169         for (double h = 0; h < 86400; h += 60.0) {
170             PVCoordinates pv = body.getPVCoordinates(date, eme2000);
171             Assert.assertEquals(0, pv.getPosition().getNorm(), 1.0e-15);
172             Assert.assertEquals(0, pv.getVelocity().getNorm(), 1.0e-15);
173         }
174     }
175 
176     @Test
177     public void testEndianness() {
178         Utils.setDataRoot("inpop");
179         JPLEphemeridesLoader.EphemerisType type = JPLEphemeridesLoader.EphemerisType.MARS;
180         JPLEphemeridesLoader loaderInpopTCBBig =
181                 new JPLEphemeridesLoader("^inpop.*_TCB_.*_bigendian\\.dat$", type);
182         CelestialBody bodysInpopTCBBig = loaderInpopTCBBig.loadCelestialBody(CelestialBodyFactory.MARS);
183         Assert.assertEquals(1.0, loaderInpopTCBBig.getLoadedConstant("TIMESC"), 1.0e-10);
184         JPLEphemeridesLoader loaderInpopTCBLittle =
185                 new JPLEphemeridesLoader("^inpop.*_TCB_.*_littleendian\\.dat$", type);
186         CelestialBody bodysInpopTCBLittle = loaderInpopTCBLittle.loadCelestialBody(CelestialBodyFactory.MARS);
187         Assert.assertEquals(1.0, loaderInpopTCBLittle.getLoadedConstant("TIMESC"), 1.0e-10);
188         AbsoluteDate t0 = new AbsoluteDate(1969, 7, 17, 10, 43, 23.4, TimeScalesFactory.getTT());
189         Frame eme2000   = FramesFactory.getEME2000();
190         for (double dt = 0; dt < 30 * Constants.JULIAN_DAY; dt += 3600) {
191             AbsoluteDate date        = t0.shiftedBy(dt);
192             Vector3D pInpopTCBBig    = bodysInpopTCBBig.getPVCoordinates(date, eme2000).getPosition();
193             Vector3D pInpopTCBLittle = bodysInpopTCBLittle.getPVCoordinates(date, eme2000).getPosition();
194             Assert.assertEquals(0.0, pInpopTCBBig.distance(pInpopTCBLittle), 1.0e-10);
195         }
196         for (String name : DataContext.getDefault().getDataProvidersManager().getLoadedDataNames()) {
197             Assert.assertTrue(name.contains("inpop"));
198         }
199     }
200 
201     @Test
202     public void testInpopvsJPL() {
203         Utils.setDataRoot("regular-data:inpop");
204         JPLEphemeridesLoader.EphemerisType type = JPLEphemeridesLoader.EphemerisType.MARS;
205         JPLEphemeridesLoader loaderDE405 =
206                 new JPLEphemeridesLoader("^unxp(\\d\\d\\d\\d)\\.405$", type);
207         CelestialBody bodysDE405 = loaderDE405.loadCelestialBody(CelestialBodyFactory.MARS);
208         JPLEphemeridesLoader loaderInpopTDBBig =
209                 new JPLEphemeridesLoader("^inpop.*_TDB_.*_bigendian\\.dat$", type);
210         CelestialBody bodysInpopTDBBig = loaderInpopTDBBig.loadCelestialBody(CelestialBodyFactory.MARS);
211         Assert.assertEquals(0.0, loaderInpopTDBBig.getLoadedConstant("TIMESC"), 1.0e-10);
212         JPLEphemeridesLoader loaderInpopTCBBig =
213                 new JPLEphemeridesLoader("^inpop.*_TCB_.*_bigendian\\.dat$", type);
214         CelestialBody bodysInpopTCBBig = loaderInpopTCBBig.loadCelestialBody(CelestialBodyFactory.MARS);
215         Assert.assertEquals(1.0, loaderInpopTCBBig.getLoadedConstant("TIMESC"), 1.0e-10);
216         AbsoluteDate t0 = new AbsoluteDate(1969, 7, 17, 10, 43, 23.4, TimeScalesFactory.getTT());
217         Frame eme2000   = FramesFactory.getEME2000();
218         for (double dt = 0; dt < 30 * Constants.JULIAN_DAY; dt += 3600) {
219             AbsoluteDate date = t0.shiftedBy(dt);
220             Vector3D pDE405          = bodysDE405.getPVCoordinates(date, eme2000).getPosition();
221             Vector3D pInpopTDBBig    = bodysInpopTDBBig.getPVCoordinates(date, eme2000).getPosition();
222             Vector3D pInpopTCBBig    = bodysInpopTCBBig.getPVCoordinates(date, eme2000).getPosition();
223             Assert.assertTrue(pDE405.distance(pInpopTDBBig) >  650.0);
224             Assert.assertTrue(pDE405.distance(pInpopTDBBig) < 1050.0);
225             Assert.assertTrue(pDE405.distance(pInpopTCBBig) > 1000.0);
226             Assert.assertTrue(pDE405.distance(pInpopTCBBig) < 2000.0);
227         }
228 
229     }
230 
231     @Test
232     public void testOverlappingEphemeridesData() throws IOException {
233         Utils.setDataRoot("overlapping-data/data.zip");
234 
235         // the data root contains two ephemerides files (JPL DE 405), which overlap in the period
236         // (1999-12-23T23:58:55.816, 2000-01-24T23:58:55.815)
237         // this test checks that the data in the overlapping and surrounding range is loaded correctly
238         // from both files (see issue #113).
239 
240         // as the bug only manifests if the DataLoader first loads the ephemerides file containing earlier
241         // data points, the data files are zipped to get a deterministic order when listing files
242 
243         CelestialBody moon = CelestialBodyFactory.getMoon();
244 
245         // 1999/12/31 0h00
246         final AbsoluteDate initDate = new AbsoluteDate(1999, 12, 31, 00, 00, 00, TimeScalesFactory.getUTC());
247         moon.getPVCoordinates(initDate, FramesFactory.getGCRF());
248 
249         // 2000/04/01 0h00
250         final AbsoluteDate otherDate = new AbsoluteDate(2000, 02, 01, 00, 00, 00, TimeScalesFactory.getUTC());
251         moon.getPVCoordinates(otherDate, FramesFactory.getGCRF());
252 
253         // 3 years from initDate
254         AbsoluteDate currentDate = new AbsoluteDate(1999, 12, 01, 00, 00, 00, TimeScalesFactory.getTAI());
255         AbsoluteDate finalDate = new AbsoluteDate(2000, 03, 14, 00, 00, 00, TimeScalesFactory.getTAI());
256 
257         while (currentDate.compareTo(finalDate) < 0)  {
258             currentDate = currentDate.shiftedBy(Constants.JULIAN_DAY);
259             moon.getPVCoordinates(currentDate, FramesFactory.getGCRF());
260         }
261 
262     }
263 
264     private void checkDerivative(String supportedNames, AbsoluteDate date, double maxChunkDuration)
265         {
266         JPLEphemeridesLoader loader =
267             new JPLEphemeridesLoader(supportedNames, JPLEphemeridesLoader.EphemerisType.MERCURY);
268         CelestialBody body = loader.loadCelestialBody(CelestialBodyFactory.MERCURY);
269         double h = 20;
270 
271         // eight points finite differences estimation of the velocity
272         Frame eme2000 = FramesFactory.getEME2000();
273         Vector3D pm4h = body.getPVCoordinates(date.shiftedBy(-4 * h), eme2000).getPosition();
274         Vector3D pm3h = body.getPVCoordinates(date.shiftedBy(-3 * h), eme2000).getPosition();
275         Vector3D pm2h = body.getPVCoordinates(date.shiftedBy(-2 * h), eme2000).getPosition();
276         Vector3D pm1h = body.getPVCoordinates(date.shiftedBy(    -h), eme2000).getPosition();
277         Vector3D pp1h = body.getPVCoordinates(date.shiftedBy(     h), eme2000).getPosition();
278         Vector3D pp2h = body.getPVCoordinates(date.shiftedBy( 2 * h), eme2000).getPosition();
279         Vector3D pp3h = body.getPVCoordinates(date.shiftedBy( 3 * h), eme2000).getPosition();
280         Vector3D pp4h = body.getPVCoordinates(date.shiftedBy( 4 * h), eme2000).getPosition();
281         Vector3D d4   = pp4h.subtract(pm4h);
282         Vector3D d3   = pp3h.subtract(pm3h);
283         Vector3D d2   = pp2h.subtract(pm2h);
284         Vector3D d1   = pp1h.subtract(pm1h);
285         double c = 1.0 / (840 * h);
286         Vector3D estimatedV = new Vector3D(-3 * c, d4, 32 * c, d3, -168 * c, d2, 672 * c, d1);
287 
288         Vector3D loadedV = body.getPVCoordinates(date, eme2000).getVelocity();
289         Assert.assertEquals(0, loadedV.subtract(estimatedV).getNorm(), 3.5e-10 * loadedV.getNorm());
290         Assert.assertEquals(maxChunkDuration, loader.getMaxChunksDuration(), 1.0e-10);
291     }
292 
293     @Before
294     public void setUp() {
295         Utils.setDataRoot("regular-data");
296     }
297 
298 }