Packages

An implementation of the Kalman Filter in Elixir.

Current section

Files

Jump to
kalman lib kalman.ex
Raw

lib/kalman.ex

defmodule Kalman do
@moduledoc """
Kalman Filter implemented in Elixir.
"""
# A = 1 # No process innovation
# B = 0 # No control input
# C = 1 # Measurement Dynamics
# Q = 0.005 # Process covariance
# R = 1 # Measurement covariance
# x = -50 # Initial estimate
# P = 1 # Initial covariance
# Process dynamics
defstruct [
:a,
# Control dynamics
:b,
# Measurement dynamics
:c,
# Current state estimate
:x,
# Current probability of state estimate
:p,
# Process covariance
:q,
# Measurement covariance
:r
]
def new(keywords \\ []) when is_list(keywords) do
state = make_default()
Enum.reduce(keywords, state, fn {k, v}, state -> Map.replace!(state, k, v) end)
end
def make_default(a \\ 1.0, b \\ 0.0, c \\ 1.0, x \\ 10.0, p \\ 1.0, q \\ 0.005, r \\ 1.0) do
%__MODULE__{a: a, b: b, c: c, x: x, p: p, q: q, r: r}
end
def step(control_input, measurement, state = %__MODULE__{}) do
# Prediction step
predicted_state_estimate = state.a * state.x + state.b * control_input
predicted_prob_estimate = state.a * state.p * state.a + state.q
# Observation step
innovation = measurement - state.c * predicted_state_estimate
innovation_covariance = state.c * predicted_prob_estimate * state.c + state.r
# Update step
kalman_gain = predicted_prob_estimate * state.c * 1 / innovation_covariance
new_x = predicted_state_estimate + kalman_gain * innovation
# eye(n) = nxn identity matrix.
new_p = (1 - kalman_gain * state.c) * predicted_prob_estimate
%__MODULE__{state | x: new_x, p: new_p}
end
def estimate(%__MODULE__{x: x}), do: x
end