PiecewisePolynomialAcceleration#
- class PiecewisePolynomialAcceleration(origin: Body, spacecraft: Spacecraft, base_frame: Frame, t0: EpochArray | float, batch_length: float, n_batches: int, order: int, coefficients: ndarray | None = None, frame: str = 'inertial', body_fixed_frame=None, relative_body=None)#
Bases:
DynamicModelModels an empirical acceleration as a piecewise polynomial in time over a fixed batch grid.
The arc is divided into \(N_b\) batches of length \(L\) starting at \(t_0\), exactly as in
PiecewiseFirstOrderGaussMarkov. Within batch \(k\), with the local time \(\tau = (t - t_0 - kL)/L \in [0, 1]\), the acceleration is a polynomial of the chosenorder:order=0(zero-order hold)One constant 3-vector per batch,
\[\mathbf a(t) = \mathbf c_k ,\]which jumps at the batch boundaries.
order=1(first-order hold)One 3-vector per batch boundary (node), linearly interpolated in between,
\[\mathbf a(t) = (1 - \tau)\,\mathbf n_k + \tau\,\mathbf n_{k+1} ,\]so the acceleration is continuous across batches by construction: the end of batch \(k\) and the start of batch \(k+1\) share the node \(\mathbf n_{k+1}\).
The coefficients are components in the frame chosen with
frame, and the applied acceleration is \(\mathbf T\,\mathbf a(t)\), where \(\mathbf T\) rotates that frame into the propagation frame.Unlike the Gauss-Markov models, nothing here is integrated: the coefficients are constants of the dynamics, estimated as a
'static'parameter. The acceleration is linear in them, so the partial the filter needs is the interpolation matrix itself,\[\begin{split}\frac{\partial \mathbf a}{\partial \mathbf c} = \begin{cases} [\,\mathbf 0 \;\cdots\; \mathbf I_3 \;\cdots\; \mathbf 0\,] & \text{order } 0 \\ [\,\mathbf 0 \;\cdots\; (1-\tau)\mathbf I_3 \;\; \tau\mathbf I_3 \;\cdots\; \mathbf 0\,] & \text{order } 1 \end{cases}\end{split}\]which is exact rather than a difference approximation.
- Parameters:
- originBody
Propagation origin.
- spacecraftSpacecraft
Spacecraft the empirical acceleration acts on.
- base_frameFrame
Reference frame of the propagator.
- t0EpochArray or float
Reference epoch at which batch 0 starts, as an
EpochArrayor as raw ephemeris seconds (TDB). It is the origin of the batch grid, not the start of the current propagation: in a multi-legMissionSequenceevery leg must be given the samet0so the batches tile the whole arc and a coefficient means the same thing in every leg.- batch_lengthfloat
Duration of each batch, in seconds.
- n_batchesint
Number of batches.
- orderint
Polynomial order within a batch:
0for a zero-order hold (constant per batch),1for a first-order hold (linear per batch, continuous across batches). Required, since the two orders size the coefficient state differently.- coefficientsnp.ndarray, optional
Default coefficient vector, used when the propagated state carries no
a_ppolyentry. This is what makes the model usable as a plain force model — a known piecewise acceleration applied without estimating anything.- framestr, optional
Frame the coefficients are expressed in:
"inertial"(the propagation frame, the default),"RTN"(radial / along-track / cross-track, the RTN triad) or"body_fixed".- body_fixed_framestr or Frame, optional
Frame the coefficients are expressed in, for
frame="body_fixed"(for example'IAU_BENNU').- relative_bodystr or Body, optional
Body the RTN triad is built about, when that is not the propagation origin. Defaults to the propagation origin.
- Attributes:
batch_lengthDuration of one batch, in seconds.
body_fixed_frameBody-fixed frame the coefficients are expressed in, if any.
default_coefficientsCoefficients applied when the state carries no
a_ppolyentry.depends_on_velocityWhether the applied acceleration is a function of velocity.
frameFrame the coefficients are expressed in.
n_batchesNumber of batches.
n_coefficientsLength of the stacked
a_ppolystate:3*n_batchesor3*(n_batches+1).orderPolynomial order within a batch:
0or1.originCelestial body serving as origin of the state vector.
origin_nameName of the origin body.
ref_frameReference frame used by the model.
relative_bodyBody the RTN triad is referred to, if any.
t0Reference epoch of the first batch, in ephemeris seconds.
Methods
Drop any pinned batch, restoring the per-epoch lookup.
Names of the stacked coefficients, in state order.
compute_acceleration(position, ...)Piecewise polynomial acceleration applied to the body.
get_active_batch_bounds(epoch)Return the active batch index and its time bounds.
pin_batch_window(t_start, t_end)Pin the batch that owns an integration arc, so the dynamics stay continuous across it.
- Raises:
- InvalidOrderError
If
orderis not one ofORDERS.- InvalidBatchGridError
If
batch_length <= 0orn_batches < 1.- InvalidEpochError
If
t0is neither anEpochArraynor a real number.- CoefficientSizeError
If
coefficientsdoes not match the order and batch count.- DynamicalUtils.InvalidFrameError
If
frameis not one of the supported frames.- DynamicalUtils.MissingBodyFixedFrameError
If
frame="body_fixed"is requested withoutbody_fixed_frame.
See also
scarabaeus.PiecewiseFirstOrderGaussMarkovBatch-segmented stochastic variant.
scarabaeus.FourierAccelerationPeriodic empirical acceleration.
scarabaeus.StateArrayState vector used to initialize the model.
scarabaeus.DynamicModelAbstract base class for all force model components.
Notes
The estimated state is one stacked
("a_ppoly", spice_id)entry, ordered batch-major (order=0) or node-major (order=1):order 0: [ c0_x c0_y c0_z | c1_x c1_y c1_z | ... | c(N-1)_x ... ] 3*N order 1: [ n0_x n0_y n0_z | n1_x n1_y n1_z | ... | nN_x ... ] 3*(N+1)
with \(N\) the number of batches.
coefficient_labels()returns the matching names. The state vector must contain an entry of the form('a_ppoly', n_coefficients, 'estimated', 'static', owner, value)
for the coefficients to be estimated.
Batch membership follows the PFOGM convention: interior boundaries belong to the batch that starts there, and the closing endpoint belongs to the last batch. The propagator splits its arcs at the batch boundaries and pins each arc to its batch with
pin_batch_window(), so the zero-order hold’s jump never falls inside an integration step.In the
"RTN"frame the coefficients are radial, along-track and cross-track components, and the coefficient partial above is left-multiplied by \(\mathbf T\). The RTN triad is built from the state, so the acceleration also gains the position and velocity partialsframe_partials()returns; the inertial and body-fixed rotations depend on the epoch alone.Examples
A first-order hold over four one-day batches, estimated:
import scarabaeus as scb state = [ ("position", 3, "estimated", "dynamic", sc, [7000, 0, 0]), ("velocity", 3, "estimated", "dynamic", sc, [0, 7.5, 0]), ("a_ppoly", 15, "estimated", "static", sc, [0.0] * 15), ] force_model = scb.ForceModelTranslation( primary_body=sc, t0=arc_start, piecewise_polynomial=True, ppoly_order=1, ppoly_batch_length=86400.0, ppoly_n_batches=4, )
- coefficient_labels() list[str]#
Names of the stacked coefficients, in state order.
- Returns:
- list of str
['batch0_x', 'batch0_y', ...]fororder=0or['node0_x', 'node0_y', ...]fororder=1, matching the layout of thea_ppolystate. The axes followframe:R,T,Nin the RTN frame.
- compute_acceleration(position: ndarray, current_state: dict, epoch: float, body: Body) ndarray#
Piecewise polynomial acceleration applied to the body.
- Parameters:
- positionnp.ndarray
Spacecraft position vector, used only to build the RTN triad.
- current_statedict
Dictionary containing the propagated state.
- epochfloat
Current epoch in ephemeris seconds (TDB).
- bodyBody
Body the acceleration is evaluated for.
- Returns:
- np.ndarray
Acceleration 3-vector in km/s^2, in the propagation frame. Zero when neither the state nor the model configuration supplies coefficients.
- get_active_batch_bounds(epoch: float) tuple[int, float, float]#
Return the active batch index and its time bounds.
- Parameters:
- epochfloat
Current epoch in ephemeris seconds (TDB).
- Returns:
- tuple[int, float, float]
Tuple
(batch_idx, batch_start, batch_end).
- pin_batch_window(t_start: float, t_end: float) int | None#
Pin the batch that owns an integration arc, so the dynamics stay continuous across it.
Batch membership is right-continuous, so the epoch closing an arc that ends on a batch boundary belongs to the next batch. For a zero-order hold the acceleration jumps there; for a first-order hold its slope does. Either way an integrator evaluating its final stage on the boundary sees a discontinuity at the very point it has to land on. Pinning the batch for the arc removes it from the arc’s interior and endpoint alike.
Only arcs that lie within a single batch are pinned; the propagator already splits arcs at interior batch boundaries, so that is the normal case. Anything else clears the pin and leaves the per-epoch lookup in charge.
- Parameters:
- t_start, t_endfloat
Arc bounds in ephemeris seconds (TDB); order does not matter.
- Returns:
- int or None
The pinned batch index, or
Noneif the arc was not pinned.
- ORDERS = (0, 1)#
Polynomial orders the model supports: zero-order and first-order hold.
- property default_coefficients#
Coefficients applied when the state carries no
a_ppolyentry.
- property depends_on_velocity: bool#
Whether the applied acceleration is a function of velocity.
True for the RTN frame, whose triad is built from the velocity. The force model reads this to decide whether a \(\partial \mathbf a / \partial \mathbf v\) block is needed.
- property ref_frame#
Reference frame used by the model.
- exception CoefficientSizeError#
Bases:
ValueErrorRaised when the
a_ppolystate does not match the order and grid.
- exception EpochOutsideGridError#
Bases:
ValueErrorRaised when an epoch falls outside the batch grid.
- exception InvalidBatchGridError#
Bases:
ValueErrorRaised when
batch_lengthorn_batchescannot form a grid.
- exception InvalidEpochError#
Bases:
TypeErrorRaised when
t0is neither anEpochArraynor a real number.
- exception InvalidOrderError#
Bases:
ValueErrorRaised when
orderis not a supported polynomial order.