Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
Project: test
Views: 91872# -*- coding: utf-8 -*-1"""2Created on Mon May 25 18:18:54 201534@author: rlabbe5"""678from math import cos, sin, sqrt, atan29import matplotlib.pyplot as plt10import numpy as np11from numpy import array, dot12from numpy.linalg import pinv13from numpy.random import randn14from filterpy.common import plot_covariance_ellipse15from filterpy.kalman import ExtendedKalmanFilter as EKF161718def print_x(x):19print(x[0, 0], x[1, 0], np.degrees(x[2, 0]))202122def normalize_angle(x, index):23if x[index] > np.pi:24x[index] -= 2*np.pi25if x[index] < -np.pi:26x[index] = 2*np.pi2728def residual(a,b):29y = a - b30normalize_angle(y, 1)31return y323334def control_update(x, u, dt):35""" x is [x, y, hdg], u is [vel, omega] """3637v = u[0]38w = u[1]39if w == 0:40# approximate straight line with huge radius41w = 1.e-3042r = v/w # radius434445return x + np.array([[-r*sin(x[2]) + r*sin(x[2] + w*dt)],46[ r*cos(x[2]) - r*cos(x[2] + w*dt)],47[w*dt]])4849a1 = 0.00150a2 = 0.00151a3 = 0.00152a4 = 0.0015354sigma_r = 0.155sigma_h = a_error = np.radians(1)56sigma_s = 0.000015758def normalize_angle(x, index):59if x[index] > np.pi:60x[index] -= 2*np.pi61if x[index] < -np.pi:62x[index] = 2*np.pi63646566class RobotEKF(EKF):67def __init__(self, dt):68EKF.__init__(self, 3, 2, 2)69self.dt = dt7071def predict_x(self, u):72self.x = self.move(self.x, u, self.dt)737475def move(self, x, u, dt):76h = x[2, 0]77v = u[0]78w = u[1]7980if w == 0:81# approximate straight line with huge radius82w = 1.e-3083r = v/w # radius8485sinh = sin(h)86sinhwdt = sin(h + w*dt)87cosh = cos(h)88coshwdt = cos(h + w*dt)8990return x + array([[-r*sinh + r*sinhwdt],91[r*cosh - r*coshwdt],92[w*dt]])939495def H_of(x, landmark_pos):96""" compute Jacobian of H matrix for state x """9798mx = landmark_pos[0]99my = landmark_pos[1]100q = (mx - x[0, 0])**2 + (my - x[1, 0])**2101102H = array(103[[-(mx - x[0, 0]) / sqrt(q), -(my - x[1, 0]) / sqrt(q), 0],104[ (my - x[1, 0]) / q, -(mx - x[0, 0]) / q, -1]])105return H106107108def Hx(x, landmark_pos):109""" takes a state variable and returns the measurement that would110correspond to that state.111"""112mx = landmark_pos[0]113my = landmark_pos[1]114q = (mx - x[0, 0])**2 + (my - x[1, 0])**2115116Hx = array([[sqrt(q)],117[atan2(my - x[1, 0], mx - x[0, 0]) - x[2, 0]]])118return Hx119120dt = 1.0121ekf = RobotEKF(dt)122123#np.random.seed(1234)124125m = array([[5, 10],126[10, 5],127[15, 15]])128129ekf.x = array([[2, 6, .3]]).T130u = array([.5, .01])131ekf.P = np.diag([1., 1., 1.])132ekf.R = np.diag([sigma_r**2, sigma_h**2])133c = [0, 1, 2]134135xp = ekf.x.copy()136137plt.scatter(m[:, 0], m[:, 1])138for i in range(300):139xp = ekf.move(xp, u, dt/10.) # simulate robot140plt.plot(xp[0], xp[1], ',', color='g')141142if i % 10 == 0:143h = ekf.x[2, 0]144v = u[0]145w = u[1]146147if w == 0:148# approximate straight line with huge radius149w = 1.e-30150r = v/w # radius151152sinh = sin(h)153sinhwdt = sin(h + w*dt)154cosh = cos(h)155coshwdt = cos(h + w*dt)156157ekf.F = array(158[[1, 0, -r*cosh + r*coshwdt],159[0, 1, -r*sinh + r*sinhwdt],160[0, 0, 1]])161162V = array(163[[(-sinh + sinhwdt)/w, v*(sin(h)-sinhwdt)/(w**2) + v*coshwdt*dt/w],164[(cosh - coshwdt)/w, -v*(cosh-coshwdt)/(w**2) + v*sinhwdt*dt/w],165[0, dt]])166167# covariance of motion noise in control space168M = array([[a1*v**2 + a2*w**2, 0],169[0, a3*v**2 + a4*w**2]])170171ekf.Q = dot(V, M).dot(V.T)172173ekf.predict(u=u)174175for lmark in m:176d = sqrt((lmark[0] - xp[0, 0])**2 + (lmark[1] - xp[1, 0])**2) + randn()*sigma_r177a = atan2(lmark[1] - xp[1, 0], lmark[0] - xp[0, 0]) - xp[2, 0] + randn()*sigma_h178z = np.array([[d], [a]])179180ekf.update(z, HJacobian=H_of, Hx=Hx, residual=residual,181args=(lmark), hx_args=(lmark))182183plot_covariance_ellipse((ekf.x[0,0], ekf.x[1,0]), ekf.P[0:2, 0:2], std=10,184facecolor='g', alpha=0.3)185186#plt.plot(ekf.x[0], ekf.x[1], 'x', color='r')187188plt.axis('equal')189plt.show()190191192193