2014-05-03 04:49:35 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
|
|
Created on Thu May 1 19:48:54 2014
|
|
|
|
|
|
|
|
@author: rlabbe
|
|
|
|
"""
|
2014-05-05 00:33:39 +02:00
|
|
|
|
2014-05-03 04:49:35 +02:00
|
|
|
import math
|
|
|
|
import matplotlib.pyplot as plt
|
|
|
|
import noise
|
2014-05-05 00:33:39 +02:00
|
|
|
import numba
|
2014-05-06 16:48:35 +02:00
|
|
|
import numpy.random as random
|
2014-05-03 04:49:35 +02:00
|
|
|
|
|
|
|
class KalmanFilter1D(object):
|
|
|
|
|
2014-05-05 00:33:39 +02:00
|
|
|
def __init__ (self, x0, var):
|
|
|
|
self.mean = x0
|
|
|
|
self.variance = var
|
2014-05-06 16:48:35 +02:00
|
|
|
|
2014-05-05 00:33:39 +02:00
|
|
|
def estimate(self, z, z_variance):
|
|
|
|
self.mean = (self.variance*z + z_variance*self.mean) / (self.variance + z_variance)
|
|
|
|
self.variance = 1. / (1./self.variance + 1./z_variance)
|
2014-05-03 04:49:35 +02:00
|
|
|
|
2014-05-05 00:33:39 +02:00
|
|
|
def project(self, u, u_variance):
|
|
|
|
self.mean += u
|
|
|
|
self.variance += u_variance
|
2014-05-03 04:49:35 +02:00
|
|
|
|
|
|
|
|
2014-05-05 00:33:39 +02:00
|
|
|
def _fixed_error_kf(measurement_error, motion_error, noise_factor = 1.0):
|
|
|
|
mean = 0
|
2014-05-03 04:49:35 +02:00
|
|
|
sig = 1000
|
2014-05-05 00:33:39 +02:00
|
|
|
measurements = [x for x in range(100)]
|
|
|
|
f = KalmanFilter1D (mean,sig)
|
2014-05-03 04:49:35 +02:00
|
|
|
|
|
|
|
ys = []
|
|
|
|
errs = []
|
|
|
|
xs = []
|
|
|
|
|
|
|
|
for i in range(len(measurements)):
|
|
|
|
r = noise.white_noise (noise_factor)
|
2014-05-05 00:33:39 +02:00
|
|
|
z = measurements[i] + r
|
|
|
|
f.estimate (z, measurement_error)
|
2014-05-03 04:49:35 +02:00
|
|
|
|
2014-05-05 00:33:39 +02:00
|
|
|
xs.append(z)
|
|
|
|
ys.append(f.mean)
|
|
|
|
errs.append (f.variance)
|
2014-05-03 04:49:35 +02:00
|
|
|
|
2014-05-05 00:33:39 +02:00
|
|
|
f.project (1, motion_error)
|
2014-05-03 04:49:35 +02:00
|
|
|
|
|
|
|
plt.clf()
|
|
|
|
|
|
|
|
p1, = plt.plot (measurements, 'r')
|
|
|
|
p2, = plt.plot (xs,'g')
|
|
|
|
p3, = plt.plot (ys, 'b')
|
|
|
|
plt.legend ([p1,p2,p3],['actual', 'measurement', 'filter'], 2)
|
|
|
|
#plt.errorbar (x=range(len(ys)), color='b', y=ys, yerr=errs)
|
|
|
|
plt.show()
|
|
|
|
|
2014-05-05 00:33:39 +02:00
|
|
|
def _varying_error_kf(noise_factor=1.0):
|
2014-05-03 04:49:35 +02:00
|
|
|
motion_sig = 2.
|
2014-05-05 00:33:39 +02:00
|
|
|
mean = 0
|
2014-05-03 04:49:35 +02:00
|
|
|
sig = 1000
|
|
|
|
|
2014-05-05 00:33:39 +02:00
|
|
|
measurements = [x for x in range(100)]
|
2014-05-03 04:49:35 +02:00
|
|
|
|
2014-05-05 00:33:39 +02:00
|
|
|
f = KalmanFilter1D (mean,sig)
|
2014-05-03 04:49:35 +02:00
|
|
|
ys = []
|
|
|
|
errs = []
|
|
|
|
xs = []
|
|
|
|
|
|
|
|
for i in range(len(measurements)):
|
|
|
|
r = random.randn() * noise_factor
|
|
|
|
m = measurements[i] + r
|
2014-05-05 00:33:39 +02:00
|
|
|
|
|
|
|
f.estimate (m, abs(r*10))
|
2014-05-03 04:49:35 +02:00
|
|
|
xs.append(m)
|
2014-05-05 00:33:39 +02:00
|
|
|
ys.append(f.mean)
|
|
|
|
errs.append (f.variance)
|
2014-05-03 04:49:35 +02:00
|
|
|
|
2014-05-05 00:33:39 +02:00
|
|
|
f.project (1.0, motion_sig)
|
2014-05-03 04:49:35 +02:00
|
|
|
|
|
|
|
plt.clf()
|
|
|
|
plt.plot (measurements, 'r')
|
|
|
|
plt.plot (xs,'g')
|
|
|
|
plt.errorbar (x=range(len(ys)), color='b', y=ys, yerr=errs)
|
|
|
|
plt.show()
|
|
|
|
|
|
|
|
|
2014-05-05 00:33:39 +02:00
|
|
|
|
|
|
|
def _test_sin ():
|
2014-05-03 04:49:35 +02:00
|
|
|
sensor_error = 1
|
|
|
|
movement = .1
|
|
|
|
movement_error = .1
|
2014-05-05 00:33:39 +02:00
|
|
|
pos = (1,500)
|
2014-05-03 04:49:35 +02:00
|
|
|
|
|
|
|
zs = []
|
|
|
|
ps = []
|
2014-05-05 00:33:39 +02:00
|
|
|
filter_ = KalmanFilter1D(pos[0],pos[1])
|
|
|
|
m_1 = filter_.mean
|
2014-05-03 04:49:35 +02:00
|
|
|
|
|
|
|
for i in range(300):
|
2014-05-05 00:33:39 +02:00
|
|
|
filter_.project(movement, movement_error)
|
2014-05-03 04:49:35 +02:00
|
|
|
|
|
|
|
Z = math.sin(i/12.) + math.sqrt(abs(noise.white_noise(.02)))
|
2014-05-05 00:33:39 +02:00
|
|
|
movement = filter_.mean - m_1
|
|
|
|
m_1 = filter_.mean
|
2014-05-03 04:49:35 +02:00
|
|
|
|
|
|
|
zs.append(Z)
|
|
|
|
|
2014-05-05 00:33:39 +02:00
|
|
|
filter_.estimate (Z, sensor_error)
|
|
|
|
ps.append(filter_.mean)
|
2014-05-03 04:49:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
p1, = plt.plot(zs,c='r', linestyle='dashed')
|
|
|
|
p2, = plt.plot(ps, c='b')
|
|
|
|
plt.legend([p1,p2], ['measurement', 'filter'], 2)
|
|
|
|
plt.show()
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
2014-05-05 00:33:39 +02:00
|
|
|
if 0:
|
2014-05-03 04:49:35 +02:00
|
|
|
# use same seed to get repeatable results
|
|
|
|
random.seed(10)
|
|
|
|
|
2014-05-05 00:33:39 +02:00
|
|
|
if 1:
|
|
|
|
plt.figure()
|
|
|
|
_varying_error_kf ()
|
|
|
|
if 1:
|
|
|
|
plt.figure()
|
|
|
|
_fixed_error_kf(measurement_error=1.,
|
|
|
|
motion_error=.1,
|
|
|
|
noise_factor=50)
|
|
|
|
|
|
|
|
if 1:
|
|
|
|
plt.figure()
|
2014-05-06 16:48:35 +02:00
|
|
|
_test_sin()
|