Commit 8395802d authored by Luc Maisonobe's avatar Luc Maisonobe
Browse files

Added support for CCSDS TDM V2.0.

Fixes #821
parent 663fcf1e
......@@ -21,6 +21,9 @@
</properties>
<body>
<release version="11.0" date="TBD" description="TBD">
<action dev="luc" type="add" issue="821">
Added support for CCSDS TDM V2.0.
</action>
<action dev="luc" type="add" issue="819">
Allow data filtering upon loading to be used for explicit loading by applications.
</action>
......
......@@ -40,6 +40,10 @@ public enum ObservationType {
* Strength of the radio signal transmitted by the spacecraft as received at the ground station or at another spacecraft.
*/
CARRIER_POWER(Unit.ONE),
/** Data: Doppler counts [n/a].<p>
* Count of signal cycles.
*/
DOPPLER_COUNT(Unit.ONE),
/** Data: Doppler instantaneous [km/s].<p>
* Instantaneous range rate of the spacecraft.
*/
......@@ -52,6 +56,26 @@ public enum ObservationType {
PC_N0(Unit.ONE),
/** Data: Ranging power to noise spectral density ratio (Pr/No) [dBHz]. */
PR_N0(Unit.ONE),
/** Data: phase cycle count at receiver. */
RECEIVE_PHASE_CT_1(Unit.ONE),
/** Data: phase cycle count at receiver. */
RECEIVE_PHASE_CT_2(Unit.ONE),
/** Data: phase cycle count at receiver. */
RECEIVE_PHASE_CT_3(Unit.ONE),
/** Data: phase cycle count at receiver. */
RECEIVE_PHASE_CT_4(Unit.ONE),
/** Data: phase cycle count at receiver. */
RECEIVE_PHASE_CT_5(Unit.ONE),
/** Data: phase cycle count at transmitter. */
TRANSMIT_PHASE_CT_1(Unit.ONE),
/** Data: phase cycle count at transmitter. */
TRANSMIT_PHASE_CT_2(Unit.ONE),
/** Data: phase cycle count at transmitter. */
TRANSMIT_PHASE_CT_3(Unit.ONE),
/** Data: phase cycle count at transmitter. */
TRANSMIT_PHASE_CT_4(Unit.ONE),
/** Data: phase cycle count at transmitter. */
TRANSMIT_PHASE_CT_5(Unit.ONE),
/** Data: Range value [km, s or RU].
* @see RangeUnits
*/
......@@ -91,7 +115,7 @@ public enum ObservationType {
},
/** Data: Received frequencies [Hz].<p>
/** Data: Received frequencies [Hz].<p>
* The RECEIVE_FREQ keyword shall be used to indicate that the values represent measurements of the received frequency.<p>
* The keyword is indexed to accommodate a scenario in which multiple downlinks are used.<p>
* RECEIVE_FREQ_n (n = 1, 2, 3, 4, 5)
......@@ -168,6 +192,12 @@ public enum ObservationType {
*/
ANGLE_2(Unit.DEGREE),
// Optical/Radar Related keywords
/** Data: visual magnitude. */
MAG(Unit.ONE),
/** Data: Radar Cross section [m²]. */
RCS(Units.M2),
// Time Related Keywords
/** Data: Clock bias [s].<p>
* The CLOCK_BIAS keyword can be used by the message recipient to adjust timetag
......
......@@ -17,6 +17,8 @@
package org.orekit.files.ccsds.ndm.tdm;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
......@@ -37,6 +39,12 @@ import org.orekit.utils.Constants;
*/
public class TdmMetadata extends Metadata {
/** Identifier for the tracking data. */
private String trackId;
/** List of data types in the data section. */
private List<String> dataTypes;
/** Start epoch of total time span covered by observations block. */
private AbsoluteDate startTime;
......@@ -68,6 +76,9 @@ public class TdmMetadata extends Metadata {
/** Path 2 (see above). */
private int[] path2;
/** Map of external ephemeris names for participants (minimum 1 and up to 5). */
private Map<Integer, String> ephemerisNames;
/** Frequency band for transmitted frequencies. */
private String transmitBand;
......@@ -120,6 +131,21 @@ public class TdmMetadata extends Metadata {
/** Reference frame in which data are given: used in combination with ANGLE_TYPE=RADEC. */
private FrameFacade referenceFrame;
/** The interpolation method to be used. */
private String interpolationMethod;
/** The interpolation degree. */
private int interpolationDegree;
/** Bias that was added to Doppler count in the data section. */
private double doppplerCountBias;
/** Scaled by which Doppler count was multiplied in the data section. */
private double dopplerCountScale;
/** Indicator for occurred rollover in Doppler count. */
private boolean doppplerCountRollover;
/** Transmit delays map.<p>
* Specifies a fixed interval of time, in seconds, for the signal to travel from the transmitting
* electronics to the transmit point. Each item in the list corresponds to the each participants.
......@@ -150,11 +176,21 @@ public class TdmMetadata extends Metadata {
*/
private double correctionDoppler;
/** Correction magnitude.<p>
* Magnitude correction that has been added or should be added to the MAGNITUDE data.
*/
private double correctionMagnitude;
/** Raw correction Range in {@link #getRangeUnits()}.<p>
* Range correction that has been added or should be added to the RANGE data.
*/
private double rawCorrectionRange;
/** Correction radar cross section.<p>
* Radar cross section correction that has been added or should be added to the RCS data.
*/
private double correctionRcs;
/** Correction receive.<p>
* Receive correction that has been added or should be added to the RECEIVE data.
*/
......@@ -165,6 +201,16 @@ public class TdmMetadata extends Metadata {
*/
private double correctionTransmit;
/** Yearly aberration correction.<p>
* Yearly correction that has been added or should be added to the ANGLE data.
*/
private double correctionAberrationYearly;
/** Diurnal aberration correction.<p>
* Diurnl correction that has been added or should be added to the ANGLE data.
*/
private double correctionAberrationDiurnal;
/** Correction applied ? YES/NO<p>
* Indicate whethers or not the values associated with the CORRECTION_* keywords have been
* applied to the tracking data.
......@@ -175,9 +221,13 @@ public class TdmMetadata extends Metadata {
*/
public TdmMetadata() {
super(null);
participants = new TreeMap<>();
transmitDelays = new TreeMap<>();
receiveDelays = new TreeMap<>();
participants = new TreeMap<>();
ephemerisNames = new TreeMap<>();
doppplerCountBias = Double.NaN;
dopplerCountScale = 1;
doppplerCountRollover = false;
transmitDelays = new TreeMap<>();
receiveDelays = new TreeMap<>();
}
/** {@inheritDoc} */
......@@ -189,6 +239,37 @@ public class TdmMetadata extends Metadata {
}
}
/** Getter for the tracking data identifier.
* @return tracking data identifier
*/
public String getTrackId() {
return trackId;
}
/** Setter for the tracking data identifier.
* @param trackId tracking data identifier
*/
public void setTrackId(final String trackId) {
refuseFurtherComments();
this.trackId = trackId;
}
/** Getter for the data types in the data section.
* @return data types in the data section
*/
public List<String> getDataTypes() {
return dataTypes;
}
/** Setter for the data types in the data section.
* @param dataTypes data types in the data section
*/
public void setDataTypes(final List<String> dataTypes) {
refuseFurtherComments();
this.dataTypes = new ArrayList<>();
this.dataTypes.addAll(dataTypes);
}
/** Getter for the startTime.
* @return the startTime
*/
......@@ -304,6 +385,31 @@ public class TdmMetadata extends Metadata {
this.path2 = safeCopy(path2);
}
/** Getter for external ephemeris names for participants.
* @return external ephemeris names for participants
*/
public Map<Integer, String> getEphemerisNames() {
return ephemerisNames;
}
/** Setter for the external ephemeris names for participants.
* @param ephemerisNames external ephemeris names for participants
*/
public void setEphemerisNames(final Map<Integer, String> ephemerisNames) {
refuseFurtherComments();
this.ephemerisNames = new TreeMap<Integer, String>();
this.ephemerisNames.putAll(ephemerisNames);
}
/** Adds an ephemeris name to the list.
* @param participantNumber the number of the participant
* @param ephemerisName name of the ephemeris for the participant
*/
public void addEphemerisName(final int participantNumber, final String ephemerisName) {
refuseFurtherComments();
this.ephemerisNames.put(participantNumber, ephemerisName);
}
/** Getter for the transmitBand.
* @return the transmitBand
*/
......@@ -514,6 +620,92 @@ public class TdmMetadata extends Metadata {
this.referenceFrame = referenceFrame;
}
/**
* Get the interpolation method to be used.
*
* @return the interpolation method
*/
public String getInterpolationMethod() {
return interpolationMethod;
}
/**
* Set the interpolation method to be used.
* @param interpolationMethod the interpolation method to be set
*/
public void setInterpolationMethod(final String interpolationMethod) {
refuseFurtherComments();
this.interpolationMethod = interpolationMethod;
}
/**
* Get the interpolation degree.
* @return the interpolation degree
*/
public int getInterpolationDegree() {
return interpolationDegree;
}
/**
* Set the interpolation degree.
* @param interpolationDegree the interpolation degree to be set
*/
public void setInterpolationDegree(final int interpolationDegree) {
refuseFurtherComments();
this.interpolationDegree = interpolationDegree;
}
/**
* Get the Doppler count bias.
* @return the Doppler count bias in Hz
*/
public double getDopplerCountBias() {
return doppplerCountBias;
}
/**
* Set the Doppler count bias.
* @param dopplerCountBias Doppler count bias in Hz to set
*/
public void setDopplerCountBias(final double dopplerCountBias) {
refuseFurtherComments();
this.doppplerCountBias = dopplerCountBias;
}
/**
* Get the Doppler count scale.
* @return the Doppler count scale
*/
public double getDopplerCountScale() {
return dopplerCountScale;
}
/**
* Set the Doppler count Scale.
* @param dopplerCountScale Doppler count scale to set
*/
public void setDopplerCountScale(final double dopplerCountScale) {
refuseFurtherComments();
this.dopplerCountScale = dopplerCountScale;
}
/**
* Check if there is a Doppler count rollover.
* @return true if there is a Doppler count rollover
*/
public boolean hasDopplerCountRollover() {
return doppplerCountRollover;
}
/**
* Set the indicator for Doppler count rollover.
* @param dopplerCountRollover indicator for Doppler count rollover
*/
public void setDopplerCountRollover(final boolean dopplerCountRollover) {
refuseFurtherComments();
this.doppplerCountRollover = dopplerCountRollover;
}
/** Getter for the transmitDelays.
* @return the transmitDelays
*/
......@@ -623,6 +815,21 @@ public class TdmMetadata extends Metadata {
this.correctionDoppler = correctionDoppler;
}
/** Getter for the magnitude correction.
* @return the magnitude correction
*/
public double getCorrectionMagnitude() {
return correctionMagnitude;
}
/** Setter for the magnitude correction.
* @param correctionMagnitude the magnitude correction to set
*/
public void setCorrectionMagnitude(final double correctionMagnitude) {
refuseFurtherComments();
this.correctionMagnitude = correctionMagnitude;
}
/** Getter for the raw correction for range in meters.
* @param converter converter to use if {@link #getRangeUnits() range units}
* are set to {@link RangeUnits#RU}
......@@ -653,6 +860,51 @@ public class TdmMetadata extends Metadata {
this.rawCorrectionRange = rawCorrectionRange;
}
/** Getter for the radar cross section correction.
* @return the radar cross section correction in m²
*/
public double getCorrectionRcs() {
return correctionRcs;
}
/** Setter for the radar cross section correction.
* @param correctionRcs the radar cross section correction in m² to set
*/
public void setCorrectionRcs(final double correctionRcs) {
refuseFurtherComments();
this.correctionRcs = correctionRcs;
}
/** Getter for the yearly aberration correction.
* @return the yearly aberration correction in radians
*/
public double getCorrectionAberrationYearly() {
return correctionAberrationYearly;
}
/** Setter for the yearly aberration correction.
* @param correctionAberrationYearly the yearly aberration correction in radians to set
*/
public void setCorrectionAberrationYearly(final double correctionAberrationYearly) {
refuseFurtherComments();
this.correctionAberrationYearly = correctionAberrationYearly;
}
/** Getter for the diurnal aberration correction.
* @return the diurnal aberration correction in radians
*/
public double getCorrectionAberrationDiurnal() {
return correctionAberrationDiurnal;
}
/** Setter for the diurnal aberration correction.
* @param correctionAberrationDiurnal the diurnal aberration correction in radians to set
*/
public void setCorrectionAberrationDiurnal(final double correctionAberrationDiurnal) {
refuseFurtherComments();
this.correctionAberrationDiurnal = correctionAberrationDiurnal;
}
/** Getter for the correctionReceive.
* @return the correctionReceive (in TDM units, without conversion)
*/
......
......@@ -16,9 +16,12 @@
*/
package org.orekit.files.ccsds.ndm.tdm;
import java.util.stream.Collectors;
import org.orekit.files.ccsds.definitions.Units;
import org.orekit.files.ccsds.utils.ContextBinding;
import org.orekit.files.ccsds.utils.lexical.ParseToken;
import org.orekit.files.ccsds.utils.lexical.TokenType;
import org.orekit.utils.units.Unit;
......@@ -28,6 +31,21 @@ import org.orekit.utils.units.Unit;
*/
public enum TdmMetadataKey {
/** Identifier for the tracking data. */
TRACK_ID((token, context, container) -> token.processAsNormalizedString(container::setTrackId)),
/** Lit of data types in the data section. */
DATA_TYPES((token, context, container) -> {
if (token.getType() == TokenType.ENTRY) {
container.setDataTypes(token.
getContentAsNormalizedList().
stream().
map(s -> s.replace(' ', '_')).
collect(Collectors.toList()));
}
return true;
}),
/** Start time entry. */
START_TIME((token, context, container) -> token.processAsDate(container::setStartTime, context)),
......@@ -61,6 +79,21 @@ public enum TdmMetadataKey {
/** Path 2 entry. */
PATH_2((token, context, container) -> token.processAsIntegerArray(container::setPath2)),
/** External ephemeris file for the participant 1. */
EPHEMERIS_NAME_1((token, context, container) -> token.processAsIndexedNormalizedString(1, container::addEphemerisName)),
/** External ephemeris file for the participant 2. */
EPHEMERIS_NAME_2((token, context, container) -> token.processAsIndexedNormalizedString(2, container::addEphemerisName)),
/** External ephemeris file for the participant 3. */
EPHEMERIS_NAME_3((token, context, container) -> token.processAsIndexedNormalizedString(3, container::addEphemerisName)),
/** External ephemeris file for the participant 4. */
EPHEMERIS_NAME_4((token, context, container) -> token.processAsIndexedNormalizedString(4, container::addEphemerisName)),
/** External ephemeris file for the participant 5. */
EPHEMERIS_NAME_5((token, context, container) -> token.processAsIndexedNormalizedString(5, container::addEphemerisName)),
/** Transmit band entry. */
TRANSMIT_BAND((token, context, container) -> token.processAsUppercaseString(container::setTransmitBand)),
......@@ -103,6 +136,23 @@ public enum TdmMetadataKey {
/** reference frame entry. */
REFERENCE_FRAME((token, context, container) -> token.processAsFrame(container::setReferenceFrame, context, true, false, false)),
/** Interpolation method for transmit phase count. */
INTERPOLATION((token, context, container) -> token.processAsUppercaseString(container::setInterpolationMethod)),
/** Interpolation degree for transmit phase count. */
INTERPOLATION_DEGREE((token, context, container) -> token.processAsInteger(container::setInterpolationDegree)),
/** Bias that was added to Doppler count in the data section. */
DOPPLER_COUNT_BIAS((token, context, container) -> token.processAsDouble(Unit.HERTZ, context.getParsedUnitsBehavior(),
container::setDopplerCountBias)),
/** Scaled by which Doppler count was multiplied in the data section. */
DOPPLER_COUNT_SCALE((token, context, container) -> token.processAsDouble(Unit.ONE, context.getParsedUnitsBehavior(),
container::setDopplerCountScale)),
/** Indicator for occurred rollover in Doppler count. */
DOPPLER_COUNT_ROLLOVER((token, context, container) -> token.processAsBoolean(container::setDopplerCountRollover)),
/** First transmit delay entry. */
TRANSMIT_DELAY_1((token, context, container) -> token.processAsIndexedDouble(1, Unit.SECOND, context.getParsedUnitsBehavior(),
container::addTransmitDelay)),
......@@ -158,10 +208,18 @@ public enum TdmMetadataKey {
CORRECTION_DOPPLER((token, context, container) -> token.processAsDouble(Units.KM_PER_S, context.getParsedUnitsBehavior(),
container::setCorrectionDoppler)),
/** Magnitude correction entry. */
CORRECTION_MAG((token, context, container) -> token.processAsDouble(Unit.ONE, context.getParsedUnitsBehavior(),
container::setCorrectionMagnitude)),
/** Range correction entry (beware the unit is Range Units here). */
CORRECTION_RANGE((token, context, container) -> token.processAsDouble(Unit.ONE, context.getParsedUnitsBehavior(),
container::setRawCorrectionRange)),
/** Radar Cross Section correction entry. */
CORRECTION_RCS((token, context, container) -> token.processAsDouble(Units.M2, context.getParsedUnitsBehavior(),
container::setCorrectionRcs)),
/** Receive correction entry. */
CORRECTION_RECEIVE((token, context, container) -> token.processAsDouble(Unit.HERTZ, context.getParsedUnitsBehavior(),
container::setCorrectionReceive)),
......@@ -170,6 +228,14 @@ public enum TdmMetadataKey {
CORRECTION_TRANSMIT((token, context, container) -> token.processAsDouble(Unit.HERTZ, context.getParsedUnitsBehavior(),
container::setCorrectionTransmit)),
/** Yearly aberration correction entry. */
CORRECTION_ABERRATION_YEARLY((token, context, container) -> token.processAsDouble(Unit.DEGREE, context.getParsedUnitsBehavior(),
container::setCorrectionAberrationYearly)),
/** Diurnal aberration correction entry. */
CORRECTION_ABERRATION_DIURNAL((token, context, container) -> token.processAsDouble(Unit.DEGREE, context.getParsedUnitsBehavior(),
container::setCorrectionAberrationDiurnal)),
/** Applied correction entry. */
CORRECTIONS_APPLIED((token, context, container) -> token.processAsEnum(CorrectionApplied.class, container::setCorrectionsApplied));
......
......@@ -58,6 +58,9 @@ class TdmMetadataWriter extends AbstractWriter {
generator.writeComments(metadata.getComments());
generator.writeEntry(TdmMetadataKey.TRACK_ID.name(), metadata.getTrackId(), null, false);
generator.writeEntry(TdmMetadataKey.DATA_TYPES.name(), metadata.getDataTypes(), false);
// time
generator.writeEntry(MetadataKey.TIME_SYSTEM.name(), metadata.getTimeSystem(), true);
generator.writeEntry(TdmMetadataKey.START_TIME.name(), timeConverter, metadata.getStartTime(), false);
......@@ -79,6 +82,12 @@ class TdmMetadataWriter extends AbstractWriter {
generator.writeEntry(TdmMetadataKey.PATH_2.name(), intArrayToString(metadata.getPath2()), null, true);
}
generator.writeEntry(TdmMetadataKey.EPHEMERIS_NAME_1.name(), metadata.getEphemerisNames().get(1), null, false);
generator.writeEntry(TdmMetadataKey.EPHEMERIS_NAME_2.name(), metadata.getEphemerisNames().get(2), null, false);
generator.writeEntry(TdmMetadataKey.EPHEMERIS_NAME_3.name(), metadata.getEphemerisNames().get(3), null, false);
generator.writeEntry(TdmMetadataKey.EPHEMERIS_NAME_4.name(), metadata.getEphemerisNames().get(4), null, false);
generator.writeEntry(TdmMetadataKey.EPHEMERIS_NAME_5.name(), metadata.getEphemerisNames().get(5), null, false);
generator.writeEntry(TdmMetadataKey.TRANSMIT_BAND.name(), metadata.getTransmitBand(), null, false);
generator.writeEntry(TdmMetadataKey.RECEIVE_BAND.name(), metadata.getReceiveBand(), null, false);
if (metadata.getTurnaroundNumerator() != 0 || metadata.getTurnaroundDenominator() != 0) {
......@@ -98,6 +107,28 @@ class TdmMetadataWriter extends AbstractWriter {
if (metadata.getReferenceFrame() != null) {
generator.writeEntry(TdmMetadataKey.REFERENCE_FRAME.name(), metadata.getReferenceFrame().getName(), null, false);
}
// interpolation
if (metadata.getInterpolationMethod() != null) {
generator.writeEntry(TdmMetadataKey.INTERPOLATION.name(),
metadata.getInterpolationMethod(),
null, true);
generator.writeEntry(TdmMetadataKey.INTERPOLATION_DEGREE.name(),
Integer.toString(metadata.getInterpolationDegree()),
null, true);
}
// Doppler
if (metadata.getDopplerCountBias() != 0) {
generator.writeEntry(TdmMetadataKey.DOPPLER_COUNT_BIAS.name(), metadata.getDopplerCountBias(), Unit.HERTZ, false);
}
if (metadata.getDopplerCountScale() != 1) {
generator.writeEntry(TdmMetadataKey.DOPPLER_COUNT_SCALE.name(), metadata.getDopplerCountScale(), Unit.ONE, false);
}
if (metadata.hasDopplerCountRollover()) {
generator.writeEntry(TdmMetadataKey.DOPPLER_COUNT_BIAS.name(), metadata.hasDopplerCountRollover() ? "YES" : "NO", null, false);
}
generator.writeEntry(TdmMetadataKey.TRANSMIT_DELAY_1.name(), metadata.getTransmitDelays().get(1), Unit.SECOND, false);
generator.writeEntry(TdmMetadataKey.TRANSMIT_DELAY_2.name(), metadata.getTransmitDelays().get(2), Unit.SECOND, false);
generator.writeEntry(TdmMetadataKey.TRANSMIT_DELAY_3.name(), metadata.getTransmitDelays().get(3), Unit.SECOND, false);
......@@ -118,15 +149,27 @@ class TdmMetadataWriter extends AbstractWriter {
if (metadata.getCorrectionDoppler() != 0) {
generator.writeEntry(TdmMetadataKey.CORRECTION_DOPPLER.name(), metadata.getCorrectionDoppler(), Units.KM_PER_S, false);
}
if (metadata.getCorrectionMagnitude() != 0) {
generator.writeEntry(TdmMetadataKey.CORRECTION_MAG.name(), metadata.getCorrectionMagnitude(), Unit.ONE, false);
}
if (metadata.getRawCorrectionRange() != 0) {
generator.writeEntry(TdmMetadataKey.CORRECTION_RANGE.name(), metadata.getRawCorrectionRange(), Unit.ONE, false);
}
if (metadata.getCorrectionRcs() != 0) {
generator.writeEntry(TdmMetadataKey.CORRECTION_RCS.name(), metadata.getCorrectionRcs(), Units.M2, false);
}
if (metadata.getCorrectionReceive() != 0) {
generator.writeEntry(TdmMetadataKey.CORRECTION_RECEIVE.name(), metadata.getCorrectionReceive(), Unit.HERTZ, false);
}
if (metadata.getCorrectionTransmit() != 0) {
generator.writeEntry(TdmMetadataKey.CORRECTION_TRANSMIT.name(), metadata.getCorrectionTransmit(), Unit.HERTZ, false);