CRDHeader.java
/* Copyright 2002-2024 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.ilrs;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import org.orekit.annotation.DefaultDataContext;
import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitMessages;
import org.orekit.time.DateComponents;
import org.orekit.time.TimeScale;
import org.orekit.time.TimeScalesFactory;
/**
* Container for Consolidated laser ranging Data Format (CDR) header.
* @author Bryan Cazabonne
* @author Rongwang Li
* @since 10.3
*/
public class CRDHeader extends ILRSHeader {
/** String delimiter regex of datetime. */
private static final String DATETIME_DELIMITER_REGEX = "[-:T]";
/** Space. */
private static final String SPACE = " ";
/** Pattern of delimiter of datetime. */
public static final Pattern PATTERN_DATETIME_DELIMITER_REGEX = Pattern.compile(DATETIME_DELIMITER_REGEX);
/** Station name from official list. */
private String stationName;
/** System identifier: Crustal Dynamics Project (CDP) Pad Identifier for SLR. */
private int systemIdentifier;
/** System number: Crustal Dynamics Project (CDP) 2-digit system number for SLR. */
private int systemNumber;
/** System occupancy: Crustal Dynamics Project (CDP) 2-digit occupancy sequence number for SLR. */
private int systemOccupancy;
/** Station Epoch Time Scale. */
private int epochIdentifier;
/** Station network. */
private String stationNetword;
/** Spacecraft Epoch Time Scale (transponders only). */
private int spacecraftEpochTimeScale;
/** Data type. */
private int dataType;
/** A flag to indicate the data release. */
private int dataReleaseFlag;
/** Tropospheric refraction correction applied indicator. */
private boolean isTroposphericRefractionApplied;
/** Center of mass correction applied indicator. */
private boolean isCenterOfMassCorrectionApplied;
/** Receive amplitude correction applied indicator. */
private boolean isReceiveAmplitudeCorrectionApplied;
/** Station system delay applied indicator. */
private boolean isStationSystemDelayApplied;
/** Spacecraft system delay applied (transponders) indicator. */
private boolean isTransponderDelayApplied;
/** Range type. */
private RangeType rangeType;
/** Data quality indicator. */
private int qualityIndicator;
/** Prediction type (CPF or TLE). */
private int predictionType;
/** Year of century from CPF or TLE. */
private int yearOfCentury;
/**
* Date and time.
* CPF starting date and hour (MMDDHH) from CPF H2 record or
* TLE epoch day/fractional day.
*/
private String dateAndTime;
/** Prediction provider (CPF provider in H1 record or TLE source). */
private String predictionProvider;
/** Empty constructor.
* <p>
* This constructor is not strictly necessary, but it prevents spurious
* javadoc warnings with JDK 18 and later.
* </p>
* @since 12.0
*/
public CRDHeader() {
// nothing to do
}
/**
* Get the station name from official list.
* @return the station name from official list
*/
public String getStationName() {
return stationName;
}
/**
* Set the station name from official list.
* @param stationName the station name to set
*/
public void setStationName(final String stationName) {
this.stationName = stationName;
}
/**
* Get the system identifier.
* @return the system identifier
*/
public int getSystemIdentifier() {
return systemIdentifier;
}
/**
* Set the system identifier.
* @param systemIdentifier the system identifier to set
*/
public void setSystemIdentifier(final int systemIdentifier) {
this.systemIdentifier = systemIdentifier;
}
/**
* Get the system number.
* @return the system number
*/
public int getSystemNumber() {
return systemNumber;
}
/**
* Set the system number.
* @param systemNumber the system number to set
*/
public void setSystemNumber(final int systemNumber) {
this.systemNumber = systemNumber;
}
/**
* Get the system occupancy.
* @return the system occupancy
*/
public int getSystemOccupancy() {
return systemOccupancy;
}
/**
* Set the system occupancy.
* @param systemOccupancy the system occupancy to set
*/
public void setSystemOccupancy(final int systemOccupancy) {
this.systemOccupancy = systemOccupancy;
}
/**
* Get the epoch identifier.
* <p>
* 3 = UTC (UNSO) ; 4 = UTC (GPS) ; 7 = UTC (BIPM) ; 10 = UTC (Station Time Scale)
* </p>
* @return the epoch identifier
*/
public int getEpochIdentifier() {
return epochIdentifier;
}
/**
* Set the epoch identifier.
* @param epochIdentifier the epoch identifier to set
*/
public void setEpochIdentifier(final int epochIdentifier) {
this.epochIdentifier = epochIdentifier;
}
/**
* Get the station network.
* @return the station network
*/
public String getStationNetword() {
return stationNetword;
}
/**
* Set the station network.
* @param stationNetword the station network to set
*/
public void setStationNetword(final String stationNetword) {
this.stationNetword = stationNetword;
}
/**
* Get the spacecraft epoch time scale.
* @return the spacecraft epoch time scale
*/
public int getSpacecraftEpochTimeScale() {
return spacecraftEpochTimeScale;
}
/**
* Set the spacecraft epoch time scale.
* @param spacecraftEpochTimeScale the spacecraft epoch time scale to set
*/
public void setSpacecraftEpochTimeScale(final int spacecraftEpochTimeScale) {
this.spacecraftEpochTimeScale = spacecraftEpochTimeScale;
}
/**
* Get the data type.
* <p>
* 0 = full rate ; 1 = normal point ; 2 = sampled engineering
* </p>
* @return the data type
*/
public int getDataType() {
return dataType;
}
/**
* Set the data type.
* @param dataType the data type to set
*/
public void setDataType(final int dataType) {
this.dataType = dataType;
}
/**
* Get the flag indicating the data release.
* @return the flag indicating the data release
*/
public int getDataReleaseFlag() {
return dataReleaseFlag;
}
/**
* Set the flag indicating the data release.
* @param dataReleaseFlag the flag to set
*/
public void setDataReleaseFlag(final int dataReleaseFlag) {
this.dataReleaseFlag = dataReleaseFlag;
}
/**
* Get the tropospheric refraction correction applied indicator.
* @return true if tropospheric refraction correction is applied
*/
public boolean isTroposphericRefractionApplied() {
return isTroposphericRefractionApplied;
}
/**
* Set the tropospheric refraction correction applied indicator.
* @param isTroposphericRefractionApplied true if tropospheric refraction correction is applied
*/
public void setIsTroposphericRefractionApplied(final boolean isTroposphericRefractionApplied) {
this.isTroposphericRefractionApplied = isTroposphericRefractionApplied;
}
/**
* Get the center of mass correction applied indicator.
* @return true if center of mass correction is applied
*/
public boolean isCenterOfMassCorrectionApplied() {
return isCenterOfMassCorrectionApplied;
}
/**
* Set the center of mass correction applied indicator.
* @param isCenterOfMassCorrectionApplied true if center of mass correction is applied
*/
public void setIsCenterOfMassCorrectionApplied(final boolean isCenterOfMassCorrectionApplied) {
this.isCenterOfMassCorrectionApplied = isCenterOfMassCorrectionApplied;
}
/**
* Get the receive amplitude correction applied indicator.
* @return true if receive amplitude correction is applied
*/
public boolean isReceiveAmplitudeCorrectionApplied() {
return isReceiveAmplitudeCorrectionApplied;
}
/**
* Set the receive amplitude correction applied indicator.
* @param isReceiveAmplitudeCorrectionApplied true if receive amplitude correction is applied
*/
public void setIsReceiveAmplitudeCorrectionApplied(final boolean isReceiveAmplitudeCorrectionApplied) {
this.isReceiveAmplitudeCorrectionApplied = isReceiveAmplitudeCorrectionApplied;
}
/**
* Get the station system delay applied indicator.
* @return true if station system delay is applied
*/
public boolean isStationSystemDelayApplied() {
return isStationSystemDelayApplied;
}
/**
* Set the station system delay applied indicator.
* @param isStationSystemDelayApplied true if station system delay is applied
*/
public void setIsStationSystemDelayApplied(final boolean isStationSystemDelayApplied) {
this.isStationSystemDelayApplied = isStationSystemDelayApplied;
}
/**
* Get the spacecraft system delay applied (transponders) indicator.
* @return true if transponder delay is applied
*/
public boolean isTransponderDelayApplied() {
return isTransponderDelayApplied;
}
/**
* Set the spacecraft system delay applied (transponders) indicator.
* @param isTransponderDelayApplied true if transponder delay is applied
*/
public void setIsTransponderDelayApplied(final boolean isTransponderDelayApplied) {
this.isTransponderDelayApplied = isTransponderDelayApplied;
}
/**
* Get the range type.
* @return the range type
*/
public RangeType getRangeType() {
return rangeType;
}
/**
* Set the range type indicator.
* @param indicator range type indicator
*/
public void setRangeType(final int indicator) {
this.rangeType = RangeType.getRangeType(indicator);
}
/**
* Get the data quality indicator.
* @return the data quality indicator
*/
public int getQualityIndicator() {
return qualityIndicator;
}
/**
* Set the data quality indicator.
* @param qualityIndicator the indicator to set
*/
public void setQualityIndicator(final int qualityIndicator) {
this.qualityIndicator = qualityIndicator;
}
/**
* Get the prediction type (CPF or TLE).
* @return the prediction type
*/
public int getPredictionType() {
return predictionType;
}
/**
* Set the prediction type.
* @param predictionType the prediction type to set
*/
public void setPredictionType(final int predictionType) {
this.predictionType = predictionType;
}
/**
* Get the year of century from CPF or TLE.
* @return the year of century from CPF or TLE
*/
public int getYearOfCentury() {
return yearOfCentury;
}
/**
* Set the year of century from CPF or TLE.
* @param yearOfCentury the year of century to set
*/
public void setYearOfCentury(final int yearOfCentury) {
this.yearOfCentury = yearOfCentury;
}
/**
* Get the date and time as the string value.
* <p>
* Depending the prediction type, this value can represent the
* CPF starting date and hour (MMDDHH) from CPF H2 record or
* TLE epoch day/fractional day
* </p>
* @return the date and time as the string value
*/
public String getDateAndTime() {
return dateAndTime;
}
/**
* Set the string value of date and time.
* @param dateAndTime the date and time to set
*/
public void setDateAndTime(final String dateAndTime) {
this.dateAndTime = dateAndTime;
}
/**
* Get the prediction provider.
* @return the preditction provider
*/
public String getPredictionProvider() {
return predictionProvider;
}
/**
* Set the prediction provider.
* @param predictionProvider the prediction provider to set
*/
public void setPredictionProvider(final String predictionProvider) {
this.predictionProvider = predictionProvider;
}
/**
* Get a string representation of the H1 in the CRD format.
* @return a string representation of the H1, in the CRD format.
* @since 12.0
*/
public String getH1CrdString() {
final DateComponents dc = getProductionEpoch();
return String.format("H1 %3s %2d %04d %02d %02d %02d", getFormat(),
getVersion(), dc.getYear(), dc.getMonth(), dc.getDay(),
getProductionHour());
}
/**
* Get a string representation of the H2 in the CRD format.
* @return a string representation of the H2, in the CRD format.
* @since 12.0
*/
public String getH2CrdString() {
return String.format("H2 %s %4d %02d %02d %2d %s", stationName,
systemIdentifier, systemNumber, systemOccupancy,
epochIdentifier, stationNetword);
}
/**
* Get a string representation of the H3 in the CRD format.
* @return a string representation of the H3, in the CRD format.
* @since 12.0
*/
public String getH3CrdString() {
final int targetLocation = getTargetLocation();
return String.format("H3 %s %7s %4s %5s %1d %1d %2s", getName(),
getIlrsSatelliteId(), getSic(), getNoradId(),
getSpacecraftEpochTimeScale(), getTargetClass(),
CRD.formatIntegerOrNaN(targetLocation, -1));
}
/**
* Get a string representation of the H4 in the CRD format.
* @return a string representation of the H4, in the CRD format.
* @since 12.0
*/
@DefaultDataContext
public String getH4CrdString() {
// "2006-11-13T15:23:52" -- > "2006 11 13 15 23 52"
final TimeScale utc = TimeScalesFactory.getUTC();
final String startEpoch = getStartEpoch().toStringWithoutUtcOffset(utc, 0);
final String endEpoch = getEndEpoch().toStringWithoutUtcOffset(utc, 0);
return String.format("H4 %2d %s %s %d %d %d %d %d %d %d %d", getDataType(),
PATTERN_DATETIME_DELIMITER_REGEX.matcher(startEpoch).replaceAll(SPACE),
PATTERN_DATETIME_DELIMITER_REGEX.matcher(endEpoch).replaceAll(SPACE),
dataReleaseFlag, isTroposphericRefractionApplied ? 1 : 0,
isCenterOfMassCorrectionApplied ? 1 : 0,
isReceiveAmplitudeCorrectionApplied ? 1 : 0,
isStationSystemDelayApplied ? 1 : 0,
isTransponderDelayApplied ? 1 : 0, rangeType.getIndicator(),
qualityIndicator);
}
/**
* Get a string representation of the H5 in the CRD format.
* @return a string representation of the H5, in the CRD format.
* @since 12.0
*/
public String getH5CrdString() {
return String.format("H5 %2d %02d %s %3s %5d", getPredictionType(), getYearOfCentury(),
getDateAndTime(), getPredictionProvider(), getSequenceNumber());
}
/** Range type for SLR data. */
public enum RangeType {
/** No ranges (i.e. transmit time only). */
NO_RANGES(0),
/** One-way ranging. */
ONE_WAY(1),
/** Two-way ranging. */
TWO_WAY(2),
/** Received times only. */
RECEIVED_ONLY(3),
/** Mixed. */
MIXED(4);
/** Codes map. */
private static final Map<Integer, RangeType> CODES_MAP = new HashMap<>();
static {
for (final RangeType type : values()) {
CODES_MAP.put(type.getIndicator(), type);
}
}
/** range type indicator. */
private final int indicator;
/**
* Constructor.
* @param indicator range type indicator
*/
RangeType(final int indicator) {
this.indicator = indicator;
}
/**
* Get the range type indicator.
* @return the range type indicator
*/
public int getIndicator() {
return indicator;
}
/**
* Get the range type for the given indicator.
* @param id indicator
* @return the range type corresponding to the indicator
*/
public static RangeType getRangeType(final int id) {
final RangeType type = CODES_MAP.get(id);
if (type == null) {
// Invalid value. An exception is thrown
throw new OrekitException(OrekitMessages.INVALID_RANGE_INDICATOR_IN_CRD_FILE, id);
}
return type;
}
}
/** Data type for CRD data.
* @since 12.0
*/
public enum DataType {
/** Full rate. */
FULL_RATE(0),
/** Normal point. */
NORMAL_POINT(1),
/** Sampled engineering. */
SAMPLED_ENGIEERING(2);
/** Codes map. */
private static final Map<Integer, DataType> CODES_MAP = new HashMap<>();
static {
for (final DataType type : values()) {
CODES_MAP.put(type.getIndicator(), type);
}
}
/** data type indicator. */
private final int indicator;
/**
* Constructor.
* @param indicator data type indicator
*/
DataType(final int indicator) {
this.indicator = indicator;
}
/**
* Get the data type indicator.
* @return the data type indicator
*/
public int getIndicator() {
return indicator;
}
/**
* Get the data type for the given indicator.
* @param id indicator
* @return the data type corresponding to the indicator
*/
public static DataType getDataType(final int id) {
final DataType type = CODES_MAP.get(id);
if (type == null) {
// Invalid value. An exception is thrown
throw new RuntimeException(String.format("Invalid data type indicator {0} in CRD file header", id));
}
return type;
}
}
}