FilterPy

FilterPy is a Python library that implements a number of Bayesian filters, most notably Kalman filters. I am writing it in conjunction with my book Kalman and Bayesian Filters in Python [1], a free book written using Ipython Notebook, hosted on github, and readable via nbviewer. However, it implements a wide variety of functionality that is not described in the book.

As such this library has a strong pedalogical flavor. It is rare that I choose the most efficient way to calculate something unless it does not obscure exposition of the concepts of the filtering being done. I will always opt for clarity over speed. I do not mean to imply that this is a toy; I use it all of the time in my job.

I mainly develop in Python 3.x, but this should support both Python 2.x and 3.x flavors. At the moment I can not tell you the lowest required version; I tend to develop on the bleeding edge of the Python releases. I am happy to receive bug reports if it does not work with older versions, but testing backwards compatibility is not a high priority at the moment. As the package matures I will shift my focus in that direction.

FilterPy requires Numpy [2] and SciPy [3] to work. The tests and examples also use matplotlib [4]. For testing I use py.test [5].

Installation

Installation with GitHub

You can get the very latest code by getting it from GitHub and then performing the installation. I will say I am not following particularly stringent version control discipline. I mostly stay on master and commit things that are not entirely ready for prime-time, mostly because I’m the only one developing. I do not promise that any check in that is not tagged with a version number is usable.

$ git clone --depth=1 https://github.com/rlabbe/filterpy.git
$ cd filterpy
$ python setup.py install

–depth=1 just gets you the last few revisions that I made, which keeps the repo small. If you want the entire repo leave out the depth parameter, or fork the repo if you plan to modify it.

Use

There are several submodules, each listed below. But in general you will need to import which classes and/or functions you need from the correct submodule, construct the objects, and then execute your code. Something lke

>>> from filterpy.kalman import KalmanFilter
>>> kf = KalmanFilter(dim_x=3, dim_z=1)

I try to provide examples in the help for each class, but this documentation needs a lot of work. For now I refer you to my book mentioned above if the documentation is not adequate. Better yet, write an issue on the GitHub issue tracker. I will respond with an answer as soon as I am online and available (minutes to a day, normally), and then revise the documentation. I shouldn’t have to be prodded like this, but life is limited. So prod.

Raise issues here: https://github.com/rlabbe/filterpy/issues

FilterPy’s Naming Conventions

A word on variable names. I am an advocate for descriptive variable names. In the Kalman filter literature the measurement noise covariance matrix is called R. The name R is not descriptive. I could reasonably call it measurement_noise_covariance, and I’ve seen libraries do that. I’ve chosen not to.

In the end, Kalman filtering is math. To write a Kalman filter you are going to start by sitting down with a piece of paper and doing math. You will be writing and solving normal algebraic equations. Every Kalman filter text and source on the web uses the same equations. You cannot read about the Kalman filter without seeing this equation

\[\dot{\mathbf{x}} = \mathbf{Fx} + \mathbf{Gu} + w\]

One of my goals is to bring you to the point where you can read the original literature on Kalman filtering. For nontrivial problems the difficulty is not the implementation of the equations, but learning how to set up the equations so they solve your problem. In other words, every Kalman filter implements \(\dot{\mathbf{x}} = \mathbf{Fx} + \mathbf{Gu} + w\); the difficult part is figuring out what to put in the matrices \(\mathbf{F}\) and \(\mathbf{G}\) to make your filter work for your problem. Vast amounts of work have been done to apply Kalman filters in various domains, and it would be tragic to be unable to avail yourself of this research.

So, like it or not you will need to learn that \(\mathbf{F}\) is the state transition matrix and that \(\mathbf{R}\) is the measurement noise covariance. Once you know that the code will become readable, and until then Kalman filter math, and all publications and web articles on Kalman filters will be inaccessible to you.

Finally, I think that mathematical programming is somewhat different than regular programming; what is readable in one domain is not readable in another. q = x + m is opaque in a normal context. On the other hand, x = (.5*a)*t**2 + v_0*t + x_0 is to me the most readable way to program the Newtonian distance equation:

\[x = \frac{1}{2}at^2 + v_0 t + x_0\]

We could write it as

distance = (.5 * constant_acceleration) * time_delta**2 +
           initial_velocity * time_delta + initial_distance

but I feel that obscures readability. This is debatable for this one equation; but most mathematical programs, and certainly Kalman filters, use systems of equations. I can most easily follow the code, and ensure that it does not have bugs, when it reads as close to the math as possible. Consider this equation from the Kalman filter:

\[\mathbf{K} = \mathbf{PH}^\mathsf{T}[\mathbf{HPH}^\mathsf{T} + \mathbf{R}]^{-1}\]

Python code for this would be

K = dot(P, H.T).dot(inv(dot(H, P).dot(H.T) + R))

It’s already a bit hard to read because of the dot function calls (required because Python does not yet support an operator for matrix multiplication). But compare this to:

kalman_gain = (
    dot(apriori_state_covariance, measurement_function_transpose).dot(
    inv(dot(measurement_function, apriori_state_covariance).dot(
    measurement_function_transpose) + measurement_noise_covariance)))

which I adapted from a popular library. I grant you this version has more context, but I cannot glance at this and see what math it is implementing. In particular, the linear algebra \(\mathbf{HPH}^\mathsf{T}\) is doing something very specific - multiplying \(\mathbf{P}\) by \(\mathbf{H}\) in a way that converts \(\mathbf{P}\) from world space to measurement space (we’ll learn what that means). It is nearly impossible to see that the Kalman gain (K) is just a ratio of one number divided by a second number which has been converted to a different basis. This statement may not convey a lot of information to you before reading the book, but I assure you that \(\mathbf{K} = \mathbf{PH}^\mathsf{T}[\mathbf{HPH}^\mathsf{T} + \mathbf{R}]^{-1}\) is saying something very succinctly. There are two key pieces of information here - we are finding a ratio, and we are doing it in measurement space. I can see that in my first Python line, I cannot see that in the second line. If you want a counter-argument, my version obscures the information that \(\mathbf{P}\) is in this context is a prior .

These comments apply to library code. Calling code should use names like sensor_noise, or gps_sensor_noise, not R. Math code should read like math, and interface or glue code should read like normal code. Context is important.

I will not win this argument, and some people will not agree with my naming choices. I will finish by stating, very truthfully, that I made two mistakes the first time I typed the second version and it took me awhile to find it. In any case, I aim for using the mathematical symbol names whenever possible, coupled with readable class and function names. So, it is KalmanFilter.P, not KF.P and not KalmanFilter.apriori_state_covariance.

Communication

Unless it is deeply private (you don’t want someone else seeing propietary code, for example), please ask questions and such on the issue tracker, not by email. This is solely so that everyone gets to see the answer. “Issue” doesn’t mean bug.

Modules

filterpy.kalman

The classes in this submodule implement the various Kalman filters. There is also support for smoother functions. The smoothers are methods of the classes. For example, the KalmanFilter class contains rts_smoother to perform Rauch-Tung-Striebal smoothing.

Linear Kalman Filters

Implements various Kalman filters using the linear equations form of the filter.

Extended Kalman Filter

Unscented Kalman Filter

These modules are used to implement the Unscented Kalman filter.

Ensemble Kalman Filter

filterpy.common

Contains various useful functions that support the filtering classes and functions. Most useful are functions to compute the process noise matrix Q. It also implements the Van Loan discretization of a linear differential equation.

filterpy.stats

Contains statistical functions useful for Kalman filtering such as multivariate Gaussian multiplication, computing the log-likelihood, NESS, and mahalanobis distance, along with plotting routines to plot multivariate Gaussians CDFs, PDFs, and covariance ellipses.

filterpy.monte_carlo

Routines for Markov Chain Monte Carlo (MCMC) computation, mainly for particle filtering.

filterpy.discrete_bayes

Routines for performing discrete Bayes filtering.

filterpy.gh

These classes various g-h filters. The functions are helpers that provide settings for the g and h parameters for various common filters.

filterpy.memory

Implements a polynomial fading memory filter. You can achieve the same results, and more, using the KalmanFilter class. However, some books use this form of the fading memory filter, so it is here for completeness. I suppose some would also find this simpler to use than the standard Kalman filter.

filterpy.hinfinity

filterpy.leastsq

Indices and tables