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.     @Override
  53.     public Map<String, OrekitSatelliteEphemeris> getSatellites() {
  54.         return Collections.unmodifiableMap(satellites);
  55.     }

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

  68.     /**
  69.      * Inner class of {@link OrekitEphemerisFile} that defines the
  70.      * {@link OrekitSatelliteEphemeris} corresponding object for this ephemeris type.
  71.      *
  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;

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

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

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

  85.         /** List of segements 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.         @Override
  98.         public String getId() {
  99.             return id;
  100.         }

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

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

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

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

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

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

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

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

  214.             if (interpolationSampleSize < minimumSampleSize) {
  215.                 throw new OrekitIllegalArgumentException(OrekitMessages.NOT_ENOUGH_DATA_FOR_INTERPOLATION,
  216.                         interpolationSampleSize);
  217.             }

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

  220.             if (this.startDate == null || start.compareTo(this.startDate) < 0) {
  221.                 this.startDate = start;
  222.             }

  223.             if (this.stopDate == null || stop.compareTo(this.stopDate) > 0) {
  224.                 this.stopDate = stop;
  225.             }

  226.             final List<TimeStampedPVCoordinates> coordinates = new ArrayList<TimeStampedPVCoordinates>();
  227.             for (SpacecraftState state : states) {
  228.                 coordinates.add(state.getPVCoordinates());
  229.             }

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

  231.             final OrekitEphemerisSegment newSeg = new OrekitEphemerisSegment(coordinates, frame, body.getName(),
  232.                     body.getGM(), timeScale, interpolationSampleSize);
  233.             this.segments.add(newSeg);

  234.             return newSeg;
  235.         }
  236.     }

  237.     public static class OrekitEphemerisSegment implements EphemerisSegment {
  238.         /** **/
  239.         private final List<TimeStampedPVCoordinates> coordinates;

  240.         /** **/
  241.         private final Frame frame;

  242.         /** **/
  243.         private final String frameCenterString;

  244.         /** **/
  245.         private final double mu;

  246.         /** **/
  247.         private final String timeScaleString;

  248.         /** **/
  249.         private final TimeScale timeScale;

  250.         /** **/
  251.         private final int samples;

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

  279.         @Override
  280.         public double getMu() {
  281.             return mu;
  282.         }

  283.         @Override
  284.         public String getFrameCenterString() {
  285.             return frameCenterString;
  286.         }

  287.         @Override
  288.         public String getFrameString() {
  289.             return frame.getName();
  290.         }

  291.         @Override
  292.         public Frame getFrame() {
  293.             return frame;
  294.         }

  295.         @Override
  296.         public Frame getInertialFrame() {
  297.             return frame;
  298.         }

  299.         @Override
  300.         public String getTimeScaleString() {
  301.             return timeScaleString;
  302.         }

  303.         @Override
  304.         public TimeScale getTimeScale() {
  305.             return timeScale;
  306.         }

  307.         @Override
  308.         public int getInterpolationSamples() {
  309.             return samples;
  310.         }

  311.         @Override
  312.         public CartesianDerivativesFilter getAvailableDerivatives() {
  313.             return CartesianDerivativesFilter.USE_PV;
  314.         }

  315.         @Override
  316.         public List<TimeStampedPVCoordinates> getCoordinates() {
  317.             return Collections.unmodifiableList(coordinates);
  318.         }

  319.         @Override
  320.         public AbsoluteDate getStart() {
  321.             return coordinates.get(0).getDate();
  322.         }

  323.         @Override
  324.         public AbsoluteDate getStop() {
  325.             return coordinates.get(coordinates.size() - 1).getDate();
  326.         }

  327.     }
  328. }