12
12
13
13
import matplotlib .pyplot as plt
14
14
15
- sys .path .append (os .path .dirname (os .path .abspath (__file__ )) +
16
- "/../RRT/" )
15
+ sys .path .append (os .path .dirname (os .path .abspath (__file__ )) + "/../RRT/" )
17
16
18
17
try :
19
18
from rrt import RRT
@@ -33,15 +32,17 @@ def __init__(self, x, y):
33
32
super ().__init__ (x , y )
34
33
self .cost = 0.0
35
34
36
- def __init__ (self , start , goal , obstacle_list , rand_area ,
35
+ def __init__ (self ,
36
+ start ,
37
+ goal ,
38
+ obstacle_list ,
39
+ rand_area ,
37
40
expand_dis = 30.0 ,
38
41
path_resolution = 1.0 ,
39
42
goal_sample_rate = 20 ,
40
43
max_iter = 300 ,
41
- connect_circle_dist = 50.0
42
- ):
43
- super ().__init__ (start , goal , obstacle_list ,
44
- rand_area , expand_dis , path_resolution , goal_sample_rate , max_iter )
44
+ connect_circle_dist = 50.0 ,
45
+ search_until_max_iter = False ):
45
46
"""
46
47
Setting Parameter
47
48
@@ -51,35 +52,46 @@ def __init__(self, start, goal, obstacle_list, rand_area,
51
52
randArea:Random Sampling Area [min,max]
52
53
53
54
"""
55
+ super ().__init__ (start , goal , obstacle_list , rand_area , expand_dis ,
56
+ path_resolution , goal_sample_rate , max_iter )
54
57
self .connect_circle_dist = connect_circle_dist
55
58
self .goal_node = self .Node (goal [0 ], goal [1 ])
59
+ self .search_until_max_iter = search_until_max_iter
56
60
57
- def planning (self , animation = True , search_until_max_iter = True ):
61
+ def planning (self , animation = True ):
58
62
"""
59
63
rrt star path planning
60
64
61
- animation: flag for animation on or off
62
- search_until_max_iter: search until max iteration for path improving or not
65
+ animation: flag for animation on or off .
63
66
"""
64
67
65
68
self .node_list = [self .start ]
66
69
for i in range (self .max_iter ):
67
70
print ("Iter:" , i , ", number of nodes:" , len (self .node_list ))
68
71
rnd = self .get_random_node ()
69
72
nearest_ind = self .get_nearest_node_index (self .node_list , rnd )
70
- new_node = self .steer (self .node_list [nearest_ind ], rnd , self .expand_dis )
73
+ new_node = self .steer (self .node_list [nearest_ind ], rnd ,
74
+ self .expand_dis )
75
+ near_node = self .node_list [nearest_ind ]
76
+ new_node .cost = near_node .cost + \
77
+ math .hypot (new_node .x - near_node .x ,
78
+ new_node .y - near_node .y )
71
79
72
80
if self .check_collision (new_node , self .obstacle_list ):
73
81
near_inds = self .find_near_nodes (new_node )
74
- new_node = self .choose_parent (new_node , near_inds )
75
- if new_node :
82
+ node_with_updated_parent = self .choose_parent (
83
+ new_node , near_inds )
84
+ if node_with_updated_parent :
85
+ self .rewire (node_with_updated_parent , near_inds )
86
+ self .node_list .append (node_with_updated_parent )
87
+ else :
76
88
self .node_list .append (new_node )
77
- self .rewire (new_node , near_inds )
78
89
79
- if animation and i % 5 == 0 :
90
+ if animation :
80
91
self .draw_graph (rnd )
81
92
82
- if (not search_until_max_iter ) and new_node : # check reaching the goal
93
+ if ((not self .search_until_max_iter )
94
+ and new_node ): # if reaches goal
83
95
last_index = self .search_best_goal_node ()
84
96
if last_index is not None :
85
97
return self .generate_final_course (last_index )
@@ -93,6 +105,21 @@ def planning(self, animation=True, search_until_max_iter=True):
93
105
return None
94
106
95
107
def choose_parent (self , new_node , near_inds ):
108
+ """
109
+ Computes the cheapest point to new_node contained in the list
110
+ near_inds and set such a node as the parent of new_node.
111
+ Arguments:
112
+ --------
113
+ new_node, Node
114
+ randomly generated node with a path from its neared point
115
+ There are not coalitions between this node and th tree.
116
+ near_inds: list
117
+ Indices of indices of the nodes what are near to new_node
118
+
119
+ Returns.
120
+ ------
121
+ Node, a copy of new_node
122
+ """
96
123
if not near_inds :
97
124
return None
98
125
@@ -113,14 +140,18 @@ def choose_parent(self, new_node, near_inds):
113
140
114
141
min_ind = near_inds [costs .index (min_cost )]
115
142
new_node = self .steer (self .node_list [min_ind ], new_node )
116
- new_node .parent = self .node_list [min_ind ]
117
143
new_node .cost = min_cost
118
144
119
145
return new_node
120
146
121
147
def search_best_goal_node (self ):
122
- dist_to_goal_list = [self .calc_dist_to_goal (n .x , n .y ) for n in self .node_list ]
123
- goal_inds = [dist_to_goal_list .index (i ) for i in dist_to_goal_list if i <= self .expand_dis ]
148
+ dist_to_goal_list = [
149
+ self .calc_dist_to_goal (n .x , n .y ) for n in self .node_list
150
+ ]
151
+ goal_inds = [
152
+ dist_to_goal_list .index (i ) for i in dist_to_goal_list
153
+ if i <= self .expand_dis
154
+ ]
124
155
125
156
safe_goal_inds = []
126
157
for goal_ind in goal_inds :
@@ -139,17 +170,48 @@ def search_best_goal_node(self):
139
170
return None
140
171
141
172
def find_near_nodes (self , new_node ):
173
+ """
174
+ 1) defines a ball centered on new_node
175
+ 2) Returns all nodes of the three that are inside this ball
176
+ Arguments:
177
+ ---------
178
+ new_node: Node
179
+ new randomly generated node, without collisions between
180
+ its nearest node
181
+ Returns:
182
+ -------
183
+ list
184
+ List with the indices of the nodes inside the ball of
185
+ radius r
186
+ """
142
187
nnode = len (self .node_list ) + 1
143
188
r = self .connect_circle_dist * math .sqrt ((math .log (nnode ) / nnode ))
144
- # if expand_dist exists, search vertices in a range no more than expand_dist
145
- if hasattr (self , 'expand_dis' ):
189
+ # if expand_dist exists, search vertices in a range no more than
190
+ # expand_dist
191
+ if hasattr (self , 'expand_dis' ):
146
192
r = min (r , self .expand_dis )
147
- dist_list = [(node .x - new_node .x ) ** 2 +
148
- ( node . y - new_node . y ) ** 2 for node in self .node_list ]
149
- near_inds = [dist_list .index (i ) for i in dist_list if i <= r ** 2 ]
193
+ dist_list = [(node .x - new_node .x )** 2 + ( node . y - new_node . y ) ** 2
194
+ for node in self .node_list ]
195
+ near_inds = [dist_list .index (i ) for i in dist_list if i <= r ** 2 ]
150
196
return near_inds
151
197
152
198
def rewire (self , new_node , near_inds ):
199
+ """
200
+ For each node in near_inds, this will check if it is cheaper to
201
+ arrive to them from new_node.
202
+ In such a case, this will re-assign the parent of the nodes in
203
+ near_inds to new_node.
204
+ Parameters:
205
+ ----------
206
+ new_node, Node
207
+ Node randomly added which can be joined to the tree
208
+
209
+ near_inds, list of uints
210
+ A list of indices of the self.new_node which contains
211
+ nodes within a circle of a given radius.
212
+ Remark: parent is designated in choose_parent.
213
+
214
+ """
153
215
for i in near_inds :
154
216
near_node = self .node_list [i ]
155
217
edge_node = self .steer (new_node , near_node )
@@ -161,7 +223,12 @@ def rewire(self, new_node, near_inds):
161
223
improved_cost = near_node .cost > edge_node .cost
162
224
163
225
if no_collision and improved_cost :
164
- self .node_list [i ] = edge_node
226
+ near_node .x = edge_node .x
227
+ near_node .y = edge_node .y
228
+ near_node .cost = edge_node .cost
229
+ near_node .path_x = edge_node .path_x
230
+ near_node .path_y = edge_node .path_y
231
+ near_node .parent = edge_node .parent
165
232
self .propagate_cost_to_leaves (new_node )
166
233
167
234
def calc_new_cost (self , from_node , to_node ):
@@ -192,10 +259,12 @@ def main():
192
259
] # [x,y,size(radius)]
193
260
194
261
# Set Initial parameters
195
- rrt_star = RRTStar (start = [0 , 0 ],
196
- goal = [6 , 10 ],
197
- rand_area = [- 2 , 15 ],
198
- obstacle_list = obstacle_list )
262
+ rrt_star = RRTStar (
263
+ start = [0 , 0 ],
264
+ goal = [6 , 10 ],
265
+ rand_area = [- 2 , 15 ],
266
+ obstacle_list = obstacle_list ,
267
+ expand_dis = 1 )
199
268
path = rrt_star .planning (animation = show_animation )
200
269
201
270
if path is None :
@@ -206,10 +275,9 @@ def main():
206
275
# Draw final path
207
276
if show_animation :
208
277
rrt_star .draw_graph ()
209
- plt .plot ([x for (x , y ) in path ], [y for (x , y ) in path ], '-r ' )
278
+ plt .plot ([x for (x , y ) in path ], [y for (x , y ) in path ], 'r-- ' )
210
279
plt .grid (True )
211
- plt .pause (0.01 ) # Need for Mac
212
- plt .show ()
280
+ plt .show ()
213
281
214
282
215
283
if __name__ == '__main__' :
0 commit comments