ARAstar.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. """
  2. ARA_star 2D (Anytime Repairing A*)
  3. @author: huiming zhou
  4. """
  5. import os
  6. import sys
  7. sys.path.append(os.path.dirname(os.path.abspath(__file__)) +
  8. "/../../Search-based Planning/")
  9. from Search_2D import queue
  10. from Search_2D import plotting
  11. from Search_2D import env
  12. class AraStar:
  13. def __init__(self, x_start, x_goal, e, heuristic_type):
  14. self.xI, self.xG = x_start, x_goal
  15. self.heuristic_type = heuristic_type
  16. self.Env = env.Env() # class Env
  17. self.u_set = self.Env.motions # feasible input set
  18. self.obs = self.Env.obs # position of obstacles
  19. self.e = e # initial weight
  20. self.g = {self.xI: 0, self.xG: float("inf")} # cost to come
  21. self.OPEN = queue.QueuePrior() # priority queue / OPEN
  22. self.CLOSED = set() # closed set
  23. self.INCONS = [] # incons set
  24. self.PARENT = {self.xI: self.xI} # relations
  25. self.path = [] # planning path
  26. self.visited = [] # order of visited nodes
  27. def searching(self):
  28. self.OPEN.put(self.xI, self.fvalue(self.xI))
  29. self.ImprovePath()
  30. self.path.append(self.extract_path())
  31. while self.update_e() > 1: # continue condition
  32. self.e -= 0.5 # increase weight
  33. OPEN_mid = [x for (p, x) in self.OPEN.enumerate()] + self.INCONS # combine two sets
  34. self.OPEN = queue.QueuePrior()
  35. self.OPEN.put(self.xI, self.fvalue(self.xI))
  36. for x in OPEN_mid:
  37. self.OPEN.put(x, self.fvalue(x)) # update priority
  38. self.INCONS = []
  39. self.CLOSED = set()
  40. self.ImprovePath() # improve path
  41. self.path.append(self.extract_path())
  42. return self.path, self.visited
  43. def ImprovePath(self):
  44. """
  45. :return: a e'-suboptimal path
  46. """
  47. visited_each = []
  48. while (self.fvalue(self.xG) >
  49. min([self.fvalue(x) for (p, x) in self.OPEN.enumerate()])):
  50. s = self.OPEN.get()
  51. if s not in self.CLOSED:
  52. self.CLOSED.add(s)
  53. for u_next in self.u_set:
  54. s_next = tuple([s[i] + u_next[i] for i in range(len(s))])
  55. if s_next not in self.obs:
  56. new_cost = self.g[s] + self.get_cost(s, u_next)
  57. if s_next not in self.g or new_cost < self.g[s_next]:
  58. self.g[s_next] = new_cost
  59. self.PARENT[s_next] = s
  60. visited_each.append(s_next)
  61. if s_next not in self.CLOSED:
  62. self.OPEN.put(s_next, self.fvalue(s_next))
  63. else:
  64. self.INCONS.append(s_next)
  65. self.visited.append(visited_each)
  66. def update_e(self):
  67. c_OPEN, c_INCONS = float("inf"), float("inf")
  68. if self.OPEN:
  69. c_OPEN = min(self.g[x] + self.Heuristic(x) for (p, x) in self.OPEN.enumerate())
  70. if self.INCONS:
  71. c_INCONS = min(self.g[x] + self.Heuristic(x) for x in self.INCONS)
  72. if min(c_OPEN, c_INCONS) == float("inf"):
  73. return 1
  74. return min(self.e, self.g[self.xG] / min(c_OPEN, c_INCONS))
  75. def fvalue(self, x):
  76. return self.g[x] + self.e * self.Heuristic(x)
  77. def extract_path(self):
  78. """
  79. Extract the path based on the relationship of nodes.
  80. :return: The planning path
  81. """
  82. path_back = [self.xG]
  83. x_current = self.xG
  84. while True:
  85. x_current = self.PARENT[x_current]
  86. path_back.append(x_current)
  87. if x_current == self.xI:
  88. break
  89. return list(path_back)
  90. @staticmethod
  91. def get_cost(x, u):
  92. """
  93. Calculate cost for this motion
  94. :param x: current node
  95. :param u: input
  96. :return: cost for this motion
  97. :note: cost function could be more complicate!
  98. """
  99. return 1
  100. def Heuristic(self, state):
  101. """
  102. Calculate heuristic.
  103. :param state: current node (state)
  104. :return: heuristic
  105. """
  106. heuristic_type = self.heuristic_type
  107. goal = self.xG
  108. if heuristic_type == "manhattan":
  109. return abs(goal[0] - state[0]) + abs(goal[1] - state[1])
  110. elif heuristic_type == "euclidean":
  111. return ((goal[0] - state[0]) ** 2 + (goal[1] - state[1]) ** 2) ** (1 / 2)
  112. else:
  113. print("Please choose right heuristic type!")
  114. def main():
  115. x_start = (5, 5) # Starting node
  116. x_goal = (45, 5) # Goal node
  117. arastar = AraStar(x_start, x_goal, 2.5, "euclidean")
  118. plot = plotting.Plotting(x_start, x_goal)
  119. fig_name = "Anytime Repairing A* (ARA*)"
  120. path, visited = arastar.searching()
  121. plot.animation_ara_star(path, visited, fig_name)
  122. if __name__ == '__main__':
  123. main()