13
13
import math
14
14
import matplotlib .pyplot as plt
15
15
16
- show_animation = True
16
+ show_animation = False
17
17
18
18
19
19
class RTree (object ):
20
20
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
+
22
23
self .vertices = dict ()
23
-
24
24
self .edges = []
25
25
self .start = start
26
26
self .lowerLimit = lowerLimit
@@ -61,7 +61,7 @@ def realCoordsToGridCoord(self, real_coord):
61
61
# the output is the same as real world coords if the resolution
62
62
# is set to 1
63
63
coord = [0 ] * self .dimension
64
- for i in range (0 , len (coord )):
64
+ for i in range (len (coord )):
65
65
start = self .lowerLimit [i ] # start of the grid space
66
66
coord [i ] = np .around ((real_coord [i ] - start ) / self .resolution )
67
67
return coord
@@ -131,8 +131,8 @@ def __init__(self, start, goal,
131
131
self .start = start
132
132
self .goal = goal
133
133
134
- self .minrand = randArea [0 ]
135
- self .maxrand = randArea [1 ]
134
+ self .minrand = randArea [0 ]
135
+ self .maxrand = randArea [1 ]
136
136
self .expandDis = expandDis
137
137
self .goalSampleRate = goalSampleRate
138
138
self .maxIter = maxIter
@@ -152,7 +152,8 @@ def __init__(self, start, goal,
152
152
# initialize tree
153
153
lowerLimit = [randArea [0 ], randArea [0 ]]
154
154
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 )
156
157
157
158
def plan (self , animation = True ):
158
159
@@ -175,14 +176,14 @@ def plan(self, animation=True):
175
176
cBest = self .g_scores [self .goalId ]
176
177
pathLen = float ('inf' )
177
178
solutionSet = set ()
178
- path = None
179
+ plan = []
179
180
180
181
# Computing the sampling space
181
182
cMin = math .sqrt (pow (self .start [0 ] - self .goal [1 ], 2 ) +
182
183
pow (self .start [0 ] - self .goal [1 ], 2 ))
183
184
xCenter = np .matrix ([[(self .start [0 ] + self .goal [0 ]) / 2.0 ],
184
185
[(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 ],
186
187
[(self .goal [1 ] - self .start [1 ]) / cMin ], [0 ]])
187
188
etheta = math .atan2 (a1 [1 ], a1 [0 ])
188
189
# first column of idenity matrix transposed
@@ -238,7 +239,7 @@ def plan(self, animation=True):
238
239
secondCoord = self .tree .nodeIdToRealWorldCoord (
239
240
bestEdge [1 ])
240
241
path = self .connect (firstCoord , secondCoord )
241
- if path == None or len (path ) == 0 :
242
+ if path is None or len (path ) == 0 :
242
243
continue
243
244
nextCoord = path [len (path ) - 1 , :]
244
245
nextCoordPathId = self .tree .realWorldToNodeId (
@@ -248,7 +249,7 @@ def plan(self, animation=True):
248
249
del self .samples [bestEdge [1 ]]
249
250
except (KeyError ):
250
251
pass
251
- eid = self .tree .addVertex (nextCoordPathId )
252
+ eid = self .tree .addVertex (nextCoord )
252
253
self .vertex_queue .append (eid )
253
254
if eid == self .goalId or bestEdge [0 ] == self .goalId or bestEdge [1 ] == self .goalId :
254
255
print ("Goal found" )
@@ -259,15 +260,17 @@ def plan(self, animation=True):
259
260
g_score = self .computeDistanceCost (
260
261
bestEdge [0 ], bestEdge [1 ])
261
262
self .g_scores [bestEdge [1 ]] = g_score + \
262
- self .g_scores [best_edge [0 ]]
263
+ self .g_scores [bestEdge [0 ]]
263
264
self .f_scores [bestEdge [1 ]] = g_score + \
264
265
self .computeHeuristicCost (bestEdge [1 ], self .goalId )
265
266
self .updateGraph ()
266
267
267
268
# 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 )
271
274
272
275
for edge in self .edge_queue :
273
276
if (edge [0 ] == bestEdge [1 ]):
@@ -288,14 +291,36 @@ def plan(self, animation=True):
288
291
plan .append (self .goal )
289
292
currId = self .goalId
290
293
while (currId != self .startId ):
291
- plan .append (seld .tree .nodeIdToRealWorldCoord (currId ))
294
+ plan .append (self .tree .nodeIdToRealWorldCoord (currId ))
292
295
currId = self .nodes [currId ]
293
296
294
297
plan .append (self .startId )
295
298
plan = plan [::- 1 ] # reverse the plan
296
299
return np .array (plan )
297
300
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
299
324
300
325
# def prune(self, c):
301
326
@@ -485,7 +510,8 @@ def updateGraph(self):
485
510
# store the parent and child
486
511
self .nodes [succesor ] = currId
487
512
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 ):
489
515
print ("Plotting Graph" )
490
516
plt .clf ()
491
517
for rnd in samples :
@@ -494,6 +520,9 @@ def drawGraph(self, xCenter=None, cBest=None, cMin=None, etheta=None, samples=No
494
520
if cBest != float ('inf' ):
495
521
self .plot_ellipse (xCenter , cBest , cMin , etheta )
496
522
523
+ if start is not None and end is not None :
524
+ plt .plot ([start [0 ], start [1 ]], [end [0 ], end [1 ]], "-g" )
525
+
497
526
# for node in self.nodeList:
498
527
# if node.parent is not None:
499
528
# 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
503
532
for (ox , oy , size ) in self .obstacleList :
504
533
plt .plot (ox , oy , "ok" , ms = 30 * size )
505
534
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" )
508
537
plt .axis ([- 2 , 15 , - 2 , 15 ])
509
538
plt .grid (True )
510
- plt .pause (5 )
539
+ plt .pause (0.01 )
511
540
512
541
def plot_ellipse (self , xCenter , cBest , cMin , etheta ):
513
542
@@ -532,16 +561,16 @@ def plot_ellipse(self, xCenter, cBest, cMin, etheta):
532
561
def main ():
533
562
print ("Starting Batch Informed Trees Star planning" )
534
563
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)
541
570
]
542
571
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 ])
545
574
path = bitStar .plan (animation = show_animation )
546
575
print ("Done" )
547
576
0 commit comments