DstarLite3D.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. import os
  4. import sys
  5. from collections import defaultdict
  6. sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/../../Search-based Planning/")
  7. from Search_3D.env3D import env
  8. from Search_3D import Astar3D
  9. from Search_3D.utils3D import getDist, getRay, g_Space, Heuristic, heuristic_fun, getNearest, isinbound, isinball, \
  10. isCollide, cost, obstacleFree, children, StateSpace
  11. from Search_3D.plot_util3D import visualization
  12. import queue
  13. import pyrr
  14. import time
  15. class D_star_Lite(object):
  16. # Original version of the D*lite
  17. def __init__(self, resolution = 1):
  18. self.Alldirec = {(1, 0, 0): 1, (0, 1, 0): 1, (0, 0, 1): 1, \
  19. (-1, 0, 0): 1, (0, -1, 0): 1, (0, 0, -1): 1, \
  20. (1, 1, 0): np.sqrt(2), (1, 0, 1): np.sqrt(2), (0, 1, 1): np.sqrt(2), \
  21. (-1, -1, 0): np.sqrt(2), (-1, 0, -1): np.sqrt(2), (0, -1, -1): np.sqrt(2), \
  22. (1, -1, 0): np.sqrt(2), (-1, 1, 0): np.sqrt(2), (1, 0, -1): np.sqrt(2), \
  23. (-1, 0, 1): np.sqrt(2), (0, 1, -1): np.sqrt(2), (0, -1, 1): np.sqrt(2), \
  24. (1, 1, 1): np.sqrt(3), (-1, -1, -1) : np.sqrt(3), \
  25. (1, -1, -1): np.sqrt(3), (-1, 1, -1): np.sqrt(3), (-1, -1, 1): np.sqrt(3), \
  26. (1, 1, -1): np.sqrt(3), (1, -1, 1): np.sqrt(3), (-1, 1, 1): np.sqrt(3)}
  27. self.env = env(resolution=resolution)
  28. # self.X = StateSpace(self.env)
  29. # self.x0, self.xt = getNearest(self.X, self.env.start), getNearest(self.X, self.env.goal)
  30. self.x0, self.xt = tuple(self.env.start), tuple(self.env.goal)
  31. self.OPEN = queue.QueuePrior()
  32. self.km = 0
  33. self.g = {} # all g initialized at inf
  34. self.rhs = {self.xt:0} # rhs(x0) = 0
  35. self.h = {}
  36. self.OPEN.put(self.xt, self.CalculateKey(self.xt))
  37. self.CLOSED = set()
  38. # init children set:
  39. self.CHILDREN = {}
  40. # init cost set
  41. self.COST = defaultdict(lambda: defaultdict(dict))
  42. # for visualization
  43. self.V = set() # vertice in closed
  44. self.ind = 0
  45. self.Path = []
  46. self.done = False
  47. def getcost(self, xi, xj):
  48. # use a LUT for getting the costd
  49. if xi not in self.COST:
  50. for (xj,xjcost) in children(self, xi, settings=1):
  51. self.COST[xi][xj] = cost(self, xi, xj, xjcost)
  52. # this might happen when there is a node changed.
  53. if xj not in self.COST[xi]:
  54. self.COST[xi][xj] = cost(self, xi, xj)
  55. return self.COST[xi][xj]
  56. def updatecost(self,range_changed=None):
  57. # TODO: update cost when the environment is changed
  58. # chaged nodes
  59. CHANGED = set()
  60. for xi in self.CLOSED:
  61. oldchildren = self.CHILDREN[xi]# A
  62. # if you don't know where the change occured:
  63. if range_changed is None:
  64. newchildren = set(children(self,xi))# B
  65. added = newchildren.difference(oldchildren)# B-A
  66. removed = oldchildren.difference(newchildren)# A-B
  67. self.CHILDREN[xi] = newchildren
  68. if added or removed:
  69. CHANGED.add(xi)
  70. for xj in removed:
  71. self.COST[xi][xj] = cost(self, xi, xj)
  72. for xj in added:
  73. self.COST[xi][xj] = cost(self, xi, xj)
  74. # if you do know where on the map changed, only update those changed around that area
  75. else:
  76. if isinbound(range_changed, xi):
  77. newchildren = set(children(self,xi))# B
  78. added = newchildren.difference(oldchildren)# B-A
  79. removed = oldchildren.difference(newchildren)# A-B
  80. self.CHILDREN[xi] = newchildren
  81. if added or removed:
  82. CHANGED.add(xi)
  83. for xj in removed:
  84. self.COST[xi][xj] = cost(self, xi, xj)
  85. for xj in added:
  86. self.COST[xi][xj] = cost(self, xi, xj)
  87. return CHANGED
  88. def getchildren(self, xi):
  89. if xi not in self.CHILDREN:
  90. allchild = children(self, xi)
  91. self.CHILDREN[xi] = set(allchild)
  92. return self.CHILDREN[xi]
  93. def updatechildren(self):
  94. # TODO: update children set when the environment is changed
  95. pass
  96. def geth(self, xi):
  97. # when the heurisitic is first calculated
  98. if xi not in self.h:
  99. self.h[xi] = heuristic_fun(self, xi, self.x0)
  100. return self.h[xi]
  101. def getg(self, xi):
  102. if xi not in self.g:
  103. self.g[xi] = np.inf
  104. return self.g[xi]
  105. def getrhs(self, xi):
  106. if xi not in self.rhs:
  107. self.rhs[xi] = np.inf
  108. return self.rhs[xi]
  109. #-------------main functions for D*Lite-------------
  110. def CalculateKey(self, s, epsilion = 1):
  111. return [min(self.getg(s), self.getrhs(s)) + epsilion * self.geth(s) + self.km, min(self.getg(s), self.getrhs(s))]
  112. def UpdateVertex(self, u):
  113. # if still in the hunt
  114. if not getDist(self.xt, u) <= self.env.resolution: # originally: u != s_goal
  115. self.rhs[u] = min([self.getcost(s, u) + self.getg(s) for s in self.getchildren(u)])
  116. # if u is in OPEN, remove it
  117. self.OPEN.check_remove(u)
  118. # if rhs(u) not equal to g(u)
  119. if self.getg(u) != self.getrhs(u):
  120. self.OPEN.put(u, self.CalculateKey(u))
  121. def ComputeShortestPath(self):
  122. while self.OPEN.top_key() < self.CalculateKey(self.x0) or self.getrhs(self.x0) != self.getg(self.x0) :
  123. kold = self.OPEN.top_key()
  124. u = self.OPEN.get()
  125. self.V.add(u)
  126. self.CLOSED.add(u)
  127. if getDist(self.x0, u) <= self.env.resolution:
  128. break
  129. # visualization(self)
  130. if kold < self.CalculateKey(u):
  131. self.OPEN.put(u, self.CalculateKey(u))
  132. if self.getg(u) > self.getrhs(u):
  133. self.g[u] = self.rhs[u]
  134. else:
  135. self.g[u] = np.inf
  136. self.UpdateVertex(u)
  137. for s in self.getchildren(u):
  138. self.UpdateVertex(s)
  139. self.ind += 1
  140. def main(self):
  141. s_last = self.x0
  142. s_start = self.x0
  143. print('first run ...')
  144. self.ComputeShortestPath()
  145. self.Path = self.path()
  146. self.done = True
  147. visualization(self)
  148. plt.pause(0.5)
  149. # plt.show()
  150. # change the environment
  151. print('running with map update ...')
  152. for i in range(100):
  153. range_changed1 = self.env.move_block(a=[0, 0, -0.1], s=0.5, block_to_move=0, mode='translation')
  154. range_changed2 = self.env.move_block(a=[0.1, 0, 0], s=0.5, block_to_move=1, mode='translation')
  155. range_changed3 = self.env.move_block(a=[0, 0.1, 0], s=0.5, block_to_move=2, mode='translation')
  156. #range_changed = self.env.move_block(a=[0.1, 0, 0], s=0.5, block_to_move=1, mode='translation')
  157. # update the edge cost of c(u,v)
  158. CHANGED1 = self.updatecost(range_changed1)
  159. CHANGED2 = self.updatecost(range_changed2)
  160. CHANGED3 = self.updatecost(range_changed3)
  161. CHANGED2 = CHANGED2.union(CHANGED1)
  162. CHANGED = CHANGED3.union(CHANGED2)
  163. while getDist(s_start, self.xt) > 2*self.env.resolution:
  164. if s_start == self.x0:
  165. children = [i for i in self.CLOSED if getDist(s_start, i) <= self.env.resolution*np.sqrt(3)]
  166. else:
  167. children = list(self.CHILDREN[s_start])
  168. s_start = children[np.argmin([cost(self,s_start,s_p) + self.g[s_p] for s_p in children])]
  169. # for all directed edges (u,v) with changed costs
  170. if CHANGED:
  171. self.km = self.km + heuristic_fun(self, s_start, s_last)
  172. for u in CHANGED:
  173. self.UpdateVertex(u)
  174. s_last = s_start
  175. self.ComputeShortestPath()
  176. self.Path = self.path()
  177. visualization(self)
  178. plt.show()
  179. def path(self):
  180. '''After ComputeShortestPath()
  181. returns, one can then follow a shortest path from s_start to
  182. s_goal by always moving from the current vertex s, starting
  183. at s_start. , to any successor s' that minimizes c(s,s') + g(s')
  184. until s_goal is reached (ties can be broken arbitrarily).'''
  185. path = []
  186. s_goal = self.xt
  187. s = self.x0
  188. ind = 0
  189. while s != s_goal:
  190. if s == self.x0:
  191. children = [i for i in self.CLOSED if getDist(s, i) <= self.env.resolution*np.sqrt(3)]
  192. else:
  193. children = list(self.CHILDREN[s])
  194. snext = children[np.argmin([cost(self,s,s_p) + self.g[s_p] for s_p in children])]
  195. path.append([s, snext])
  196. s = snext
  197. if ind > 100:
  198. break
  199. ind += 1
  200. return path
  201. if __name__ == '__main__':
  202. D_lite = D_star_Lite(1)
  203. #D_lite.ComputeShortestPath()
  204. a = time.time()
  205. #range_changed = D_lite.env.move_block(a=[0, 0, 1], s=0.5, block_to_move=1, mode='translation')
  206. #CHANGED = D_lite.updatecost(range_changed)
  207. D_lite.main()
  208. print('used time (s) is ' + str(time.time() - a))