1   /* Contributed in the public domain.
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    * CS 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  
19  import java.util.ArrayList;
20  import java.util.List;
21  import java.util.Map;
22  
23  import org.orekit.errors.OrekitException;
24  import org.orekit.frames.Frame;
25  import org.orekit.propagation.BoundedPropagator;
26  import org.orekit.propagation.Propagator;
27  import org.orekit.propagation.analytical.AggregateBoundedPropagator;
28  import org.orekit.time.AbsoluteDate;
29  import org.orekit.utils.CartesianDerivativesFilter;
30  import org.orekit.utils.TimeStampedPVCoordinates;
31  
32  /**
33   * An interface for accessing the data stored in an ephemeris file and using the data to
34   * create a working {@link org.orekit.propagation.Propagator Propagator}.
35   *
36   * <p> An {@link EphemerisFile} consists of one or more satellites each with a unique ID
37   * within the file. The ephemeris for each satellite consists of one or more segments.
38   *
39   * <p> Some ephemeris file formats may supply additional information that is not available
40   * via this interface. In those cases it is recommended that the parser return a subclass
41   * of this interface to provide access to the additional information.
42   *
43   * @param <C> type of the Cartesian coordinates
44   * @param <S> type of the segment
45   * @author Evan Ward
46   * @see SatelliteEphemeris
47   * @see EphemerisSegment
48   */
49  public interface EphemerisFile<C extends TimeStampedPVCoordinates,
50                                 S extends EphemerisFile.EphemerisSegment<C>> {
51  
52      /**
53       * Get the loaded ephemeris for each satellite in the file.
54       *
55       * @return a map from the satellite's ID to the information about that satellite
56       * contained in the file.
57       */
58      Map<String, ? extends SatelliteEphemeris<C, S>> getSatellites();
59  
60      /**
61       * Contains the information about a single satellite from an {@link EphemerisFile}.
62       *
63       * <p> A satellite ephemeris consists of one or more {@link EphemerisSegment}s.
64       * Segments are typically used to split up an ephemeris at discontinuous events, such
65       * as a maneuver.
66       * @param <C> type of the Cartesian coordinates
67       * @param <S> type of the segment
68       * @author Evan Ward
69       * @see EphemerisFile
70       * @see EphemerisSegment
71       */
72      interface SatelliteEphemeris<C extends TimeStampedPVCoordinates,
73                                   S extends EphemerisSegment<C>> {
74  
75          /**
76           * Get the satellite ID. The satellite ID is unique only within the same ephemeris
77           * file.
78           *
79           * @return the satellite's ID, never {@code null}.
80           */
81          String getId();
82  
83          /**
84           * Get the standard gravitational parameter for the satellite.
85           *
86           * @return the gravitational parameter used in {@link #getPropagator()}, in m³/s².
87           */
88          double getMu();
89  
90          /**
91           * Get the segments of the ephemeris.
92           *
93           * <p> Ephemeris segments are typically used to split an ephemeris around
94           * discontinuous events, such as maneuvers.
95           *
96           * @return the segments contained in the ephemeris file for this satellite.
97           */
98          List<S> getSegments();
99  
100         /**
101          * Get the start date of the ephemeris.
102          *
103          * <p> The date returned by this method is equivalent to {@code
104          * getPropagator().getMinDate()}.
105          *
106          * @return ephemeris start date.
107          */
108         AbsoluteDate getStart();
109 
110         /**
111          * Get the end date of the ephemeris.
112          *
113          * <p> The date returned by this method is equivalent to {@code getPropagator().getMaxDate()}.
114          *
115          * @return ephemeris end date.
116          */
117         AbsoluteDate getStop();
118 
119         /**
120          * View this ephemeris as a propagator, combining data from all {@link
121          * #getSegments() segments}.
122          *
123          * <p>In order to view the ephemeris for this satellite as a {@link Propagator}
124          * several conditions must be met. An Orekit {@link Frame} must be constructable
125          * from the frame specification in the ephemeris file. This condition is met when
126          * {@link EphemerisSegment#getFrame()} return normally for all {@link
127          * #getSegments() segments}. If there are multiple segments they must be adjacent
128          * such that there are no duplicates or gaps in the ephemeris. The definition of
129          * adjacent depends on the ephemeris format as some formats define usable start
130          * and stop times that are different from the ephemeris data start and stop times.
131          * If these conditions are not met an {@link OrekitException} may be thrown by
132          * this method or by one of the methods of the returned {@link Propagator}.
133          *
134          * <p> Each call to this method creates a new propagator.
135          *
136          * @return a propagator for all the data in this ephemeris file.
137          */
138         default BoundedPropagator getPropagator() {
139             final List<BoundedPropagator> propagators = new ArrayList<>();
140             for (final EphemerisSegment<C> segment : this.getSegments()) {
141                 propagators.add(segment.getPropagator());
142             }
143             return new AggregateBoundedPropagator(propagators);
144         }
145 
146     }
147 
148     /**
149      * A segment of an ephemeris for a satellite.
150      *
151      * <p> Segments are typically used to split an ephemeris around discontinuous events
152      * such as maneuvers.
153      *
154      * @param <C> type of the Cartesian coordinates
155      * @author Evan Ward
156      * @see EphemerisFile
157      * @see SatelliteEphemeris
158      */
159     interface EphemerisSegment<C extends TimeStampedPVCoordinates> {
160 
161         /**
162          * Get the standard gravitational parameter for the satellite.
163          *
164          * @return the gravitational parameter used in {@link #getPropagator()}, in m³/s².
165          */
166         double getMu();
167 
168         /**
169          * Get the reference frame for this ephemeris segment. The defining frame for
170          * {@link #getCoordinates()}.
171          *
172          * @return the reference frame for this segment. Never {@code null}.
173          */
174         Frame getFrame();
175 
176         /**
177          * Get the inertial reference frame for this ephemeris segment. Defines the
178          * propagation frame for {@link #getPropagator()}.
179          *
180          * <p>The default implementation returns {@link #getFrame()} if it is inertial.
181          * Otherwise it returns {@link Frame#getRoot()}. Implementors are encouraged to
182          * override this default implementation if a more suitable inertial frame is
183          * available.
184          *
185          * @return an reference frame that is inertial, i.e. {@link
186          * Frame#isPseudoInertial()} is {@code true}. May be the same as {@link
187          * #getFrame()} if it is inertial.
188          */
189         default Frame getInertialFrame() {
190             final Frame frame = getFrame();
191             if (frame.isPseudoInertial()) {
192                 return frame;
193             }
194             return Frame.getRoot();
195         }
196 
197         /**
198          * Get the number of samples to use in interpolation.
199          *
200          * @return the number of points to use for interpolation.
201          */
202         int getInterpolationSamples();
203 
204         /**
205          * Get which derivatives of position are available in this ephemeris segment.
206          *
207          * <p> While {@link #getCoordinates()} always returns position, velocity, and
208          * acceleration the return value from this method indicates which of those are in
209          * the ephemeris file and are actually valid.
210          *
211          * @return a value indicating if the file contains velocity and/or acceleration
212          * data.
213          */
214         CartesianDerivativesFilter getAvailableDerivatives();
215 
216         /**
217          * Get the coordinates for this ephemeris segment in {@link #getFrame()}.
218          *
219          * @return a list of state vectors in chronological order. The coordinates are not
220          * necessarily evenly spaced in time. The value of {@link
221          * #getAvailableDerivatives()} indicates if the velocity or accelerations were
222          * specified in the file. Any position, velocity, or acceleration coordinates that
223          * are not specified in the ephemeris file are zero in the returned values.
224          */
225         List<C> getCoordinates();
226 
227         /**
228          * Get the start date of this ephemeris segment.
229          *
230          * <p> The date returned by this method is equivalent to {@code
231          * getPropagator().getMinDate()}.
232          *
233          * @return ephemeris segment start date.
234          */
235         AbsoluteDate getStart();
236 
237         /**
238          * Get the end date of this ephemeris segment.
239          *
240          * <p> The date returned by this method is equivalent to {@code
241          * getPropagator().getMaxDate()}.
242          *
243          * @return ephemeris segment end date.
244          */
245         AbsoluteDate getStop();
246 
247         /**
248          * View this ephemeris segment as a propagator.
249          *
250          * <p>In order to view the ephemeris for this satellite as a {@link Propagator}
251          * several conditions must be met. An Orekit {@link Frame} must be constructable
252          * from the frame specification in the ephemeris file. This condition is met when
253          * {@link EphemerisSegment#getFrame()} return normally. Additionally,
254          * {@link #getMu()} must return a valid value. If these conditions are not met an
255          * {@link OrekitException} may be thrown by this method or by one of the methods
256          * of the returned {@link Propagator}.
257          *
258          * <p> Each call to this method creates a new propagator.
259          *
260          * @return a propagator for this ephemeris segment.
261          */
262         default BoundedPropagator getPropagator() {
263             return new EphemerisSegmentPropagator<>(this);
264         }
265 
266     }
267 
268 }