The org.orekit.forces.maneuvers
package and sub-packages provide several type of maneuvers for orbit control.
The simplest maneuver model is ImpulseManeuver
. This models an instantaneous velocity change. As the change is a discrete event, it is implemented as an EventDetector
with an event handler that return Action.RESET_STATE
when the event occurs, so the resetState
method can be called and change the spacecraft velocity.
As ImpulseManeuver
is really an EventDetector
and relies on resetState
, it can be used with most propagators (analytical propagators, semi-analytical propagators or numerical propagators). It cannot be used with TLE propagators or ephemeris-based propagators because they forbid state resets.
The ImpulseManeuver
is built from a lower level EventDetector
that acts as a trigger for the maneuver. Any detector can be used. Classical ones are DateDetector
for maneuvers with already known dates, but it is possible to use for example NodeDetector
to perform inclination maneuvers at nodes or PositionAngleDetector
to perform circularization maneuvers at apogee.
The other build parameters for ImpulseManeuver
are the ΔV vector in spacecraft frame (typically one of the canonical spacecraft axis depending on the thruster used for this maneuvers) and the specific impulse (which is used to update the mass). The ΔV vector will be converted from spacecraft frame to inertial frame taking into account either the current attitude as configured in the propagator or an overriding attitude provider. Overriding the attitude allows to configure the nominal attitude in the propagator while using a maneuver-specific attitude just for the sake of ΔV vector computation.
The most accurate maneuver model is Maneuver
. This models a progressive velocity change induced by firing a thruster. As the change is a continuous one, it is implemented as a ForceModel
.
As Maneuver
is really a ForceModel
, it can be used only with integration-based propagators (semi-analytical propagators with some care and numerical propagator). Using it with semi-analytical propagators is limited, though. Large maneuvers or long maneuvers that extend to a sizeable portion of the orbit may break the assumptions used to separate mean motion from short periodic terms.
The following class diagram shows the design of the Maneuver
class and supporting classes and interfaces.
A Maneuver
contains a PropulsionModel
, a ManeuverTriggers
and an optional attitude override.
The PropulsionModel
defines the characteristics of the acceleration. Its main implementation is BasicConstantThrustPropulsionModel
. The ScaledConstantThrustPropulsionModel
implementation is inteded to be used in estimation processes, by evaluating scaling factors.
The ManeuverTriggers
defines when the acceleration occurs. There are two main implementations: IntervalEventTrigger
and StartStopEventsTrigger
. IntervalEventTrigger
is based on a single event detector, firing intervals correspond to time spans with positive value of the single event detector g
function. StartStopEventsTrigger
is based on a pair of event detectors, firing intervals starts when the start detector g
function becomes positive and stops when the stop detector g
function becomes positive. The decreasing events of both detectors (i.e. when their g
functions become negative) are ignored.
In order to allow field-based propagation, both IntervalEventTrigger
and StartStopEventsTrigger
classes are abstract classes and concrete subclasses must implement a conversion method to automatically generate a field-based event detector from the primitive double based detector provided at construction time for any field. This may be tricky to do and Java syntax is sometimes abstruse with parameterized classes and methods. The following code snippet shows how to do it for an arbitrary XyzDetector
for which a field-based implementation FieldXyzDetector
exists. In this example, we assume the detector is built from a date and a number parameter and we use it in IntervalEventTrigger
. The pattern for StartStopEventsTrigger
is similar, except that two methods must be implemented: convertStartDetector
and convertStopDetector
.
public XyzTrigger extends IntervalEventTrigger<XysDetector> { protected <D extends FieldEventDetector<S>, S extends CalculusFieldElement<S>> FieldAbstractDetector<D, S> convertIntervalDetector(final Field<S> field, final XyzDetector detector) { final FieldAbsoluteDate<S> date = new FieldAbsoluteDate<>(field, detector.getDate()); final S param = field.getZero().newInstance(detector.getParam()); @SuppressWarnings("unchecked") final FieldAbstractDetector<D, S> converted = (FieldAbstractDetector<D, S>) new FieldXyzDetector<>(date, param); return converted; } }
The SmallManeuverAnalyticalModel
is another maneuver model intended to be used for fast optimization of a large number of small station-keeping maneuvers at once.
The principle of this model is to run a full-featured propagator without maneuvers first and have it generate a reference ephemeris. Then, at each iteration of an optimization loop, an AdapterPropagator
is created and populated with the differential effects induced by the maneuvers that should be added to the reference ephemeris. The maneuvers created change from iteration to iteration as their parameters are optimized. Then the AdapterPropagator
is run and the station keeping targets are checked. As the differential effects are analytical and as the reference ephemeris, once generated, is also analytical, this propagation loop is much faster than using the full-featured propagator itself during optimization.
Of course, once the maneuvers parameters have been optimized, a new full-featured propagation can be performed with maneuvers taken into account for full accuracy.