Commit b265d4a1 authored by Luc Maisonobe's avatar Luc Maisonobe
Browse files

Added write for XML OEM files.

This is the final touch on implementing ODM V3!

Fixes #474
parent 35a20bb2
Pipeline #1056 passed with stage
in 24 minutes and 28 seconds
......@@ -24,6 +24,7 @@ import org.orekit.data.DataContext;
import org.orekit.data.DataSource;
import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitMessages;
import org.orekit.files.ccsds.definitions.Units;
import org.orekit.files.ccsds.ndm.ParsedUnitsBehavior;
import org.orekit.files.ccsds.ndm.odm.CartesianCovariance;
import org.orekit.files.ccsds.ndm.odm.CartesianCovarianceKey;
......@@ -364,13 +365,13 @@ public class OemParser extends OdmParser<OemFile, OemParser> implements Ephemeri
stateVectorBlock.setP(0, Unit.KILOMETRE.toSI(Double.parseDouble(fields[1])));
stateVectorBlock.setP(1, Unit.KILOMETRE.toSI(Double.parseDouble(fields[2])));
stateVectorBlock.setP(2, Unit.KILOMETRE.toSI(Double.parseDouble(fields[3])));
stateVectorBlock.setV(0, Unit.KILOMETRE.toSI(Double.parseDouble(fields[4])));
stateVectorBlock.setV(1, Unit.KILOMETRE.toSI(Double.parseDouble(fields[5])));
stateVectorBlock.setV(2, Unit.KILOMETRE.toSI(Double.parseDouble(fields[6])));
stateVectorBlock.setV(0, Units.KM_PER_S.toSI(Double.parseDouble(fields[4])));
stateVectorBlock.setV(1, Units.KM_PER_S.toSI(Double.parseDouble(fields[5])));
stateVectorBlock.setV(2, Units.KM_PER_S.toSI(Double.parseDouble(fields[6])));
if (fields.length == 10) {
stateVectorBlock.setA(0, Unit.KILOMETRE.toSI(Double.parseDouble(fields[7])));
stateVectorBlock.setA(1, Unit.KILOMETRE.toSI(Double.parseDouble(fields[8])));
stateVectorBlock.setA(2, Unit.KILOMETRE.toSI(Double.parseDouble(fields[9])));
stateVectorBlock.setA(0, Units.KM_PER_S2.toSI(Double.parseDouble(fields[7])));
stateVectorBlock.setA(1, Units.KM_PER_S2.toSI(Double.parseDouble(fields[8])));
stateVectorBlock.setA(2, Units.KM_PER_S2.toSI(Double.parseDouble(fields[9])));
}
return currentBlock.addData(stateVectorBlock.toTimeStampedPVCoordinates(),
stateVectorBlock.hasAcceleration());
......
......@@ -24,7 +24,6 @@ import java.util.Map;
import org.hipparchus.linear.RealMatrix;
import org.orekit.data.DataContext;
import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitInternalError;
import org.orekit.errors.OrekitMessages;
import org.orekit.files.ccsds.definitions.TimeConverter;
import org.orekit.files.ccsds.definitions.TimeSystem;
......@@ -34,6 +33,7 @@ import org.orekit.files.ccsds.ndm.odm.CartesianCovariance;
import org.orekit.files.ccsds.ndm.odm.CartesianCovarianceKey;
import org.orekit.files.ccsds.ndm.odm.CommonMetadataKey;
import org.orekit.files.ccsds.ndm.odm.OdmMetadataKey;
import org.orekit.files.ccsds.ndm.odm.StateVectorKey;
import org.orekit.files.ccsds.section.Header;
import org.orekit.files.ccsds.section.HeaderKey;
import org.orekit.files.ccsds.section.KvnStructureKey;
......@@ -244,6 +244,8 @@ public class OemWriter extends AbstractMessageWriter<Header, OemSegment, OemFile
final OemMetadata metadata = segment.getMetadata();
writeMetadata(generator, metadata);
startData(generator);
// write data comments
generator.writeComments(segment.getData().getComments());
......@@ -260,6 +262,8 @@ public class OemWriter extends AbstractMessageWriter<Header, OemSegment, OemFile
// output covariance data
writeCovariances(generator, segment.getMetadata(), segment.getData().getCovarianceMatrices());
endData(generator);
}
/** Write an ephemeris segment metadata.
......@@ -331,38 +335,65 @@ public class OemWriter extends AbstractMessageWriter<Header, OemSegment, OemFile
final boolean useAcceleration)
throws IOException {
// Epoch
generator.writeRawData(generator.dateToString(getTimeConverter(), coordinates.getDate()));
// Position data in km
generator.writeRawData(' ');
generator.writeRawData(String.format(AccurateFormatter.format(Unit.KILOMETRE.fromSI(coordinates.getPosition().getX()))));
generator.writeRawData(' ');
generator.writeRawData(String.format(AccurateFormatter.format(Unit.KILOMETRE.fromSI(coordinates.getPosition().getY()))));
generator.writeRawData(' ');
generator.writeRawData(String.format(AccurateFormatter.format(Unit.KILOMETRE.fromSI(coordinates.getPosition().getZ()))));
// Velocity data in km/s
generator.writeRawData(' ');
generator.writeRawData(String.format(AccurateFormatter.format(Units.KM_PER_S.fromSI(coordinates.getVelocity().getX()))));
generator.writeRawData(' ');
generator.writeRawData(String.format(AccurateFormatter.format(Units.KM_PER_S.fromSI(coordinates.getVelocity().getY()))));
generator.writeRawData(' ');
generator.writeRawData(String.format(AccurateFormatter.format(Units.KM_PER_S.fromSI(coordinates.getVelocity().getZ()))));
// Acceleration data in km/s²
if (useAcceleration) {
if (generator.getFormat() == FileFormat.KVN) {
// Epoch
generator.writeRawData(generator.dateToString(getTimeConverter(), coordinates.getDate()));
// Position data in km
generator.writeRawData(' ');
generator.writeRawData(String.format(AccurateFormatter.format(Units.KM_PER_S2.fromSI(coordinates.getAcceleration().getX()))));
generator.writeRawData(String.format(AccurateFormatter.format(Unit.KILOMETRE.fromSI(coordinates.getPosition().getX()))));
generator.writeRawData(' ');
generator.writeRawData(String.format(AccurateFormatter.format(Units.KM_PER_S2.fromSI(coordinates.getAcceleration().getY()))));
generator.writeRawData(String.format(AccurateFormatter.format(Unit.KILOMETRE.fromSI(coordinates.getPosition().getY()))));
generator.writeRawData(' ');
generator.writeRawData(String.format(AccurateFormatter.format(Units.KM_PER_S2.fromSI(coordinates.getAcceleration().getZ()))));
}
generator.writeRawData(String.format(AccurateFormatter.format(Unit.KILOMETRE.fromSI(coordinates.getPosition().getZ()))));
// end the line
generator.newLine();
// Velocity data in km/s
generator.writeRawData(' ');
generator.writeRawData(String.format(AccurateFormatter.format(Units.KM_PER_S.fromSI(coordinates.getVelocity().getX()))));
generator.writeRawData(' ');
generator.writeRawData(String.format(AccurateFormatter.format(Units.KM_PER_S.fromSI(coordinates.getVelocity().getY()))));
generator.writeRawData(' ');
generator.writeRawData(String.format(AccurateFormatter.format(Units.KM_PER_S.fromSI(coordinates.getVelocity().getZ()))));
// Acceleration data in km/s²
if (useAcceleration) {
generator.writeRawData(' ');
generator.writeRawData(String.format(AccurateFormatter.format(Units.KM_PER_S2.fromSI(coordinates.getAcceleration().getX()))));
generator.writeRawData(' ');
generator.writeRawData(String.format(AccurateFormatter.format(Units.KM_PER_S2.fromSI(coordinates.getAcceleration().getY()))));
generator.writeRawData(' ');
generator.writeRawData(String.format(AccurateFormatter.format(Units.KM_PER_S2.fromSI(coordinates.getAcceleration().getZ()))));
}
// end the line
generator.newLine();
} else {
generator.enterSection(OemDataSubStructureKey.stateVector.name());
// Epoch
generator.writeEntry(StateVectorKey.EPOCH.name(), getTimeConverter(), coordinates.getDate(), true);
// Position data in km
generator.writeEntry(StateVectorKey.X.name(), coordinates.getPosition().getX(), Unit.KILOMETRE, true);
generator.writeEntry(StateVectorKey.Y.name(), coordinates.getPosition().getY(), Unit.KILOMETRE, true);
generator.writeEntry(StateVectorKey.Z.name(), coordinates.getPosition().getZ(), Unit.KILOMETRE, true);
// Velocity data in km/s
generator.writeEntry(StateVectorKey.X_DOT.name(), coordinates.getVelocity().getX(), Units.KM_PER_S, true);
generator.writeEntry(StateVectorKey.Y_DOT.name(), coordinates.getVelocity().getY(), Units.KM_PER_S, true);
generator.writeEntry(StateVectorKey.Z_DOT.name(), coordinates.getVelocity().getZ(), Units.KM_PER_S, true);
// Acceleration data in km/s²
if (useAcceleration) {
generator.writeEntry(StateVectorKey.X_DDOT.name(), coordinates.getAcceleration().getX(), Units.KM_PER_S2, true);
generator.writeEntry(StateVectorKey.Y_DDOT.name(), coordinates.getAcceleration().getY(), Units.KM_PER_S2, true);
generator.writeEntry(StateVectorKey.Z_DDOT.name(), coordinates.getAcceleration().getZ(), Units.KM_PER_S2, true);
}
generator.exitSection();
}
}
/**
......@@ -377,24 +408,19 @@ public class OemWriter extends AbstractMessageWriter<Header, OemSegment, OemFile
throws IOException {
if (covariances != null && !covariances.isEmpty()) {
// enter the section
if (generator.getFormat() == FileFormat.XML) {
generator.enterSection(OemDataSubStructureKey.covarianceMatrix.name());
} else {
// enter the global covariance section in KVN
if (generator.getFormat() == FileFormat.KVN) {
generator.enterSection(OemDataSubStructureKey.COVARIANCE.name());
}
boolean continuation = false;
for (final CartesianCovariance covariance : covariances) {
if (continuation) {
generator.newLine();
}
writeCovariance(generator, metadata, covariance);
continuation = true;
}
// exit the section
generator.exitSection();
// exit the global covariance section in KVN
if (generator.getFormat() == FileFormat.KVN) {
generator.exitSection();
}
}
}
......@@ -409,16 +435,23 @@ public class OemWriter extends AbstractMessageWriter<Header, OemSegment, OemFile
private void writeCovariance(final Generator generator, final OemMetadata metadata,
final CartesianCovariance covariance)
throws IOException {
// wrapper for a single matrix in XML
if (generator.getFormat() == FileFormat.XML) {
generator.enterSection(OemDataSubStructureKey.covarianceMatrix.name());
}
// epoch
generator.writeEntry(CartesianCovarianceKey.EPOCH.name(), getTimeConverter(), covariance.getEpoch(), true);
// reference frame
if (covariance.getReferenceFrame() != metadata.getReferenceFrame()) {
generator.writeEntry(CartesianCovarianceKey.COV_REF_FRAME.name(), covariance.getReferenceFrame().getName(), null, false);
}
// matrix data
final RealMatrix m = covariance.getCovarianceMatrix();
if (generator.getFormat() == FileFormat.KVN) {
generator.writeEntry(CartesianCovarianceKey.EPOCH.name(),
getTimeConverter(), covariance.getEpoch(),
true);
if (covariance.getReferenceFrame() != metadata.getReferenceFrame()) {
generator.writeEntry(CartesianCovarianceKey.COV_REF_FRAME.name(),
covariance.getReferenceFrame().getName(),
null, false);
}
final RealMatrix m = covariance.getCovarianceMatrix();
for (int i = 0; i < m.getRowDimension(); ++i) {
// write triangular matrix entries
......@@ -434,9 +467,34 @@ public class OemWriter extends AbstractMessageWriter<Header, OemSegment, OemFile
}
} else {
// TODO: write covariance in OEM XML files
throw new OrekitInternalError(null);
generator.writeEntry(CartesianCovarianceKey.CX_X.name(), m.getEntry(0, 0), Units.KM2, true);
generator.writeEntry(CartesianCovarianceKey.CY_X.name(), m.getEntry(1, 0), Units.KM2, true);
generator.writeEntry(CartesianCovarianceKey.CY_Y.name(), m.getEntry(1, 1), Units.KM2, true);
generator.writeEntry(CartesianCovarianceKey.CZ_X.name(), m.getEntry(2, 0), Units.KM2, true);
generator.writeEntry(CartesianCovarianceKey.CZ_Y.name(), m.getEntry(2, 1), Units.KM2, true);
generator.writeEntry(CartesianCovarianceKey.CZ_Z.name(), m.getEntry(2, 2), Units.KM2, true);
generator.writeEntry(CartesianCovarianceKey.CX_DOT_X.name(), m.getEntry(3, 0), Units.KM2_PER_S, true);
generator.writeEntry(CartesianCovarianceKey.CX_DOT_Y.name(), m.getEntry(3, 1), Units.KM2_PER_S, true);
generator.writeEntry(CartesianCovarianceKey.CX_DOT_Z.name(), m.getEntry(3, 2), Units.KM2_PER_S, true);
generator.writeEntry(CartesianCovarianceKey.CX_DOT_X_DOT.name(), m.getEntry(3, 3), Units.KM2_PER_S2, true);
generator.writeEntry(CartesianCovarianceKey.CY_DOT_X.name(), m.getEntry(4, 0), Units.KM2_PER_S, true);
generator.writeEntry(CartesianCovarianceKey.CY_DOT_Y.name(), m.getEntry(4, 1), Units.KM2_PER_S, true);
generator.writeEntry(CartesianCovarianceKey.CY_DOT_Z.name(), m.getEntry(4, 2), Units.KM2_PER_S, true);
generator.writeEntry(CartesianCovarianceKey.CY_DOT_X_DOT.name(), m.getEntry(4, 3), Units.KM2_PER_S2, true);
generator.writeEntry(CartesianCovarianceKey.CY_DOT_Y_DOT.name(), m.getEntry(4, 4), Units.KM2_PER_S2, true);
generator.writeEntry(CartesianCovarianceKey.CZ_DOT_X.name(), m.getEntry(5, 0), Units.KM2_PER_S, true);
generator.writeEntry(CartesianCovarianceKey.CZ_DOT_Y.name(), m.getEntry(5, 1), Units.KM2_PER_S, true);
generator.writeEntry(CartesianCovarianceKey.CZ_DOT_Z.name(), m.getEntry(5, 2), Units.KM2_PER_S, true);
generator.writeEntry(CartesianCovarianceKey.CZ_DOT_X_DOT.name(), m.getEntry(5, 3), Units.KM2_PER_S2, true);
generator.writeEntry(CartesianCovarianceKey.CZ_DOT_Y_DOT.name(), m.getEntry(5, 4), Units.KM2_PER_S2, true);
generator.writeEntry(CartesianCovarianceKey.CZ_DOT_Z_DOT.name(), m.getEntry(5, 5), Units.KM2_PER_S2, true);
}
// wrapper for a single matrix in XML
if (generator.getFormat() == FileFormat.XML) {
generator.exitSection();
}
}
/** Start of a data block.
......
......@@ -36,6 +36,8 @@ import org.junit.Assert;
import org.junit.Before;
import org.orekit.Utils;
import org.orekit.data.DataSource;
import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitMessages;
import org.orekit.files.ccsds.definitions.BodyFacade;
import org.orekit.files.ccsds.definitions.FrameFacade;
import org.orekit.files.ccsds.definitions.OdMethodFacade;
......@@ -207,11 +209,15 @@ public abstract class AbstractNdmWriterTest<H extends Header, S extends Segment<
m.getParameterCount() == 0).
forEach(getter -> {
try {
if (!recurseCheck(getter.invoke(original), getter.invoke(rebuilt))) {
System.out.println("eeee");
}
Assert.assertTrue(recurseCheck(getter.invoke(original), getter.invoke(rebuilt)));
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
} catch (InvocationTargetException e) {
if (!(getter.getName().equals("getFrame") &&
e.getCause() instanceof OrekitException &&
((OrekitException) e.getCause()).getSpecifier() ==
OrekitMessages.NO_DATA_LOADED_FOR_CELESTIAL_BODY)) {
Assert.fail(e.getCause().getLocalizedMessage());
}
} catch (IllegalAccessException | IllegalArgumentException e) {
Assert.fail(e.getLocalizedMessage());
}
});
......
......@@ -109,7 +109,6 @@ public class OemParserTest {
CelestialBodyFactory.getEarth().getGM());
Assert.assertArrayEquals(orbit.getPVCoordinates().getPosition().toArray(), file.getSegments().get(0).getData().getEphemeridesDataLines().get(0).getPosition().toArray(), 1e-10);
Assert.assertArrayEquals(orbit.getPVCoordinates().getVelocity().toArray(), file.getSegments().get(0).getData().getEphemeridesDataLines().get(0).getVelocity().toArray(), 1e-10);
Assert.assertArrayEquals((new Vector3D(1, 1, 1)).toArray(), file.getSegments().get(1).getData().getEphemeridesDataLines().get(0).getAcceleration().toArray(), 1e-10);
Assert.assertEquals(Vector3D.ZERO, file.getSegments().get(1).getData().getEphemeridesDataLines().get(1).getAcceleration());
final Array2DRowRealMatrix covMatrix = new Array2DRowRealMatrix(6, 6);
final double[] column1 = {
......
/* Copyright 2002-2021 CS GROUP
* Licensed to CS GROUP (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.ndm.odm.oem;
import org.junit.Test;
import org.orekit.files.ccsds.ndm.AbstractNdmWriterTest;
import org.orekit.files.ccsds.ndm.ParsedUnitsBehavior;
import org.orekit.files.ccsds.ndm.ParserBuilder;
import org.orekit.files.ccsds.ndm.WriterBuilder;
import org.orekit.files.ccsds.section.Header;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.Constants;
public class OemWriterTest extends AbstractNdmWriterTest<Header, OemSegment, OemFile> {
protected OemParser getParser() {
return new ParserBuilder().
withMu(Constants.EIGEN5C_EARTH_MU).
withMissionReferenceDate(new AbsoluteDate("1996-12-17T00:00:00.000", TimeScalesFactory.getUTC())).
withParsedUnitsBehavior(ParsedUnitsBehavior.STRICT_COMPLIANCE).
buildOemParser();
}
protected OemWriter getWriter() {
return new WriterBuilder().buildOemWriter();
}
@Test
public void testWriteExample1() {
doTest("/ccsds/odm/oem/OEMExample1.txt");
}
@Test
public void testWriteExample2() {
doTest("/ccsds/odm/oem/OEMExample2.txt");
}
@Test
public void testWriteKvnExample3() {
doTest("/ccsds/odm/oem/OEMExample3.txt");
}
@Test
public void testWriteXmlExample3() {
doTest("/ccsds/odm/oem/OEMExample3.txt");
}
@Test
public void testWriteExample4() {
doTest("/ccsds/odm/oem/OEMExample4.txt");
}
@Test
public void testWriteExample5() {
doTest("/ccsds/odm/oem/OEMExample5.txt");
}
@Test
public void testWriteExample6() {
doTest("/ccsds/odm/oem/OEMExample6.txt");
}
@Test
public void testWriteExample8() {
doTest("/ccsds/odm/oem/OEMExample8.txt");
}
}
......@@ -41,7 +41,7 @@ META_STOP
COMMENT This block begins after trajectory correction maneuver TCM-3.
1996-12-28T21:29:07.267 -2432.166 -063.042 1742.754 7.33702 -3.495867 -1.041945 0.001 0.001 0.001
1996-12-28T21:29:07.267 -2432.166 -063.042 1742.754 7.33702 -3.495867 -1.041945
1996-12-28T21:59:02.267 -2445.234 -878.141 1873.073 1.86043 -3.421256 -0.996366
1996-12-28T22:00:02.267 -2458.079 -683.858 2007.684 6.36786 -3.339563 -0.946654
1996-12-30T01:28:02.267 2164.375 1115.811 -688.131 -3.53328 -2.88452 0.88535
......
......@@ -40,7 +40,7 @@ INTERPOLATION_DEGREE = 2
META_STOP
COMMENT This block begins after trajectory correction maneuver TCM-3.
1996-12-28T21:29:07.267 -2432.166 -063.042 1742.754 7.33702 -3.495867 -1.041945 0.001 0.001 0.001
1996-12-28T21:29:07.267 -2432.166 -063.042 1742.754 7.33702 -3.495867 -1.041945 0.0 0.0 0.0
1996-12-28T21:59:02.267 -2445.234 -878.141 1873.073 1.86043 -3.421256 -0.996366
1996-12-28T22:00:02.267 -2458.079 -683.858 2007.684 6.36786 -3.339563 -0.946654
......
......@@ -33,7 +33,7 @@ STOP_TIME = 2002-12-30T01:28:02.267
META_STOP
COMMENT This block begins after trajectory correction maneuver TCM-3.
2002-12-28T21:29:07.267 -2432.166 -063.042 1742.754 7.33702 -3.495867 -1.041945 0.001 0.001 0.001
2002-12-28T21:29:07.267 -2432.166 -063.042 1742.754 7.33702 -3.495867 -1.041945 0.0 0.0 0.0
2002-12-28T21:59:02.267 -2445.234 -878.141 1873.073 1.86043 -3.421256 -0.996366
2002-12-28T22:00:02.267 -2458.079 -683.858 2007.684 6.36786 -3.339563 -0.946654
......
......@@ -39,7 +39,7 @@ INTERPOLATION_DEGREE = 7
META_STOP
COMMENT This block begins after trajectory correction maneuver TCM-3.
1996-12-28T21:29:07.267 -2432.166 -063.042 1742.754 7.33702 -3.495867 -1.041945 0.001 0.001 0.001
1996-12-28T21:29:07.267 -2432.166 -063.042 1742.754 7.33702 -3.495867 -1.041945
1996-12-28T21:59:02.267 -2445.234 -878.141 1873.073 1.86043 -3.421256 -0.996366
1996-12-28T22:00:02.267 -2458.079 -683.858 2007.684 6.36786 -3.339563 -0.946654
1996-12-30T01:28:02.267 2164.375 1115.811 -688.131 -3.53328 -2.88452 0.88535
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment