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