Theory
This section presents the error-state multiplicative EKF implemented on the code.
Please note that the documentation currently is bare bones, and the notation used might not be very rigorous; I will be adding more details and improving the documentation as the project progresses.
Notation
Code |
Math |
Description |
|---|---|---|
|
\(\mathbf{q}\) |
Attitude quaternion |
|
\(\boldsymbol{\beta}\) |
Gyro bias vector |
|
\(\boldsymbol{\delta\theta}\) |
Attitude error rotation vector |
|
\(\boldsymbol{\omega}\) |
Angular velocity vector |
|
\(P\) |
Error covariance matrix |
|
\(\Phi\) |
State transition matrix |
|
\(Q\) |
Discrete-time process noise covariance matrix |
|
\(K\) |
Kalman gain matrix |
|
\(H\) |
Measurement matrix |
|
\(R\) |
Measurement noise covariance matrix |
|
\(S\) |
Innovation covariance matrix |
|
\(\sigma_v\) |
Gyro angle random walk coefficient [rad/s^{0.5}] |
|
\(\sigma_u\) |
Gyro rate random walk coefficient [rad/s^{1.5}] |
|
\(\sigma_{st}\) |
Star tracker measurement accuracy [arcsec] |
|
\(\Delta t\) |
Base time step for ground truth propagation |
|
\(\Delta t_g\) |
Time step between gyro measurements |
|
\(I_3\) |
Identity matrix (3x3) |
Code |
Math |
Description |
|---|---|---|
|
\(\hat{X}\) |
Estimated value of variable |
|
\(X_t\) |
Ground truth value of variable |
|
\(X_m\) |
Measured value of variable |
|
\(X_0\) |
Initial value of variable |
|
\(X_l\) |
Logged variable for analysis |
|
\(\delta X\) |
Error between truth and estimate ( |
|
\(X_n\) |
Noise term added to variable |
State and Error Representation
The nominal state consists of the estimates for the attitude quaternion and gyro bias, where \((\hat{\mathbf{q}}, \hat{\beta}) \in \mathbb{S}^3 \times \mathbb{R}^3\). However, the Kalman filter updates the error states, then injects these updates to the nominal state. The error quaternion is the relation between the ground truth quaternion, represented multiplicatevely:
We use the error rotation vector \(\boldsymbol{\delta\theta} \in \mathbb{R}^3\) in our state instead of the error quaternion:
For small angles,
A gyro measurement is modelled with a moving bias and white noise (random walk):
The bias grows as a Weiner process, at a level related to the rate random walk coefficient:
The gyro bias error is defined as:
Quaternion math
Throughout the documentation, we use the following quaternion multiplication convention. First we define the quaternion function \(\Xi\):
Then, the quaternion multiplication is defined as:
In the code we use the function quat_mul in utils.py to perform this multiplication. The quaternion inverse is defined as:
Initialization
The user provides an initial gyro bias \(\boldsymbol{\beta_0}\) and initial attitude quaternion \(\boldsymbol{\mathbf{q}_0}\). Additionally, the user provides initial values for the Kalman filter estimator: the attitude error covariance \(P_q\) and the gyro bias error covariance \(P_b\); the initial estimate of the attitude error \(\boldsymbol{\delta\theta_0}\) and the initial estimate of the gyro bias error \(\boldsymbol{\delta\beta_0}\).
Ground truth update
The user inputs a desired ground truth angular velocity \(\boldsymbol{\omega_t}(t)\) with the function w_t_fun in efk.py. The user also inputs an initial gyro bias \(\boldsymbol{\beta_0}\). The ground truth quaternion and gyro bias are propagated at a period of \(\Delta t\).
Define \(\varphi = \|\boldsymbol{\omega}_t\| \Delta t\). The quaternion increment associated with the rotation \(\boldsymbol{\omega}_t \Delta t\) is:
This assumes that the angular velocity is constant throughout this timestep. The ground truth update is:
In a discrete step, the bias is updated as:
Estimate propagation (gyro measurements)
Gyros are used for dynamic model replacement, i.e. I do not integrate the Euler rigid body equations. Instead, I use the gyro measurements to propagate the estimate.
At gyro sampling instants separated by \(\Delta t_g\), the gyro provides a measurement which is synthesized from the ground truth angular velocity \(\boldsymbol{\omega}_t\) and the gyro bias \(\boldsymbol{\beta}_t\).
The estimate of the angular velocity is:
We propagate the estimated attitude quaternion the same way as the ground truth (see the section above).
The bias is constant in propagation:
The covariance propagation in a gyro measurement step is discussed in the next two sections.
Linearized Error-State Propagation
Let \(\boldsymbol{\delta x} = \begin{bmatrix} \boldsymbol{\delta\theta} \\ \delta\boldsymbol{\beta} \end{bmatrix} \in \mathbb{R}^6\). For a step \(\Delta t_g\) with input \(\boldsymbol{\hat{\omega}}\), the first-order discrete transition is:
With \(\varphi = \|\boldsymbol{\hat{\omega}}\| \Delta t_g\), \(s = \sin \varphi\), \(c = \cos \varphi\), and boldsymbol{hat{omega}}_times is the skew-symmetric matrix of \(\boldsymbol{\hat{\omega}}\),
For \(\|\boldsymbol{\hat{\omega}}\| \Delta t_g \ll 1\), the approximation
can be used (user toggleable).
Process Noise Discretization
With gyro angle random walk density \(\sigma_v^2\) and bias random walk density \(\sigma_u^2\), the discrete process covariance over \(\Delta t_g\) is
Finally, covaraince is propagated as:
Star tracker measurement synthesis
At star tracker measurement events, a quaternion measurement \(\mathbf{q}_m\) of attitude is available. This is synthesized from the ground truth quaternion \(q_t\) with white noise. This is done by synthesizing a R3 vector with white noise and then converting it to a quaternion.
Here, we used small angle approximation (as the startracker measurement error is in the order of arcseconds). Now, the estimated error quaternion for this measurement is:
We then convert this to a rotation vector, explained in the first section.
The observation model matrix is:
The measurement noise covariance matrix is the startracker measurement accuracy (assumed isotropic):
We discuss the measurement update and injection in the next section, carried out in star tracker measurement events.
Measurement update and injection
Compute the innovation covariance and gain, then the correction:
Split \(\boldsymbol{\delta \hat x} = \begin{bmatrix} \hat{\boldsymbol{\delta\theta}} \\ \hat{\boldsymbol{\delta\beta}} \end{bmatrix}\) and inject into the global state:
Map the estimated error vector to a quaternion:
and update the attitude multiplicatively:
Update the covariance (the Joseph form is used by default; a simple form is also available):