DynamicalUtils#
- class DynamicalUtils#
Bases:
objectShared geometry of the dynamics models: the spacecraft attitude of the surface-force models and the component frames of the empirical accelerations.
Spacecraft attitude. Force models whose surfaces or boresights are fixed in the spacecraft frame (
nPlateSRP,ThermalRadiation,AntennaRadiationPressure) need the spacecraft-fixed to inertial rotation \(C\), so that a spacecraft-fixed vector \(\mathbf{e}_b\) reaches the inertial frame as \(\mathbf{e} = C\mathbf{e}_b\). The supportedSpacecraft.attitudeModevalues,ATTITUDE_MODES, are:"CK": \(C\) from the loaded C-kernel (ck_dcm())."inertialFixedAttitude": \(C\) isSpacecraft.fixedInertialAttitude(fixed_dcm())."nadirPointingSun": the axes follow the heliocentric position \(\mathbf{s}\) and velocity \(\mathbf{w}\) (nadirPointingSun()),\[\hat{\mathbf{x}} = \frac{\mathbf{s}}{\lVert\mathbf{s}\rVert},\quad \hat{\mathbf{z}} = \frac{\hat{\mathbf{x}}\times\hat{\mathbf{w}}} {\lVert\hat{\mathbf{x}}\times\hat{\mathbf{w}}\rVert},\quad \hat{\mathbf{y}} = \hat{\mathbf{z}}\times\hat{\mathbf{x}},\quad C = \left[\hat{\mathbf{x}}\;\hat{\mathbf{y}}\;\hat{\mathbf{z}}\right]\]so the spacecraft \(-X\) axis points at the Sun. It replaces the deprecated
inertial_to_body_DCM_nadirPointingSun(), which returns \(C^T\). Only this mode depends on the state, and on the velocity as well as the position.
The last nadir attitude evaluated with derivatives is kept here, since the position and velocity Jacobians of every surface model are taken at one state.
Acceleration frames. An empirical acceleration (
FirstOrderGaussMarkov,PiecewiseFirstOrderGaussMarkov,PiecewisePolynomialAcceleration,FourierAcceleration) can express its components \(\mathbf{a}^{(f)}\) in a chosen frame. They reach the propagation frame as \(\mathbf{a} = T\,\mathbf{a}^{(f)}\) (from_frame()). Theframeoptions are the keys ofACCELERATION_FRAME_AXES:"inertial": components in the propagation frame, \(T = I\)."body_fixed": components in a rotating body-fixed frame, rotated out through SPICE, \(T = R_{bf\to rf}(t)\) (body_fixed_rotation())."RTN": components in the radial / along-track / cross-track triad of the orbit (also called RSW or RIC), \(T = \left[\hat{\mathbf{R}}\;\hat{\mathbf{T}}\; \hat{\mathbf{N}}\right]\), fromrtn(), which is built and differentiated like the nadir attitude. The triad is built from the state, so it adds the position and velocity partialsframe_partials()returns. With arelative_bodyit describes the orbit about that body rather than the propagation origin (relative_state()).
A model resolves its settings once in its constructor with
resolve_frame(), and exposes them as the publicframe,body_fixed_frameandrelative_bodyproperties next toref_frameandorigin_name, which is all the methods here read. A model that also carries a_frame_memodict gets the body-fixed rotation and the relative-body offset memoized for the epoch of the RHS step in progress: the acceleration and every partial are evaluated at the same epoch, so each SPICE lookup happens once per step rather than per call.All methods are static or class methods and work on raw NumPy arrays; no instantiation is required:
mode = scb.DynamicalUtils.attitude_mode(spacecraft) C, D_r, D_v = scb.DynamicalUtils.nadirPointingSun(s, w, derivatives=True) frame, bff, rel = scb.DynamicalUtils.resolve_frame("rtn") a = scb.DynamicalUtils.from_frame(model, a_rtn, r, state, epoch, sc) da_dr, da_dv = scb.DynamicalUtils.frame_partials( model, a_rtn, r, state, epoch, sc )
Methods
attitude_mode(body)The spacecraft attitude mode, checked against
ATTITUDE_MODES.body_fixed_rotation(model, epoch)Body-fixed to propagation-frame rotation \(R_{bf\to rf}(t)\).
body_vector_jacobian(vectors_b, D)Jacobian of spacecraft-fixed vectors mapped to the inertial frame, \(\partial(C\mathbf{e}_b)/\partial\mathbf{q} = \sum_j e_{b,j} D[j]\).
ck_dcm(body, epoch[, frame])Spacecraft-fixed to inertial rotation from the C-kernel.
cross(a, b)Cross product of two
(3,)vectors, written out by component.depends_on_velocity(body)Whether the attitude of
bodydepends on its velocity.fixed_dcm(body)Spacecraft-fixed to inertial rotation of an
inertialFixedAttitudespacecraft.frame_matrix(model, position, current_state, ...)Rotation from the component frame into the propagation frame.
frame_name(frame)Reduce a Frame or string to the frame name SPICE expects.
frame_partials(model, a_frame, position, ...)Position and velocity partials of \(T\,\mathbf{a}^{(f)}\) for frame-local components that do not depend on the state.
from_frame(model, values, position, ...)Rotate frame-local components into the propagation frame.
nadirPointingSun(sun2body, sun2body_vel[, ...])Spacecraft-fixed to inertial rotation of the
nadirPointingSunattitude and, optionally, its derivatives.relative_state(model, position, ...)Spacecraft position and velocity about the body the orbit is described about.
resolve_frame([frame, body_fixed_frame, ...])Validate the frame settings of a frame-expressed acceleration.
rtn(position, velocity[, derivatives])Radial / along-track / cross-track (RTN) to inertial rotation of an orbit and, optionally, its derivatives.
rtn_triad(model, position, current_state, ...)RTN triad of the orbit about the model's relative body.
skew(v)Cross-product matrix \([\mathbf{v}]_\times\), so that \([\mathbf{v}]_\times \mathbf{u} = \mathbf{v} \times \mathbf{u}\).
sun_to_origin_velocity(origin_spice_name, ...)Sun->origin velocity from SPICE.
velocity_from_state(current_state, body)Spacecraft velocity relative to the origin, read from the state.
See also
scarabaeus.nPlateSRPSolar radiation pressure on a plate model.
scarabaeus.ThermalRadiationThermal re-radiation recoil.
scarabaeus.AntennaRadiationPressureAntenna and LIDAR recoil.
scarabaeus.SpacecraftCarries
attitudeModeandfixedInertialAttitude.scarabaeus.FirstOrderGaussMarkovGauss-Markov empirical acceleration.
scarabaeus.FourierAccelerationFourier-series empirical acceleration.
- classmethod attitude_mode(body) str#
The spacecraft attitude mode, checked against
ATTITUDE_MODES.- Parameters:
- bodySpacecraft
The spacecraft.
- Returns:
- str
body.attitudeMode.
- Raises:
- InvalidAttitudeModeError
If the mode is not one of
ATTITUDE_MODES.
- classmethod body_fixed_rotation(model, epoch) ndarray#
Body-fixed to propagation-frame rotation \(R_{bf\to rf}(t)\).
- Parameters:
- modelDynamicModel
Frame-expressed acceleration; reads
body_fixed_frameandref_frame.- epochfloat
Epoch of the rotation, in ephemeris seconds (TDB).
- Returns:
- numpy.ndarray
(3, 3)rotation matrix.
- Raises:
- MissingEpochError
If no epoch is supplied.
- classmethod fixed_dcm(body) ndarray#
Spacecraft-fixed to inertial rotation of an
inertialFixedAttitudespacecraft.- Parameters:
- bodySpacecraft
The spacecraft.
- Returns:
- numpy.ndarray
(3, 3)float copy ofbody.fixedInertialAttitude.
- Raises:
- InvalidFixedAttitudeError
If
fixedInertialAttitudeis not a 3x3np.ndarray.
- classmethod frame_matrix(model, position, current_state: dict, epoch, body)#
Rotation from the component frame into the propagation frame.
- Parameters:
- modelDynamicModel
Frame-expressed acceleration.
- positionnumpy.ndarray
Spacecraft position 3-vector, km.
- current_statedict
The propagated state.
- epochfloat
Current epoch in ephemeris seconds (TDB).
- bodyBody
Body the acceleration is evaluated for.
- Returns:
- numpy.ndarray or None
(3, 3)rotation, orNonefor the inertial frame, where the components already live in the propagation frame.
- classmethod frame_partials(model, a_frame, position, current_state: dict, epoch, body) tuple#
Position and velocity partials of \(T\,\mathbf{a}^{(f)}\) for frame-local components that do not depend on the state.
Only the RTN triad is built from the state, so
\[\frac{\partial \mathbf{a}}{\partial \mathbf{r}} = \sum_j a^{(f)}_j \, \frac{\partial \hat{\mathbf{e}}_j}{\partial \mathbf{r}}, \qquad \frac{\partial \mathbf{a}}{\partial \mathbf{v}} = \sum_j a^{(f)}_j \, \frac{\partial \hat{\mathbf{e}}_j}{\partial \mathbf{v}},\]with \(\hat{\mathbf{e}}_j\) the RTN axes. The inertial and body-fixed rotations depend on the epoch alone, so both blocks are zero there.
- Parameters:
- modelDynamicModel
Frame-expressed acceleration.
- a_framenumpy.ndarray
Frame-local acceleration 3-vector, km/s^2.
- positionnumpy.ndarray
Spacecraft position 3-vector, km.
- current_statedict
The propagated state.
- epochfloat
Current epoch in ephemeris seconds (TDB).
- bodyBody
Body the acceleration is evaluated for.
- Returns:
- tuple of numpy.ndarray
(da_dr, da_dv), each(3, 3).
- classmethod from_frame(model, values, position, current_state: dict, epoch, body)#
Rotate frame-local components into the propagation frame.
Applied to the acceleration, \(\mathbf{a} = T\,\mathbf{a}^{(f)}\), and to its partial with respect to a parameter the frame does not depend on, \(\partial\mathbf{a}/\partial\mathbf{p} = T\,\partial\mathbf{a}^{(f)}/\partial\mathbf{p}\).
- Parameters:
- modelDynamicModel
Frame-expressed acceleration.
- valuesnumpy.ndarray
3-vector or
(3, n)matrix of frame-local components.- positionnumpy.ndarray
Spacecraft position 3-vector, km.
- current_statedict
The propagated state.
- epochfloat
Current epoch in ephemeris seconds (TDB).
- bodyBody
Body the acceleration is evaluated for.
- Returns:
- numpy.ndarray
valuesexpressed in the propagation frame.
- classmethod nadirPointingSun(sun2body, sun2body_vel, derivatives: bool = False) tuple#
Spacecraft-fixed to inertial rotation of the
nadirPointingSunattitude and, optionally, its derivatives.With \(C = [\hat{\mathbf{x}}\;\hat{\mathbf{y}}\;\hat{\mathbf{z}}]\) (see the class docstring) the derivatives are returned per axis,
D[j]being the Jacobian of axis \(j\). With \(\hat{\mathbf{w}}\) the unit heliocentric velocity and \(\mathbf{z}_0 = \hat{\mathbf{x}}\times\hat{\mathbf{w}}\):\[\frac{\partial\hat{\mathbf{x}}}{\partial\mathbf{r}} = \frac{I - \hat{\mathbf{x}}\hat{\mathbf{x}}^T} {\lVert\mathbf{s}\rVert},\quad \frac{\partial\hat{\mathbf{z}}}{\partial\mathbf{r}} = -\frac{I - \hat{\mathbf{z}}\hat{\mathbf{z}}^T} {\lVert\mathbf{z}_0\rVert} [\hat{\mathbf{w}}]_\times \frac{\partial\hat{\mathbf{x}}}{\partial\mathbf{r}},\quad \frac{\partial\hat{\mathbf{y}}}{\partial\mathbf{r}} = [\hat{\mathbf{z}}]_\times \frac{\partial\hat{\mathbf{x}}}{\partial\mathbf{r}} - [\hat{\mathbf{x}}]_\times \frac{\partial\hat{\mathbf{z}}}{\partial\mathbf{r}}\]and, since \(\hat{\mathbf{x}}\) does not depend on the velocity,
\[\frac{\partial\hat{\mathbf{z}}}{\partial\mathbf{v}} = \frac{I - \hat{\mathbf{z}}\hat{\mathbf{z}}^T} {\lVert\mathbf{z}_0\rVert} [\hat{\mathbf{x}}]_\times \frac{I - \hat{\mathbf{w}}\hat{\mathbf{w}}^T} {\lVert\mathbf{w}\rVert},\quad \frac{\partial\hat{\mathbf{y}}}{\partial\mathbf{v}} = -[\hat{\mathbf{x}}]_\times \frac{\partial\hat{\mathbf{z}}}{\partial\mathbf{v}}\]The Sun->origin terms do not depend on the spacecraft state, so these are the derivatives with respect to the spacecraft position \(\mathbf{r}\) and velocity \(\mathbf{v}\) relative to the origin. A spacecraft-fixed vector then has \(\partial\mathbf{e}/\partial\mathbf{r} = \sum_j e_{b,j} D_r[j]\) (
body_vector_jacobian()).- Parameters:
- sun2bodynumpy.ndarray or ArrayBox
(3,)Sun->spacecraft position, km.- sun2body_velnumpy.ndarray or ArrayBox
(3,)Sun->spacecraft velocity, km/s.- derivativesbool, optional
Also return the derivatives. Defaults to
False.
- Returns:
- tuple
(C, D_r, D_v):Cis the(3, 3)spacecraft-fixed to inertial DCM, traced when the inputs are;D_randD_vare plain(3, 3, 3)arrays, orNonewhenderivativesis false.
- classmethod relative_state(model, position, current_state: dict, epoch, body) tuple#
Spacecraft position and velocity about the body the orbit is described about.
Identical to the propagated state when
model.relative_bodyis unset. When it is set, the body’s own state is subtracted, so the RTN triad describes the orbit about that body.The offset comes from the ephemeris and so does not depend on the spacecraft state: the partials of anything built from the relative state are therefore unchanged in form, since \(\partial \mathbf{r}_{rel}/\partial \mathbf{r} = I\).
- Parameters:
- modelDynamicModel
Frame-expressed acceleration; reads
relative_body,ref_frameandorigin_name.- positionnumpy.ndarray
Spacecraft position 3-vector from the propagation origin, km.
- current_statedict
The propagated state.
- epochfloat
Current epoch in ephemeris seconds (TDB).
- bodyBody
Body the acceleration is evaluated for.
- Returns:
- tuple of numpy.ndarray
(r, v)relative torelative_body, in km and km/s.
- Raises:
- MissingEpochError
If
relative_bodyis set and no epoch is supplied.- MissingVelocityError
If the state carries no velocity for
body.
- classmethod resolve_frame(frame='inertial', body_fixed_frame=None, relative_body=None) tuple#
Validate the frame settings of a frame-expressed acceleration.
- Parameters:
- framestr, optional
"inertial","body_fixed"or"RTN", in any case. Defaults to"inertial".- body_fixed_framestr or Frame, optional
Frame the components 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: a lunar RTN frame while propagating an Earth-centred arc. Defaults to the propagation origin.
- Returns:
- tuple
(frame, body_fixed_frame, relative_body): the frame key as spelled inACCELERATION_FRAME_AXES, and the two names,Nonewhere unset.
- Raises:
- InvalidFrameError
If
frameis not a key ofACCELERATION_FRAME_AXES.- MissingBodyFixedFrameError
If
frame="body_fixed"is requested withoutbody_fixed_frame.
- classmethod rtn(position, velocity, derivatives: bool = False) tuple#
Radial / along-track / cross-track (RTN) to inertial rotation of an orbit and, optionally, its derivatives.
With the angular momentum \(\mathbf{h} = \mathbf{r}\times\mathbf{v}\),
\[\hat{\mathbf{R}} = \frac{\mathbf{r}}{\lVert\mathbf{r}\rVert},\quad \hat{\mathbf{N}} = \frac{\mathbf{h}}{\lVert\mathbf{h}\rVert},\quad \hat{\mathbf{T}} = \hat{\mathbf{N}}\times\hat{\mathbf{R}},\quad C = \left[\hat{\mathbf{R}}\;\hat{\mathbf{T}}\;\hat{\mathbf{N}}\right]\](the triad is also called RSW or RIC). The derivatives are returned per axis, as for
nadirPointingSun():\[\frac{\partial\hat{\mathbf{R}}}{\partial\mathbf{r}} = \frac{I - \hat{\mathbf{R}}\hat{\mathbf{R}}^T} {\lVert\mathbf{r}\rVert},\quad \frac{\partial\hat{\mathbf{N}}}{\partial\mathbf{r}} = -P_h[\mathbf{v}]_\times,\quad \frac{\partial\hat{\mathbf{N}}}{\partial\mathbf{v}} = P_h[\mathbf{r}]_\times,\quad P_h = \frac{I - \hat{\mathbf{N}}\hat{\mathbf{N}}^T}{\lVert\mathbf{h}\rVert}\]and \(d\hat{\mathbf{T}} = -[\hat{\mathbf{R}}]_\times d\hat{\mathbf{N}} + [\hat{\mathbf{N}}]_\times d\hat{\mathbf{R}}\). The radial axis does not depend on the velocity, so
D_v[0]is zero.- Parameters:
- positionnumpy.ndarray or ArrayBox
(3,)position about the body the orbit is described about, km.- velocitynumpy.ndarray or ArrayBox
(3,)velocity about the same body, km/s.- derivativesbool, optional
Also return the derivatives. Defaults to
False.
- Returns:
- tuple
(C, D_r, D_v):Cis the(3, 3)RTN to inertial DCM, traced when the inputs are;D_randD_vare plain(3, 3, 3)arrays, orNonewhenderivativesis false.
- Raises:
- DegenerateGeometryError
If the radius or the angular momentum vanishes.
- classmethod rtn_triad(model, position, current_state: dict, epoch, body, derivatives: bool = False) tuple#
RTN triad of the orbit about the model’s relative body.
relative_state()followed byrtn().- Parameters:
- modelDynamicModel
Frame-expressed acceleration.
- positionnumpy.ndarray
Spacecraft position 3-vector, km.
- current_statedict
The propagated state.
- epochfloat
Current epoch in ephemeris seconds (TDB).
- bodyBody
Body the acceleration is evaluated for.
- derivativesbool, optional
Also return the position and velocity derivatives of the axes.
- Returns:
- tuple
(T, D_r, D_v): the(3, 3)matrix \([\hat{\mathbf{R}}\;\hat{\mathbf{T}}\;\hat{\mathbf{N}}]\) and, withderivatives, the(3, 3, 3)stacks whose[j]is the Jacobian of axisj(Noneotherwise).
- Raises:
- DegenerateGeometryError
If the radius or the angular momentum vanishes.
- classmethod velocity_from_state(current_state: dict, body)#
Spacecraft velocity relative to the origin, read from the state.
- Parameters:
- current_statedict
The propagated state.
- bodySpacecraft
The spacecraft.
- Returns:
- numpy.ndarray or ArrayBox
(3,)velocity in km/s, still traced when the state is.
- Raises:
- MissingVelocityError
If the state holds neither
("velocity", spice_id)nor"velocity".
- static body_vector_jacobian(vectors_b: ndarray, D: ndarray) ndarray#
Jacobian of spacecraft-fixed vectors mapped to the inertial frame, \(\partial(C\mathbf{e}_b)/\partial\mathbf{q} = \sum_j e_{b,j} D[j]\).
- Parameters:
- vectors_bnumpy.ndarray
(3,)vector, or(..., 3)stack of vectors, in the spacecraft frame.- Dnumpy.ndarray
(3, 3, 3)axis derivatives fromnadirPointingSun()orrtn().
- Returns:
- numpy.ndarray
(3, 3)Jacobian, or(..., 3, 3)for a stack.
- static ck_dcm(body, epoch: float, frame: Frame = None) ndarray#
Spacecraft-fixed to inertial rotation from the C-kernel.
- Parameters:
- bodySpacecraft
Spacecraft whose C-kernel attitude is queried.
- epochfloat
TDB epoch (seconds past J2000).
- frameFrame, optional
Inertial frame. Anything that is not a
Frame, includingNone, means J2000.
- Returns:
- numpy.ndarray
(3, 3)spacecraft-fixed to inertial DCM.
- static cross(a, b)#
Cross product of two
(3,)vectors, written out by component.np.crossspends most of its time on axis handling for inputs this small; this is several times faster and stays traceable by autograd.- Parameters:
- a, bnumpy.ndarray or ArrayBox
(3,)vectors.
- Returns:
- numpy.ndarray or ArrayBox
(3,)vector \(\mathbf{a}\times\mathbf{b}\).
- static depends_on_velocity(body) bool#
Whether the attitude of
bodydepends on its velocity.True only for
"nadirPointingSun", whose Y axis follows the heliocentric velocity. The mode is not validated here.- Parameters:
- bodySpacecraft
The spacecraft.
- Returns:
- bool
- static frame_name(frame)#
Reduce a Frame or string to the frame name SPICE expects.
- Parameters:
- frameFrame or str or None
Frame to resolve.
- Returns:
- str or None
The frame name, or
Nonewhen nothing was supplied.
- static skew(v: ndarray) ndarray#
Cross-product matrix \([\mathbf{v}]_\times\), so that \([\mathbf{v}]_\times \mathbf{u} = \mathbf{v} \times \mathbf{u}\).
- Parameters:
- vnumpy.ndarray
(3,)vector.
- Returns:
- numpy.ndarray
(3, 3)skew-symmetric matrix.
- static sun_to_origin_velocity(origin_spice_name: str, frame, epoch: float) ndarray#
Sun->origin velocity from SPICE.
- Parameters:
- origin_spice_namestr
SPICE name of the propagation origin.
- frameFrame or str
Inertial frame of the result.
- epochfloat
TDB epoch (seconds past J2000).
- Returns:
- numpy.ndarray
(3,)Sun->origin velocity in km/s.
- ACCELERATION_FRAME_AXES = {'RTN': ('R', 'T', 'N'), 'body_fixed': ('x', 'y', 'z'), 'inertial': ('x', 'y', 'z')}#
Frames an empirical acceleration can be expressed in, with the axis labels of each. The keys are the
frameoptionsresolve_frame()accepts; the labels name the components in reports and plot legends. The inertial and body-fixed frames are Cartesian triads, the RTN one is radial / along-track / cross-track.
- ATTITUDE_MODES = ('CK', 'nadirPointingSun', 'inertialFixedAttitude')#
Spacecraft.attitudeModevalues the surface-force models support. Each is turned into the spacecraft-fixed to inertial rotation: from the loaded C-kernel, from the heliocentric position and velocity, or fromSpacecraft.fixedInertialAttitude.
- NADIR_ATTITUDE_MODE = 'nadirPointingSun'#
The entry of
ATTITUDE_MODESwhose rotation depends on the spacecraft state, on its velocity as well as its position.
- exception DegenerateGeometryError#
Bases:
ValueErrorThe RTN triad is undefined for the given state.
The along-track and cross-track directions follow the orbital angular momentum \(\mathbf{r}\times\mathbf{v}\), which vanishes for a zero radius or a purely radial trajectory.
- exception InvalidAttitudeModeError#
Bases:
ValueErrorThe spacecraft attitude mode is not supported.
Surface normals and boresights are fixed in the spacecraft frame, so a spacecraft-to-inertial rotation is needed. It is available for the
"CK","nadirPointingSun"and"inertialFixedAttitude"modes only.
- exception InvalidFixedAttitudeError#
Bases:
ValueErrorfixedInertialAttitudeis not a 3x3 array.An
inertialFixedAttitudespacecraft must carry the spacecraft-fixed to inertial rotation as a 3x3np.ndarray.
- exception InvalidFrameError#
Bases:
ValueErrorframeis not one of the supported frames.The options are the keys of
DynamicalUtils.ACCELERATION_FRAME_AXES, matched without regard to case.
- exception MissingBodyFixedFrameError#
Bases:
ValueErrorframe='body_fixed'was requested without a frame name.The body-fixed frame the components are expressed in (for example
'IAU_BENNU') is what SPICE rotates them out of.
- exception MissingEpochError#
Bases:
ValueErrorAn ephemeris lookup was needed but no epoch was supplied.
The body-fixed rotation and the offset of a
relative_bodyare both evaluated at the epoch of the acceleration.
- exception MissingVelocityError#
Bases:
KeyErrorThe spacecraft velocity is not in the propagated state.
The
nadirPointingSunattitude uses the heliocentric velocity to fix the spacecraft Y axis, and the RTN triad uses the orbital angular momentum, so the state must hold("velocity", spice_id)or a plain"velocity"entry.