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