@@ -51,30 +51,60 @@ def get_target_point(path, targetL):
51
51
return [x , y , ti ]
52
52
53
53
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
+ """
78
108
le = get_path_length (path )
79
109
80
110
for i in range (max_iter ):
@@ -94,7 +124,7 @@ def path_smoothing(path, max_iter, obstacle_list):
94
124
continue
95
125
96
126
# collision check
97
- if not line_collision_check (first , second , obstacle_list ):
127
+ if not line_collision_check (first , second , obstacle_list , robot_radius ):
98
128
continue
99
129
100
130
# Create New path
@@ -121,12 +151,14 @@ def main():
121
151
(9 , 5 , 2 )
122
152
] # [x,y,size]
123
153
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 )
125
156
path = rrt .planning (animation = show_animation )
126
157
127
158
# Path smoothing
128
159
maxIter = 1000
129
- smoothedPath = path_smoothing (path , maxIter , obstacleList )
160
+ smoothedPath = path_smoothing (path , maxIter , obstacleList ,
161
+ robot_radius = rrt .robot_radius )
130
162
131
163
# Draw final path
132
164
if show_animation :
0 commit comments