@@ -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