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
  44.     implements EphemerisFile<TimeStampedPVCoordinates, OrekitEphemerisFile.OrekitEphemerisSegment> {

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

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

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

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

  70.     /**
  71.      * Inner class of {@link OrekitEphemerisFile} that defines the
  72.      * {@link OrekitSatelliteEphemeris} corresponding object for this ephemeris type.
  73.      */
  74.     public static class OrekitSatelliteEphemeris
  75.         implements EphemerisFile.SatelliteEphemeris<TimeStampedPVCoordinates, OrekitEphemerisSegment> {

  76.         /**
  77.          * Defines the default interpolation sample size if it is not specified
  78.          * on a segment.
  79.          **/
  80.         public static final int DEFAULT_INTERPOLATION_SIZE = 2;

  81.         /** ID of the space object encapsulated here. **/
  82.         private final String id;

  83.         /** Earliest date of this file. **/
  84.         private AbsoluteDate startDate;

  85.         /** Latest date of this file. **/
  86.         private AbsoluteDate stopDate;

  87.         /** List of segments in the file. **/
  88.         private final List<OrekitEphemerisSegment> segments;

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

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

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

  113.         /** {@inheritDoc} */
  114.         @Override
  115.         public List<OrekitEphemerisSegment> getSegments() {
  116.             return Collections.unmodifiableList(this.segments);
  117.         }

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

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

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

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

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

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

  220.             if (interpolationSampleSize < minimumSampleSize) {
  221.                 throw new OrekitIllegalArgumentException(OrekitMessages.NOT_ENOUGH_DATA,
  222.                         interpolationSampleSize);
  223.             }

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

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

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

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

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

  237.             final OrekitEphemerisSegment newSeg =
  238.                             new OrekitEphemerisSegment(coordinates, frame, body.getGM(), interpolationSampleSize);
  239.             this.segments.add(newSeg);

  240.             return newSeg;
  241.         }
  242.     }

  243.     /** Ephemeris segment. */
  244.     public static class OrekitEphemerisSegment
  245.         implements EphemerisFile.EphemerisSegment<TimeStampedPVCoordinates> {

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

  248.         /** The reference frame for this ephemeris segment. **/
  249.         private final Frame frame;

  250.         /** Standard gravitational parameter for the satellite. **/
  251.         private final double mu;

  252.         /** The number of interpolation samples. */
  253.         private final int interpolationSamples;

  254.         /**
  255.          * constructor for OrekitEphemerisSegment.
  256.          *
  257.          * @param coordinates
  258.          *            coordinates making up the ephemeris for this segment
  259.          * @param frame
  260.          *            the frame the coordinates are in
  261.          * @param mu
  262.          *            the gravitational constant used in force model evaluations
  263.          * @param interpolationSamples
  264.          *            the number of samples to use during interpolation
  265.          */
  266.         public OrekitEphemerisSegment(final List<TimeStampedPVCoordinates> coordinates, final Frame frame,
  267.                                       final double mu, final int interpolationSamples) {
  268.             this.coordinates          = coordinates;
  269.             this.frame                = frame;
  270.             this.mu                   = mu;
  271.             this.interpolationSamples = interpolationSamples;
  272.         }

  273.         /** {@inheritDoc} */
  274.         @Override
  275.         public double getMu() {
  276.             return mu;
  277.         }

  278.         /** {@inheritDoc} */
  279.         @Override
  280.         public Frame getFrame() {
  281.             return frame;
  282.         }

  283.         /** {@inheritDoc} */
  284.         @Override
  285.         public Frame getInertialFrame() {
  286.             return frame;
  287.         }

  288.         /** {@inheritDoc} */
  289.         @Override
  290.         public int getInterpolationSamples() {
  291.             return interpolationSamples;
  292.         }

  293.         /** {@inheritDoc} */
  294.         @Override
  295.         public CartesianDerivativesFilter getAvailableDerivatives() {
  296.             return CartesianDerivativesFilter.USE_PV;
  297.         }

  298.         /** {@inheritDoc} */
  299.         @Override
  300.         public List<TimeStampedPVCoordinates> getCoordinates() {
  301.             return Collections.unmodifiableList(coordinates);
  302.         }

  303.         /** {@inheritDoc} */
  304.         @Override
  305.         public AbsoluteDate getStart() {
  306.             return coordinates.get(0).getDate();
  307.         }

  308.         /** {@inheritDoc} */
  309.         @Override
  310.         public AbsoluteDate getStop() {
  311.             return coordinates.get(coordinates.size() - 1).getDate();
  312.         }

  313.     }
  314. }