Skip to content

Commit f57fb4f

Browse files
committed
Test: Add unit test to verify smoothed path respects robot_radius
1 parent bbe005a commit f57fb4f

File tree

2 files changed

+89
-8
lines changed

2 files changed

+89
-8
lines changed

PathPlanning/RRT/rrt_with_pathsmoothing.py

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,44 @@ def get_target_point(path, targetL):
5151
return [x, y, ti]
5252

5353

54-
def line_collision_check(first, second, obstacle_list, robot_radius=0.0):
54+
def is_point_collision(x, y, obstacle_list, robot_radius):
55+
"""
56+
Check whether a single point collides with any obstacle.
57+
58+
This function calculates the Euclidean distance between the given point (x, y)
59+
and each obstacle center. If the distance is less than or equal to the sum of
60+
the obstacle's radius and the robot's radius, a collision is detected.
61+
62+
Args:
63+
x (float): X-coordinate of the point to check.
64+
y (float): Y-coordinate of the point to check.
65+
obstacle_list (List[Tuple[float, float, float]]): List of obstacles defined as (ox, oy, radius).
66+
robot_radius (float): Radius of the robot, used to inflate the obstacles.
67+
68+
Returns:
69+
bool: True if the point is in collision with any obstacle, False otherwise.
70+
"""
71+
for (ox, oy, obstacle_radius) in obstacle_list:
72+
d = math.hypot(ox - x, oy - y)
73+
if d <= obstacle_radius + robot_radius:
74+
return True # Collided
75+
return False
76+
77+
78+
def line_collision_check(first, second, obstacle_list, robot_radius=0.0, sample_step=0.2):
5579
"""
5680
Check if the line segment between `first` and `second` collides with any obstacle.
5781
Considers the robot_radius by inflating the obstacle size.
82+
83+
Args:
84+
first (List[float]): Start point of the line [x, y]
85+
second (List[float]): End point of the line [x, y]
86+
obstacle_list (List[Tuple[float, float, float]]): Obstacles as (x, y, radius)
87+
robot_radius (float): Radius of robot
88+
sample_step (float): Distance between sampling points along the segment
89+
90+
Returns:
91+
bool: True if collision-free, False otherwise
5892
"""
5993
x1, y1 = first[0], first[1]
6094
x2, y2 = second[0], second[1]
@@ -64,19 +98,18 @@ def line_collision_check(first, second, obstacle_list, robot_radius=0.0):
6498
length = math.hypot(dx, dy)
6599

66100
if length == 0:
67-
return True # Degenerate case
101+
# Degenerate case: point collision check
102+
return not is_point_collision(x1, y1, obstacle_list, robot_radius)
68103

69-
steps = int(length / 0.2) + 1 # Sampling every 0.2m along the segment
104+
steps = int(length / sample_step) + 1 # Sampling every sample_step along the segment
70105

71106
for i in range(steps + 1):
72107
t = i / steps
73108
x = x1 + t * dx
74109
y = y1 + t * dy
75110

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
111+
if is_point_collision(x, y, obstacle_list, robot_radius):
112+
return False # Collision found
80113

81114
return True # Safe
82115

@@ -149,7 +182,7 @@ def main():
149182
(3, 10, 2),
150183
(7, 5, 2),
151184
(9, 5, 2)
152-
] # [x,y,size]
185+
] # [x,y,radius]
153186
rrt = RRT(start=[0, 0], goal=[6, 10],
154187
rand_area=[-2, 15], obstacle_list=obstacleList,
155188
robot_radius=0.3)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import conftest
2+
import math
3+
4+
from PathPlanning.RRT import rrt_with_pathsmoothing as rrt_module
5+
6+
def test_smoothed_path_safety():
7+
# Define test environment
8+
obstacle_list = [
9+
(5, 5, 1.0),
10+
(3, 6, 2.0),
11+
(3, 8, 2.0),
12+
(3, 10, 2.0),
13+
(7, 5, 2.0),
14+
(9, 5, 2.0)
15+
]
16+
robot_radius = 0.5
17+
18+
# Disable animation for testing
19+
rrt_module.show_animation = False
20+
21+
# Create RRT planner
22+
rrt = rrt_module.RRT(
23+
start=[0, 0],
24+
goal=[6, 10],
25+
rand_area=[-2, 15],
26+
obstacle_list=obstacle_list,
27+
robot_radius=robot_radius
28+
)
29+
30+
# Run RRT
31+
path = rrt.planning(animation=False)
32+
33+
# Smooth the path
34+
smoothed = rrt_module.path_smoothing(path, max_iter=1000,
35+
obstacle_list=obstacle_list,
36+
robot_radius=robot_radius)
37+
38+
# Check if all points on the smoothed path are safely distant from obstacles
39+
for x, y in smoothed:
40+
for ox, oy, obs_radius in obstacle_list:
41+
d = math.hypot(x - ox, y - oy)
42+
min_safe_dist = obs_radius + robot_radius
43+
assert d > min_safe_dist, \
44+
f"Point ({x:.2f}, {y:.2f}) too close to obstacle at ({ox}, {oy})"
45+
46+
47+
if __name__ == '__main__':
48+
conftest.run_this_test(__file__)

0 commit comments

Comments
 (0)