1   /* Copyright 2002-2025 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  import java.io.BufferedReader;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.InputStreamReader;
23  import java.text.ParseException;
24  
25  import org.hipparchus.geometry.euclidean.threed.Vector3D;
26  import org.hipparchus.util.CombinatoricsUtils;
27  import org.hipparchus.util.FastMath;
28  import org.junit.jupiter.api.Assertions;
29  import org.junit.jupiter.api.BeforeEach;
30  import org.junit.jupiter.api.Test;
31  import org.orekit.Utils;
32  import org.orekit.errors.OrekitException;
33  import org.orekit.errors.OrekitMessages;
34  import org.orekit.propagation.SpacecraftState;
35  import org.orekit.propagation.conversion.osc2mean.FixedPointConverter;
36  import org.orekit.propagation.conversion.osc2mean.OsculatingToMeanConverter;
37  import org.orekit.time.AbsoluteDate;
38  import org.orekit.time.DateComponents;
39  import org.orekit.time.TimeComponents;
40  import org.orekit.time.TimeScalesFactory;
41  import org.orekit.utils.Constants;
42  import org.orekit.utils.PVCoordinates;
43  
44  
45  public class TLETest {
46  
47      @Test
48      public void testTLEFormat() {
49  
50          String line1 = "1 27421U 02021A   02124.48976499 -.00021470  00000-0 -89879-2 0    20";
51          String line2 = "2 27421  98.7490 199.5121 0001333 133.9522 226.1918 14.26113993    62";
52  
53          Assertions.assertTrue(TLE.isFormatOK(line1, line2));
54  
55          TLE tle = new TLE(line1, line2);
56          Assertions.assertEquals(27421, tle.getSatelliteNumber(), 0);
57          Assertions.assertEquals(2002, tle.getLaunchYear());
58          Assertions.assertEquals(21, tle.getLaunchNumber());
59          Assertions.assertEquals("A", tle.getLaunchPiece());
60          Assertions.assertEquals(-0.0089879, tle.getBStar(), 0);
61          Assertions.assertEquals(0, tle.getEphemerisType());
62          Assertions.assertEquals(98.749, FastMath.toDegrees(tle.getI()), 1e-10);
63          Assertions.assertEquals(199.5121, FastMath.toDegrees(tle.getRaan()), 1e-10);
64          Assertions.assertEquals(0.0001333, tle.getE(), 1e-10);
65          Assertions.assertEquals(133.9522, FastMath.toDegrees(tle.getPerigeeArgument()), 1e-10);
66          Assertions.assertEquals(226.1918, FastMath.toDegrees(tle.getMeanAnomaly()), 1e-10);
67          Assertions.assertEquals(14.26113993, tle.getMeanMotion() * Constants.JULIAN_DAY / (2 * FastMath.PI), 0);
68          Assertions.assertEquals(7182888.814633288, tle.computeSemiMajorAxis(), 1e-10);
69          Assertions.assertEquals(tle.getRevolutionNumberAtEpoch(), 6, 0);
70          Assertions.assertEquals(tle.getElementNumber(), 2 , 0);
71  
72          line1 = "1 T7421U 02021A   02124.48976499 -.00021470  00000-0 -89879-2 0    28";
73          line2 = "2 T7421  98.7490 199.5121 0001333 133.9522 226.1918 14.26113993    60";
74          Assertions.assertTrue(TLE.isFormatOK(line1, line2));
75  
76          tle = new TLE(line1, line2);
77          Assertions.assertEquals(277421, tle.getSatelliteNumber(), 0);
78  
79          line1 = "1 I7421U 02021A   02124.48976499 -.00021470  00000-0 -89879-2 0    28";
80          line2 = "2 I7421  98.7490 199.5121 0001333 133.9522 226.1918 14.26113993    60";
81          Assertions.assertFalse(TLE.isFormatOK(line1, line2));
82          try {
83              new TLE(line1, line2);
84              Assertions.fail("an exception should have been thrown");
85          } catch (NumberFormatException nfe) {
86              // expected
87          }
88  
89          line1 = "1 27421U 02021A   02124.48976499 -.00021470  00000-0 -89879-2 0    20";
90          line2 = "2 27421  98.7490 199.5121 0001333 133.9522 226.1918 14*26113993    62";
91          Assertions.assertFalse(TLE.isFormatOK(line1, line2));
92  
93          line1 = "1 27421 02021A   02124.48976499 -.00021470  00000-0 -89879-2 0    20";
94          line2 = "2 27421  98.7490 199.5121 0001333 133.9522 226.1918 14.26113993    62";
95          Assertions.assertFalse(TLE.isFormatOK(line1, line2));
96  
97          line1 = "1 27421U 02021A   02124.48976499 -.00021470  00000-0 -89879-2 0    20";
98          line2 = "2 27421  98.7490 199.5121 0001333 133.9522 226.1918 10006113993    62";
99          Assertions.assertFalse(TLE.isFormatOK(line1, line2));
100 
101         line1 = "1 27421U 02021A   02124.48976499 -.00021470  00000-0 -89879 2 0    20";
102         line2 = "2 27421  98.7490 199.5121 0001333 133.9522 226.1918 14.26113993    62";
103         Assertions.assertFalse(TLE.isFormatOK(line1, line2));
104     }
105 
106     @Test
107     public void testIssue196() {
108 
109         String line1A = "1 27421U 02021A   02124.48976499 -.00021470  00000-0 -89879-2 0    20";
110         String line1B = "1 27421U 02021A   02124.48976499  -.0002147  00000-0 -89879-2 0    20";
111         String line2 = "2 27421  98.7490 199.5121 0001333 133.9522 226.1918 14.26113993    62";
112 
113         Assertions.assertTrue(TLE.isFormatOK(line1A, line2));
114         TLE tleA = new TLE(line1A, line2);
115         Assertions.assertTrue(TLE.isFormatOK(line1B, line2));
116         TLE tleB = new TLE(line1B, line2);
117         Assertions.assertEquals(tleA.getSatelliteNumber(),         tleB.getSatelliteNumber(), 0);
118         Assertions.assertEquals(tleA.getLaunchYear(),              tleB.getLaunchYear());
119         Assertions.assertEquals(tleA.getLaunchNumber(),            tleB.getLaunchNumber());
120         Assertions.assertEquals(tleA.getLaunchPiece(),             tleB.getLaunchPiece());
121         Assertions.assertEquals(tleA.getBStar(),                   tleB.getBStar(), 0);
122         Assertions.assertEquals(tleA.getEphemerisType(),           tleB.getEphemerisType());
123         Assertions.assertEquals(tleA.getI(),                       tleB.getI(), 1e-10);
124         Assertions.assertEquals(tleA.getRaan(),                    tleB.getRaan(), 1e-10);
125         Assertions.assertEquals(tleA.getE(),                       tleB.getE(), 1e-10);
126         Assertions.assertEquals(tleA.getPerigeeArgument(),         tleB.getPerigeeArgument(), 1e-10);
127         Assertions.assertEquals(tleA.getMeanAnomaly(),             tleB.getMeanAnomaly(), 1e-10);
128         Assertions.assertEquals(tleA.getMeanMotion(),              tleB.getMeanMotion(), 0);
129         Assertions.assertEquals(tleA.getRevolutionNumberAtEpoch(), tleB.getRevolutionNumberAtEpoch(), 0);
130         Assertions.assertEquals(tleA.getElementNumber(),           tleB.getElementNumber(), 0);
131 
132     }
133 
134     @Test
135     public void testSymmetry() {
136         checkSymmetry("1 27421U 02021A   02124.48976499 -.00021470  00000-0 -89879-2 0    20",
137                       "2 27421  98.7490 199.5121 0001333 133.9522 226.1918 14.26113993    62");
138         checkSymmetry("1 31928U 98067BA  08269.84884916  .00114257  17652-4  13615-3 0  4412",
139                       "2 31928  51.6257 175.4142 0001703  41.9031 318.2112 16.08175249 68368");
140         checkSymmetry("1 T7421U 02021A   02124.48976499 -.00021470  00000-0 -89879-2 0    28",
141                       "2 T7421  98.7490 199.5121 0001333 133.9522 226.1918 14.26113993    60");
142     }
143 
144     private void checkSymmetry(String line1, String line2) {
145         TLE tleRef = new TLE(line1, line2);
146         TLE tle = new TLE(tleRef.getSatelliteNumber(), tleRef.getClassification(),
147                           tleRef.getLaunchYear(), tleRef.getLaunchNumber(), tleRef.getLaunchPiece(),
148                           tleRef.getEphemerisType(), tleRef.getElementNumber(), tleRef.getDate(),
149                           tleRef.getMeanMotion(), tleRef.getMeanMotionFirstDerivative(),
150                           tleRef.getMeanMotionSecondDerivative(), tleRef.getE(), tleRef.getI(),
151                           tleRef.getPerigeeArgument(), tleRef.getRaan(), tleRef.getMeanAnomaly(),
152                           tleRef.getRevolutionNumberAtEpoch(), tleRef.getBStar());
153         Assertions.assertEquals(line1, tle.getLine1());
154         Assertions.assertEquals(line2, tle.getLine2());
155     }
156 
157     @Test
158     public void testBug74() {
159         checkSymmetry("1 00001U 00001A   12026.45833333 2.94600864  39565-9  16165-7 1    12",
160                       "2 00001 127.0796 254.4522 0000000 224.9662   0.4817  0.00000000    11");
161     }
162 
163     @Test
164     public void testBug77() {
165         checkSymmetry("1 05555U 71086J   12026.96078249 -.00000004  00001-9  01234-9 0  9082",
166                       "2 05555  74.0161 228.9750 0075476 328.9888  30.6709 12.26882470804545");
167     }
168 
169     @Test
170     public void testDirectConstruction() {
171         TLE tleA = new TLE(5555, 'U', 1971, 86, "J", 0, 908,
172                            new AbsoluteDate(new DateComponents(2012, 26),
173                                             new TimeComponents(0.96078249 * Constants.JULIAN_DAY),
174                                             TimeScalesFactory.getUTC()),
175                            taylorConvert(12.26882470, 1), taylorConvert(-0.00000004, 2), taylorConvert(0.00001e-9, 3),
176                            0.0075476, FastMath.toRadians(74.0161), FastMath.toRadians(328.9888),
177                            FastMath.toRadians(228.9750), FastMath.toRadians(30.6709), 80454, 0.01234e-9);
178         TLE tleB =  new TLE("1 05555U 71086J   12026.96078249 -.00000004  00001-9  01234-9 0  9082",
179                             "2 05555  74.0161 228.9750 0075476 328.9888  30.6709 12.26882470804545");
180         Assertions.assertEquals(tleA.getSatelliteNumber(),         tleB.getSatelliteNumber(), 0);
181         Assertions.assertEquals(tleA.getLaunchYear(),              tleB.getLaunchYear());
182         Assertions.assertEquals(tleA.getLaunchNumber(),            tleB.getLaunchNumber());
183         Assertions.assertEquals(tleA.getLaunchPiece(),             tleB.getLaunchPiece());
184         Assertions.assertEquals(tleA.getBStar(),                   tleB.getBStar(), 0);
185         Assertions.assertEquals(tleA.getEphemerisType(),           tleB.getEphemerisType());
186         Assertions.assertEquals(tleA.getI(),                       tleB.getI(), 1e-10);
187         Assertions.assertEquals(tleA.getRaan(),                    tleB.getRaan(), 1e-10);
188         Assertions.assertEquals(tleA.getE(),                       tleB.getE(), 1e-10);
189         Assertions.assertEquals(tleA.getPerigeeArgument(),         tleB.getPerigeeArgument(), 1e-10);
190         Assertions.assertEquals(tleA.getMeanAnomaly(),             tleB.getMeanAnomaly(), 1e-10);
191         Assertions.assertEquals(tleA.getMeanMotion(),              tleB.getMeanMotion(), 0);
192         Assertions.assertEquals(tleA.getRevolutionNumberAtEpoch(), tleB.getRevolutionNumberAtEpoch(), 0);
193         Assertions.assertEquals(tleA.getElementNumber(),           tleB.getElementNumber(), 0);
194     }
195 
196     @Test
197     public void testGenerateAlpha5() {
198         TLE tle = new TLE(339999, 'U', 1971, 86, "J", 0, 908,
199                           new AbsoluteDate(new DateComponents(2012, 26),
200                                            new TimeComponents(0.96078249 * Constants.JULIAN_DAY),
201                                            TimeScalesFactory.getUTC()),
202                           taylorConvert(12.26882470, 1), taylorConvert(-0.00000004, 2), taylorConvert(0.00001e-9, 3),
203                           0.0075476, FastMath.toRadians(74.0161), FastMath.toRadians(328.9888),
204                           FastMath.toRadians(228.9750), FastMath.toRadians(30.6709), 80454, 0.01234e-9);
205         Assertions.assertEquals("1 Z9999U 71086J   12026.96078249 -.00000004  00001-9  01234-9 0  9088", tle.getLine1());
206         Assertions.assertEquals("2 Z9999  74.0161 228.9750 0075476 328.9888  30.6709 12.26882470804541", tle.getLine2());
207     }
208 
209     @Test
210     public void testBug77TooLargeSecondDerivative() {
211         try {
212             TLE tle = new TLE(5555, 'U', 1971, 86, "J", 0, 908,
213                               new AbsoluteDate(new DateComponents(2012, 26),
214                                                new TimeComponents(0.96078249 * Constants.JULIAN_DAY),
215                                                TimeScalesFactory.getUTC()),
216                               taylorConvert(12.26882470, 1), taylorConvert(-0.00000004, 2), taylorConvert(0.99999e11, 3),
217                               0.0075476, FastMath.toRadians(74.0161), FastMath.toRadians(328.9888),
218                               FastMath.toRadians(228.9750), FastMath.toRadians(30.6709), 80454, 0.01234e-9);
219             tle.getLine1();
220             Assertions.fail("an exception should have been thrown");
221         } catch (OrekitException oe) {
222             Assertions.assertEquals(OrekitMessages.TLE_INVALID_PARAMETER, oe.getSpecifier());
223             Assertions.assertEquals(5555, ((Integer) oe.getParts()[0]).intValue());
224             Assertions.assertEquals("meanMotionSecondDerivative", oe.getParts()[1]);
225         }
226     }
227 
228     @Test
229     public void testBug77TooLargeBStar() {
230         try {
231             TLE tle = new TLE(5555, 'U', 1971, 86, "J", 0, 908,
232                               new AbsoluteDate(new DateComponents(2012, 26),
233                                                new TimeComponents(0.96078249 * Constants.JULIAN_DAY),
234                                                TimeScalesFactory.getUTC()),
235                               taylorConvert(12.26882470, 1), taylorConvert(-0.00000004, 2), taylorConvert(0.00001e-9, 3),
236                               0.0075476, FastMath.toRadians(74.0161), FastMath.toRadians(328.9888),
237                               FastMath.toRadians(228.9750), FastMath.toRadians(30.6709), 80454, 0.99999e11);
238             tle.getLine1();
239             Assertions.fail("an exception should have been thrown");
240         } catch (OrekitException oe) {
241             Assertions.assertEquals(OrekitMessages.TLE_INVALID_PARAMETER, oe.getSpecifier());
242             Assertions.assertEquals(5555, ((Integer) oe.getParts()[0]).intValue());
243             Assertions.assertEquals("B*", oe.getParts()[1]);
244         }
245     }
246 
247     @Test
248     public void testBug77TooLargeEccentricity() {
249         try {
250             TLE tle = new TLE(5555, 'U', 1971, 86, "J", 0, 908,
251                               new AbsoluteDate(new DateComponents(2012, 26),
252                                                new TimeComponents(0.96078249 * Constants.JULIAN_DAY),
253                                                TimeScalesFactory.getUTC()),
254                               taylorConvert(12.26882470, 1), taylorConvert(-0.00000004, 2), taylorConvert(0.00001e-9, 3),
255                               1.0075476, FastMath.toRadians(74.0161), FastMath.toRadians(328.9888),
256                               FastMath.toRadians(228.9750), FastMath.toRadians(30.6709), 80454, 0.01234e-9);
257             tle.getLine2();
258             Assertions.fail("an exception should have been thrown");
259         } catch (OrekitException oe) {
260             Assertions.assertEquals(OrekitMessages.TLE_INVALID_PARAMETER, oe.getSpecifier());
261             Assertions.assertEquals(5555, ((Integer) oe.getParts()[0]).intValue());
262             Assertions.assertEquals("eccentricity", oe.getParts()[1]);
263         }
264     }
265 
266     @Test
267     public void testBug77TooLargeSatelliteNumber1() {
268         try {
269             TLE tle = new TLE(340000, 'U', 1971, 86, "J", 0, 908,
270                               new AbsoluteDate(new DateComponents(2012, 26),
271                                                new TimeComponents(0.96078249 * Constants.JULIAN_DAY),
272                                                TimeScalesFactory.getUTC()),
273                               taylorConvert(12.26882470, 1), taylorConvert(-0.00000004, 2), taylorConvert(0.00001e-9, 3),
274                               0.0075476, FastMath.toRadians(74.0161), FastMath.toRadians(328.9888),
275                               FastMath.toRadians(228.9750), FastMath.toRadians(30.6709), 80454, 0.01234e-9);
276             tle.getLine1();
277             Assertions.fail("an exception should have been thrown");
278         } catch (OrekitException oe) {
279             Assertions.assertEquals(OrekitMessages.TLE_INVALID_PARAMETER, oe.getSpecifier());
280             Assertions.assertEquals(340000, ((Integer) oe.getParts()[0]).intValue());
281             Assertions.assertEquals("satelliteNumber-1", oe.getParts()[1]);
282         }
283     }
284 
285     @Test
286     public void testBug77TooLargeSatelliteNumber2() {
287         try {
288             TLE tle = new TLE(1000000, 'U', 1971, 86, "J", 0, 908,
289                               new AbsoluteDate(new DateComponents(2012, 26),
290                                                new TimeComponents(0.96078249 * Constants.JULIAN_DAY),
291                                                TimeScalesFactory.getUTC()),
292                               taylorConvert(12.26882470, 1), taylorConvert(-0.00000004, 2), taylorConvert(0.00001e-9, 3),
293                               0.0075476, FastMath.toRadians(74.0161), FastMath.toRadians(328.9888),
294                               FastMath.toRadians(228.9750), FastMath.toRadians(30.6709), 80454, 0.01234e-9);
295             tle.getLine2();
296             Assertions.fail("an exception should have been thrown");
297         } catch (OrekitException oe) {
298             Assertions.assertEquals(OrekitMessages.TLE_INVALID_PARAMETER, oe.getSpecifier());
299             Assertions.assertEquals(1000000, ((Integer) oe.getParts()[0]).intValue());
300             Assertions.assertEquals("satelliteNumber-2", oe.getParts()[1]);
301         }
302     }
303 
304     final double taylorConvert(final double m, final int n) {
305         // convert one term of TLE mean motion Taylor series
306         return  m * 2 * FastMath.PI * CombinatoricsUtils.factorial(n) / FastMath.pow(Constants.JULIAN_DAY, n);
307     }
308 
309     @Test
310     public void testDifferentSatNumbers() {
311         Assertions.assertThrows(OrekitException.class, () -> {
312             new TLE("1 27421U 02021A   02124.48976499 -.00021470  00000-0 -89879-2 0    20",
313                     "2 27422  98.7490 199.5121 0001333 133.9522 226.1918 14.26113993    62");
314         });
315     }
316 
317     @Test
318     public void testChecksumOK() {
319         TLE.isFormatOK("1 27421U 02021A   02124.48976499 -.00021470  00000-0 -89879-2 0    20",
320                        "2 27421  98.7490 199.5121 0001333 133.9522 226.1918 14.26113993    62");
321     }
322 
323     @Test
324     public void testWrongChecksum1() {
325         try {
326             TLE.isFormatOK("1 27421U 02021A   02124.48976499 -.00021470  00000-0 -89879-2 0    21",
327                            "2 27421  98.7490 199.5121 0001333 133.9522 226.1918 14.26113993    62");
328             Assertions.fail("an exception should have been thrown");
329         } catch (OrekitException oe) {
330             Assertions.assertEquals(OrekitMessages.TLE_CHECKSUM_ERROR, oe.getSpecifier());
331             Assertions.assertEquals(1, ((Integer) oe.getParts()[0]).intValue());
332             Assertions.assertEquals("0", oe.getParts()[1]);
333             Assertions.assertEquals("1", oe.getParts()[2]);
334             Assertions.assertEquals("1 27421U 02021A   02124.48976499 -.00021470  00000-0 -89879-2 0    21",
335                                 oe.getParts()[3]);
336         }
337     }
338 
339     @Test
340     public void testWrongChecksum2() {
341         try {
342             TLE.isFormatOK("1 27421U 02021A   02124.48976499 -.00021470  00000-0 -89879-2 0    20",
343                            "2 27421  98.7490 199.5121 0001333 133.9522 226.1918 14.26113993    61");
344             Assertions.fail("an exception should have been thrown");
345         } catch (OrekitException oe) {
346             Assertions.assertEquals(OrekitMessages.TLE_CHECKSUM_ERROR, oe.getSpecifier());
347             Assertions.assertEquals(2, ((Integer) oe.getParts()[0]).intValue());
348             Assertions.assertEquals("2", oe.getParts()[1]);
349             Assertions.assertEquals("1", oe.getParts()[2]);
350             Assertions.assertEquals("2 27421  98.7490 199.5121 0001333 133.9522 226.1918 14.26113993    61",
351                                 oe.getParts()[3]);
352         }
353     }
354 
355     @Test
356     public void testSatCodeCompliance() throws IOException, OrekitException, ParseException {
357 
358         BufferedReader rEntry = null;
359         BufferedReader rResults = null;
360 
361         InputStream inEntry =
362             TLETest.class.getResourceAsStream("/tle/extrapolationTest-data/SatCode-entry");
363         rEntry = new BufferedReader(new InputStreamReader(inEntry));
364 
365         try {
366             InputStream inResults =
367                 TLETest.class.getResourceAsStream("/tle/extrapolationTest-data/SatCode-results");
368             rResults = new BufferedReader(new InputStreamReader(inResults));
369 
370             try {
371                 double cumulated = 0; // sum of all differences between test cases and OREKIT results
372                 boolean stop = false;
373 
374                 String rline = rResults.readLine();
375 
376                 while (!stop) {
377                     if (rline == null) break;
378 
379                     String[] title = rline.split(" ");
380 
381                     if (title[0].matches("r")) {
382 
383                         String eline;
384                         int count = 0;
385                         String[] header = new String[4];
386                         for (eline = rEntry.readLine(); (eline != null) && (eline.charAt(0)=='#'); eline = rEntry.readLine()) {
387                             header[count++] = eline;
388                         }
389                         String line1 = eline;
390                         String line2 = rEntry.readLine();
391                         Assertions.assertTrue(TLE.isFormatOK(line1, line2));
392 
393                         TLE tle = new TLE(line1, line2);
394 
395                         int satNum = Integer.parseInt(title[1]);
396                         Assertions.assertTrue(satNum==tle.getSatelliteNumber());
397                         TLEPropagator ex = TLEPropagator.selectExtrapolator(tle);
398 
399                         for (rline = rResults.readLine(); (rline!=null)&&(rline.charAt(0)!='r'); rline = rResults.readLine()) {
400 
401                             String[] data = rline.split(" ");
402                             double minFromStart = Double.parseDouble(data[0]);
403                             double pX = 1000*Double.parseDouble(data[1]);
404                             double pY = 1000*Double.parseDouble(data[2]);
405                             double pZ = 1000*Double.parseDouble(data[3]);
406                             double vX = 1000*Double.parseDouble(data[4]);
407                             double vY = 1000*Double.parseDouble(data[5]);
408                             double vZ = 1000*Double.parseDouble(data[6]);
409                             Vector3D testPos = new Vector3D(pX, pY, pZ);
410                             Vector3D testVel = new Vector3D(vX, vY, vZ);
411 
412                             AbsoluteDate date = tle.getDate().shiftedBy(minFromStart * 60);
413                             PVCoordinates results = ex.getPVCoordinates(date);
414                             double normDifPos = testPos.subtract(results.getPosition()).getNorm();
415                             double normDifVel = testVel.subtract(results.getVelocity()).getNorm();
416 
417                             cumulated += normDifPos;
418                             Assertions.assertEquals(0, normDifPos, 2e-3);
419                             Assertions.assertEquals(0, normDifVel, 1e-5);
420 
421 
422                         }
423                     }
424                 }
425                 Assertions.assertEquals(0, cumulated, 0.026);
426             } finally {
427                 if (rResults != null) {
428                     rResults.close();
429                 }
430             }
431         } finally {
432             if (rEntry != null) {
433                 rEntry.close();
434             }
435         }
436     }
437 
438     @Test
439     public void testZeroInclination() {
440         TLE tle = new TLE("1 26451U 00043A   10130.13784012 -.00000276  00000-0  10000-3 0  3866",
441                           "2 26451 000.0000 266.1044 0001893 160.7642 152.5985 01.00271160 35865");
442         TLEPropagator propagator = TLEPropagator.selectExtrapolator(tle);
443         PVCoordinates pv = propagator.propagate(tle.getDate().shiftedBy(100)).getPVCoordinates();
444         Assertions.assertEquals(42171546.979560345, pv.getPosition().getNorm(), 1.0e-3);
445         Assertions.assertEquals(3074.1890089357994, pv.getVelocity().getNorm(), 1.0e-6);
446     }
447 
448     @Test
449     public void testSymmetryAfterLeapSecondIntroduction() {
450         checkSymmetry("1 34602U 09013A   12187.35117436  .00002472  18981-5  42406-5 0  9995",
451                       "2 34602  96.5991 210.0210 0006808 112.8142 247.3865 16.06008103193411");
452     }
453 
454     @Test
455     public void testOldTLE() {
456         String line1 = "1 15427U          85091.94293084 0.00000051  00000+0  32913-4 0   179";
457         String line2 = "2 15427  98.9385  46.0219 0015502 321.4354  38.5705 14.11363211 15580";
458         Assertions.assertTrue(TLE.isFormatOK(line1, line2));
459         TLE tle = new TLE(line1, line2);
460         Assertions.assertEquals(15427, tle.getSatelliteNumber());
461         Assertions.assertEquals(0.00000051,
462                             tle.getMeanMotionFirstDerivative() * Constants.JULIAN_DAY * Constants.JULIAN_DAY / (4 * FastMath.PI),
463                             1.0e-15);
464     }
465 
466     @Test
467     public void testEqualTLE() {
468         TLE tleA = new TLE("1 27421U 02021A   02124.48976499 -.00021470  00000-0 -89879-2 0    20",
469                            "2 27421  98.7490 199.5121 0001333 133.9522 226.1918 14.26113993    62");
470         TLE tleB = new TLE("1 27421U 02021A   02124.48976499 -.00021470  00000-0 -89879-2 0    20",
471                            "2 27421  98.7490 199.5121 0001333 133.9522 226.1918 14.26113993    62");
472         Assertions.assertEquals(tleA, tleB);
473         Assertions.assertEquals(tleA, tleA);
474     }
475 
476     @Test
477     public void testNonEqualTLE() {
478         TLE tleA = new TLE("1 27421U 02021A   02124.48976499 -.00021470  00000-0 -89879-2 0    20",
479                 "2 27421  98.7490 199.5121 0001333 133.9522 226.1918 14.26113993    62");
480         TLE tleB = new TLE("1 05555U 71086J   12026.96078249 -.00000004  00001-9  01234-9 0  9082",
481                 "2 05555  74.0161 228.9750 0075476 328.9888  30.6709 12.26882470804545");
482         Assertions.assertNotEquals(tleA, tleB);
483         Assertions.assertNotEquals(tleA, tleA.getLine1());
484     }
485 
486     @Test
487     public void testIssue388() {
488         TLE tleRef = new TLE("1 27421U 02021A   02124.48976499 -.00021470  00000-0 -89879-2 0    20",
489                              "2 27421  98.7490 199.5121 0001333 133.9522 226.1918 14.26113993    62");
490         TLE tleOriginal = new TLE(27421, 'U', 2002, 21, "A", TLE.DEFAULT, 2,
491                                   new AbsoluteDate("2002-05-04T11:45:15.695", TimeScalesFactory.getUTC()),
492                                   FastMath.toRadians(14.26113993 * 360 / Constants.JULIAN_DAY),
493                                   FastMath.toRadians(-.00021470 * 360 * 2 / (Constants.JULIAN_DAY * Constants.JULIAN_DAY)),
494                                   FastMath.toRadians(0.0),
495                                   1.333E-4, FastMath.toRadians(98.7490),
496                                   FastMath.toRadians(133.9522), FastMath.toRadians(199.5121), FastMath.toRadians(226.1918),
497                                   6, -0.0089879);
498         Assertions.assertEquals(tleRef.getLine1(), tleOriginal.getLine1());
499         Assertions.assertEquals(tleRef.getLine2(), tleOriginal.getLine2());
500         TLE changedBStar = new TLE(27421, 'U', 2002, 21, "A", TLE.DEFAULT, 2,
501                                    new AbsoluteDate("2002-05-04T11:45:15.695", TimeScalesFactory.getUTC()),
502                                    FastMath.toRadians(14.26113993 * 360 / Constants.JULIAN_DAY),
503                                    FastMath.toRadians(-.00021470 * 360 * 2 / (Constants.JULIAN_DAY * Constants.JULIAN_DAY)),
504                                    FastMath.toRadians(0.0),
505                                    1.333E-4, FastMath.toRadians(98.7490),
506                                    FastMath.toRadians(133.9522), FastMath.toRadians(199.5121), FastMath.toRadians(226.1918),
507                                    6, 1.0e-4);
508         Assertions.assertEquals(tleRef.getLine1().replace("-89879-2", " 10000-3"), changedBStar.getLine1());
509         Assertions.assertEquals(tleRef.getLine2(), changedBStar.getLine2());
510         Assertions.assertEquals(1.0e-4, new TLE(changedBStar.getLine1(), changedBStar.getLine2()).getBStar(), 1.0e-15);
511     }
512 
513     @Test
514     public void testIssue664NegativeRaanPa() {
515         TLE tle = new TLE(99999, 'X', 2020, 42, "F", 0, 999,
516                 new AbsoluteDate("2020-01-01T01:00:00.000", TimeScalesFactory.getUTC()), 0.0011010400252833312, 0.0,
517                 0.0, 0.0016310523359516962, 1.6999188604164899, -3.219351286726724, -2.096689019811356,
518                 2.157567545975006, 1, 1e-05);
519         // Comparing with TLE strings generated in Orekit Python after forcing the RAAN
520         // and PA to the [0, 2*Pi] range
521         Assertions.assertEquals(tle.getLine1(), "1 99999X 20042F   20001.04166667  .00000000  00000-0  10000-4 0  9997");
522         Assertions.assertEquals(tle.getLine2(), "2 99999  97.3982 239.8686 0016311 175.5448 123.6195 15.14038717    18");
523     }
524 
525     @Test
526     public void testStateToTleISS() {
527 
528         // Initialize TLE
529         final TLE tleISS = new TLE("1 25544U 98067A   21035.14486477  .00001026  00000-0  26816-4 0  9998",
530                                    "2 25544  51.6455 280.7636 0002243 335.6496 186.1723 15.48938788267977");
531 
532         // TLE propagator
533         final TLEPropagator propagator = TLEPropagator.selectExtrapolator(tleISS);
534 
535         // State at TLE epoch
536         final SpacecraftState state = propagator.propagate(tleISS.getDate());
537 
538         // Osculating to mean orbit converter
539         final OsculatingToMeanConverter converter = new FixedPointConverter();
540 
541         // Convert to TLE
542         final TLE rebuilt = TLE.stateToTLE(state, tleISS, converter);
543 
544         // Verify
545         final double eps = 1.0e-7;
546         Assertions.assertEquals(tleISS.getSatelliteNumber(),         rebuilt.getSatelliteNumber());
547         Assertions.assertEquals(tleISS.getClassification(),          rebuilt.getClassification());
548         Assertions.assertEquals(tleISS.getLaunchYear(),              rebuilt.getLaunchYear());
549         Assertions.assertEquals(tleISS.getLaunchNumber(),            rebuilt.getLaunchNumber());
550         Assertions.assertEquals(tleISS.getLaunchPiece(),             rebuilt.getLaunchPiece());
551         Assertions.assertEquals(tleISS.getElementNumber(),           rebuilt.getElementNumber());
552         Assertions.assertEquals(tleISS.getRevolutionNumberAtEpoch(), rebuilt.getRevolutionNumberAtEpoch());
553         Assertions.assertEquals(tleISS.getMeanMotion(),              rebuilt.getMeanMotion(),      eps * tleISS.getMeanMotion());
554         Assertions.assertEquals(tleISS.getE(),                       rebuilt.getE(),               eps * tleISS.getE());
555         Assertions.assertEquals(tleISS.getI(),                       rebuilt.getI(),               eps * tleISS.getI());
556         Assertions.assertEquals(tleISS.getPerigeeArgument(),         rebuilt.getPerigeeArgument(), eps * tleISS.getPerigeeArgument());
557         Assertions.assertEquals(tleISS.getRaan(),                    rebuilt.getRaan(),            eps * tleISS.getRaan());
558         Assertions.assertEquals(tleISS.getMeanAnomaly(),             rebuilt.getMeanAnomaly(),     eps * tleISS.getMeanAnomaly());
559         Assertions.assertEquals(tleISS.getMeanAnomaly(),             rebuilt.getMeanAnomaly(),     eps * tleISS.getMeanAnomaly());
560         Assertions.assertEquals(tleISS.getBStar(),                   rebuilt.getBStar(),           eps * tleISS.getBStar());
561     }
562 
563     @Test
564     public void testUnknowParameter() {
565 
566         // Initialize TLE
567         final TLE tleISS = new TLE("1 25544U 98067A   21035.14486477  .00001026  00000-0  26816-4 0  9998",
568                                    "2 25544  51.6455 280.7636 0002243 335.6496 186.1723 15.48938788267977");
569 
570         try {
571             tleISS.getParameterDriver("MyWonderfulDriver");
572             Assertions.fail("an exception should have been thrown");
573         } catch (OrekitException oe) {
574             Assertions.assertEquals(OrekitMessages.UNSUPPORTED_PARAMETER_NAME, oe.getSpecifier());
575         }
576 
577     }
578 
579     @Test
580     void roundToNextDayError() {
581         //Given
582         final AbsoluteDate tleDate = new AbsoluteDate("2022-01-01T23:59:59.99999999", TimeScalesFactory.getUTC());
583 
584         final TLE tle =
585                 new TLE(99999, 'U', 2022, 999, "A", 0, 1, tleDate, 0.0, 0.0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 99, 11606 * 1e-4,
586                         TimeScalesFactory.getUTC());
587 
588         //When
589         final AbsoluteDate returnedDate = tle.getDate();
590 
591         //Then
592         // Assert that TLE class did not round the date to the next day
593         Assertions.assertEquals(tleDate, returnedDate);
594     }
595 
596     @BeforeEach
597     public void setUp() {
598         Utils.setDataRoot("regular-data");
599     }
600 }