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.propagation.analytical.gnss;
18  
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  import org.hipparchus.geometry.euclidean.threed.Vector3D;
23  import org.hipparchus.util.FastMath;
24  import org.hipparchus.util.Precision;
25  import org.junit.Assert;
26  import org.junit.BeforeClass;
27  import org.junit.Test;
28  import org.orekit.Utils;
29  import org.orekit.errors.OrekitException;
30  import org.orekit.errors.OrekitMessages;
31  import org.orekit.frames.Frame;
32  import org.orekit.frames.FramesFactory;
33  import org.orekit.propagation.analytical.gnss.data.GLONASSAlmanac;
34  import org.orekit.propagation.analytical.gnss.data.GLONASSOrbitalElements;
35  import org.orekit.propagation.analytical.gnss.data.GNSSConstants;
36  import org.orekit.time.AbsoluteDate;
37  import org.orekit.time.DateComponents;
38  import org.orekit.time.GLONASSDate;
39  import org.orekit.time.TimeComponents;
40  import org.orekit.time.TimeScalesFactory;
41  import org.orekit.utils.CartesianDerivativesFilter;
42  import org.orekit.utils.Constants;
43  import org.orekit.utils.IERSConventions;
44  import org.orekit.utils.PVCoordinates;
45  import org.orekit.utils.TimeStampedPVCoordinates;
46  
47  public class GLONASSAnalyticalPropagatorTest {
48  
49      private static GLONASSAlmanac almanac;
50  
51      @BeforeClass
52      public static void setUpBeforeClass() {
53          Utils.setDataRoot("gnss");
54          // Reference values for validation are given into Glonass Interface Control Document v1.0 2016
55          final double pi = GNSSConstants.GLONASS_PI;
56          almanac = new GLONASSAlmanac(0, 1, 22, 12, 2007, 33571.625,
57                                       -0.293967247009277 * pi,
58                                       -0.00012947082519531 * pi,
59                                       0.57867431640625 * pi,
60                                       0.000432968139648438,
61                                       0.01953124999975,
62                                       6.103515625e-5,
63                                       0.0, 0.0, 0.0);
64      }
65  
66      @Test
67      public void testPerfectValues() {
68          // Build the propagator
69          final GLONASSAnalyticalPropagator propagator = new GLONASSAnalyticalPropagatorBuilder(almanac).
70                          attitudeProvider(Utils.defaultLaw()).
71                          mass(1521.0).
72                          eci(FramesFactory.getEME2000()).
73                          ecef(FramesFactory.getITRF(IERSConventions.IERS_2010, false)).
74                          build();
75  
76          // Target
77          final AbsoluteDate target = new AbsoluteDate(new DateComponents(2007, 12, 23),
78                                                       new TimeComponents(51300),
79                                                       TimeScalesFactory.getGLONASS());
80  
81          Assert.assertEquals(0.0, almanac.getGlo2UTC(), Precision.SAFE_MIN);
82          Assert.assertEquals(0.0, almanac.getGloOffset(), Precision.SAFE_MIN);
83          Assert.assertEquals(0.0, almanac.getGPS2Glo(), Precision.SAFE_MIN);
84          Assert.assertEquals(1,   almanac.getHealth());
85          Assert.assertEquals(0,   almanac.getFrequencyChannel());
86  
87          // Compute PVCoordinates at the date in the ECEF
88          final PVCoordinates pvFinal    = propagator.propagateInEcef(target);
89  
90          // Reference values (see GLONASS ICD)
91          final PVCoordinates pvExpected = new PVCoordinates(new Vector3D(10697116.4874360654,
92                                                                          21058292.4241863210,
93                                                                          -9635679.33963303405),
94                                                             new Vector3D(-0686.100809921691084,
95                                                                          -1136.54864124521881,
96                                                                          -3249.98587740305799));
97  
98          // Check
99          Assert.assertEquals(1521.0, propagator.getMass(target), 0.1);
100         Assert.assertEquals(0.0, pvFinal.getPosition().distance(pvExpected.getPosition()), 1.1e-7);
101         Assert.assertEquals(0.0, pvFinal.getVelocity().distance(pvExpected.getVelocity()), 1.1e-5);
102 
103         // Get PVCoordinates at the date in the ECEF
104         final PVCoordinates pvFinal2 = propagator.getPVCoordinates(target, propagator.getECEF());
105         Assert.assertEquals(0., pvFinal.getPosition().distance(pvFinal2.getPosition()), 1.9e-8);
106     }
107 
108     @Test
109     public void testFrames() {
110         // Builds the GLONASSAnalyticalPropagator from the almanac
111         final GLONASSAnalyticalPropagator propagator = new GLONASSAnalyticalPropagatorBuilder(almanac).build();
112         Assert.assertEquals("EME2000", propagator.getFrame().getName());
113         Assert.assertEquals("EME2000", propagator.getECI().getName());
114         Assert.assertEquals(3.986004418e+14, GNSSConstants.GLONASS_MU, 1.0e6);
115         // Defines some date
116         final AbsoluteDate date = new AbsoluteDate(2016, 3, 3, 12, 0, 0., TimeScalesFactory.getUTC());
117         // Get PVCoordinates at the date in the ECEF
118         final PVCoordinates pv0 = propagator.propagateInEcef(date);
119         // Get PVCoordinates at the date in the ECEF
120         final PVCoordinates pv1 = propagator.getPVCoordinates(date, propagator.getECEF());
121 
122         // Checks
123         Assert.assertEquals(0., pv0.getPosition().distance(pv1.getPosition()), 2.6e-8);
124         Assert.assertEquals(0., pv0.getVelocity().distance(pv1.getVelocity()), 2.8e-12);
125     }
126 
127     @Test
128     public void testDerivativesConsistency() {
129 
130         final Frame eme2000 = FramesFactory.getEME2000();
131         double errorP = 0;
132         double errorV = 0;
133         double errorA = 0;
134         GLONASSAnalyticalPropagator propagator = new GLONASSAnalyticalPropagatorBuilder(almanac).build();
135         GLONASSOrbitalElements elements = propagator.getGLONASSOrbitalElements();
136         AbsoluteDate t0 = new GLONASSDate(elements.getNa(), elements.getN4(), elements.getTime()).getDate();
137         for (double dt = 0; dt < Constants.JULIAN_DAY; dt += 600) {
138             final AbsoluteDate central = t0.shiftedBy(dt);
139             final PVCoordinates pv = propagator.getPVCoordinates(central, eme2000);
140             final double h = 10.0;
141             List<TimeStampedPVCoordinates> sample = new ArrayList<TimeStampedPVCoordinates>();
142             for (int i = -3; i <= 3; ++i) {
143                 sample.add(propagator.getPVCoordinates(central.shiftedBy(i * h), eme2000));
144             }
145             final PVCoordinates interpolated =
146                             TimeStampedPVCoordinates.interpolate(central,
147                                                                  CartesianDerivativesFilter.USE_P,
148                                                                  sample);
149             errorP = FastMath.max(errorP, Vector3D.distance(pv.getPosition(), interpolated.getPosition()));
150             errorV = FastMath.max(errorV, Vector3D.distance(pv.getVelocity(), interpolated.getVelocity()));
151             errorA = FastMath.max(errorA, Vector3D.distance(pv.getAcceleration(), interpolated.getAcceleration()));
152         }
153         Assert.assertEquals(0.0, errorP, 1.9e-9);
154         Assert.assertEquals(0.0, errorV, 3.2e-3);
155         Assert.assertEquals(0.0, errorA, 7.0e-4);
156 
157     }
158 
159     @Test
160     public void testNoReset() {
161         try {
162             GLONASSAnalyticalPropagator propagator = new GLONASSAnalyticalPropagatorBuilder(almanac).build();
163             propagator.resetInitialState(propagator.getInitialState());
164             Assert.fail("an exception should have been thrown");
165         } catch (OrekitException oe) {
166             Assert.assertEquals(OrekitMessages.NON_RESETABLE_STATE, oe.getSpecifier());
167         }
168         try {
169             GLONASSAnalyticalPropagator propagator = new GLONASSAnalyticalPropagatorBuilder(almanac).build();
170             propagator.resetIntermediateState(propagator.getInitialState(), true);
171             Assert.fail("an exception should have been thrown");
172         } catch (OrekitException oe) {
173             Assert.assertEquals(OrekitMessages.NON_RESETABLE_STATE, oe.getSpecifier());
174         }
175     }
176 
177     @Test
178     public void testIssue544() {
179         // Builds the GLONASSAnalyticalPropagator from the almanac
180         final GLONASSAnalyticalPropagator propagator = new GLONASSAnalyticalPropagatorBuilder(almanac).build();
181         // In order to test the issue, we volontary set a Double.NaN value in the date.
182         final AbsoluteDate date0 = new AbsoluteDate(2010, 5, 7, 7, 50, Double.NaN, TimeScalesFactory.getUTC());
183         final PVCoordinates pv0 = propagator.propagateInEcef(date0);
184         // Verify that an infinite loop did not occur
185         Assert.assertEquals(Vector3D.NaN, pv0.getPosition());
186         Assert.assertEquals(Vector3D.NaN, pv0.getVelocity());
187         
188     }
189 
190 }