Skip to content

Commit 20cb379

Browse files
committed
first release
1 parent cd876c0 commit 20cb379

File tree

3 files changed

+112
-44
lines changed

3 files changed

+112
-44
lines changed

.gitmodules

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,3 @@
2828
[submodule "PathPlanning/DynamicWindowApproach/matplotrecorder"]
2929
path = PathPlanning/DynamicWindowApproach/matplotrecorder
3030
url = https://github.com/AtsushiSakai/matplotrecorder
31-
[submodule "PathPlanning/ProbablisticRoadMap/matplotrecorder"]
32-
path = PathPlanning/ProbablisticRoadMap/matplotrecorder
33-
url = https://github.com/AtsushiSakai/matplotrecorder
34-
[submodule "PathPlanning/ProbablisticRoadMap/pyfastnns"]
35-
path = PathPlanning/ProbablisticRoadMap/pyfastnns
36-
url = https://github.com/AtsushiSakai/pyfastnns
6.46 MB
Loading

PathPlanning/ProbabilisticRoadMap/probabilistic_road_map.py

Lines changed: 112 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,21 @@
99
import random
1010
import math
1111
import numpy as np
12+
import scipy.spatial
1213
import matplotlib.pyplot as plt
13-
from matplotrecorder import matplotrecorder
14-
from pyfastnns import pyfastnns
15-
matplotrecorder.donothing = True
1614

1715
# 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
2018
MAX_EDGE_LEN = 30.0 # [m] Maximum edge length
2119

20+
show_animation = True
21+
2222

2323
class Node:
24+
"""
25+
Node class for dijkstra search
26+
"""
2427

2528
def __init__(self, x, y, cost, pind):
2629
self.x = x
@@ -32,37 +35,120 @@ def __str__(self):
3235
return str(self.x) + "," + str(self.y) + "," + str(self.cost) + "," + str(self.pind)
3336

3437

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+
3578
def PRM_planning(sx, sy, gx, gy, ox, oy, rr):
3679

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)
3981

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)
4187

4288
rx, ry = dijkstra_planning(
4389
sx, sy, gx, gy, ox, oy, rr, road_map, sample_x, sample_y)
4490

4591
return rx, ry
4692

4793

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+
"""
49132

50133
road_map = []
51134
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)
53136

54137
for (i, ix, iy) in zip(range(nsample), sample_x, sample_y):
55138

56-
index = skdtree.search(
139+
index, dists = skdtree.search(
57140
np.matrix([ix, iy]).T, k=nsample)
141+
inds = index[0][0]
58142
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]]
59148

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])
63151

64-
# if !is_collision(ix, iy, nx, ny, rr, okdtree)
65-
edge_id.append(index[0][0][0][ii])
66152
if len(edge_id) >= N_KNN:
67153
break
68154

@@ -94,21 +180,16 @@ def dijkstra_planning(sx, sy, gx, gy, ox, oy, rr, road_map, sample_x, sample_y):
94180
print("Cannot find path")
95181
break
96182

97-
print(len(openset), len(closedset))
98-
99183
c_id = min(openset, key=lambda o: openset[o].cost)
100184
current = openset[c_id]
101-
print("current", current, c_id)
102-
# input()
103185

104186
# 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")
107189
plt.pause(0.001)
108-
matplotrecorder.save_frame()
109190

110191
if c_id == (len(road_map) - 1):
111-
print("Find goal")
192+
print("goal is found!")
112193
ngoal.pind = current.pind
113194
ngoal.cost = current.cost
114195
break
@@ -121,16 +202,12 @@ def dijkstra_planning(sx, sy, gx, gy, ox, oy, rr, road_map, sample_x, sample_y):
121202
# expand search grid based on motion model
122203
for i in range(len(road_map[c_id])):
123204
n_id = road_map[c_id][i]
124-
print(i, n_id)
125205
dx = sample_x[n_id] - current.x
126206
dy = sample_y[n_id] - current.y
127207
d = math.sqrt(dx**2 + dy**2)
128208
node = Node(sample_x[n_id], sample_y[n_id],
129209
current.cost + d, c_id)
130210

131-
# if not verify_node(node, obmap, minx, miny, maxx, maxy):
132-
# continue
133-
134211
if n_id in closedset:
135212
continue
136213
# Otherwise if it is already in the open set
@@ -163,21 +240,19 @@ def plot_road_map(road_map, sample_x, sample_y):
163240
[sample_y[i], sample_y[ind]], "-k")
164241

165242

166-
def sample_points(sx, sy, gx, gy, rr, ox, oy):
243+
def sample_points(sx, sy, gx, gy, rr, ox, oy, obkdtree):
167244
maxx = max(ox)
168245
maxy = max(oy)
169246
minx = min(ox)
170247
miny = min(oy)
171248

172249
sample_x, sample_y = [], []
173250

174-
nns = pyfastnns.NNS(np.vstack((ox, oy)).T)
175-
176251
while len(sample_x) <= N_SAMPLE:
177252
tx = (random.random() - minx) * (maxx - minx)
178253
ty = (random.random() - miny) * (maxy - miny)
179254

180-
index, dist = nns.search(np.matrix([tx, ty]).T)
255+
index, dist = obkdtree.search(np.matrix([tx, ty]).T)
181256

182257
if dist[0] >= rr:
183258
sample_x.append(tx)
@@ -224,20 +299,19 @@ def main():
224299
oy.append(60.0 - i)
225300

226301
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")
229304
plt.grid(True)
230305
plt.axis("equal")
231306

232307
rx, ry = PRM_planning(sx, sy, gx, gy, ox, oy, robot_size)
233308

234309
plt.plot(rx, ry, "-r")
235310

236-
for i in range(20):
237-
matplotrecorder.save_frame()
238-
plt.show()
311+
assert len(rx) != 0, 'Cannot found path'
239312

240-
matplotrecorder.save_movie("animation.gif", 0.1)
313+
if show_animation:
314+
plt.show()
241315

242316

243317
if __name__ == '__main__':

0 commit comments

Comments
 (0)