SP3.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.gnss.TimeSystem;
  29. import org.orekit.propagation.BoundedPropagator;
  30. import org.orekit.time.AbsoluteDate;
  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 SP3
  39.     implements EphemerisFile<SP3.SP3Coordinate, SP3.SP3Ephemeris> {
  40.     /** String representation of the center of ephemeris coordinate system. **/
  41.     public static final String SP3_FRAME_CENTER_STRING = "EARTH";

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

  65.     /** Orbit type indicator. */
  66.     public enum SP3OrbitType {
  67.         /** fitted. */
  68.         FIT,
  69.         /** extrapolated or predicted. */
  70.         EXT,
  71.         /** broadcast. */
  72.         BCT,
  73.         /** fitted after applying a Helmert transformation. */
  74.         HLM,
  75.         /** other type, defined by SP3 file producing agency.
  76.          * @since 9.3
  77.          */
  78.         OTHER;

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

  103.     }

  104.     /** File type. */
  105.     private SP3FileType type;

  106.     /** Time system. */
  107.     private TimeSystem timeSystem;

  108.     /** Epoch of the file. */
  109.     private AbsoluteDate epoch;

  110.     /** GPS week. */
  111.     private int gpsWeek;

  112.     /** Seconds of the current GPS week. */
  113.     private double secondsOfWeek;

  114.     /** Julian day. */
  115.     private int julianDay;

  116.     /** Day fraction. */
  117.     private double dayFraction;

  118.     /** Time-interval between epochs. */
  119.     private double epochInterval;

  120.     /** Number of epochs. */
  121.     private int numberOfEpochs;

  122.     /** Coordinate system. */
  123.     private String coordinateSystem;

  124.     /** Data used indicator. */
  125.     private String dataUsed;

  126.     /** Orbit type. */
  127.     private SP3OrbitType orbitType;

  128.     /** Key for orbit type.
  129.      * @since 9.3
  130.      */
  131.     private String orbitTypeKey;

  132.     /** Agency providing the file. */
  133.     private String agency;

  134.     /** Indicates if data contains velocity or not. */
  135.     private CartesianDerivativesFilter filter;

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

  138.     /** Number of samples to use when interpolating. */
  139.     private final int interpolationSamples;

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

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

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

  160.     /**
  161.      * Set the derivatives filter.
  162.      *
  163.      * @param filter that indicates which derivatives of position are available.
  164.      */
  165.     public void setFilter(final CartesianDerivativesFilter filter) {
  166.         this.filter = filter;
  167.     }

  168.     /** Returns the {@link SP3FileType} associated with this SP3 file.
  169.      * @return the file type for this SP3 file
  170.      */
  171.     public SP3FileType getType() {
  172.         return type;
  173.     }

  174.     /** Set the file type for this SP3 file.
  175.      * @param fileType the file type to be set
  176.      */
  177.     public void setType(final SP3FileType fileType) {
  178.         this.type = fileType;
  179.     }

  180.     /** Returns the {@link TimeSystem} used to time-stamp position entries.
  181.      * @return the {@link TimeSystem} of the orbit file
  182.      */
  183.     public TimeSystem getTimeSystem() {
  184.         return timeSystem;
  185.     }

  186.     /** Set the time system used in this SP3 file.
  187.      * @param system the time system to be set
  188.      */
  189.     public void setTimeSystem(final TimeSystem system) {
  190.         this.timeSystem = system;
  191.     }

  192.     /** Returns the data used indicator from the SP3 file.
  193.      * @return the data used indicator (unparsed)
  194.      */
  195.     public String getDataUsed() {
  196.         return dataUsed;
  197.     }

  198.     /** Set the data used indicator for this SP3 file.
  199.      * @param data the data used indicator to be set
  200.      */
  201.     public void setDataUsed(final String data) {
  202.         this.dataUsed = data;
  203.     }

  204.     /** Returns the start epoch of the orbit file.
  205.      * @return the start epoch
  206.      */
  207.     public AbsoluteDate getEpoch() {
  208.         return epoch;
  209.     }

  210.     /** Set the epoch of the SP3 file.
  211.      * @param time the epoch to be set
  212.      */
  213.     public void setEpoch(final AbsoluteDate time) {
  214.         this.epoch = time;
  215.     }

  216.     /** Returns the GPS week as contained in the SP3 file.
  217.      * @return the GPS week of the SP3 file
  218.      */
  219.     public int getGpsWeek() {
  220.         return gpsWeek;
  221.     }

  222.     /** Set the GPS week of the SP3 file.
  223.      * @param week the GPS week to be set
  224.      */
  225.     public void setGpsWeek(final int week) {
  226.         this.gpsWeek = week;
  227.     }

  228.     /** Returns the seconds of the GPS week as contained in the SP3 file.
  229.      * @return the seconds of the GPS week
  230.      */
  231.     public double getSecondsOfWeek() {
  232.         return secondsOfWeek;
  233.     }

  234.     /** Set the seconds of the GPS week for this SP3 file.
  235.      * @param seconds the seconds to be set
  236.      */
  237.     public void setSecondsOfWeek(final double seconds) {
  238.         this.secondsOfWeek = seconds;
  239.     }

  240.     /** Returns the julian day for this SP3 file.
  241.      * @return the julian day
  242.      */
  243.     public int getJulianDay() {
  244.         return julianDay;
  245.     }

  246.     /** Set the julian day for this SP3 file.
  247.      * @param day the julian day to be set
  248.      */
  249.     public void setJulianDay(final int day) {
  250.         this.julianDay = day;
  251.     }

  252.     /** Returns the day fraction for this SP3 file.
  253.      * @return the day fraction
  254.      */
  255.     public double getDayFraction() {
  256.         return dayFraction;
  257.     }

  258.     /** Set the day fraction for this SP3 file.
  259.      * @param fraction the day fraction to be set
  260.      */
  261.     public void setDayFraction(final double fraction) {
  262.         this.dayFraction = fraction;
  263.     }

  264.     /** Returns the time interval between epochs (in seconds).
  265.      * @return the time interval between epochs
  266.      */
  267.     public double getEpochInterval() {
  268.         return epochInterval;
  269.     }

  270.     /** Set the epoch interval for this SP3 file.
  271.      * @param interval the interval between orbit entries
  272.      */
  273.     public void setEpochInterval(final double interval) {
  274.         this.epochInterval = interval;
  275.     }

  276.     /** Returns the number of epochs contained in this orbit file.
  277.      * @return the number of epochs
  278.      */
  279.     public int getNumberOfEpochs() {
  280.         return numberOfEpochs;
  281.     }

  282.     /** Set the number of epochs as contained in the SP3 file.
  283.      * @param epochCount the number of epochs to be set
  284.      */
  285.     public void setNumberOfEpochs(final int epochCount) {
  286.         this.numberOfEpochs = epochCount;
  287.     }

  288.     /** Returns the coordinate system of the entries in this orbit file.
  289.      * @return the coordinate system
  290.      */
  291.     public String getCoordinateSystem() {
  292.         return coordinateSystem;
  293.     }

  294.     /** Set the coordinate system used for the orbit entries.
  295.      * @param system the coordinate system to be set
  296.      */
  297.     public void setCoordinateSystem(final String system) {
  298.         this.coordinateSystem = system;
  299.     }

  300.     /** Returns the {@link SP3OrbitType} for this SP3 file.
  301.      * @return the orbit type
  302.      */
  303.     public SP3OrbitType getOrbitType() {
  304.         return orbitType;
  305.     }

  306.     /** Returns the orbit type key for this SP3 file.
  307.      * @return the orbit type key
  308.      * @since 9.3
  309.      */
  310.     public String getOrbitTypeKey() {
  311.         return orbitTypeKey;
  312.     }

  313.     /** Set the orbit type key for this SP3 file.
  314.      * @param oTypeKey the orbit type key to be set
  315.      * @since 9.3
  316.      */
  317.     public void setOrbitTypeKey(final String oTypeKey) {
  318.         this.orbitTypeKey = oTypeKey;
  319.         this.orbitType    = SP3OrbitType.parseType(oTypeKey);
  320.     }

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

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

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

  341.     @Override
  342.     public Map<String, SP3Ephemeris> getSatellites() {
  343.         return Collections.unmodifiableMap(satellites);
  344.     }

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

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

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

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

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

  401.     /** An ephemeris for a single satellite in a SP3 file. */
  402.     public class SP3Ephemeris
  403.         implements  EphemerisFile.SatelliteEphemeris<SP3Coordinate, SP3Ephemeris>,
  404.                     EphemerisFile.EphemerisSegment<SP3Coordinate> {

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

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

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

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

  428.         @Override
  429.         public Frame getFrame() {
  430.             return frameBuilder.apply(SP3_FRAME_CENTER_STRING);
  431.         }

  432.         @Override
  433.         public int getInterpolationSamples() {
  434.             return interpolationSamples;
  435.         }

  436.         @Override
  437.         public CartesianDerivativesFilter getAvailableDerivatives() {
  438.             return filter;
  439.         }

  440.         @Override
  441.         public List<SP3Coordinate> getCoordinates() {
  442.             return Collections.unmodifiableList(this.coordinates);
  443.         }

  444.         /** Returns a list containing only {@code this}. */
  445.         @Override
  446.         public List<SP3Ephemeris> getSegments() {
  447.             return Collections.singletonList(this);
  448.         }

  449.         @Override
  450.         public AbsoluteDate getStart() {
  451.             return coordinates.get(0).getDate();
  452.         }

  453.         @Override
  454.         public AbsoluteDate getStop() {
  455.             return coordinates.get(coordinates.size() - 1).getDate();
  456.         }

  457.         @Override
  458.         public BoundedPropagator getPropagator() {
  459.             return EphemerisSegment.super.getPropagator();
  460.         }

  461.         /**
  462.          * Set the accuracy for this satellite.
  463.          *
  464.          * @param accuracy in m.
  465.          */
  466.         public void setAccuracy(final double accuracy) {
  467.             this.accuracy = accuracy;
  468.         }

  469.         /**
  470.          * Get the formal accuracy for this satellite.
  471.          *
  472.          * <p>The accuracy is limited by the SP3 standard to be a power of 2 in mm.
  473.          * The value returned here is in meters.</p>
  474.          *
  475.          * @return magnitude of one standard deviation, in m.
  476.          */
  477.         public double getAccuracy() {
  478.             return accuracy;
  479.         }

  480.     }

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

  483.         /** Serializable UID. */
  484.         private static final long serialVersionUID = 20161116L;
  485.         /** Clock correction in s. */
  486.         private final double clock;
  487.         /** Clock rate in s / s. */
  488.         private final double clockRate;

  489.         /**
  490.          * Create a coordinate with only position.
  491.          *
  492.          * @param date     of validity.
  493.          * @param position of the satellite.
  494.          * @param clock    correction in s.
  495.          */
  496.         public SP3Coordinate(final AbsoluteDate date,
  497.                              final Vector3D position,
  498.                              final double clock) {
  499.             this(date, position, Vector3D.ZERO, clock, 0);
  500.         }

  501.         /**
  502.          * Create a coordinate with position and velocity.
  503.          *
  504.          * @param date      of validity.
  505.          * @param position  of the satellite.
  506.          * @param velocity  of the satellite.
  507.          * @param clock     correction in s.
  508.          * @param clockRate in s / s.
  509.          */
  510.         public SP3Coordinate(final AbsoluteDate date,
  511.                              final Vector3D position,
  512.                              final Vector3D velocity,
  513.                              final double clock,
  514.                              final double clockRate) {
  515.             super(date, position, velocity, Vector3D.ZERO);
  516.             this.clock = clock;
  517.             this.clockRate = clockRate;
  518.         }

  519.         /**
  520.          * Returns the clock correction value.
  521.          *
  522.          * @return the clock correction in s.
  523.          */
  524.         public double getClockCorrection() {
  525.             return clock;
  526.         }

  527.         /**
  528.          * Returns the clock rate.
  529.          *
  530.          * @return the clock rate of change in s/s.
  531.          */
  532.         public double getClockRateChange() {
  533.             return clockRate;
  534.         }

  535.     }

  536. }