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  import org.hipparchus.Field;
20  import org.hipparchus.CalculusFieldElement;
21  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
22  import org.hipparchus.geometry.euclidean.threed.Vector3D;
23  import org.hipparchus.util.Decimal64Field;
24  import org.hipparchus.util.FastMath;
25  import org.junit.Assert;
26  import org.junit.Before;
27  import org.junit.Test;
28  import org.orekit.Utils;
29  import org.orekit.bodies.CelestialBody;
30  import org.orekit.bodies.CelestialBodyFactory;
31  import org.orekit.time.AbsoluteDate;
32  import org.orekit.time.FieldAbsoluteDate;
33  import org.orekit.time.TimeScalesFactory;
34  import org.orekit.utils.Constants;
35  import org.orekit.utils.FieldPVCoordinates;
36  import org.orekit.utils.PVCoordinates;
37  
38  /**Unit tests for {@link L1TransformProvider}.
39   *
40   * @author Luc Maisonobe
41   * @author Julio Hernanz
42   */
43  public class L1TransformProviderTest {
44  
45      @Test
46      public void testTransformationOrientationForEarthMoon() {
47  
48          // Load Bodies
49          final CelestialBody earth = CelestialBodyFactory.getEarth();
50          final CelestialBody moon = CelestialBodyFactory.getMoon();
51  
52          // Set framesd
53          final Frame eme2000 = FramesFactory.getEME2000();
54          final Frame l1Frame = new L1Frame(earth, moon);
55  
56          // Time settings
57          final AbsoluteDate date = new AbsoluteDate(2000, 01, 01, 0, 0, 00.000,
58                                                     TimeScalesFactory.getUTC());
59  
60          // Compute Moon position in EME2000
61          PVCoordinates pvMoon = moon.getPVCoordinates(date, eme2000);
62          Vector3D posMoon = pvMoon.getPosition();
63  
64          // Compute L1 position in EME2000
65          // (it is important to use transformPosition(Vector3D.ZERO) and *not* getTranslation()
66          // because the test should avoid doing wrong interpretation of the meaning and
67          // particularly on the sign of the translation)
68          Vector3D posL1   = l1Frame.getTransformTo(eme2000,date).transformPosition(Vector3D.ZERO);
69  
70          // check L1 and Moon are aligned as seen from Earth
71          Assert.assertEquals(0.0, Vector3D.angle(posMoon, posL1), 1.0e-10);
72  
73          // check the Moon is at least 40 000km farther than L1
74          Assert.assertTrue(posMoon.getNorm() > posL1.getNorm() + 4.0e7);
75  
76      }
77  
78      @Test
79      public void testFieldTransformationOrientationForEarthMoon() {
80          doTestFieldTransformationOrientationForEarthMoon(Decimal64Field.getInstance());
81      }
82  
83      private <T extends CalculusFieldElement<T>> void doTestFieldTransformationOrientationForEarthMoon(final Field<T> field) {
84  
85          // Load Bodies
86          final CelestialBody earth = CelestialBodyFactory.getEarth();
87          final CelestialBody moon = CelestialBodyFactory.getMoon();
88  
89          // Set framesd
90          final Frame eme2000 = FramesFactory.getEME2000();
91          final Frame l1Frame = new L1Frame(earth, moon);
92  
93          // Time settings
94          final FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, 2000, 01, 01, 0, 0, 00.000,
95                                                                    TimeScalesFactory.getUTC());
96  
97          // Compute Moon position in EME2000
98          FieldPVCoordinates<T> pvMoon = moon.getPVCoordinates(date, eme2000);
99          FieldVector3D<T> posMoon = pvMoon.getPosition();
100 
101         // Compute L2 position in EME2000
102         // (it is important to use transformPosition(Vector3D.ZERO) and *not* getTranslation()
103         // because the test should avoid doing wrong interpretation of the meaning and
104         // particularly on the sign of the translation)
105         FieldVector3D<T> posL1   = l1Frame.getTransformTo(eme2000,date).transformPosition(Vector3D.ZERO);
106 
107         // check L2 and Moon are aligned as seen from Earth
108         Assert.assertEquals(0.0, FieldVector3D.angle(posMoon, posL1).getReal(), 1.0e-10);
109 
110         // check L2 if at least 40 000km farther than Moon
111         Assert.assertTrue(posMoon.getNorm().getReal() > posL1.getNorm().getReal() + 4.0e7);
112 
113     }
114 
115 
116     @Test
117     public void testSunEarth() {
118 
119         // Load Bodies
120         final CelestialBody sun = CelestialBodyFactory.getSun();
121         final CelestialBody earth = CelestialBodyFactory.getEarth();
122 
123         // Set frames
124         final Frame sunFrame = sun.getInertiallyOrientedFrame();
125         final Frame l1Frame = new L1Frame(sun, earth);
126 
127         // Time settings
128         final AbsoluteDate date = new AbsoluteDate(2000, 01, 01, 0, 0, 00.000,
129                                                    TimeScalesFactory.getUTC());
130 
131         // Compute Earth position in Sun centered frame
132         PVCoordinates pvEarth = earth.getPVCoordinates(date, sunFrame);
133         Vector3D posEarth = pvEarth.getPosition();
134 
135         // Compute L1 position in Sun centered frame
136         // (it is important to use transformPosition(Vector3D.ZERO) and *not* getTranslation()
137         // because the test should avoid doing wrong interpretation of the meaning and
138         // particularly on the sign of the translation)
139         Vector3D posL1   = l1Frame.getTransformTo(sunFrame,date).transformPosition(Vector3D.ZERO);
140 
141         // check L1 and Earth are aligned as seen from Sun
142         Assert.assertEquals(0.0, Vector3D.angle(posEarth, posL1), 1.0e-10);
143 
144         // check if Earth is at least 1 000 000km farther than L1
145         Assert.assertTrue(posEarth.getNorm() > posL1.getNorm() + 1.0e9);
146     }
147 
148     @Test
149     public void testFieldSunEarth() {
150         doTestFieldSunEarth(Decimal64Field.getInstance());
151     }
152 
153     private <T extends CalculusFieldElement<T>> void doTestFieldSunEarth(final Field<T> field) {
154 
155         // Load Bodies
156         final CelestialBody sun = CelestialBodyFactory.getSun();
157         final CelestialBody earth = CelestialBodyFactory.getEarth();
158 
159         // Set frames
160         final Frame sunFrame = sun.getInertiallyOrientedFrame();
161         final Frame l1Frame = new L1Frame(sun, earth);
162 
163         // Time settings
164         final FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, 2000, 01, 01, 0, 0, 00.000,
165                                                    TimeScalesFactory.getUTC());
166 
167         // Compute Earth position in Sun centered frame
168         FieldPVCoordinates<T> pvEarth = earth.getPVCoordinates(date, sunFrame);
169         FieldVector3D<T> posEarth = pvEarth.getPosition();
170 
171         // Compute L2 position in Sun centered frame
172         // (it is important to use transformPosition(Vector3D.ZERO) and *not* getTranslation()
173         // because the test should avoid doing wrong interpretation of the meaning and
174         // particularly on the sign of the translation)
175         FieldVector3D<T> posL1   = l1Frame.getTransformTo(sunFrame,date).transformPosition(Vector3D.ZERO);
176 
177         // check L2 and Earth are aligned as seen from Sun
178         Assert.assertEquals(0.0, FieldVector3D.angle(posEarth, posL1).getReal(), 1.0e-10);
179 
180         // check L2 if at least 1 000 000km farther than Earth
181         Assert.assertTrue(posEarth.getNorm().getReal() > posL1.getNorm().getReal() + 1.0e9);
182     }
183 
184     @Test
185     public void testSunJupiter() {
186 
187         // Load Bodies
188         final CelestialBody sun = CelestialBodyFactory.getSun();
189         final CelestialBody jupiter = CelestialBodyFactory.getJupiter();
190 
191         // Set frames
192         final Frame sunFrame = sun.getInertiallyOrientedFrame();
193         final Frame l1Frame = new L1Frame(sun, jupiter);
194 
195         // Time settings
196         final AbsoluteDate date = new AbsoluteDate(2000, 01, 01, 0, 0, 00.000,
197                                                    TimeScalesFactory.getUTC());
198 
199         // Compute Jupiter position in Sun centered frame
200         PVCoordinates pvJupiter = jupiter.getPVCoordinates(date, sunFrame);
201         Vector3D posJupiter = pvJupiter.getPosition();
202 
203         // Compute L1 position in Sun centered frame
204         // (it is important to use transformPosition(Vector3D.ZERO) and *not* getTranslation()
205         // because the test should avoid doing wrong interpretation of the meaning and
206         // particularly on the sign of the translation)
207         Vector3D posL1   = l1Frame.getTransformTo(sunFrame,date).transformPosition(Vector3D.ZERO);
208 
209         // check L1 and Jupiter are aligned as seen from Sun
210         Assert.assertEquals(0.0, Vector3D.angle(posJupiter, posL1), 1.0e-10);
211 
212         // check if Jupiter is at least 45 000 000km farther than L1
213         Assert.assertTrue(posJupiter.getNorm() > posL1.getNorm() + 4.5e10);
214     }
215 
216     @Test
217     public void testFieldSunJupiter() {
218         doTestFieldSunJupiter(Decimal64Field.getInstance());
219     }
220 
221     private <T extends CalculusFieldElement<T>> void doTestFieldSunJupiter(final Field<T> field) {
222 
223         // Load Bodies
224         final CelestialBody sun = CelestialBodyFactory.getSun();
225         final CelestialBody jupiter = CelestialBodyFactory.getJupiter();
226 
227         // Set frames
228         final Frame sunFrame = sun.getInertiallyOrientedFrame();
229         final Frame l1Frame = new L1Frame(sun, jupiter);
230 
231         // Time settings
232         final FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, 2000, 01, 01, 0, 0, 00.000,
233                                                                   TimeScalesFactory.getUTC());
234 
235         // Compute Jupiter position in Sun centered frame
236         FieldPVCoordinates<T> pvJupiter = jupiter.getPVCoordinates(date, sunFrame);
237         FieldVector3D<T> posJupiter = pvJupiter.getPosition();
238 
239         // Compute L2 position in Sun centered frame
240         // (it is important to use transformPosition(Vector3D.ZERO) and *not* getTranslation()
241         // because the test should avoid doing wrong interpretation of the meaning and
242         // particularly on the sign of the translation)
243         FieldVector3D<T> posL1   = l1Frame.getTransformTo(sunFrame,date).transformPosition(Vector3D.ZERO);
244 
245         // check L2 and Jupiter are aligned as seen from Sun
246         Assert.assertEquals(0.0, FieldVector3D.angle(posJupiter, posL1).getReal(), 1.0e-10);
247 
248         // check L2 if at least 50 000 000km farther than Jupiter
249         Assert.assertTrue(posJupiter.getNorm().getReal() > posL1.getNorm().getReal() + 4.5e10);
250     }
251 
252     @Test
253     public void testL1Orientation() {
254 
255         final AbsoluteDate date0 = new AbsoluteDate(2000, 01, 1, 11, 58, 20.000,
256                                                    TimeScalesFactory.getUTC());
257         final CelestialBody sun     = CelestialBodyFactory.getSun();
258         final CelestialBody earth   = CelestialBodyFactory.getEarth();
259         final Frame         l1Frame = new L1Frame(sun, earth);
260         for (double dt = -Constants.JULIAN_DAY; dt <= Constants.JULIAN_DAY; dt += 3600.0) {
261             final AbsoluteDate date              = date0.shiftedBy(dt);
262             final Vector3D     sunPositionInL1   = sun.getPVCoordinates(date, l1Frame).getPosition();
263             final Vector3D     earthPositionInL1 = earth.getPVCoordinates(date, l1Frame).getPosition();
264             Assert.assertEquals(0.0, Vector3D.angle(sunPositionInL1,   Vector3D.MINUS_I), 3.0e-14);
265             Assert.assertEquals(FastMath.PI, Vector3D.angle(earthPositionInL1, Vector3D.MINUS_I), 3.0e-14);
266         }
267     }
268 
269     @Test
270     public void testFieldL1Orientation() {
271         doTestFieldL1Orientation(Decimal64Field.getInstance());
272     }
273 
274     private <T extends CalculusFieldElement<T>> void doTestFieldL1Orientation(final Field<T> field) {
275 
276         final FieldAbsoluteDate<T> date0 = new FieldAbsoluteDate<>(field, 2000, 01, 1, 11, 58, 20.000,
277                                                                    TimeScalesFactory.getUTC());
278         final CelestialBody sun     = CelestialBodyFactory.getSun();
279         final CelestialBody earth   = CelestialBodyFactory.getEarth();
280         final Frame         l1Frame = new L1Frame(sun, earth);
281         for (double dt = -Constants.JULIAN_DAY; dt <= Constants.JULIAN_DAY; dt += 3600.0) {
282             final FieldAbsoluteDate<T> date              = date0.shiftedBy(dt);
283             final FieldVector3D<T>     sunPositionInL1   = sun.getPVCoordinates(date, l1Frame).getPosition();
284             final FieldVector3D<T>     earthPositionInL1 = earth.getPVCoordinates(date, l1Frame).getPosition();
285             Assert.assertEquals(0.0, FieldVector3D.angle(sunPositionInL1,   Vector3D.MINUS_I).getReal(), 3.0e-14);
286             Assert.assertEquals(FastMath.PI, FieldVector3D.angle(earthPositionInL1, Vector3D.MINUS_I).getReal(), 3.0e-14);
287         }
288     }
289 
290     @Before
291     public void setUp() {
292         Utils.setDataRoot("regular-data");
293     }
294 
295 }