/* 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.files.ccsds;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import org.hipparchus.geometry.euclidean.threed.Rotation;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.linear.Array2DRowRealMatrix;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.orekit.OrekitMatchers;
import org.orekit.Utils;
import org.orekit.bodies.CelestialBody;
import org.orekit.bodies.CelestialBodyFactory;
import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitMessages;
import org.orekit.files.ccsds.OEMFile.EphemeridesBlock;
import org.orekit.files.ccsds.OEMFile.OemSatelliteEphemeris;
import org.orekit.frames.FactoryManagedFrame;
import org.orekit.frames.Frame;
import org.orekit.frames.FramesFactory;
import org.orekit.frames.LOFType;
import org.orekit.frames.Transform;
import org.orekit.orbits.CartesianOrbit;
import org.orekit.propagation.BoundedPropagator;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.CartesianDerivativesFilter;
import org.orekit.utils.IERSConventions;
import org.orekit.utils.PVCoordinates;
import org.orekit.utils.TimeStampedPVCoordinates;
public class OEMParserTest {
@Before
public void setUp()
throws Exception {
Utils.setDataRoot("regular-data");
}
@Test
public void testParseOEM1() throws OrekitException, IOException {
//
final String ex = "/ccsds/OEMExample.txt";
final InputStream inEntry = getClass().getResourceAsStream(ex);
final OEMParser parser = new OEMParser().withMu(CelestialBodyFactory.getEarth().getGM());
final OEMFile file = parser.parse(inEntry, "OEMExample.txt");
Assert.assertEquals(CcsdsTimeScale.UTC, file.getEphemeridesBlocks().get(0).getMetaData().getTimeSystem());
Assert.assertEquals("MARS GLOBAL SURVEYOR", file.getEphemeridesBlocks().get(0).getMetaData().getObjectName());
Assert.assertEquals("1996-062A", file.getEphemeridesBlocks().get(0).getMetaData().getObjectID());
Assert.assertEquals("MARS BARYCENTER", file.getEphemeridesBlocks().get(0).getMetaData().getCenterName());
Assert.assertEquals(1996, file.getEphemeridesBlocks().get(0).getMetaData().getLaunchYear());
Assert.assertEquals(62, file.getEphemeridesBlocks().get(0).getMetaData().getLaunchNumber());
Assert.assertEquals("A", file.getEphemeridesBlocks().get(0).getMetaData().getLaunchPiece());
Assert.assertFalse(file.getEphemeridesBlocks().get(0).getMetaData().getHasCreatableBody());
Assert.assertNull(file.getEphemeridesBlocks().get(0).getMetaData().getCenterBody());
Assert.assertEquals(new AbsoluteDate(1996, 12, 18, 12, 00, 0.331, TimeScalesFactory.getUTC()),
file.getEphemeridesBlocks().get(0).getStartTime());
Assert.assertEquals(new AbsoluteDate(1996, 12, 28, 21, 28, 0.331, TimeScalesFactory.getUTC()),
file.getEphemeridesBlocks().get(0).getStopTime());
Assert.assertEquals(new AbsoluteDate(1996, 12, 18, 12, 10, 0.331, TimeScalesFactory.getUTC()),
file.getEphemeridesBlocks().get(0).getUseableStartTime());
Assert.assertEquals(new AbsoluteDate(1996, 12, 28, 21, 23, 0.331, TimeScalesFactory.getUTC()),
file.getEphemeridesBlocks().get(0).getUseableStopTime());
Assert.assertEquals("HERMITE", file.getEphemeridesBlocks().get(0).getInterpolationMethod());
Assert.assertEquals(7, file.getEphemeridesBlocks().get(0).getInterpolationDegree());
ArrayList<String> ephemeridesDataLinesComment = new ArrayList<String>();
ephemeridesDataLinesComment.add("This file was produced by M.R. Somebody, MSOO NAV/JPL, 1996NOV 04. It is");
ephemeridesDataLinesComment.add("to be used for DSN scheduling purposes only.");
Assert.assertEquals(ephemeridesDataLinesComment, file.getEphemeridesBlocks().get(0).getEphemeridesDataLinesComment());
CartesianOrbit orbit = new CartesianOrbit(new PVCoordinates
(new Vector3D(2789.619 * 1000, -280.045 * 1000, -1746.755 * 1000),
new Vector3D(4.73372 * 1000, -2.49586 * 1000, -1.04195 * 1000)),
FramesFactory.getEME2000(),
new AbsoluteDate("1996-12-18T12:00:00.331",TimeScalesFactory.getUTC()),
CelestialBodyFactory.getEarth().getGM());
Assert.assertArrayEquals(orbit.getPVCoordinates().getPosition().toArray(), file.getEphemeridesBlocks().get(0).getEphemeridesDataLines().get(0).getPosition().toArray(),1e-10);
Assert.assertArrayEquals(orbit.getPVCoordinates().getVelocity().toArray(), file.getEphemeridesBlocks().get(0).getEphemeridesDataLines().get(0).getVelocity().toArray(),1e-10);
Assert.assertArrayEquals((new Vector3D(1, 1, 1)).toArray(), file.getEphemeridesBlocks().get(1).getEphemeridesDataLines().get(0).getAcceleration().toArray(), 1e-10);
Assert.assertEquals(Vector3D.ZERO, file.getEphemeridesBlocks().get(1).getEphemeridesDataLines().get(1).getAcceleration());
final Array2DRowRealMatrix covMatrix = new Array2DRowRealMatrix(6, 6);
final double[] column1 = {
3.331349476038534e-04, 4.618927349220216e-04,
-3.070007847730449e-04, -3.349365033922630e-07,
-2.211832501084875e-07, -3.041346050686871e-07
};
final double[] column2 = {
4.618927349220216e-04, 6.782421679971363e-04,
-4.221234189514228e-04, -4.686084221046758e-07,
-2.864186892102733e-07, -4.989496988610662e-07
};
final double[] column3 = {
-3.070007847730449e-04, -4.221234189514228e-04,
3.231931992380369e-04, 2.484949578400095e-07,
1.798098699846038e-07, 3.540310904497689e-07
};
final double[] column4 = {
-3.349365033922630e-07, -4.686084221046758e-07,
2.484949578400095e-07, 4.296022805587290e-10,
2.608899201686016e-10, 1.869263192954590e-10
};
final double[] column5 = {
-2.211832501084875e-07, -2.864186892102733e-07,
1.798098699846038e-07, 2.608899201686016e-10,
1.767514756338532e-10, 1.008862586240695e-10
};
final double[] column6 = {
-3.041346050686871e-07, -4.989496988610662e-07,
3.540310904497689e-07, 1.869263192954590e-10,
1.008862586240695e-10, 6.224444338635500e-10
};
covMatrix.setColumn(0, column1);
covMatrix.setColumn(1, column2);
covMatrix.setColumn(2, column3);
covMatrix.setColumn(3, column4);
covMatrix.setColumn(4, column5);
covMatrix.setColumn(5, column6);
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 6; j++) {
Assert.assertEquals(covMatrix.getEntry(i, j),
file.getEphemeridesBlocks().get(2).getCovarianceMatrices().get(0).getMatrix().getEntry(i, j),
1e-10);
}
}
Assert.assertEquals(new AbsoluteDate("1996-12-28T21:29:07.267", TimeScalesFactory.getUTC()),
file.getEphemeridesBlocks().get(2).getCovarianceMatrices().get(0).getEpoch());
Assert.assertEquals(LOFType.QSW,
file.getEphemeridesBlocks().get(2).getCovarianceMatrices().get(0).getLofType());
Assert.assertNull(file.getEphemeridesBlocks().get(2).getCovarianceMatrices().get(0).getFrame());
Assert.assertEquals(FramesFactory.getEME2000(),
file.getEphemeridesBlocks().get(2).getCovarianceMatrices().get(1).getFrame());
Assert.assertNull(file.getEphemeridesBlocks().get(2).getCovarianceMatrices().get(1).getLofType());
}
@Test
public void testParseOEM1OrbitFile() throws OrekitException, IOException {
final String ex = "/ccsds/OEMExample3.txt";
final InputStream inEntry = getClass().getResourceAsStream(ex);
final OEMParser parser = new OEMParser()
.withMu(CelestialBodyFactory.getEarth().getGM())
.withConventions(IERSConventions.IERS_2010);
final OEMFile file = parser.parse(inEntry);
Assert.assertEquals(CcsdsTimeScale.UTC, file.getEphemeridesBlocks().get(0).getMetaData().getTimeSystem());
Assert.assertEquals("MARS GLOBAL SURVEYOR", file.getEphemeridesBlocks().get(0).getMetaData().getObjectName());
Assert.assertEquals("1996-062A", file.getEphemeridesBlocks().get(0).getMetaData().getObjectID());
Assert.assertEquals(1, file.getSatellites().size());
Assert.assertEquals(true, file.getSatellites().containsKey("1996-062A"));
Assert.assertEquals(false, file.getSatellites().containsKey("MARS GLOBAL SURVEYOR"));
Assert.assertEquals(1, file.getSatellites().size());
Assert.assertEquals("1996-062A", file.getSatellites().values().iterator().next().getId());
Assert.assertEquals(
new AbsoluteDate("1996-12-18T12:00:00.331", TimeScalesFactory.getUTC()),
file.getEphemeridesBlocks().get(0).getStartTime());
final OemSatelliteEphemeris satellite = file.getSatellites().get("1996-062A");
Assert.assertEquals(satellite.getId(), "1996-062A");
Assert.assertEquals(satellite.getMu(), file.getMuUsed(), 0);
final EphemeridesBlock actualBlock = satellite.getSegments().get(0);
Assert.assertEquals(actualBlock.getMu(), file.getMuUsed(), 0);
Assert.assertEquals(actualBlock.getFrameString(), "EME2000");
Assert.assertEquals(actualBlock.getFrameCenterString(), "MARS BARYCENTER");
Assert.assertEquals(actualBlock.getMetaData().getHasCreatableBody(), false);
// Frame not creatable since it's center can't be created.
try {
actualBlock.getFrame();
Assert.fail("Expected Exception");
} catch (OrekitException e){
Assert.assertEquals(e.getSpecifier(),
OrekitMessages.NO_DATA_LOADED_FOR_CELESTIAL_BODY);
}
Assert.assertEquals(actualBlock.getTimeScaleString(), "UTC");
Assert.assertEquals(actualBlock.getTimeScale(), TimeScalesFactory.getUTC());
Assert.assertEquals(actualBlock.getInterpolationSamples(), 3);
Assert.assertEquals(actualBlock.getAvailableDerivatives(),
CartesianDerivativesFilter.USE_PV);
// propagator can't be created since frame can't be created
try {
satellite.getPropagator();
Assert.fail("Expected Exception");
} catch (OrekitException e){
Assert.assertEquals(e.getSpecifier(),
OrekitMessages.NO_DATA_LOADED_FOR_CELESTIAL_BODY);
}
}
@Test
public void testParseOemMissingOptionalData() throws OrekitException, IOException {
final String ex = "/ccsds/OEMExample6.txt";
final InputStream inEntry = getClass().getResourceAsStream(ex);
final OEMParser parser = new OEMParser()
.withMu(CelestialBodyFactory.getEarth().getGM())
.withConventions(IERSConventions.IERS_2010);
final OEMFile file = parser.parse(inEntry);
Assert.assertEquals(CcsdsTimeScale.UTC, file.getEphemeridesBlocks().get(0).getMetaData().getTimeSystem());
Assert.assertEquals("MARS GLOBAL SURVEYOR", file.getEphemeridesBlocks().get(0).getMetaData().getObjectName());
Assert.assertEquals("1996-062A", file.getEphemeridesBlocks().get(0).getMetaData().getObjectID());
Assert.assertEquals(1, file.getSatellites().size());
Assert.assertEquals(true, file.getSatellites().containsKey("1996-062A"));
Assert.assertEquals(false, file.getSatellites().containsKey("MARS GLOBAL SURVEYOR"));
Assert.assertEquals(1, file.getSatellites().size());
Assert.assertEquals("1996-062A", file.getSatellites().values().iterator().next().getId());
Assert.assertEquals(
new AbsoluteDate("2002-12-18T12:00:00.331", TimeScalesFactory.getUTC()),
file.getEphemeridesBlocks().get(0).getStartTime());
OemSatelliteEphemeris satellite = file.getSatellites().get("1996-062A");
Assert.assertEquals(satellite.getId(), "1996-062A");
Assert.assertEquals(satellite.getMu(), file.getMuUsed(), 0);
EphemeridesBlock actualBlock = satellite.getSegments().get(0);
Assert.assertEquals(actualBlock.getMu(), file.getMuUsed(), 0);
FactoryManagedFrame eme2000 = FramesFactory.getEME2000();
Frame actualFrame = actualBlock.getFrame();
AbsoluteDate actualStart = satellite.getStart();
Transform actualTransform = eme2000.getTransformTo(actualFrame, actualStart);
CelestialBody mars = CelestialBodyFactory.getMars();
TimeStampedPVCoordinates marsPV = mars.getPVCoordinates(actualStart, eme2000);
Assert.assertEquals(actualTransform.getTranslation(), marsPV.getPosition());
Assert.assertEquals(actualTransform.getVelocity(), marsPV.getVelocity());
Assert.assertEquals(actualTransform.getAcceleration(), marsPV.getAcceleration());
Assert.assertEquals(
Rotation.distance(actualTransform.getRotation(), Rotation.IDENTITY),
0.0, 0.0);
Assert.assertEquals(actualTransform.getRotationRate(), Vector3D.ZERO);
Assert.assertEquals(actualTransform.getRotationAcceleration(), Vector3D.ZERO);
Assert.assertEquals(actualFrame.getName(), "Mars/EME2000");
Assert.assertEquals(actualBlock.getFrameString(), "EME2000");
Assert.assertEquals(actualBlock.getTimeScaleString(), "UTC");
Assert.assertEquals(actualBlock.getTimeScale(), TimeScalesFactory.getUTC());
Assert.assertEquals(actualBlock.getAvailableDerivatives(),
CartesianDerivativesFilter.USE_PV);
Assert.assertEquals(satellite.getSegments().get(0).getStartTime(), actualStart);
Assert.assertEquals(satellite.getSegments().get(2).getStopTime(), satellite.getStop());
final BoundedPropagator propagator = satellite.getPropagator();
Assert.assertEquals(propagator.getMinDate(), satellite.getStart());
Assert.assertEquals(propagator.getMinDate(), satellite.getSegments().get(0).getStart());
Assert.assertEquals(propagator.getMaxDate(), satellite.getStop());
Assert.assertEquals(propagator.getMaxDate(), satellite.getSegments().get(2).getStop());
final List<TimeStampedPVCoordinates> dataLines = new ArrayList<>();
for (EphemeridesBlock block : file.getEphemeridesBlocks()) {
for (TimeStampedPVCoordinates dataLine : block.getEphemeridesDataLines()) {
if (dataLine.getDate().compareTo(satellite.getStart()) >= 0) {
dataLines.add(dataLine);
}
}
}
final int ulps = 12;
for (TimeStampedPVCoordinates coord : dataLines) {
Assert.assertThat(
propagator.getPVCoordinates(coord.getDate(), actualFrame),
OrekitMatchers.pvCloseTo(coord, ulps));
Assert.assertThat(
propagator.propagate(coord.getDate()).getPVCoordinates(),
OrekitMatchers.pvCloseTo(coord, ulps));
}
}
@Test
public void testParseOEM2()
throws OrekitException, URISyntaxException {
final String name = getClass().getResource("/ccsds/OEMExample2.txt").toURI().getPath();
OEMParser parser = new OEMParser().
withConventions(IERSConventions.IERS_2010).
withSimpleEOP(true).
withMu(CelestialBodyFactory.getMars().getGM()).
withInternationalDesignator(1996, 2, "A").
withMissionReferenceDate(new AbsoluteDate("1996-12-17T00:00:00.000",
TimeScalesFactory.getUTC()));
final OEMFile file = parser.parse(name);
final List<String> headerComment = new ArrayList<String>();
headerComment.add("comment");
Assert.assertEquals(headerComment, file.getHeaderComment());
final List<String> metadataComment = new ArrayList<String>();
metadataComment.add("comment 1");
metadataComment.add("comment 2");
Assert.assertEquals(metadataComment, file.getEphemeridesBlocks().get(0).getMetaData().getComment());
Assert.assertEquals("TOD", file.getEphemeridesBlocks().get(0).getFrameString());
Assert.assertEquals("EME2000", file.getEphemeridesBlocks().get(1).getFrameString());
List<EphemeridesBlock> blocks = file.getEphemeridesBlocks();
Assert.assertEquals(2, blocks.size());
Assert.assertTrue(blocks.get(0).getHasRefFrameEpoch());
Assert.assertEquals(129600.331,
blocks.get(0).getStartTime().durationFrom(file.getMissionReferenceDate()),
1.0e-15);
Assert.assertEquals(941347.267,
blocks.get(1).getStartTime().durationFrom(file.getMissionReferenceDate()),
1.0e-15);
}
@Test
public void testWrongODMType() {
try {
new OEMParser().parse(getClass().getResourceAsStream("/ccsds/OPMExample.txt"), "OPMExample.txt");
} catch (OrekitException oe) {
Assert.assertEquals(OrekitMessages.CCSDS_UNEXPECTED_KEYWORD, oe.getSpecifier());
Assert.assertEquals(1, oe.getParts()[0]);
Assert.assertEquals("OPMExample.txt", oe.getParts()[1]);
Assert.assertEquals("CCSDS_OPM_VERS = 2.0", oe.getParts()[2]);
}
}
@Test
public void testEphemerisNumberFormatErrorType() {
try {
new OEMParser().withMu(CelestialBodyFactory.getMars().getGM()).
parse(getClass().getResourceAsStream("/ccsds/OEM-ephemeris-number-format-error.txt"),
"OEM-ephemeris-number-format-error.txt");
} catch (OrekitException oe) {
Assert.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
Assert.assertEquals(44, oe.getParts()[0]);
Assert.assertEquals("OEM-ephemeris-number-format-error.txt", oe.getParts()[1]);
Assert.assertEquals("1996-12-28T21:59:02.267 -2445.234 -878.141 this-is-not-a-number 1.86043 -3.421256 -0.996366", oe.getParts()[2]);
}
}
@Test
public void testCovarianceNumberFormatErrorType() {
try {
new OEMParser().withMu(CelestialBodyFactory.getMars().getGM()).
parse(getClass().getResourceAsStream("/ccsds/OEM-covariance-number-format-error.txt"),
"OEM-covariance-number-format-error.txt");
} catch (OrekitException oe) {
Assert.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
Assert.assertEquals(52, oe.getParts()[0]);
Assert.assertEquals("OEM-covariance-number-format-error.txt", oe.getParts()[1]);
Assert.assertEquals("4.6189273e-04 this-is-not-a-number", oe.getParts()[2]);
}
}
@Test
public void testNonExistentFile() throws URISyntaxException {
final String realName = getClass().getResource("/ccsds/OEMExample.txt").toURI().getPath();
final String wrongName = realName + "xxxxx";
try {
new OEMParser().parse(wrongName);
Assert.fail("an exception should have been thrown");
} catch (OrekitException oe) {
Assert.assertEquals(OrekitMessages.UNABLE_TO_FIND_FILE, oe.getSpecifier());
Assert.assertEquals(wrongName, oe.getParts()[0]);
}
}
@Test
public void testInconsistentTimeSystems() {
try {
new OEMParser().withMu(CelestialBodyFactory.getMars().getGM()).parse(getClass().getResourceAsStream("/ccsds/OEM-inconsistent-time-systems.txt"));
} catch (OrekitException oe) {
Assert.assertEquals(OrekitMessages.CCSDS_OEM_INCONSISTENT_TIME_SYSTEMS, oe.getSpecifier());
Assert.assertEquals(CcsdsTimeScale.UTC, oe.getParts()[0]);
Assert.assertEquals(CcsdsTimeScale.TCG, oe.getParts()[1]);
}
}
@Test
public void testLowerCaseValue() throws OrekitException {
//setup
String file = "/ccsds/oemLowerCaseValue.oem";
InputStream in = getClass().getResourceAsStream(file);
//action
OEMFile actual = new OEMParser().parse(in, file);
//verify
Assert.assertEquals(
CelestialBodyFactory.getEarth(),
actual.getEphemeridesBlocks().get(0).getMetaData().getCenterBody());
}
@Test
public void testWrongKeyword()
throws OrekitException, URISyntaxException {
// simple test for OMM file, contains p/v entries and other mandatory
// data.
final String name = getClass().getResource("/ccsds/OEM-wrong-keyword.txt").toURI().getPath();
try {
new OEMParser().parse(name);
Assert.fail("an exception should have been thrown");
} catch (OrekitException oe) {
Assert.assertEquals(OrekitMessages.CCSDS_UNEXPECTED_KEYWORD, oe.getSpecifier());
Assert.assertEquals(19, ((Integer) oe.getParts()[0]).intValue());
Assert.assertTrue(((String) oe.getParts()[2]).startsWith("WRONG_KEYWORD"));
}
}
@Test
public void testKeywordWithinEphemeris()
throws OrekitException, URISyntaxException {
// simple test for OMM file, contains p/v entries and other mandatory
// data.
final String name = getClass().getResource("/ccsds/OEM-keyword-within-ephemeris.txt").toURI().getPath();
try {
new OEMParser().withMu(CelestialBodyFactory.getMars().getGM()).parse(name);
Assert.fail("an exception should have been thrown");
} catch (OrekitException oe) {
Assert.assertEquals(OrekitMessages.CCSDS_UNEXPECTED_KEYWORD, oe.getSpecifier());
Assert.assertEquals(24, ((Integer) oe.getParts()[0]).intValue());
Assert.assertTrue(((String) oe.getParts()[2]).startsWith("USER_DEFINED_TEST_KEY"));
}
}
@Test
public void testKeywordWithinCovariance()
throws OrekitException, URISyntaxException {
// simple test for OMM file, contains p/v entries and other mandatory
// data.
final String name = getClass().getResource("/ccsds/OEM-keyword-within-covariance.txt").toURI().getPath();
try {
new OEMParser().withMu(CelestialBodyFactory.getMars().getGM()).parse(name);
Assert.fail("an exception should have been thrown");
} catch (OrekitException oe) {
Assert.assertEquals(OrekitMessages.CCSDS_UNEXPECTED_KEYWORD, oe.getSpecifier());
Assert.assertEquals(91, ((Integer) oe.getParts()[0]).intValue());
Assert.assertTrue(((String) oe.getParts()[2]).startsWith("USER_DEFINED_TEST_KEY"));
}
}
}