Skip to content

Principle Introduction and Theoretical Support Analysis: Linear Kalman Filters

Kaelin Laundry edited this page Aug 25, 2019 · 23 revisions

Introduction

We keep track of our own odometry and tracked targets using simple linear kalman filters. All our kalman filters use a constant acceleration model.

We believe DJI has published a comprehensive article on the theory of linear kalman filters on the RoboMaster forums before so we will only be giving a brief introduction theory-wise.

There were multiple problems that we were unable to resolve this season so this page will be dedicated more to what we got wrong and the possible areas of improvement.

Theory Summary

We will give a very brief and non-mathematically rigorous introduction of the Kalman filter.

Standard Kalman Filter notation:

xk - state vector, x, at timestep k

Fk - transition matrix, F, at timestep, k

Bk - control matrix, B, at timestep, k (we do not use this)

uk - control vector, u, at timestep k (we do not use this)

Hk - measurement matrix, H, at timestep, k

zk - measurements, z, at timestep k

Qk - process noise covariance, Q, at timestep k

Rk - measurement noise covariance, R, at timestep k

Kk - Kalman gain, K, at timestep k

Pk - error covariances, P, at timestep k

@ denotes matrix multiplication

We will use d to denote the number of state parameters and m to denote the number of measurement parameters.

We use OpenCV's implementation of the Kalman Filter.

A Simple linear Kalman filter estimates the state at each timestep, xk, by the following process. It first makes an estimation of the current state using the transition model: predicted state = transition matrix @ previous state vector + control matrix @ control vector. This is typically called the 'predict step'. We denote this predicted state at timestep k as xprimek:

transition

We don't use the control matrix and control vector so this simplifies to

realtransition

for us.

After obtaining xprimek, the filter obtains a more accurate reading by correcting it using the measurements acquired on this timestep. This is typically called the 'update step'. First it obtains what the measurements should be on this timestep based on the predicted xprimek: predicted measurements = measurement matrix @ predicted state. We denote this predicted measurement at timestep k as zprimek.

measurement

It then calculates, yk, the difference between the actual measurement, zk, and the predicted measurements: deviation. After that, it calculates the Kalman gain, Kk, using the process noise covariance, Qk, the measurement noise covariance, Rk, and the predicted error covariances, Pprimek (calculation for Pprimek not shown). It then uses the Kalman gain, Kk, to update the predicted state to get the optimal state estimate for this timestep:

update

The Kalman gain is then also used to give the optimal estimates for the error covariances, Pk.

We've skipped presenting all the maths relating to the calculating of covariance estimates because their derivation and presentation are pretty lengthy, and RoboMaster has published an article on this before.

However, intuitively, the Kalman gain, Kk, is a d x m matrix that maps from measurement space into state space, and it gives a measure of how much the filter trusts the measurement, zk, over the prediction, xprimek. Kalman gain increases with a larger process noise, Qk, and decreases with a larger measurement noise, Rk. At the extreme where Kk is a zero matrix, the update step above becomes nomeas and the measurement is completely discarded. On the other extreme, Kk converges to the pseudo inverse of Hk, and the new state is just based on the measurement.

The Big Problems

While the linear Kalman filter is optimal for linear processes, it is obvious that robot movement is a non-linear process. Since our constant acceleration model for robot movement is wrong, error covariances, Pk, constantly increase in magnitude, and eventually our Kalman filter diverges.

We've made a temporary workaround by resetting the Kalman filters when the error covariances get too large. However, this is clearly not ideal.

As such, we will be exploring other state tracking and filtering algorithms more suited to our use case, such as the Extended Kalman Filter, Unscented Kalman Filter, Particle Filter, or even just moving averages, this next season.

We also did not spend enough time tuning the noise covariances (process noise Qk and measurement noise Rk) of our Kalman Filters.

There were other problems and mistakes that we made in our implementation of the linear Kalman filters as well, and we will detail them in the individual sections below.

We hope that other teams can study these mistakes and build upon them.

Detailed Breakdown

Odometry

All our measurements use the ROS coordinate system (+x forward, +y left, +z up) and radians for angular values. For angular values, positive is always counter-clockwise, i.e. the direction of your finger grip when pointing your right thumb in the direction of the axis.

Four wheel odometry

Four wheel odometry keeps track of the odometry data of all four wheel mecanum drive robots using data from wheel motor encoders and the IMU onboard the MCB Type A. We primarily referred to this paper for the math to calculate the robot's odometry. In particular, we used equation (2) and fig. 3 on the pages labelled 589 and 590 (page 3 and 4 on the PDF linked).

Relevant files:

  • aruw_odometry/src/four_wheel_mecanum_drive.py

Kalman filters:

We use 2 Kalman filters. One Kalman filter is in the chassis frame of reference while the other Kalman filter is in the IMU frame of reference.

Per common notation, v for velocity, a for acceleration, omega for angular velocity and alpha for angular acceleration

Chassis Kalman Filter

State vector xk:

s4

Transition Matrix Fk:

deltat

F4

Measurements zk:

z4

Measurements are calculated from the wheel RPMs using the formula detailed in the paper reference above.

Measurement Matrix Hk:

H4

Process and measurement noise covariances were not well-tuned.

IMU Kalman Filter:

State vector xk:

si

Transition Matrix Fk:

deltat

Fi

Measurements zk:

zi

Measurements are raw measurements from the IMU onboard the MCB Type A, except om_wheels, which is obtained from the state estimate of the chassis kalman filter. The purpose of om_wheels is to double as a measurement for om_z to mitigate yaw drift since we do not use the magnetometer to do so.

Measurement Matrix Hk:

Hi

Process and measurement noise covariances were not well-tuned.

Sentry odometry

Like four wheel odometry, sentry odometry keeps track of the odometry data of the sentry robot using data from wheel motor encoders and the IMU onboard the MCB Type A. The calculations were simpler since movement of the robot is confined to a single plane.

Relevant files:

  • aruw_odometry/src/sentinel_drive.py

Kalman filters:

Again, we use 2 Kalman filters. One Kalman filter is in the chassis frame of reference while the other Kalman filter is in the IMU frame of reference.

Chassis Kalman Filter

State vector xk:

ss

Transition Matrix Fk:

deltat

Fs

Measurements zk:

zs

Measurements are calculated by averaging the wheel RPMs and then using yaw readings from the IMU to determine direction.

Measurement Matrix Hk:

Hs

Process and measurement noise covariances were not well-tuned.

IMU Kalman Filter:

State vector xk:

si

Transition Matrix Fk:

deltat

Fi

Measurements zk:

zsi

Measurements are raw measurements from the IMU onboard the MCB Type A

Measurement Matrix Hk:

Hsi

Process and measurement noise covariances were not well-tuned.

Areas for improvement/ Roadmap:

  • Using 2 separate Kalman filters to keep track of odometry was a big mistake. We should be combining the measurements into a single Kalman filter and let the filter do the relative calculations instead of manually doing the relative calculations. For example, we currently use the four wheel odometry's yaw predictions from the chassis kalman filter to calculate relative vx and vy. To do this, one possible option is an Extended Kalman Filter which would require us to define the function that maps all the current odometry state variables - linear and angular position, velocity and acceleration - to the next predicted state. In the case above, if we had used an Extended Kalman Filter, the state transition mathematical function would simply capture how the current state's yaw affects the predicted vx.

  • Experiment with variable process and measurement covariances (Qk and Rk) that vary with deltatalone

  • Consider adding in user commands as a control vector for greater accuracy. However, these commands will likely have to be filtered due to latency.

Tracked target

We track our targets across time using a simple linear kalman filter with a constant acceleration model adjusted for time deltas as well.

For each tracked target, we match its current state measurement to the detected target that is closest to its predicted position. For more information, see: https://github.com/uw-advanced-robotics/aruw-vision-platform-2019/wiki/Principle-Introduction-and-Theoretical-Support-Analysis:-Target-Tracking-and-Target-Selection

Relevant files:

  • aruw_odometry/src/tracked_target.py

Kalman filter:

All variables are in the static ('odom') frame. Per common notation, v for velocity, a for acceleration.

State vector xk:

st

Transition Matrix Fk:

deltat

Fi

Measurements zk:

zt

Measurements are calculated by converting 3-D readings from the camera frame into the static frame.

Measurement Matrix Hk:

Ht

Process and measurement noise covariances were not well-tuned.

Areas for improvement/ Roadmap:

  • As was mentioned above, it seems like the linear kalman filter is not good enough.
  • Consider using velocity and acceleration data from our own odometry as a control vector