1   /* Contributed in the public domain.
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 java.io.ByteArrayInputStream;
20  import java.io.ByteArrayOutputStream;
21  import java.io.IOException;
22  import java.io.ObjectInputStream;
23  import java.io.ObjectOutputStream;
24  
25  import org.hamcrest.MatcherAssert;
26  import org.hamcrest.core.IsInstanceOf;
27  import org.hipparchus.geometry.euclidean.threed.Vector3D;
28  import org.junit.Assert;
29  import org.junit.BeforeClass;
30  import org.junit.Test;
31  import org.orekit.Utils;
32  import org.orekit.bodies.CelestialBody;
33  import org.orekit.bodies.CelestialBodyFactory;
34  import org.orekit.time.AbsoluteDate;
35  import org.orekit.time.TimeScale;
36  import org.orekit.time.TimeScalesFactory;
37  import org.orekit.utils.Constants;
38  import org.orekit.utils.IERSConventions;
39  
40  /** Unit tests for {@link EclipticProvider}. */
41  public class EclipticProviderTest {
42  
43      /** Set the orekit data to include ephemerides. */
44      @BeforeClass
45      public static void setUpBefore() {
46          Utils.setDataRoot("regular-data");
47      }
48  
49      /**
50       * Check the Ecliptic frame defined from IERS mean obliquity equations against the
51       * position of Sun and Earth from the JPL 406 ephemerides.
52       *
53       * @throws Exception on error
54       */
55      @Test
56      public void testAgreementWith406Ephemerides() throws Exception {
57          TimeScale utc = TimeScalesFactory.getUTC();
58  
59          //time spans we have test data sets for.
60          checkAlignment(new AbsoluteDate(1969, 5, 27, utc), new AbsoluteDate(1969, 9, 20, utc));
61          checkAlignment(new AbsoluteDate(1969, 12, 5, utc), new AbsoluteDate(1970, 4, 1, utc));
62          checkAlignment(new AbsoluteDate(1970, 6, 15, utc), new AbsoluteDate(1970, 8, 1, utc));
63          checkAlignment(new AbsoluteDate(2002, 12, 16, utc), new AbsoluteDate(2004, 2, 3, utc));
64  
65          checkAlignment(new AbsoluteDate(1999, 11, 22, utc), new AbsoluteDate(2000, 5, 21, utc));
66      }
67  
68      /**
69       * Check alignment of ecliptic +z with Earth-Moon barycenter angular momentum. Angular
70       * difference will be checked every month.
71       *
72       * @param start start date of check.
73       * @param end   en date of check.
74       */
75      private void checkAlignment(AbsoluteDate start, AbsoluteDate end) {
76          //setup
77          CelestialBody sun = CelestialBodyFactory.getSun();
78          CelestialBody emb = CelestialBodyFactory.getEarthMoonBarycenter();
79          Frame heliocentric = sun.getInertiallyOrientedFrame();
80          //subject under test
81          Frame ecliptic = FramesFactory.getEcliptic(IERSConventions.IERS_2010);
82  
83          //verify
84          //precise definition is +z is parallel to Earth-Moon barycenter's angular momentum
85          //over date range of ephemeris, a season at a time
86          double preciseTol = 0.50 * Constants.ARC_SECONDS_TO_RADIANS;
87          for (AbsoluteDate date = start;
88               date.compareTo(end) < 0;
89               date = date.shiftedBy(Constants.JULIAN_YEAR / 12.0)) {
90  
91              Transform heliocentricToEcliptic = heliocentric.getTransformTo(ecliptic, date);
92              Vector3D momentum = emb.getPVCoordinates(date, heliocentric).getMomentum();
93              Vector3D actual = heliocentricToEcliptic.transformVector(momentum);
94              double angle = Vector3D.angle(
95                      Vector3D.PLUS_K,
96                      actual
97              );
98              Assert.assertEquals("Agrees with ephemerides to within " + preciseTol, 0, angle, preciseTol);
99  
100         }
101 
102     }
103 
104     /**
105      * Check frame has the right name.
106      */
107     @Test
108     public void testGetName() {
109         Assert.assertEquals("Ecliptic/1996",
110                             FramesFactory.getEcliptic(IERSConventions.IERS_1996).getName());
111         Assert.assertEquals("Ecliptic/2003",
112                             FramesFactory.getEcliptic(IERSConventions.IERS_2003).getName());
113         Assert.assertEquals("Ecliptic/2010",
114                             FramesFactory.getEcliptic(IERSConventions.IERS_2010).getName());
115     }
116 
117     /**
118      * Check the parent frame is MOD.
119      */
120     @Test
121     public void testGetParent() {
122         //setup
123         Frame frame = FramesFactory.getEcliptic(IERSConventions.IERS_2003);
124 
125         //action + verify
126         MatcherAssert.assertThat(frame.getParent().getTransformProvider(),
127                           IsInstanceOf.instanceOf(MODProvider.class));
128     }
129 
130     @Test
131     public void testSerialization() throws IOException, ClassNotFoundException {
132         TransformProvider provider = new EclipticProvider(IERSConventions.IERS_2010);
133 
134         ByteArrayOutputStream bos = new ByteArrayOutputStream();
135         ObjectOutputStream    oos = new ObjectOutputStream(bos);
136         oos.writeObject(provider);
137 
138         Assert.assertTrue(bos.size() > 200);
139         Assert.assertTrue(bos.size() < 250);
140 
141         ByteArrayInputStream  bis = new ByteArrayInputStream(bos.toByteArray());
142         ObjectInputStream     ois = new ObjectInputStream(bis);
143         TransformProvider deserialized  = (TransformProvider) ois.readObject();
144         for (double dt = 0; dt < Constants.JULIAN_DAY; dt += 3600) {
145             AbsoluteDate date = AbsoluteDate.J2000_EPOCH.shiftedBy(dt);
146             Transform expectedIdentity = new Transform(date,
147                                                        provider.getTransform(date).getInverse(),
148                                                        deserialized.getTransform(date));
149             Assert.assertEquals(0.0, expectedIdentity.getTranslation().getNorm(), 1.0e-15);
150             Assert.assertEquals(0.0, expectedIdentity.getRotation().getAngle(),   1.0e-15);
151         }
152 
153     }
154 
155 }