1616R = np .diag ([1.0 , np .deg2rad (20.0 )]) ** 2
1717
1818# 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
2222
2323DT = 0.1 # time tick [s]
2424SIM_TIME = 50.0 # simulation time [s]
2525MAX_RANGE = 20.0 # maximum observation range
2626M_DIST_TH = 2.0 # Threshold of Mahalanobis distance for data association.
2727STATE_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]
2929N_PARTICLE = 100 # number of particle
3030NTH = N_PARTICLE / 1.5 # Number of particle for re-sampling
3131
3434
3535class Particle :
3636
37- def __init__ (self , N_LM ):
37+ def __init__ (self , n_landmark ):
3838 self .w = 1.0 / N_PARTICLE
3939 self .x = 0.0
4040 self .y = 0.0
4141 self .yaw = 0.0
4242 # landmark x-y positions
43- self .lm = np .zeros ((N_LM , LM_SIZE ))
43+ self .lm = np .zeros ((n_landmark , LM_SIZE ))
4444 # 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 ))
4646
4747
4848def fast_slam1 (particles , u , z ):
@@ -56,11 +56,11 @@ def fast_slam1(particles, u, z):
5656
5757
5858def normalize_weight (particles ):
59- sumw = sum ([p .w for p in particles ])
59+ sum_w = sum ([p .w for p in particles ])
6060
6161 try :
6262 for i in range (N_PARTICLE ):
63- particles [i ].w /= sumw
63+ particles [i ].w /= sum_w
6464 except ZeroDivisionError :
6565 for i in range (N_PARTICLE ):
6666 particles [i ].w = 1.0 / N_PARTICLE
@@ -101,7 +101,7 @@ def predict_particles(particles, u):
101101 return particles
102102
103103
104- def add_new_lm (particle , z , Q_cov ):
104+ def add_new_landmark (particle , z , Q_cov ):
105105 r = z [0 ]
106106 b = z [1 ]
107107 lm_id = int (z [2 ])
@@ -113,10 +113,14 @@ def add_new_lm(particle, z, Q_cov):
113113 particle .lm [lm_id , 1 ] = particle .y + r * s
114114
115115 # 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 )
120124
121125 return particle
122126
@@ -146,10 +150,10 @@ def update_kf_with_cholesky(xf, Pf, v, Q_cov, Hf):
146150 S = Hf @ PHt + Q_cov
147151
148152 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
153157
154158 x = xf + W @ v
155159 P = Pf - W1 @ W1 .T
@@ -187,7 +191,7 @@ def compute_weight(particle, z, Q_cov):
187191 try :
188192 invS = np .linalg .inv (Sf )
189193 except np .linalg .linalg .LinAlgError :
190- print ("singuler " )
194+ print ("singular " )
191195 return 1.0
192196
193197 num = math .exp (- 0.5 * dx .T @ invS @ dx )
@@ -201,12 +205,12 @@ def compute_weight(particle, z, Q_cov):
201205def update_with_observation (particles , z ):
202206 for iz in range (len (z [0 , :])):
203207
204- lmid = int (z [2 , iz ])
208+ landmark_id = int (z [2 , iz ])
205209
206210 for ip in range (N_PARTICLE ):
207211 # 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 )
210214 # known landmark
211215 else :
212216 w = compute_weight (particles [ip ], z [:, iz ], Q )
@@ -229,28 +233,29 @@ def resampling(particles):
229233
230234 pw = np .array (pw )
231235
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 )
234238
235- if Neff < NTH : # resampling
236- wcum = np .cumsum (pw )
239+ if n_eff < NTH : # resampling
240+ w_cum = np .cumsum (pw )
237241 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
239243
240244 inds = []
241245 ind = 0
242246 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 ]):
244249 ind += 1
245250 inds .append (ind )
246251
247- tparticles = particles [:]
252+ tmp_particles = particles [:]
248253 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 [:, :]
254259 particles [i ].w = 1.0 / N_PARTICLE
255260
256261 return particles
@@ -259,37 +264,39 @@ def resampling(particles):
259264def calc_input (time ):
260265 if time <= 3.0 : # wait at first
261266 v = 0.0
262- yawrate = 0.0
267+ yaw_rate = 0.0
263268 else :
264269 v = 1.0 # [m/s]
265- yawrate = 0.1 # [rad/s]
270+ yaw_rate = 0.1 # [rad/s]
266271
267- u = np .array ([v , yawrate ]).reshape (2 , 1 )
272+ u = np .array ([v , yaw_rate ]).reshape (2 , 1 )
268273
269274 return u
270275
271276
272- def observation (xTrue , xd , u , RFID ):
277+ def observation (xTrue , xd , u , rfid ):
273278 # calc true state
274279 xTrue = motion_model (xTrue , u )
275280
276281 # add noise to range observation
277282 z = np .zeros ((3 , 0 ))
278- for i in range (len (RFID [:, 0 ])):
283+ for i in range (len (rfid [:, 0 ])):
279284
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 ]
282287 d = math .hypot (dx , dy )
283288 angle = pi_2_pi (math .atan2 (dy , dx ) - xTrue [2 , 0 ])
284289 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 )
288294 z = np .hstack ((z , zi ))
289295
290296 # 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
293300 ud = np .array ([ud1 , ud2 ]).reshape (2 , 1 )
294301
295302 xd = motion_model (xd , ud )
@@ -332,7 +339,7 @@ def main():
332339 [- 5.0 , 5.0 ],
333340 [- 10.0 , 15.0 ]
334341 ])
335- N_LM = RFID .shape [0 ]
342+ n_landmark = RFID .shape [0 ]
336343
337344 # State Vector [x y yaw v]'
338345 xEst = np .zeros ((STATE_SIZE , 1 )) # SLAM estimation
@@ -344,7 +351,7 @@ def main():
344351 hxTrue = xTrue
345352 hxDR = xTrue
346353
347- particles = [Particle (N_LM ) for _ in range (N_PARTICLE )]
354+ particles = [Particle (n_landmark ) for _ in range (N_PARTICLE )]
348355
349356 while SIM_TIME >= time :
350357 time += DT
@@ -366,8 +373,9 @@ def main():
366373 if show_animation : # pragma: no cover
367374 plt .cla ()
368375 # 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 ])
371379 plt .plot (RFID [:, 0 ], RFID [:, 1 ], "*k" )
372380
373381 for i in range (N_PARTICLE ):
0 commit comments