16
16
R = np .diag ([1.0 , np .deg2rad (20.0 )]) ** 2
17
17
18
18
# Simulation parameter
19
- Qsim = np .diag ([0.3 , np .deg2rad (2.0 )]) ** 2
20
- Rsim = np .diag ([0.5 , np .deg2rad (10.0 )]) ** 2
21
- OFFSET_YAWRATE_NOISE = 0.01
19
+ Q_sim = np .diag ([0.3 , np .deg2rad (2.0 )]) ** 2
20
+ R_sim = np .diag ([0.5 , np .deg2rad (10.0 )]) ** 2
21
+ OFFSET_YAW_RATE_NOISE = 0.01
22
22
23
23
DT = 0.1 # time tick [s]
24
24
SIM_TIME = 50.0 # simulation time [s]
25
25
MAX_RANGE = 20.0 # maximum observation range
26
26
M_DIST_TH = 2.0 # Threshold of Mahalanobis distance for data association.
27
27
STATE_SIZE = 3 # State size [x,y,yaw]
28
- LM_SIZE = 2 # LM srate size [x,y]
28
+ LM_SIZE = 2 # LM state size [x,y]
29
29
N_PARTICLE = 100 # number of particle
30
30
NTH = N_PARTICLE / 1.5 # Number of particle for re-sampling
31
31
34
34
35
35
class Particle :
36
36
37
- def __init__ (self , N_LM ):
37
+ def __init__ (self , n_landmark ):
38
38
self .w = 1.0 / N_PARTICLE
39
39
self .x = 0.0
40
40
self .y = 0.0
41
41
self .yaw = 0.0
42
42
# landmark x-y positions
43
- self .lm = np .zeros ((N_LM , LM_SIZE ))
43
+ self .lm = np .zeros ((n_landmark , LM_SIZE ))
44
44
# landmark position covariance
45
- self .lmP = np .zeros ((N_LM * LM_SIZE , LM_SIZE ))
45
+ self .lmP = np .zeros ((n_landmark * LM_SIZE , LM_SIZE ))
46
46
47
47
48
48
def fast_slam1 (particles , u , z ):
@@ -56,11 +56,11 @@ def fast_slam1(particles, u, z):
56
56
57
57
58
58
def normalize_weight (particles ):
59
- sumw = sum ([p .w for p in particles ])
59
+ sum_w = sum ([p .w for p in particles ])
60
60
61
61
try :
62
62
for i in range (N_PARTICLE ):
63
- particles [i ].w /= sumw
63
+ particles [i ].w /= sum_w
64
64
except ZeroDivisionError :
65
65
for i in range (N_PARTICLE ):
66
66
particles [i ].w = 1.0 / N_PARTICLE
@@ -101,7 +101,7 @@ def predict_particles(particles, u):
101
101
return particles
102
102
103
103
104
- def add_new_lm (particle , z , Q_cov ):
104
+ def add_new_landmark (particle , z , Q_cov ):
105
105
r = z [0 ]
106
106
b = z [1 ]
107
107
lm_id = int (z [2 ])
@@ -113,10 +113,14 @@ def add_new_lm(particle, z, Q_cov):
113
113
particle .lm [lm_id , 1 ] = particle .y + r * s
114
114
115
115
# covariance
116
- Gz = np .array ([[c , - r * s ],
117
- [s , r * c ]])
118
-
119
- particle .lmP [2 * lm_id :2 * lm_id + 2 ] = Gz @ Q_cov @ Gz .T
116
+ dx = r * c
117
+ dy = r * s
118
+ d2 = dx ** 2 + dy ** 2
119
+ d = math .sqrt (d2 )
120
+ Gz = np .array ([[dx / d , dy / d ],
121
+ [- dy / d2 , dx / d2 ]])
122
+ particle .lmP [2 * lm_id :2 * lm_id + 2 ] = np .linalg .inv (
123
+ Gz ) @ Q_cov @ np .linalg .inv (Gz .T )
120
124
121
125
return particle
122
126
@@ -146,10 +150,10 @@ def update_kf_with_cholesky(xf, Pf, v, Q_cov, Hf):
146
150
S = Hf @ PHt + Q_cov
147
151
148
152
S = (S + S .T ) * 0.5
149
- SChol = np .linalg .cholesky (S ).T
150
- SCholInv = np .linalg .inv (SChol )
151
- W1 = PHt @ SCholInv
152
- W = W1 @ SCholInv .T
153
+ s_chol = np .linalg .cholesky (S ).T
154
+ s_chol_inv = np .linalg .inv (s_chol )
155
+ W1 = PHt @ s_chol_inv
156
+ W = W1 @ s_chol_inv .T
153
157
154
158
x = xf + W @ v
155
159
P = Pf - W1 @ W1 .T
@@ -187,7 +191,7 @@ def compute_weight(particle, z, Q_cov):
187
191
try :
188
192
invS = np .linalg .inv (Sf )
189
193
except np .linalg .linalg .LinAlgError :
190
- print ("singuler " )
194
+ print ("singular " )
191
195
return 1.0
192
196
193
197
num = math .exp (- 0.5 * dx .T @ invS @ dx )
@@ -201,12 +205,12 @@ def compute_weight(particle, z, Q_cov):
201
205
def update_with_observation (particles , z ):
202
206
for iz in range (len (z [0 , :])):
203
207
204
- lmid = int (z [2 , iz ])
208
+ landmark_id = int (z [2 , iz ])
205
209
206
210
for ip in range (N_PARTICLE ):
207
211
# new landmark
208
- if abs (particles [ip ].lm [lmid , 0 ]) <= 0.01 :
209
- particles [ip ] = add_new_lm (particles [ip ], z [:, iz ], Q )
212
+ if abs (particles [ip ].lm [landmark_id , 0 ]) <= 0.01 :
213
+ particles [ip ] = add_new_landmark (particles [ip ], z [:, iz ], Q )
210
214
# known landmark
211
215
else :
212
216
w = compute_weight (particles [ip ], z [:, iz ], Q )
@@ -229,28 +233,29 @@ def resampling(particles):
229
233
230
234
pw = np .array (pw )
231
235
232
- Neff = 1.0 / (pw @ pw .T ) # Effective particle number
233
- # print(Neff )
236
+ n_eff = 1.0 / (pw @ pw .T ) # Effective particle number
237
+ # print(n_eff )
234
238
235
- if Neff < NTH : # resampling
236
- wcum = np .cumsum (pw )
239
+ if n_eff < NTH : # resampling
240
+ w_cum = np .cumsum (pw )
237
241
base = np .cumsum (pw * 0.0 + 1 / N_PARTICLE ) - 1 / N_PARTICLE
238
- resampleid = base + np .random .rand (base .shape [0 ]) / N_PARTICLE
242
+ resample_id = base + np .random .rand (base .shape [0 ]) / N_PARTICLE
239
243
240
244
inds = []
241
245
ind = 0
242
246
for ip in range (N_PARTICLE ):
243
- while (ind < wcum .shape [0 ] - 1 ) and (resampleid [ip ] > wcum [ind ]):
247
+ while (ind < w_cum .shape [0 ] - 1 ) \
248
+ and (resample_id [ip ] > w_cum [ind ]):
244
249
ind += 1
245
250
inds .append (ind )
246
251
247
- tparticles = particles [:]
252
+ tmp_particles = particles [:]
248
253
for i in range (len (inds )):
249
- particles [i ].x = tparticles [inds [i ]].x
250
- particles [i ].y = tparticles [inds [i ]].y
251
- particles [i ].yaw = tparticles [inds [i ]].yaw
252
- particles [i ].lm = tparticles [inds [i ]].lm [:, :]
253
- particles [i ].lmP = tparticles [inds [i ]].lmP [:, :]
254
+ particles [i ].x = tmp_particles [inds [i ]].x
255
+ particles [i ].y = tmp_particles [inds [i ]].y
256
+ particles [i ].yaw = tmp_particles [inds [i ]].yaw
257
+ particles [i ].lm = tmp_particles [inds [i ]].lm [:, :]
258
+ particles [i ].lmP = tmp_particles [inds [i ]].lmP [:, :]
254
259
particles [i ].w = 1.0 / N_PARTICLE
255
260
256
261
return particles
@@ -259,37 +264,39 @@ def resampling(particles):
259
264
def calc_input (time ):
260
265
if time <= 3.0 : # wait at first
261
266
v = 0.0
262
- yawrate = 0.0
267
+ yaw_rate = 0.0
263
268
else :
264
269
v = 1.0 # [m/s]
265
- yawrate = 0.1 # [rad/s]
270
+ yaw_rate = 0.1 # [rad/s]
266
271
267
- u = np .array ([v , yawrate ]).reshape (2 , 1 )
272
+ u = np .array ([v , yaw_rate ]).reshape (2 , 1 )
268
273
269
274
return u
270
275
271
276
272
- def observation (xTrue , xd , u , RFID ):
277
+ def observation (xTrue , xd , u , rfid ):
273
278
# calc true state
274
279
xTrue = motion_model (xTrue , u )
275
280
276
281
# add noise to range observation
277
282
z = np .zeros ((3 , 0 ))
278
- for i in range (len (RFID [:, 0 ])):
283
+ for i in range (len (rfid [:, 0 ])):
279
284
280
- dx = RFID [i , 0 ] - xTrue [0 , 0 ]
281
- dy = RFID [i , 1 ] - xTrue [1 , 0 ]
285
+ dx = rfid [i , 0 ] - xTrue [0 , 0 ]
286
+ dy = rfid [i , 1 ] - xTrue [1 , 0 ]
282
287
d = math .hypot (dx , dy )
283
288
angle = pi_2_pi (math .atan2 (dy , dx ) - xTrue [2 , 0 ])
284
289
if d <= MAX_RANGE :
285
- dn = d + np .random .randn () * Qsim [0 , 0 ] ** 0.5 # add noise
286
- anglen = angle + np .random .randn () * Qsim [1 , 1 ] ** 0.5 # add noise
287
- zi = np .array ([dn , pi_2_pi (anglen ), i ]).reshape (3 , 1 )
290
+ dn = d + np .random .randn () * Q_sim [0 , 0 ] ** 0.5 # add noise
291
+ angle_with_noize = angle + np .random .randn () * Q_sim [
292
+ 1 , 1 ] ** 0.5 # add noise
293
+ zi = np .array ([dn , pi_2_pi (angle_with_noize ), i ]).reshape (3 , 1 )
288
294
z = np .hstack ((z , zi ))
289
295
290
296
# add noise to input
291
- ud1 = u [0 , 0 ] + np .random .randn () * Rsim [0 , 0 ] ** 0.5
292
- ud2 = u [1 , 0 ] + np .random .randn () * Rsim [1 , 1 ] ** 0.5 + OFFSET_YAWRATE_NOISE
297
+ ud1 = u [0 , 0 ] + np .random .randn () * R_sim [0 , 0 ] ** 0.5
298
+ ud2 = u [1 , 0 ] + np .random .randn () * R_sim [
299
+ 1 , 1 ] ** 0.5 + OFFSET_YAW_RATE_NOISE
293
300
ud = np .array ([ud1 , ud2 ]).reshape (2 , 1 )
294
301
295
302
xd = motion_model (xd , ud )
@@ -332,7 +339,7 @@ def main():
332
339
[- 5.0 , 5.0 ],
333
340
[- 10.0 , 15.0 ]
334
341
])
335
- N_LM = RFID .shape [0 ]
342
+ n_landmark = RFID .shape [0 ]
336
343
337
344
# State Vector [x y yaw v]'
338
345
xEst = np .zeros ((STATE_SIZE , 1 )) # SLAM estimation
@@ -344,7 +351,7 @@ def main():
344
351
hxTrue = xTrue
345
352
hxDR = xTrue
346
353
347
- particles = [Particle (N_LM ) for _ in range (N_PARTICLE )]
354
+ particles = [Particle (n_landmark ) for _ in range (N_PARTICLE )]
348
355
349
356
while SIM_TIME >= time :
350
357
time += DT
@@ -366,8 +373,9 @@ def main():
366
373
if show_animation : # pragma: no cover
367
374
plt .cla ()
368
375
# for stopping simulation with the esc key.
369
- plt .gcf ().canvas .mpl_connect ('key_release_event' ,
370
- lambda event : [exit (0 ) if event .key == 'escape' else None ])
376
+ plt .gcf ().canvas .mpl_connect (
377
+ 'key_release_event' , lambda event :
378
+ [exit (0 ) if event .key == 'escape' else None ])
371
379
plt .plot (RFID [:, 0 ], RFID [:, 1 ], "*k" )
372
380
373
381
for i in range (N_PARTICLE ):
0 commit comments