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&eacute;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 }