1- #!/usr/bin/python
2- # -*- coding: utf-8 -*-
3- u"""
4- @brief: Path Planning Sample Code with Randamized Rapidly-Exploring Random Trees (RRT)
5-
6- @author: AtsushiSakai
1+ """
2+ Path Planning Sample Code with Randamized Rapidly-Exploring Random Trees (RRT)
73
8- @license: MIT
4+ @author: AtsushiSakai(@Atsushi_twi)
95
106"""
117
8+ import matplotlib .pyplot as plt
129import random
1310import math
1411import copy
1512
13+ show_animation = True
14+
15+
1616class RRT ():
17- u """
17+ """
1818 Class for RRT Planning
1919 """
2020
21- def __init__ (self , start , goal , obstacleList ,randArea ,expandDis = 1.0 ,goalSampleRate = 5 ,maxIter = 500 ):
22- u """
21+ def __init__ (self , start , goal , obstacleList , randArea , expandDis = 1.0 , goalSampleRate = 5 , maxIter = 500 ):
22+ """
2323 Setting Parameter
2424
2525 start:Start Position [x,y]
@@ -28,17 +28,18 @@ def __init__(self, start, goal, obstacleList,randArea,expandDis=1.0,goalSampleRa
2828 randArea:Ramdom Samping Area [min,max]
2929
3030 """
31- self .start = Node (start [0 ],start [1 ])
32- self .end = Node (goal [0 ],goal [1 ])
31+ self .start = Node (start [0 ], start [1 ])
32+ self .end = Node (goal [0 ], goal [1 ])
3333 self .minrand = randArea [0 ]
3434 self .maxrand = randArea [1 ]
3535 self .expandDis = expandDis
3636 self .goalSampleRate = goalSampleRate
3737 self .maxIter = maxIter
38+ self .obstacleList = obstacleList
3839
39- def Planning (self ,animation = True ):
40- u """
41- Pathplanning
40+ def Planning (self , animation = True ):
41+ """
42+ Pathplanning
4243
4344 animation: flag for animation on or off
4445 """
@@ -47,7 +48,8 @@ def Planning(self,animation=True):
4748 while True :
4849 # Random Sampling
4950 if random .randint (0 , 100 ) > self .goalSampleRate :
50- rnd = [random .uniform (self .minrand , self .maxrand ), random .uniform (self .minrand , self .maxrand )]
51+ rnd = [random .uniform (self .minrand , self .maxrand ), random .uniform (
52+ self .minrand , self .maxrand )]
5153 else :
5254 rnd = [self .end .x , self .end .y ]
5355
@@ -56,15 +58,15 @@ def Planning(self,animation=True):
5658 # print(nind)
5759
5860 # expand tree
59- nearestNode = self .nodeList [nind ]
61+ nearestNode = self .nodeList [nind ]
6062 theta = math .atan2 (rnd [1 ] - nearestNode .y , rnd [0 ] - nearestNode .x )
6163
6264 newNode = copy .deepcopy (nearestNode )
6365 newNode .x += self .expandDis * math .cos (theta )
6466 newNode .y += self .expandDis * math .sin (theta )
6567 newNode .parent = nind
6668
67- if not self .__CollisionCheck (newNode , obstacleList ):
69+ if not self .__CollisionCheck (newNode , self . obstacleList ):
6870 continue
6971
7072 self .nodeList .append (newNode )
@@ -80,43 +82,43 @@ def Planning(self,animation=True):
8082 if animation :
8183 self .DrawGraph (rnd )
8284
83-
84- path = [[self .end .x ,self .end .y ]]
85+ path = [[self .end .x , self .end .y ]]
8586 lastIndex = len (self .nodeList ) - 1
8687 while self .nodeList [lastIndex ].parent is not None :
8788 node = self .nodeList [lastIndex ]
88- path .append ([node .x ,node .y ])
89+ path .append ([node .x , node .y ])
8990 lastIndex = node .parent
9091 path .append ([self .start .x , self .start .y ])
9192
9293 return path
9394
94- def DrawGraph (self ,rnd = None ):
95- import matplotlib .pyplot as plt
95+ def DrawGraph (self , rnd = None ):
9696 plt .clf ()
9797 if rnd is not None :
9898 plt .plot (rnd [0 ], rnd [1 ], "^k" )
9999 for node in self .nodeList :
100100 if node .parent is not None :
101- plt .plot ([node .x , self .nodeList [node .parent ].x ], [node .y , self .nodeList [node .parent ].y ], "-g" )
102- for (x ,y ,size ) in obstacleList :
103- self .PlotCircle (x ,y ,size )
101+ plt .plot ([node .x , self .nodeList [node .parent ].x ], [
102+ node .y , self .nodeList [node .parent ].y ], "-g" )
103+ for (x , y , size ) in self .obstacleList :
104+ self .PlotCircle (x , y , size )
104105
105106 plt .plot (self .start .x , self .start .y , "xr" )
106107 plt .plot (self .end .x , self .end .y , "xr" )
107108 plt .axis ([- 2 , 15 , - 2 , 15 ])
108109 plt .grid (True )
109110 plt .pause (0.01 )
110111
111- def PlotCircle (self ,x , y , size ):
112- deg = range (0 ,360 ,5 )
112+ def PlotCircle (self , x , y , size ):
113+ deg = list ( range (0 , 360 , 5 ) )
113114 deg .append (0 )
114- xl = [ x + size * math .cos (math .radians (d )) for d in deg ]
115- yl = [ y + size * math .sin (math .radians (d )) for d in deg ]
115+ xl = [ x + size * math .cos (math .radians (d )) for d in deg ]
116+ yl = [ y + size * math .sin (math .radians (d )) for d in deg ]
116117 plt .plot (xl , yl , "-k" )
117118
118119 def GetNearestListIndex (self , nodeList , rnd ):
119- dlist = [(node .x - rnd [0 ]) ** 2 + (node .y - rnd [1 ]) ** 2 for node in nodeList ]
120+ dlist = [(node .x - rnd [0 ]) ** 2 + (node .y - rnd [1 ])
121+ ** 2 for node in nodeList ]
120122 minind = dlist .index (min (dlist ))
121123 return minind
122124
@@ -131,8 +133,9 @@ def __CollisionCheck(self, node, obstacleList):
131133
132134 return True # safe
133135
136+
134137class Node ():
135- u """
138+ """
136139 RRT Node
137140 """
138141
@@ -143,31 +146,31 @@ def __init__(self, x, y):
143146
144147
145148def GetPathLength (path ):
146- l = 0
149+ le = 0
147150 for i in range (len (path ) - 1 ):
148151 dx = path [i + 1 ][0 ] - path [i ][0 ]
149152 dy = path [i + 1 ][1 ] - path [i ][1 ]
150153 d = math .sqrt (dx * dx + dy * dy )
151- l += d
154+ le += d
152155
153- return l
156+ return le
154157
155158
156159def GetTargetPoint (path , targetL ):
157- l = 0
160+ le = 0
158161 ti = 0
159162 lastPairLen = 0
160163 for i in range (len (path ) - 1 ):
161164 dx = path [i + 1 ][0 ] - path [i ][0 ]
162165 dy = path [i + 1 ][1 ] - path [i ][1 ]
163166 d = math .sqrt (dx * dx + dy * dy )
164- l += d
165- if l >= targetL :
166- ti = i - 1
167+ le += d
168+ if le >= targetL :
169+ ti = i - 1
167170 lastPairLen = d
168171 break
169172
170- partRatio = (l - targetL ) / lastPairLen
173+ partRatio = (le - targetL ) / lastPairLen
171174 # print(partRatio)
172175 # print((ti,len(path),path[ti],path[ti+1]))
173176
@@ -181,26 +184,21 @@ def GetTargetPoint(path, targetL):
181184def LineCollisionCheck (first , second , obstacleList ):
182185 # Line Equation
183186
184- x1 = first [0 ]
185- y1 = first [1 ]
186- x2 = second [0 ]
187- y2 = second [1 ]
187+ x1 = first [0 ]
188+ y1 = first [1 ]
189+ x2 = second [0 ]
190+ y2 = second [1 ]
188191
189192 try :
190- a = y2 - y1
191- b = - (x2 - x1 )
192- c = y2 * (x2 - x1 )- x2 * (y2 - y1 )
193+ a = y2 - y1
194+ b = - (x2 - x1 )
195+ c = y2 * (x2 - x1 ) - x2 * (y2 - y1 )
193196 except ZeroDivisionError :
194197 return False
195198
196- # print(first)
197- # print(second)
198-
199- for (ox ,oy ,size ) in obstacleList :
200- d = abs (a * ox + b * oy + c )/ (math .sqrt (a * a + b * b ))
201- # print((ox,oy,size,d))
202- if d <= (size ):
203- # print("NG")
199+ for (ox , oy , size ) in obstacleList :
200+ d = abs (a * ox + b * oy + c ) / (math .sqrt (a * a + b * b ))
201+ if d <= (size ):
204202 return False
205203
206204 # print("OK")
@@ -211,46 +209,45 @@ def LineCollisionCheck(first, second, obstacleList):
211209def PathSmoothing (path , maxIter , obstacleList ):
212210 # print("PathSmoothing")
213211
214- l = GetPathLength (path )
212+ le = GetPathLength (path )
215213
216214 for i in range (maxIter ):
217215 # Sample two points
218- pickPoints = [random .uniform (0 , l ), random .uniform (0 , l )]
216+ pickPoints = [random .uniform (0 , le ), random .uniform (0 , le )]
219217 pickPoints .sort ()
220218 # print(pickPoints)
221219 first = GetTargetPoint (path , pickPoints [0 ])
222220 # print(first)
223221 second = GetTargetPoint (path , pickPoints [1 ])
224222 # print(second)
225223
226- if first [2 ]<= 0 or second [2 ]<= 0 :
224+ if first [2 ] <= 0 or second [2 ] <= 0 :
227225 continue
228226
229- if (second [2 ]+ 1 ) > len (path ):
227+ if (second [2 ] + 1 ) > len (path ):
230228 continue
231229
232- if second [2 ]== first [2 ]:
230+ if second [2 ] == first [2 ]:
233231 continue
234232
235233 # collision check
236234 if not LineCollisionCheck (first , second , obstacleList ):
237235 continue
238236
239- #Create New path
240- newPath = []
241- newPath .extend (path [:first [2 ]+ 1 ])
242- newPath .append ([first [0 ],first [1 ]])
243- newPath .append ([second [0 ],second [1 ]])
244- newPath .extend (path [second [2 ]+ 1 :])
245- path = newPath
246- l = GetPathLength (path )
237+ # Create New path
238+ newPath = []
239+ newPath .extend (path [:first [2 ] + 1 ])
240+ newPath .append ([first [0 ], first [1 ]])
241+ newPath .append ([second [0 ], second [1 ]])
242+ newPath .extend (path [second [2 ] + 1 :])
243+ path = newPath
244+ le = GetPathLength (path )
247245
248246 return path
249247
250248
251- if __name__ == '__main__' :
252- import matplotlib .pyplot as plt
253- #====Search Path with RRT====
249+ def main ():
250+ # ====Search Path with RRT====
254251 # Parameter
255252 obstacleList = [
256253 (5 , 5 , 1 ),
@@ -260,18 +257,26 @@ def PathSmoothing(path, maxIter, obstacleList):
260257 (7 , 5 , 2 ),
261258 (9 , 5 , 2 )
262259 ] # [x,y,size]
263- rrt = RRT (start = [0 ,0 ],goal = [5 ,10 ],randArea = [- 2 ,15 ],obstacleList = obstacleList )
264- path = rrt .Planning (animation = True )
260+ rrt = RRT (start = [0 , 0 ], goal = [5 , 10 ],
261+ randArea = [- 2 , 15 ], obstacleList = obstacleList )
262+ path = rrt .Planning (animation = show_animation )
263+
264+ # Path smoothing
265+ maxIter = 1000
266+ smoothedPath = PathSmoothing (path , maxIter , obstacleList )
265267
266268 # Draw final path
267- rrt .DrawGraph ()
268- plt .plot ([x for (x ,y ) in path ], [y for (x ,y ) in path ],'-r' )
269+ if show_animation :
270+ rrt .DrawGraph ()
271+ plt .plot ([x for (x , y ) in path ], [y for (x , y ) in path ], '-r' )
269272
270- #Path smoothing
271- maxIter = 1000
272- smoothedPath = PathSmoothing (path , maxIter , obstacleList )
273- plt .plot ([x for (x ,y ) in smoothedPath ], [y for (x ,y ) in smoothedPath ],'-b' )
273+ plt .plot ([x for (x , y ) in smoothedPath ], [
274+ y for (x , y ) in smoothedPath ], '-b' )
274275
275- plt .grid (True )
276- plt .pause (0.01 ) # Need for Mac
277- plt .show ()
276+ plt .grid (True )
277+ plt .pause (0.01 ) # Need for Mac
278+ plt .show ()
279+
280+
281+ if __name__ == '__main__' :
282+ main ()
0 commit comments