LP_Astar3D.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. import os
  4. import sys
  5. sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/../../Search-based Planning/")
  6. from Search_3D.env3D import env
  7. from Search_3D import Astar3D
  8. from Search_3D.utils3D import getDist, getRay, StateSpace, Heuristic, getNearest, isinbound, isinball, hash3D, dehash, \
  9. cost, obstacleFree
  10. from Search_3D.plot_util3D import visualization
  11. import queue
  12. import pyrr
  13. import time
  14. class Lifelong_Astar(object):
  15. def __init__(self,resolution = 1):
  16. self.Alldirec = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 0], [1, 0, 1], [0, 1, 1], [1, 1, 1],
  17. [-1, 0, 0], [0, -1, 0], [0, 0, -1], [-1, -1, 0], [-1, 0, -1], [0, -1, -1],
  18. [-1, -1, -1],
  19. [1, -1, 0], [-1, 1, 0], [1, 0, -1], [-1, 0, 1], [0, 1, -1], [0, -1, 1],
  20. [1, -1, -1], [-1, 1, -1], [-1, -1, 1], [1, 1, -1], [1, -1, 1], [-1, 1, 1]])
  21. self.env = env(resolution=resolution)
  22. self.g = StateSpace(self)
  23. self.start, self.goal = getNearest(self.g, self.env.start), getNearest(self.g, self.env.goal)
  24. self.x0, self.xt = hash3D(self.start), hash3D(self.goal)
  25. self.v = StateSpace(self) # rhs(.) = g(.) = inf
  26. self.v[hash3D(self.start)] = 0 # rhs(x0) = 0
  27. self.h = Heuristic(self.g, self.goal)
  28. self.OPEN = queue.QueuePrior() # store [point,priority]
  29. self.OPEN.put(self.x0, [self.h[self.x0],0])
  30. self.CLOSED = set()
  31. # used for A*
  32. self.done = False
  33. self.Path = []
  34. self.V = []
  35. self.ind = 0
  36. # initialize children list
  37. self.CHILDREN = {}
  38. self.getCHILDRENset()
  39. # initialize cost list
  40. self.COST = {}
  41. _ = self.costset()
  42. def costset(self):
  43. NodeToChange = set()
  44. for strxi in self.CHILDREN.keys():
  45. children = self.CHILDREN[strxi]
  46. xi = dehash(strxi)
  47. toUpdate = [self.cost(xj,xi) for xj in children]
  48. if strxi in self.COST:
  49. # if the old cost not equal to new cost
  50. diff = np.not_equal(self.COST[strxi],toUpdate)
  51. cd = np.array(children)[diff]
  52. for i in cd:
  53. NodeToChange.add(hash3D(i))
  54. self.COST[strxi] = toUpdate
  55. else:
  56. self.COST[strxi] = toUpdate
  57. return NodeToChange
  58. def getCOSTset(self,strxi,xj):
  59. ind, children = 0, self.CHILDREN[strxi]
  60. for i in children:
  61. if all(i == xj):
  62. return self.COST[strxi][ind]
  63. ind += 1
  64. def children(self, x):
  65. allchild = []
  66. resolution = self.env.resolution
  67. for direc in self.Alldirec:
  68. child = np.array(list(map(np.add,x,np.multiply(direc,resolution))))
  69. if isinbound(self.env.boundary,child):
  70. allchild.append(child)
  71. return allchild
  72. def getCHILDRENset(self):
  73. for strxi in self.g.keys():
  74. xi = dehash(strxi)
  75. self.CHILDREN[strxi] = self.children(xi)
  76. def isCollide(self, x, child):
  77. ray , dist = getRay(x, child) , getDist(x, child)
  78. if not isinbound(self.env.boundary,child):
  79. return True, dist
  80. for i in self.env.AABB:
  81. shot = pyrr.geometric_tests.ray_intersect_aabb(ray, i)
  82. if shot is not None:
  83. dist_wall = getDist(x, shot)
  84. if dist_wall <= dist: # collide
  85. return True, dist
  86. for i in self.env.balls:
  87. if isinball(i, child):
  88. return True, dist
  89. shot = pyrr.geometric_tests.ray_intersect_sphere(ray, i)
  90. if shot != []:
  91. dists_ball = [getDist(x, j) for j in shot]
  92. if all(dists_ball <= dist): # collide
  93. return True, dist
  94. return False, dist
  95. def cost(self, x, y):
  96. collide, dist = self.isCollide(x, y)
  97. if collide: return np.inf
  98. else: return dist
  99. def key(self,strxi,epsilion = 1):
  100. return [min(self.g[strxi],self.v[strxi]) + epsilion*self.h[strxi],min(self.g[strxi],self.v[strxi])]
  101. def path(self):
  102. path = []
  103. strx = self.xt
  104. strstart = self.x0
  105. ind = 0
  106. while strx != strstart:
  107. j = dehash(strx)
  108. nei = self.CHILDREN[strx]
  109. gset = [self.g[hash3D(xi)] for xi in nei]
  110. # collision check and make g cost inf
  111. for i in range(len(nei)):
  112. if self.isCollide(nei[i],j)[0]:
  113. gset[i] = np.inf
  114. parent = nei[np.argmin(gset)]
  115. path.append([dehash(strx), parent])
  116. strx = hash3D(parent)
  117. if ind > 100:
  118. break
  119. ind += 1
  120. return path
  121. #------------------Lifelong Plannning A*
  122. def UpdateMembership(self,strxi, xi, xparent=None):
  123. if strxi != self.x0:
  124. self.v[strxi] = min([self.g[hash3D(j)] + self.getCOSTset(strxi,j) for j in self.CHILDREN[strxi]])
  125. self.OPEN.check_remove(strxi)
  126. if self.g[strxi] != self.v[strxi]:
  127. self.OPEN.put(strxi,self.key(strxi))
  128. def ComputePath(self):
  129. print('computing path ...')
  130. while self.key(self.xt) > self.OPEN.top_key() or self.v[self.xt] != self.g[self.xt]:
  131. strxi = self.OPEN.get()
  132. xi = dehash(strxi)
  133. # if g > rhs, overconsistent
  134. if self.g[strxi] > self.v[strxi]:
  135. self.g[strxi] = self.v[strxi]
  136. # add xi to expanded node set
  137. if strxi not in self.CLOSED:
  138. self.V.append(xi)
  139. self.CLOSED.add(strxi)
  140. else: # underconsistent and consistent
  141. self.g[strxi] = np.inf
  142. self.UpdateMembership(strxi, xi)
  143. for xj in self.CHILDREN[strxi]:
  144. strxj = hash3D(xj)
  145. self.UpdateMembership(strxj, xj)
  146. # visualization(self)
  147. self.ind += 1
  148. self.Path = self.path()
  149. self.done = True
  150. visualization(self)
  151. plt.pause(2)
  152. def change_env(self):
  153. self.env.change()
  154. self.done = False
  155. self.Path = []
  156. self.CLOSED = set()
  157. N = self.costset()
  158. for strxi in N:
  159. xi = dehash(strxi)
  160. self.UpdateMembership(strxi,xi)
  161. if __name__ == '__main__':
  162. sta = time.time()
  163. Astar = Lifelong_Astar(1)
  164. Astar.ComputePath()
  165. Astar.change_env()
  166. Astar.ComputePath()
  167. plt.show()
  168. print(time.time() - sta)