.. FilterPy documentation master file
FilterPy
********
.. toctree::
:maxdepth: 2
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 pip (recommended)
-----------------------------------
FilterPy is available on github (https://github.com/rlabbe/filterpy). However,
it is also hosted on PyPi, and unless you want to be on the bleeding edge of
development I recommend you get it from there. To install from the command line,
merely type:
.. code-block:: bash
$ pip install filterpy
To test the installation, from a python REPL type:
>>> import filterpy
>>> filterpy.__version__
and it should display the version number that you installed.
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.
.. code-block:: bash
$ 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
.. math::
\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 :math:`\dot{\mathbf{x}} = \mathbf{Fx} + \mathbf{Gu} + w`; the difficult part is figuring out what to put in the matrices :math:`\mathbf{F}` and :math:`\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 :math:`\mathbf{F}` is the *state transition matrix* and that :math:`\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:
.. math::
x = \frac{1}{2}at^2 + v_0 t + x_0
We could write it as
.. code-block:: Python
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:
.. math::
\mathbf{K} = \mathbf{PH}^\mathsf{T}[\mathbf{HPH}^\mathsf{T} + \mathbf{R}]^{-1}
Python code for this would be
.. code-block:: Python
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 :math:`\mathbf{HPH}^\mathsf{T}` is doing something very specific - multiplying :math:`\mathbf{P}` by :math:`\mathbf{H}` in a way that converts :math:`\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 :math:`\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 :math:`\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.
.. toctree::
:maxdepth: 1
kalman/KalmanFilter
kalman/Saver
kalman/FixedLagSmoother
kalman/SquareRootFilter
kalman/InformationFilter
kalman/FadingKalmanFilter
kalman/MMAEFilterBank
kalman/IMMEstimator
Extended Kalman Filter
++++++++++++++++++++++
.. toctree::
:maxdepth: 1
kalman/ExtendedKalmanFilter
Unscented Kalman Filter
+++++++++++++++++++++++
These modules are used to implement the Unscented Kalman filter.
.. toctree::
:maxdepth: 1
kalman/UnscentedKalmanFilter
kalman/unscented_transform
Ensemble Kalman Filter
+++++++++++++++++++++++
.. toctree::
:maxdepth: 1
kalman/EnsembleKalmanFilter
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.
.. toctree::
:maxdepth: 1
common/common
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.
.. toctree::
:maxdepth: 1
stats/stats
filterpy.monte_carlo
--------------------
Routines for Markov Chain Monte Carlo (MCMC) computation, mainly for
particle filtering.
.. toctree::
:maxdepth: 1
monte_carlo/resampling
filterpy.discrete_bayes
-----------------------
Routines for performing discrete Bayes filtering.
.. toctree::
:maxdepth: 1
discrete_bayes/discrete_bayes
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.
.. toctree::
:maxdepth: 1
gh/GHFilterOrder
gh/GHFilter
gh/GHKFilter
gh/optimal_noise_smoothing
gh/least_squares_parameters
gh/critical_damping_parameters
gh/benedict_bornder_constants
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.
.. toctree::
:maxdepth: 1
memory/FadingMemoryFilter
filterpy.hinfinity
------------------
.. toctree::
:maxdepth: 1
hinfinity/HInfinityFilter
filterpy.leastsq
++++++++++++++++
.. toctree::
:maxdepth: 1
leastsq/LeastSquaresFilter
References
==========
.. [1] Labbe, Roger. "Kalman and Bayesian Filters in Python".
github repo:
https://github.com/rlabbe/Kalman-and-Bayesian-Filters-in-Python
read online:
http://nbviewer.ipython.org/github/rlabbe/Kalman-and-Bayesian-Filters-in-Python/blob/master/table_of_contents.ipynb
PDF version (often lags the two sources above)
https://github.com/rlabbe/Kalman-and-Bayesian-Filters-in-Python/blob/master/Kalman_and_Bayesian_Filters_in_Python.pdf
.. [2] NumPy
http://www.numpy.org
.. [3] SciPy
http://www.scipy.org
.. [4] matplotlib
http://http://matplotlib.org/
.. [5] pytest http://pytest.org/latest/
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`