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 }