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.tle;
18  
19  
20  import org.hamcrest.MatcherAssert;
21  import org.hipparchus.geometry.euclidean.threed.Line;
22  import org.hipparchus.geometry.euclidean.threed.Rotation;
23  import org.hipparchus.geometry.euclidean.threed.Vector3D;
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.OrekitMatchers;
29  import org.orekit.Utils;
30  import org.orekit.attitudes.BodyCenterPointing;
31  import org.orekit.bodies.OneAxisEllipsoid;
32  import org.orekit.frames.Frame;
33  import org.orekit.frames.FramesFactory;
34  import org.orekit.frames.Transform;
35  import org.orekit.propagation.BoundedPropagator;
36  import org.orekit.propagation.EphemerisGenerator;
37  import org.orekit.propagation.Propagator;
38  import org.orekit.propagation.SpacecraftState;
39  import org.orekit.propagation.sampling.OrekitFixedStepHandler;
40  import org.orekit.time.AbsoluteDate;
41  import org.orekit.utils.Constants;
42  import org.orekit.utils.IERSConventions;
43  import org.orekit.utils.PVCoordinates;
44  
45  
46  public class TLEPropagatorTest {
47  
48      private TLE tle;
49      private double period;
50  
51      @Test
52      public void testsecondaryMode() {
53  
54          TLEPropagator propagator = TLEPropagator.selectExtrapolator(tle);
55          AbsoluteDate initDate = tle.getDate();
56          SpacecraftState initialState = propagator.getInitialState();
57  
58          // Simulate a full period of a GPS satellite
59          // -----------------------------------------
60          SpacecraftState finalState = propagator.propagate(initDate.shiftedBy(period));
61  
62          // Check results
63          Assert.assertEquals(initialState.getA(), finalState.getA(), 1e-1);
64          Assert.assertEquals(initialState.getEquinoctialEx(), finalState.getEquinoctialEx(), 1e-1);
65          Assert.assertEquals(initialState.getEquinoctialEy(), finalState.getEquinoctialEy(), 1e-1);
66          Assert.assertEquals(initialState.getHx(), finalState.getHx(), 1e-3);
67          Assert.assertEquals(initialState.getHy(), finalState.getHy(), 1e-3);
68          Assert.assertEquals(initialState.getLM(), finalState.getLM(), 1e-3);
69  
70      }
71  
72      @Test
73      public void testEphemerisMode() {
74  
75          TLEPropagator propagator = TLEPropagator.selectExtrapolator(tle);
76          final EphemerisGenerator generator = propagator.getEphemerisGenerator();
77  
78          AbsoluteDate initDate = tle.getDate();
79          SpacecraftState initialState = propagator.getInitialState();
80  
81          // Simulate a full period of a GPS satellite
82          // -----------------------------------------
83          AbsoluteDate endDate = initDate.shiftedBy(period);
84          propagator.propagate(endDate);
85  
86          // get the ephemeris
87          BoundedPropagator boundedProp = generator.getGeneratedEphemeris();
88  
89          // get the initial state from the ephemeris and check if it is the same as
90          // the initial state from the TLE
91          SpacecraftState boundedState = boundedProp.propagate(initDate);
92  
93          // Check results
94          Assert.assertEquals(initialState.getA(), boundedState.getA(), 0.);
95          Assert.assertEquals(initialState.getEquinoctialEx(), boundedState.getEquinoctialEx(), 0.);
96          Assert.assertEquals(initialState.getEquinoctialEy(), boundedState.getEquinoctialEy(), 0.);
97          Assert.assertEquals(initialState.getHx(), boundedState.getHx(), 0.);
98          Assert.assertEquals(initialState.getHy(), boundedState.getHy(), 0.);
99          Assert.assertEquals(initialState.getLM(), boundedState.getLM(), 1e-14);
100 
101         SpacecraftState finalState = boundedProp.propagate(endDate);
102 
103         // Check results
104         Assert.assertEquals(initialState.getA(), finalState.getA(), 1e-1);
105         Assert.assertEquals(initialState.getEquinoctialEx(), finalState.getEquinoctialEx(), 1e-1);
106         Assert.assertEquals(initialState.getEquinoctialEy(), finalState.getEquinoctialEy(), 1e-1);
107         Assert.assertEquals(initialState.getHx(), finalState.getHx(), 1e-3);
108         Assert.assertEquals(initialState.getHy(), finalState.getHy(), 1e-3);
109         Assert.assertEquals(initialState.getLM(), finalState.getLM(), 1e-3);
110 
111     }
112 
113     /** Test if body center belongs to the direction pointed by the satellite
114      */
115     @Test
116     public void testBodyCenterInPointingDirection() {
117 
118         final Frame itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
119         final OneAxisEllipsoid earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
120                                                             Constants.WGS84_EARTH_FLATTENING,
121                                                             itrf);
122         DistanceChecker checker = new DistanceChecker(itrf);
123 
124         // with Earth pointing attitude, distance should be small
125         TLEPropagator propagator =
126                 TLEPropagator.selectExtrapolator(tle,
127                                                  new BodyCenterPointing(FramesFactory.getTEME(), earth),
128                                                  Propagator.DEFAULT_MASS);
129         propagator.setStepHandler(900.0, checker);
130         propagator.propagate(tle.getDate().shiftedBy(period));
131         Assert.assertEquals(0.0, checker.getMaxDistance(), 2.0e-7);
132 
133         // with default attitude mode, distance should be large
134         propagator = TLEPropagator.selectExtrapolator(tle);
135         propagator.setStepHandler(900.0, checker);
136         propagator.propagate(tle.getDate().shiftedBy(period));
137         MatcherAssert.assertThat(checker.getMinDistance(),
138                 OrekitMatchers.greaterThan(1.5218e7));
139         Assert.assertEquals(2.6572e7, checker.getMaxDistance(), 1000.0);
140 
141     }
142 
143     private static class DistanceChecker implements OrekitFixedStepHandler {
144 
145         private final Frame itrf;
146         private double minDistance;
147         private double maxDistance;
148 
149         public DistanceChecker(Frame itrf) {
150             this.itrf = itrf;
151         }
152 
153         public double getMinDistance() {
154             return minDistance;
155         }
156 
157         public double getMaxDistance() {
158             return maxDistance;
159         }
160 
161         public void init(SpacecraftState s0, AbsoluteDate t, double step) {
162             minDistance = Double.POSITIVE_INFINITY;
163             maxDistance = Double.NEGATIVE_INFINITY;
164         }
165 
166         public void handleStep(SpacecraftState currentState) {
167             // Get satellite attitude rotation, i.e rotation from inertial frame to satellite frame
168             Rotation rotSat = currentState.getAttitude().getRotation();
169 
170             // Transform Z axis from satellite frame to inertial frame
171             Vector3D zSat = rotSat.applyInverseTo(Vector3D.PLUS_K);
172 
173             // Transform Z axis from inertial frame to ITRF
174             Transform transform = currentState.getFrame().getTransformTo(itrf, currentState.getDate());
175             Vector3D zSatITRF = transform.transformVector(zSat);
176 
177             // Transform satellite position/velocity from inertial frame to ITRF
178             PVCoordinates pvSatITRF = transform.transformPVCoordinates(currentState.getPVCoordinates());
179 
180             // Line containing satellite point and following pointing direction
181             Line pointingLine = new Line(pvSatITRF.getPosition(),
182                                          pvSatITRF.getPosition().add(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
183                                                                      zSatITRF),
184                                          1.0e-10);
185 
186             double distance = pointingLine.distance(Vector3D.ZERO);
187             minDistance = FastMath.min(minDistance, distance);
188             maxDistance = FastMath.max(maxDistance, distance);
189         }
190 
191     }
192 
193     @Before
194     public void setUp() {
195         Utils.setDataRoot("regular-data");
196 
197         // setup a TLE for a GPS satellite
198         String line1 = "1 37753U 11036A   12090.13205652 -.00000006  00000-0  00000+0 0  2272";
199         String line2 = "2 37753  55.0032 176.5796 0004733  13.2285 346.8266  2.00565440  5153";
200 
201         tle = new TLE(line1, line2);
202 
203         // the period of the GPS satellite
204         period = 717.97 * 60.0;
205     }
206 
207 }
208