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