11"""
22
3- Graph SLAM example
3+ Graph based SLAM example
44
55author: Atsushi Sakai (@Atsushi_twi)
66
1414
1515
1616# Simulation parameter
17- Qsim = np .diag ([0.2 , math .radians (1 .0 )])** 2
18- Rsim = np .diag ([1 .0 , math .radians (10 .0 )])** 2
17+ Qsim = np .diag ([0.0 , math .radians (0 .0 )])** 2
18+ Rsim = np .diag ([0 .0 , math .radians (00 .0 )])** 2
1919
2020DT = 1.0 # time tick [s]
21- SIM_TIME = 50 .0 # simulation time [s]
21+ SIM_TIME = 20 .0 # simulation time [s]
2222MAX_RANGE = 20.0 # maximum observation range
2323STATE_SIZE = 3 # State size [x,y,yaw]
2424
@@ -37,12 +37,12 @@ class Edge():
3737 def __init__ (self ):
3838 self .e = np .zeros ((3 , 1 ))
3939 self .omega = np .zeros ((3 , 3 )) # information matrix
40- self .d_t = 0.0
41- self .d_td = 0.0
42- self .yaw_t = 0.0
43- self .yaw_td = 0.0
44- self .angle_t = 0.0
45- self .angle_td = 0.0
40+ self .d1 = 0.0
41+ self .d2 = 0.0
42+ self .yaw1 = 0.0
43+ self .yaw2 = 0.0
44+ self .angle1 = 0.0
45+ self .angle2 = 0.0
4646 self .id1 = 0
4747 self .id2 = 0
4848
@@ -65,32 +65,32 @@ def calc_rotational_matrix(angle):
6565 return Rt
6666
6767
68- def calc_edge (xt , yt , yawt , xtd , ytd , yawtd , dt ,
69- anglet , phit , dtd , angletd , phitd , t , td ):
68+ def calc_edge (x1 , y1 , yaw1 , x2 , y2 , yaw2 , d1 ,
69+ angle1 , phi1 , d2 , angle2 , phi2 , t1 , t2 ):
7070 edge = Edge ()
7171
72- tangle1 = pi_2_pi (yawt + anglet )
73- tangle2 = pi_2_pi (yawt + anglet )
74- t1 = dt * math .cos (tangle1 )
75- t2 = dtd * math .cos (tangle2 )
76- t3 = dt * math .sin (tangle1 )
77- t4 = dtd * math .sin (tangle2 )
72+ tangle1 = pi_2_pi (yaw1 + angle1 )
73+ tangle2 = pi_2_pi (yaw2 + angle2 )
74+ tmp1 = d1 * math .cos (tangle1 )
75+ tmp2 = d2 * math .cos (tangle2 )
76+ tmp3 = d1 * math .sin (tangle1 )
77+ tmp4 = d2 * math .sin (tangle2 )
7878
79- edge .e [0 , 0 ] = xtd - xt - t1 + t2
80- edge .e [1 , 0 ] = ytd - yt - t3 + t4
81- edge .e [2 , 0 ] = pi_2_pi (yawtd - yawt - phit + phitd )
79+ edge .e [0 , 0 ] = x2 - x1 - tmp1 + tmp2
80+ edge .e [1 , 0 ] = y2 - y1 - tmp3 + tmp4
81+ edge .e [2 , 0 ] = pi_2_pi (yaw2 - yaw1 - phi1 + phi2 )
8282
83- sig_t = cal_observation_sigma (dt )
84- sig_td = cal_observation_sigma (dtd )
83+ sig_t = cal_observation_sigma (d1 )
84+ sig_td = cal_observation_sigma (d2 )
8585
8686 Rt = calc_rotational_matrix (tangle1 )
8787 Rtd = calc_rotational_matrix (tangle2 )
8888
8989 edge .omega = np .linalg .inv (Rt * sig_t * Rt .T + Rtd * sig_td * Rtd .T )
90- edge .d_t , edge .d_td = dt , dtd
91- edge .yaw_t , edge .yaw_td = yawt , yawtd
92- edge .angle_t , edge .angle_td = anglet , angletd
93- edge .id1 , edge .id2 = t , td
90+ edge .d1 , edge .d2 = d1 , d2
91+ edge .yaw1 , edge .yaw2 = yaw1 , yaw2
92+ edge .angle1 , edge .angle2 = angle1 , angle2
93+ edge .id1 , edge .id2 = t1 , t2
9494
9595 return edge
9696
@@ -100,40 +100,35 @@ def calc_edges(xlist, zlist):
100100 edges = []
101101 zids = list (itertools .combinations (range (len (zlist )), 2 ))
102102
103- for (t , td ) in zids :
104- # print(xlist)
105- # print(zlist)
106- xt , yt , yawt = xlist [0 , t ], xlist [1 , t ], xlist [2 , t ]
107- xtd , ytd , yawtd = xlist [0 , td ], xlist [1 , td ], xlist [2 , td ]
108- # print(zlist[t])
109- # print(zlist[td])
110-
111- for iz1 in range (len (zlist [t ][:, 0 ])):
112- for iz2 in range (len (zlist [td ][:, 0 ])):
113- if zlist [t ][iz1 , 3 ] == zlist [td ][iz2 , 3 ]:
114- dt , anglet , phit = zlist [t ][iz1 ,
115- 0 ], zlist [t ][iz1 , 1 ], zlist [t ][iz1 , 2 ]
116- dtd , angletd , phitd = zlist [td ][iz2 ,
117- 0 ], zlist [td ][iz2 , 1 ], zlist [td ][iz2 , 2 ]
118-
119- edge = calc_edge (xt , yt , yawt , xtd , ytd , yawtd , dt ,
120- anglet , phit , dtd , angletd , phitd , t , td )
103+ for (t1 , t2 ) in zids :
104+ x1 , y1 , yaw1 = xlist [0 , t1 ], xlist [1 , t1 ], xlist [2 , t1 ]
105+ x2 , y2 , yaw2 = xlist [0 , t2 ], xlist [1 , t2 ], xlist [2 , t2 ]
106+
107+ for iz1 in range (len (zlist [t1 ][:, 0 ])):
108+ for iz2 in range (len (zlist [t2 ][:, 0 ])):
109+ if zlist [t1 ][iz1 , 3 ] == zlist [t2 ][iz2 , 3 ]:
110+ d1 = zlist [t1 ][iz1 , 0 ]
111+ angle1 , phi1 = zlist [t1 ][iz1 , 1 ], zlist [t1 ][iz1 , 2 ]
112+ d2 = zlist [t2 ][iz2 , 0 ]
113+ angle2 , phi2 = zlist [t2 ][iz2 , 1 ], zlist [t2 ][iz2 , 2 ]
114+
115+ edge = calc_edge (x1 , y1 , yaw1 , x2 , y2 , yaw2 , d1 ,
116+ angle1 , phi1 , d2 , angle2 , phi2 , t1 , t2 )
121117
122118 edges .append (edge )
123- break
124119
125120 return edges
126121
127122
128123def calc_jacobian (edge ):
129- t = edge .yaw_t + edge .angle_t
130- A = np .matrix ([[- 1.0 , 0 , edge .d_t * math .sin (t )],
131- [0 , - 1.0 , - edge .d_t * math .cos (t )],
124+ t1 = edge .yaw1 + edge .angle1
125+ A = np .matrix ([[- 1.0 , 0 , edge .d1 * math .sin (t1 )],
126+ [0 , - 1.0 , - edge .d1 * math .cos (t1 )],
132127 [0 , 0 , - 1.0 ]])
133128
134- td = edge .yaw_td + edge .angle_td
135- B = np .matrix ([[1.0 , 0 , - edge .d_td * math .sin (td )],
136- [0 , 1.0 , edge .d_td * math .cos (td )],
129+ t2 = edge .yaw2 + edge .angle2
130+ B = np .matrix ([[1.0 , 0 , - edge .d2 * math .sin (t2 )],
131+ [0 , 1.0 , edge .d2 * math .cos (t2 )],
137132 [0 , 0 , 1.0 ]])
138133
139134 return A , B
@@ -143,27 +138,25 @@ def fill_H_and_b(H, b, edge):
143138
144139 A , B = calc_jacobian (edge )
145140
146- id1 = edge .id1 * 3
147- id2 = edge .id2 * 3
141+ id1 = edge .id1 * STATE_SIZE
142+ id2 = edge .id2 * STATE_SIZE
148143
149- H [id1 :id1 + 3 , id1 :id1 + 3 ] += A .T * edge .omega * A
150- H [id1 :id1 + 3 , id2 :id2 + 3 ] += A .T * edge .omega * B
151- H [id2 :id2 + 3 , id1 :id1 + 3 ] += B .T * edge .omega * A
152- H [id2 :id2 + 3 , id2 :id2 + 3 ] += B .T * edge .omega * B
144+ H [id1 :id1 + STATE_SIZE , id1 :id1 + STATE_SIZE ] += A .T * edge .omega * A
145+ H [id1 :id1 + STATE_SIZE , id2 :id2 + STATE_SIZE ] += A .T * edge .omega * B
146+ H [id2 :id2 + STATE_SIZE , id1 :id1 + STATE_SIZE ] += B .T * edge .omega * A
147+ H [id2 :id2 + STATE_SIZE , id2 :id2 + STATE_SIZE ] += B .T * edge .omega * B
153148
154- b [id1 :id1 + 3 , 0 ] += (A .T * edge .omega * edge .e )
155- b [id2 :id2 + 3 , 0 ] += (B .T * edge .omega * edge .e )
149+ b [id1 :id1 + STATE_SIZE , 0 ] += (A .T * edge .omega * edge .e )
150+ b [id2 :id2 + STATE_SIZE , 0 ] += (B .T * edge .omega * edge .e )
156151
157152 return H , b
158153
159154
160- def graph_based_slam (u , z , hxDR , hz ):
155+ def graph_based_slam (x_init , hz ):
161156 print ("start graph based slam" )
162157
163- x_opt = copy .deepcopy (hxDR )
164- n = len (hz ) * 3
165-
166- # return x_opt
158+ x_opt = copy .deepcopy (x_init )
159+ n = len (hz ) * STATE_SIZE
167160
168161 for itr in range (MAX_ITR ):
169162 edges = calc_edges (x_opt , hz )
@@ -175,10 +168,10 @@ def graph_based_slam(u, z, hxDR, hz):
175168 for edge in edges :
176169 H , b = fill_H_and_b (H , b , edge )
177170
178- H [0 :3 , 0 :3 ] += np .identity (3 ) * 10000 # to fix origin
171+ # to fix origin
172+ H [0 :STATE_SIZE , 0 :STATE_SIZE ] += np .identity (STATE_SIZE )
179173
180174 dx = - np .linalg .inv (H ).dot (b )
181- # print(dx)
182175
183176 for i in range (len (hz )):
184177 x_opt [0 :3 , i ] += dx [i * 3 :i * 3 + 3 , 0 ]
@@ -268,13 +261,14 @@ def main():
268261
269262 # State Vector [x y yaw v]'
270263 xTrue = np .matrix (np .zeros ((STATE_SIZE , 1 )))
271-
272264 xDR = np .matrix (np .zeros ((STATE_SIZE , 1 ))) # Dead reckoning
273265
274266 # history
275267 hxTrue = xTrue
276268 hxDR = xTrue
277- hz = []
269+ hz = [np .matrix (np .zeros ((1 , 4 )))]
270+ hz [0 ][0 , 3 ] = - 1
271+ # hz = []
278272
279273 while SIM_TIME >= time :
280274 time += DT
@@ -283,12 +277,10 @@ def main():
283277 xTrue , z , xDR , ud = observation (xTrue , xDR , u , RFID )
284278
285279 hxDR = np .hstack ((hxDR , xDR ))
286- hz .append (z )
287-
288- # store data history
289280 hxTrue = np .hstack ((hxTrue , xTrue ))
281+ hz .append (z )
290282
291- x_opt = graph_based_slam (ud , z , hxDR , hz )
283+ x_opt = graph_based_slam (hxDR , hz )
292284
293285 if show_animation :
294286 plt .cla ()
0 commit comments