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 }