SP3File.java

  1. /* Copyright 2002-2012 Space Applications Services
  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.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.Locale;
  23. import java.util.Map;
  24. import java.util.function.Function;

  25. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  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.         /** other type, defined by SP3 file producing agency.
  71.          * @since 9.3
  72.          */
  73.         OTHER;

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

  98.     }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  158.     /**
  159.      * Create a new SP3 file object.
  160.      *
  161.      * @param mu                   is the standard gravitational parameter in m^3 / s^2.
  162.      * @param interpolationSamples number of samples to use in interpolation.
  163.      * @param frameBuilder         for constructing a reference frame from the identifier
  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.     /** Returns the orbit type key for this SP3 file.
  337.      * @return the orbit type key
  338.      * @since 9.3
  339.      */
  340.     public String getOrbitTypeKey() {
  341.         return orbitTypeKey;
  342.     }

  343.     /** Set the orbit type key for this SP3 file.
  344.      * @param oTypeKey the orbit type key to be set
  345.      * @since 9.3
  346.      */
  347.     void setOrbitTypeKey(final String oTypeKey) {
  348.         this.orbitTypeKey = oTypeKey;
  349.         this.orbitType    = SP3OrbitType.parseType(oTypeKey);
  350.     }

  351.     /** Returns the agency that prepared this SP3 file.
  352.      * @return the agency
  353.      */
  354.     public String getAgency() {
  355.         return agency;
  356.     }

  357.     /** Set the agency string for this SP3 file.
  358.      * @param agencyStr the agency string to be set
  359.      */
  360.     void setAgency(final String agencyStr) {
  361.         this.agency = agencyStr;
  362.     }

  363.     /** Add a new satellite with a given identifier to the list of
  364.      * stored satellites.
  365.      * @param satId the satellite identifier
  366.      */
  367.     public void addSatellite(final String satId) {
  368.         // only add satellites which have not been added before
  369.         satellites.putIfAbsent(satId, new SP3Ephemeris(satId));
  370.     }

  371.     @Override
  372.     public Map<String, SP3Ephemeris> getSatellites() {
  373.         return Collections.unmodifiableMap(satellites);
  374.     }

  375.     /** Get the number of satellites contained in this orbit file.
  376.      * @return the number of satellites
  377.      */
  378.     public int getSatelliteCount() {
  379.         return satellites.size();
  380.     }

  381.     /**
  382.      * Set the formal accuracy for a satellite.
  383.      *
  384.      * @param index    is the index of the satellite.
  385.      * @param accuracy of the satellite, in m.
  386.      */
  387.     void setAccuracy(final int index, final double accuracy) {
  388.         int n = index;
  389.         for (final SP3Ephemeris ephemeris : satellites.values()) {
  390.             if (n == 0) {
  391.                 ephemeris.setAccuracy(accuracy);
  392.                 return;
  393.             }
  394.             n--;
  395.         }
  396.     }

  397.     /**
  398.      * Get the formal accuracy for a satellite.
  399.      *
  400.      * @param index    is the index of the satellite.
  401.      * @return accuracy of the satellite, in m.
  402.      */
  403.     double getAccuracy(final int index) {
  404.         int n = index;
  405.         for (final SP3Ephemeris ephemeris : satellites.values()) {
  406.             if (n == 0) {
  407.                 return ephemeris.getAccuracy();
  408.             }
  409.             n--;
  410.         }
  411.         return Double.NaN;
  412.     }

  413.     /** Tests whether a satellite with the given id is contained in this orbit
  414.      * file.
  415.      * @param satId the satellite id
  416.      * @return {@code true} if the satellite is contained in the file,
  417.      *         {@code false} otherwise
  418.      */
  419.     public boolean containsSatellite(final String satId) {
  420.         return satellites.containsKey(satId);
  421.     }

  422.     /**
  423.      * Adds a new P/V coordinate for a given satellite.
  424.      *
  425.      * @param satId the satellite identifier
  426.      * @param coord the P/V coordinate of the satellite
  427.      */
  428.     void addSatelliteCoordinate(final String satId, final SP3Coordinate coord) {
  429.         satellites.get(satId).coordinates.add(coord);
  430.     }

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

  433.         /** Satellite ID. */
  434.         private final String id;
  435.         /** Ephemeris Data. */
  436.         private final List<SP3Coordinate> coordinates;
  437.         /** Accuracy in m. */
  438.         private double accuracy;

  439.         /**
  440.          * Create an ephemeris for a single satellite.
  441.          *
  442.          * @param id of the satellite.
  443.          */
  444.         SP3Ephemeris(final String id) {
  445.             this.id = id;
  446.             this.coordinates = new ArrayList<>();
  447.         }

  448.         @Override
  449.         public String getId() {
  450.             return this.id;
  451.         }

  452.         @Override
  453.         public double getMu() {
  454.             return mu;
  455.         }

  456.         @Override
  457.         public String getFrameCenterString() {
  458.             return SP3_FRAME_CENTER_STRING;
  459.         }

  460.         @Override
  461.         public String getFrameString() {
  462.             return getCoordinateSystem();
  463.         }

  464.         @Override
  465.         public Frame getFrame() {
  466.             return frameBuilder.apply(getFrameString());
  467.         }

  468.         @Override
  469.         public String getTimeScaleString() {
  470.             return timeScaleString;
  471.         }

  472.         @Override
  473.         public TimeScale getTimeScale() {
  474.             return timeScale;
  475.         }

  476.         @Override
  477.         public int getInterpolationSamples() {
  478.             return interpolationSamples;
  479.         }

  480.         @Override
  481.         public CartesianDerivativesFilter getAvailableDerivatives() {
  482.             return filter;
  483.         }

  484.         @Override
  485.         public List<SP3Coordinate> getCoordinates() {
  486.             return Collections.unmodifiableList(this.coordinates);
  487.         }

  488.         /** Returns a list containing only {@code this}. */
  489.         @Override
  490.         public List<SP3Ephemeris> getSegments() {
  491.             return Collections.singletonList(this);
  492.         }

  493.         @Override
  494.         public AbsoluteDate getStart() {
  495.             return coordinates.get(0).getDate();
  496.         }

  497.         @Override
  498.         public AbsoluteDate getStop() {
  499.             return coordinates.get(coordinates.size() - 1).getDate();
  500.         }

  501.         @Override
  502.         public BoundedPropagator getPropagator() {
  503.             return EphemerisSegment.super.getPropagator();
  504.         }

  505.         /**
  506.          * Set the accuracy for this satellite.
  507.          *
  508.          * @param accuracy in m.
  509.          */
  510.         void setAccuracy(final double accuracy) {
  511.             this.accuracy = accuracy;
  512.         }

  513.         /**
  514.          * Get the formal accuracy for this satellite.
  515.          *
  516.          * <p>The accuracy is limited by the SP3 standard to be a power of 2 in mm.
  517.          * The value returned here is in meters.</p>
  518.          *
  519.          * @return magnitude of one standard deviation, in m.
  520.          */
  521.         public double getAccuracy() {
  522.             return accuracy;
  523.         }

  524.     }

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

  527.         /** Serializable UID. */
  528.         private static final long serialVersionUID = 20161116L;
  529.         /** Clock correction in s. */
  530.         private final double clock;
  531.         /** Clock rate in s / s. */
  532.         private final double clockRate;

  533.         /**
  534.          * Create a coordinate with only position.
  535.          *
  536.          * @param date     of validity.
  537.          * @param position of the satellite.
  538.          * @param clock    correction in s.
  539.          */
  540.         SP3Coordinate(final AbsoluteDate date,
  541.                       final Vector3D position,
  542.                       final double clock) {
  543.             this(date, position, Vector3D.ZERO, clock, 0);
  544.         }

  545.         /**
  546.          * Create a coordinate with position and velocity.
  547.          *
  548.          * @param date      of validity.
  549.          * @param position  of the satellite.
  550.          * @param velocity  of the satellite.
  551.          * @param clock     correction in s.
  552.          * @param clockRate in s / s.
  553.          */
  554.         SP3Coordinate(final AbsoluteDate date,
  555.                       final Vector3D position,
  556.                       final Vector3D velocity,
  557.                       final double clock,
  558.                       final double clockRate) {
  559.             super(date, position, velocity, Vector3D.ZERO);
  560.             this.clock = clock;
  561.             this.clockRate = clockRate;
  562.         }

  563.         /**
  564.          * Returns the clock correction value.
  565.          *
  566.          * @return the clock correction in s.
  567.          */
  568.         public double getClockCorrection() {
  569.             return clock;
  570.         }

  571.         /**
  572.          * Returns the clock rate.
  573.          *
  574.          * @return the clock rate of change in s/s.
  575.          */
  576.         public double getClockRateChange() {
  577.             return clockRate;
  578.         }

  579.     }

  580. }