Skip to content

Commit 98d5851

Browse files
kadirhasKadir Haspalamutgil
andauthored
Utilize numpy to reduce calculation time (AtsushiSakai#767)
* Utilize numpy to reduce calculation time Change-Id: I6e421a1c2524a3d8f8875121a1a6d2ed832c3150 * styling updates to follow flake8 Change-Id: I909d49b40e6792efcb796846c97a0d984471d3c9 * improves readabilty for d_star_lite Change-Id: Ic329c2140f2200b49feeb03c588d7a805b96cbdc * removes self.detected_obstacles Change-Id: I4a0f2a424f17f44de3b444cb9c2e8e715d761d34 * styling for flake8 Change-Id: Id55c5972cbe76a2f6a69527dbf770f9bdf059109 Co-authored-by: Kadir Haspalamutgil <[email protected]>
1 parent ad4067d commit 98d5851

File tree

1 file changed

+62
-33
lines changed

1 file changed

+62
-33
lines changed

PathPlanning/DStarLite/d_star_lite.py

Lines changed: 62 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import math
1313
import matplotlib.pyplot as plt
1414
import random
15+
import numpy as np
1516

1617
show_animation = True
1718
pause_time = 0.001
@@ -62,32 +63,40 @@ def __init__(self, ox: list, oy: list):
6263
self.y_max = int(abs(max(oy) - self.y_min_world))
6364
self.obstacles = [Node(x - self.x_min_world, y - self.y_min_world)
6465
for x, y in zip(ox, oy)]
66+
self.obstacles_xy = np.array(
67+
[[obstacle.x, obstacle.y] for obstacle in self.obstacles]
68+
)
6569
self.start = Node(0, 0)
6670
self.goal = Node(0, 0)
6771
self.U = list() # type: ignore
6872
self.km = 0.0
6973
self.kold = 0.0
70-
self.rhs = list() # type: ignore
71-
self.g = list() # type: ignore
72-
self.detected_obstacles = list() # type: ignore
74+
self.rhs = self.create_grid(float("inf"))
75+
self.g = self.create_grid(float("inf"))
76+
self.detected_obstacles_xy = np.empty((0, 2))
77+
self.xy = np.empty((0, 2))
7378
if show_animation:
7479
self.detected_obstacles_for_plotting_x = list() # type: ignore
7580
self.detected_obstacles_for_plotting_y = list() # type: ignore
81+
self.initialized = False
7682

7783
def create_grid(self, val: float):
78-
grid = list()
79-
for _ in range(0, self.x_max):
80-
grid_row = list()
81-
for _ in range(0, self.y_max):
82-
grid_row.append(val)
83-
grid.append(grid_row)
84-
return grid
84+
return np.full((self.x_max, self.y_max), val)
8585

8686
def is_obstacle(self, node: Node):
87-
return any([compare_coordinates(node, obstacle)
88-
for obstacle in self.obstacles]) or \
89-
any([compare_coordinates(node, obstacle)
90-
for obstacle in self.detected_obstacles])
87+
x = np.array([node.x])
88+
y = np.array([node.y])
89+
obstacle_x_equal = self.obstacles_xy[:, 0] == x
90+
obstacle_y_equal = self.obstacles_xy[:, 1] == y
91+
is_in_obstacles = (obstacle_x_equal & obstacle_y_equal).any()
92+
93+
is_in_detected_obstacles = False
94+
if self.detected_obstacles_xy.shape[0] > 0:
95+
is_x_equal = self.detected_obstacles_xy[:, 0] == x
96+
is_y_equal = self.detected_obstacles_xy[:, 1] == y
97+
is_in_detected_obstacles = (is_x_equal & is_y_equal).any()
98+
99+
return is_in_obstacles or is_in_detected_obstacles
91100

92101
def c(self, node1: Node, node2: Node):
93102
if self.is_obstacle(node2):
@@ -139,13 +148,16 @@ def initialize(self, start: Node, goal: Node):
139148
self.start.y = start.y - self.y_min_world
140149
self.goal.x = goal.x - self.x_min_world
141150
self.goal.y = goal.y - self.y_min_world
142-
self.U = list() # Would normally be a priority queue
143-
self.km = 0.0
144-
self.rhs = self.create_grid(math.inf)
145-
self.g = self.create_grid(math.inf)
146-
self.rhs[self.goal.x][self.goal.y] = 0
147-
self.U.append((self.goal, self.calculate_key(self.goal)))
148-
self.detected_obstacles = list()
151+
if not self.initialized:
152+
self.initialized = True
153+
print('Initializing')
154+
self.U = list() # Would normally be a priority queue
155+
self.km = 0.0
156+
self.rhs = self.create_grid(math.inf)
157+
self.g = self.create_grid(math.inf)
158+
self.rhs[self.goal.x][self.goal.y] = 0
159+
self.U.append((self.goal, self.calculate_key(self.goal)))
160+
self.detected_obstacles_xy = np.empty((0, 2))
149161

150162
def update_vertex(self, u: Node):
151163
if not compare_coordinates(u, self.goal):
@@ -167,26 +179,33 @@ def compare_keys(self, key_pair1: tuple[float, float],
167179

168180
def compute_shortest_path(self):
169181
self.U.sort(key=lambda x: x[1])
170-
while (len(self.U) > 0 and
171-
self.compare_keys(self.U[0][1],
172-
self.calculate_key(self.start))) or \
173-
self.rhs[self.start.x][self.start.y] != \
174-
self.g[self.start.x][self.start.y]:
182+
has_elements = len(self.U) > 0
183+
start_key_not_updated = self.compare_keys(
184+
self.U[0][1], self.calculate_key(self.start)
185+
)
186+
rhs_not_equal_to_g = self.rhs[self.start.x][self.start.y] != \
187+
self.g[self.start.x][self.start.y]
188+
while has_elements and start_key_not_updated or rhs_not_equal_to_g:
175189
self.kold = self.U[0][1]
176190
u = self.U[0][0]
177191
self.U.pop(0)
178192
if self.compare_keys(self.kold, self.calculate_key(u)):
179193
self.U.append((u, self.calculate_key(u)))
180194
self.U.sort(key=lambda x: x[1])
181-
elif self.g[u.x][u.y] > self.rhs[u.x][u.y]:
182-
self.g[u.x][u.y] = self.rhs[u.x][u.y]
195+
elif (self.g[u.x, u.y] > self.rhs[u.x, u.y]).any():
196+
self.g[u.x, u.y] = self.rhs[u.x, u.y]
183197
for s in self.pred(u):
184198
self.update_vertex(s)
185199
else:
186-
self.g[u.x][u.y] = math.inf
200+
self.g[u.x, u.y] = math.inf
187201
for s in self.pred(u) + [u]:
188202
self.update_vertex(s)
189203
self.U.sort(key=lambda x: x[1])
204+
start_key_not_updated = self.compare_keys(
205+
self.U[0][1], self.calculate_key(self.start)
206+
)
207+
rhs_not_equal_to_g = self.rhs[self.start.x][self.start.y] != \
208+
self.g[self.start.x][self.start.y]
190209

191210
def detect_changes(self):
192211
changed_vertices = list()
@@ -196,7 +215,12 @@ def detect_changes(self):
196215
compare_coordinates(spoofed_obstacle, self.goal):
197216
continue
198217
changed_vertices.append(spoofed_obstacle)
199-
self.detected_obstacles.append(spoofed_obstacle)
218+
self.detected_obstacles_xy = np.concatenate(
219+
(
220+
self.detected_obstacles_xy,
221+
[[spoofed_obstacle.x, spoofed_obstacle.y]]
222+
)
223+
)
200224
if show_animation:
201225
self.detected_obstacles_for_plotting_x.append(
202226
spoofed_obstacle.x + self.x_min_world)
@@ -210,14 +234,19 @@ def detect_changes(self):
210234
# Allows random generation of obstacles
211235
random.seed()
212236
if random.random() > 1 - p_create_random_obstacle:
213-
x = random.randint(0, self.x_max)
214-
y = random.randint(0, self.y_max)
237+
x = random.randint(0, self.x_max - 1)
238+
y = random.randint(0, self.y_max - 1)
215239
new_obs = Node(x, y)
216240
if compare_coordinates(new_obs, self.start) or \
217241
compare_coordinates(new_obs, self.goal):
218242
return changed_vertices
219243
changed_vertices.append(Node(x, y))
220-
self.detected_obstacles.append(Node(x, y))
244+
self.detected_obstacles_xy = np.concatenate(
245+
(
246+
self.detected_obstacles_xy,
247+
[[x, y]]
248+
)
249+
)
221250
if show_animation:
222251
self.detected_obstacles_for_plotting_x.append(x +
223252
self.x_min_world)

0 commit comments

Comments
 (0)