Kalman Filter
Table of Contents
Given $k-1$ data points: $x_1,x_2,\cdots,x_{k-1}$
New data $x_k$ comes in
Recursive
dt = 0.2;
t = 0:dt:10;
m = length(t);
x = 14.4 + 4*randn(m,1);
avg = [];
preAvg = 0;
for k = 1:m
alpha = (k-1)/k;
avg(k) = alpha*preAvg + (1-alpha)*x(k);
preAvg = avg(k);
end
plot(t,x,'r:*')
hold on
plot(t, avg, 'o-')
hold off
legend('measured','Average')
xlabel('Time (sec)','fontsize',8)
ylabel('Volt (sec)','fontsize',8)
Only use the latest $n$ data points
with $n = 30$
load data_files/SonarAlt
X = sonarAlt;
m = length(X);
%% Coded for real-time data steaming
n = 30; % window size
XHAT = [];
Xsaved = [];
xbuf = [];
preAvg = 0;
for k = 1:m
xm = X(k);
if k == 1
xbuf = xm*ones(n+1,1);
preAvg = xm;
end
for i = 1:n
xbuf(i) = xbuf(i+1);
end
xbuf(n+1) = xm;
xhat = preAvg + (xm - xbuf(1))/n;
preAvg = xhat;
XHAT(k) = xhat;
Xsaved(k) = xm;
end
%% plot
dt = 0.02;
t = 0:dt:(m-1)*dt;
plot(t, X, 'r.'); hold on
plot(t, XHAT, 'b','linewidth',1); hold off
xlim([0,10]);
leg = legend('Measured', 'Moving average');
set(leg,'fontsize',6,'location','southeast')
xlabel('Time (sec)','fontsize',8)
ylabel('Volt (sec)','fontsize',8)
with $n = 10$
load data_files/SonarAlt
X = sonarAlt;
m = length(X);
%% it is coded as if data is real-time streamed
n = 10; % window size
XHAT = [];
Xsaved = [];
xbuf = [];
preAvg = 0;
for k = 1:m
xm = X(k);
if k == 1
xbuf = xm*ones(n+1,1);
preAvg = xm;
end
for i = 1:n
xbuf(i) = xbuf(i+1);
end
xbuf(n+1) = xm;
xhat = preAvg + (xm - xbuf(1))/n;
preAvg = xhat;
XHAT(k) = xhat;
Xsaved(k) = xm;
end
%% plot
dt = 0.02;
t = 0:dt:(m-1)*dt;
plot(t, X, 'r.'); hold on
plot(t, XHAT, 'b','linewidth',1); hold off
xlim([0,10]);
leg = legend('Measured', 'Moving average');
set(leg,'fontsize',6,'location','southeast')
xlabel('Time (sec)','fontsize',8)
ylabel('Volt (sec)','fontsize',8)
with $\alpha = 0.9$
load data_files/SonarAlt
X = sonarAlt;
m = length(X);
%% it is coded as if data is real-time streamed
XHAT = [];
Xsaved = [];
prevX = 0;
alpha = 0.9;
for k = 1:m
xm = X(k);
if k == 1
prevX = xm;
end
xhat = alpha*prevX + (1 - alpha)*xm;
prevX = xhat;
XHAT(k) = xhat;
Xsaved(k) = xm;
end
%% plot
dt = 0.02;
t = 0:dt:(m-1)*dt;
plot(t, X, 'r.'); hold on
plot(t, XHAT, 'b','linewidth',1); hold off
xlim([0,10]);
leg = legend('Measured', 'Moving average');
set(leg,'fontsize',6,'location','southeast')
xlabel('Time (sec)','fontsize',8)
ylabel('Volt (sec)','fontsize',8)
with $\alpha = 0.1$
load data_files/SonarAlt
X = sonarAlt;
m = length(X);
%% it is coded as if data is real-time streamed
XHAT = [];
Xsaved = [];
prevX = 0;
alpha = 0.1;
for k = 1:m
xm = X(k);
if k == 1
prevX = xm;
end
xhat = alpha*prevX + (1 - alpha)*xm;
prevX = xhat;
XHAT(k) = xhat;
Xsaved(k) = xm;
end
%% plot
dt = 0.02;
t = 0:dt:(m-1)*dt;
plot(t, X, 'r.'); hold on
plot(t, XHAT, 'b','linewidth',1); hold off
xlim([0,10]);
leg = legend('Measured', 'Moving average');
set(leg,'fontsize',6,'location','southeast')
xlabel('Time (sec)','fontsize',8)
ylabel('Volt (sec)','fontsize',8)
Assumptions
Optimal position estimation $\hat x$
References:
Bayesian filtering: From Kalman filters to particle filters, and beyond by Zhe Chen
System and Measurement Models by Dan Lee
Maximum-A-Posterior Estimation by Dan Lee
Discrete linear dynamical system of motion
Kalman filter has a very nice Bayesian interpretation.
Most other materials use different notations to explain the Kalman filter (by S. Lall).
Suppose $x \sim N(\mu, \Sigma)$, and
Then the conditional pdf of $x_1$ given $x_2 = y$ is Gaussian
Look at the Kalman filter via conditional probability of Gaussian distributions, given a linear system
$\quad \;$ We do not have any more data, we just update our earlier posterior of $x_t$ to give a new posterior of $x_{t+1}$
$\quad \;$ We are just propagating the pmf under the linear dynamics
$\quad \;$ We start with $\hat{x}_{t \mid t-1}$, and use it as the prior for our next measurement of $z_t$
%%javascript
$.getScript('https://kmahelona.github.io/ipython_notebook_goodies/ipython_notebook_toc.js')