ADCS.estimators.attitude_estimators.attitude_UAKF module¶
- class ADCS.estimators.attitude_estimators.attitude_UAKF.UAKF(est_sat, J2000, x_hat, P_hat, Q_hat, dt=1.0, cross_term=False, quat_as_vec=False)[source]¶
Bases:
Attitude_EstimatorUnscented Kalman Filter (UKF) with an error-state attitude representation.
This class implements an Unscented Kalman Filter (UKF) for spacecraft attitude estimation and associated bias/parameter states. It inherits the augmented-state bookkeeping (full-state storage, reduced covariance representation, and satellite synchronization) from
Attitude_Estimator.The implementation uses an error-state attitude representation by default (
quat_as_vec=False), in which the quaternion is stored in the full state vector but the covariance is stored in a minimal 3-parameter attitude-error coordinate (e.g., \(\delta\boldsymbol{\theta}\in\mathbb{R}^3\)). Ifquat_as_vec=True, the quaternion is included as a 4-vector in the covariance.State and covariance structure¶
Let the full augmented state be
\[\begin{split}\mathbf{x} = \begin{bmatrix} \boldsymbol{\omega} \\ \mathbf{q} \\ \mathbf{z} \end{bmatrix},\end{split}\]where \(\boldsymbol{\omega}\in\mathbb{R}^3\) is the angular rate, \(\mathbf{q}\in\mathbb{R}^4\) is the unit quaternion, and \(\mathbf{z}\) stacks remaining physical/bias/disturbance states.
In reduced error-state mode, the filter internally works with an error vector
\[\begin{split}\delta\mathbf{x} = \begin{bmatrix} \delta\boldsymbol{\omega} \\ \delta\boldsymbol{\theta} \\ \delta\mathbf{z} \end{bmatrix},\end{split}\]with \(\delta\boldsymbol{\theta}\in\mathbb{R}^3\) representing attitude error, typically mapped to a quaternion increment \(\delta\mathbf{q}\) and composed multiplicatively with a reference quaternion. The full state always stores \(\mathbf{q}\) explicitly.
Unscented transform overview¶
For an augmented dimension \(L\), the UKF constructs sigma points \(\chi_i\) around the current mean using
\[\lambda = \alpha^2 (L + \kappa) - L,\qquad \gamma = \sqrt{L + \lambda}.\]Mean and covariance weights are
\[W_0^{(m)} = \frac{\lambda}{L+\lambda},\qquad W_0^{(c)} = \frac{\lambda}{L+\lambda} + (1-\alpha^2+\beta),\]\[W_i^{(m)} = W_i^{(c)} = \frac{1}{2(L+\lambda)},\quad i=1,\ldots,2L.\]Sigma points are propagated through the nonlinear dynamics
\[\chi_i^- = f(\chi_i, \mathbf{u}, \mathbf{w}_i),\]where propagation is performed by
noiseless_rk4()with appropriate injected control perturbations. Predicted measurements are\[\gamma_i^- = h(\chi_i^-),\]computed using
sensor_readings()(with anErrorModeselecting bias/noise behavior).Predicted means are
\[\bar{\mathbf{x}}^- = \sum_{i=0}^{2L} W_i^{(m)} \chi_i^-,\qquad \bar{\mathbf{y}}^- = \sum_{i=0}^{2L} W_i^{(m)} \gamma_i^-.\]Covariances are
\[P^- = \sum_{i=0}^{2L} W_i^{(c)}(\chi_i^- - \bar{\mathbf{x}}^-)(\chi_i^- - \bar{\mathbf{x}}^-)^\top + Q,\]\[P_{yy} = \sum_{i=0}^{2L} W_i^{(c)}(\gamma_i^- - \bar{\mathbf{y}}^-)(\gamma_i^- - \bar{\mathbf{y}}^-)^\top + R,\]\[P_{y x} = \sum_{i=0}^{2L} W_i^{(c)}(\gamma_i^- - \bar{\mathbf{y}}^-)(\chi_i^- - \bar{\mathbf{x}}^-)^\top.\]The gain is formed as
\[K = P_{x y} P_{yy}^{-1},\]and the mean/covariance are updated using innovation \(\boldsymbol{\nu} = \mathbf{y} - \bar{\mathbf{y}}^-\):
\[\bar{\mathbf{x}}^+ = \bar{\mathbf{x}}^- + K\boldsymbol{\nu},\qquad P^+ = P^- - K P_{yy} K^\top.\]Quaternion error composition¶
In reduced attitude-error mode, attitude is updated multiplicatively:
\[\delta\mathbf{q} = \operatorname{vec3\_to\_quat}(\delta\boldsymbol{\theta}),\qquad \mathbf{q}^+ = \mathbf{q}^- \otimes \delta\mathbf{q},\]using
vec3_to_quat()andquat_mult(). Ifquat_as_vec=True, the quaternion is renormalized vianormalize(), and covariance is transformed usingstate_norm_jac().- add_to_state(state, add)[source]¶
Apply an error perturbation to a base state on the attitude manifold.
This method implements the sigma-point “addition” operator. In Euclidean state components, it is additive. For quaternion attitude, it is multiplicative when
quat_as_vec=False.Single-point (vector) case¶
For a single base state \(\mathbf{x}\) and perturbation \(\delta\mathbf{x}\), the update is:
If
quat_as_vec=True(additive quaternion with renormalization):\[\mathbf{x}^+ = \mathbf{x} + \delta\mathbf{x},\qquad \mathbf{q}^+ \leftarrow \frac{\mathbf{q}^+}{\lVert \mathbf{q}^+ \rVert}.\]Quaternion normalization uses
normalize().If
quat_as_vec=False(multiplicative quaternion):\[\boldsymbol{\omega}^+ = \boldsymbol{\omega} + \delta\boldsymbol{\omega},\]\[\delta\mathbf{q} = \operatorname{vec3\_to\_quat}(\delta\boldsymbol{\theta}),\qquad \mathbf{q}^+ = \mathbf{q} \otimes \delta\mathbf{q},\]\[\mathbf{z}^+ = \mathbf{z} + \delta\mathbf{z}.\]Quaternion composition uses
quat_mult()and the vector-to-quaternion map usesvec3_to_quat().
Batch (matrix) case¶
If
addis a 2D array (sigma-point perturbations), the same operations are applied row-wise. Forquat_as_vec=True, quaternion rows are normalized withmatrix_row_normalize().- param state:
Base state vector (1D) or base full state vector (1D) used for all sigma points.
- type state:
numpy.ndarray
- param add:
Perturbation/error vector(s), shape
(n,)or(k,n).- type add:
numpy.ndarray
- return:
Updated state vector(s) after applying the perturbation on the manifold.
- rtype:
numpy.ndarray
- Parameters:
state (ndarray)
add (ndarray)
- Return type:
ndarray
- determine_covariances_to_use(state_cov, sens_cov, control_cov, int_cov)[source]¶
Determine which covariance blocks are included in sigma-point augmentation.
The UKF may be implemented with an augmented state that includes process noise and/or measurement noise as additional random variables. This method encodes the estimator’s policy for which covariance blocks contribute to the augmented dimension \(L\) used in sigma point generation.
In this implementation, the returned list corresponds to:
\[[\text{state},\ \text{sensor},\ \text{control},\ \text{process}],\]determining whether each covariance block is included in the sigma-point construction in
make_pts_and_wts().- Parameters:
state_cov (numpy.ndarray) – State covariance matrix \(P\) (reduced or full according to
quat_as_vec).sens_cov (numpy.ndarray) – Sensor noise covariance matrix \(R\) for active sensors.
control_cov (numpy.ndarray) – Control noise covariance associated with actuation commands.
int_cov (numpy.ndarray) – Process (integration) noise covariance \(Q\).
- Returns:
A 4-element boolean list indicating whether to include
[state, sensor, control, process]covariance blocks.- Return type:
list[bool]
- make_pts_and_wts(pt0, which_sensors)[source]¶
Build augmented sigma points and Unscented Transform weights.
This method constructs sigma points in an augmented space comprised of selected covariance blocks (state, sensor noise, control noise, process noise). The inclusion policy is determined by
determine_covariances_to_use().Augmented dimension¶
Let covariance blocks be:
state covariance \(P_x\),
sensor covariance \(R\),
control covariance \(Q_u\),
process covariance \(Q\).
With inclusion flags \(b_j\in\{0,1\}\), the augmented dimension is
\[L = \sum_{j} b_j\, n_j,\]where \(n_j\) is the dimension of the corresponding block.
Sigma point generation¶
Define
\[\lambda = \alpha^2(L+\kappa) - L,\qquad \gamma = \sqrt{L + \lambda},\qquad \text{scale} = L + \lambda.\]For each included block with covariance \(P\), the method forms the scaled Cholesky factor:
\[\text{scale}\,P = LL^\top,\]using
numpy.linalg.cholesky(), then creates offsets\[\Delta_i \in \{\pm L_{:,k}\}_{k=1}^{n},\]yielding \(2n\) offsets per block.
For the state block (error-state), offsets are mapped onto the manifold using
add_to_state(), ensuring multiplicative quaternion perturbations whenquat_as_vec=False.For non-state blocks (noise blocks), offsets are inserted into the sigma-point container list structure as additive perturbations on those blocks only.
Weights¶
Mean and covariance weights follow the standard UKF formulas:
\[W_0^{(m)} = \frac{\lambda}{L+\lambda},\qquad W_0^{(c)} = \frac{\lambda}{L+\lambda} + (1-\alpha^2+\beta),\]\[W_i^{(m)} = W_i^{(c)} = \frac{1}{2(L+\lambda)},\quad i=1,\ldots,2L.\]Output formats¶
The method returns:
pts: a list of length \(2L+1\) where each entry is:\[[\text{full\_state},\ \text{sens\_noise},\ \text{control\_noise},\ \text{int\_noise}].\]sig0: a stacked array of the state component only, aligned withpts. Points not perturbed in the state block are padded with the mean state.
- param pt0:
Current mean full state vector.
- type pt0:
numpy.ndarray
- param which_sensors:
Boolean mask indicating which sensors are active/valid.
- type which_sensors:
list[bool]
- return:
Tuple
(L, pts, wts_m, wts_c, sig0)where:Lis the augmented dimension,ptsis the sigma-point container list,wts_mare mean weights (length \(2L+1\)),wts_care covariance weights (length \(2L+1\)),sig0is the stacked state-only sigma-point array aligned withpts.
- rtype:
tuple[int, list, numpy.ndarray, numpy.ndarray, numpy.ndarray]
- Parameters:
pt0 (ndarray)
which_sensors (List[bool])
- new_post_state(pre_rest_state, post_dynstate, int_err, quatref)[source]¶
Construct posterior reduced and full states after propagation with integration error.
This helper reconstructs, for a given sigma point, both:
post_state: the reduced error-state representation used internally by the UKF,full_state: the full augmented state with quaternion suitable for satellite models.
Integration error injection¶
The integration error vector
int_erris interpreted in the reduced error-state coordinates and partitioned into:a head portion applied to the dynamic state on the manifold via
add_to_state(),a tail portion applied additively to the remaining bias/parameter states.
If
state_lenis the satellite dynamic-state length (including quaternion), the reduced “head length” used is\[n_h = \text{state\_len} - 1 + \mathbf{1}[\text{quat\_as\_vec}],\]matching the implementation.
Full-state reconstruction¶
After obtaining the reduced posterior vector
post_state, the method constructs an auxiliary reference state containingquatrefand then re-applies the reduced perturbation usingadd_to_state()to produce a full state with a quaternion.- param pre_rest_state:
Bias/parameter states before propagation (assumed constant through dynamics).
- type pre_rest_state:
numpy.ndarray
- param post_dynstate:
Propagated dynamic state (rate + quaternion + other dynamic entries).
- type post_dynstate:
numpy.ndarray
- param int_err:
Integration error/process-noise vector for this sigma point (reduced coordinates).
- type int_err:
numpy.ndarray
- param quatref:
Reference quaternion used for sigma-point attitude error mapping.
- type quatref:
numpy.ndarray
- return:
Tuple
(post_state, full_state)wherepost_stateis the reduced error-state vector andfull_stateis the full augmented state vector.- rtype:
tuple[numpy.ndarray, numpy.ndarray]
- Parameters:
pre_rest_state (ndarray)
post_dynstate (ndarray)
int_err (ndarray)
quatref (ndarray)
- reunite_states(dynstate, rest_state, quatref)[source]¶
Reassemble the reduced error-state vector from propagated dynamics and static components.
This helper constructs a reduced state representation used internally by the filter for sigma-point bookkeeping.
Quaternion mapping¶
If
quat_as_vec=True, the quaternion is treated as part of the additive state vector and the method simply concatenates:\[\begin{split}\mathbf{x}_{red} = \begin{bmatrix}\mathbf{x}_{dyn} \\ \mathbf{x}_{rest}\end{bmatrix}.\end{split}\]If
quat_as_vec=False, the propagated dynamic statedynstatecontains the full quaternion \(\mathbf{q}\). The method converts this quaternion into a 3-vector attitude error relative to a reference quaternion \(\mathbf{q}_{ref}\) by computing:\[\delta\mathbf{q} = \mathbf{q}_{ref}^{-1} \otimes \mathbf{q},\]using
quat_inv()andquat_mult(), then mapping \(\delta\mathbf{q}\) to a 3-vector:\[\delta\boldsymbol{\theta} = \operatorname{quat\_to\_vec3}(\delta\mathbf{q}),\]via
quat_to_vec3().The returned reduced vector is arranged as:
\[[\boldsymbol{\omega},\ \delta\boldsymbol{\theta},\ \text{(other dyn)},\ \text{rest\_state}].\]- param dynstate:
Dynamic part of the state (rate + attitude + other dynamic entries); contains a full quaternion.
- type dynstate:
numpy.ndarray
- param rest_state:
Static/bias/parameter portion of the state appended after the dynamic portion.
- type rest_state:
numpy.ndarray
- param quatref:
Reference quaternion used to compute the attitude error (ignored if
quat_as_vec=True).- type quatref:
numpy.ndarray
- return:
Reduced error-state vector consistent with the estimator’s internal representation.
- rtype:
numpy.ndarray
- Parameters:
dynstate (ndarray)
rest_state (ndarray)
quatref (ndarray)
- Return type:
ndarray
- sat_match(est_sat, state)[source]¶
Synchronize an
EstimatedSatelliteinstance with a raw full state vector.Sigma-point propagation and measurement prediction require the satellite model to reflect the sigma point’s specific biases/parameters and attitude. This method constructs an
EstimatedArraycompatible container, inserts the provided raw state entries at indices defined byuse, and then updates the satellite model viamatch_estimate().- Parameters:
est_sat (
EstimatedSatellite) – Satellite model instance to be updated for sigma-point propagation.state (numpy.ndarray) – Full augmented state vector to apply.
- Returns:
None.- Return type:
None
- update_core(u, sensors, os)[source]¶
Perform one UKF predict/update cycle in reduced error-state coordinates.
This method implements a complete UKF step:
Determine active sensors from the provided measurement vector (NaN check), then expand to an output-level mask via
_expand_sensor_mask().Build augmented sigma points via
make_pts_and_wts().Propagate each sigma point through nonlinear dynamics using
noiseless_rk4().Predict measurements for each propagated sigma point using
sensor_readings()withErrorModeselecting bias inclusion.Compute predicted mean/covariances using unscented weights.
Solve for Kalman gain, apply innovation update, and map the reduced attitude error back to a full quaternion state.
Orbital interpolation (CG5)¶
This implementation computes intermediate orbital states between
prev_osand the currentOrbital_Stateusing coefficients fromCG5:\[\mathbf{o}_j = \operatorname{average}(\mathbf{o}_{prev}, \mathbf{o}, c_j),\qquad j=0,\ldots,4,\]via
average(), where \(c_j\) are the CG5 coefficients.Unscented prediction and update¶
Let propagated reduced sigma points be \(\chi_i^-\) and predicted measurement sigma points be \(\gamma_i^-\). Predicted means:
\[\bar{\mathbf{x}}^- = \sum_{i=0}^{2L} W_i^{(m)} \chi_i^-,\qquad \bar{\mathbf{y}}^- = \sum_{i=0}^{2L} W_i^{(m)} \gamma_i^-.\]Deviations:
\[\mathbf{X}_i = \chi_i^- - \bar{\mathbf{x}}^-,\qquad \mathbf{Y}_i = \gamma_i^- - \bar{\mathbf{y}}^-.\]Covariances:
\[P^- = \sum_{i=0}^{2L} W_i^{(c)} \mathbf{X}_i\mathbf{X}_i^\top + Q,\]\[P_{yy} = \sum_{i=0}^{2L} W_i^{(c)} \mathbf{Y}_i\mathbf{Y}_i^\top + R,\]\[P_{y x} = \sum_{i=0}^{2L} W_i^{(c)} \mathbf{Y}_i\mathbf{X}_i^\top.\]Gain and update (note the implementation’s array orientation):
\[K = P_{yy}^{-1} P_{y x},\]and with innovation \(\boldsymbol{\nu}=\mathbf{y}-\bar{\mathbf{y}}^-\):
\[\bar{\mathbf{x}}^+ = \bar{\mathbf{x}}^- + \boldsymbol{\nu}^\top K,\]\[P^+ = P^- - K^\top P_{yy} K.\]Quaternion reconstruction¶
In reduced attitude-error mode (
quat_as_vec=False), the updated reduced vector contains an attitude error \(\delta\boldsymbol{\theta}\) which is mapped to a quaternion increment and composed with the propagated reference quaternion:\[\delta\mathbf{q} = \operatorname{vec3\_to\_quat}(\delta\boldsymbol{\theta}),\qquad \mathbf{q}^+ = \mathbf{q}_{ref} \otimes \delta\mathbf{q},\]using
vec3_to_quat()andquat_mult().If
quat_as_vec=True, the quaternion is renormalized withnormalize()and the covariance is transformed by the normalization Jacobian fromstate_norm_jac():\[P^+ \leftarrow J^\top P^+ J.\]- param u:
Control input vector.
- type u:
numpy.ndarray
- param sensors:
Stacked array of actual sensor measurements.
- type sensors:
numpy.ndarray
- param os:
Current orbital environment state.
- type os:
- raises numpy.linalg.LinAlgError:
If the measurement covariance matrix is singular during gain computation.
- return:
Updated estimate container with updated full state and reduced covariance.
- rtype:
- Parameters:
u (ndarray)
sensors (ndarray)
os (Orbital_State)
- Return type:
- Parameters:
est_sat (EstimatedSatellite)
J2000 (float)
x_hat (ndarray)
P_hat (ndarray)
Q_hat (ndarray)
dt (float)
cross_term (bool)
quat_as_vec (bool)