Home Robotics Blog: Extended Kalman Filter
Post
Cancel

Robotics Blog: Extended Kalman Filter

This posts outlines an example of localization using an EKF filter. The model is based on a Python implementation by AtsushiSakai on Github. Implementation.

Extended Kalman Filter

The kalman filter is linear algorithm that combines a series of noisy measurements and produces an estimate of unknown variables that tend to be more accurate than if you were to use one estimate. The extended kalman filter is a nonlinear version of the kalman filter in which we linearize the motion model and observation model to propogate our states.

The equations that govern the extended kalman filter are as follows:

State Predict:

\[X_{Pred} = F X_t + B u_t\] \[P_{Pred} = J_F P_t J_F^T + Q\]

State Update:

\[z_{Pred} = H X_{Pred}\] \[Y = z - z_{Pred}\] \[S = J_H P_{Pred} J_H^T + R\] \[K = P_{Pred} J_H^T S^{-1}\] \[X_{t+1} = X_{Pred} + KY\] \[P_{t+1} = (I - K J_H) P_{Pred}\]

In-depth Example

State, Control and Observation

Let us model the state, control and observation of a 2D robot as follows:

We track the (x, y) position of the robot, heading \(\phi\) and velocity \(v\) in its state

\[X_t = \begin{bmatrix} x_t \\ y_t \\ \phi_t \\ v_t \\ \end{bmatrix}\]

We can send any combination of linear velocity and angular velocity to our robot.

\[u_t = \begin{bmatrix} v_t \\ \omega_t \\ \end{bmatrix}\]

Our robot makes GPS-like observatoins to its current location.

\[z_t = \begin{bmatrix} x_t \\ y_t \\ \end{bmatrix}\]

Motion Model

Our robot will be a differential drive robot, so it’s equations of motion are described as follows:

\[\dot{x} = v cos(\phi)\] \[\dot{y} = v sin(\phi)\] \[\dot{\phi} = \omega\]

For a small time step we can update the state with the following eqation:

\[X_{t+1} = \begin{bmatrix} x_t + v cos \phi_t \Delta_t \\ y_t + v sin \phi_t \Delta_t \\ \phi_t + \omega_t \Delta_t \\ v_t \end{bmatrix}\]

We can express this in matrix form

\[X_{t+1} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 0 \\ \end{bmatrix} \begin{bmatrix} x_t \\ y_t \\ \phi_t \\ v_t \\ \end{bmatrix} + \begin{bmatrix} cos \phi_t \Delta_t & 0 \\ sin \phi_t \Delta_t & 0 \\ 0 & \Delta_t \\ 1 & 0 \\ \end{bmatrix} \begin{bmatrix} v_t \\ \omega_t \\ \end{bmatrix}\] \[X_{t+1} = F X_{t} + B u_t\]

The jacobian of F is:

\[J_F = \begin{bmatrix} \frac{\partial x}{\partial x} & \frac{\partial x}{\partial y} & \frac{\partial x}{\partial \phi} & \frac{\partial x}{\partial v} \\ \frac{\partial y}{\partial x} & \frac{\partial y}{\partial y} & \frac{\partial y}{\partial \phi} & \frac{\partial y}{\partial v} \\ \frac{\partial \phi}{\partial x} & \frac{\partial \phi}{\partial y} & \frac{\partial \phi}{\partial \phi} & \frac{\partial \phi}{\partial v} \\ \frac{\partial v}{\partial x} & \frac{\partial v}{\partial y} & \frac{\partial v}{\partial \phi} & \frac{\partial v}{\partial v} \\ \end{bmatrix} = \begin{bmatrix} 1 & 0 & -v sin \phi \Delta_t & cos \phi \Delta_t \\ 0 & 1 & v cos \phi \Delta_t & sin \phi \Delta_t \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}\]

Observation Model

The matrix form of our observation model is:

\[z_t = H x_t\] \[z_t = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ \end{bmatrix} \begin{bmatrix} x_t \\ y_t \\ \phi_t \\ v_t \end{bmatrix} = \begin{bmatrix} x_t \\ y_t \end{bmatrix}\]

The jacobian of our observation model is:

\[J_H = \begin{bmatrix} \frac{\partial x}{\partial x} & \frac{\partial x}{\partial y} & \frac{\partial x}{\partial \phi} & \frac{\partial x}{\partial v} \\ \frac{\partial y}{\partial x} & \frac{\partial y}{\partial y} & \frac{\partial y}{\partial \phi} & \frac{\partial y}{\partial v} \\ \end{bmatrix} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \end{bmatrix}\]

Doing the Filtering

We propogate our state using the extendedKalmanFilter filter function which is basically identical to the equations given above.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void extendedKalmanFilter(Eigen::Vector4f& x_est, Eigen::Matrix4f& P_est,
                       const Eigen::Vector2f& u, const Eigen::Vector2f& z,
                       const Eigen::Matrix4f& Q, const Eigen::Matrix2f& R,
                       const float dt ) {
    // state predict
    Eigen::Vector4f x_pred = motionModel(x_est, u, dt); // 4x1
    Eigen::Matrix4f J_F = jacobianF(x_est, u, dt); //4x4
    Eigen::Matrix4f P_pred = J_F * P_est * J_F.transpose() + Q; // 4x4

    // state update
    Eigen::Vector2f z_pred = observationModel(x_pred);
    Eigen::Vector2f y = z - z_pred;

    Eigen::Matrix<float, 2, 4> J_H = jacobianH();
    Eigen::Matrix2f S = J_H * P_pred * J_H.transpose() + R;
    Eigen::Matrix<float, 4, 2> K  = P_pred *  J_H.transpose() * S.inverse();

    x_est = x_pred + K * y;
    P_est = (Eigen::Matrix4f::Identity()  - K * J_H) * P_pred;
}
This post is licensed under CC BY 4.0 by the author.
Contents