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