D_star.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. """
  2. D_star 2D
  3. @author: huiming zhou
  4. """
  5. import os
  6. import sys
  7. import matplotlib.pyplot as plt
  8. sys.path.append(os.path.dirname(os.path.abspath(__file__)) +
  9. "/../../Search-based Planning/")
  10. from Search_2D import plotting
  11. from Search_2D import env
  12. class Dstar:
  13. def __init__(self, x_start, x_goal):
  14. self.xI, self.xG = x_start, x_goal
  15. self.Env = env.Env()
  16. self.Plot = plotting.Plotting(self.xI, self.xG)
  17. self.u_set = self.Env.motions
  18. self.obs = self.Env.obs
  19. self.x = self.Env.x_range
  20. self.y = self.Env.y_range
  21. self.fig = plt.figure()
  22. self.OPEN = set()
  23. self.t = {}
  24. self.PARENT = {}
  25. self.h = {self.xG: 0}
  26. self.k = {}
  27. self.path = []
  28. for i in range(self.Env.x_range):
  29. for j in range(self.Env.y_range):
  30. self.t[(i, j)] = 'NEW'
  31. self.k[(i, j)] = 0
  32. self.PARENT[(i, j)] = None
  33. def run(self, s_start, s_end):
  34. self.insert(s_end, 0)
  35. while True:
  36. self.process_state()
  37. if self.t[s_start] == 'CLOSED':
  38. break
  39. self.path = self.extract_path(s_start, s_end)
  40. self.Plot.plot_grid("Dynamic A* (D*)")
  41. self.plot_path(self.path)
  42. self.fig.canvas.mpl_connect('button_press_event', self.on_press)
  43. plt.show()
  44. def on_press(self, event):
  45. x, y = event.xdata, event.ydata
  46. if x < 0 or x > self.x - 1 or y < 0 or y > self.y - 1:
  47. print("Please choose right area!")
  48. else:
  49. x, y = int(x), int(y)
  50. print("Add obstacle at: x =", x, ",", "y =", y)
  51. self.obs.add((x, y))
  52. plt.plot(x, y, 'sk')
  53. if (x, y) in self.path:
  54. s = self.xI
  55. while s != self.xG:
  56. if self.PARENT[s] in self.obs:
  57. self.modify(s)
  58. continue
  59. s = self.PARENT[s]
  60. self.path = self.extract_path(self.xI, self.xG)
  61. self.plot_path(self.path)
  62. self.fig.canvas.draw_idle()
  63. def extract_path(self, s_start, s_end):
  64. path = []
  65. s = s_start
  66. while True:
  67. s = self.PARENT[s]
  68. if s == s_end:
  69. return path
  70. path.append(s)
  71. def process_state(self):
  72. s = self.min_state()
  73. if s is None:
  74. return -1
  75. k_old = self.get_k_min()
  76. self.delete(s)
  77. if k_old < self.h[s]:
  78. for s_n in self.get_neighbor(s):
  79. if self.h[s_n] <= k_old and self.h[s] > self.h[s_n] + self.cost(s_n, s):
  80. self.PARENT[s] = s_n
  81. self.h[s] = self.h[s_n] + self.cost(s_n, s)
  82. if k_old == self.h[s]:
  83. for s_n in self.get_neighbor(s):
  84. if self.t[s_n] == 'NEW' or \
  85. (self.PARENT[s_n] == s and self.h[s_n] != self.h[s] + self.cost(s, s_n)) or \
  86. (self.PARENT[s_n] != s and self.h[s_n] > self.h[s] + self.cost(s, s_n)):
  87. self.PARENT[s_n] = s
  88. self.insert(s_n, self.h[s] + self.cost(s, s_n))
  89. else:
  90. for s_n in self.get_neighbor(s):
  91. if self.t[s_n] == 'NEW' or \
  92. (self.PARENT[s_n] == s and self.h[s_n] != self.h[s] + self.cost(s, s_n)):
  93. self.PARENT[s_n] = s
  94. self.insert(s_n, self.h[s] + self.cost(s, s_n))
  95. else:
  96. if self.PARENT[s_n] != s and self.h[s_n] > self.h[s] + self.cost(s, s_n):
  97. self.insert(s, self.h[s])
  98. else:
  99. if self.PARENT[s_n] != s and \
  100. self.h[s] > self.h[s_n] + self.cost(s_n, s) and \
  101. self.t[s_n] == 'CLOSED' and \
  102. self.h[s_n] > k_old:
  103. self.insert(s_n, self.h[s_n])
  104. return self.get_k_min()
  105. def min_state(self):
  106. if not self.OPEN:
  107. return None
  108. return min(self.OPEN, key=lambda x: self.k[x])
  109. def get_k_min(self):
  110. if not self.OPEN:
  111. return -1
  112. return min([self.k[x] for x in self.OPEN])
  113. def insert(self, s, h_new):
  114. if self.t[s] == 'NEW':
  115. self.k[s] = h_new
  116. elif self.t[s] == 'OPEN':
  117. self.k[s] = min(self.k[s], h_new)
  118. elif self.t[s] == 'CLOSED':
  119. self.k[s] = min(self.h[s], h_new)
  120. self.h[s] = h_new
  121. self.t[s] = 'OPEN'
  122. self.OPEN.add(s)
  123. def delete(self, s):
  124. if self.t[s] == 'OPEN':
  125. self.t[s] = 'CLOSED'
  126. self.OPEN.remove(s)
  127. def modify(self, s):
  128. self.modify_cost(s)
  129. while True:
  130. k_min = self.process_state()
  131. if k_min >= self.h[s]:
  132. break
  133. def modify_cost(self, s):
  134. if self.t[s] == 'CLOSED':
  135. self.insert(s, self.h[self.PARENT[s]] + self.cost(s, self.PARENT[s]))
  136. def get_neighbor(self, s):
  137. nei_list = set()
  138. for u in self.u_set:
  139. s_next = tuple([s[i] + u[i] for i in range(2)])
  140. if s_next not in self.obs:
  141. nei_list.add(s_next)
  142. return nei_list
  143. def cost(self, s_start, s_end):
  144. if s_start in self.obs or s_end in self.obs:
  145. return float("inf")
  146. return 1
  147. @staticmethod
  148. def plot_path(path):
  149. px = [x[0] for x in path]
  150. py = [x[1] for x in path]
  151. plt.plot(px, py, marker='o')
  152. def main():
  153. s_start = (5, 5)
  154. s_goal = (45, 25)
  155. dstar = Dstar(s_start, s_goal)
  156. dstar.run(s_start, s_goal)
  157. if __name__ == '__main__':
  158. main()