CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

| Download
Project: test
Views: 91872
1
# -*- coding: utf-8 -*-
2
"""
3
Created on Mon Jun 1 18:13:23 2015
4
5
@author: rlabbe
6
"""
7
8
from filterpy.common import plot_covariance_ellipse
9
from filterpy.kalman import UnscentedKalmanFilter as UKF
10
from filterpy.kalman import MerweScaledSigmaPoints, JulierSigmaPoints
11
from math import tan, sin, cos, sqrt, atan2, radians, sqrt
12
import matplotlib.pyplot as plt
13
from numpy import array
14
import numpy as np
15
from numpy.random import randn, seed
16
17
18
19
def normalize_angle(x):
20
x = x % (2 * np.pi) # force in range [0, 2 pi)
21
if x > np.pi: # move to [-pi, pi]
22
x -= 2 * np.pi
23
return x
24
25
26
def residual_h(aa, bb):
27
y = aa - bb
28
y[1] = normalize_angle(y[1])
29
return y
30
31
32
def residual_x(a, b):
33
y = a - b
34
y[2] = normalize_angle(y[2])
35
return y
36
37
38
def move(x, u, dt, wheelbase):
39
h = x[2]
40
v = u[0]
41
steering_angle = u[1]
42
43
dist = v*dt
44
45
if abs(steering_angle) > 0.001:
46
b = dist / wheelbase * tan(steering_angle)
47
r = wheelbase / tan(steering_angle) # radius
48
49
sinh = sin(h)
50
sinhb = sin(h + b)
51
cosh = cos(h)
52
coshb = cos(h + b)
53
54
return x + array([-r*sinh + r*sinhb, r*cosh - r*coshb, b])
55
else:
56
return x + array([dist*cos(h), dist*sin(h), 0])
57
58
59
def state_mean(sigmas, Wm):
60
x = np.zeros(3)
61
sum_sin, sum_cos = 0., 0.
62
63
for i in range(len(sigmas)):
64
s = sigmas[i]
65
x[0] += s[0] * Wm[i]
66
x[1] += s[1] * Wm[i]
67
sum_sin += sin(s[2])*Wm[i]
68
sum_cos += cos(s[2])*Wm[i]
69
70
x[2] = atan2(sum_sin, sum_cos)
71
return x
72
73
74
def z_mean(sigmas, Wm):
75
x = np.zeros(2)
76
sum_sin, sum_cos = 0., 0.
77
78
for i in range(len(sigmas)):
79
s = sigmas[i]
80
x[0] += s[0] * Wm[i]
81
sum_sin += sin(s[1])*Wm[i]
82
sum_cos += cos(s[1])*Wm[i]
83
84
x[1] = atan2(sum_sin, sum_cos)
85
return x
86
87
88
sigma_r = .3
89
sigma_h = .01#radians(.5)#np.radians(1)
90
#sigma_steer = radians(10)
91
dt = 0.1
92
wheelbase = 0.5
93
94
m = array([[5., 10], [10, 5], [15, 15], [20, 5], [0, 30], [50, 30], [40, 10]])
95
#m = array([[5, 10], [10, 5], [15, 15], [20, 5],[5,5], [8, 8.4]])#, [0, 30], [50, 30], [40, 10]])
96
m = array([[5, 10], [10, 5]])#, [0, 30], [50, 30], [40, 10]])
97
98
99
def fx(x, dt, u):
100
return move(x, u, dt, wheelbase)
101
102
103
def Hx(x, landmark):
104
""" takes a state variable and returns the measurement that would
105
correspond to that state.
106
"""
107
px, py = landmark
108
dist = sqrt((px - x[0])**2 + (py - x[1])**2)
109
angle = atan2(py - x[1], px - x[0])
110
return array([dist, normalize_angle(angle - x[2])])
111
112
113
points = MerweScaledSigmaPoints(n=3, alpha=.1, beta=2, kappa=0)
114
#points = JulierSigmaPoints(n=3, kappa=3)
115
ukf= UKF(dim_x=3, dim_z=2, fx=fx, hx=Hx, dt=dt, points=points,
116
x_mean_fn=state_mean, z_mean_fn=z_mean,
117
residual_x=residual_x, residual_z=residual_h)
118
ukf.x = array([2, 6, .3])
119
ukf.P = np.diag([.1, .1, .2])
120
ukf.R = np.diag([sigma_r**2, sigma_h**2])
121
ukf.Q = None#np.eye(3)*.00000
122
123
124
u = array([1.1, 0.])
125
126
xp = ukf.x.copy()
127
128
129
plt.cla()
130
plt.scatter(m[:, 0], m[:, 1])
131
132
cmds = [[v, .0] for v in np.linspace(0.001, 1.1, 30)]
133
cmds.extend([cmds[-1]]*50)
134
135
v = cmds[-1][0]
136
cmds.extend([[v, a] for a in np.linspace(0, np.radians(2), 15)])
137
cmds.extend([cmds[-1]]*100)
138
139
cmds.extend([[v, a] for a in np.linspace(np.radians(2), -np.radians(2), 15)])
140
cmds.extend([cmds[-1]]*200)
141
142
cmds.extend([[v, a] for a in np.linspace(-np.radians(2), 0, 15)])
143
cmds.extend([cmds[-1]]*150)
144
145
#cmds.extend([[v, a] for a in np.linspace(0, -np.radians(1), 25)])
146
147
148
149
seed(12)
150
cmds = np.array(cmds)
151
152
cindex = 0
153
u = cmds[0]
154
155
track = []
156
157
while cindex < len(cmds):
158
u = cmds[cindex]
159
xp = move(xp, u, dt, wheelbase) # simulate robot
160
track.append(xp)
161
162
ukf.predict(fx_args=u)
163
164
if cindex % 20 == 30:
165
plot_covariance_ellipse((ukf.x[0], ukf.x[1]), ukf.P[0:2, 0:2], std=18,
166
facecolor='b', alpha=0.58)
167
168
#print(cindex, ukf.P.diagonal())
169
print(xp)
170
for lmark in m:
171
172
d = sqrt((lmark[0] - xp[0])**2 + (lmark[1] - xp[1])**2) + randn()*sigma_r
173
bearing = atan2(lmark[1] - xp[1], lmark[0] - xp[0])
174
a = normalize_angle(bearing - xp[2] + randn()*sigma_h)
175
z = np.array([d, a])
176
177
if cindex % 20 == 0:
178
plt.plot([lmark[0], lmark[0] - d*cos(a+xp[2])], [lmark[1], lmark[1]-d*sin(a+xp[2])], color='r')
179
180
ukf.update(z, hx_args=(lmark,))
181
print(ukf.P)
182
print()
183
184
if cindex % 20 == 0:
185
plot_covariance_ellipse((ukf.x[0], ukf.x[1]), ukf.P[0:2, 0:2], std=15,
186
facecolor='g', alpha=0.99)
187
cindex += 1
188
189
190
track = np.array(track)
191
plt.plot(track[:, 0], track[:,1], color='k')
192
193
plt.axis('equal')
194
plt.title("UKF Robot localization")
195
plt.show()
196
print(ukf.P.diagonal())
197
198