CRDHeader.java

  1. /* Copyright 2002-2025 CS GROUP
  2.  * Licensed to CS GROUP (CS) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * CS licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *   http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.orekit.files.ilrs;

  18. import java.util.HashMap;
  19. import java.util.Locale;
  20. import java.util.Map;
  21. import java.util.regex.Pattern;

  22. import org.orekit.annotation.DefaultDataContext;
  23. import org.orekit.errors.OrekitException;
  24. import org.orekit.errors.OrekitMessages;
  25. import org.orekit.time.DateComponents;
  26. import org.orekit.time.TimeScale;
  27. import org.orekit.time.TimeScalesFactory;

  28. /**
  29.  * Container for Consolidated laser ranging Data Format (CDR) header.
  30.  * @author Bryan Cazabonne
  31.  * @author Rongwang Li
  32.  * @since 10.3
  33.  */
  34. public class CRDHeader extends ILRSHeader {

  35.     /** String delimiter regex of datetime. */
  36.     private static final String DATETIME_DELIMITER_REGEX = "[-:T]";

  37.     /** Space. */
  38.     private static final String SPACE = " ";

  39.     /** Pattern of delimiter of datetime. */
  40.     public static final Pattern PATTERN_DATETIME_DELIMITER_REGEX = Pattern.compile(DATETIME_DELIMITER_REGEX);

  41.     /** Station name from official list. */
  42.     private String stationName;

  43.     /** System identifier: Crustal Dynamics Project (CDP) Pad Identifier for SLR. */
  44.     private int systemIdentifier;

  45.     /** System number: Crustal Dynamics Project (CDP) 2-digit system number for SLR. */
  46.     private int systemNumber;

  47.     /** System occupancy: Crustal Dynamics Project (CDP) 2-digit occupancy sequence number for SLR. */
  48.     private int systemOccupancy;

  49.     /** Station Epoch Time Scale. */
  50.     private int epochIdentifier;

  51.     /** Station network. */
  52.     private String stationNetword;

  53.     /** Spacecraft Epoch Time Scale (transponders only). */
  54.     private int spacecraftEpochTimeScale;

  55.     /** Data type. */
  56.     private int dataType;

  57.     /** A flag to indicate the data release. */
  58.     private int dataReleaseFlag;

  59.     /** Tropospheric refraction correction applied indicator. */
  60.     private boolean isTroposphericRefractionApplied;

  61.     /** Center of mass correction applied indicator. */
  62.     private boolean isCenterOfMassCorrectionApplied;

  63.     /** Receive amplitude correction applied indicator. */
  64.     private boolean isReceiveAmplitudeCorrectionApplied;

  65.     /** Station system delay applied indicator. */
  66.     private boolean isStationSystemDelayApplied;

  67.     /** Spacecraft system delay applied (transponders) indicator. */
  68.     private boolean isTransponderDelayApplied;

  69.     /** Range type. */
  70.     private RangeType rangeType;

  71.     /** Data quality indicator. */
  72.     private int qualityIndicator;

  73.     /** Prediction type (CPF or TLE). */
  74.     private int predictionType;

  75.     /** Year of century from CPF or TLE. */
  76.     private int yearOfCentury;

  77.     /**
  78.      * Date and time.
  79.      * CPF starting date and hour (MMDDHH) from CPF H2 record or
  80.      * TLE epoch day/fractional day.
  81.      */
  82.     private String dateAndTime;

  83.     /** Prediction provider (CPF provider in H1 record or TLE source). */
  84.     private String predictionProvider;

  85.     /** Empty constructor.
  86.      * <p>
  87.      * This constructor is not strictly necessary, but it prevents spurious
  88.      * javadoc warnings with JDK 18 and later.
  89.      * </p>
  90.      * @since 12.0
  91.      */
  92.     public CRDHeader() {
  93.         // nothing to do
  94.     }

  95.     /**
  96.      * Get the station name from official list.
  97.      * @return the station name from official list
  98.      */
  99.     public String getStationName() {
  100.         return stationName;
  101.     }

  102.     /**
  103.      * Set the station name from official list.
  104.      * @param stationName the station name to set
  105.      */
  106.     public void setStationName(final String stationName) {
  107.         this.stationName = stationName;
  108.     }

  109.     /**
  110.      * Get the system identifier.
  111.      * @return the system identifier
  112.      */
  113.     public int getSystemIdentifier() {
  114.         return systemIdentifier;
  115.     }

  116.     /**
  117.      * Set the system identifier.
  118.      * @param systemIdentifier the system identifier to set
  119.      */
  120.     public void setSystemIdentifier(final int systemIdentifier) {
  121.         this.systemIdentifier = systemIdentifier;
  122.     }

  123.     /**
  124.      * Get the system number.
  125.      * @return the system number
  126.      */
  127.     public int getSystemNumber() {
  128.         return systemNumber;
  129.     }

  130.     /**
  131.      * Set the system number.
  132.      * @param systemNumber the system number to set
  133.      */
  134.     public void setSystemNumber(final int systemNumber) {
  135.         this.systemNumber = systemNumber;
  136.     }

  137.     /**
  138.      * Get the system occupancy.
  139.      * @return the system occupancy
  140.      */
  141.     public int getSystemOccupancy() {
  142.         return systemOccupancy;
  143.     }

  144.     /**
  145.      * Set the system occupancy.
  146.      * @param systemOccupancy the system occupancy to set
  147.      */
  148.     public void setSystemOccupancy(final int systemOccupancy) {
  149.         this.systemOccupancy = systemOccupancy;
  150.     }

  151.     /**
  152.      * Get the epoch identifier.
  153.      * <p>
  154.      * 3 = UTC (UNSO) ; 4 = UTC (GPS) ; 7 = UTC (BIPM) ; 10 = UTC (Station Time Scale)
  155.      * </p>
  156.      * @return the epoch identifier
  157.      */
  158.     public int getEpochIdentifier() {
  159.         return epochIdentifier;
  160.     }

  161.     /**
  162.      * Set the epoch identifier.
  163.      * @param epochIdentifier the epoch identifier to set
  164.      */
  165.     public void setEpochIdentifier(final int epochIdentifier) {
  166.         this.epochIdentifier = epochIdentifier;
  167.     }

  168.     /**
  169.      * Get the station network.
  170.      * @return the station network
  171.      */
  172.     public String getStationNetword() {
  173.         return stationNetword;
  174.     }

  175.     /**
  176.      * Set the station network.
  177.      * @param stationNetword the station network to set
  178.      */
  179.     public void setStationNetword(final String stationNetword) {
  180.         this.stationNetword = stationNetword;
  181.     }

  182.     /**
  183.      * Get the spacecraft epoch time scale.
  184.      * @return the spacecraft epoch time scale
  185.      */
  186.     public int getSpacecraftEpochTimeScale() {
  187.         return spacecraftEpochTimeScale;
  188.     }

  189.     /**
  190.      * Set the spacecraft epoch time scale.
  191.      * @param spacecraftEpochTimeScale the spacecraft epoch time scale to set
  192.      */
  193.     public void setSpacecraftEpochTimeScale(final int spacecraftEpochTimeScale) {
  194.         this.spacecraftEpochTimeScale = spacecraftEpochTimeScale;
  195.     }

  196.     /**
  197.      * Get the data type.
  198.      * <p>
  199.      * 0 = full rate ; 1 = normal point ; 2 = sampled engineering
  200.      * </p>
  201.      * @return the data type
  202.      */
  203.     public int getDataType() {
  204.         return dataType;
  205.     }

  206.     /**
  207.      * Set the data type.
  208.      * @param dataType the data type to set
  209.      */
  210.     public void setDataType(final int dataType) {
  211.         this.dataType = dataType;
  212.     }

  213.     /**
  214.      * Get the flag indicating the data release.
  215.      * @return the flag indicating the data release
  216.      */
  217.     public int getDataReleaseFlag() {
  218.         return dataReleaseFlag;
  219.     }

  220.     /**
  221.      * Set the flag indicating the data release.
  222.      * @param dataReleaseFlag the flag to set
  223.      */
  224.     public void setDataReleaseFlag(final int dataReleaseFlag) {
  225.         this.dataReleaseFlag = dataReleaseFlag;
  226.     }

  227.     /**
  228.      * Get the tropospheric refraction correction applied indicator.
  229.      * @return true if tropospheric refraction correction is applied
  230.      */
  231.     public boolean isTroposphericRefractionApplied() {
  232.         return isTroposphericRefractionApplied;
  233.     }

  234.     /**
  235.      * Set the tropospheric refraction correction applied indicator.
  236.      * @param isTroposphericRefractionApplied true if tropospheric refraction correction is applied
  237.      */
  238.     public void setIsTroposphericRefractionApplied(final boolean isTroposphericRefractionApplied) {
  239.         this.isTroposphericRefractionApplied = isTroposphericRefractionApplied;
  240.     }

  241.     /**
  242.      * Get the center of mass correction applied indicator.
  243.      * @return true if center of mass correction is applied
  244.      */
  245.     public boolean isCenterOfMassCorrectionApplied() {
  246.         return isCenterOfMassCorrectionApplied;
  247.     }

  248.     /**
  249.      * Set the center of mass correction applied indicator.
  250.      * @param isCenterOfMassCorrectionApplied true if center of mass correction is applied
  251.      */
  252.     public void setIsCenterOfMassCorrectionApplied(final boolean isCenterOfMassCorrectionApplied) {
  253.         this.isCenterOfMassCorrectionApplied = isCenterOfMassCorrectionApplied;
  254.     }

  255.     /**
  256.      * Get the receive amplitude correction applied indicator.
  257.      * @return true if receive amplitude correction is applied
  258.      */
  259.     public boolean isReceiveAmplitudeCorrectionApplied() {
  260.         return isReceiveAmplitudeCorrectionApplied;
  261.     }

  262.     /**
  263.      * Set the receive amplitude correction applied indicator.
  264.      * @param isReceiveAmplitudeCorrectionApplied true if receive amplitude correction is applied
  265.      */
  266.     public void setIsReceiveAmplitudeCorrectionApplied(final boolean isReceiveAmplitudeCorrectionApplied) {
  267.         this.isReceiveAmplitudeCorrectionApplied = isReceiveAmplitudeCorrectionApplied;
  268.     }

  269.     /**
  270.      * Get the station system delay applied indicator.
  271.      * @return true if station system delay is applied
  272.      */
  273.     public boolean isStationSystemDelayApplied() {
  274.         return isStationSystemDelayApplied;
  275.     }

  276.     /**
  277.      * Set the station system delay applied indicator.
  278.      * @param isStationSystemDelayApplied true if station system delay is applied
  279.      */
  280.     public void setIsStationSystemDelayApplied(final boolean isStationSystemDelayApplied) {
  281.         this.isStationSystemDelayApplied = isStationSystemDelayApplied;
  282.     }

  283.     /**
  284.      * Get the spacecraft system delay applied (transponders) indicator.
  285.      * @return true if transponder delay is applied
  286.      */
  287.     public boolean isTransponderDelayApplied() {
  288.         return isTransponderDelayApplied;
  289.     }

  290.     /**
  291.      * Set the spacecraft system delay applied (transponders) indicator.
  292.      * @param isTransponderDelayApplied true if transponder delay is applied
  293.      */
  294.     public void setIsTransponderDelayApplied(final boolean isTransponderDelayApplied) {
  295.         this.isTransponderDelayApplied = isTransponderDelayApplied;
  296.     }

  297.     /**
  298.      * Get the range type.
  299.      * @return the range type
  300.      */
  301.     public RangeType getRangeType() {
  302.         return rangeType;
  303.     }

  304.     /**
  305.      * Set the range type indicator.
  306.      * @param indicator range type indicator
  307.      */
  308.     public void setRangeType(final int indicator) {
  309.         this.rangeType = RangeType.getRangeType(indicator);
  310.     }

  311.     /**
  312.      * Get the data quality indicator.
  313.      * @return the data quality indicator
  314.      */
  315.     public int getQualityIndicator() {
  316.         return qualityIndicator;
  317.     }

  318.     /**
  319.      * Set the data quality indicator.
  320.      * @param qualityIndicator the indicator to set
  321.      */
  322.     public void setQualityIndicator(final int qualityIndicator) {
  323.         this.qualityIndicator = qualityIndicator;
  324.     }

  325.     /**
  326.      * Get the prediction type (CPF or TLE).
  327.      * @return the prediction type
  328.      */
  329.     public int getPredictionType() {
  330.         return predictionType;
  331.     }

  332.     /**
  333.      * Set the prediction type.
  334.      * @param predictionType the prediction type to set
  335.      */
  336.     public void setPredictionType(final int predictionType) {
  337.         this.predictionType = predictionType;
  338.     }

  339.     /**
  340.      * Get the year of century from CPF or TLE.
  341.      * @return the year of century from CPF or TLE
  342.      */
  343.     public int getYearOfCentury() {
  344.         return yearOfCentury;
  345.     }

  346.     /**
  347.      * Set the year of century from CPF or TLE.
  348.      * @param yearOfCentury the year of century to set
  349.      */
  350.     public void setYearOfCentury(final int yearOfCentury) {
  351.         this.yearOfCentury = yearOfCentury;
  352.     }


  353.     /**
  354.      * Get the date and time as the string value.
  355.      * <p>
  356.      * Depending the prediction type, this value can represent the
  357.      * CPF starting date and hour (MMDDHH) from CPF H2 record or
  358.      * TLE epoch day/fractional day
  359.      * </p>
  360.      * @return the date and time as the string value
  361.      */
  362.     public String getDateAndTime() {
  363.         return dateAndTime;
  364.     }

  365.     /**
  366.      * Set the string value of date and time.
  367.      * @param dateAndTime the date and time to set
  368.      */
  369.     public void setDateAndTime(final String dateAndTime) {
  370.         this.dateAndTime = dateAndTime;
  371.     }

  372.     /**
  373.      * Get the prediction provider.
  374.      * @return the preditction provider
  375.      */
  376.     public String getPredictionProvider() {
  377.         return predictionProvider;
  378.     }

  379.     /**
  380.      * Set the prediction provider.
  381.      * @param predictionProvider the prediction provider to set
  382.      */
  383.     public void setPredictionProvider(final String predictionProvider) {
  384.         this.predictionProvider = predictionProvider;
  385.     }

  386.     /**
  387.      * Get a string representation of the H1 in the CRD format.
  388.      * @return a string representation of the H1, in the CRD format.
  389.      * @since 12.0
  390.      */
  391.     public String getH1CrdString() {
  392.         final DateComponents dc = getProductionEpoch();
  393.         return String.format(Locale.US, "H1 %3s %2d %04d %02d %02d %02d", getFormat(),
  394.                              getVersion(), dc.getYear(), dc.getMonth(), dc.getDay(),
  395.                              getProductionHour());
  396.     }

  397.     /**
  398.      * Get a string representation of the H2 in the CRD format.
  399.      * @return a string representation of the H2, in the CRD format.
  400.      * @since 12.0
  401.      */
  402.     public String getH2CrdString() {
  403.         return String.format(Locale.US, "H2 %s %4d %02d %02d %2d %s", stationName,
  404.                 systemIdentifier, systemNumber, systemOccupancy,
  405.                 epochIdentifier, stationNetword);
  406.     }

  407.     /**
  408.      * Get a string representation of the H3 in the CRD format.
  409.      * @return a string representation of the H3, in the CRD format.
  410.      * @since 12.0
  411.      */
  412.     public String getH3CrdString() {
  413.         final int targetLocation = getTargetLocation();
  414.         return String.format(Locale.US, "H3 %s %7s %4s %5s %1d %1d %2s", getName(),
  415.                 getIlrsSatelliteId(), getSic(), getNoradId(),
  416.                 getSpacecraftEpochTimeScale(), getTargetClass(),
  417.                 CRD.formatIntegerOrNaN(targetLocation, -1));
  418.     }

  419.     /**
  420.      * Get a string representation of the H4 in the CRD format.
  421.      * @return a string representation of the H4, in the CRD format.
  422.      * @since 12.0
  423.      */
  424.     @DefaultDataContext
  425.     public String getH4CrdString() {
  426.         // "2006-11-13T15:23:52" -- > "2006 11 13 15 23 52"
  427.         final TimeScale utc = TimeScalesFactory.getUTC();
  428.         final String startEpoch = getStartEpoch().toStringWithoutUtcOffset(utc, 0);
  429.         final String endEpoch = getEndEpoch().toStringWithoutUtcOffset(utc, 0);
  430.         return String.format(Locale.US, "H4 %2d %s %s %d %d %d %d %d %d %d %d", getDataType(),
  431.                 PATTERN_DATETIME_DELIMITER_REGEX.matcher(startEpoch).replaceAll(SPACE),
  432.                 PATTERN_DATETIME_DELIMITER_REGEX.matcher(endEpoch).replaceAll(SPACE),
  433.                 dataReleaseFlag, isTroposphericRefractionApplied ? 1 : 0,
  434.                 isCenterOfMassCorrectionApplied ? 1 : 0,
  435.                 isReceiveAmplitudeCorrectionApplied ? 1 : 0,
  436.                 isStationSystemDelayApplied ? 1 : 0,
  437.                 isTransponderDelayApplied ? 1 : 0, rangeType.getIndicator(),
  438.                 qualityIndicator);
  439.     }

  440.     /**
  441.      * Get a string representation of the H5 in the CRD format.
  442.      * @return a string representation of the H5, in the CRD format.
  443.      * @since 12.0
  444.      */
  445.     public String getH5CrdString() {
  446.         return String.format(Locale.US, "H5 %2d %02d %s %3s %5d", getPredictionType(), getYearOfCentury(),
  447.                 getDateAndTime(), getPredictionProvider(), getSequenceNumber());
  448.     }

  449.     /** Range type for SLR data. */
  450.     public enum RangeType {

  451.         /** No ranges (i.e. transmit time only). */
  452.         NO_RANGES(0),

  453.         /** One-way ranging. */
  454.         ONE_WAY(1),

  455.         /** Two-way ranging. */
  456.         TWO_WAY(2),

  457.         /** Received times only. */
  458.         RECEIVED_ONLY(3),

  459.         /** Mixed. */
  460.         MIXED(4);

  461.         /** Codes map. */
  462.         private static final Map<Integer, RangeType> CODES_MAP = new HashMap<>();
  463.         static {
  464.             for (final RangeType type : values()) {
  465.                 CODES_MAP.put(type.getIndicator(), type);
  466.             }
  467.         }

  468.         /** range type indicator. */
  469.         private final int indicator;

  470.         /**
  471.          * Constructor.
  472.          * @param indicator range type indicator
  473.          */
  474.         RangeType(final int indicator) {
  475.             this.indicator = indicator;
  476.         }

  477.         /**
  478.          * Get the range type indicator.
  479.          * @return the range type indicator
  480.          */
  481.         public int getIndicator() {
  482.             return indicator;
  483.         }

  484.         /**
  485.          * Get the range type for the given indicator.
  486.          * @param id indicator
  487.          * @return the range type corresponding to the indicator
  488.          */
  489.         public static RangeType getRangeType(final int id) {
  490.             final RangeType type = CODES_MAP.get(id);
  491.             if (type == null) {
  492.                // Invalid value. An exception is thrown
  493.                 throw new OrekitException(OrekitMessages.INVALID_RANGE_INDICATOR_IN_CRD_FILE, id);
  494.             }
  495.             return type;
  496.         }

  497.     }

  498.     /** Data type for CRD data.
  499.      * @since 12.0
  500.      */
  501.     public enum DataType {

  502.         /** Full rate. */
  503.         FULL_RATE(0),

  504.         /** Normal point. */
  505.         NORMAL_POINT(1),

  506.         /** Sampled engineering. */
  507.         SAMPLED_ENGIEERING(2);

  508.         /** Codes map. */
  509.         private static final Map<Integer, DataType> CODES_MAP = new HashMap<>();
  510.         static {
  511.             for (final DataType type : values()) {
  512.                 CODES_MAP.put(type.getIndicator(), type);
  513.             }
  514.         }

  515.         /** data type indicator. */
  516.         private final int indicator;

  517.         /**
  518.          * Constructor.
  519.          * @param indicator data type indicator
  520.          */
  521.         DataType(final int indicator) {
  522.             this.indicator = indicator;
  523.         }

  524.         /**
  525.          * Get the data type indicator.
  526.          * @return the data type indicator
  527.          */
  528.         public int getIndicator() {
  529.             return indicator;
  530.         }

  531.         /**
  532.          * Get the data type for the given indicator.
  533.          * @param id indicator
  534.          * @return the data type corresponding to the indicator
  535.          */
  536.         public static DataType getDataType(final int id) {
  537.             final DataType type = CODES_MAP.get(id);
  538.             if (type == null) {
  539.                // Invalid value. An exception is thrown
  540.                 throw new RuntimeException(String.format(Locale.US,
  541.                                                          "Invalid data type indicator {0} in CRD file header", id));
  542.             }
  543.             return type;
  544.         }

  545.     }

  546. }