OrekitEphemerisFile.java

  1. /* Copyright 2016 Applied Defense Solutions (ADS)
  2.  * Licensed to CS Systèmes d'Information (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.bodies.CelestialBody;
  24. import org.orekit.bodies.CelestialBodyFactory;
  25. import org.orekit.errors.OrekitException;
  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.time.TimeScalesFactory;
  33. import org.orekit.utils.CartesianDerivativesFilter;
  34. import org.orekit.utils.TimeStampedPVCoordinates;

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

  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.     @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.      */
  74.     public static class OrekitSatelliteEphemeris implements SatelliteEphemeris {
  75.         /**
  76.          * Defines the default interpolation sample size if it is not specified
  77.          * on a segment.
  78.          **/
  79.         public static final int DEFAULT_INTERPOLATION_SIZE = 7;

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

  82.         /** Earlist date of this file. **/
  83.         private AbsoluteDate startDate;

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

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

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

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

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

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

  114.         @Override
  115.         public AbsoluteDate getStart() {
  116.             return this.startDate;
  117.         }

  118.         @Override
  119.         public AbsoluteDate getStop() {
  120.             // TODO Auto-generated method stub
  121.             return this.stopDate;
  122.         }

  123.         /**
  124.          * Injects pre-computed satellite states into this ephemeris file
  125.          * object, returning the generated {@link OrekitEphemerisSegment} that
  126.          * has been stored internally. Defaults the celestial body to earth and
  127.          * the interpolation size to the default.
  128.          *
  129.          * @param states
  130.          *            a list of {@link SpacecraftState} that will comprise this
  131.          *            new unit.
  132.          * @return the generated {@link OrekitEphemerisSegment}
  133.          * @throws OrekitException
  134.          *             if there is an exception in time or frame transformations
  135.          */
  136.         public OrekitEphemerisSegment addNewSegment(final List<SpacecraftState> states) throws OrekitException {
  137.             return this.addNewSegment(states, CelestialBodyFactory.getEarth(), DEFAULT_INTERPOLATION_SIZE);
  138.         }

  139.         /**
  140.          * Injects pre-computed satellite states into this ephemeris file
  141.          * object, returning the generated {@link OrekitEphemerisSegment} that
  142.          * has been stored internally. Defaults the Celestial Body to be Earths
  143.          *
  144.          * @param states
  145.          *            a list of {@link SpacecraftState} that will comprise this
  146.          *            new unit.
  147.          * @param interpolationSampleSize
  148.          *            the number of interpolation samples that should be used
  149.          *            when processed by another system
  150.          * @return the generated {@link OrekitEphemerisSegment}
  151.          * @throws OrekitException
  152.          *             if there is an exception in time or frame transformations
  153.          */
  154.         public OrekitEphemerisSegment addNewSegment(final List<SpacecraftState> states,
  155.                 final int interpolationSampleSize) throws OrekitException {
  156.             return this.addNewSegment(states, CelestialBodyFactory.getEarth(), interpolationSampleSize);
  157.         }

  158.         /**
  159.          * Injects pre-computed satellite states into this ephemeris file
  160.          * object, returning the generated {@link OrekitEphemerisSegment} that
  161.          * has been stored internally.
  162.          *
  163.          * @param states
  164.          *            a list of {@link SpacecraftState} that will comprise this
  165.          *            new unit.
  166.          * @param body
  167.          *            the celestial body the state's frames are with respect to
  168.          * @param interpolationSampleSize
  169.          *            the number of interpolation samples that should be used
  170.          *            when processed by another system
  171.          * @return the generated {@link OrekitEphemerisSegment}
  172.          * @throws OrekitException
  173.          *             if there is an exception in time or frame transformations
  174.          */
  175.         public OrekitEphemerisSegment addNewSegment(final List<SpacecraftState> states, final CelestialBody body,
  176.                 final int interpolationSampleSize) throws OrekitException {
  177.             final int minimumSampleSize = 2;
  178.             if (states == null || states.size() == 0) {
  179.                 throw new OrekitIllegalArgumentException(OrekitMessages.NULL_ARGUMENT, "states");
  180.             }

  181.             if (interpolationSampleSize < minimumSampleSize) {
  182.                 throw new OrekitIllegalArgumentException(OrekitMessages.NOT_ENOUGH_DATA_FOR_INTERPOLATION,
  183.                         interpolationSampleSize);
  184.             }

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

  187.             if (this.startDate == null || start.compareTo(this.startDate) < 0) {
  188.                 this.startDate = start;
  189.             }

  190.             if (this.stopDate == null || stop.compareTo(this.stopDate) > 0) {
  191.                 this.stopDate = stop;
  192.             }

  193.             final List<TimeStampedPVCoordinates> coordinates = new ArrayList<TimeStampedPVCoordinates>();
  194.             for (SpacecraftState state : states) {
  195.                 coordinates.add(state.getPVCoordinates());
  196.             }

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

  198.             final OrekitEphemerisSegment newSeg = new OrekitEphemerisSegment(coordinates, frame, body.getName(),
  199.                     body.getGM(), TimeScalesFactory.getUTC(), interpolationSampleSize);
  200.             this.segments.add(newSeg);

  201.             return newSeg;
  202.         }
  203.     }

  204.     public static class OrekitEphemerisSegment implements EphemerisSegment {
  205.         /** **/
  206.         private final List<TimeStampedPVCoordinates> coordinates;

  207.         /** **/
  208.         private final Frame frame;

  209.         /** **/
  210.         private final String frameCenterString;

  211.         /** **/
  212.         private final double mu;

  213.         /** **/
  214.         private final String timeScaleString;

  215.         /** **/
  216.         private final TimeScale timeScale;

  217.         /** **/
  218.         private final int samples;

  219.         /**
  220.          * constructor for OrekitEphemerisSegment.
  221.          *
  222.          * @param coordinates
  223.          *            coordinates making up the ephemeris for this segment
  224.          * @param frame
  225.          *            the frame the coordinates are in
  226.          * @param frameCenterString
  227.          *            the name of celestial body the frame is attached to
  228.          * @param mu
  229.          *            the gravitional constant used in force model evaluations
  230.          * @param timeScale
  231.          *            the time scale of these ephemeris points
  232.          * @param samples
  233.          *            the number of samples to use during interpolation
  234.          */
  235.         public OrekitEphemerisSegment(final List<TimeStampedPVCoordinates> coordinates, final Frame frame,
  236.                 final String frameCenterString, final double mu, final TimeScale timeScale, final int samples) {
  237.             super();
  238.             this.coordinates = coordinates;
  239.             this.frame = frame;
  240.             this.frameCenterString = frameCenterString;
  241.             this.mu = mu;
  242.             this.timeScale = timeScale;
  243.             this.timeScaleString = timeScale.getName();
  244.             this.samples = samples;
  245.         }

  246.         @Override
  247.         public double getMu() {
  248.             return mu;
  249.         }

  250.         @Override
  251.         public String getFrameCenterString() {
  252.             return frameCenterString;
  253.         }

  254.         @Override
  255.         public String getFrameString() {
  256.             return frame.getName();
  257.         }

  258.         @Override
  259.         public Frame getFrame() throws OrekitException {
  260.             return frame;
  261.         }

  262.         @Override
  263.         public String getTimeScaleString() {
  264.             return timeScaleString;
  265.         }

  266.         @Override
  267.         public TimeScale getTimeScale() throws OrekitException {
  268.             return timeScale;
  269.         }

  270.         @Override
  271.         public int getInterpolationSamples() {
  272.             return samples;
  273.         }

  274.         @Override
  275.         public CartesianDerivativesFilter getAvailableDerivatives() {
  276.             return CartesianDerivativesFilter.USE_PV;
  277.         }

  278.         @Override
  279.         public List<TimeStampedPVCoordinates> getCoordinates() {
  280.             return Collections.unmodifiableList(coordinates);
  281.         }

  282.         @Override
  283.         public AbsoluteDate getStart() {
  284.             return coordinates.get(0).getDate();
  285.         }

  286.         @Override
  287.         public AbsoluteDate getStop() {
  288.             return coordinates.get(coordinates.size() - 1).getDate();
  289.         }

  290.     }
  291. }