SP3File.java

  1. /* Copyright 2002-2012 Space Applications Services
  2.  * Licensed to CS Systèmes d'Information (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.sp3;

  18. import java.util.ArrayList;
  19. import java.util.Collections;
  20. import java.util.LinkedHashMap;
  21. import java.util.List;
  22. import java.util.Map;
  23. import java.util.function.Function;

  24. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  25. import org.orekit.files.general.EphemerisFile;
  26. import org.orekit.frames.Frame;
  27. import org.orekit.propagation.BoundedPropagator;
  28. import org.orekit.time.AbsoluteDate;
  29. import org.orekit.time.TimeScale;
  30. import org.orekit.utils.CartesianDerivativesFilter;
  31. import org.orekit.utils.TimeStampedPVCoordinates;

  32. /**
  33.  * Represents a parsed SP3 orbit file.
  34.  * @author Thomas Neidhart
  35.  * @author Evan Ward
  36.  */
  37. public class SP3File implements EphemerisFile {
  38.     /** String representation of the center of ephemeris coordinate system. **/
  39.     public static final String SP3_FRAME_CENTER_STRING = "EARTH";

  40.     /** File type indicator. */
  41.     public enum SP3FileType {
  42.         /** GPS only file. */
  43.         GPS,
  44.         /** Mixed file. */
  45.         MIXED,
  46.         /** GLONASS only file. */
  47.         GLONASS,
  48.         /** LEO only file. */
  49.         LEO,
  50.         /** Galileo only file. */
  51.         GALILEO,
  52.         /** COMPASS only file. */
  53.         COMPASS,
  54.         /** QZSS only file. */
  55.         QZSS,
  56.         /** undefined file format. */
  57.         UNDEFINED
  58.     }

  59.     /** Orbit type indicator. */
  60.     public enum SP3OrbitType {
  61.         /** fitted. */
  62.         FIT,
  63.         /** extrapolated or predicted. */
  64.         EXT,
  65.         /** broadcast. */
  66.         BCT,
  67.         /** fitted after applying a Helmert transformation. */
  68.         HLM,
  69.         /** other type, defined by SP3 file producing agency.
  70.          * @since 9.3
  71.          */
  72.         OTHER;

  73.         /** Parse a string to get the type.
  74.          * @param s string to parse
  75.          * @return the type corresponding to the string
  76.          */
  77.         public static SP3OrbitType parseType(final String s) {
  78.             final String normalizedString = s.trim().toUpperCase();
  79.             if ("EST".equals(normalizedString)) {
  80.                 return FIT;
  81.             } else if ("BHN".equals(normalizedString)) {
  82.                 // ESOC navigation team uses BHN for files produced
  83.                 // by their main parameter estimation program Bahn
  84.                 return FIT;
  85.             } else if ("PRO".equals(normalizedString)) {
  86.                 // ESOC navigation team uses PRO for files produced
  87.                 // by their orbit propagation program Propag
  88.                 return EXT;
  89.             } else {
  90.                 try {
  91.                     return valueOf(normalizedString);
  92.                 } catch (IllegalArgumentException iae) {
  93.                     return OTHER;
  94.                 }
  95.             }
  96.         }

  97.     }

  98.     /** Time system used throughout this SP3 file. */
  99.     public enum TimeSystem {
  100.         /** Global Positioning System. */
  101.         GPS,
  102.         /** GLONASS. */
  103.         GLO,
  104.         /** GALILEO. */
  105.         GAL,
  106.         /** International Atomic Time. */
  107.         TAI,
  108.         /** Coordinated Universal Time. */
  109.         UTC,
  110.         /** Quasi-Zenith System. */
  111.         QZS
  112.     }

  113.     /** File type. */
  114.     private SP3FileType type;

  115.     /** Time system. */
  116.     private TimeSystem timeSystem;

  117.     /** Epoch of the file. */
  118.     private AbsoluteDate epoch;

  119.     /** GPS week. */
  120.     private int gpsWeek;

  121.     /** Seconds of the current GPS week. */
  122.     private double secondsOfWeek;

  123.     /** Julian day. */
  124.     private int julianDay;

  125.     /** Day fraction. */
  126.     private double dayFraction;

  127.     /** Time-interval between epochs. */
  128.     private double epochInterval;

  129.     /** Number of epochs. */
  130.     private int numberOfEpochs;

  131.     /** Coordinate system. */
  132.     private String coordinateSystem;

  133.     /** Data used indicator. */
  134.     private String dataUsed;

  135.     /** Orbit type. */
  136.     private SP3OrbitType orbitType;

  137.     /** Key for orbit type.
  138.      * @since 9.3
  139.      */
  140.     private String orbitTypeKey;

  141.     /** Agency providing the file. */
  142.     private String agency;

  143.     /** Indicates if data contains velocity or not. */
  144.     private CartesianDerivativesFilter filter;

  145.     /** Time scale of dates in the ephemeris file. */
  146.     private TimeScale timeScale;

  147.     /** Time scale, as specified in the file. */
  148.     private String timeScaleString;

  149.     /** Standard gravitational parameter in m^3 / s^2. */
  150.     private final double mu;

  151.     /** Number of samples to use when interpolating. */
  152.     private final int interpolationSamples;

  153.     /** Maps {@link #coordinateSystem} to a {@link Frame}. */
  154.     private final Function<? super String, ? extends Frame> frameBuilder;

  155.     /** A map containing satellite information. */
  156.     private Map<String, SP3Ephemeris> satellites;

  157.     /**
  158.      * Create a new SP3 file object.
  159.      *
  160.      * @param mu                   is the standard gravitational parameter in m^3 / s^2.
  161.      * @param interpolationSamples number of samples to use in interpolation.
  162.      * @param frameBuilder         for constructing a reference frame from the identifier
  163.      *                             in the file.
  164.      */
  165.     SP3File(final double mu,
  166.             final int interpolationSamples,
  167.             final Function<? super String, ? extends Frame> frameBuilder) {
  168.         this.mu = mu;
  169.         this.interpolationSamples = interpolationSamples;
  170.         this.frameBuilder = frameBuilder;
  171.         // must be linked has map to preserve order of satellites in the file.
  172.         satellites = new LinkedHashMap<>();
  173.     }

  174.     /**
  175.      * Set the derivatives filter.
  176.      *
  177.      * @param filter that indicates which derivatives of position are available.
  178.      */
  179.     void setFilter(final CartesianDerivativesFilter filter) {
  180.         this.filter = filter;
  181.     }

  182.     /**
  183.      * Set the time scale.
  184.      *
  185.      * @param timeScale use to parse dates in this file.
  186.      */
  187.     void setTimeScale(final TimeScale timeScale) {
  188.         this.timeScale = timeScale;
  189.     }

  190.     /**
  191.      * Set the string used to define the time scale.
  192.      *
  193.      * @param timeScaleString the time scale identifier used in the file.
  194.      */
  195.     void setTimeScaleString(final String timeScaleString) {
  196.         this.timeScaleString = timeScaleString;
  197.     }

  198.     /** Returns the {@link SP3FileType} associated with this SP3 file.
  199.      * @return the file type for this SP3 file
  200.      */
  201.     public SP3FileType getType() {
  202.         return type;
  203.     }

  204.     /** Set the file type for this SP3 file.
  205.      * @param fileType the file type to be set
  206.      */
  207.     void setType(final SP3FileType fileType) {
  208.         this.type = fileType;
  209.     }

  210.     /** Returns the {@link TimeSystem} used to time-stamp position entries.
  211.      * @return the {@link TimeSystem} of the orbit file
  212.      */
  213.     public TimeSystem getTimeSystem() {
  214.         return timeSystem;
  215.     }

  216.     /** Set the time system used in this SP3 file.
  217.      * @param system the time system to be set
  218.      */
  219.     void setTimeSystem(final TimeSystem system) {
  220.         this.timeSystem = system;
  221.     }

  222.     /** Returns the data used indicator from the SP3 file.
  223.      * @return the data used indicator (unparsed)
  224.      */
  225.     public String getDataUsed() {
  226.         return dataUsed;
  227.     }

  228.     /** Set the data used indicator for this SP3 file.
  229.      * @param data the data used indicator to be set
  230.      */
  231.     void setDataUsed(final String data) {
  232.         this.dataUsed = data;
  233.     }

  234.     /** Returns the start epoch of the orbit file.
  235.      * @return the start epoch
  236.      */
  237.     public AbsoluteDate getEpoch() {
  238.         return epoch;
  239.     }

  240.     /** Set the epoch of the SP3 file.
  241.      * @param time the epoch to be set
  242.      */
  243.     void setEpoch(final AbsoluteDate time) {
  244.         this.epoch = time;
  245.     }

  246.     /** Returns the GPS week as contained in the SP3 file.
  247.      * @return the GPS week of the SP3 file
  248.      */
  249.     public int getGpsWeek() {
  250.         return gpsWeek;
  251.     }

  252.     /** Set the GPS week of the SP3 file.
  253.      * @param week the GPS week to be set
  254.      */
  255.     void setGpsWeek(final int week) {
  256.         this.gpsWeek = week;
  257.     }

  258.     /** Returns the seconds of the GPS week as contained in the SP3 file.
  259.      * @return the seconds of the GPS week
  260.      */
  261.     public double getSecondsOfWeek() {
  262.         return secondsOfWeek;
  263.     }

  264.     /** Set the seconds of the GPS week for this SP3 file.
  265.      * @param seconds the seconds to be set
  266.      */
  267.     void setSecondsOfWeek(final double seconds) {
  268.         this.secondsOfWeek = seconds;
  269.     }

  270.     /** Returns the julian day for this SP3 file.
  271.      * @return the julian day
  272.      */
  273.     public int getJulianDay() {
  274.         return julianDay;
  275.     }

  276.     /** Set the julian day for this SP3 file.
  277.      * @param day the julian day to be set
  278.      */
  279.     void setJulianDay(final int day) {
  280.         this.julianDay = day;
  281.     }

  282.     /** Returns the day fraction for this SP3 file.
  283.      * @return the day fraction
  284.      */
  285.     public double getDayFraction() {
  286.         return dayFraction;
  287.     }

  288.     /** Set the day fraction for this SP3 file.
  289.      * @param fraction the day fraction to be set
  290.      */
  291.     void setDayFraction(final double fraction) {
  292.         this.dayFraction = fraction;
  293.     }

  294.     /** Returns the time interval between epochs (in seconds).
  295.      * @return the time interval between epochs
  296.      */
  297.     public double getEpochInterval() {
  298.         return epochInterval;
  299.     }

  300.     /** Set the epoch interval for this SP3 file.
  301.      * @param interval the interval between orbit entries
  302.      */
  303.     void setEpochInterval(final double interval) {
  304.         this.epochInterval = interval;
  305.     }

  306.     /** Returns the number of epochs contained in this orbit file.
  307.      * @return the number of epochs
  308.      */
  309.     public int getNumberOfEpochs() {
  310.         return numberOfEpochs;
  311.     }

  312.     /** Set the number of epochs as contained in the SP3 file.
  313.      * @param epochCount the number of epochs to be set
  314.      */
  315.     void setNumberOfEpochs(final int epochCount) {
  316.         this.numberOfEpochs = epochCount;
  317.     }

  318.     /** Returns the coordinate system of the entries in this orbit file.
  319.      * @return the coordinate system
  320.      */
  321.     public String getCoordinateSystem() {
  322.         return coordinateSystem;
  323.     }

  324.     /** Set the coordinate system used for the orbit entries.
  325.      * @param system the coordinate system to be set
  326.      */
  327.     void setCoordinateSystem(final String system) {
  328.         this.coordinateSystem = system;
  329.     }

  330.     /** Returns the {@link SP3OrbitType} for this SP3 file.
  331.      * @return the orbit type
  332.      */
  333.     public SP3OrbitType getOrbitType() {
  334.         return orbitType;
  335.     }

  336.     /** Set the {@link SP3OrbitType} for this SP3 file.
  337.      * @param oType the orbit type to be set
  338.      * @deprecated as of 9.4, replaced by {@link #setOrbitTypeKey(String)}
  339.      */
  340.     void setOrbitType(final SP3OrbitType oType) {
  341.         this.orbitType = oType;
  342.     }

  343.     /** Returns the orbit type key for this SP3 file.
  344.      * @return the orbit type key
  345.      * @since 9.3
  346.      */
  347.     public String getOrbitTypeKey() {
  348.         return orbitTypeKey;
  349.     }

  350.     /** Set the orbit type key for this SP3 file.
  351.      * @param oTypeKey the orbit type key to be set
  352.      * @since 9.3
  353.      */
  354.     void setOrbitTypeKey(final String oTypeKey) {
  355.         this.orbitTypeKey = oTypeKey;
  356.         this.orbitType    = SP3OrbitType.parseType(oTypeKey);
  357.     }

  358.     /** Returns the agency that prepared this SP3 file.
  359.      * @return the agency
  360.      */
  361.     public String getAgency() {
  362.         return agency;
  363.     }

  364.     /** Set the agency string for this SP3 file.
  365.      * @param agencyStr the agency string to be set
  366.      */
  367.     void setAgency(final String agencyStr) {
  368.         this.agency = agencyStr;
  369.     }

  370.     /** Add a new satellite with a given identifier to the list of
  371.      * stored satellites.
  372.      * @param satId the satellite identifier
  373.      */
  374.     public void addSatellite(final String satId) {
  375.         // only add satellites which have not been added before
  376.         satellites.putIfAbsent(satId, new SP3Ephemeris(satId));
  377.     }

  378.     @Override
  379.     public Map<String, SP3Ephemeris> getSatellites() {
  380.         return Collections.unmodifiableMap(satellites);
  381.     }

  382.     /** Get the number of satellites contained in this orbit file.
  383.      * @return the number of satellites
  384.      */
  385.     public int getSatelliteCount() {
  386.         return satellites.size();
  387.     }

  388.     /**
  389.      * Set the formal accuracy for a satellite.
  390.      *
  391.      * @param index    is the index of the satellite.
  392.      * @param accuracy of the satellite, in m.
  393.      */
  394.     void setAccuracy(final int index, final double accuracy) {
  395.         int n = index;
  396.         for (final SP3Ephemeris ephemeris : satellites.values()) {
  397.             if (n == 0) {
  398.                 ephemeris.setAccuracy(accuracy);
  399.                 return;
  400.             }
  401.             n--;
  402.         }
  403.     }

  404.     /**
  405.      * Get the formal accuracy for a satellite.
  406.      *
  407.      * @param index    is the index of the satellite.
  408.      * @return accuracy of the satellite, in m.
  409.      */
  410.     double getAccuracy(final int index) {
  411.         int n = index;
  412.         for (final SP3Ephemeris ephemeris : satellites.values()) {
  413.             if (n == 0) {
  414.                 return ephemeris.getAccuracy();
  415.             }
  416.             n--;
  417.         }
  418.         return Double.NaN;
  419.     }

  420.     /** Tests whether a satellite with the given id is contained in this orbit
  421.      * file.
  422.      * @param satId the satellite id
  423.      * @return {@code true} if the satellite is contained in the file,
  424.      *         {@code false} otherwise
  425.      */
  426.     public boolean containsSatellite(final String satId) {
  427.         return satellites.containsKey(satId);
  428.     }

  429.     /**
  430.      * Adds a new P/V coordinate for a given satellite.
  431.      *
  432.      * @param satId the satellite identifier
  433.      * @param coord the P/V coordinate of the satellite
  434.      */
  435.     void addSatelliteCoordinate(final String satId, final SP3Coordinate coord) {
  436.         satellites.get(satId).coordinates.add(coord);
  437.     }

  438.     /** An ephemeris for a single satellite in a SP3 file. */
  439.     public class SP3Ephemeris implements SatelliteEphemeris, EphemerisSegment {

  440.         /** Satellite ID. */
  441.         private final String id;
  442.         /** Ephemeris Data. */
  443.         private final List<SP3Coordinate> coordinates;
  444.         /** Accuracy in m. */
  445.         private double accuracy;

  446.         /**
  447.          * Create an ephemeris for a single satellite.
  448.          *
  449.          * @param id of the satellite.
  450.          */
  451.         SP3Ephemeris(final String id) {
  452.             this.id = id;
  453.             this.coordinates = new ArrayList<>();
  454.         }

  455.         @Override
  456.         public String getId() {
  457.             return this.id;
  458.         }

  459.         @Override
  460.         public double getMu() {
  461.             return mu;
  462.         }

  463.         @Override
  464.         public String getFrameCenterString() {
  465.             return SP3_FRAME_CENTER_STRING;
  466.         }

  467.         @Override
  468.         public String getFrameString() {
  469.             return getCoordinateSystem();
  470.         }

  471.         @Override
  472.         public Frame getFrame() {
  473.             return frameBuilder.apply(getFrameString());
  474.         }

  475.         @Override
  476.         public String getTimeScaleString() {
  477.             return timeScaleString;
  478.         }

  479.         @Override
  480.         public TimeScale getTimeScale() {
  481.             return timeScale;
  482.         }

  483.         @Override
  484.         public int getInterpolationSamples() {
  485.             return interpolationSamples;
  486.         }

  487.         @Override
  488.         public CartesianDerivativesFilter getAvailableDerivatives() {
  489.             return filter;
  490.         }

  491.         @Override
  492.         public List<SP3Coordinate> getCoordinates() {
  493.             return Collections.unmodifiableList(this.coordinates);
  494.         }

  495.         /** Returns a list containing only {@code this}. */
  496.         @Override
  497.         public List<SP3Ephemeris> getSegments() {
  498.             return Collections.singletonList(this);
  499.         }

  500.         @Override
  501.         public AbsoluteDate getStart() {
  502.             return coordinates.get(0).getDate();
  503.         }

  504.         @Override
  505.         public AbsoluteDate getStop() {
  506.             return coordinates.get(coordinates.size() - 1).getDate();
  507.         }

  508.         @Override
  509.         public BoundedPropagator getPropagator() {
  510.             return EphemerisSegment.super.getPropagator();
  511.         }

  512.         /**
  513.          * Set the accuracy for this satellite.
  514.          *
  515.          * @param accuracy in m.
  516.          */
  517.         void setAccuracy(final double accuracy) {
  518.             this.accuracy = accuracy;
  519.         }

  520.         /**
  521.          * Get the formal accuracy for this satellite.
  522.          *
  523.          * <p>The accuracy is limited by the SP3 standard to be a power of 2 in mm.
  524.          * The value returned here is in meters.</p>
  525.          *
  526.          * @return magnitude of one standard deviation, in m.
  527.          */
  528.         public double getAccuracy() {
  529.             return accuracy;
  530.         }

  531.     }

  532.     /** A single record of position clock and possibly derivatives in an SP3 file. */
  533.     public static class SP3Coordinate extends TimeStampedPVCoordinates {

  534.         /** Serializable UID. */
  535.         private static final long serialVersionUID = 20161116L;
  536.         /** Clock correction in s. */
  537.         private final double clock;
  538.         /** Clock rate in s / s. */
  539.         private final double clockRate;

  540.         /**
  541.          * Create a coordinate with only position.
  542.          *
  543.          * @param date     of validity.
  544.          * @param position of the satellite.
  545.          * @param clock    correction in s.
  546.          */
  547.         SP3Coordinate(final AbsoluteDate date,
  548.                       final Vector3D position,
  549.                       final double clock) {
  550.             this(date, position, Vector3D.ZERO, clock, 0);
  551.         }

  552.         /**
  553.          * Create a coordinate with position and velocity.
  554.          *
  555.          * @param date      of validity.
  556.          * @param position  of the satellite.
  557.          * @param velocity  of the satellite.
  558.          * @param clock     correction in s.
  559.          * @param clockRate in s / s.
  560.          */
  561.         SP3Coordinate(final AbsoluteDate date,
  562.                       final Vector3D position,
  563.                       final Vector3D velocity,
  564.                       final double clock,
  565.                       final double clockRate) {
  566.             super(date, position, velocity, Vector3D.ZERO);
  567.             this.clock = clock;
  568.             this.clockRate = clockRate;
  569.         }

  570.         /**
  571.          * Returns the clock correction value.
  572.          *
  573.          * @return the clock correction in s.
  574.          */
  575.         public double getClockCorrection() {
  576.             return clock;
  577.         }

  578.         /**
  579.          * Returns the clock rate.
  580.          *
  581.          * @return the clock rate of change in s/s.
  582.          */
  583.         public double getClockRateChange() {
  584.             return clockRate;
  585.         }

  586.     }

  587. }