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 Thu May 28 20:23:57 2015
4
5
@author: rlabbe
6
"""
7
8
9
from math import cos, sin, sqrt, atan2, tan
10
import matplotlib.pyplot as plt
11
import numpy as np
12
from numpy import array, dot
13
from numpy.linalg import pinv
14
from numpy.random import randn
15
from filterpy.common import plot_covariance_ellipse
16
from filterpy.kalman import ExtendedKalmanFilter as EKF
17
18
19
def print_x(x):
20
print(x[0, 0], x[1, 0], np.degrees(x[2, 0]))
21
22
23
def normalize_angle(x, index):
24
if x[index] > np.pi:
25
x[index] -= 2*np.pi
26
if x[index] < -np.pi:
27
x[index] = 2*np.pi
28
29
def residual(a,b):
30
y = a - b
31
normalize_angle(y, 1)
32
return y
33
34
35
sigma_r = 0.1
36
sigma_h = np.radians(1)
37
sigma_steer = np.radians(1)
38
39
#only partway through. predict is using old control and movement code. computation of m uses
40
#old u.
41
42
class RobotEKF(EKF):
43
def __init__(self, dt, wheelbase):
44
EKF.__init__(self, 3, 2, 2)
45
self.dt = dt
46
self.wheelbase = wheelbase
47
48
def predict(self, u=0):
49
50
self.x = self.move(self.x, u, self.dt)
51
52
h = self.x[2, 0]
53
v = u[0]
54
steering_angle = u[1]
55
56
dist = v*self.dt
57
58
if abs(steering_angle) < 0.0001:
59
# approximate straight line with huge radius
60
r = 1.e-30
61
b = dist / self.wheelbase * tan(steering_angle)
62
r = self.wheelbase / tan(steering_angle) # radius
63
64
65
sinh = sin(h)
66
sinhb = sin(h + b)
67
cosh = cos(h)
68
coshb = cos(h + b)
69
70
F = array([[1., 0., -r*cosh + r*coshb],
71
[0., 1., -r*sinh + r*sinhb],
72
[0., 0., 1.]])
73
74
w = self.wheelbase
75
76
F = array([[1., 0., (-w*cosh + w*coshb)/tan(steering_angle)],
77
[0., 1., (-w*sinh + w*sinhb)/tan(steering_angle)],
78
[0., 0., 1.]])
79
80
print('F', F)
81
82
V = array(
83
[[-r*sinh + r*sinhb, 0],
84
[r*cosh + r*coshb, 0],
85
[0, 0]])
86
87
88
t2 = tan(steering_angle)**2
89
V = array([[0, w*sinh*(-t2-1)/t2 + w*sinhb*(-t2-1)/t2],
90
[0, w*cosh*(-t2-1)/t2 - w*coshb*(-t2-1)/t2],
91
[0,0]])
92
93
94
t2 = tan(steering_angle)**2
95
96
a = steering_angle
97
d = v*dt
98
it = dt*v*tan(a)/w + h
99
100
101
102
V[0,0] = dt*cos(d/w*tan(a) + h)
103
V[0,1] = (dt*v*(t2+1)*cos(it)/tan(a) -
104
w*sinh*(-t2-1)/t2 +
105
w*(-t2-1)*sin(it)/t2)
106
107
108
print(dt*v*(t2+1)*cos(it)/tan(a))
109
print(w*sinh*(-t2-1)/t2)
110
print(w*(-t2-1)*sin(it)/t2)
111
112
113
114
V[1,0] = dt*sin(it)
115
116
V[1,1] = (d*(t2+1)*sin(it)/tan(a) + w*cosh/t2*(-t2-1) -
117
w*(-t2-1)*cos(it)/t2)
118
119
V[2,0] = dt/w*tan(a)
120
V[2,1] = d/w*(t2+1)
121
122
theta = h
123
124
v01 = (dt*v*(tan(a)**2 + 1)*cos(dt*v*tan(a)/w + theta)/tan(a) -
125
w*(-tan(a)**2 - 1)*sin(theta)/(tan(a)**2) +
126
w*(-tan(a)**2 - 1)*sin(dt*v*tan(a)/w + theta)/(tan(a)**2))
127
128
print(dt*v*(tan(a)**2 + 1)*cos(dt*v*tan(a)/w + theta)/tan(a))
129
print(w*(-tan(a)**2 - 1)*sin(theta)/(tan(a)**2))
130
print(w*(-tan(a)**2 - 1)*sin(dt*v*tan(a)/w + theta)/(tan(a)**2))
131
132
'''v11 = (dt*v*(tan(a)**2 + 1)*sin(dt*v*tan(a)/w + theta)/tan(a) +
133
w*(-tan(a)**2 - 1)*cos(theta)/tan(a)**2 -
134
w*(-tan(a)**2 - 1)*cos(dt*v*tan(a)/w + theta)/tan(a)**2)
135
136
137
print(dt*v*(tan(a)**2 + 1)*sin(dt*v*tan(a)/w + theta)/tan(a))
138
print(w*(-tan(a)**2 - 1)*cos(theta)/tan(a)**2)
139
print(w*(-tan(a)**2 - 1)*cos(dt*v*tan(a)/w + theta)/tan(a)**2)
140
print(v11)
141
print(V[1,1])
142
1/0
143
144
V[1,1] = v11'''
145
146
print(V)
147
148
149
# covariance of motion noise in control space
150
M = array([[0.1*v**2, 0],
151
[0, sigma_steer**2]])
152
153
154
fpf = dot(F, self.P).dot(F.T)
155
Q = dot(V, M).dot(V.T)
156
print('FPF', fpf)
157
print('V', V)
158
print('Q', Q)
159
print()
160
self.P = dot(F, self.P).dot(F.T) + dot(V, M).dot(V.T)
161
162
163
164
def move(self, x, u, dt):
165
h = x[2, 0]
166
v = u[0]
167
steering_angle = u[1]
168
169
dist = v*dt
170
171
if abs(steering_angle) < 0.0001:
172
# approximate straight line with huge radius
173
r = 1.e-30
174
b = dist / self.wheelbase * tan(steering_angle)
175
r = self.wheelbase / tan(steering_angle) # radius
176
177
178
sinh = sin(h)
179
sinhb = sin(h + b)
180
cosh = cos(h)
181
coshb = cos(h + b)
182
183
return x + array([[-r*sinh + r*sinhb],
184
[r*cosh - r*coshb],
185
[b]])
186
187
188
def H_of(x, p):
189
""" compute Jacobian of H matrix where h(x) computes the range and
190
bearing to a landmark for state x """
191
192
px = p[0]
193
py = p[1]
194
hyp = (px - x[0, 0])**2 + (py - x[1, 0])**2
195
dist = np.sqrt(hyp)
196
197
H = array(
198
[[-(px - x[0, 0]) / dist, -(py - x[1, 0]) / dist, 0],
199
[ (py - x[1, 0]) / hyp, -(px - x[0, 0]) / hyp, -1]])
200
return H
201
202
203
def Hx(x, p):
204
""" takes a state variable and returns the measurement that would
205
correspond to that state.
206
"""
207
px = p[0]
208
py = p[1]
209
dist = np.sqrt((px - x[0, 0])**2 + (py - x[1, 0])**2)
210
211
Hx = array([[dist],
212
[atan2(py - x[1, 0], px - x[0, 0]) - x[2, 0]]])
213
return Hx
214
215
dt = 1.0
216
ekf = RobotEKF(dt, wheelbase=0.5)
217
218
#np.random.seed(1234)
219
220
m = array([[5, 10],
221
[10, 5],
222
[15, 15]])
223
224
ekf.x = array([[2, 6, .3]]).T
225
u = array([.5, .01])
226
ekf.P = np.diag([1., 1., 1.])
227
ekf.R = np.diag([sigma_r**2, sigma_h**2])
228
c = [0, 1, 2]
229
230
xp = ekf.x.copy()
231
232
plt.scatter(m[:, 0], m[:, 1])
233
for i in range(300):
234
xp = ekf.move(xp, u, dt/10.) # simulate robot
235
plt.plot(xp[0], xp[1], ',', color='g')
236
237
if i % 10 == 0:
238
239
ekf.predict(u=u)
240
241
plot_covariance_ellipse((ekf.x[0,0], ekf.x[1,0]), ekf.P[0:2, 0:2], std=2,
242
facecolor='b', alpha=0.3)
243
244
for lmark in m:
245
d = sqrt((lmark[0] - xp[0, 0])**2 + (lmark[1] - xp[1, 0])**2) + randn()*sigma_r
246
a = atan2(lmark[1] - xp[1, 0], lmark[0] - xp[0, 0]) - xp[2, 0] + randn()*sigma_h
247
z = np.array([[d], [a]])
248
249
ekf.update(z, HJacobian=H_of, Hx=Hx, residual=residual,
250
args=(lmark), hx_args=(lmark))
251
252
plot_covariance_ellipse((ekf.x[0,0], ekf.x[1,0]), ekf.P[0:2, 0:2], std=10,
253
facecolor='g', alpha=0.3)
254
255
#plt.plot(ekf.x[0], ekf.x[1], 'x', color='r')
256
257
plt.axis('equal')
258
plt.show()
259
260
261