66
77"""
88
9- import copy
109import math
1110import os
1211import sys
@@ -29,21 +28,20 @@ class RRTStar(RRT):
2928 Class for RRT Star planning
3029 """
3130
32- class Node :
31+ class Node ( RRT . Node ) :
3332 def __init__ (self , x , y ):
34- self .x = x
35- self .y = y
33+ super ().__init__ (x , y )
3634 self .cost = 0.0
37- self .parent = None
3835
3936 def __init__ (self , start , goal , obstacle_list , rand_area ,
40- expand_dis = 0.5 ,
37+ expand_dis = 3.0 ,
38+ path_resolution = 1.0 ,
4139 goal_sample_rate = 20 ,
42- max_iter = 500 ,
40+ max_iter = 300 ,
4341 connect_circle_dist = 50.0
4442 ):
4543 super ().__init__ (start , goal , obstacle_list ,
46- rand_area , expand_dis , goal_sample_rate , max_iter )
44+ rand_area , expand_dis , path_resolution , goal_sample_rate , max_iter )
4745 """
4846 Setting Parameter
4947
@@ -65,11 +63,12 @@ def planning(self, animation=True, search_until_maxiter=True):
6563
6664 self .node_list = [self .start ]
6765 for i in range (self .max_iter ):
68- rnd = self .get_random_point ()
66+ print (i , len (self .node_list ))
67+ rnd = self .get_random_node ()
6968 nearest_ind = self .get_nearest_list_index (self .node_list , rnd )
70- new_node = self .steer (rnd , self .node_list [nearest_ind ])
69+ new_node = self .steer (self .node_list [nearest_ind ], rnd , self . expand_dis )
7170
72- if self .check_collision (new_node , self .obstacleList ):
71+ if self .check_collision (new_node , self .obstacle_list ):
7372 near_inds = self .find_near_nodes (new_node )
7473 new_node = self .choose_parent (new_node , near_inds )
7574 if new_node :
@@ -79,7 +78,7 @@ def planning(self, animation=True, search_until_maxiter=True):
7978 if animation and i % 5 == 0 :
8079 self .draw_graph (rnd )
8180
82- if not search_until_maxiter and new_node : # check reaching the goal
81+ if ( not search_until_maxiter ) and new_node : # check reaching the goal
8382 d , _ = self .calc_distance_and_angle (new_node , self .end )
8483 if d <= self .expand_dis :
8584 return self .generate_final_course (len (self .node_list ) - 1 )
@@ -92,16 +91,36 @@ def planning(self, animation=True, search_until_maxiter=True):
9291
9392 return None
9493
94+ def connect_nodes (self , from_node , to_node ):
95+ new_node = self .Node (from_node .x , from_node .y )
96+ d , theta = self .calc_distance_and_angle (new_node , to_node )
97+
98+ new_node .path_x = [new_node .x ]
99+ new_node .path_y = [new_node .y ]
100+
101+ n_expand = math .floor (d / self .path_resolution )
102+
103+ for _ in range (n_expand ):
104+ new_node .x += self .path_resolution * math .cos (theta )
105+ new_node .y += self .path_resolution * math .sin (theta )
106+ new_node .path_x .append (new_node .x )
107+ new_node .path_y .append (new_node .y )
108+
109+ new_node .parent = from_node
110+
111+ return new_node
112+
95113 def choose_parent (self , new_node , near_inds ):
96114 if not near_inds :
97115 return None
98116
99117 # search nearest cost in near_inds
100118 costs = []
101119 for i in near_inds :
102- d , theta = self .calc_distance_and_angle (self .node_list [i ], new_node )
103- if self .check_collision_extend (self .node_list [i ], theta , d ):
104- costs .append (self .node_list [i ].cost + d )
120+ near_node = self .node_list [i ]
121+ t_node = self .steer (near_node , new_node )
122+ if self .check_collision (t_node , self .obstacle_list ):
123+ costs .append (self .calc_new_cost (near_node , new_node ))
105124 else :
106125 costs .append (float ("inf" )) # the cost of collision node
107126 min_cost = min (costs )
@@ -110,9 +129,10 @@ def choose_parent(self, new_node, near_inds):
110129 print ("There is no good path.(min_cost is inf)" )
111130 return None
112131
113- new_node .cost = min_cost
114132 min_ind = near_inds [costs .index (min_cost )]
115133 new_node .parent = self .node_list [min_ind ]
134+ new_node = self .steer (new_node .parent , new_node )
135+ new_node .cost = min_cost
116136
117137 return new_node
118138
@@ -141,34 +161,27 @@ def find_near_nodes(self, new_node):
141161 def rewire (self , new_node , near_inds ):
142162 for i in near_inds :
143163 near_node = self .node_list [i ]
144- d , theta = self .calc_distance_and_angle (near_node , new_node )
145- new_cost = new_node .cost + d
164+ edge_node = self .steer (new_node , near_node )
165+ edge_node .cost = self .calc_new_cost (near_node , new_node )
166+
167+ no_collision = self .check_collision (edge_node , self .obstacle_list )
168+ improved_cost = near_node .cost > edge_node .cost
169+
170+ if no_collision and improved_cost :
171+ near_node .parent = new_node
172+ near_node .cost = edge_node .cost
173+ self .propagate_cost_to_leaves (new_node )
146174
147- if near_node .cost > new_cost :
148- if self .check_collision_extend (near_node , theta , d ):
149- near_node .parent = new_node
150- near_node .cost = new_cost
151- self .propagate_cost_to_leaves (new_node )
175+ def calc_new_cost (self , from_node , to_node ):
176+ d , _ = self .calc_distance_and_angle (from_node , to_node )
177+ return from_node .cost + d
152178
153179 def propagate_cost_to_leaves (self , parent_node ):
154180 for node in self .node_list :
155181 if node .parent == parent_node :
156- d , _ = self .calc_distance_and_angle (parent_node , node )
157- node .cost = parent_node .cost + d
182+ node .cost = self .calc_new_cost (parent_node , node )
158183 self .propagate_cost_to_leaves (node )
159184
160- def check_collision_extend (self , near_node , theta , d ):
161-
162- tmp_node = copy .deepcopy (near_node )
163-
164- for i in range (int (d / self .expand_dis )):
165- tmp_node .x += self .expand_dis * math .cos (theta )
166- tmp_node .y += self .expand_dis * math .sin (theta )
167- if not self .check_collision (tmp_node , self .obstacleList ):
168- return False
169-
170- return True
171-
172185
173186def main ():
174187 print ("Start " + __file__ )
@@ -184,11 +197,11 @@ def main():
184197 ] # [x,y,size(radius)]
185198
186199 # Set Initial parameters
187- rrt = RRTStar (start = [0 , 0 ],
188- goal = [10 , 10 ],
189- rand_area = [- 2 , 15 ],
190- obstacle_list = obstacle_list )
191- path = rrt .planning (animation = show_animation , search_until_maxiter = False )
200+ rrt_star = RRTStar (start = [0 , 0 ],
201+ goal = [10 , 10 ],
202+ rand_area = [- 2 , 15 ],
203+ obstacle_list = obstacle_list )
204+ path = rrt_star .planning (animation = show_animation )
192205
193206 if path is None :
194207 print ("Cannot find path" )
@@ -197,7 +210,7 @@ def main():
197210
198211 # Draw final path
199212 if show_animation :
200- rrt .draw_graph ()
213+ rrt_star .draw_graph ()
201214 plt .plot ([x for (x , y ) in path ], [y for (x , y ) in path ], '-r' )
202215 plt .grid (True )
203216 plt .pause (0.01 ) # Need for Mac
0 commit comments