CRDHeader.java

  1. /* Copyright 2002-2024 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.Map;
  20. import java.util.regex.Pattern;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  496.     }

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

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

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

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

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

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

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

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

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

  543.     }

  544. }