9
9
import random
10
10
import math
11
11
import numpy as np
12
+ import scipy .spatial
12
13
import matplotlib .pyplot as plt
13
- from matplotrecorder import matplotrecorder
14
- from pyfastnns import pyfastnns
15
- matplotrecorder .donothing = True
16
14
17
15
# parameter
18
- N_SAMPLE = 500
19
- N_KNN = 10
16
+ N_SAMPLE = 500 # number of sample_points
17
+ N_KNN = 10 # number of edge from one sampled point
20
18
MAX_EDGE_LEN = 30.0 # [m] Maximum edge length
21
19
20
+ show_animation = True
21
+
22
22
23
23
class Node :
24
+ """
25
+ Node class for dijkstra search
26
+ """
24
27
25
28
def __init__ (self , x , y , cost , pind ):
26
29
self .x = x
@@ -32,37 +35,120 @@ def __str__(self):
32
35
return str (self .x ) + "," + str (self .y ) + "," + str (self .cost ) + "," + str (self .pind )
33
36
34
37
38
+ class KDTree :
39
+ """
40
+ Nearest neighbor search class with KDTree
41
+ """
42
+
43
+ def __init__ (self , data ):
44
+ # store kd-tree
45
+ self .tree = scipy .spatial .cKDTree (data )
46
+
47
+ def search (self , inp , k = 1 ):
48
+ u"""
49
+ Search NN
50
+
51
+ inp: input data, single frame or multi frame
52
+
53
+ """
54
+
55
+ if len (inp .shape ) >= 2 : # multi input
56
+ index = []
57
+ dist = []
58
+
59
+ for i in inp .T :
60
+ idist , iindex = self .tree .query (i , k = k )
61
+ index .append (iindex )
62
+ dist .append (idist )
63
+
64
+ return index , dist
65
+ else :
66
+ dist , index = self .tree .query (inp , k = k )
67
+ return index , dist
68
+
69
+ def search_in_distance (self , inp , r ):
70
+ u"""
71
+ find points with in a distance r
72
+ """
73
+
74
+ index = self .tree .query_ball_point (inp , r )
75
+ return index
76
+
77
+
35
78
def PRM_planning (sx , sy , gx , gy , ox , oy , rr ):
36
79
37
- sample_x , sample_y = sample_points (sx , sy , gx , gy , rr , ox , oy )
38
- plt .plot (sample_x , sample_y , ".r" )
80
+ obkdtree = KDTree (np .vstack ((ox , oy )).T )
39
81
40
- road_map = generate_roadmap (sample_x , sample_y , rr )
82
+ sample_x , sample_y = sample_points (sx , sy , gx , gy , rr , ox , oy , obkdtree )
83
+ if show_animation :
84
+ plt .plot (sample_x , sample_y , ".b" )
85
+
86
+ road_map = generate_roadmap (sample_x , sample_y , rr , obkdtree )
41
87
42
88
rx , ry = dijkstra_planning (
43
89
sx , sy , gx , gy , ox , oy , rr , road_map , sample_x , sample_y )
44
90
45
91
return rx , ry
46
92
47
93
48
- def generate_roadmap (sample_x , sample_y , rr ):
94
+ def is_collision (sx , sy , gx , gy , rr , okdtree ):
95
+ x = sx
96
+ y = sy
97
+ dx = gx - sx
98
+ dy = gy - sy
99
+ yaw = math .atan2 (gy - sy , gx - sx )
100
+ d = math .sqrt (dx ** 2 + dy ** 2 )
101
+
102
+ if d >= MAX_EDGE_LEN :
103
+ return True
104
+
105
+ D = rr
106
+ nstep = round (d / D )
107
+
108
+ for i in range (nstep ):
109
+ idxs , dist = okdtree .search (np .matrix ([x , y ]).T )
110
+ if dist [0 ] <= rr :
111
+ return True # collision
112
+ x += D * math .cos (yaw )
113
+ y += D * math .sin (yaw )
114
+
115
+ # goal point check
116
+ idxs , dist = okdtree .search (np .matrix ([gx , gy ]).T )
117
+ if dist [0 ] <= rr :
118
+ return True # collision
119
+
120
+ return False # OK
121
+
122
+
123
+ def generate_roadmap (sample_x , sample_y , rr , obkdtree ):
124
+ """
125
+ Road map generation
126
+
127
+ sample_x: [m] x positions of sampled points
128
+ sample_y: [m] y positions of sampled points
129
+ rr: Robot Radius[m]
130
+ obkdtree: KDTree object of obstacles
131
+ """
49
132
50
133
road_map = []
51
134
nsample = len (sample_x )
52
- skdtree = pyfastnns . NNS (np .vstack ((sample_x , sample_y )).T )
135
+ skdtree = KDTree (np .vstack ((sample_x , sample_y )).T )
53
136
54
137
for (i , ix , iy ) in zip (range (nsample ), sample_x , sample_y ):
55
138
56
- index = skdtree .search (
139
+ index , dists = skdtree .search (
57
140
np .matrix ([ix , iy ]).T , k = nsample )
141
+ inds = index [0 ][0 ]
58
142
edge_id = []
143
+ # print(index)
144
+
145
+ for ii in range (1 , len (inds )):
146
+ nx = sample_x [inds [ii ]]
147
+ ny = sample_y [inds [ii ]]
59
148
60
- for ii in range (1 , len (index [0 ][0 ][0 ])):
61
- # nx = sample_x[index[i]]
62
- # ny = sample_y[index[i]]
149
+ if not is_collision (ix , iy , nx , ny , rr , obkdtree ):
150
+ edge_id .append (inds [ii ])
63
151
64
- # if !is_collision(ix, iy, nx, ny, rr, okdtree)
65
- edge_id .append (index [0 ][0 ][0 ][ii ])
66
152
if len (edge_id ) >= N_KNN :
67
153
break
68
154
@@ -94,21 +180,16 @@ def dijkstra_planning(sx, sy, gx, gy, ox, oy, rr, road_map, sample_x, sample_y):
94
180
print ("Cannot find path" )
95
181
break
96
182
97
- print (len (openset ), len (closedset ))
98
-
99
183
c_id = min (openset , key = lambda o : openset [o ].cost )
100
184
current = openset [c_id ]
101
- print ("current" , current , c_id )
102
- # input()
103
185
104
186
# show graph
105
- plt . plot ( current . x , current . y , "xc" )
106
- if len ( closedset . keys ()) % 10 == 0 :
187
+ if show_animation and len ( closedset . keys ()) % 2 == 0 :
188
+ plt . plot ( current . x , current . y , "xg" )
107
189
plt .pause (0.001 )
108
- matplotrecorder .save_frame ()
109
190
110
191
if c_id == (len (road_map ) - 1 ):
111
- print ("Find goal" )
192
+ print ("goal is found! " )
112
193
ngoal .pind = current .pind
113
194
ngoal .cost = current .cost
114
195
break
@@ -121,16 +202,12 @@ def dijkstra_planning(sx, sy, gx, gy, ox, oy, rr, road_map, sample_x, sample_y):
121
202
# expand search grid based on motion model
122
203
for i in range (len (road_map [c_id ])):
123
204
n_id = road_map [c_id ][i ]
124
- print (i , n_id )
125
205
dx = sample_x [n_id ] - current .x
126
206
dy = sample_y [n_id ] - current .y
127
207
d = math .sqrt (dx ** 2 + dy ** 2 )
128
208
node = Node (sample_x [n_id ], sample_y [n_id ],
129
209
current .cost + d , c_id )
130
210
131
- # if not verify_node(node, obmap, minx, miny, maxx, maxy):
132
- # continue
133
-
134
211
if n_id in closedset :
135
212
continue
136
213
# Otherwise if it is already in the open set
@@ -163,21 +240,19 @@ def plot_road_map(road_map, sample_x, sample_y):
163
240
[sample_y [i ], sample_y [ind ]], "-k" )
164
241
165
242
166
- def sample_points (sx , sy , gx , gy , rr , ox , oy ):
243
+ def sample_points (sx , sy , gx , gy , rr , ox , oy , obkdtree ):
167
244
maxx = max (ox )
168
245
maxy = max (oy )
169
246
minx = min (ox )
170
247
miny = min (oy )
171
248
172
249
sample_x , sample_y = [], []
173
250
174
- nns = pyfastnns .NNS (np .vstack ((ox , oy )).T )
175
-
176
251
while len (sample_x ) <= N_SAMPLE :
177
252
tx = (random .random () - minx ) * (maxx - minx )
178
253
ty = (random .random () - miny ) * (maxy - miny )
179
254
180
- index , dist = nns .search (np .matrix ([tx , ty ]).T )
255
+ index , dist = obkdtree .search (np .matrix ([tx , ty ]).T )
181
256
182
257
if dist [0 ] >= rr :
183
258
sample_x .append (tx )
@@ -224,20 +299,19 @@ def main():
224
299
oy .append (60.0 - i )
225
300
226
301
plt .plot (ox , oy , ".k" )
227
- plt .plot (sx , sy , "xr " )
228
- plt .plot (gx , gy , "xb " )
302
+ plt .plot (sx , sy , "^r " )
303
+ plt .plot (gx , gy , "^c " )
229
304
plt .grid (True )
230
305
plt .axis ("equal" )
231
306
232
307
rx , ry = PRM_planning (sx , sy , gx , gy , ox , oy , robot_size )
233
308
234
309
plt .plot (rx , ry , "-r" )
235
310
236
- for i in range (20 ):
237
- matplotrecorder .save_frame ()
238
- plt .show ()
311
+ assert len (rx ) != 0 , 'Cannot found path'
239
312
240
- matplotrecorder .save_movie ("animation.gif" , 0.1 )
313
+ if show_animation :
314
+ plt .show ()
241
315
242
316
243
317
if __name__ == '__main__' :
0 commit comments