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