1010import numpy as np
1111import matplotlib .pyplot as plt
1212
13+ # ICP parameters
14+ EPS = 0.0001
15+ MAXITER = 100
1316
14- def update_homogenerous_matrix (Hin , R , T ):
15-
16- H = np .matrix (np .zeros ((3 , 3 ))) # translation vector
17-
18- H [0 , 0 ] = R [0 , 0 ]
19- H [1 , 0 ] = R [1 , 0 ]
20- H [0 , 1 ] = R [0 , 1 ]
21- H [1 , 1 ] = R [1 , 1 ]
22- H [2 , 2 ] = 1.0
23-
24- H [0 , 2 ] = T [0 , 0 ]
25- H [1 , 2 ] = T [1 , 0 ]
26-
27- if Hin is None :
28- return H
29- else :
30- return Hin * H
17+ show_animation = True
3118
3219
3320def ICP_matching (pdata , data ):
3421 H = None # homogeneraous transformation matrix
3522
36- # ICP
37- EPS = 0.0001
38- maxIter = 100
39-
4023 dError = 1000.0
4124 preError = 1000.0
4225 count = 0
4326
4427 while dError >= EPS :
4528 count += 1
4629
47- error = nearest_neighbor_assosiation (pdata , data )
48- Rt , Tt = SVD_motion_estimation (pdata , data )
30+ if show_animation :
31+ plt .cla ()
32+ plt .plot (pdata [0 , :], pdata [1 , :], ".r" )
33+ plt .plot (data [0 , :], data [1 , :], ".b" )
34+ plt .plot (0.0 , 0.0 , "xr" )
35+ plt .axis ("equal" )
36+ plt .pause (1.0 )
37+
38+ inds , error = nearest_neighbor_assosiation (pdata , data )
39+ Rt , Tt = SVD_motion_estimation (pdata [:, inds ], data )
4940
41+ # update current points
5042 data = (Rt * data ) + Tt
5143
5244 H = update_homogenerous_matrix (H , Rt , Tt )
5345
5446 dError = abs (preError - error )
5547 preError = error
48+ print ("Residual:" , error )
5649
5750 if dError <= EPS :
58- print ("Converge" , dError , count )
51+ print ("Converge" , error , dError , count )
5952 break
60- elif maxIter <= count :
53+ elif MAXITER <= count :
54+ print ("Not Converge..." , error , dError , count )
6155 break
6256
6357 R = np .matrix (H [0 :2 , 0 :2 ])
@@ -66,19 +60,47 @@ def ICP_matching(pdata, data):
6660 return R , T
6761
6862
63+ def update_homogenerous_matrix (Hin , R , T ):
64+
65+ H = np .matrix (np .zeros ((3 , 3 )))
66+
67+ H [0 , 0 ] = R [0 , 0 ]
68+ H [1 , 0 ] = R [1 , 0 ]
69+ H [0 , 1 ] = R [0 , 1 ]
70+ H [1 , 1 ] = R [1 , 1 ]
71+ H [2 , 2 ] = 1.0
72+
73+ H [0 , 2 ] = T [0 , 0 ]
74+ H [1 , 2 ] = T [1 , 0 ]
75+
76+ if Hin is None :
77+ return H
78+ else :
79+ return Hin * H
80+
81+
6982def nearest_neighbor_assosiation (pdata , data ):
7083
84+ # calc the sum of residual errors
7185 ddata = pdata - data
72-
7386 d = np .linalg .norm (ddata , axis = 0 )
74-
7587 error = sum (d )
7688
89+ # calc index with nearest neighbor assosiation
90+ inds = []
7791 for i in range (data .shape [1 ]):
78- for ii in range (data .shape [1 ]):
79- print (i )
92+ minid = - 1
93+ mind = float ("inf" )
94+ for ii in range (pdata .shape [1 ]):
95+ d = np .linalg .norm (pdata [:, ii ] - data [:, i ])
96+
97+ if mind >= d :
98+ mind = d
99+ minid = ii
100+
101+ inds .append (minid )
80102
81- return error
103+ return inds , error
82104
83105
84106def SVD_motion_estimation (pdata , data ):
@@ -104,35 +126,25 @@ def main():
104126 # simulation parameters
105127 nPoint = 10
106128 fieldLength = 50.0
107- motion = [0.5 , 1.0 , math .radians (- 40.0 )] # movement [x[m],y[m],yaw[deg]]
108- # transitionSigma=0.01;%並進方向の移動誤差標準偏差[m]
109- # thetaSigma=1; %回転方向の誤差標準偏差[deg]
110-
111- # previous point data
112- px = (np .random .rand (nPoint ) - 0.5 ) * fieldLength
113- py = (np .random .rand (nPoint ) - 0.5 ) * fieldLength
114-
115- cx = [math .cos (motion [2 ]) * x - math .sin (motion [2 ]) * y + motion [0 ]
116- for (x , y ) in zip (px , py )]
117- cy = [math .sin (motion [2 ]) * x + math .cos (motion [2 ]) * y + motion [1 ]
118- for (x , y ) in zip (px , py )]
119-
120- pdata = np .matrix (np .vstack ((px , py )))
121- # print(pdata)
122- data = np .matrix (np .vstack ((cx , cy )))
123- # print(data)
124- odata = data [:, :]
125-
126- R , T = ICP_matching (pdata , data )
127-
128- fdata = (R * odata ) + T
129-
130- plt .plot (px , py , ".b" )
131- plt .plot (cx , cy , ".r" )
132- plt .plot (fdata [0 , :], fdata [1 , :], "xk" )
133- plt .plot (0.0 , 0.0 , "xr" )
134- plt .axis ("equal" )
135- plt .show ()
129+ motion = [0.5 , 2.0 , math .radians (- 10.0 )] # movement [x[m],y[m],yaw[deg]]
130+
131+ nsim = 3 # number of simulation
132+
133+ for _ in range (nsim ):
134+
135+ # previous points
136+ px = (np .random .rand (nPoint ) - 0.5 ) * fieldLength
137+ py = (np .random .rand (nPoint ) - 0.5 ) * fieldLength
138+ pdata = np .matrix (np .vstack ((px , py )))
139+
140+ # current points
141+ cx = [math .cos (motion [2 ]) * x - math .sin (motion [2 ]) * y + motion [0 ]
142+ for (x , y ) in zip (px , py )]
143+ cy = [math .sin (motion [2 ]) * x + math .cos (motion [2 ]) * y + motion [1 ]
144+ for (x , y ) in zip (px , py )]
145+ data = np .matrix (np .vstack ((cx , cy )))
146+
147+ R , T = ICP_matching (pdata , data )
136148
137149
138150if __name__ == '__main__' :
0 commit comments