Skip to content

Commit c1ba9ba

Browse files
fix check segment intersection with obstacle
The previous method only worked because the step that checked collision from a point of the line to obstacles was the same as the minimum obstacle radius. If the obstacle radius is very small a great amount of steps would be required. Thus It's better to check the distance from the segment to the obstacles directly and compare with obstacle radius Now there is no need to have two check functions.
1 parent 87a5517 commit c1ba9ba

File tree

1 file changed

+29
-25
lines changed

1 file changed

+29
-25
lines changed

PathPlanning/InformedRRTStar/informed_rrt_star.py

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,9 @@ def informed_rrt_star_search(self, animation=True):
7474
newNode = self.get_new_node(theta, nind, nearestNode)
7575
d = self.line_cost(nearestNode, newNode)
7676

77-
isCollision = self.collision_check(newNode, self.obstacle_list)
78-
isCollisionEx = self.check_collision_extend(nearestNode, theta, d)
77+
isCollision = self.check_collision(nearestNode, theta, d)
7978

80-
if isCollision and isCollisionEx:
79+
if isCollision:
8180
nearInds = self.find_near_nodes(newNode)
8281
newNode = self.choose_parent(newNode, nearInds)
8382

@@ -110,7 +109,7 @@ def choose_parent(self, newNode, nearInds):
110109
dy = newNode.y - self.node_list[i].y
111110
d = math.sqrt(dx ** 2 + dy ** 2)
112111
theta = math.atan2(dy, dx)
113-
if self.check_collision_extend(self.node_list[i], theta, d):
112+
if self.check_collision(self.node_list[i], theta, d):
114113
dList.append(self.node_list[i].cost + d)
115114
else:
116115
dList.append(float('inf'))
@@ -194,17 +193,6 @@ def get_nearest_list_index(nodes, rnd):
194193
minIndex = dList.index(min(dList))
195194
return minIndex
196195

197-
@staticmethod
198-
def collision_check(newNode, obstacleList):
199-
for (ox, oy, size) in obstacleList:
200-
dx = ox - newNode.x
201-
dy = oy - newNode.y
202-
d = dx * dx + dy * dy
203-
if d <= 1.1 * size ** 2:
204-
return False # collision
205-
206-
return True # safe
207-
208196
def get_new_node(self, theta, nind, nearestNode):
209197
newNode = copy.deepcopy(nearestNode)
210198

@@ -234,19 +222,35 @@ def rewire(self, newNode, nearInds):
234222
if nearNode.cost > scost:
235223
theta = math.atan2(newNode.y - nearNode.y,
236224
newNode.x - nearNode.x)
237-
if self.check_collision_extend(nearNode, theta, d):
225+
if self.check_collision(nearNode, theta, d):
238226
nearNode.parent = n_node - 1
239227
nearNode.cost = scost
240-
241-
def check_collision_extend(self, nearNode, theta, d):
228+
229+
@staticmethod
230+
def distance_squared_point_to_segment(v, w, p):
231+
# Return minimum distance between line segment vw and point p
232+
if (np.array_equal(v, w)):
233+
return (p-v).dot(p-v) # v == w case
234+
l2 = (w-v).dot(w-v) # i.e. |w-v|^2 - avoid a sqrt
235+
# Consider the line extending the segment, parameterized as v + t (w - v).
236+
# We find projection of point p onto the line.
237+
# It falls where t = [(p-v) . (w-v)] / |w-v|^2
238+
# We clamp t from [0,1] to handle points outside the segment vw.
239+
t = max(0, min(1, (p - v).dot(w - v) / l2))
240+
projection = v + t * (w - v) # Projection falls on the segment
241+
return (p-projection).dot(p-projection)
242+
243+
def check_collision(self, nearNode, theta, d):
242244
tmpNode = copy.deepcopy(nearNode)
243-
244-
for i in range(int(d / self.expand_dis)):
245-
tmpNode.x += self.expand_dis * math.cos(theta)
246-
tmpNode.y += self.expand_dis * math.sin(theta)
247-
if not self.collision_check(tmpNode, self.obstacle_list):
248-
return False
249-
245+
endx = tmpNode.x + math.cos(theta)*d
246+
endy = tmpNode.y + math.sin(theta)*d
247+
for (ox, oy, size) in self.obstacle_list:
248+
dd = self.distance_squared_point_to_segment(
249+
np.array([tmpNode.x, tmpNode.y]),
250+
np.array([endx, endy]),
251+
np.array([ox, oy]))
252+
if dd <= 1.1 * size**2:
253+
return False # collision
250254
return True
251255

252256
def get_final_course(self, lastIndex):

0 commit comments

Comments
 (0)