FilterEx.Kalman (filter_ex v0.2.4)

Kalman filters in pure Elixir with Nx. Supports adaptive feedback to increase responsiveness to external pertubations in the signal.

Examples

Generate example data which jumps up midway from 20 to 30.

iex> %{random_data: random_data} = FilterExTest.generate_data(3)
...> random_data
[20.237325241821775, 19.917010488673977, 20.11041356431258, 29.95666616025292, 30.099203428410778, 30.079518640113378]

Create a Kalman filter with adaptive gain.

iex> %{random_data: random_data} = FilterExTest.generate_data(3)
...> kalman = FilterEx.Kalman.new(dim_x: 1, dim_z: 1, dim_u: 1)
...> kalman = kalman |> FilterEx.Kalman.set(
...>  x: 20.0,       # initial state (location and velocity)
...>  fF: 1.0,    # state transition matrix
...>  hH: 1.0,    # Measurement function
...>  rR: 1.0,                       # state uncertainty
...>  qQ: 1.0/10.0                  # process uncertainty
...> )
...> kalman = kalman |> Kalman.to_eps_adaptive(
...>   q_scale_factor: 3.1, eps_max: 1.0
...> )
...> {_kalman, %{estimates: estimates}} = kalman |> FilterEx.Kalman.filter(random_data)
...> estimates
[20.124313354492188, 20.044675827026367, 20.06612205505371, 23.02187156677246, 25.700191497802734, 28.752626419067383]

Summary

Functions

Link to this function

adaptive_eps(self, z)

Link to this function

adaptive_stddev(self, z)

Link to this function

estimate!(self, value)

Set the estimate for the Kalman filter.

iex> kalman = FilterEx.Kalman.new(dim_x: 1, dim_z: 1, dim_u: 1)
...> kalman = kalman |> FilterEx.Kalman.estimate!(3.3)
...> kalman |> FilterEx.Kalman.estimate()
Nx.tensor([[3.3]])
Link to this function

filter(self, zz, opts \\ [])

Link to this function

new(opts \\ [])

Parameters

dim_x : int

  Number of state variables for the Kalman filter. For example, if
  you are tracking the position and velocity of an object in two
  dimensions, dim_x would be 4.
  This is used to set the default size of P, Q, and u

dim_z : int

  Number of of measurement inputs. For example, if the sensor
  provides you with position in (x,y), dim_z would be 2.

dim_u : int (optional)

  size of the control input, if it is being used.
  Default value of 0 indicates it is not used.
Link to this function

predict(self, u \\ nil, bB \\ nil, fF \\ nil, qQ \\ nil)

Predict next state (prior) using the Kalman filter state propagation equations.

Parameters

u : np.array, default 0

Optional control vector.

B : np.array(dim_x, dim_u), or None

Optional control transition matrix; a value of None
will cause the filter to use `self.B`.

F : np.array(dim_x, dim_x), or None

Optional state transition matrix; a value of None
will cause the filter to use `self.F`.

Q : np.array(dim_x, dim_x), scalar, or None

Optional process noise matrix; a value of None will cause the
filter to use `self.Q`.
Link to this function

set(self, values)

Link to this function

to_eps_adaptive(self, opts)

Link to this function

to_stddev_adaptive(self, opts)

Link to this function

update(self, z, rR \\ nil, hH \\ nil)

Add a new measurement (z) to the Kalman filter.

If z is None, nothing is computed. However, x_post and P_post are updated with the prior (x_prior, P_prior), and self.z is set to None.

Parameters

z : (dim_z, 1): array_like

  measurement for this update. z can be a scalar if dim_z is 1,
  otherwise it must be convertible to a column vector.

  If you pass in a value of H, z must be a column vector the
  of the correct size.

R : np.array, scalar, or None

  Optionally provide R to override the measurement noise for this
  one call, otherwise  self.R will be used.

H : np.array, or None

  Optionally provide H to override the measurement function for this
  one call, otherwise self.H will be used.