Station.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.sinex;

  18. import java.util.ArrayList;
  19. import java.util.HashMap;
  20. import java.util.List;
  21. import java.util.Map;

  22. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  23. import org.orekit.errors.OrekitException;
  24. import org.orekit.errors.OrekitMessages;
  25. import org.orekit.gnss.GnssSignal;
  26. import org.orekit.models.earth.displacement.PsdCorrection;
  27. import org.orekit.time.AbsoluteDate;
  28. import org.orekit.utils.TimeSpanMap;

  29. /**
  30.  * Station model.
  31.  * <p>
  32.  * Since Orekit 11.1, this class handles multiple site antenna
  33.  * eccentricity.
  34.  * The {@link #getEccentricities(AbsoluteDate)} method can be
  35.  * used to access the site antenna eccentricity values for a
  36.  * given epoch.
  37.  * </p>
  38.  * @author Bryan Cazabonne
  39.  * @since 10.3
  40.  */
  41. public class Station {

  42.     /** Site code. */
  43.     private String siteCode;

  44.     /** DOMES number. */
  45.     private String domes;

  46.     /** Start of validity. */
  47.     private AbsoluteDate validFrom;

  48.     /** End of validity. */
  49.     private AbsoluteDate validUntil;

  50.     /** Eccentricity reference system. */
  51.     private ReferenceSystem eccRefSystem;

  52.     /** TimeSpanMap of site antenna eccentricities. */
  53.     private final TimeSpanMap<Vector3D> eccentricitiesTimeSpanMap;

  54.     /** Antenna key.
  55.      * @since 13.0
  56.      */
  57.     private final TimeSpanMap<AntennaKey> antennaKeysMap;

  58.     /** Phase centers.
  59.      * @since 13.0
  60.      */
  61.     private final TimeSpanMap<Map<GnssSignal, Vector3D>> phaseCentersMap;

  62.     /** Post-Seismic Deformation.
  63.      * @since 12.0
  64.      */
  65.     private final TimeSpanMap<List<PsdCorrection>> psdMap;

  66.     /** Station position. */
  67.     private Vector3D position;

  68.     /** Station velocity. */
  69.     private Vector3D velocity;

  70.     /** Coordinates reference epoch. */
  71.     private AbsoluteDate epoch;

  72.     /**
  73.      * Constructor.
  74.      */
  75.     public Station() {
  76.         this.eccentricitiesTimeSpanMap = new TimeSpanMap<>(null);
  77.         this.antennaKeysMap            = new TimeSpanMap<>(null);
  78.         this.phaseCentersMap           = new TimeSpanMap<>(null);
  79.         this.psdMap                    = new TimeSpanMap<>(null);
  80.         this.position                  = Vector3D.ZERO;
  81.         this.velocity                  = Vector3D.ZERO;
  82.     }

  83.     /**
  84.      * Get the site code (station identifier).
  85.      * @return the site code
  86.      */
  87.     public String getSiteCode() {
  88.         return siteCode;
  89.     }

  90.     /**
  91.      * Set the site code (station identifier).
  92.      * @param siteCode the site code to set
  93.      */
  94.     public void setSiteCode(final String siteCode) {
  95.         this.siteCode = siteCode;
  96.     }

  97.     /**
  98.      * Get the site DOMES number.
  99.      * @return the DOMES number
  100.      */
  101.     public String getDomes() {
  102.         return domes;
  103.     }

  104.     /**
  105.      * Set the DOMES number.
  106.      * @param domes the DOMES number to set
  107.      */
  108.     public void setDomes(final String domes) {
  109.         this.domes = domes;
  110.     }

  111.     /**
  112.      * Get start of validity.
  113.      * @return start of validity
  114.      */
  115.     public AbsoluteDate getValidFrom() {
  116.         return validFrom;
  117.     }

  118.     /**
  119.      * Set the start of validity.
  120.      * @param validFrom the start of validity to set
  121.      */
  122.     public void setValidFrom(final AbsoluteDate validFrom) {
  123.         this.validFrom = validFrom;
  124.     }

  125.     /**
  126.      * Get end of validity.
  127.      * @return end of validity
  128.      */
  129.     public AbsoluteDate getValidUntil() {
  130.         return validUntil;
  131.     }

  132.     /**
  133.      * Set the end of validity.
  134.      * @param validUntil the end of validity to set
  135.      */
  136.     public void setValidUntil(final AbsoluteDate validUntil) {
  137.         this.validUntil = validUntil;
  138.     }

  139.     /**
  140.      * Get the reference system used to define the eccentricity vector (local or cartesian).
  141.      * @return the reference system used to define the eccentricity vector
  142.      */
  143.     public ReferenceSystem getEccRefSystem() {
  144.         return eccRefSystem;
  145.     }

  146.     /**
  147.      * Set the reference system used to define the eccentricity vector (local or cartesian).
  148.      * @param eccRefSystem the reference system used to define the eccentricity vector
  149.      */
  150.     public void setEccRefSystem(final ReferenceSystem eccRefSystem) {
  151.         this.eccRefSystem = eccRefSystem;
  152.     }

  153.     /**
  154.      * Get the station antenna eccentricities for the given epoch.
  155.      * <p>
  156.      * Vector convention: X-Y-Z or UP-NORTH-EAST.
  157.      * See {@link #getEccRefSystem()} method.
  158.      * <p>
  159.      * If there is no eccentricity values for the given epoch, an
  160.      * exception is thrown.
  161.      * @param date epoch
  162.      * @return station antenna eccentricities (m)
  163.      * @since 11.1
  164.      */
  165.     public Vector3D getEccentricities(final AbsoluteDate date) {
  166.         final Vector3D eccAtEpoch = eccentricitiesTimeSpanMap.get(date);
  167.         // If the entry is null, there is no valid eccentricity values for the input epoch
  168.         if (eccAtEpoch == null) {
  169.             // Throw an exception
  170.             throw new OrekitException(OrekitMessages.MISSING_STATION_DATA_FOR_EPOCH, date);
  171.         }
  172.         return eccAtEpoch;
  173.     }

  174.     /**
  175.      * Get the TimeSpanMap of site antenna eccentricities.
  176.      * @return the TimeSpanMap of site antenna eccentricities
  177.      * @since 11.1
  178.      */
  179.     public TimeSpanMap<Vector3D> getEccentricitiesTimeSpanMap() {
  180.         return eccentricitiesTimeSpanMap;
  181.     }

  182.     /** Add a station eccentricity vector entry valid before a limit date.<br>
  183.      * Using <code>addStationEccentricitiesValidBefore(entry, t)</code> will make <code>entry</code>
  184.      * valid in ]-∞, t[ (note the open bracket).
  185.      * @param entry station eccentricity vector entry
  186.      * @param latestValidityDate date before which the entry is valid
  187.      * (must be different from <b>all</b> dates already used for transitions)
  188.      * @since 11.1
  189.      */
  190.     public void addStationEccentricitiesValidBefore(final Vector3D entry, final AbsoluteDate latestValidityDate) {
  191.         eccentricitiesTimeSpanMap.addValidBefore(entry, latestValidityDate, false);
  192.     }

  193.     /** Get the TimeSpanMap of Post-Seismic Deformation.
  194.      * @return the TimeSpanMap of Post-Seismic Deformation
  195.      * @since 12.1
  196.      */
  197.     public TimeSpanMap<List<PsdCorrection>> getPsdTimeSpanMap() {
  198.         return psdMap;
  199.     }

  200.     /** Add a Post-Seismic Deformation entry valid after a limit date.<br>
  201.      * Using {@code addPsdCorrectionValidAfter(entry, t)} will make {@code entry}
  202.      * valid in [t, +∞[ (note the closed bracket).
  203.      * @param entry Post-Seismic Deformation entry
  204.      * @param earliestValidityDate date after which the entry is valid
  205.      * (must be different from <b>all</b> dates already used for transitions)
  206.      * @since 12.1
  207.      */
  208.     public void addPsdCorrectionValidAfter(final PsdCorrection entry, final AbsoluteDate earliestValidityDate) {

  209.         // get the list of corrections active just after earthquake date
  210.         List<PsdCorrection> corrections = psdMap.get(earliestValidityDate.shiftedBy(1.0e-3));

  211.         if (corrections == null ||
  212.             earliestValidityDate.durationFrom(corrections.get(0).getEarthquakeDate()) > 1.0e-3) {
  213.             // either this is the first earthquake we consider or
  214.             // this earthquake is after another one already considered
  215.             // we need to create a new list of corrections for this new earthquake
  216.             corrections = new ArrayList<>();
  217.             psdMap.addValidAfter(corrections, earliestValidityDate, false);
  218.         }

  219.         // add the entry to the current list
  220.         corrections.add(entry);

  221.     }

  222.     /**
  223.      * Get the antenna key for the given epoch.
  224.      * If there is no antenna keys for the given epoch, an
  225.      * exception is thrown.
  226.      * @param date epoch
  227.      * @return antenna key
  228.      * @since 13.0
  229.      */
  230.     public AntennaKey getAntennaKey(final AbsoluteDate date) {
  231.         final AntennaKey keyAtEpoch = antennaKeysMap.get(date);
  232.         // If the entry is null, there is no valid type for the input epoch
  233.         if (keyAtEpoch == null) {
  234.             // Throw an exception
  235.             throw new OrekitException(OrekitMessages.MISSING_STATION_DATA_FOR_EPOCH, date);
  236.         }
  237.         return keyAtEpoch;
  238.     }

  239.     /**
  240.      * Get the TimeSpanMap of site antenna type.
  241.      * @return the TimeSpanMap of site antenna type
  242.      * @since 12.0
  243.      */
  244.     public TimeSpanMap<AntennaKey> getAntennaKeyTimeSpanMap() {
  245.         return antennaKeysMap;
  246.     }

  247.     /** Add a antenna key entry valid before a limit date.<br>
  248.      * Using <code>addAntennaKeyValidBefore(entry, t)</code> will make <code>entry</code>
  249.      * valid in ]-∞, t[ (note the open bracket).
  250.      * @param entry antenna key entry
  251.      * @param latestValidityDate date before which the entry is valid
  252.      * (must be different from <b>all</b> dates already used for transitions)
  253.      * @since 12.0
  254.      */
  255.     public void addAntennaKeyValidBefore(final AntennaKey entry, final AbsoluteDate latestValidityDate) {
  256.         antennaKeysMap.addValidBefore(entry, latestValidityDate, false);
  257.     }

  258.     /**
  259.      * Get the TimeSpanMap of phase centers.
  260.      * @return the TimeSpanMap of phase centers
  261.      * @since 13.0
  262.      */
  263.     public TimeSpanMap<Map<GnssSignal, Vector3D>> getPhaseCentersMap() {
  264.         return phaseCentersMap;
  265.     }

  266.     /**
  267.      * Get the phase centers for the given epoch.
  268.      * If there is no phase centers for the given epoch, an
  269.      * exception is thrown.
  270.      * @param date epoch
  271.      * @return phase centers
  272.      * @since 13.0
  273.      */
  274.     public Map<GnssSignal, Vector3D> getPhaseCenters(final AbsoluteDate date) {
  275.         final Map<GnssSignal, Vector3D> phaseCentersAtEpoch = phaseCentersMap.get(date);
  276.         // If the entry is null, there is no valid key for the input epoch
  277.         if (phaseCentersAtEpoch == null) {
  278.             // Throw an exception
  279.             throw new OrekitException(OrekitMessages.MISSING_STATION_DATA_FOR_EPOCH, date);
  280.         }
  281.         return phaseCentersAtEpoch;
  282.     }

  283.     /**
  284.      * Get the station position.
  285.      * @return the station position (m)
  286.      */
  287.     public Vector3D getPosition() {
  288.         return position;
  289.     }

  290.     /**
  291.      * Set the station position.
  292.      * @param position the position to set
  293.      */
  294.     public void setPosition(final Vector3D position) {
  295.         this.position = position;
  296.     }

  297.     /**
  298.      * Get the station velocity.
  299.      * @return the station velocity (m/s)
  300.      */
  301.     public Vector3D getVelocity() {
  302.         return velocity;
  303.     }

  304.     /**
  305.      * Set the station velocity.
  306.      * @param velocity the velocity to set
  307.      */
  308.     public void setVelocity(final Vector3D velocity) {
  309.         this.velocity = velocity;
  310.     }

  311.     /**
  312.      * Get the coordinates reference epoch.
  313.      * @return the coordinates reference epoch
  314.      */
  315.     public AbsoluteDate getEpoch() {
  316.         return epoch;
  317.     }

  318.     /**
  319.      * Set the coordinates reference epoch.
  320.      * @param epoch the epoch to set
  321.      */
  322.     public void setEpoch(final AbsoluteDate epoch) {
  323.         this.epoch = epoch;
  324.     }

  325.     /** Eccentricity reference system. */
  326.     public enum ReferenceSystem {

  327.         /** Local reference system Up, North, East. */
  328.         UNE("UNE"),

  329.         /** Cartesian reference system X, Y, Z. */
  330.         XYZ("XYZ");

  331.         /** Codes map. */
  332.         private static final Map<String, ReferenceSystem> CODES_MAP = new HashMap<>();
  333.         static {
  334.             for (final ReferenceSystem type : values()) {
  335.                 CODES_MAP.put(type.getName(), type);
  336.             }
  337.         }

  338.         /** Name used to define the reference system in SINEX file. */
  339.         private final String name;

  340.         /**
  341.          * Constructor.
  342.          * @param name name used to define the reference system in SINEX file
  343.          */
  344.         ReferenceSystem(final String name) {
  345.             this.name = name;
  346.         }

  347.         /**
  348.          * Get the name used to define the reference system in SINEX file.
  349.          * @return the name
  350.          */
  351.         public String getName() {
  352.             return name;
  353.         }

  354.         /**
  355.          * Get the eccentricity reference system corresponding to the given value.
  356.          * @param value given value
  357.          * @return the corresponding eccentricity reference system
  358.          */
  359.         public static ReferenceSystem getEccRefSystem(final String value) {
  360.             return CODES_MAP.get(value);
  361.         }

  362.     }

  363. }