package org.orekit.files.ccsds;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.hamcrest.CoreMatchers;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.junit.Before;
import org.junit.Test;
import org.orekit.Utils;
import org.orekit.bodies.CelestialBody;
import org.orekit.bodies.CelestialBodyFactory;
import org.orekit.errors.OrekitException;
import org.orekit.files.ccsds.OEMFile.EphemeridesBlock;
import org.orekit.files.ccsds.OEMFile.OemSatelliteEphemeris;
import org.orekit.files.ccsds.StreamingOemWriter.Segment;
import org.orekit.frames.Frame;
import org.orekit.frames.FramesFactory;
import org.orekit.propagation.BoundedPropagator;
import org.orekit.time.TimeScale;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.IERSConventions;
import org.orekit.utils.TimeStampedPVCoordinates;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
/**
* Check {@link StreamingOemWriter}.
*
* @author Evan Ward
*/
public class StreamingOemWriterTest {
/** Set Orekit data. */
@Before
public void setUp() {
Utils.setDataRoot("regular-data");
}
/**
* Check guessing the CCSDS frame name for some frames.
*
* @throws OrekitException on error.
*/
@Test
public void testGuessFrame() throws OrekitException {
// action + verify
// check all non-LOF frames created by OEMParser
for (CCSDSFrame ccsdsFrame : CCSDSFrame.values()) {
if (!ccsdsFrame.isLof()) {
Frame frame = ccsdsFrame.getFrame(IERSConventions.IERS_2010, true);
String actual = StreamingOemWriter.guessFrame(frame);
assertThat(actual.replace("-", ""), CoreMatchers.is(ccsdsFrame.name()));
}
}
// check common Orekit frames from FramesFactory
assertThat(StreamingOemWriter.guessFrame(FramesFactory.getGCRF()),
CoreMatchers.is("GCRF"));
assertThat(StreamingOemWriter.guessFrame(FramesFactory.getEME2000()),
CoreMatchers.is("EME2000"));
assertThat(
StreamingOemWriter.guessFrame(
FramesFactory.getITRFEquinox(IERSConventions.IERS_2010, true)),
CoreMatchers.is("GRC"));
assertThat(StreamingOemWriter.guessFrame(FramesFactory.getICRF()),
CoreMatchers.is("ICRF"));
assertThat(
StreamingOemWriter.guessFrame(
FramesFactory.getITRF(IERSConventions.IERS_2010, true)),
CoreMatchers.is("ITRF2008"));
assertThat(StreamingOemWriter.guessFrame(FramesFactory.getGTOD(true)),
CoreMatchers.is("TDR"));
assertThat(StreamingOemWriter.guessFrame(FramesFactory.getTEME()),
CoreMatchers.is("TEME"));
assertThat(StreamingOemWriter.guessFrame(FramesFactory.getTOD(true)),
CoreMatchers.is("TOD"));
// check other names in Annex A
assertThat(
StreamingOemWriter.guessFrame(
CelestialBodyFactory.getMars().getInertiallyOrientedFrame()),
CoreMatchers.is("MCI"));
assertThat(
StreamingOemWriter.guessFrame(
CelestialBodyFactory.getSolarSystemBarycenter()
.getInertiallyOrientedFrame()),
CoreMatchers.is("ICRF"));
// check some special CCSDS frames
CcsdsModifiedFrame frame = new CcsdsModifiedFrame(
FramesFactory.getEME2000(), "EME2000",
CelestialBodyFactory.getMars(), "MARS");
assertThat(StreamingOemWriter.guessFrame(frame), CoreMatchers.is("EME2000"));
}
/**
* Check guessing the frame center for some frames.
*
* @throws OrekitException on error.
*/
@Test
public void testGuessCenter() throws OrekitException {
// action + verify
// check all CCSDS common center names
List<CenterName> centerNames =
new ArrayList<>(Arrays.asList(CenterName.values()));
centerNames.remove(CenterName.EARTH_MOON);
for (CenterName centerName : centerNames) {
CelestialBody body = centerName.getCelestialBody();
String name = centerName.name().replace('_', ' ');
assertThat(StreamingOemWriter.guessCenter(body.getInertiallyOrientedFrame()),
CoreMatchers.is(name));
assertThat(StreamingOemWriter.guessCenter(body.getBodyOrientedFrame()),
CoreMatchers.is(name));
}
// Earth-Moon Barycenter is special
CelestialBody emb = CenterName.EARTH_MOON.getCelestialBody();
assertThat(StreamingOemWriter.guessCenter(emb.getInertiallyOrientedFrame()),
CoreMatchers.is("EARTH-MOON BARYCENTER"));
assertThat(StreamingOemWriter.guessCenter(emb.getBodyOrientedFrame()),
CoreMatchers.is("EARTH-MOON BARYCENTER"));
// check some special CCSDS frames
CcsdsModifiedFrame frame = new CcsdsModifiedFrame(
FramesFactory.getEME2000(), "EME2000",
CelestialBodyFactory.getMars(), "MARS");
assertThat(StreamingOemWriter.guessCenter(frame), CoreMatchers.is("MARS"));
}
/**
* Check reading and writing an OEM both with and without using the step handler
* methods.
*
* @throws Exception on error.
*/
@Test
public void testWriteOemStepHandler() throws Exception {
// setup
TimeScale utc = TimeScalesFactory.getUTC();
List<String> files =
Arrays.asList("/ccsds/OEMExample5.txt", "/ccsds/OEMExample4.txt");
for (String ex : files) {
InputStream inEntry = getClass().getResourceAsStream(ex);
OEMParser parser = new OEMParser()
.withMu(CelestialBodyFactory.getEarth().getGM())
.withConventions(IERSConventions.IERS_2010);
OEMFile oemFile = parser.parse(inEntry, "OEMExample.txt");
OemSatelliteEphemeris satellite =
oemFile.getSatellites().values().iterator().next();
EphemeridesBlock ephemerisBlock = satellite.getSegments().get(0);
Frame frame = ephemerisBlock.getFrame();
double step = ephemerisBlock.getStopTime()
.durationFrom(ephemerisBlock.getStartTime()) /
(ephemerisBlock.getCoordinates().size() - 1);
String originator = oemFile.getOriginator();
EphemeridesBlock block = oemFile.getEphemeridesBlocks().get(0);
String objectName = block.getMetaData().getObjectName();
String objectID = block.getMetaData().getObjectID();
Map<Keyword, String> metadata = new LinkedHashMap<>();
metadata.put(Keyword.ORIGINATOR, originator);
metadata.put(Keyword.OBJECT_NAME, "will be overwritten");
metadata.put(Keyword.OBJECT_ID, objectID);
Map<Keyword, String> segmentData = new LinkedHashMap<>();
segmentData.put(Keyword.OBJECT_NAME, objectName);
// check using the Propagator / StepHandler interface
StringBuilder buffer = new StringBuilder();
StreamingOemWriter writer = new StreamingOemWriter(buffer, utc, metadata);
writer.writeHeader();
Segment segment = writer.newSegment(frame, segmentData);
BoundedPropagator propagator = satellite.getPropagator();
propagator.setMasterMode(step, segment);
propagator.propagate(propagator.getMinDate(), propagator.getMaxDate());
// verify
BufferedReader reader =
new BufferedReader(new StringReader(buffer.toString()));
OEMFile generatedOemFile = parser.parse(reader, "buffer");
compareOemFiles(oemFile, generatedOemFile, 1e-7, 1e-7);
// check calling the methods directly
buffer = new StringBuilder();
writer = new StreamingOemWriter(buffer, utc, metadata);
writer.writeHeader();
// set start and stop date manually
segmentData.put(Keyword.START_TIME,
StreamingOemWriter.dateToString(block.getStart().getComponents(utc)));
segmentData.put(Keyword.STOP_TIME,
StreamingOemWriter.dateToString(block.getStop().getComponents(utc)));
segment = writer.newSegment(frame, segmentData);
segment.writeMetadata();
for (TimeStampedPVCoordinates coordinate : block.getCoordinates()) {
segment.writeEphemerisLine(coordinate);
}
// verify
reader = new BufferedReader(new StringReader(buffer.toString()));
generatedOemFile = parser.parse(reader, "buffer");
compareOemFiles(oemFile, generatedOemFile, 1e-7, 1e-7);
}
}
private static void compareOemEphemerisBlocks(EphemeridesBlock block1,
EphemeridesBlock block2,
double p_tol,
double v_tol) {
compareOemEphemerisBlocksMetadata(block1.getMetaData(), block2.getMetaData());
assertEquals(block1.getStart(), block2.getStart());
assertEquals(block1.getStop(), block2.getStop());
assertEquals(block1.getEphemeridesDataLines().size(), block2.getEphemeridesDataLines().size());
for (int i = 0; i < block1.getEphemeridesDataLines().size(); i++) {
TimeStampedPVCoordinates c1 = block1.getEphemeridesDataLines().get(i);
TimeStampedPVCoordinates c2 = block2.getEphemeridesDataLines().get(i);
assertEquals(c1.getDate(), c2.getDate());
assertEquals(c1.getPosition() + " -> " + c2.getPosition(), 0.0,
Vector3D.distance(c1.getPosition(), c2.getPosition()), p_tol);
assertEquals(c1.getVelocity() + " -> " + c2.getVelocity(), 0.0,
Vector3D.distance(c1.getVelocity(), c2.getVelocity()), v_tol);
}
}
private static void compareOemEphemerisBlocksMetadata(ODMMetaData meta1, ODMMetaData meta2) {
assertEquals(meta1.getObjectID(), meta2.getObjectID());
assertEquals(meta1.getObjectName(), meta2.getObjectName());
assertEquals(meta1.getCenterName(), meta2.getCenterName());
assertEquals(meta1.getFrameString(), meta2.getFrameString());
assertEquals(meta1.getTimeSystem(), meta2.getTimeSystem());
}
static void compareOemFiles(OEMFile file1,
OEMFile file2,
double p_tol,
double v_tol) {
assertEquals(file1.getOriginator(), file2.getOriginator());
assertEquals(file1.getEphemeridesBlocks().size(), file2.getEphemeridesBlocks().size());
for (int i = 0; i < file1.getEphemeridesBlocks().size(); i++) {
compareOemEphemerisBlocks(
file1.getEphemeridesBlocks().get(i),
file2.getEphemeridesBlocks().get(i),
p_tol,
v_tol);
}
}
}