/* Copyright 2002-2017 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (CS) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* CS licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.orekit.propagation.analytical.tle;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.ParseException;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.util.CombinatoricsUtils;
import org.hipparchus.util.FastMath;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.orekit.Utils;
import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitMessages;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.DateComponents;
import org.orekit.time.TimeComponents;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.Constants;
import org.orekit.utils.PVCoordinates;
public class TLETest {
@Test
public void testTLEFormat() throws OrekitException {
String line1 = "1 27421U 02021A 02124.48976499 -.00021470 00000-0 -89879-2 0 20";
String line2 = "2 27421 98.7490 199.5121 0001333 133.9522 226.1918 14.26113993 62";
Assert.assertTrue(TLE.isFormatOK(line1, line2));
TLE tle = new TLE(line1, line2);
Assert.assertEquals(27421, tle.getSatelliteNumber(), 0);
Assert.assertEquals(2002, tle.getLaunchYear());
Assert.assertEquals(21, tle.getLaunchNumber());
Assert.assertEquals("A", tle.getLaunchPiece());
Assert.assertEquals(-0.0089879, tle.getBStar(), 0);
Assert.assertEquals(0, tle.getEphemerisType());
Assert.assertEquals(98.749, FastMath.toDegrees(tle.getI()), 1e-10);
Assert.assertEquals(199.5121, FastMath.toDegrees(tle.getRaan()), 1e-10);
Assert.assertEquals(0.0001333, tle.getE(), 1e-10);
Assert.assertEquals(133.9522, FastMath.toDegrees(tle.getPerigeeArgument()), 1e-10);
Assert.assertEquals(226.1918, FastMath.toDegrees(tle.getMeanAnomaly()), 1e-10);
Assert.assertEquals(14.26113993, tle.getMeanMotion() * Constants.JULIAN_DAY / (2 * FastMath.PI), 0);
Assert.assertEquals(tle.getRevolutionNumberAtEpoch(), 6, 0);
Assert.assertEquals(tle.getElementNumber(), 2 ,0);
line1 = "1 27421U 02021A 02124.48976499 -.00021470 00000-0 -89879-2 0 20";
line2 = "2 27421 98.7490 199.5121 0001333 133.9522 226.1918 14*26113993 62";
Assert.assertFalse(TLE.isFormatOK(line1, line2));
line1 = "1 27421 02021A 02124.48976499 -.00021470 00000-0 -89879-2 0 20";
line2 = "2 27421 98.7490 199.5121 0001333 133.9522 226.1918 14.26113993 62";
Assert.assertFalse(TLE.isFormatOK(line1, line2));
line1 = "1 27421U 02021A 02124.48976499 -.00021470 00000-0 -89879-2 0 20";
line2 = "2 27421 98.7490 199.5121 0001333 133.9522 226.1918 10006113993 62";
Assert.assertFalse(TLE.isFormatOK(line1, line2));
line1 = "1 27421U 02021A 02124.48976499 -.00021470 00000-0 -89879 2 0 20";
line2 = "2 27421 98.7490 199.5121 0001333 133.9522 226.1918 14.26113993 62";
Assert.assertFalse(TLE.isFormatOK(line1, line2));
}
@Test
public void testIssue196() throws OrekitException {
String line1A = "1 27421U 02021A 02124.48976499 -.00021470 00000-0 -89879-2 0 20";
String line1B = "1 27421U 02021A 02124.48976499 -.0002147 00000-0 -89879-2 0 20";
String line2 = "2 27421 98.7490 199.5121 0001333 133.9522 226.1918 14.26113993 62";
Assert.assertTrue(TLE.isFormatOK(line1A, line2));
TLE tleA = new TLE(line1A, line2);
Assert.assertTrue(TLE.isFormatOK(line1B, line2));
TLE tleB = new TLE(line1B, line2);
Assert.assertEquals(tleA.getSatelliteNumber(), tleB.getSatelliteNumber(), 0);
Assert.assertEquals(tleA.getLaunchYear(), tleB.getLaunchYear());
Assert.assertEquals(tleA.getLaunchNumber(), tleB.getLaunchNumber());
Assert.assertEquals(tleA.getLaunchPiece(), tleB.getLaunchPiece());
Assert.assertEquals(tleA.getBStar(), tleB.getBStar(), 0);
Assert.assertEquals(tleA.getEphemerisType(), tleB.getEphemerisType());
Assert.assertEquals(tleA.getI(), tleB.getI(), 1e-10);
Assert.assertEquals(tleA.getRaan(), tleB.getRaan(), 1e-10);
Assert.assertEquals(tleA.getE(), tleB.getE(), 1e-10);
Assert.assertEquals(tleA.getPerigeeArgument(), tleB.getPerigeeArgument(), 1e-10);
Assert.assertEquals(tleA.getMeanAnomaly(), tleB.getMeanAnomaly(), 1e-10);
Assert.assertEquals(tleA.getMeanMotion(), tleB.getMeanMotion(), 0);
Assert.assertEquals(tleA.getRevolutionNumberAtEpoch(), tleB.getRevolutionNumberAtEpoch(), 0);
Assert.assertEquals(tleA.getElementNumber(), tleB.getElementNumber(), 0);
}
@Test
public void testSymmetry() throws OrekitException {
checkSymmetry("1 27421U 02021A 02124.48976499 -.00021470 00000-0 -89879-2 0 20",
"2 27421 98.7490 199.5121 0001333 133.9522 226.1918 14.26113993 62");
checkSymmetry("1 31928U 98067BA 08269.84884916 .00114257 17652-4 13615-3 0 4412",
"2 31928 51.6257 175.4142 0001703 41.9031 318.2112 16.08175249 68368");
}
private void checkSymmetry(String line1, String line2) throws OrekitException {
TLE tleRef = new TLE(line1, line2);
TLE tle = new TLE(tleRef.getSatelliteNumber(), tleRef.getClassification(),
tleRef.getLaunchYear(), tleRef.getLaunchNumber(), tleRef.getLaunchPiece(),
tleRef.getEphemerisType(), tleRef.getElementNumber(), tleRef.getDate(),
tleRef.getMeanMotion(), tleRef.getMeanMotionFirstDerivative(),
tleRef.getMeanMotionSecondDerivative(), tleRef.getE(), tleRef.getI(),
tleRef.getPerigeeArgument(), tleRef.getRaan(), tleRef.getMeanAnomaly(),
tleRef.getRevolutionNumberAtEpoch(), tleRef.getBStar());
Assert.assertEquals(line1, tle.getLine1());
Assert.assertEquals(line2, tle.getLine2());
}
@Test
public void testBug74() throws OrekitException {
checkSymmetry("1 00001U 00001A 12026.45833333 2.94600864 39565-9 16165-7 1 12",
"2 00001 627.0796 454.4522 0000000 624.9662 0.4817 0.00000000 12");
}
@Test
public void testBug77() throws OrekitException {
checkSymmetry("1 05555U 71086J 12026.96078249 -.00000004 00001-9 01234-9 0 9082",
"2 05555 74.0161 228.9750 0075476 328.9888 30.6709 12.26882470804545");
}
@Test
public void testDirectConstruction() throws OrekitException {
TLE tleA = new TLE(5555, 'U', 1971, 86, "J", 0, 908,
new AbsoluteDate(new DateComponents(2012, 26),
new TimeComponents(0.96078249 * Constants.JULIAN_DAY),
TimeScalesFactory.getUTC()),
taylorConvert(12.26882470, 1), taylorConvert(-0.00000004, 2), taylorConvert(0.00001e-9, 3),
0.0075476, FastMath.toRadians(74.0161), FastMath.toRadians(328.9888),
FastMath.toRadians(228.9750), FastMath.toRadians(30.6709), 80454, 0.01234e-9);
TLE tleB = new TLE("1 05555U 71086J 12026.96078249 -.00000004 00001-9 01234-9 0 9082",
"2 05555 74.0161 228.9750 0075476 328.9888 30.6709 12.26882470804545");
Assert.assertEquals(tleA.getSatelliteNumber(), tleB.getSatelliteNumber(), 0);
Assert.assertEquals(tleA.getLaunchYear(), tleB.getLaunchYear());
Assert.assertEquals(tleA.getLaunchNumber(), tleB.getLaunchNumber());
Assert.assertEquals(tleA.getLaunchPiece(), tleB.getLaunchPiece());
Assert.assertEquals(tleA.getBStar(), tleB.getBStar(), 0);
Assert.assertEquals(tleA.getEphemerisType(), tleB.getEphemerisType());
Assert.assertEquals(tleA.getI(), tleB.getI(), 1e-10);
Assert.assertEquals(tleA.getRaan(), tleB.getRaan(), 1e-10);
Assert.assertEquals(tleA.getE(), tleB.getE(), 1e-10);
Assert.assertEquals(tleA.getPerigeeArgument(), tleB.getPerigeeArgument(), 1e-10);
Assert.assertEquals(tleA.getMeanAnomaly(), tleB.getMeanAnomaly(), 1e-10);
Assert.assertEquals(tleA.getMeanMotion(), tleB.getMeanMotion(), 0);
Assert.assertEquals(tleA.getRevolutionNumberAtEpoch(), tleB.getRevolutionNumberAtEpoch(), 0);
Assert.assertEquals(tleA.getElementNumber(), tleB.getElementNumber(), 0);
}
@Test
public void testBug77TooLargeSecondDerivative() throws OrekitException {
try {
TLE tle = new TLE(5555, 'U', 1971, 86, "J", 0, 908,
new AbsoluteDate(new DateComponents(2012, 26),
new TimeComponents(0.96078249 * Constants.JULIAN_DAY),
TimeScalesFactory.getUTC()),
taylorConvert(12.26882470, 1), taylorConvert(-0.00000004, 2), taylorConvert(0.99999e11, 3),
0.0075476, FastMath.toRadians(74.0161), FastMath.toRadians(328.9888),
FastMath.toRadians(228.9750), FastMath.toRadians(30.6709), 80454, 0.01234e-9);
tle.getLine1();
Assert.fail("an exception should have been thrown");
} catch (OrekitException oe) {
Assert.assertEquals(OrekitMessages.TLE_INVALID_PARAMETER, oe.getSpecifier());
Assert.assertEquals(5555, ((Integer) oe.getParts()[0]).intValue());
Assert.assertEquals("meanMotionSecondDerivative", oe.getParts()[1]);
}
}
@Test
public void testBug77TooLargeBStar() throws OrekitException {
try {
TLE tle = new TLE(5555, 'U', 1971, 86, "J", 0, 908,
new AbsoluteDate(new DateComponents(2012, 26),
new TimeComponents(0.96078249 * Constants.JULIAN_DAY),
TimeScalesFactory.getUTC()),
taylorConvert(12.26882470, 1), taylorConvert(-0.00000004, 2), taylorConvert(0.00001e-9, 3),
0.0075476, FastMath.toRadians(74.0161), FastMath.toRadians(328.9888),
FastMath.toRadians(228.9750), FastMath.toRadians(30.6709), 80454, 0.99999e11);
tle.getLine1();
Assert.fail("an exception should have been thrown");
} catch (OrekitException oe) {
Assert.assertEquals(OrekitMessages.TLE_INVALID_PARAMETER, oe.getSpecifier());
Assert.assertEquals(5555, ((Integer) oe.getParts()[0]).intValue());
Assert.assertEquals("B*", oe.getParts()[1]);
}
}
@Test
public void testBug77TooLargeEccentricity() throws OrekitException {
try {
TLE tle = new TLE(5555, 'U', 1971, 86, "J", 0, 908,
new AbsoluteDate(new DateComponents(2012, 26),
new TimeComponents(0.96078249 * Constants.JULIAN_DAY),
TimeScalesFactory.getUTC()),
taylorConvert(12.26882470, 1), taylorConvert(-0.00000004, 2), taylorConvert(0.00001e-9, 3),
1.0075476, FastMath.toRadians(74.0161), FastMath.toRadians(328.9888),
FastMath.toRadians(228.9750), FastMath.toRadians(30.6709), 80454, 0.01234e-9);
tle.getLine2();
Assert.fail("an exception should have been thrown");
} catch (OrekitException oe) {
Assert.assertEquals(OrekitMessages.TLE_INVALID_PARAMETER, oe.getSpecifier());
Assert.assertEquals(5555, ((Integer) oe.getParts()[0]).intValue());
Assert.assertEquals("eccentricity", oe.getParts()[1]);
}
}
@Test
public void testBug77TooLargeSatelliteNumber1() throws OrekitException {
try {
TLE tle = new TLE(1000000, 'U', 1971, 86, "J", 0, 908,
new AbsoluteDate(new DateComponents(2012, 26),
new TimeComponents(0.96078249 * Constants.JULIAN_DAY),
TimeScalesFactory.getUTC()),
taylorConvert(12.26882470, 1), taylorConvert(-0.00000004, 2), taylorConvert(0.00001e-9, 3),
0.0075476, FastMath.toRadians(74.0161), FastMath.toRadians(328.9888),
FastMath.toRadians(228.9750), FastMath.toRadians(30.6709), 80454, 0.01234e-9);
tle.getLine1();
Assert.fail("an exception should have been thrown");
} catch (OrekitException oe) {
Assert.assertEquals(OrekitMessages.TLE_INVALID_PARAMETER, oe.getSpecifier());
Assert.assertEquals(1000000, ((Integer) oe.getParts()[0]).intValue());
Assert.assertEquals("satelliteNumber-1", oe.getParts()[1]);
}
}
@Test
public void testBug77TooLargeSatelliteNumber2() throws OrekitException {
try {
TLE tle = new TLE(1000000, 'U', 1971, 86, "J", 0, 908,
new AbsoluteDate(new DateComponents(2012, 26),
new TimeComponents(0.96078249 * Constants.JULIAN_DAY),
TimeScalesFactory.getUTC()),
taylorConvert(12.26882470, 1), taylorConvert(-0.00000004, 2), taylorConvert(0.00001e-9, 3),
0.0075476, FastMath.toRadians(74.0161), FastMath.toRadians(328.9888),
FastMath.toRadians(228.9750), FastMath.toRadians(30.6709), 80454, 0.01234e-9);
tle.getLine2();
Assert.fail("an exception should have been thrown");
} catch (OrekitException oe) {
Assert.assertEquals(OrekitMessages.TLE_INVALID_PARAMETER, oe.getSpecifier());
Assert.assertEquals(1000000, ((Integer) oe.getParts()[0]).intValue());
Assert.assertEquals("satelliteNumber-2", oe.getParts()[1]);
}
}
final double taylorConvert(final double m, final int n) {
// convert one term of TLE mean motion Taylor series
return m * 2 * FastMath.PI * CombinatoricsUtils.factorial(n) / FastMath.pow(Constants.JULIAN_DAY, n);
}
@Test(expected=OrekitException.class)
public void testDifferentSatNumbers() throws OrekitException {
new TLE("1 27421U 02021A 02124.48976499 -.00021470 00000-0 -89879-2 0 20",
"2 27422 98.7490 199.5121 0001333 133.9522 226.1918 14.26113993 62");
}
@Test
public void testChecksumOK() throws OrekitException {
TLE.isFormatOK("1 27421U 02021A 02124.48976499 -.00021470 00000-0 -89879-2 0 20",
"2 27421 98.7490 199.5121 0001333 133.9522 226.1918 14.26113993 62");
}
@Test(expected=OrekitException.class)
public void testWrongChecksum1() throws OrekitException {
TLE.isFormatOK("1 27421U 02021A 02124.48976499 -.00021470 00000-0 -89879-2 0 21",
"2 27421 98.7490 199.5121 0001333 133.9522 226.1918 14.26113993 62");
}
@Test(expected=OrekitException.class)
public void testWrongChecksum2() throws OrekitException {
TLE.isFormatOK("1 27421U 02021A 02124.48976499 -.00021470 00000-0 -89879-2 0 20",
"2 27421 98.7490 199.5121 0001333 133.9522 226.1918 14.26113993 61");
}
@Test
public void testSatCodeCompliance() throws IOException, OrekitException, ParseException {
BufferedReader rEntry = null;
BufferedReader rResults = null;
InputStream inEntry =
TLETest.class.getResourceAsStream("/tle/extrapolationTest-data/SatCode-entry");
rEntry = new BufferedReader(new InputStreamReader(inEntry));
try {
InputStream inResults =
TLETest.class.getResourceAsStream("/tle/extrapolationTest-data/SatCode-results");
rResults = new BufferedReader(new InputStreamReader(inResults));
try {
double cumulated = 0; // sum of all differences between test cases and OREKIT results
boolean stop = false;
String rline = rResults.readLine();
while (!stop) {
if (rline == null) break;
String[] title = rline.split(" ");
if (title[0].matches("r")) {
String eline;
int count = 0;
String[] header = new String[4];
for (eline = rEntry.readLine(); (eline != null) && (eline.charAt(0)=='#'); eline = rEntry.readLine()) {
header[count++] = eline;
}
String line1 = eline;
String line2 = rEntry.readLine();
Assert.assertTrue(TLE.isFormatOK(line1, line2));
TLE tle = new TLE(line1, line2);
int satNum = Integer.parseInt(title[1]);
Assert.assertTrue(satNum==tle.getSatelliteNumber());
TLEPropagator ex = TLEPropagator.selectExtrapolator(tle);
for (rline = rResults.readLine(); (rline!=null)&&(rline.charAt(0)!='r'); rline = rResults.readLine()) {
String[] data = rline.split(" ");
double minFromStart = Double.parseDouble(data[0]);
double pX = 1000*Double.parseDouble(data[1]);
double pY = 1000*Double.parseDouble(data[2]);
double pZ = 1000*Double.parseDouble(data[3]);
double vX = 1000*Double.parseDouble(data[4]);
double vY = 1000*Double.parseDouble(data[5]);
double vZ = 1000*Double.parseDouble(data[6]);
Vector3D testPos = new Vector3D(pX, pY, pZ);
Vector3D testVel = new Vector3D(vX, vY, vZ);
AbsoluteDate date = tle.getDate().shiftedBy(minFromStart * 60);
PVCoordinates results = ex.getPVCoordinates(date);
double normDifPos = testPos.subtract(results.getPosition()).getNorm();
double normDifVel = testVel.subtract(results.getVelocity()).getNorm();
cumulated += normDifPos;
Assert.assertEquals(0, normDifPos, 2e-3);;
Assert.assertEquals(0, normDifVel, 1e-5);
}
}
}
Assert.assertEquals(0, cumulated, 0.026);
} finally {
if (rResults != null) {
rResults.close();
}
}
} finally {
if (rEntry != null) {
rEntry.close();
}
}
}
@Test
public void testZeroInclination() throws OrekitException{
TLE tle = new TLE("1 26451U 00043A 10130.13784012 -.00000276 00000-0 10000-3 0 3866",
"2 26451 000.0000 266.1044 0001893 160.7642 152.5985 01.00271160 35865");
TLEPropagator propagator = TLEPropagator.selectExtrapolator(tle);
PVCoordinates pv = propagator.propagate(tle.getDate().shiftedBy(100)).getPVCoordinates();
Assert.assertEquals(42171546.979560345, pv.getPosition().getNorm(), 1.0e-3);
Assert.assertEquals(3074.1890089357994, pv.getVelocity().getNorm(), 1.0e-6);
}
@Test
public void testSymmetryAfterLeapSecondIntroduction() throws OrekitException {
checkSymmetry("1 34602U 09013A 12187.35117436 .00002472 18981-5 42406-5 0 9995",
"2 34602 96.5991 210.0210 0006808 112.8142 247.3865 16.06008103193411");
}
@Before
public void setUp() {
Utils.setDataRoot("regular-data");
}
}