OrekitEphemerisFile.java

  1. /* Copyright 2016 Applied Defense Solutions (ADS)
  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.  * ADS 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.general;

  18. import java.util.ArrayList;
  19. import java.util.Collections;
  20. import java.util.List;
  21. import java.util.Map;
  22. import java.util.concurrent.ConcurrentHashMap;

  23. import org.orekit.annotation.DefaultDataContext;
  24. import org.orekit.bodies.CelestialBody;
  25. import org.orekit.data.DataContext;
  26. import org.orekit.errors.OrekitIllegalArgumentException;
  27. import org.orekit.errors.OrekitMessages;
  28. import org.orekit.frames.Frame;
  29. import org.orekit.propagation.SpacecraftState;
  30. import org.orekit.time.AbsoluteDate;
  31. import org.orekit.time.TimeScale;
  32. import org.orekit.utils.CartesianDerivativesFilter;
  33. import org.orekit.utils.TimeStampedPVCoordinates;

  34. /**
  35.  * A class for encapsulating Orekit propagators within an {@link EphemerisFile}
  36.  * complaint object that makes for easy serialization to external ephemeris
  37.  * formats like OEM.
  38.  *
  39.  * @author Hank Grabowski
  40.  * @since 9.0
  41.  *
  42.  */
  43. public class OrekitEphemerisFile implements EphemerisFile {

  44.     /** Hashmap of satellite ephemeris. **/
  45.     private final Map<String, OrekitSatelliteEphemeris> satellites;

  46.     /**
  47.      * Standard default constructor.
  48.      */
  49.     public OrekitEphemerisFile() {
  50.         this.satellites = new ConcurrentHashMap<String, OrekitSatelliteEphemeris>();
  51.     }

  52.     /** {@inheritDoc} */
  53.     @Override
  54.     public Map<String, OrekitSatelliteEphemeris> getSatellites() {
  55.         return Collections.unmodifiableMap(satellites);
  56.     }

  57.     /**
  58.      * Adds a new satellite to this object.
  59.      *
  60.      * @param id
  61.      *            ID to use for this satellite
  62.      * @return the new satellite object
  63.      */
  64.     public OrekitSatelliteEphemeris addSatellite(final String id) {
  65.         final OrekitSatelliteEphemeris newSat = new OrekitSatelliteEphemeris(id);
  66.         this.satellites.put(id, newSat);
  67.         return newSat;
  68.     }

  69.     /**
  70.      * Inner class of {@link OrekitEphemerisFile} that defines the
  71.      * {@link OrekitSatelliteEphemeris} corresponding object for this ephemeris type.
  72.      */
  73.     public static class OrekitSatelliteEphemeris implements SatelliteEphemeris {

  74.         /**
  75.          * Defines the default interpolation sample size if it is not specified
  76.          * on a segment.
  77.          **/
  78.         public static final int DEFAULT_INTERPOLATION_SIZE = 7; // TODO change default interpolation size to 2 in 11.0 to be consistent with default interpolation degree in OEMParser

  79.         /** ID of the space object encapsulated here. **/
  80.         private final String id;

  81.         /** Earliest date of this file. **/
  82.         private AbsoluteDate startDate;

  83.         /** Latest date of this file. **/
  84.         private AbsoluteDate stopDate;

  85.         /** List of segments in the file. **/
  86.         private final List<OrekitEphemerisSegment> segments;

  87.         /**
  88.          * Standard constructor for building the satellite Ephemeris object.
  89.          *
  90.          * @param id
  91.          *            the ID of the space object for this data
  92.          */
  93.         public OrekitSatelliteEphemeris(final String id) {
  94.             this.id = id;
  95.             this.segments = new ArrayList<OrekitEphemerisSegment>();
  96.         }

  97.         /** {@inheritDoc} */
  98.         @Override
  99.         public String getId() {
  100.             return id;
  101.         }

  102.         /** {@inheritDoc} */
  103.         @Override
  104.         public double getMu() {
  105.             if (this.segments.size() == 0) {
  106.                 return 0;
  107.             } else {
  108.                 return this.segments.get(0).getMu();
  109.             }
  110.         }

  111.         /** {@inheritDoc} */
  112.         @Override
  113.         public List<? extends EphemerisSegment> getSegments() {
  114.             return Collections.unmodifiableList(this.segments);
  115.         }

  116.         /** {@inheritDoc} */
  117.         @Override
  118.         public AbsoluteDate getStart() {
  119.             return this.startDate;
  120.         }

  121.         /** {@inheritDoc} */
  122.         @Override
  123.         public AbsoluteDate getStop() {
  124.             return this.stopDate;
  125.         }

  126.         /**
  127.          * Injects pre-computed satellite states into this ephemeris file
  128.          * object, returning the generated {@link OrekitEphemerisSegment} that
  129.          * has been stored internally. Defaults the celestial body to earth and
  130.          * the interpolation size to the default.
  131.          *
  132.          * <p>This method uses the {@link DataContext#getDefault() default data context}.
  133.          *
  134.          * @param states
  135.          *            a list of {@link SpacecraftState} that will comprise this
  136.          *            new unit.
  137.          * @return the generated {@link OrekitEphemerisSegment}
  138.          * @see #addNewSegment(List, CelestialBody, int, TimeScale)
  139.          */
  140.         @DefaultDataContext
  141.         public OrekitEphemerisSegment addNewSegment(final List<SpacecraftState> states) {
  142.             return this.addNewSegment(states, DEFAULT_INTERPOLATION_SIZE);
  143.         }

  144.         /**
  145.          * Injects pre-computed satellite states into this ephemeris file
  146.          * object, returning the generated {@link OrekitEphemerisSegment} that
  147.          * has been stored internally. Defaults the Celestial Body to be Earths
  148.          *
  149.          * <p>This method uses the {@link DataContext#getDefault() default data context}.
  150.          *
  151.          * @param states
  152.          *            a list of {@link SpacecraftState} that will comprise this
  153.          *            new unit.
  154.          * @param interpolationSampleSize
  155.          *            the number of interpolation samples that should be used
  156.          *            when processed by another system
  157.          * @return the generated {@link OrekitEphemerisSegment}
  158.          * @see #addNewSegment(List, CelestialBody, int, TimeScale)
  159.          */
  160.         @DefaultDataContext
  161.         public OrekitEphemerisSegment addNewSegment(final List<SpacecraftState> states,
  162.                 final int interpolationSampleSize) {
  163.             return this.addNewSegment(
  164.                     states,
  165.                     DataContext.getDefault().getCelestialBodies().getEarth(),
  166.                     interpolationSampleSize);
  167.         }

  168.         /**
  169.          * Injects pre-computed satellite states into this ephemeris file
  170.          * object, returning the generated {@link OrekitEphemerisSegment} that
  171.          * has been stored internally.
  172.          *
  173.          * <p>This method uses the {@link DataContext#getDefault() default data context}.
  174.          *
  175.          * @param states
  176.          *            a list of {@link SpacecraftState} that will comprise this
  177.          *            new unit.
  178.          * @param body
  179.          *            the celestial body the state's frames are with respect to
  180.          * @param interpolationSampleSize
  181.          *            the number of interpolation samples that should be used
  182.          *            when processed by another system
  183.          * @return the generated {@link OrekitEphemerisSegment}
  184.          * @see #addNewSegment(List, CelestialBody, int, TimeScale)
  185.          */
  186.         @DefaultDataContext
  187.         public OrekitEphemerisSegment addNewSegment(final List<SpacecraftState> states, final CelestialBody body,
  188.                                                     final int interpolationSampleSize) {
  189.             return addNewSegment(states, body, interpolationSampleSize,
  190.                     DataContext.getDefault().getTimeScales().getUTC());
  191.         }

  192.         /**
  193.          * Injects pre-computed satellite states into this ephemeris file
  194.          * object, returning the generated {@link OrekitEphemerisSegment} that
  195.          * has been stored internally.
  196.          *
  197.          * @param states
  198.          *            a list of {@link SpacecraftState} that will comprise this
  199.          *            new unit.
  200.          * @param body
  201.          *            the celestial body from which the frames are defined
  202.          * @param interpolationSampleSize
  203.          *            the number of interpolation samples that should be used
  204.          *            when processed by another system
  205.          * @param timeScale
  206.          *            the time scale used in the new segment.
  207.          * @return the generated {@link OrekitEphemerisSegment}
  208.          * @since 10.1
  209.          */
  210.         public OrekitEphemerisSegment addNewSegment(final List<SpacecraftState> states,
  211.                                                     final CelestialBody body,
  212.                                                     final int interpolationSampleSize,
  213.                                                     final TimeScale timeScale) {
  214.             final int minimumSampleSize = 2;
  215.             if (states == null || states.size() == 0) {
  216.                 throw new OrekitIllegalArgumentException(OrekitMessages.NULL_ARGUMENT, "states");
  217.             }

  218.             if (interpolationSampleSize < minimumSampleSize) {
  219.                 throw new OrekitIllegalArgumentException(OrekitMessages.NOT_ENOUGH_DATA_FOR_INTERPOLATION,
  220.                         interpolationSampleSize);
  221.             }

  222.             final AbsoluteDate start = states.get(0).getDate();
  223.             final AbsoluteDate stop = states.get(states.size() - 1).getDate();

  224.             if (this.startDate == null || start.compareTo(this.startDate) < 0) {
  225.                 this.startDate = start;
  226.             }

  227.             if (this.stopDate == null || stop.compareTo(this.stopDate) > 0) {
  228.                 this.stopDate = stop;
  229.             }

  230.             final List<TimeStampedPVCoordinates> coordinates = new ArrayList<TimeStampedPVCoordinates>();
  231.             for (SpacecraftState state : states) {
  232.                 coordinates.add(state.getPVCoordinates());
  233.             }

  234.             final Frame frame = states.get(0).getFrame();

  235.             final OrekitEphemerisSegment newSeg = new OrekitEphemerisSegment(coordinates, frame, body.getName(),
  236.                     body.getGM(), timeScale, interpolationSampleSize);
  237.             this.segments.add(newSeg);

  238.             return newSeg;
  239.         }
  240.     }

  241.     public static class OrekitEphemerisSegment implements EphemerisSegment {

  242.         /** Coordinates for this ephemeris segment. **/
  243.         private final List<TimeStampedPVCoordinates> coordinates;

  244.         /** The reference frame for this ephemeris segment. **/
  245.         private final Frame frame;

  246.         /** The name of the frame center. **/
  247.         private final String frameCenterString;

  248.         /** Standard gravitational parameter for the satellite. **/
  249.         private final double mu;

  250.         /** The time scale identifier, as specified in the ephemeris file. **/
  251.         private final String timeScaleString;

  252.         /** The time scale for this segment. **/
  253.         private final TimeScale timeScale;

  254.         /** The number of interpolation samples. */
  255.         private final int interpolationSamples;

  256.         /**
  257.          * constructor for OrekitEphemerisSegment.
  258.          *
  259.          * @param coordinates
  260.          *            coordinates making up the ephemeris for this segment
  261.          * @param frame
  262.          *            the frame the coordinates are in
  263.          * @param frameCenterString
  264.          *            the name of celestial body the frame is attached to
  265.          * @param mu
  266.          *            the gravitational constant used in force model evaluations
  267.          * @param timeScale
  268.          *            the time scale of these ephemeris points
  269.          * @param interpolationSamples
  270.          *            the number of samples to use during interpolation
  271.          */
  272.         public OrekitEphemerisSegment(final List<TimeStampedPVCoordinates> coordinates, final Frame frame,
  273.                 final String frameCenterString, final double mu, final TimeScale timeScale, final int interpolationSamples) {
  274.             super();
  275.             this.coordinates = coordinates;
  276.             this.frame = frame;
  277.             this.frameCenterString = frameCenterString;
  278.             this.mu = mu;
  279.             this.timeScale = timeScale;
  280.             this.timeScaleString = timeScale.getName();
  281.             this.interpolationSamples = interpolationSamples;
  282.         }

  283.         /** {@inheritDoc} */
  284.         @Override
  285.         public double getMu() {
  286.             return mu;
  287.         }

  288.         /** {@inheritDoc} */
  289.         @Override
  290.         public String getFrameCenterString() {
  291.             return frameCenterString;
  292.         }

  293.         /** {@inheritDoc} */
  294.         @Override
  295.         public String getFrameString() {
  296.             return frame.getName();
  297.         }

  298.         /** {@inheritDoc} */
  299.         @Override
  300.         public Frame getFrame() {
  301.             return frame;
  302.         }

  303.         /** {@inheritDoc} */
  304.         @Override
  305.         public Frame getInertialFrame() {
  306.             return frame;
  307.         }

  308.         /** {@inheritDoc} */
  309.         @Override
  310.         public String getTimeScaleString() {
  311.             return timeScaleString;
  312.         }

  313.         /** {@inheritDoc} */
  314.         @Override
  315.         public TimeScale getTimeScale() {
  316.             return timeScale;
  317.         }

  318.         /** {@inheritDoc} */
  319.         @Override
  320.         public int getInterpolationSamples() {
  321.             return interpolationSamples;
  322.         }

  323.         /** {@inheritDoc} */
  324.         @Override
  325.         public CartesianDerivativesFilter getAvailableDerivatives() {
  326.             return CartesianDerivativesFilter.USE_PV;
  327.         }

  328.         /** {@inheritDoc} */
  329.         @Override
  330.         public List<TimeStampedPVCoordinates> getCoordinates() {
  331.             return Collections.unmodifiableList(coordinates);
  332.         }

  333.         /** {@inheritDoc} */
  334.         @Override
  335.         public AbsoluteDate getStart() {
  336.             return coordinates.get(0).getDate();
  337.         }

  338.         /** {@inheritDoc} */
  339.         @Override
  340.         public AbsoluteDate getStop() {
  341.             return coordinates.get(coordinates.size() - 1).getDate();
  342.         }

  343.     }
  344. }