Skip to content

Commit a36ddb4

Browse files
authored
use scipy kd-tree directly (AtsushiSakai#337)
1 parent b8afdb1 commit a36ddb4

File tree

5 files changed

+31
-164
lines changed

5 files changed

+31
-164
lines changed

PathPlanning/HybridAStar/car.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def check_car_collision(x_list, y_list, yaw_list, ox, oy, kd_tree):
3131
cx = i_x + W_BUBBLE_DIST * cos(i_yaw)
3232
cy = i_y + W_BUBBLE_DIST * sin(i_yaw)
3333

34-
ids = kd_tree.search_in_distance([cx, cy], W_BUBBLE_R)
34+
ids = kd_tree.query_ball_point([cx, cy], W_BUBBLE_R)
3535

3636
if not ids:
3737
continue
@@ -71,7 +71,7 @@ def plot_arrow(x, y, yaw, length=1.0, width=0.5, fc="r", ec="k"):
7171
def plot_car(x, y, yaw):
7272
car_color = '-k'
7373
c, s = cos(yaw), sin(yaw)
74-
rot = Rot.from_euler('z', yaw).as_matrix()[0:2, 0:2]
74+
rot = Rot.from_euler('z', -yaw).as_matrix()[0:2, 0:2]
7575
car_outline_x, car_outline_y = [], []
7676
for rx, ry in zip(VRX, VRY):
7777
converted_xy = np.stack([rx, ry]).T @ rot

PathPlanning/HybridAStar/hybrid_a_star.py

Lines changed: 2 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
import matplotlib.pyplot as plt
1515
import numpy as np
16-
import scipy.spatial
16+
from scipy.spatial import cKDTree
1717

1818
sys.path.append(os.path.dirname(os.path.abspath(__file__))
1919
+ "/../ReedsSheppPath")
@@ -67,44 +67,6 @@ def __init__(self, x_list, y_list, yaw_list, direction_list, cost):
6767
self.cost = cost
6868

6969

70-
class KDTree:
71-
"""
72-
Nearest neighbor search class with KDTree
73-
"""
74-
75-
def __init__(self, data):
76-
# store kd-tree
77-
self.tree = scipy.spatial.cKDTree(data)
78-
79-
def search(self, inp, k=1):
80-
"""
81-
Search NN
82-
inp: input data, single frame or multi frame
83-
"""
84-
85-
if len(inp.shape) >= 2: # multi input
86-
index = []
87-
dist = []
88-
89-
for i in inp.T:
90-
i_dist, i_index = self.tree.query(i, k=k)
91-
index.append(i_index)
92-
dist.append(i_dist)
93-
94-
return index, dist
95-
96-
dist, index = self.tree.query(inp, k=k)
97-
return index, dist
98-
99-
def search_in_distance(self, inp, r):
100-
"""
101-
find points with in a distance r
102-
"""
103-
104-
index = self.tree.query_ball_point(inp, r)
105-
return index
106-
107-
10870
class Config:
10971

11072
def __init__(self, ox, oy, xy_resolution, yaw_resolution):
@@ -297,7 +259,7 @@ def hybrid_a_star_planning(start, goal, ox, oy, xy_resolution, yaw_resolution):
297259
start[2], goal[2] = rs.pi_2_pi(start[2]), rs.pi_2_pi(goal[2])
298260
tox, toy = ox[:], oy[:]
299261

300-
obstacle_kd_tree = KDTree(np.vstack((tox, toy)).T)
262+
obstacle_kd_tree = cKDTree(np.vstack((tox, toy)).T)
301263

302264
config = Config(tox, toy, xy_resolution, yaw_resolution)
303265

PathPlanning/ProbabilisticRoadMap/probabilistic_road_map.py

Lines changed: 14 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
import random
1010
import math
1111
import numpy as np
12-
import scipy.spatial
1312
import matplotlib.pyplot as plt
13+
from scipy.spatial import cKDTree
1414

1515
# parameter
1616
N_SAMPLE = 500 # number of sample_points
@@ -36,49 +36,9 @@ def __str__(self):
3636
str(self.cost) + "," + str(self.parent_index)
3737

3838

39-
class KDTree:
40-
"""
41-
Nearest neighbor search class with KDTree
42-
"""
43-
44-
def __init__(self, data):
45-
# store kd-tree
46-
self.tree = scipy.spatial.cKDTree(data)
47-
48-
def search(self, inp, k=1):
49-
"""
50-
Search NN
51-
52-
inp: input data, single frame or multi frame
53-
54-
"""
55-
56-
if len(inp.shape) >= 2: # multi input
57-
index = []
58-
dist = []
59-
60-
for i in inp.T:
61-
i_dist, i_index = self.tree.query(i, k=k)
62-
index.append(i_index)
63-
dist.append(i_dist)
64-
65-
return index, dist
66-
67-
dist, index = self.tree.query(inp, k=k)
68-
return index, dist
69-
70-
def search_in_distance(self, inp, r):
71-
"""
72-
find points with in a distance r
73-
"""
74-
75-
index = self.tree.query_ball_point(inp, r)
76-
return index
77-
78-
7939
def prm_planning(sx, sy, gx, gy, ox, oy, rr):
8040

81-
obstacle_kd_tree = KDTree(np.vstack((ox, oy)).T)
41+
obstacle_kd_tree = cKDTree(np.vstack((ox, oy)).T)
8242

8343
sample_x, sample_y = sample_points(sx, sy, gx, gy,
8444
rr, ox, oy, obstacle_kd_tree)
@@ -108,15 +68,15 @@ def is_collision(sx, sy, gx, gy, rr, obstacle_kd_tree):
10868
n_step = round(d / D)
10969

11070
for i in range(n_step):
111-
_, dist = obstacle_kd_tree.search(np.array([x, y]).reshape(2, 1))
112-
if dist[0] <= rr:
71+
dist, _ = obstacle_kd_tree.query([x, y])
72+
if dist <= rr:
11373
return True # collision
11474
x += D * math.cos(yaw)
11575
y += D * math.sin(yaw)
11676

11777
# goal point check
118-
_, dist = obstacle_kd_tree.search(np.array([gx, gy]).reshape(2, 1))
119-
if dist[0] <= rr:
78+
dist, _ = obstacle_kd_tree.query([gx, gy])
79+
if dist <= rr:
12080
return True # collision
12181

12282
return False # OK
@@ -134,22 +94,19 @@ def generate_road_map(sample_x, sample_y, rr, obstacle_kd_tree):
13494

13595
road_map = []
13696
n_sample = len(sample_x)
137-
sample_kd_tree = KDTree(np.vstack((sample_x, sample_y)).T)
97+
sample_kd_tree = cKDTree(np.vstack((sample_x, sample_y)).T)
13898

13999
for (i, ix, iy) in zip(range(n_sample), sample_x, sample_y):
140100

141-
index, dists = sample_kd_tree.search(
142-
np.array([ix, iy]).reshape(2, 1), k=n_sample)
143-
inds = index[0]
101+
dists, indexes = sample_kd_tree.query([ix, iy], k=n_sample)
144102
edge_id = []
145-
# print(index)
146103

147-
for ii in range(1, len(inds)):
148-
nx = sample_x[inds[ii]]
149-
ny = sample_y[inds[ii]]
104+
for ii in range(1, len(indexes)):
105+
nx = sample_x[indexes[ii]]
106+
ny = sample_y[indexes[ii]]
150107

151108
if not is_collision(ix, iy, nx, ny, rr, obstacle_kd_tree):
152-
edge_id.append(inds[ii])
109+
edge_id.append(indexes[ii])
153110

154111
if len(edge_id) >= N_KNN:
155112
break
@@ -270,9 +227,9 @@ def sample_points(sx, sy, gx, gy, rr, ox, oy, obstacle_kd_tree):
270227
tx = (random.random() * (max_x - min_x)) + min_x
271228
ty = (random.random() * (max_y - min_y)) + min_y
272229

273-
index, dist = obstacle_kd_tree.search(np.array([tx, ty]).reshape(2, 1))
230+
dist, index = obstacle_kd_tree.query([tx, ty])
274231

275-
if dist[0] >= rr:
232+
if dist >= rr:
276233
sample_x.append(tx)
277234
sample_y.append(ty)
278235

PathPlanning/VoronoiRoadMap/kdtree.py

Lines changed: 0 additions & 49 deletions
This file was deleted.

PathPlanning/VoronoiRoadMap/voronoi_road_map.py

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@
88

99
import math
1010
import numpy as np
11-
import scipy.spatial
1211
import matplotlib.pyplot as plt
1312
from dijkstra_search import DijkstraSearch
14-
from kdtree import KDTree
13+
from scipy.spatial import cKDTree, Voronoi
1514

1615
show_animation = True
1716

@@ -24,7 +23,7 @@ def __init__(self):
2423
self.MAX_EDGE_LEN = 30.0 # [m] Maximum edge length
2524

2625
def planning(self, sx, sy, gx, gy, ox, oy, robot_radius):
27-
obstacle_tree = KDTree(np.vstack((ox, oy)).T)
26+
obstacle_tree = cKDTree(np.vstack((ox, oy)).T)
2827

2928
sample_x, sample_y = self.voronoi_sampling(sx, sy, gx, gy, ox, oy)
3029
if show_animation: # pragma: no cover
@@ -53,15 +52,15 @@ def is_collision(self, sx, sy, gx, gy, rr, obstacle_kd_tree):
5352
n_step = round(d / D)
5453

5554
for i in range(n_step):
56-
ids, dist = obstacle_kd_tree.search(np.array([x, y]).reshape(2, 1))
57-
if dist[0] <= rr:
55+
dist, _ = obstacle_kd_tree.query([x, y])
56+
if dist <= rr:
5857
return True # collision
5958
x += D * math.cos(yaw)
6059
y += D * math.sin(yaw)
6160

6261
# goal point check
63-
ids, dist = obstacle_kd_tree.search(np.array([gx, gy]).reshape(2, 1))
64-
if dist[0] <= rr:
62+
dist, _ = obstacle_kd_tree.query([gx, gy])
63+
if dist <= rr:
6564
return True # collision
6665

6766
return False # OK
@@ -78,22 +77,20 @@ def generate_road_map_info(self, node_x, node_y, rr, obstacle_tree):
7877

7978
road_map = []
8079
n_sample = len(node_x)
81-
node_tree = KDTree(np.vstack((node_x, node_y)).T)
80+
node_tree = cKDTree(np.vstack((node_x, node_y)).T)
8281

8382
for (i, ix, iy) in zip(range(n_sample), node_x, node_y):
8483

85-
index, dists = node_tree.search(
86-
np.array([ix, iy]).reshape(2, 1), k=n_sample)
84+
dists, indexes = node_tree.query([ix, iy], k=n_sample)
8785

88-
inds = index[0]
8986
edge_id = []
9087

91-
for ii in range(1, len(inds)):
92-
nx = node_x[inds[ii]]
93-
ny = node_y[inds[ii]]
88+
for ii in range(1, len(indexes)):
89+
nx = node_x[indexes[ii]]
90+
ny = node_y[indexes[ii]]
9491

9592
if not self.is_collision(ix, iy, nx, ny, rr, obstacle_tree):
96-
edge_id.append(inds[ii])
93+
edge_id.append(indexes[ii])
9794

9895
if len(edge_id) >= self.N_KNN:
9996
break
@@ -119,7 +116,7 @@ def voronoi_sampling(sx, sy, gx, gy, ox, oy):
119116
oxy = np.vstack((ox, oy)).T
120117

121118
# generate voronoi point
122-
vor = scipy.spatial.Voronoi(oxy)
119+
vor = Voronoi(oxy)
123120
sample_x = [ix for [ix, _] in vor.vertices]
124121
sample_y = [iy for [_, iy] in vor.vertices]
125122

0 commit comments

Comments
 (0)