Path: blob/master/experiments/ekfloc.py
1700 views
# -*- coding: utf-8 -*-1"""2Created on Sun May 24 08:39:36 201534@author: Roger5"""67#x = x x' y y' theta89from math import cos, sin, sqrt, atan210import numpy as np11from numpy import array, dot12from numpy.linalg import pinv131415def print_x(x):16print(x[0, 0], x[1, 0], np.degrees(x[2, 0]))171819def control_update(x, u, dt):20""" x is [x, y, hdg], u is [vel, omega] """2122v = u[0]23w = u[1]24if w == 0:25# approximate straight line with huge radius26w = 1.e-3027r = v/w # radius282930return x + np.array([[-r*sin(x[2]) + r*sin(x[2] + w*dt)],31[ r*cos(x[2]) - r*cos(x[2] + w*dt)],32[w*dt]])333435a1 = 0.00136a2 = 0.00137a3 = 0.00138a4 = 0.0013940sigma_r = 0.141sigma_h = a_error = np.radians(1)42sigma_s = 0.000014344def normalize_angle(x, index):45if x[index] > np.pi:46x[index] -= 2*np.pi47if x[index] < -np.pi:48x[index] = 2*np.pi495051def ekfloc_predict(x, P, u, dt):5253h = x[2]54v = u[0]55w = u[1]5657if w == 0:58# approximate straight line with huge radius59w = 1.e-3060r = v/w # radius6162sinh = sin(h)63sinhwdt = sin(h + w*dt)64cosh = cos(h)65coshwdt = cos(h + w*dt)6667G = array(68[[1, 0, -r*cosh + r*coshwdt],69[0, 1, -r*sinh + r*sinhwdt],70[0, 0, 1]])7172V = array(73[[(-sinh + sinhwdt)/w, v*(sin(h)-sinhwdt)/(w**2) + v*coshwdt*dt/w],74[(cosh - coshwdt)/w, -v*(cosh-coshwdt)/(w**2) + v*sinhwdt*dt/w],75[0, dt]])767778# covariance of motion noise in control space79M = array([[a1*v**2 + a2*w**2, 0],80[0, a3*v**2 + a4*w**2]])81828384x = x + array([[-r*sinh + r*sinhwdt],85[r*cosh - r*coshwdt],86[w*dt]])8788P = dot(G, P).dot(G.T) + dot(V, M).dot(V.T)8990return x, P9192def ekfloc(x, P, u, zs, c, m, dt):9394h = x[2]95v = u[0]96w = u[1]9798if w == 0:99# approximate straight line with huge radius100w = 1.e-30101r = v/w # radius102103sinh = sin(h)104sinhwdt = sin(h + w*dt)105cosh = cos(h)106coshwdt = cos(h + w*dt)107108F = array(109[[1, 0, -r*cosh + r*coshwdt],110[0, 1, -r*sinh + r*sinhwdt],111[0, 0, 1]])112113V = array(114[[(-sinh + sinhwdt)/w, v*(sin(h)-sinhwdt)/(w**2) + v*coshwdt*dt/w],115[(cosh - coshwdt)/w, -v*(cosh-coshwdt)/(w**2) + v*sinhwdt*dt/w],116[0, dt]])117118119# covariance of motion noise in control space120M = array([[a1*v**2 + a2*w**2, 0],121[0, a3*v**2 + a4*w**2]])122123124x = x + array([[-r*sinh + r*sinhwdt],125[r*cosh - r*coshwdt],126[w*dt]])127128P = dot(F, P).dot(F.T) + dot(V, M).dot(V.T)129130131R = np.diag([sigma_r**2, sigma_h**2, sigma_s**2])132133for i, z in enumerate(zs):134j = c[i]135136q = (m[j][0] - x[0, 0])**2 + (m[j][1] - x[1, 0])**2137138z_est = array([sqrt(q),139atan2(m[j][1] - x[1, 0], m[j][0] - x[0, 0]) - x[2, 0],1400])141142143H = array(144[[-(m[j, 0] - x[0, 0]) / sqrt(q), -(m[j, 1] - x[1, 0]) / sqrt(q), 0],145[ (m[j, 1] - x[1, 0]) / q, -(m[j, 0] - x[0, 0]) / q, -1],146[0, 0, 0]])147148149150S = dot(H, P).dot(H.T) + R151152#print('S', S)153K = dot(P, H.T).dot(pinv(S))154y = z - z_est155normalize_angle(y, 1)156y = array([y]).T157#print('y', y)158159x = x + dot(K, y)160I = np.eye(P.shape[0])161I_KH = I - dot(K, H)162#print('i', I_KH)163164P = dot(I_KH, P).dot(I_KH.T) + dot(K, R).dot(K.T)165166return x, P167168169170def ekfloc2(x, P, u, zs, c, m, dt):171172h = x[2]173v = u[0]174w = u[1]175176if w == 0:177# approximate straight line with huge radius178w = 1.e-30179r = v/w # radius180181sinh = sin(h)182sinhwdt = sin(h + w*dt)183cosh = cos(h)184coshwdt = cos(h + w*dt)185186F = array(187[[1, 0, -r*cosh + r*coshwdt],188[0, 1, -r*sinh + r*sinhwdt],189[0, 0, 1]])190191V = array(192[[(-sinh + sinhwdt)/w, v*(sin(h)-sinhwdt)/(w**2) + v*coshwdt*dt/w],193[(cosh - coshwdt)/w, -v*(cosh-coshwdt)/(w**2) + v*sinhwdt*dt/w],194[0, dt]])195196197# covariance of motion noise in control space198M = array([[a1*v**2 + a2*w**2, 0],199[0, a3*v**2 + a4*w**2]])200201202x = x + array([[-r*sinh + r*sinhwdt],203[r*cosh - r*coshwdt],204[w*dt]])205206207P = dot(F, P).dot(F.T) + dot(V, M).dot(V.T)208209210211R = np.diag([sigma_r**2, sigma_h**2])212213for i, z in enumerate(zs):214j = c[i]215216q = (m[j][0] - x[0, 0])**2 + (m[j][1] - x[1, 0])**2217218z_est = array([sqrt(q),219atan2(m[j][1] - x[1, 0], m[j][0] - x[0, 0]) - x[2, 0]])220221H = array(222[[-(m[j, 0] - x[0, 0]) / sqrt(q), -(m[j, 1] - x[1, 0]) / sqrt(q), 0],223[ (m[j, 1] - x[1, 0]) / q, -(m[j, 0] - x[0, 0]) / q, -1]])224225226S = dot(H, P).dot(H.T) + R227228#print('S', S)229K = dot(P, H.T).dot(pinv(S))230y = z - z_est231normalize_angle(y, 1)232y = array([y]).T233#print('y', y)234235x = x + dot(K, y)236print('x', x)237I = np.eye(P.shape[0])238I_KH = I - dot(K, H)239240P = dot(I_KH, P).dot(I_KH.T) + dot(K, R).dot(K.T)241242return x, P243244m = array([[5, 5],245[7,6],246[4, 8]])247248x = array([[2, 6, .3]]).T249u = array([.5, .01])250P = np.diag([1., 1., 1.])251c = [0, 1, 2]252253254255import matplotlib.pyplot as plt256from numpy.random import randn257from filterpy.common import plot_covariance_ellipse258from filterpy.kalman import KalmanFilter259plt.figure()260plt.plot(m[:, 0], m[:, 1], 'o')261plt.plot(x[0], x[1], 'x', color='b', ms=20)262263xp = x.copy()264dt = 0.1265np.random.seed(1234)266267for i in range(1000):268xp, _ = ekfloc_predict(xp, P, u, dt)269plt.plot(xp[0], xp[1], 'x', color='g', ms=20)270271if i % 10 == 0:272zs = []273274for lmark in m:275d = sqrt((lmark[0] - xp[0, 0])**2 + (lmark[1] - xp[1, 0])**2) + randn()*sigma_r276a = atan2(lmark[1] - xp[1, 0], lmark[0] - xp[0, 0]) - xp[2, 0] + randn()*sigma_h277zs.append(np.array([d, a]))278279x, P = ekfloc2(x, P, u, zs, c, m, dt*10)280281282if P[0,0] < 10000:283plot_covariance_ellipse((x[0,0], x[1,0]), P[0:2, 0:2], std=2,284facecolor='g', alpha=0.3)285286plt.plot(x[0], x[1], 'x', color='r')287288plt.axis('equal')289plt.show()290291292