Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
96129 views
1
# -*- coding: utf-8 -*-
2
"""
3
Created on Sun May 24 08:39:36 2015
4
5
@author: Roger
6
"""
7
8
#x = x x' y y' theta
9
10
from math import cos, sin, sqrt, atan2
11
import numpy as np
12
from numpy import array, dot
13
from numpy.linalg import pinv
14
15
16
def print_x(x):
17
print(x[0, 0], x[1, 0], np.degrees(x[2, 0]))
18
19
20
def control_update(x, u, dt):
21
""" x is [x, y, hdg], u is [vel, omega] """
22
23
v = u[0]
24
w = u[1]
25
if w == 0:
26
# approximate straight line with huge radius
27
w = 1.e-30
28
r = v/w # radius
29
30
31
return x + np.array([[-r*sin(x[2]) + r*sin(x[2] + w*dt)],
32
[ r*cos(x[2]) - r*cos(x[2] + w*dt)],
33
[w*dt]])
34
35
36
a1 = 0.001
37
a2 = 0.001
38
a3 = 0.001
39
a4 = 0.001
40
41
sigma_r = 0.1
42
sigma_h = a_error = np.radians(1)
43
sigma_s = 0.00001
44
45
def normalize_angle(x, index):
46
if x[index] > np.pi:
47
x[index] -= 2*np.pi
48
if x[index] < -np.pi:
49
x[index] = 2*np.pi
50
51
52
def ekfloc_predict(x, P, u, dt):
53
54
h = x[2]
55
v = u[0]
56
w = u[1]
57
58
if w == 0:
59
# approximate straight line with huge radius
60
w = 1.e-30
61
r = v/w # radius
62
63
sinh = sin(h)
64
sinhwdt = sin(h + w*dt)
65
cosh = cos(h)
66
coshwdt = cos(h + w*dt)
67
68
G = array(
69
[[1, 0, -r*cosh + r*coshwdt],
70
[0, 1, -r*sinh + r*sinhwdt],
71
[0, 0, 1]])
72
73
V = array(
74
[[(-sinh + sinhwdt)/w, v*(sin(h)-sinhwdt)/(w**2) + v*coshwdt*dt/w],
75
[(cosh - coshwdt)/w, -v*(cosh-coshwdt)/(w**2) + v*sinhwdt*dt/w],
76
[0, dt]])
77
78
79
# covariance of motion noise in control space
80
M = array([[a1*v**2 + a2*w**2, 0],
81
[0, a3*v**2 + a4*w**2]])
82
83
84
85
x = x + array([[-r*sinh + r*sinhwdt],
86
[r*cosh - r*coshwdt],
87
[w*dt]])
88
89
P = dot(G, P).dot(G.T) + dot(V, M).dot(V.T)
90
91
return x, P
92
93
def ekfloc(x, P, u, zs, c, m, dt):
94
95
h = x[2]
96
v = u[0]
97
w = u[1]
98
99
if w == 0:
100
# approximate straight line with huge radius
101
w = 1.e-30
102
r = v/w # radius
103
104
sinh = sin(h)
105
sinhwdt = sin(h + w*dt)
106
cosh = cos(h)
107
coshwdt = cos(h + w*dt)
108
109
F = array(
110
[[1, 0, -r*cosh + r*coshwdt],
111
[0, 1, -r*sinh + r*sinhwdt],
112
[0, 0, 1]])
113
114
V = array(
115
[[(-sinh + sinhwdt)/w, v*(sin(h)-sinhwdt)/(w**2) + v*coshwdt*dt/w],
116
[(cosh - coshwdt)/w, -v*(cosh-coshwdt)/(w**2) + v*sinhwdt*dt/w],
117
[0, dt]])
118
119
120
# covariance of motion noise in control space
121
M = array([[a1*v**2 + a2*w**2, 0],
122
[0, a3*v**2 + a4*w**2]])
123
124
125
x = x + array([[-r*sinh + r*sinhwdt],
126
[r*cosh - r*coshwdt],
127
[w*dt]])
128
129
P = dot(F, P).dot(F.T) + dot(V, M).dot(V.T)
130
131
132
R = np.diag([sigma_r**2, sigma_h**2, sigma_s**2])
133
134
for i, z in enumerate(zs):
135
j = c[i]
136
137
q = (m[j][0] - x[0, 0])**2 + (m[j][1] - x[1, 0])**2
138
139
z_est = array([sqrt(q),
140
atan2(m[j][1] - x[1, 0], m[j][0] - x[0, 0]) - x[2, 0],
141
0])
142
143
144
H = array(
145
[[-(m[j, 0] - x[0, 0]) / sqrt(q), -(m[j, 1] - x[1, 0]) / sqrt(q), 0],
146
[ (m[j, 1] - x[1, 0]) / q, -(m[j, 0] - x[0, 0]) / q, -1],
147
[0, 0, 0]])
148
149
150
151
S = dot(H, P).dot(H.T) + R
152
153
#print('S', S)
154
K = dot(P, H.T).dot(pinv(S))
155
y = z - z_est
156
normalize_angle(y, 1)
157
y = array([y]).T
158
#print('y', y)
159
160
x = x + dot(K, y)
161
I = np.eye(P.shape[0])
162
I_KH = I - dot(K, H)
163
#print('i', I_KH)
164
165
P = dot(I_KH, P).dot(I_KH.T) + dot(K, R).dot(K.T)
166
167
return x, P
168
169
170
171
def ekfloc2(x, P, u, zs, c, m, dt):
172
173
h = x[2]
174
v = u[0]
175
w = u[1]
176
177
if w == 0:
178
# approximate straight line with huge radius
179
w = 1.e-30
180
r = v/w # radius
181
182
sinh = sin(h)
183
sinhwdt = sin(h + w*dt)
184
cosh = cos(h)
185
coshwdt = cos(h + w*dt)
186
187
F = array(
188
[[1, 0, -r*cosh + r*coshwdt],
189
[0, 1, -r*sinh + r*sinhwdt],
190
[0, 0, 1]])
191
192
V = array(
193
[[(-sinh + sinhwdt)/w, v*(sin(h)-sinhwdt)/(w**2) + v*coshwdt*dt/w],
194
[(cosh - coshwdt)/w, -v*(cosh-coshwdt)/(w**2) + v*sinhwdt*dt/w],
195
[0, dt]])
196
197
198
# covariance of motion noise in control space
199
M = array([[a1*v**2 + a2*w**2, 0],
200
[0, a3*v**2 + a4*w**2]])
201
202
203
x = x + array([[-r*sinh + r*sinhwdt],
204
[r*cosh - r*coshwdt],
205
[w*dt]])
206
207
208
P = dot(F, P).dot(F.T) + dot(V, M).dot(V.T)
209
210
211
212
R = np.diag([sigma_r**2, sigma_h**2])
213
214
for i, z in enumerate(zs):
215
j = c[i]
216
217
q = (m[j][0] - x[0, 0])**2 + (m[j][1] - x[1, 0])**2
218
219
z_est = array([sqrt(q),
220
atan2(m[j][1] - x[1, 0], m[j][0] - x[0, 0]) - x[2, 0]])
221
222
H = array(
223
[[-(m[j, 0] - x[0, 0]) / sqrt(q), -(m[j, 1] - x[1, 0]) / sqrt(q), 0],
224
[ (m[j, 1] - x[1, 0]) / q, -(m[j, 0] - x[0, 0]) / q, -1]])
225
226
227
S = dot(H, P).dot(H.T) + R
228
229
#print('S', S)
230
K = dot(P, H.T).dot(pinv(S))
231
y = z - z_est
232
normalize_angle(y, 1)
233
y = array([y]).T
234
#print('y', y)
235
236
x = x + dot(K, y)
237
print('x', x)
238
I = np.eye(P.shape[0])
239
I_KH = I - dot(K, H)
240
241
P = dot(I_KH, P).dot(I_KH.T) + dot(K, R).dot(K.T)
242
243
return x, P
244
245
m = array([[5, 5],
246
[7,6],
247
[4, 8]])
248
249
x = array([[2, 6, .3]]).T
250
u = array([.5, .01])
251
P = np.diag([1., 1., 1.])
252
c = [0, 1, 2]
253
254
255
256
import matplotlib.pyplot as plt
257
from numpy.random import randn
258
from filterpy.common import plot_covariance_ellipse
259
from filterpy.kalman import KalmanFilter
260
plt.figure()
261
plt.plot(m[:, 0], m[:, 1], 'o')
262
plt.plot(x[0], x[1], 'x', color='b', ms=20)
263
264
xp = x.copy()
265
dt = 0.1
266
np.random.seed(1234)
267
268
for i in range(1000):
269
xp, _ = ekfloc_predict(xp, P, u, dt)
270
plt.plot(xp[0], xp[1], 'x', color='g', ms=20)
271
272
if i % 10 == 0:
273
zs = []
274
275
for lmark in m:
276
d = sqrt((lmark[0] - xp[0, 0])**2 + (lmark[1] - xp[1, 0])**2) + randn()*sigma_r
277
a = atan2(lmark[1] - xp[1, 0], lmark[0] - xp[0, 0]) - xp[2, 0] + randn()*sigma_h
278
zs.append(np.array([d, a]))
279
280
x, P = ekfloc2(x, P, u, zs, c, m, dt*10)
281
282
283
if P[0,0] < 10000:
284
plot_covariance_ellipse((x[0,0], x[1,0]), P[0:2, 0:2], std=2,
285
facecolor='g', alpha=0.3)
286
287
plt.plot(x[0], x[1], 'x', color='r')
288
289
plt.axis('equal')
290
plt.show()
291
292