{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "[Table of Contents](http://nbviewer.ipython.org/github/rlabbe/Kalman-and-Bayesian-Filters-in-Python/blob/master/table_of_contents.ipynb)" ] }, { "cell_type": "raw", "metadata": { "collapsed": false }, "source": [ "\\appendix" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Installation, Python, NumPy, and FilterPy" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#format the book\n", "%matplotlib inline\n", "from __future__ import division, print_function\n", "import matplotlib.pyplot as plt\n", "import book_format\n", "book_format.load_style()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This book is written in IPython Notebook, a browser based interactive Python environment that mixes Python, text, and math. I choose it because of the interactive features - I found Kalman filtering nearly impossible to learn until I started working in an interactive environment. It is difficult to form an intuition of the effect of many of the parameters that you can tune until you can change them rapidly and immediately see the output. An interactive environment also allows you to play 'what if' scenarios out. \"What if I set $\\mathbf{Q}$ to zero?\" It is trivial to find out with IPython Notebook.\n", "\n", "Another reason I choose it is because I find that a typical textbook leaves many things opaque. For example, there might be a beautiful plot next to some pseudocode. That plot was produced by software, but software that is not available to me as a reader. I want everything that went into producing this book to be available to the reader. How do you plot a covariance ellipse? You won't know if you read most books. With IPython Notebook all you have to do is look at the source code.\n", "\n", "Even if you choose to read the book online you will want Python and the SciPy stack installed so that you can write your own Kalman filters. There are many different ways to install these libraries, and I cannot cover them all, but I will cover a few typical scenarios." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Installing the SciPy Stack" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This book requires IPython, NumPy, SciPy, SymPy, and Matplotlib. The SciPy stack depends on third party Fortran and C code, and is *not* trivial to install from source code - even the SciPy website strongly urges using a pre-built installation, and I concur with this advice.\n", "\n", "I use the Anaconda distribution from Continuum Analytics. This is an excellent package that combines all of the packages listed above, plus many others in one distribution. Installation is very straightforward, and it can be done alongside other Python installation you might already have on your machine. It is free to use, and Continuum Analytics will always ensure that the latest releases of all it's packages are available and built correctly for your OS. You may download it from here: http://continuum.io/downloads\n", "\n", "I strongly recommend using the latest Python 3 version that they provide; I am developing in Python 3.x, and only sporadically test that everything works in Python 2.7. However, it is my long term goal to support 2.7, and if you wish to either not be bothered with 3.x and are willing to be occasionally frustrated with breaking check ins you may stick with Python 2.7.\n", "\n", "I am still writing the book, so I do not know exactly what versions of each package is required. I do strongly urge you to use IPython 2.0 or later (this version number has nothing to do with Python 2 vs 3, by the way), as it provides many useful features which I will explain later. \n", "\n", "There are other choices for installing the SciPy stack. The SciPy stack provides instructions here: http://scipy.org/install.html" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Installing FilterPy\n", "\n", "FilterPy is a Python library that implements all of the filters used in this book, and quite a few not used by this book. Installation is easy using Pip. Issue the following command from the command prompt.\n", "\n", " pip install filterpy\n", " \n", " \n", "FilterPy is written by me, and the latest development version is always available at github.com/rlabbe/filterpy.\n", " \n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Manual Install of the SciPy stack" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This really isn't easy, and again I advice you to follow the advice of the SciPy website and to use a prepackaged solution. Still, I will give you one example of an install from a fresh operating system. You will have to adapt the instructions to fit your OS and OS version. I will use xubuntu, a linux distribution, because that is what I am most familiar with. I know there are pre-built binaries for Windows (link provided on the SciPy installation web page), and I have no experience with Mac and Python.\n", "\n", "I started by doing a fresh install of xubuntu 14.04 on a virtual machine. At that point there is a version of Python 2.7.6 and 3.4 pre-installed. As discussed above you may use either version; I will give the instructions for version 3.4 both because I prefer version 3 and because it can be slightly more tricky because 2.7 is the default Python that runs in xubuntu. Basically the difference is that you have to append a '3' at the end of commands. `python3` instead of `python`, `pip3` instead of `pip`, and so on.\n", "\n", "First we will install pip with the following command:\n", "\n", " sudo apt-get install python3-pip\n", " \n", " \n", "Now you will need to install the various packages from the Ubuntu repositories. Unfortunately they usually do not contain the latest version, so we will also install the development tools necessary to perform an upgrade, which requires compiling various modules.\n", "\n", "\n", " sudo apt-get install python3-numpy python3-scipy python3-matplotlib\n", " sudo apt-get install libblas-dev liblapack-dev gfortran python3-dev \n", "\n", "\n", "Now you can upgrade the packages. This will take a long time as everything needs to be compiled from source. If you get an error I do not know how to help you!\n", "\n", " sudo pip3 install numpy --upgrade\n", " sudo pip3 install scipy --upgrade\n", "\n", "Now you get to install SymPy. You can download it from github (replace version number with the most recent version):\n", "\n", " wget https://github.com/sympy/sympy/releases/download/sympy-0.7.6/sympy-0.7.6.tar.gz\n", " tar -zxvf sympy-0.7.6.tar.gz\n", "\n", "Now go into the directory you just extracted and run setup. \n", "\n", " sudo python3 setup.py install\n", " \n", " \n", "If all of this went without a hitch you should have a good install. Try the following. From the command line type `ipython3` to launch ipython, then issue the following commands. Each should run with no exceptions.\n", "\n", " import numpy as np\n", " import scipy as sp\n", " import sympy as sym\n", " np.__version__\n", " sp.__version__\n", " sum.__version__\n", " \n", "Now let's make sure plotting works correctly.\n", "\n", " import matplotlib.pyplot as plt\n", " plt.plot([1, 4, 3])\n", " plt.show()\n", " \n", "Now you get to fix IPython so ipython notebook will run. First, I had to uninstall IPython with\n", "\n", " sudo pip3 uninstall ipython\n", " \n", "Then, I reinstalled it with the `[all]` option so that all the required dependencies are installed.\n", "\n", " sudo pip3 install \"ipython3[all]\"\n", " \n", "Now test the installation by typing\n", "\n", " ipython notebook\n", " \n", "If successful, it should launch a browser showing you the IPython home page.\n", "\n", "\n", "That was not fun. It actually goes somewhat smoother in Windows, where you can download pre-built binaries for these packages; however, you are dependent on this being done for you in a timely manner. So, please follow the SciPy advice and use a pre-built distribution! I will not be supporting this manual install process." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Installing/downloading and running the book" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Okay, so now you have the SciPy stack installed, how do you download the book? This is easy as the book is in a github repository. From the command line type the following:\n", "\n", " git clone https://github.com/rlabbe/Kalman-and-Bayesian-Filters-in-Python.git\n", " \n", "Alternatively, browse to https://github.com/rlabbe/Kalman-and-Bayesian-Filters-in-Python and download it via your browser.\n", "\n", "Now, from the command prompt change to the directory that was just created, and then run ipython notebook:\n", "\n", " cd Kalman-and-Bayesian-Filters-in-Python\n", " ipython notebook\n", "\n", "A browser window should launch showing you all of the chapters in the book. Browse to the first chapter by clicking on it, then open the notebook in that subdirectory by clicking on the link." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Using IPython Notebook" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A complete tutorial on IPython Notebook is beyond the scope of this book. Many are available online. In short, Python code is placed in cells. These are prefaced with text like `In [1]:`, and the code itself is in a boxed area. If you press CTRL-ENTER while focus is inside the box the code will run and the results will be displayed below the box. Like this:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10.2\n" ] } ], "source": [ "print(3+7.2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you have this open in ipython notebook now, go ahead and modify that code by changing the expression inside the print statement and pressing CTRL+ENTER. The output should be changed to reflect what you typed in the code cell." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## SymPy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "SymPy is a Python package for performing symbolic mathematics. The full scope of its abilities are beyond this book, but it can perform algebra, integrate and differentiate equations, find solutions to differential equations, and much more. For example, we use use to to compute the Jacobian of matrices and the expected value integral computations.\n", "\n", "First, a simple example. We will import SymPy, initialize its pretty print functionality (which will print equations using LaTeX). We will then declare a symbol for Numpy to use." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/latex": [ "$$\\phi$$" ], "text/plain": [ "\\phi" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import sympy\n", "sympy.init_printing(use_latex='mathjax')\n", "\n", "phi, x = sympy.symbols('\\phi, x')\n", "phi" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice how we use a latex expression for the symbol `phi`. This is not necessary, but if you do it will render as LaTeX when output. Now let's do some math. What is the derivative of $\\sqrt{\\phi}$?" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/latex": [ "$$\\frac{1}{2 \\sqrt{\\phi}}$$" ], "text/plain": [ " 1 \n", "───────\n", " ___\n", "2⋅╲╱ φ " ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sympy.diff('sqrt(phi)')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can factor equations" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/latex": [ "$$\\left(\\phi - 1\\right) \\left(\\phi^{2} + 1\\right)$$" ], "text/plain": [ " ⎛ 2 ⎞\n", "(\\phi - 1)⋅⎝\\phi + 1⎠" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sympy.factor(phi**3 -phi**2 + phi - 1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "and we can expand them." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/latex": [ "$$\\phi^{2} - 3 \\phi - 4$$" ], "text/plain": [ " 2 \n", "\\phi - 3⋅\\phi - 4" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "((phi+1)*(phi-4)).expand()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can find the value of an equation by substituting in a value for a variable" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/latex": [ "$$8$$" ], "text/plain": [ "8" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "w =x**2 -3*x +4\n", "w.subs(x,4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also use strings for equations that use symbols that you have not defined" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/latex": [ "$$2 t + 2$$" ], "text/plain": [ "2⋅t + 2" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = sympy.expand('(t+1)*2')\n", "x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let's use SymPy to compute the Jacobian of a matrix. Let us have a function\n", "\n", "$$h=\\sqrt{(x^2 + z^2)}$$\n", "\n", "for which we want to find the Jacobian with respect to x, y, and z." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}\\frac{x}{\\sqrt{x^{2} + z^{2}}} & 0 & \\frac{z}{\\sqrt{x^{2} + z^{2}}}\\end{matrix}\\right]$$" ], "text/plain": [ "⎡ x z ⎤\n", "⎢──────────── 0 ────────────⎥\n", "⎢ _________ _________⎥\n", "⎢ ╱ 2 2 ╱ 2 2 ⎥\n", "⎣╲╱ x + z ╲╱ x + z ⎦" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x, y, z = sympy.symbols('x y z')\n", "\n", "H = sympy.Matrix([sympy.sqrt(x**2 + z**2)])\n", "\n", "state = sympy.Matrix([x, y, z])\n", "H.jacobian(state)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let's compute the discrete process noise matrix $\\mathbf{Q}_k$ given the continuous process noise matrix \n", "$$\\mathbf{Q} = \\Phi_s \\begin{bmatrix}0&0&0\\\\0&0&0\\\\0&0&1\\end{bmatrix}$$\n", "\n", "and the equation\n", "\n", "$$\\mathbf{Q} = \\int_0^{\\Delta t} \\Phi(t)\\mathbf{Q}\\Phi^T(t) dt$$\n", "\n", "where \n", "$$\\Phi(t) = \\begin{bmatrix}1 & \\Delta t & {\\Delta t}^2/2 \\\\ 0 & 1 & \\Delta t\\\\ 0& 0& 1\\end{bmatrix}$$" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/latex": [ "$$\\left[\\begin{matrix}\\frac{\\Delta{t}^{5}}{20} & \\frac{\\Delta{t}^{4}}{8} & \\frac{\\Delta{t}^{3}}{6}\\\\\\frac{\\Delta{t}^{4}}{8} & \\frac{\\Delta{t}^{3}}{3} & \\frac{\\Delta{t}^{2}}{2}\\\\\\frac{\\Delta{t}^{3}}{6} & \\frac{\\Delta{t}^{2}}{2} & \\Delta{t}\\end{matrix}\\right]$$" ], "text/plain": [ "⎡ 5 4 3⎤\n", "⎢\\Delta{t} \\Delta{t} \\Delta{t} ⎥\n", "⎢────────── ────────── ──────────⎥\n", "⎢ 20 8 6 ⎥\n", "⎢ ⎥\n", "⎢ 4 3 2⎥\n", "⎢\\Delta{t} \\Delta{t} \\Delta{t} ⎥\n", "⎢────────── ────────── ──────────⎥\n", "⎢ 8 3 2 ⎥\n", "⎢ ⎥\n", "⎢ 3 2 ⎥\n", "⎢\\Delta{t} \\Delta{t} ⎥\n", "⎢────────── ────────── \\Delta{t} ⎥\n", "⎣ 6 2 ⎦" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dt = sympy.symbols('\\Delta{t}')\n", "F_k = sympy.Matrix([[1, dt, dt**2/2],\n", " [0, 1, dt],\n", " [0, 0, 1]])\n", "Q = sympy.Matrix([[0,0,0],\n", " [0,0,0],\n", " [0,0,1]])\n", "\n", "sympy.integrate(F_k*Q*F_k.T,(dt, 0, dt))" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.4.3" } }, "nbformat": 4, "nbformat_minor": 0 }