1
-
2
1
"""
3
2
4
3
Ensemble Kalman Filter(EnKF) localization sample
10
9
11
10
"""
12
11
13
- import numpy as np
14
12
import math
13
+
15
14
import matplotlib .pyplot as plt
15
+ import numpy as np
16
16
17
17
# Simulation parameter
18
- Qsim = np .diag ([0.2 , np .deg2rad (1.0 )])** 2
19
- Rsim = np .diag ([1.0 , np .deg2rad (30.0 )])** 2
18
+ Q_sim = np .diag ([0.2 , np .deg2rad (1.0 )]) ** 2
19
+ R_sim = np .diag ([1.0 , np .deg2rad (30.0 )]) ** 2
20
20
21
21
DT = 0.1 # time tick [s]
22
22
SIM_TIME = 50.0 # simulation time [s]
30
30
31
31
def calc_input ():
32
32
v = 1.0 # [m/s]
33
- yawrate = 0.1 # [rad/s]
34
- u = np .array ([[v , yawrate ]]).T
33
+ yaw_rate = 0.1 # [rad/s]
34
+ u = np .array ([[v , yaw_rate ]]).T
35
35
return u
36
36
37
37
38
38
def observation (xTrue , xd , u , RFID ):
39
-
40
39
xTrue = motion_model (xTrue , u )
41
40
42
41
z = np .zeros ((0 , 4 ))
@@ -45,18 +44,18 @@ def observation(xTrue, xd, u, RFID):
45
44
46
45
dx = RFID [i , 0 ] - xTrue [0 , 0 ]
47
46
dy = RFID [i , 1 ] - xTrue [1 , 0 ]
48
- d = math .sqrt (dx ** 2 + dy ** 2 )
47
+ d = math .sqrt (dx ** 2 + dy ** 2 )
49
48
angle = pi_2_pi (math .atan2 (dy , dx ) - xTrue [2 , 0 ])
50
49
if d <= MAX_RANGE :
51
- dn = d + np .random .randn () * Qsim [0 , 0 ] # add noise
52
- anglen = angle + np .random .randn () * Qsim [1 , 1 ] # add noise
50
+ dn = d + np .random .randn () * Q_sim [0 , 0 ] ** 0.5 # add noise
51
+ anglen = angle + np .random .randn () * Q_sim [1 , 1 ] ** 0.5 # add noise
53
52
zi = np .array ([dn , anglen , RFID [i , 0 ], RFID [i , 1 ]])
54
53
z = np .vstack ((z , zi ))
55
54
56
55
# add noise to input
57
56
ud = np .array ([[
58
- u [0 , 0 ] + np .random .randn () * Rsim [0 , 0 ],
59
- u [1 , 0 ] + np .random .randn () * Rsim [1 , 1 ]]]).T
57
+ u [0 , 0 ] + np .random .randn () * R_sim [0 , 0 ] ** 0.5 ,
58
+ u [1 , 0 ] + np .random .randn () * R_sim [1 , 1 ] ** 0.5 ]]).T
60
59
61
60
xd = motion_model (xd , ud )
62
61
return xTrue , z , xd , ud
@@ -77,15 +76,13 @@ def motion_model(x, u):
77
76
return x
78
77
79
78
80
- def calc_LM_Pos (x , landmarks ):
81
- landmarks_pos = np .zeros ((2 * landmarks .shape [0 ], 1 ))
79
+ def observe_landmark_position (x , landmarks ):
80
+ landmarks_pos = np .zeros ((2 * landmarks .shape [0 ], 1 ))
82
81
for (i , lm ) in enumerate (landmarks ):
83
- landmarks_pos [2 * i ] = x [0 , 0 ] + lm [0 ] * \
84
- math .cos (x [2 , 0 ] + lm [1 ]) + np .random .randn () * \
85
- Qsim [0 , 0 ]/ np .sqrt (2 )
86
- landmarks_pos [2 * i + 1 ] = x [1 , 0 ] + lm [0 ] * \
87
- math .sin (x [2 , 0 ] + lm [1 ]) + np .random .randn () * \
88
- Qsim [0 , 0 ]/ np .sqrt (2 )
82
+ landmarks_pos [2 * i ] = x [0 , 0 ] + lm [0 ] * math .cos (x [2 , 0 ] + lm [1 ]) + np .random .randn () * Q_sim [
83
+ 0 , 0 ] ** 0.5 / np .sqrt (2 )
84
+ landmarks_pos [2 * i + 1 ] = x [1 , 0 ] + lm [0 ] * math .sin (x [2 , 0 ] + lm [1 ]) + np .random .randn () * Q_sim [
85
+ 0 , 0 ] ** 0.5 / np .sqrt (2 )
89
86
return landmarks_pos
90
87
91
88
@@ -95,25 +92,26 @@ def calc_covariance(xEst, px):
95
92
for i in range (px .shape [1 ]):
96
93
dx = (px [:, i ] - xEst )[0 :3 ]
97
94
cov += dx .dot (dx .T )
95
+ cov /= NP
98
96
99
97
return cov
100
98
101
99
102
- def enkf_localization (px , xEst , PEst , z , u ):
100
+ def enkf_localization (px , z , u ):
103
101
"""
104
102
Localization with Ensemble Kalman filter
105
103
"""
106
- pz = np .zeros ((z .shape [0 ]* 2 , NP )) # Particle store of z
104
+ pz = np .zeros ((z .shape [0 ] * 2 , NP )) # Particle store of z
107
105
for ip in range (NP ):
108
106
x = np .array ([px [:, ip ]]).T
109
107
110
108
# Predict with random input sampling
111
- ud1 = u [0 , 0 ] + np .random .randn () * Rsim [0 , 0 ]
112
- ud2 = u [1 , 0 ] + np .random .randn () * Rsim [1 , 1 ]
109
+ ud1 = u [0 , 0 ] + np .random .randn () * R_sim [0 , 0 ] ** 0.5
110
+ ud2 = u [1 , 0 ] + np .random .randn () * R_sim [1 , 1 ] ** 0.5
113
111
ud = np .array ([[ud1 , ud2 ]]).T
114
112
x = motion_model (x , ud )
115
113
px [:, ip ] = x [:, 0 ]
116
- z_pos = calc_LM_Pos (x , z )
114
+ z_pos = observe_landmark_position (x , z )
117
115
pz [:, ip ] = z_pos [:, 0 ]
118
116
119
117
x_ave = np .mean (px , axis = 1 )
@@ -122,12 +120,12 @@ def enkf_localization(px, xEst, PEst, z, u):
122
120
z_ave = np .mean (pz , axis = 1 )
123
121
z_dif = pz - np .tile (z_ave , (NP , 1 )).T
124
122
125
- U = 1 / (NP - 1 ) * x_dif @ z_dif .T
126
- V = 1 / (NP - 1 ) * z_dif @ z_dif .T
123
+ U = 1 / (NP - 1 ) * x_dif @ z_dif .T
124
+ V = 1 / (NP - 1 ) * z_dif @ z_dif .T
127
125
128
126
K = U @ np .linalg .inv (V ) # Kalman Gain
129
127
130
- z_lm_pos = z [:, [2 , 3 ]].reshape (- 1 ,)
128
+ z_lm_pos = z [:, [2 , 3 ]].reshape (- 1 , )
131
129
132
130
px_hat = px + K @ (np .tile (z_lm_pos , (NP , 1 )).T - pz )
133
131
@@ -139,32 +137,32 @@ def enkf_localization(px, xEst, PEst, z, u):
139
137
140
138
def plot_covariance_ellipse (xEst , PEst ): # pragma: no cover
141
139
Pxy = PEst [0 :2 , 0 :2 ]
142
- eigval , eigvec = np .linalg .eig (Pxy )
140
+ eig_val , eig_vec = np .linalg .eig (Pxy )
143
141
144
- if eigval [0 ] >= eigval [1 ]:
145
- bigind = 0
146
- smallind = 1
142
+ if eig_val [0 ] >= eig_val [1 ]:
143
+ big_ind = 0
144
+ small_ind = 1
147
145
else :
148
- bigind = 1
149
- smallind = 0
146
+ big_ind = 1
147
+ small_ind = 0
150
148
151
149
t = np .arange (0 , 2 * math .pi + 0.1 , 0.1 )
152
150
153
- # eigval[bigind ] or eiqval[smallind ] were occassionally negative numbers extremely
151
+ # eig_val[big_ind ] or eiq_val[small_ind ] were occasionally negative numbers extremely
154
152
# close to 0 (~10^-20), catch these cases and set the respective variable to 0
155
153
try :
156
- a = math .sqrt (eigval [ bigind ])
154
+ a = math .sqrt (eig_val [ big_ind ])
157
155
except ValueError :
158
156
a = 0
159
157
160
158
try :
161
- b = math .sqrt (eigval [ smallind ])
159
+ b = math .sqrt (eig_val [ small_ind ])
162
160
except ValueError :
163
161
b = 0
164
162
165
163
x = [a * math .cos (it ) for it in t ]
166
164
y = [b * math .sin (it ) for it in t ]
167
- angle = math .atan2 (eigvec [ bigind , 1 ], eigvec [ bigind , 0 ])
165
+ angle = math .atan2 (eig_vec [ big_ind , 1 ], eig_vec [ big_ind , 0 ])
168
166
R = np .array ([[math .cos (angle ), math .sin (angle )],
169
167
[- math .sin (angle ), math .cos (angle )]])
170
168
fx = R .dot (np .array ([[x , y ]]))
@@ -182,17 +180,15 @@ def main():
182
180
183
181
time = 0.0
184
182
185
- # RFID positions [x, y]
186
- RFID = np .array ([[10.0 , 0.0 ],
187
- [10.0 , 10.0 ],
188
- [0.0 , 15.0 ],
189
- [- 5.0 , 20.0 ]])
183
+ # RF_ID positions [x, y]
184
+ RF_ID = np .array ([[10.0 , 0.0 ],
185
+ [10.0 , 10.0 ],
186
+ [0.0 , 15.0 ],
187
+ [- 5.0 , 20.0 ]])
190
188
191
189
# State Vector [x y yaw v]'
192
190
xEst = np .zeros ((4 , 1 ))
193
191
xTrue = np .zeros ((4 , 1 ))
194
- PEst = np .eye (4 )
195
-
196
192
px = np .zeros ((4 , NP )) # Particle store of x
197
193
198
194
xDR = np .zeros ((4 , 1 )) # Dead reckoning
@@ -206,9 +202,9 @@ def main():
206
202
time += DT
207
203
u = calc_input ()
208
204
209
- xTrue , z , xDR , ud = observation (xTrue , xDR , u , RFID )
205
+ xTrue , z , xDR , ud = observation (xTrue , xDR , u , RF_ID )
210
206
211
- xEst , PEst , px = enkf_localization (px , xEst , PEst , z , ud )
207
+ xEst , PEst , px = enkf_localization (px , z , ud )
212
208
213
209
# store data history
214
210
hxEst = np .hstack ((hxEst , xEst ))
@@ -220,20 +216,19 @@ def main():
220
216
221
217
for i in range (len (z [:, 0 ])):
222
218
plt .plot ([xTrue [0 , 0 ], z [i , 2 ]], [xTrue [1 , 0 ], z [i , 3 ]], "-k" )
223
- plt .plot (RFID [:, 0 ], RFID [:, 1 ], "*k" )
219
+ plt .plot (RF_ID [:, 0 ], RF_ID [:, 1 ], "*k" )
224
220
plt .plot (px [0 , :], px [1 , :], ".r" )
225
221
plt .plot (np .array (hxTrue [0 , :]).flatten (),
226
222
np .array (hxTrue [1 , :]).flatten (), "-b" )
227
223
plt .plot (np .array (hxDR [0 , :]).flatten (),
228
224
np .array (hxDR [1 , :]).flatten (), "-k" )
229
225
plt .plot (np .array (hxEst [0 , :]).flatten (),
230
226
np .array (hxEst [1 , :]).flatten (), "-r" )
231
- #plot_covariance_ellipse(xEst, PEst)
227
+ # plot_covariance_ellipse(xEst, PEst)
232
228
plt .axis ("equal" )
233
229
plt .grid (True )
234
230
plt .pause (0.001 )
235
231
236
232
237
233
if __name__ == '__main__' :
238
234
main ()
239
-
0 commit comments