1313import math
1414import matplotlib .pyplot as plt
1515
16- show_animation = True
16+ show_animation = False
1717
1818
1919class RTree (object ):
2020
21- def __init__ (self , start = [0 ,0 ], lowerLimit = [0 ,0 ], upperLimit = [10 ,10 ], resolution = 1 ):
21+ def __init__ (self , start = [0 , 0 ], lowerLimit = [0 , 0 ], upperLimit = [10 , 10 ], resolution = 1 ):
22+
2223 self .vertices = dict ()
23-
2424 self .edges = []
2525 self .start = start
2626 self .lowerLimit = lowerLimit
@@ -61,7 +61,7 @@ def realCoordsToGridCoord(self, real_coord):
6161 # the output is the same as real world coords if the resolution
6262 # is set to 1
6363 coord = [0 ] * self .dimension
64- for i in range (0 , len (coord )):
64+ for i in range (len (coord )):
6565 start = self .lowerLimit [i ] # start of the grid space
6666 coord [i ] = np .around ((real_coord [i ] - start ) / self .resolution )
6767 return coord
@@ -131,8 +131,8 @@ def __init__(self, start, goal,
131131 self .start = start
132132 self .goal = goal
133133
134- self .minrand = randArea [0 ]
135- self .maxrand = randArea [1 ]
134+ self .minrand = randArea [0 ]
135+ self .maxrand = randArea [1 ]
136136 self .expandDis = expandDis
137137 self .goalSampleRate = goalSampleRate
138138 self .maxIter = maxIter
@@ -152,7 +152,8 @@ def __init__(self, start, goal,
152152 # initialize tree
153153 lowerLimit = [randArea [0 ], randArea [0 ]]
154154 upperLimit = [randArea [1 ], randArea [1 ]]
155- self .tree = RTree (start = start ,lowerLimit = lowerLimit ,upperLimit = upperLimit ,resolution = 0.1 )
155+ self .tree = RTree (start = start , lowerLimit = lowerLimit ,
156+ upperLimit = upperLimit , resolution = 0.1 )
156157
157158 def plan (self , animation = True ):
158159
@@ -175,14 +176,14 @@ def plan(self, animation=True):
175176 cBest = self .g_scores [self .goalId ]
176177 pathLen = float ('inf' )
177178 solutionSet = set ()
178- path = None
179+ plan = []
179180
180181 # Computing the sampling space
181182 cMin = math .sqrt (pow (self .start [0 ] - self .goal [1 ], 2 ) +
182183 pow (self .start [0 ] - self .goal [1 ], 2 ))
183184 xCenter = np .matrix ([[(self .start [0 ] + self .goal [0 ]) / 2.0 ],
184185 [(self .goal [1 ] - self .start [1 ]) / 2.0 ], [0 ]])
185- a1 = np .matrix ([[(self .goal [0 ]- self .start [0 ]) / cMin ],
186+ a1 = np .matrix ([[(self .goal [0 ] - self .start [0 ]) / cMin ],
186187 [(self .goal [1 ] - self .start [1 ]) / cMin ], [0 ]])
187188 etheta = math .atan2 (a1 [1 ], a1 [0 ])
188189 # first column of idenity matrix transposed
@@ -238,7 +239,7 @@ def plan(self, animation=True):
238239 secondCoord = self .tree .nodeIdToRealWorldCoord (
239240 bestEdge [1 ])
240241 path = self .connect (firstCoord , secondCoord )
241- if path == None or len (path ) == 0 :
242+ if path is None or len (path ) == 0 :
242243 continue
243244 nextCoord = path [len (path ) - 1 , :]
244245 nextCoordPathId = self .tree .realWorldToNodeId (
@@ -248,7 +249,7 @@ def plan(self, animation=True):
248249 del self .samples [bestEdge [1 ]]
249250 except (KeyError ):
250251 pass
251- eid = self .tree .addVertex (nextCoordPathId )
252+ eid = self .tree .addVertex (nextCoord )
252253 self .vertex_queue .append (eid )
253254 if eid == self .goalId or bestEdge [0 ] == self .goalId or bestEdge [1 ] == self .goalId :
254255 print ("Goal found" )
@@ -259,15 +260,17 @@ def plan(self, animation=True):
259260 g_score = self .computeDistanceCost (
260261 bestEdge [0 ], bestEdge [1 ])
261262 self .g_scores [bestEdge [1 ]] = g_score + \
262- self .g_scores [best_edge [0 ]]
263+ self .g_scores [bestEdge [0 ]]
263264 self .f_scores [bestEdge [1 ]] = g_score + \
264265 self .computeHeuristicCost (bestEdge [1 ], self .goalId )
265266 self .updateGraph ()
266267
267268 # visualize new edge
268- # if animation:
269- # self.drawGraph(xCenter=xCenter, cBest=cBest,
270- # cMin=cMin, etheta=etheta, samples=samples)
269+
270+ if animation :
271+ self .drawGraph (xCenter = xCenter , cBest = cBest ,
272+ cMin = cMin , etheta = etheta , samples = self .samples .values (),
273+ start = firstCoord , end = secondCoord , plan = plan )
271274
272275 for edge in self .edge_queue :
273276 if (edge [0 ] == bestEdge [1 ]):
@@ -288,14 +291,36 @@ def plan(self, animation=True):
288291 plan .append (self .goal )
289292 currId = self .goalId
290293 while (currId != self .startId ):
291- plan .append (seld .tree .nodeIdToRealWorldCoord (currId ))
294+ plan .append (self .tree .nodeIdToRealWorldCoord (currId ))
292295 currId = self .nodes [currId ]
293296
294297 plan .append (self .startId )
295298 plan = plan [::- 1 ] # reverse the plan
296299 return np .array (plan )
297300
298- # def expandVertex(self, vertex):
301+ def connect (self , start , end ):
302+ # A function which attempts to extend from a start coordinates
303+ # to goal coordinates
304+ steps = self .computeDistanceCost (self .tree .realWorldToNodeId (
305+ start ), self .tree .realWorldToNodeId (end )) * 25
306+ x = np .linspace (start [0 ], end [0 ], num = steps )
307+ y = np .linspace (start [1 ], end [1 ], num = steps )
308+ for i in range (len (x )):
309+ if (self ._collisionCheck (x [i ], y [i ])):
310+ if (i == 0 ):
311+ return None
312+ # if collision, send path until collision
313+ return np .vstack ((x [0 :i ], y [0 :i ])).transpose ()
314+ return np .vstack ((x , y )).transpose ()
315+
316+ def _collisionCheck (self , x , y ):
317+ for (ox , oy , size ) in self .obstacleList :
318+ dx = ox - x
319+ dy = oy - y
320+ d = dx * dx + dy * dy
321+ if d <= 1.1 * size ** 2 :
322+ return True # collision
323+ return False
299324
300325 # def prune(self, c):
301326
@@ -485,7 +510,8 @@ def updateGraph(self):
485510 # store the parent and child
486511 self .nodes [succesor ] = currId
487512
488- def drawGraph (self , xCenter = None , cBest = None , cMin = None , etheta = None , samples = None ):
513+ def drawGraph (self , xCenter = None , cBest = None , cMin = None , etheta = None ,
514+ samples = None , start = None , end = None , plan = None ):
489515 print ("Plotting Graph" )
490516 plt .clf ()
491517 for rnd in samples :
@@ -494,6 +520,9 @@ def drawGraph(self, xCenter=None, cBest=None, cMin=None, etheta=None, samples=No
494520 if cBest != float ('inf' ):
495521 self .plot_ellipse (xCenter , cBest , cMin , etheta )
496522
523+ if start is not None and end is not None :
524+ plt .plot ([start [0 ], start [1 ]], [end [0 ], end [1 ]], "-g" )
525+
497526 # for node in self.nodeList:
498527 # if node.parent is not None:
499528 # if node.x or node.y is not None:
@@ -503,11 +532,11 @@ def drawGraph(self, xCenter=None, cBest=None, cMin=None, etheta=None, samples=No
503532 for (ox , oy , size ) in self .obstacleList :
504533 plt .plot (ox , oy , "ok" , ms = 30 * size )
505534
506- plt .plot (self .start . x , self .start . y , "xr" )
507- plt .plot (self .goal . x , self .goal . y , "xr" )
535+ plt .plot (self .start [ 0 ] , self .start [ 1 ] , "xr" )
536+ plt .plot (self .goal [ 0 ] , self .goal [ 1 ] , "xr" )
508537 plt .axis ([- 2 , 15 , - 2 , 15 ])
509538 plt .grid (True )
510- plt .pause (5 )
539+ plt .pause (0.01 )
511540
512541 def plot_ellipse (self , xCenter , cBest , cMin , etheta ):
513542
@@ -532,16 +561,16 @@ def plot_ellipse(self, xCenter, cBest, cMin, etheta):
532561def main ():
533562 print ("Starting Batch Informed Trees Star planning" )
534563 obstacleList = [
535- (5 , 5 , 0.5 ),
536- (9 , 6 , 1 ),
537- (7 , 5 , 1 ),
538- (1 , 5 , 1 ),
539- (3 , 6 , 1 ),
540- (7 , 9 , 1 )
564+ # (5, 5, 0.5),
565+ # (9, 6, 1),
566+ # (7, 5, 1),
567+ # (1, 5, 1),
568+ # (3, 6, 1),
569+ # (7, 9, 1)
541570 ]
542571
543- bitStar = BITStar (start = [0 , 0 ], goal = [5 , 10 ], obstacleList = obstacleList ,
544- randArea = [0 , 15 ])
572+ bitStar = BITStar (start = [0 , 0 ], goal = [2 , 4 ], obstacleList = obstacleList ,
573+ randArea = [- 2 , 15 ])
545574 path = bitStar .plan (animation = show_animation )
546575 print ("Done" )
547576
0 commit comments