Skip to content

Commit bbe005a

Browse files
committed
Fix: Include robot_radius in path_smoothing collision check
1 parent 4ffd8e7 commit bbe005a

File tree

1 file changed

+59
-27
lines changed

1 file changed

+59
-27
lines changed

PathPlanning/RRT/rrt_with_pathsmoothing.py

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -51,30 +51,60 @@ def get_target_point(path, targetL):
5151
return [x, y, ti]
5252

5353

54-
def line_collision_check(first, second, obstacleList):
55-
# Line Equation
56-
57-
x1 = first[0]
58-
y1 = first[1]
59-
x2 = second[0]
60-
y2 = second[1]
61-
62-
try:
63-
a = y2 - y1
64-
b = -(x2 - x1)
65-
c = y2 * (x2 - x1) - x2 * (y2 - y1)
66-
except ZeroDivisionError:
67-
return False
68-
69-
for (ox, oy, size) in obstacleList:
70-
d = abs(a * ox + b * oy + c) / (math.hypot(a, b))
71-
if d <= size:
72-
return False
73-
74-
return True # OK
75-
76-
77-
def path_smoothing(path, max_iter, obstacle_list):
54+
def line_collision_check(first, second, obstacle_list, robot_radius=0.0):
55+
"""
56+
Check if the line segment between `first` and `second` collides with any obstacle.
57+
Considers the robot_radius by inflating the obstacle size.
58+
"""
59+
x1, y1 = first[0], first[1]
60+
x2, y2 = second[0], second[1]
61+
62+
dx = x2 - x1
63+
dy = y2 - y1
64+
length = math.hypot(dx, dy)
65+
66+
if length == 0:
67+
return True # Degenerate case
68+
69+
steps = int(length / 0.2) + 1 # Sampling every 0.2m along the segment
70+
71+
for i in range(steps + 1):
72+
t = i / steps
73+
x = x1 + t * dx
74+
y = y1 + t * dy
75+
76+
for (ox, oy, size) in obstacle_list:
77+
d = math.hypot(ox - x, oy - y)
78+
if d <= size + robot_radius:
79+
return False # Collision
80+
81+
return True # Safe
82+
83+
84+
def path_smoothing(path, max_iter, obstacle_list, robot_radius=0.0):
85+
"""
86+
Smooths a given path by iteratively replacing segments with shortcut connections,
87+
while ensuring the new segments are collision-free.
88+
89+
The algorithm randomly picks two points along the original path and attempts to
90+
connect them with a straight line. If the line does not collide with any obstacles
91+
(considering the robot's radius), the intermediate path points between them are
92+
replaced with the direct connection.
93+
94+
Args:
95+
path (List[List[float]]): The original path as a list of [x, y] coordinates.
96+
max_iter (int): Number of iterations for smoothing attempts.
97+
obstacle_list (List[Tuple[float, float, float]]): List of obstacles represented as
98+
(x, y, radius).
99+
robot_radius (float, optional): Radius of the robot, used to inflate obstacle size
100+
during collision checking. Defaults to 0.0.
101+
102+
Returns:
103+
List[List[float]]: The smoothed path as a list of [x, y] coordinates.
104+
105+
Example:
106+
>>> smoothed = path_smoothing(path, 1000, obstacle_list, robot_radius=0.5)
107+
"""
78108
le = get_path_length(path)
79109

80110
for i in range(max_iter):
@@ -94,7 +124,7 @@ def path_smoothing(path, max_iter, obstacle_list):
94124
continue
95125

96126
# collision check
97-
if not line_collision_check(first, second, obstacle_list):
127+
if not line_collision_check(first, second, obstacle_list, robot_radius):
98128
continue
99129

100130
# Create New path
@@ -121,12 +151,14 @@ def main():
121151
(9, 5, 2)
122152
] # [x,y,size]
123153
rrt = RRT(start=[0, 0], goal=[6, 10],
124-
rand_area=[-2, 15], obstacle_list=obstacleList)
154+
rand_area=[-2, 15], obstacle_list=obstacleList,
155+
robot_radius=0.3)
125156
path = rrt.planning(animation=show_animation)
126157

127158
# Path smoothing
128159
maxIter = 1000
129-
smoothedPath = path_smoothing(path, maxIter, obstacleList)
160+
smoothedPath = path_smoothing(path, maxIter, obstacleList,
161+
robot_radius=rrt.robot_radius)
130162

131163
# Draw final path
132164
if show_animation:

0 commit comments

Comments
 (0)