Advertisement
Guest User

Untitled

a guest
Dec 8th, 2019
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.93 KB | None | 0 0
  1. import sys
  2.  
  3. import matplotlib.pyplot as plt
  4. from matplotlib.path import Path
  5. import matplotlib.patches as patches
  6. from matplotlib import collections as mc
  7. import numpy as np
  8. import math
  9. import queue
  10. import random
  11. from datetime import datetime
  12.  
  13. '''
  14. Set up matplotlib to create a plot with an empty square
  15. '''
  16. def setupPlot():
  17. fig = plt.figure(num=None, figsize=(5, 5), dpi=120, facecolor='w', edgecolor='k')
  18. ax = fig.subplots()
  19. ax.set_axisbelow(True)
  20. ax.set_ylim(-1, 11)
  21. ax.set_xlim(-1, 11)
  22. ax.grid(which='minor', linestyle=':', alpha=0.2)
  23. ax.grid(which='major', linestyle=':', alpha=0.5)
  24. return fig, ax
  25.  
  26. '''
  27. Make a patch for a single pology
  28. '''
  29. def createPolygonPatch(polygon, color):
  30. verts = []
  31. codes= []
  32. for v in range(0, len(polygon)):
  33. xy = polygon[v]
  34. verts.append((xy[0], xy[1]))
  35. if v == 0:
  36. codes.append(Path.MOVETO)
  37. else:
  38. codes.append(Path.LINETO)
  39. verts.append(verts[0])
  40. codes.append(Path.CLOSEPOLY)
  41. path = Path(verts, codes)
  42. patch = patches.PathPatch(path, facecolor=color, lw=1)
  43.  
  44. return patch
  45.  
  46.  
  47. '''
  48. Render the problem
  49. '''
  50. def drawProblem(robotStart, robotGoal, polygons):
  51. _, ax = setupPlot()
  52. patch = createPolygonPatch(robotStart, 'green')
  53. ax.add_patch(patch)
  54. patch = createPolygonPatch(robotGoal, 'red')
  55. ax.add_patch(patch)
  56. for p in range(0, len(polygons)):
  57. patch = createPolygonPatch(polygons[p], 'gray')
  58. ax.add_patch(patch)
  59. plt.show()
  60.  
  61. '''
  62. Grow a simple RRT
  63. '''
  64. def growSimpleRRT(points):
  65. newPoints = {}
  66. adjListMap = {}
  67.  
  68. bool = True
  69. count = 0
  70. # Your code goes here
  71. for i in points:
  72. if len(newPoints) == 0:
  73. newPoints[i] = points[i]
  74. newPoints[i+1] = points[i+1]
  75. adjListMap[i] = [i+1]
  76. adjListMap[i+1] = [i]
  77. elif len(newPoints) == 2 and bool:
  78. bool = False
  79. continue
  80. else:
  81. num = 0
  82. index = 0
  83. point1 = 0
  84. point2 = 0
  85. d = sys.maxsize #distance from random point to nearest point on line
  86. x = 0
  87. y = 0
  88. for j in list(adjListMap): # j is the key in adjListMap. j just goes through each point
  89. for k in adjListMap[j]: # k goes through every point that j is connected to
  90. m1 = (newPoints[k][1]-newPoints[j][1])/(newPoints[k][0]-newPoints[j][0])
  91. b1 = newPoints[j][1] - m1*newPoints[j][0]
  92. m2 = -1/m1
  93. b2 = points[i][1] - m2*points[i][0]
  94. newPointX = (b2-b1)/(m1-m2)
  95. newPointY = m1*newPointX + b1
  96. if not collisionDetection(adjListMap,newPoints,[points[i],(newPointX,newPointY)],j,k,0):
  97. if (newPoints[k][0] <= newPointX <= newPoints[j][0] or newPoints[k][0] >= newPointX >= newPoints[j][0]) and (newPoints[k][1] <= newPointY <= newPoints[j][1] or newPoints[k][1] >= newPointY >= newPoints[j][1]):
  98. if d > math.sqrt((newPointX-points[i][0])**2+(newPointY-points[i][1])**2):
  99. d = math.sqrt((newPointX-points[i][0])**2+(newPointY-points[i][1])**2)
  100. x = newPointX
  101. y = newPointY
  102. point1 = j
  103. point2 = k
  104. num = 0
  105. else:
  106. if newPoints[k][0] > newPoints[j][0]:
  107. if newPointX > newPoints[k][0]:
  108. if d > math.sqrt((newPoints[k][0]-points[i][0])**2+(newPoints[k][1]-points[i][1])**2):
  109. d = math.sqrt((newPoints[k][0]-points[i][0])**2+(newPoints[k][1]-points[i][1])**2)
  110. index = k
  111. num = 1
  112. else:
  113. if d > math.sqrt((newPoints[j][0]-points[i][0])**2+(newPoints[j][1]-points[i][1])**2):
  114. d = math.sqrt((newPoints[j][0]-points[i][0])**2+(newPoints[j][1]-points[i][1])**2)
  115. index = j
  116. num = 1
  117. else:
  118. if newPointX > newPoints[j][0]:
  119. if d > math.sqrt((newPoints[j][0]-points[i][0])**2+(newPoints[j][1]-points[i][1])**2):
  120. d = math.sqrt((newPoints[j][0]-points[i][0])**2+(newPoints[j][1]-points[i][1])**2)
  121. index = j
  122. num = 1
  123. else:
  124. if d > math.sqrt((newPoints[k][0]-points[i][0])**2+(newPoints[k][1]-points[i][1])**2):
  125. d = math.sqrt((newPoints[k][0]-points[i][0])**2+(newPoints[k][1]-points[i][1])**2)
  126. index = k
  127. num = 1
  128.  
  129. if newPointX != points[i][0] and newPointY != points[i][1]:
  130. temp = i+count
  131. newPoints[i] = points[i]
  132. if num == 0:
  133. count+=1
  134. newPoints[len(points)+count] = (x,y)
  135. if adjListMap.get(i) == None:
  136. adjListMap[i] = [len(points)+count]
  137. else:
  138. adjListMap[temp].append(len(points)+count)
  139. adjListMap[len(points)+count] = [i]
  140. adjListMap[len(points)+count].append(point1)
  141. adjListMap[len(points)+count].append(point2)
  142. newList = adjListMap[point1]
  143. newList.remove(point2)
  144. newList.append(len(points)+count)
  145. adjListMap[point1] = newList
  146. newList = adjListMap[point2]
  147. newList.remove(point1)
  148. newList.append(len(points)+count)
  149. adjListMap[point2] = newList
  150. else:
  151. adjListMap[i] = [index]
  152. adjListMap[index].append(i)
  153.  
  154.  
  155. return newPoints, adjListMap
  156.  
  157. def intersectLines(line, tree, points):
  158. firstline = np.array([line[0][0],line[0][1],line[1][0],line[1][1]]).reshape(2,2)
  159. for i in tree:
  160. for j in tree[i]:
  161. if points[i] == line[0] or points[i] == line[1] or points[j] == line[0] or points[j] == line[1]:
  162. continue
  163. line2 = [points[i],points[j]]
  164. secondline = np.array([line2[0][0],line2[0][1],line2[1][0],line2[1][1]]).reshape(2,2)
  165.  
  166. linecodes = [Path.MOVETO,Path.LINETO,Path.CLOSEPOLY]
  167. line_path = Path(firstline)
  168. line_path2 = Path(secondline)
  169.  
  170. if(Path.intersects_path(line_path,line_path2,filled=True)):
  171. return True
  172. return False
  173.  
  174. def collisionDetection(adjListMap, newPoints, points,a,b,c):
  175. bool = 0
  176. for i in adjListMap:
  177. for j in adjListMap[i]:
  178. if c == 0:
  179. if i == a and j == b or i == b and j == a:
  180. continue
  181. else:
  182. if b == j or b == i:
  183. continue
  184. intersectX = sys.maxsize
  185. intersectY = sys.maxsize
  186. m1 = 0
  187. b1 = 0
  188. if newPoints[j][1] == newPoints[i][1]:
  189. intersectY = newPoints[j][1]
  190. elif newPoints[j][0] == newPoints[i][0]:
  191. intersectX = newPoints[j][0]
  192. else:
  193. m1 = (newPoints[j][1]-newPoints[i][1])/(newPoints[j][0]-newPoints[i][0])
  194. b1 = newPoints[i][1] - m1*newPoints[i][0]
  195. # Test to see if x points or y points are the same
  196. # This would result in either a 0 slope or divide by 0 error
  197. if points[1][0] == points[0][0]:
  198. if intersectX != sys.maxsize:
  199. bool = 1
  200. break
  201. elif interxectY != sys.maxsize:
  202. intersectX = points[1][0]
  203. else:
  204. intersectX = points[1][0]
  205. intersectY = m1*intersectX + b1
  206. elif points[1][1] == points[0][1]:
  207. if intersectY != sys.maxsize:
  208. bool = 1
  209. break
  210. elif intersectX != sys.maxsize:
  211. intersectY = points[1][1]
  212. else:
  213. intersectY = points[1][1]
  214. intersectX = (intersectY-b1)/m1
  215. for k in adjListMap:
  216. for l in adjListMap[k]:
  217. if ((newPoints[l][0] > intersectX > newPoints[k][0] or newPoints[l][0] < intersectX < newPoints[k][0]) and (newPoints[l][1] > intersectY > newPoints[k][1] or newPoints[l][1] < intersectY < newPoints[k][1])) and ((points[0][0] < intersectX < points[1][0] or points[0][0] > intersectX > points[1][0]) and (points[0][1] < intersectY < points[1][1] or points[0][1] > intersectY > points[1][1])) and not intersectX == points[1][0] and not intersectY == points[1][1]:
  218. bool = 1
  219. break
  220. if bool==1:
  221. break
  222. if bool==1:
  223. break
  224. if bool==1:
  225. break
  226. if bool==1:
  227. return True #the lines collide. This is not a valid point
  228. return False #the lines do not collide.
  229.  
  230. '''
  231. Perform basic search
  232. '''
  233. def backtrace(parent, start, end):
  234. path = [end]
  235. while path[-1] != start:
  236. path.append(parent[path[-1]])
  237. path.reverse()
  238. return path
  239.  
  240. def basicSearch(tree, start, goal):
  241. parent = {}
  242. path = []
  243. visited = [False] * (len(tree)+1)
  244. squeue = queue.Queue()
  245.  
  246. squeue.put(start)
  247. visited[start] = True
  248. found=False
  249. while squeue:
  250. s = squeue.get(0)
  251. path.append(s)
  252. if(s == goal):
  253. found=True
  254. return backtrace(parent, start, goal)
  255.  
  256. # Get all adjacent vertices of the
  257. # dequeued vertex s. If a adjacent
  258. # has not been visited, then mark it
  259. # visited and enqueue it
  260.  
  261. for l in tree[s]:
  262. if visited[l] == False:
  263. parent[l] = s
  264. squeue.put(l)
  265. visited[l] = True
  266.  
  267.  
  268. return path
  269.  
  270. '''
  271. Display the RRT and Path
  272. '''
  273. def displayRRTandPath(points, adjListMap, path, robotStart=None, robotGoal=None, polygons=None):
  274. # Your code goes here
  275. # You could start by copying code from the function
  276. # drawProblem and modify it to do what you need.
  277. # You should draw the problem when applicable.
  278. _, ax = setupPlot()
  279. if(robotStart!=None):
  280. patch = createPolygonPatch(robotStart, 'green')
  281. ax.add_patch(patch)
  282. if(robotGoal!=None):
  283. patch = createPolygonPatch(robotGoal, 'red')
  284. ax.add_patch(patch)
  285.  
  286. if(polygons!=None):
  287. for p in range(0, len(polygons)):
  288. patch = createPolygonPatch(polygons[p], 'gray')
  289. ax.add_patch(patch)
  290.  
  291. line = []
  292. for j in adjListMap:
  293. for k in adjListMap[j]:
  294. line.append([points[j],points[k]])
  295.  
  296. lc = mc.LineCollection(line, linewidths=2, color='black')
  297. ax.add_collection(lc)
  298.  
  299. pathline=[]
  300. for j in range(1,len(path)):
  301. pathline.append([points[path[j-1]],points[path[j]]])
  302. pl = mc.LineCollection(pathline, linewidths=2, color='orange')
  303. ax.add_collection(pl)
  304.  
  305.  
  306. plt.show()
  307.  
  308. #lines = [[(0, 1), (1, 1)], [(2, 3), (3, 3)], [(1, 2), (1, 3)]]
  309. #lc = mc.LineCollection(lines, linewidths=2)
  310. #ax.add_collection(lc)
  311. #plt.scatter(x,y, color='black', marker='o')
  312. return
  313.  
  314. '''
  315. Collision checking
  316. '''
  317. def isCollisionFree(robot, point, obstacles):
  318.  
  319. # Your code goes here.
  320. for i in range(0,len(robot)):
  321. robot[i] = (robot[i][0]+point[0],robot[i][1]+point[1])
  322. if robot[i][0] < 0 or robot[i][1] < 0 or robot[i][0] > 10 or robot[i][1] > 10:
  323. return False
  324. if withinPoly(obstacles, robot[i]):
  325. return False
  326.  
  327. return True
  328.  
  329. '''
  330. The full RRT algorithm
  331. '''
  332. def RRT(robot, obstacles, startPoint, goalPoint):
  333.  
  334. max = 100
  335. points = dict()
  336. tree = dict()
  337. path = []
  338. tree[1] = [2]
  339. tree[2] = [1]
  340. while len(points) != 2:
  341. x = random.uniform(0.1,9.9)
  342. y = random.uniform(0.1,9.9)
  343. if not (withinPoly(obstacles,[x,y]) and not isCollisionFree(robot,(x,y),obstacles)):
  344. if len(points) == 0:
  345. points[1] = (x,y)
  346. else:
  347. if not lineWithinPoly(obstacles,[(x,y),points[1]]):
  348. points[2] = (x,y)
  349. # Your code goes here.
  350. i = 2
  351. while i < max+1:
  352. x = random.uniform(0.1,9.9)
  353. y = random.uniform(0.1,9.9)
  354. if (x,y) in points.values():
  355. continue
  356. if withinPoly(obstacles,[x,y]) and not isCollisionFree(robot,(x,y),obstacles):
  357. continue
  358. d = sys.maxsize
  359. index = 0
  360. for j in list(tree):
  361. for k in tree[j]:
  362. if i == 3:
  363. if not lineWithinPoly(obstacles,[(x,y),points[k]]):
  364. if d > math.sqrt((x-points[k][0])**2+(y-points[k][1])**2):
  365. d = math.sqrt((x-points[k][0])**2+(y-points[k][1])**2)
  366. index = k
  367. elif not intersectLines([points[k],(x,y)],tree,points) and not lineWithinPoly(obstacles,[(x,y),points[k]]): #collisionDetection(tree,points,[points[k],(x,y)],j,k,1)
  368. if d > math.sqrt((x-points[k][0])**2+(y-points[k][1])**2):
  369. d = math.sqrt((x-points[k][0])**2+(y-points[k][1])**2)
  370. index = k
  371. if index != 0:
  372. points[i] = (x,y)
  373. if points.get(i) == None:
  374. points[i] = (x,y)
  375. if tree.get(index) == None:
  376. tree[index] = [i]
  377. else:
  378. tree[index].append(i)
  379. tree[i] = [index]
  380. else:
  381. continue
  382. i+=1
  383.  
  384. dStart = sys.maxsize
  385. dGoal = sys.maxsize
  386. indexS = 0
  387. indexG = 0
  388. for i in range(1,len(points)+1):
  389. if not intersectLines([points[i],startPoint],tree,points) and not lineWithinPoly(obstacles,[startPoint,points[i]]): #collisionDetection(tree,points,[startPoint,points.get(i)],0,i,1)
  390. if dStart > math.sqrt((startPoint[0]-points[i][0])**2+(startPoint[1]-points[i][1])**2):
  391. dStart = math.sqrt((startPoint[0]-points[i][0])**2+(startPoint[1]-points[i][1])**2)
  392. indexS = i
  393. if not intersectLines([points[i],goalPoint],tree,points) and not lineWithinPoly(obstacles,[goalPoint,points[i]]): #collisionDetection(tree,points,[goalPoint,points.get(i)],0,i,1)
  394. if dGoal > math.sqrt((goalPoint[0]-points[i][0])**2+(goalPoint[1]-points[i][1])**2):
  395. dGoal = math.sqrt((goalPoint[0]-points[i][0])**2+(goalPoint[1]-points[i][1])**2)
  396. indexG = i
  397. points[max+1] = startPoint
  398. points[max+2] = goalPoint
  399.  
  400. if indexS != 0:
  401. tree[max+1] = [indexS]
  402. tree[indexS].append(max+1)
  403. else:
  404. print("failed connecting startPoint")
  405.  
  406. if indexG != 0:
  407. tree[max+2] = [indexG]
  408. tree[indexG].append(max+2)
  409. else:
  410. print("failed connecting endPoint")
  411.  
  412. path = basicSearch(tree, max+1, max+2)
  413. return points, tree, path
  414.  
  415. def withinPoly(polygons, point):
  416. for poly in polygons:
  417. patch = createPolygonPatch(poly, 'grey')
  418. if(patch.get_path().contains_point(point)):
  419. return True
  420. return False
  421.  
  422. def lineWithinPoly(polygons, line):
  423. for poly in polygons:
  424. patch = createPolygonPatch(poly, 'grey')
  425.  
  426. vcount = 0
  427. verts=[]
  428. for vertex in poly:
  429. verts.append(vertex)
  430. vcount+=1
  431. verts.append(verts[0])
  432.  
  433. codes = [Path.MOVETO]
  434. for i in range(0,vcount-1):
  435. codes.append(Path.LINETO)
  436. codes.append(Path.CLOSEPOLY)
  437.  
  438. path = Path(verts, codes)
  439. line = np.array([line[0][0],line[0][1],line[1][0],line[1][1]]).reshape(2,2)
  440. linecodes = [Path.MOVETO,Path.LINETO,Path.CLOSEPOLY]
  441. line_path = Path(line)
  442.  
  443. if(Path.intersects_path(line_path,path)):
  444. return True
  445. return False
  446.  
  447. def main(filename, x1, y1, x2, y2, display=''):
  448. # Read data and parse polygons
  449. lines = [line.rstrip('\n') for line in open(filename)]
  450. robot = []
  451. obstacles = []
  452. for line in range(0, len(lines)):
  453. xys = lines[line].split(';')
  454. polygon = []
  455. for p in range(0, len(xys)):
  456. xy = xys[p].split(',')
  457. polygon.append((float(xy[0]), float(xy[1])))
  458. if line == 0 :
  459. robot = polygon
  460. else:
  461. obstacles.append(polygon)
  462.  
  463. # Print out the data
  464. print("Robot:")
  465. print(str(robot))
  466. print("Pologonal obstacles:")
  467. for p in range(0, len(obstacles)):
  468. print(str(obstacles[p]))
  469. print("")
  470.  
  471.  
  472. # Visualize
  473. if display == 'display':
  474. robotStart = [(x + x1, y + y1) for x, y in robot]
  475. robotGoal = [(x + x2, y + y2) for x, y in robot]
  476. #drawProblem(robotStart, robotGoal, obstacles)
  477.  
  478. # Example points for calling growSimpleRRT
  479. # You should expect many mroe points, e.g., 200-500
  480. points = dict()
  481. points[1] = (5, 5)
  482. points[2] = (7, 8.2)
  483. points[3] = (6.5, 5.2)
  484. points[4] = (0.3, 4)
  485. points[5] = (6, 3.7)
  486. points[6] = (6,8)
  487. #points[6] = (9.7, 6.4)
  488. points[7] = (4.4, 2.8)
  489. points[8] = (8.3,2.1)
  490. points[9] = (7.7,6.3)
  491. points[10] = (9,0.6)
  492. #points[8] = (9.1, 3.1)
  493. #points[9] = (8.1, 6.5)
  494. #points[10] = (0.7, 5.4)
  495. '''points[11] = (5.1, 3.9)
  496. points[12] = (2, 6)
  497. points[13] = (0.5, 6.7)
  498. points[14] = (8.3, 2.1)
  499. points[15] = (7.7, 6.3)
  500. points[16] = (7.9, 5)
  501. points[17] = (4.8, 6.1)
  502. points[18] = (3.2, 9.3)
  503. points[19] = (7.3, 5.8)
  504. points[20] = (9, 0.6)'''
  505.  
  506. # Printing the points
  507. print("")
  508. print("The input points are:")
  509. print(str(points))
  510. print("")
  511.  
  512. points, adjListMap = growSimpleRRT(points)
  513. print("")
  514. print("The new points are:")
  515. print(str(points))
  516. print("")
  517. print("")
  518. print("The tree is:")
  519. print(str(adjListMap))
  520. print("")
  521.  
  522. # Search for a solution
  523. # change 1 and 20 as you want
  524. path = basicSearch(adjListMap, 1, 10)
  525. print("")
  526. print("The path is:")
  527. print(str(path))
  528. print("")
  529.  
  530. # Your visualization code
  531. #if display == 'display':
  532. #displayRRTandPath(points, adjListMap, path)
  533.  
  534. start=datetime.now()
  535. # Solve a real RRT problem
  536. points, adjListMap, path = RRT(robot, obstacles, (x1, y1), (x2, y2))
  537. print("")
  538. print("runtime = ",(datetime.now()-start).total_seconds(),"seconds")
  539.  
  540. print("points:")
  541. print(str(points))
  542. print("")
  543. print("tree:")
  544. print(str(adjListMap))
  545. print("")
  546. print("path:")
  547. print(str(path))
  548.  
  549. # Your visualization code
  550. if display == 'display':
  551. displayRRTandPath(points, adjListMap, path, robotStart, robotGoal, obstacles)
  552.  
  553.  
  554. if __name__ == "__main__":
  555. # Retrive file name for input data
  556. if(len(sys.argv) < 6):
  557. print("Five arguments required: python spr.py [env-file] [x1] [y1] [x2] [y2]")
  558. exit()
  559.  
  560. filename = sys.argv[1]
  561. x1 = float(sys.argv[2])
  562. y1 = float(sys.argv[3])
  563. x2 = float(sys.argv[4])
  564. y2 = float(sys.argv[5])
  565. display = ''
  566. if(len(sys.argv) == 7):
  567. display = sys.argv[6]
  568.  
  569. main(filename, x1, y1, x2, y2, display)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement