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_FOR_INTERPOLATION,
  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.     public static class OrekitEphemerisSegment
  244.         implements EphemerisFile.EphemerisSegment<TimeStampedPVCoordinates> {

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

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

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

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

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

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

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

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

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

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

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

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

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

  312.     }
  313. }