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