Commit 9e3437df authored by Luc Maisonobe's avatar Luc Maisonobe
Browse files

Updated CCSDS ODM parsing according to changes in latest draft.

parent 5c2c79c2
......@@ -28,8 +28,8 @@ import org.orekit.files.ccsds.section.Data;
*/
public class OcmData implements Data {
/** Orbit state histories logical blocks. */
private final List<OrbitStateHistory> orbitBlocks;
/** Trajectory state histories logical blocks. */
private final List<TrajectoryStateHistory> trajectoryBlocks;
/** Physical properties logical block. */
private final PhysicalProperties physicBlock;
......@@ -50,7 +50,7 @@ public class OcmData implements Data {
private final UserDefined userDefinedBlock;
/** Simple constructor.
* @param orbitBlocks orbital state histories logical blocks (may be empty)
* @param trajectoryBlocks trajectory state histories logical blocks (may be empty)
* @param physicBlock physical properties logical block (may be null)
* @param covarianceBlocks covariance logical blocks (may be empty)
* @param maneuverBlocks maneuvers logical blocks (may be empty)
......@@ -58,14 +58,14 @@ public class OcmData implements Data {
* @param orbitDeterminationBlock orbit determination logical block (may be null)
* @param userDefinedBlock user defined parameters logical block (may be null)
*/
public OcmData(final List<OrbitStateHistory> orbitBlocks,
final PhysicalProperties physicBlock,
final List<CovarianceHistory> covarianceBlocks,
final List<ManeuverHistory> maneuverBlocks,
final Perturbations perturbationsBlock,
final OrbitDetermination orbitDeterminationBlock,
final UserDefined userDefinedBlock) {
this.orbitBlocks = orbitBlocks;
public OcmData(final List<TrajectoryStateHistory> trajectoryBlocks,
final PhysicalProperties physicBlock,
final List<CovarianceHistory> covarianceBlocks,
final List<ManeuverHistory> maneuverBlocks,
final Perturbations perturbationsBlock,
final OrbitDetermination orbitDeterminationBlock,
final UserDefined userDefinedBlock) {
this.trajectoryBlocks = trajectoryBlocks;
this.physicBlock = physicBlock;
this.covarianceBlocks = covarianceBlocks;
this.maneuverBlocks = maneuverBlocks;
......@@ -77,8 +77,8 @@ public class OcmData implements Data {
/** {@inheritDoc} */
@Override
public void validate(final double version) {
if (orbitBlocks != null) {
for (final OrbitStateHistory osh : orbitBlocks) {
if (trajectoryBlocks != null) {
for (final TrajectoryStateHistory osh : trajectoryBlocks) {
osh.getMetadata().validate(version);
}
}
......@@ -106,11 +106,11 @@ public class OcmData implements Data {
}
}
/** Get orbit state histories logical blocks.
* @return orbita state histories logical blocks (may be null)
/** Get trajectory state histories logical blocks.
* @return trajectory state histories logical blocks (may be null)
*/
public List<OrbitStateHistory> getOrbitBlocks() {
return orbitBlocks;
public List<TrajectoryStateHistory> getOTrajectoryBlocks() {
return trajectoryBlocks;
}
/** Get physical properties logical block.
......
......@@ -25,11 +25,11 @@ import org.orekit.files.ccsds.utils.lexical.TokenType;
*/
public enum OcmDataSubStructureKey {
/** Orbit state time history section. */
ORB((token, parser) -> parser.manageOrbitStateSection(token.getType() == TokenType.START)),
/** Trajectory state time history section. */
TRAJ((token, parser) -> parser.manageTrajectoryStateSection(token.getType() == TokenType.START)),
/** Orbit state time history section. */
orb((token, parser) -> parser.manageOrbitStateSection(token.getType() == TokenType.START)),
/** Trajectory state time history section. */
orb((token, parser) -> parser.manageTrajectoryStateSection(token.getType() == TokenType.START)),
/** Physical properties section. */
PHYS((token, parser) -> parser.managePhysicalPropertiesSection(token.getType() == TokenType.START)),
......
......@@ -34,7 +34,7 @@ import org.orekit.utils.TimeStampedPVCoordinates;
* @since 11.0
*/
public class OcmFile extends NdmConstituent<Header, Segment<OcmMetadata, OcmData>>
implements EphemerisFile<TimeStampedPVCoordinates, OrbitStateHistory> {
implements EphemerisFile<TimeStampedPVCoordinates, TrajectoryStateHistory> {
/** Root element for XML messages. */
public static final String ROOT = "ocm";
......@@ -113,7 +113,7 @@ public class OcmFile extends NdmConstituent<Header, Segment<OcmMetadata, OcmData
} else {
name = UNKNOWN_OBJECT;
}
final List<OrbitStateHistory> histories = getSegments().get(0).getData().getOrbitBlocks();
final List<TrajectoryStateHistory> histories = getSegments().get(0).getData().getOTrajectoryBlocks();
final OcmSatelliteEphemeris ose = new OcmSatelliteEphemeris(name, mu, histories);
return Collections.singletonMap(name, ose);
}
......
......@@ -76,14 +76,14 @@ public class OcmParser extends OdmParser<OcmFile, OcmParser> implements Ephemeri
/** Context binding valid for current metadata. */
private ContextBinding context;
/** Orbital state histories logical blocks. */
private List<OrbitStateHistory> orbitBlocks;
/** Trajectory state histories logical blocks. */
private List<TrajectoryStateHistory> trajectoryBlocks;
/** Current orbit state metadata. */
private OrbitStateHistoryMetadata currentOrbitStateHistoryMetadata;
/** Current trajectory state metadata. */
private TrajectoryStateHistoryMetadata currentTrajectoryStateHistoryMetadata;
/** Current orbit state time history being read. */
private List<OrbitState> currentOrbitStateHistory;
/** Current trajectory state time history being read. */
private List<TrajectoryState> currentTrajectoryStateHistory;
/** Physical properties logical block. */
private PhysicalProperties physicBlock;
......@@ -167,7 +167,7 @@ public class OcmParser extends OdmParser<OcmFile, OcmParser> implements Ephemeri
header = new Header(3.0);
metadata = null;
context = null;
orbitBlocks = null;
trajectoryBlocks = null;
physicBlock = null;
covarianceBlocks = null;
maneuverBlocks = null;
......@@ -250,41 +250,41 @@ public class OcmParser extends OdmParser<OcmFile, OcmParser> implements Ephemeri
@Override
public boolean finalizeData() {
// fix gravitational parameter now that all sections have been completed
final List<OrbitStateHistory> old = orbitBlocks;
final List<TrajectoryStateHistory> old = trajectoryBlocks;
if (old != null) {
orbitBlocks = new ArrayList<>(old.size());
for (final OrbitStateHistory osh : old) {
orbitBlocks.add(new OrbitStateHistory(osh.getMetadata(), osh.getOrbitalStates(), getSelectedMu()));
trajectoryBlocks = new ArrayList<>(old.size());
for (final TrajectoryStateHistory osh : old) {
trajectoryBlocks.add(new TrajectoryStateHistory(osh.getMetadata(), osh.getTrajectoryStates(), getSelectedMu()));
}
}
return true;
}
/** Manage orbit state history section.
/** Manage trajectory state history section.
* @param starting if true, parser is entering the section
* otherwise it is leaving the section
* @return always return true
*/
boolean manageOrbitStateSection(final boolean starting) {
boolean manageTrajectoryStateSection(final boolean starting) {
if (starting) {
if (orbitBlocks == null) {
// this is the first orbit block, we need to allocate the container
orbitBlocks = new ArrayList<>();
if (trajectoryBlocks == null) {
// this is the first trajectory block, we need to allocate the container
trajectoryBlocks = new ArrayList<>();
}
currentOrbitStateHistoryMetadata = new OrbitStateHistoryMetadata(metadata.getEpochT0(),
getDataContext());
currentOrbitStateHistory = new ArrayList<>();
anticipateNext(this::processOrbitStateToken);
currentTrajectoryStateHistoryMetadata = new TrajectoryStateHistoryMetadata(metadata.getEpochT0(),
getDataContext());
currentTrajectoryStateHistory = new ArrayList<>();
anticipateNext(this::processTrajectoryStateToken);
} else {
anticipateNext(structureProcessor);
if (currentOrbitStateHistoryMetadata.getCenter().getBody() != null) {
setMuCreated(currentOrbitStateHistoryMetadata.getCenter().getBody().getGM());
if (currentTrajectoryStateHistoryMetadata.getCenter().getBody() != null) {
setMuCreated(currentTrajectoryStateHistoryMetadata.getCenter().getBody().getGM());
}
// we temporarily set gravitational parameter to NaN,
// as we may get a proper one in the perturbations section
orbitBlocks.add(new OrbitStateHistory(currentOrbitStateHistoryMetadata,
currentOrbitStateHistory,
Double.NaN));
trajectoryBlocks.add(new TrajectoryStateHistory(currentTrajectoryStateHistoryMetadata,
currentTrajectoryStateHistory,
Double.NaN));
}
return true;
}
......@@ -422,7 +422,7 @@ public class OcmParser extends OdmParser<OcmFile, OcmParser> implements Ephemeri
// this may be Double.NaN, but it will be handled correctly
setMuParsed(perturbationsBlock.getGm());
}
final OcmData data = new OcmData(orbitBlocks, physicBlock, covarianceBlocks,
final OcmData data = new OcmData(trajectoryBlocks, physicBlock, covarianceBlocks,
maneuverBlocks, perturbationsBlock,
orbitDeterminationBlock, userDefinedBlock);
data.validate(header.getFormatVersion());
......@@ -467,25 +467,25 @@ public class OcmParser extends OdmParser<OcmFile, OcmParser> implements Ephemeri
}
}
/** Process one orbit state history data token.
/** Process one trajectory state history data token.
* @param token token to process
* @return true if token was processed, false otherwise
*/
private boolean processOrbitStateToken(final ParseToken token) {
private boolean processTrajectoryStateToken(final ParseToken token) {
if (token.getName() != null && !token.getName().equals(OcmFile.ORB_LINE)) {
// we are in the section metadata part
try {
return OrbitStateHistoryMetadataKey.valueOf(token.getName()).
process(token, context, currentOrbitStateHistoryMetadata);
return TrajectoryStateHistoryMetadataKey.valueOf(token.getName()).
process(token, context, currentTrajectoryStateHistoryMetadata);
} catch (IllegalArgumentException iae) {
// token has not been recognized
return false;
}
} else {
// we are in the section data part
if (currentOrbitStateHistory.isEmpty()) {
if (currentTrajectoryStateHistory.isEmpty()) {
// we are starting the real data section, we can now check metadata is complete
currentOrbitStateHistoryMetadata.validate(header.getFormatVersion());
currentTrajectoryStateHistoryMetadata.validate(header.getFormatVersion());
anticipateNext(this::processDataSubStructureToken);
}
if (token.getType() == TokenType.START || token.getType() == TokenType.STOP) {
......@@ -493,14 +493,14 @@ public class OcmParser extends OdmParser<OcmFile, OcmParser> implements Ephemeri
}
try {
final String[] fields = SPLIT_AT_BLANKS.split(token.getRawContent().trim());
// as ORB_UNITS is optional and indeed MUST match type, get them directly from type
final List<Unit> units = currentOrbitStateHistoryMetadata.getOrbType().getUnits();
// as TRAJ_UNITS is optional and indeed MUST match type, get them directly from type
final List<Unit> units = currentTrajectoryStateHistoryMetadata.getTrajType().getUnits();
if (fields.length != units.size() + 1) {
throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
token.getLineNumber(), token.getFileName(), token.getContentAsNormalizedString());
}
final AbsoluteDate epoch = context.getTimeSystem().getConverter(context).parse(fields[0]);
return currentOrbitStateHistory.add(new OrbitState(currentOrbitStateHistoryMetadata.getOrbType(),
return currentTrajectoryStateHistory.add(new TrajectoryState(currentTrajectoryStateHistoryMetadata.getTrajType(),
epoch, fields, 1, units));
} catch (NumberFormatException | OrekitIllegalArgumentException e) {
throw new OrekitException(e, OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
......
......@@ -29,7 +29,7 @@ import org.orekit.utils.TimeStampedPVCoordinates;
* @since 11.0
*/
public class OcmSatelliteEphemeris
implements EphemerisFile.SatelliteEphemeris<TimeStampedPVCoordinates, OrbitStateHistory> {
implements EphemerisFile.SatelliteEphemeris<TimeStampedPVCoordinates, TrajectoryStateHistory> {
/** Name of the object. */
private final String name;
......@@ -38,7 +38,7 @@ public class OcmSatelliteEphemeris
private final double mu;
/** The ephemeris data for the satellite. */
private final List<OrbitStateHistory> blocks;
private final List<TrajectoryStateHistory> blocks;
/**
* Create a container for the set of ephemeris blocks in the file that pertain to
......@@ -48,7 +48,7 @@ public class OcmSatelliteEphemeris
* @param mu gravitational coefficient to use for building Cartesian/Keplerian orbits
* @param blocks containing ephemeris data for the satellite.
*/
public OcmSatelliteEphemeris(final String name, final double mu, final List<OrbitStateHistory> blocks) {
public OcmSatelliteEphemeris(final String name, final double mu, final List<TrajectoryStateHistory> blocks) {
this.name = name;
this.mu = mu;
this.blocks = blocks;
......@@ -68,7 +68,7 @@ public class OcmSatelliteEphemeris
/** {@inheritDoc} */
@Override
public List<OrbitStateHistory> getSegments() {
public List<TrajectoryStateHistory> getSegments() {
return Collections.unmodifiableList(blocks);
}
......
......@@ -88,11 +88,11 @@ public class OcmWriter extends AbstractMessageWriter<Header, Segment<OcmMetadata
generator.enterSection(XmlStructureKey.data.name());
}
// orbit history
if (segment.getData().getOrbitBlocks() != null && !segment.getData().getOrbitBlocks().isEmpty()) {
for (final OrbitStateHistory history : segment.getData().getOrbitBlocks()) {
// write optional orbits history block
new OrbitStateHistoryWriter(history, getTimeConverter()).write(generator);
// trajectory history
if (segment.getData().getOTrajectoryBlocks() != null && !segment.getData().getOTrajectoryBlocks().isEmpty()) {
for (final TrajectoryStateHistory history : segment.getData().getOTrajectoryBlocks()) {
// write optional trajectory history block
new TrajectoryStateHistoryWriter(history, getTimeConverter()).write(generator);
}
}
......
......@@ -26,11 +26,11 @@ import org.orekit.utils.CartesianDerivativesFilter;
import org.orekit.utils.TimeStampedPVCoordinates;
import org.orekit.utils.units.Unit;
/** Orbit state entry.
/** Trajectory state entry.
* @author Luc Maisonobe
* @since 11.0
*/
public class OrbitState implements TimeStamped {
public class TrajectoryState implements TimeStamped {
/** Type of the elements. */
private final ElementsType type;
......@@ -38,18 +38,18 @@ public class OrbitState implements TimeStamped {
/** Entry date. */
private final AbsoluteDate date;
/** Orbital elements. */
/** Trajectory elements. */
private final double[] elements;
/** Simple constructor.
* @param type type of the elements
* @param date entry date
* @param fields orbital elements
* @param fields trajectory elements
* @param first index of first field to consider
* @param units units to use for parsing
*/
public OrbitState(final ElementsType type, final AbsoluteDate date,
final String[] fields, final int first, final List<Unit> units) {
public TrajectoryState(final ElementsType type, final AbsoluteDate date,
final String[] fields, final int first, final List<Unit> units) {
this.type = type;
this.date = date;
this.elements = new double[units.size()];
......@@ -64,8 +64,8 @@ public class OrbitState implements TimeStamped {
return date;
}
/** Get orbital elements.
* @return orbital elements
/** Get trajectory elements.
* @return trajectory elements
*/
public double[] getElements() {
return elements.clone();
......
......@@ -29,17 +29,17 @@ import org.orekit.time.AbsoluteDate;
import org.orekit.utils.CartesianDerivativesFilter;
import org.orekit.utils.TimeStampedPVCoordinates;
/** Orbit state history.
/** Trajectory state history.
* @author Luc Maisonobe
* @since 11.0
*/
public class OrbitStateHistory implements EphemerisFile.EphemerisSegment<TimeStampedPVCoordinates> {
public class TrajectoryStateHistory implements EphemerisFile.EphemerisSegment<TimeStampedPVCoordinates> {
/** Metadata. */
private final OrbitStateHistoryMetadata metadata;
private final TrajectoryStateHistoryMetadata metadata;
/** Orbital states. */
private final List<OrbitState> states;
/** Trajectory states. */
private final List<TrajectoryState> states;
/** Gravitational parameter in m³/s². */
private final double mu;
......@@ -49,8 +49,8 @@ public class OrbitStateHistory implements EphemerisFile.EphemerisSegment<TimeSta
* @param states orbital states
* @param mu gravitational parameter in m³/s²
*/
OrbitStateHistory(final OrbitStateHistoryMetadata metadata,
final List<OrbitState> states,
TrajectoryStateHistory(final TrajectoryStateHistoryMetadata metadata,
final List<TrajectoryState> states,
final double mu) {
this.metadata = metadata;
this.states = states;
......@@ -60,14 +60,14 @@ public class OrbitStateHistory implements EphemerisFile.EphemerisSegment<TimeSta
/** Get metadata.
* @return metadata
*/
public OrbitStateHistoryMetadata getMetadata() {
public TrajectoryStateHistoryMetadata getMetadata() {
return metadata;
}
/** Get the orbital states.
* @return orbital states
/** Get the trajectory states.
* @return trajectory states
*/
public List<OrbitState> getOrbitalStates() {
public List<TrajectoryState> getTrajectoryStates() {
return Collections.unmodifiableList(states);
}
......@@ -80,10 +80,10 @@ public class OrbitStateHistory implements EphemerisFile.EphemerisSegment<TimeSta
/** {@inheritDoc} */
@Override
public Frame getFrame() {
final Frame frame = metadata.getOrbReferenceFrame().asFrame();
final Frame frame = metadata.getTrajReferenceFrame().asFrame();
if (frame == null) {
throw new OrekitException(OrekitMessages.CCSDS_INVALID_FRAME,
metadata.getOrbReferenceFrame().getName());
metadata.getTrajReferenceFrame().getName());
}
return frame;
}
......
......@@ -20,6 +20,8 @@ package org.orekit.files.ccsds.ndm.odm.ocm;
import java.util.List;
import org.orekit.data.DataContext;
import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitMessages;
import org.orekit.files.ccsds.definitions.BodyFacade;
import org.orekit.files.ccsds.definitions.CelestialBodyFrame;
import org.orekit.files.ccsds.definitions.ElementsType;
......@@ -29,26 +31,26 @@ import org.orekit.files.ccsds.section.CommentsContainer;
import org.orekit.time.AbsoluteDate;
import org.orekit.utils.units.Unit;
/** Metadata for orbit state history.
/** Metadata for trajectory state history.
* @author Luc Maisonobe
* @since 11.0
*/
public class OrbitStateHistoryMetadata extends CommentsContainer {
public class TrajectoryStateHistoryMetadata extends CommentsContainer {
/** Orbit identification number. */
private String orbID;
/** Trajectory identification number. */
private String trajID;
/** Identification number of previous orbit. */
private String orbPrevID;
/** Identification number of previous trajectory. */
private String trajPrevID;
/** Identification number of next orbit. */
private String orbNextID;
/** Identification number of next trajectory. */
private String trajNextID;
/** Basis of this orbit state time history data. */
private String orbBasis;
/** Basis of this trajectory state time history data. */
private String trajBasis;
/** Identification number of the orbit determination or simulation upon which this orbit is based. */
private String orbBasisID;
/** Identification number of the orbit determination or simulation upon which this trajectory is based. */
private String trajBasisID;
/** Interpolation method. */
private InterpolationMethod interpolationMethod;
......@@ -62,11 +64,11 @@ public class OrbitStateHistoryMetadata extends CommentsContainer {
/** Origin of reference frame. */
private BodyFacade center;
/** Reference frame of the orbit. */
private FrameFacade orbReferenceFrame;
/** Reference frame of the trajectory. */
private FrameFacade trajReferenceFrame;
/** Epoch of the orbit reference frame. */
private AbsoluteDate orbFrameEpoch;
/** Epoch of the trajectory reference frame. */
private AbsoluteDate trajFrameEpoch;
/** Start of useable time span covered by ephemerides data, it may be
* necessary to allow for proper interpolation. */
......@@ -76,114 +78,126 @@ public class OrbitStateHistoryMetadata extends CommentsContainer {
* necessary to allow for proper interpolation. */
private AbsoluteDate useableStopTime;
/** Orbit element set type. */
private ElementsType orbType;
/** Integer orbit revolution number. */
private int orbRevNum;
/** Units of orbit element set. */
private List<Unit> orbUnits;
/** Basis for orbit revolution counter (i.e is first launch/deployment on orbit 0 or 1). */
private int orbRevNumBasis;
/** Trajectory element set type. */
private ElementsType trajType;
/** Units of trajectory element set. */
private List<Unit> trajUnits;
/** Simple constructor.
* @param epochT0 T0 epoch from file metadata
* @param dataContext data context
*/
OrbitStateHistoryMetadata(final AbsoluteDate epochT0, final DataContext dataContext) {
TrajectoryStateHistoryMetadata(final AbsoluteDate epochT0, final DataContext dataContext) {
// we don't call the setXxx() methods in order to avoid
// calling refuseFurtherComments as a side effect
orbBasis = "PREDICTED";
trajBasis = "PREDICTED";
interpolationMethod = InterpolationMethod.HERMITE;
interpolationDegree = 3;
orbAveraging = "OSCULATING";
center = new BodyFacade("EARTH",
dataContext.getCelestialBodies().getEarth());
orbReferenceFrame = new FrameFacade(dataContext.getFrames().getICRF(),
trajReferenceFrame = new FrameFacade(dataContext.getFrames().getICRF(),
CelestialBodyFrame.ICRF, null, null,
CelestialBodyFrame.ICRF.name());
orbFrameEpoch = epochT0;
orbType = ElementsType.CARTPV;
trajFrameEpoch = epochT0;
trajType = ElementsType.CARTPV;
orbRevNum = -1;
orbRevNumBasis = -1;
}
/** {@inheritDoc} */
@Override
public void validate(final double version) {
super.validate(version);
if (orbUnits != null) {
orbType.checkUnits(orbUnits);
if (trajUnits != null) {
trajType.checkUnits(trajUnits);
}
if (orbRevNum >= 0 && orbRevNumBasis < 0) {
throw new OrekitException(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY,
TrajectoryStateHistoryMetadataKey.ORB_REVNUM_BASIS.name());
}
}
/** Get orbit identification number.
* @return orbit identification number
/** Get trajectory identification number.
* @return trajectory identification number
*/
public String getOrbID() {
return orbID;
public String getTrajID() {
return trajID;
}
/** Set orbit identification number.
* @param orbID orbit identification number
/** Set trajectory identification number.
* @param trajID trajectory identification number
*/
public void setOrbID(final String orbID) {
public void setTrajID(final String trajID) {
refuseFurtherComments();
this.orbID = orbID;
this.trajID = trajID;
}