1 /* Copyright 2002-2025 CS GROUP
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.propagation;
18
19 import java.util.Collection;
20 import java.util.List;
21
22 import org.hipparchus.CalculusFieldElement;
23 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
24 import org.orekit.attitudes.AttitudeProvider;
25 import org.orekit.frames.FieldKinematicTransform;
26 import org.orekit.frames.Frame;
27 import org.orekit.propagation.events.FieldEventDetector;
28 import org.orekit.propagation.sampling.FieldOrekitFixedStepHandler;
29 import org.orekit.propagation.sampling.FieldOrekitStepHandler;
30 import org.orekit.propagation.sampling.FieldStepHandlerMultiplexer;
31 import org.orekit.time.FieldAbsoluteDate;
32 import org.orekit.utils.FieldPVCoordinatesProvider;
33 import org.orekit.utils.TimeStampedFieldPVCoordinates;
34
35 /** This interface provides a way to propagate an orbit at any time.
36 *
37 * <p>This interface is the top-level abstraction for orbit propagation.
38 * It only allows propagation to a predefined date.
39 * It is implemented by analytical models which have no time limit,
40 * by orbit readers based on external data files, by numerical integrators
41 * using rich force models and by continuous models built after numerical
42 * integration has been completed and dense output data as been
43 * gathered.</p>
44 * @param <T> the type of the field elements
45
46 * @author Luc Maisonobe
47 * @author Véronique Pommier-Maurussane
48 *
49 */
50
51 public interface FieldPropagator<T extends CalculusFieldElement<T>> extends FieldPVCoordinatesProvider<T> {
52
53 /** Default mass. */
54 double DEFAULT_MASS = 1000.0;
55
56 /** Get the multiplexer holding all step handlers.
57 * @return multiplexer holding all step handlers
58 * @since 11.0
59 */
60 FieldStepHandlerMultiplexer<T> getMultiplexer();
61
62 /** Remove all step handlers.
63 * <p>This convenience method is equivalent to call {@code getMultiplexer().clear()}</p>
64 * @see #getMultiplexer()
65 * @see FieldStepHandlerMultiplexer#clear()
66 * @since 11.0
67 */
68 default void clearStepHandlers() {
69 getMultiplexer().clear();
70 }
71
72 /** Set a single handler for fixed stepsizes.
73 * <p>This convenience method is equivalent to call {@code getMultiplexer().clear()}
74 * followed by {@code getMultiplexer().add(h, handler)}</p>
75 * @param h fixed stepsize (s)
76 * @param handler handler called at the end of each finalized step
77 * @see #getMultiplexer()
78 * @see FieldStepHandlerMultiplexer#add(CalculusFieldElement, FieldOrekitFixedStepHandler)
79 * @since 11.0
80 */
81 default void setStepHandler(final T h, final FieldOrekitFixedStepHandler<T> handler) {
82 getMultiplexer().clear();
83 getMultiplexer().add(h, handler);
84 }
85
86 /** Set a single handler for variable stepsizes.
87 * <p>This convenience method is equivalent to call {@code getMultiplexer().clear()}
88 * followed by {@code getMultiplexer().add(handler)}</p>
89 * @param handler handler called at the end of each finalized step
90 * @see #getMultiplexer()
91 * @see FieldStepHandlerMultiplexer#add(FieldOrekitStepHandler)
92 * @since 11.0
93 */
94 default void setStepHandler(final FieldOrekitStepHandler<T> handler) {
95 getMultiplexer().clear();
96 getMultiplexer().add(handler);
97 }
98
99 /**
100 * Set up an ephemeris generator that will monitor the propagation for building
101 * an ephemeris from it once completed.
102 *
103 * <p>
104 * This generator can be used when the user needs fast random access to the orbit
105 * state at any time between the initial and target times. A typical example is the
106 * implementation of search and iterative algorithms that may navigate forward and
107 * backward inside the propagation range before finding their result even if the
108 * propagator used is integration-based and only goes from one initial time to one
109 * target time.
110 * </p>
111 * <p>
112 * Beware that when used with integration-based propagators, the generator will
113 * store <strong>all</strong> intermediate results. It is therefore memory intensive
114 * for long integration-based ranges and high precision/short time steps. When
115 * used with analytical propagators, the generator only stores start/stop time
116 * and a reference to the analytical propagator itself to call it back as needed,
117 * so it is less memory intensive.
118 * </p>
119 * <p>
120 * The returned ephemeris generator will be initially empty, it will be filled
121 * with propagation data when a subsequent call to either {@link #propagate(FieldAbsoluteDate)
122 * propagate(target)} or {@link #propagate(FieldAbsoluteDate, FieldAbsoluteDate)
123 * propagate(start, target)} is called. The proper way to use this method is
124 * therefore to do:
125 * </p>
126 * <pre>
127 * FieldEphemerisGenerator<T> generator = propagator.getEphemerisGenerator();
128 * propagator.propagate(target);
129 * FieldBoundedPropagator<T> ephemeris = generator.getGeneratedEphemeris();
130 * </pre>
131 * @return ephemeris generator
132 */
133 FieldEphemerisGenerator<T> getEphemerisGenerator();
134
135 /** Get the propagator initial state.
136 * @return initial state
137 */
138 FieldSpacecraftState<T> getInitialState();
139
140 /** Reset the propagator initial state.
141 * @param state new initial state to consider
142 */
143 void resetInitialState(FieldSpacecraftState<T> state);
144
145 /** Add a set of user-specified data to be computed along with the orbit propagation.
146 * @param additionalDataProvider provider for additional data
147 */
148 void addAdditionalDataProvider(FieldAdditionalDataProvider<?, T> additionalDataProvider);
149
150 /** Get an unmodifiable list of providers for additional data.
151 * @return providers for the additional states
152 */
153 List<FieldAdditionalDataProvider<?, T>> getAdditionalDataProviders();
154
155 /** Check if an additional data is managed.
156 * <p>
157 * Managed data are the ones for which the propagators know how to compute
158 * its evolution. They correspond to additional data for which an
159 * {@link FieldAdditionalDataProvider additional data provider} has been registered
160 * by calling the {@link #addAdditionalDataProvider(FieldAdditionalDataProvider)
161 * addAdditionalDataProvider} method. If the propagator is an {@link
162 * org.orekit.propagation.integration.FieldAbstractIntegratedPropagator integrator-based
163 * propagator}, the states for which a set of {@link
164 * org.orekit.propagation.integration.FieldAdditionalDerivativesProvider additional derivatives
165 * provider} has been registered by calling the {@link
166 * org.orekit.propagation.integration.FieldAbstractIntegratedPropagator#addAdditionalDerivativesProvider(
167 * org.orekit.propagation.integration.FieldAdditionalDerivativesProvider) addAdditionalDerivativesProvider}
168 * method are also counted as managed additional states.
169 * </p>
170 * <p>
171 * Additional data that are present in the {@link #getInitialState() initial state}
172 * but have no evolution method registered are <em>not</em> considered as managed data.
173 * These unmanaged additional data are not lost during propagation, though. Their
174 * value are piecewise constant between state resets that may change them if some
175 * event handler {@link
176 * org.orekit.propagation.events.handlers.FieldEventHandler#resetState(FieldEventDetector,
177 * FieldSpacecraftState) resetState} method is called at an event occurrence and happens
178 * to change the unmanaged additional data.
179 * </p>
180 * @param name name of the additional data
181 * @return true if the additional data is managed
182 */
183 boolean isAdditionalDataManaged(String name);
184
185 /** Get all the names of all managed data.
186 * @return names of all managed data
187 */
188 String[] getManagedAdditionalData();
189
190 /** Add an event detector.
191 * @param detector event detector to add
192 * @see #clearEventsDetectors()
193 * @see #getEventDetectors()
194 * @param <D> class type for the generic version
195 */
196 <D extends FieldEventDetector<T>> void addEventDetector(D detector);
197
198 /** Get all the events detectors that have been added.
199 * @return an unmodifiable collection of the added detectors
200 * @see #addEventDetector(FieldEventDetector)
201 * @see #clearEventsDetectors()
202 */
203 Collection<FieldEventDetector<T>> getEventDetectors();
204
205 /** Remove all events detectors.
206 * @see #addEventDetector(FieldEventDetector)
207 * @see #getEventDetectors()
208 */
209 void clearEventsDetectors();
210
211 /** Get attitude provider.
212 * @return attitude provider
213 */
214 AttitudeProvider getAttitudeProvider();
215
216 /** Set attitude provider.
217 * @param attitudeProvider attitude provider
218 */
219 void setAttitudeProvider(AttitudeProvider attitudeProvider);
220
221 /** Get the frame in which the orbit is propagated.
222 * <p>
223 * The propagation frame is the definition frame of the initial
224 * state, so this method should be called after this state has
225 * been set, otherwise it may return null.
226 * </p>
227 * @return frame in which the orbit is propagated
228 * @see #resetInitialState(FieldSpacecraftState)
229 */
230 Frame getFrame();
231
232 /** Propagate towards a target date.
233 * <p>Simple propagators use only the target date as the specification for
234 * computing the propagated state. More feature rich propagators can consider
235 * other information and provide different operating modes or G-stop
236 * facilities to stop at pinpointed events occurrences. In these cases, the
237 * target date is only a hint, not a mandatory objective.</p>
238 * @param target target date towards which orbit state should be propagated
239 * @return propagated state
240 */
241 FieldSpacecraftState<T> propagate(FieldAbsoluteDate<T> target);
242
243 /** Propagate from a start date towards a target date.
244 * <p>Those propagators use a start date and a target date to
245 * compute the propagated state. For propagators using event detection mechanism,
246 * if the provided start date is different from the initial state date, a first,
247 * simple propagation is performed, without processing any event computation.
248 * Then complete propagation is performed from start date to target date.</p>
249 * @param start start date from which orbit state should be propagated
250 * @param target target date to which orbit state should be propagated
251 * @return propagated state
252 */
253 FieldSpacecraftState<T> propagate(FieldAbsoluteDate<T> start, FieldAbsoluteDate<T> target);
254
255 /** {@inheritDoc} */
256 @Override
257 default TimeStampedFieldPVCoordinates<T> getPVCoordinates(final FieldAbsoluteDate<T> date, final Frame frame) {
258 return propagate(date).getPVCoordinates(frame);
259 }
260
261 /** {@inheritDoc} */
262 @Override
263 default FieldVector3D<T> getVelocity(final FieldAbsoluteDate<T> date, final Frame frame) {
264 final FieldSpacecraftState<T> state = propagate(date);
265 if (frame == getFrame()) {
266 return state.getVelocity();
267 }
268 final FieldKinematicTransform<T> kinematicTransform = getFrame().getKinematicTransformTo(frame, date);
269 return kinematicTransform.transformOnlyPV(state.getPVCoordinates()).getVelocity();
270 }
271
272 /** {@inheritDoc} */
273 @Override
274 default FieldVector3D<T> getPosition(final FieldAbsoluteDate<T> date, final Frame frame) {
275 return propagate(date).getPosition(frame);
276 }
277
278 }