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.errors.OrekitException;
  26. import org.orekit.files.general.EphemerisFile;
  27. import org.orekit.frames.Frame;
  28. import org.orekit.propagation.BoundedPropagator;
  29. import org.orekit.time.AbsoluteDate;
  30. import org.orekit.time.TimeScale;
  31. import org.orekit.utils.CartesianDerivativesFilter;
  32. import org.orekit.utils.TimeStampedPVCoordinates;

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

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

  60.     /** Orbit type indicator. */
  61.     public enum SP3OrbitType {
  62.         /** fitted. */
  63.         FIT,
  64.         /** extrapolated or predicted. */
  65.         EXT,
  66.         /** broadcast. */
  67.         BCT,
  68.         /** fitted after applying a Helmert transformation. */
  69.         HLM;

  70.         /** Parse a string to get the type.
  71.          * @param s string to parse
  72.          * @return the type corresponding to the string
  73.          * @exception IllegalArgumentException if the string does not correspond to a type
  74.          */
  75.         public static SP3OrbitType parseType(final String s) {
  76.             final String normalizedString = s.trim().toUpperCase();
  77.             if ("EST".equals(normalizedString)) {
  78.                 return FIT;
  79.             } else {
  80.                 return valueOf(normalizedString);
  81.             }
  82.         }

  83.     }

  84.     /** Time system used throughout this SP3 file. */
  85.     public enum TimeSystem {
  86.         /** Global Positioning System. */
  87.         GPS,
  88.         /** GLONASS. */
  89.         GLO,
  90.         /** GALILEO. */
  91.         GAL,
  92.         /** International Atomic Time. */
  93.         TAI,
  94.         /** Coordinated Universal Time. */
  95.         UTC,
  96.         /** Quasi-Zenith System. */
  97.         QZS
  98.     }

  99.     /** File type. */
  100.     private SP3FileType type;

  101.     /** Time system. */
  102.     private TimeSystem timeSystem;

  103.     /** Epoch of the file. */
  104.     private AbsoluteDate epoch;

  105.     /** GPS week. */
  106.     private int gpsWeek;

  107.     /** Seconds of the current GPS week. */
  108.     private double secondsOfWeek;

  109.     /** Julian day. */
  110.     private int julianDay;

  111.     /** Day fraction. */
  112.     private double dayFraction;

  113.     /** Time-interval between epochs. */
  114.     private double epochInterval;

  115.     /** Number of epochs. */
  116.     private int numberOfEpochs;

  117.     /** Coordinate system. */
  118.     private String coordinateSystem;

  119.     /** Data used indicator. */
  120.     private String dataUsed;

  121.     /** Orbit type. */
  122.     private SP3OrbitType orbitType;

  123.     /** Agency providing the file. */
  124.     private String agency;

  125.     /** Indicates if data contains velocity or not. */
  126.     private CartesianDerivativesFilter filter;

  127.     /** Time scale of dates in the ephemeris file. */
  128.     private TimeScale timeScale;

  129.     /** Time scale, as specified in the file. */
  130.     private String timeScaleString;

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

  133.     /** Number of samples to use when interpolating. */
  134.     private final int interpolationSamples;

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

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

  139.     /**
  140.      * Create a new SP3 file object.
  141.      *
  142.      * @param mu                   is the standard gravitational parameter in m^3 / s^2.
  143.      * @param interpolationSamples number of samples to use in interpolation.
  144.      * @param frameBuilder         for constructing a reference frame from the identifier
  145.      *                             in the file.
  146.      */
  147.     SP3File(final double mu,
  148.             final int interpolationSamples,
  149.             final Function<? super String, ? extends Frame> frameBuilder) {
  150.         this.mu = mu;
  151.         this.interpolationSamples = interpolationSamples;
  152.         this.frameBuilder = frameBuilder;
  153.         // must be linked has map to preserve order of satellites in the file.
  154.         satellites = new LinkedHashMap<>();
  155.     }

  156.     /**
  157.      * Set the derivatives filter.
  158.      *
  159.      * @param filter that indicates which derivatives of position are available.
  160.      */
  161.     void setFilter(final CartesianDerivativesFilter filter) {
  162.         this.filter = filter;
  163.     }

  164.     /**
  165.      * Set the time scale.
  166.      *
  167.      * @param timeScale use to parse dates in this file.
  168.      */
  169.     void setTimeScale(final TimeScale timeScale) {
  170.         this.timeScale = timeScale;
  171.     }

  172.     /**
  173.      * Set the string used to define the time scale.
  174.      *
  175.      * @param timeScaleString the time scale identifier used in the file.
  176.      */
  177.     void setTimeScaleString(final String timeScaleString) {
  178.         this.timeScaleString = timeScaleString;
  179.     }

  180.     /** Returns the {@link SP3FileType} associated with this SP3 file.
  181.      * @return the file type for this SP3 file
  182.      */
  183.     public SP3FileType getType() {
  184.         return type;
  185.     }

  186.     /** Set the file type for this SP3 file.
  187.      * @param fileType the file type to be set
  188.      */
  189.     void setType(final SP3FileType fileType) {
  190.         this.type = fileType;
  191.     }

  192.     /** Returns the {@link TimeSystem} used to time-stamp position entries.
  193.      * @return the {@link TimeSystem} of the orbit file
  194.      */
  195.     public TimeSystem getTimeSystem() {
  196.         return timeSystem;
  197.     }

  198.     /** Set the time system used in this SP3 file.
  199.      * @param system the time system to be set
  200.      */
  201.     void setTimeSystem(final TimeSystem system) {
  202.         this.timeSystem = system;
  203.     }

  204.     /** Returns the data used indicator from the SP3 file.
  205.      * @return the data used indicator (unparsed)
  206.      */
  207.     public String getDataUsed() {
  208.         return dataUsed;
  209.     }

  210.     /** Set the data used indicator for this SP3 file.
  211.      * @param data the data used indicator to be set
  212.      */
  213.     void setDataUsed(final String data) {
  214.         this.dataUsed = data;
  215.     }

  216.     /** Returns the start epoch of the orbit file.
  217.      * @return the start epoch
  218.      */
  219.     public AbsoluteDate getEpoch() {
  220.         return epoch;
  221.     }

  222.     /** Set the epoch of the SP3 file.
  223.      * @param time the epoch to be set
  224.      */
  225.     void setEpoch(final AbsoluteDate time) {
  226.         this.epoch = time;
  227.     }

  228.     /** Returns the GPS week as contained in the SP3 file.
  229.      * @return the GPS week of the SP3 file
  230.      */
  231.     public int getGpsWeek() {
  232.         return gpsWeek;
  233.     }

  234.     /** Set the GPS week of the SP3 file.
  235.      * @param week the GPS week to be set
  236.      */
  237.     void setGpsWeek(final int week) {
  238.         this.gpsWeek = week;
  239.     }

  240.     /** Returns the seconds of the GPS week as contained in the SP3 file.
  241.      * @return the seconds of the GPS week
  242.      */
  243.     public double getSecondsOfWeek() {
  244.         return secondsOfWeek;
  245.     }

  246.     /** Set the seconds of the GPS week for this SP3 file.
  247.      * @param seconds the seconds to be set
  248.      */
  249.     void setSecondsOfWeek(final double seconds) {
  250.         this.secondsOfWeek = seconds;
  251.     }

  252.     /** Returns the julian day for this SP3 file.
  253.      * @return the julian day
  254.      */
  255.     public int getJulianDay() {
  256.         return julianDay;
  257.     }

  258.     /** Set the julian day for this SP3 file.
  259.      * @param day the julian day to be set
  260.      */
  261.     void setJulianDay(final int day) {
  262.         this.julianDay = day;
  263.     }

  264.     /** Returns the day fraction for this SP3 file.
  265.      * @return the day fraction
  266.      */
  267.     public double getDayFraction() {
  268.         return dayFraction;
  269.     }

  270.     /** Set the day fraction for this SP3 file.
  271.      * @param fraction the day fraction to be set
  272.      */
  273.     void setDayFraction(final double fraction) {
  274.         this.dayFraction = fraction;
  275.     }

  276.     /** Returns the time interval between epochs (in seconds).
  277.      * @return the time interval between epochs
  278.      */
  279.     public double getEpochInterval() {
  280.         return epochInterval;
  281.     }

  282.     /** Set the epoch interval for this SP3 file.
  283.      * @param interval the interval between orbit entries
  284.      */
  285.     void setEpochInterval(final double interval) {
  286.         this.epochInterval = interval;
  287.     }

  288.     /** Returns the number of epochs contained in this orbit file.
  289.      * @return the number of epochs
  290.      */
  291.     public int getNumberOfEpochs() {
  292.         return numberOfEpochs;
  293.     }

  294.     /** Set the number of epochs as contained in the SP3 file.
  295.      * @param epochCount the number of epochs to be set
  296.      */
  297.     void setNumberOfEpochs(final int epochCount) {
  298.         this.numberOfEpochs = epochCount;
  299.     }

  300.     /** Returns the coordinate system of the entries in this orbit file.
  301.      * @return the coordinate system
  302.      */
  303.     public String getCoordinateSystem() {
  304.         return coordinateSystem;
  305.     }

  306.     /** Set the coordinate system used for the orbit entries.
  307.      * @param system the coordinate system to be set
  308.      */
  309.     void setCoordinateSystem(final String system) {
  310.         this.coordinateSystem = system;
  311.     }

  312.     /** Returns the {@link SP3OrbitType} for this SP3 file.
  313.      * @return the orbit type
  314.      */
  315.     public SP3OrbitType getOrbitType() {
  316.         return orbitType;
  317.     }

  318.     /** Set the {@link SP3OrbitType} for this SP3 file.
  319.      * @param oType the orbit type to be set
  320.      */
  321.     void setOrbitType(final SP3OrbitType oType) {
  322.         this.orbitType = oType;
  323.     }

  324.     /** Returns the agency that prepared this SP3 file.
  325.      * @return the agency
  326.      */
  327.     public String getAgency() {
  328.         return agency;
  329.     }

  330.     /** Set the agency string for this SP3 file.
  331.      * @param agencyStr the agency string to be set
  332.      */
  333.     void setAgency(final String agencyStr) {
  334.         this.agency = agencyStr;
  335.     }

  336.     /** Add a new satellite with a given identifier to the list of
  337.      * stored satellites.
  338.      * @param satId the satellite identifier
  339.      */
  340.     public void addSatellite(final String satId) {
  341.         // only add satellites which have not been added before
  342.         satellites.putIfAbsent(satId, new SP3Ephemeris(satId));
  343.     }

  344.     @Override
  345.     public Map<String, SP3Ephemeris> getSatellites() {
  346.         return Collections.unmodifiableMap(satellites);
  347.     }

  348.     /** Get the number of satellites contained in this orbit file.
  349.      * @return the number of satellites
  350.      */
  351.     public int getSatelliteCount() {
  352.         return satellites.size();
  353.     }

  354.     /**
  355.      * Set the formal accuracy for a satellite.
  356.      *
  357.      * @param index    is the index of the satellite.
  358.      * @param accuracy of the satellite, in m.
  359.      */
  360.     void setAccuracy(final int index, final double accuracy) {
  361.         int n = index;
  362.         for (final SP3Ephemeris ephemeris : satellites.values()) {
  363.             if (n == 0) {
  364.                 ephemeris.setAccuracy(accuracy);
  365.                 return;
  366.             }
  367.             n--;
  368.         }
  369.     }

  370.     /**
  371.      * Get the formal accuracy for a satellite.
  372.      *
  373.      * @param index    is the index of the satellite.
  374.      * @return accuracy of the satellite, in m.
  375.      */
  376.     double getAccuracy(final int index) {
  377.         int n = index;
  378.         for (final SP3Ephemeris ephemeris : satellites.values()) {
  379.             if (n == 0) {
  380.                 return ephemeris.getAccuracy();
  381.             }
  382.             n--;
  383.         }
  384.         return Double.NaN;
  385.     }

  386.     /** Tests whether a satellite with the given id is contained in this orbit
  387.      * file.
  388.      * @param satId the satellite id
  389.      * @return {@code true} if the satellite is contained in the file,
  390.      *         {@code false} otherwise
  391.      */
  392.     public boolean containsSatellite(final String satId) {
  393.         return satellites.containsKey(satId);
  394.     }

  395.     /**
  396.      * Adds a new P/V coordinate for a given satellite.
  397.      *
  398.      * @param satId the satellite identifier
  399.      * @param coord the P/V coordinate of the satellite
  400.      */
  401.     void addSatelliteCoordinate(final String satId, final SP3Coordinate coord) {
  402.         satellites.get(satId).coordinates.add(coord);
  403.     }

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

  406.         /** Satellite ID. */
  407.         private final String id;
  408.         /** Ephemeris Data. */
  409.         private final List<SP3Coordinate> coordinates;
  410.         /** Accuracy in m. */
  411.         private double accuracy;

  412.         /**
  413.          * Create an ephemeris for a single satellite.
  414.          *
  415.          * @param id of the satellite.
  416.          */
  417.         SP3Ephemeris(final String id) {
  418.             this.id = id;
  419.             this.coordinates = new ArrayList<>();
  420.         }

  421.         @Override
  422.         public String getId() {
  423.             return this.id;
  424.         }

  425.         @Override
  426.         public double getMu() {
  427.             return mu;
  428.         }

  429.         @Override
  430.         public String getFrameCenterString() {
  431.             return SP3_FRAME_CENTER_STRING;
  432.         }

  433.         @Override
  434.         public String getFrameString() {
  435.             return getCoordinateSystem();
  436.         }

  437.         @Override
  438.         public Frame getFrame() throws OrekitException {
  439.             return frameBuilder.apply(getFrameString());
  440.         }

  441.         @Override
  442.         public String getTimeScaleString() {
  443.             return timeScaleString;
  444.         }

  445.         @Override
  446.         public TimeScale getTimeScale() throws OrekitException {
  447.             return timeScale;
  448.         }

  449.         @Override
  450.         public int getInterpolationSamples() {
  451.             return interpolationSamples;
  452.         }

  453.         @Override
  454.         public CartesianDerivativesFilter getAvailableDerivatives() {
  455.             return filter;
  456.         }

  457.         @Override
  458.         public List<SP3Coordinate> getCoordinates() {
  459.             return Collections.unmodifiableList(this.coordinates);
  460.         }

  461.         /** Returns a list containing only {@code this}. */
  462.         @Override
  463.         public List<SP3Ephemeris> getSegments() {
  464.             return Collections.singletonList(this);
  465.         }

  466.         @Override
  467.         public AbsoluteDate getStart() {
  468.             return coordinates.get(0).getDate();
  469.         }

  470.         @Override
  471.         public AbsoluteDate getStop() {
  472.             return coordinates.get(coordinates.size() - 1).getDate();
  473.         }

  474.         @Override
  475.         public BoundedPropagator getPropagator() throws OrekitException {
  476.             return EphemerisSegment.super.getPropagator();
  477.         }

  478.         /**
  479.          * Set the accuracy for this satellite.
  480.          *
  481.          * @param accuracy in m.
  482.          */
  483.         void setAccuracy(final double accuracy) {
  484.             this.accuracy = accuracy;
  485.         }

  486.         /**
  487.          * Get the formal accuracy for this satellite.
  488.          *
  489.          * <p>The accuracy is limited by the SP3 standard to be a power of 2 in mm.
  490.          * The value returned here is in meters.</p>
  491.          *
  492.          * @return magnitude of one standard deviation, in m.
  493.          */
  494.         public double getAccuracy() {
  495.             return accuracy;
  496.         }

  497.     }

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

  500.         /** Serializable UID. */
  501.         private static final long serialVersionUID = 20161116L;
  502.         /** Clock correction in s. */
  503.         private final double clock;
  504.         /** Clock rate in s / s. */
  505.         private final double clockRate;

  506.         /**
  507.          * Create a coordinate with only position.
  508.          *
  509.          * @param date     of validity.
  510.          * @param position of the satellite.
  511.          * @param clock    correction in s.
  512.          */
  513.         SP3Coordinate(final AbsoluteDate date,
  514.                       final Vector3D position,
  515.                       final double clock) {
  516.             this(date, position, Vector3D.ZERO, clock, 0);
  517.         }

  518.         /**
  519.          * Create a coordinate with position and velocity.
  520.          *
  521.          * @param date      of validity.
  522.          * @param position  of the satellite.
  523.          * @param velocity  of the satellite.
  524.          * @param clock     correction in s.
  525.          * @param clockRate in s / s.
  526.          */
  527.         SP3Coordinate(final AbsoluteDate date,
  528.                       final Vector3D position,
  529.                       final Vector3D velocity,
  530.                       final double clock,
  531.                       final double clockRate) {
  532.             super(date, position, velocity, Vector3D.ZERO);
  533.             this.clock = clock;
  534.             this.clockRate = clockRate;
  535.         }

  536.         /**
  537.          * Returns the clock correction value.
  538.          *
  539.          * @return the clock correction in s.
  540.          */
  541.         public double getClockCorrection() {
  542.             return clock;
  543.         }

  544.         /**
  545.          * Returns the clock rate.
  546.          *
  547.          * @return the clock rate of change in s/s.
  548.          */
  549.         public double getClockRateChange() {
  550.             return clockRate;
  551.         }

  552.     }

  553. }