LPAstar.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. """
  2. LPA_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 queue
  11. from Search_2D import plotting
  12. from Search_2D import env
  13. class LpaStar:
  14. def __init__(self, x_start, x_goal, heuristic_type):
  15. self.xI, self.xG = x_start, x_goal
  16. self.heuristic_type = heuristic_type
  17. self.Env = env.Env() # class Env
  18. self.u_set = self.Env.motions # feasible input set
  19. self.obs = self.Env.obs # position of obstacles
  20. self.U = queue.QueuePrior() # priority queue / OPEN set
  21. self.g, self.rhs = {}, {}
  22. for i in range(self.Env.x_range):
  23. for j in range(self.Env.y_range):
  24. self.rhs[(i, j)] = float("inf")
  25. self.g[(i, j)] = float("inf")
  26. self.rhs[self.xI] = 0
  27. self.U.put(self.xI, [self.h(self.xI), 0])
  28. def searching(self):
  29. self.computePath()
  30. path = self.extract_path()
  31. return path
  32. def computePath(self):
  33. while self.U.top_key() < self.CalculateKey(self.xG) \
  34. or self.rhs[self.xG] != self.g[self.xG]:
  35. s = self.U.get()
  36. if self.g[s] > self.rhs[s]:
  37. self.g[s] = self.rhs[s]
  38. for x in self.get_neighbor(s):
  39. self.UpdateVertex(x)
  40. else:
  41. self.g[s] = float("inf")
  42. self.UpdateVertex(s)
  43. for x in self.get_neighbor(s):
  44. self.UpdateVertex(x)
  45. def extract_path(self):
  46. path = []
  47. s = self.xG
  48. while True:
  49. g_list = {}
  50. for x in self.get_neighbor(s):
  51. g_list[x] = self.g[x]
  52. s = min(g_list, key=g_list.get)
  53. if s == self.xI:
  54. return list(reversed(path))
  55. path.append(s)
  56. def get_neighbor(self, s):
  57. nei_list = set()
  58. for u in self.u_set:
  59. s_next = tuple([s[i] + u[i] for i in range(2)])
  60. if s_next not in self.obs:
  61. nei_list.add(s_next)
  62. return nei_list
  63. def CalculateKey(self, s):
  64. return [min(self.g[s], self.rhs[s]) + self.h(s),
  65. min(self.g[s], self.rhs[s])]
  66. def UpdateVertex(self, u):
  67. if u != self.xI:
  68. u_min = float("inf")
  69. for x in self.get_neighbor(u):
  70. u_min = min(u_min, self.g[x] + 1)
  71. self.rhs[u] = u_min
  72. self.U.check_remove(u)
  73. if self.g[u] != self.rhs[u]:
  74. self.U.put(u, self.CalculateKey(u))
  75. def h(self, s):
  76. heuristic_type = self.heuristic_type # heuristic type
  77. goal = self.xG # goal node
  78. if heuristic_type == "manhattan":
  79. return abs(goal[0] - s[0]) + abs(goal[1] - s[1])
  80. elif heuristic_type == "euclidean":
  81. return ((goal[0] - s[0]) ** 2 + (goal[1] - s[1]) ** 2) ** (1 / 2)
  82. else:
  83. print("Please choose right heuristic type!")
  84. @staticmethod
  85. def get_cost(x, u):
  86. """
  87. Calculate cost for this motion
  88. :param x: current node
  89. :param u: current input
  90. :return: cost for this motion
  91. :note: cost function could be more complicate!
  92. """
  93. return 1
  94. def main():
  95. x_start = (5, 5)
  96. x_goal = (45, 25)
  97. lpastar = LpaStar(x_start, x_goal, "manhattan")
  98. plot = plotting.Plotting(x_start, x_goal)
  99. path = lpastar.searching()
  100. plot.plot_grid("test")
  101. px = [x[0] for x in path]
  102. py = [x[1] for x in path]
  103. plt.plot(px, py, color='red', marker='o')
  104. plt.show()
  105. if __name__ == '__main__':
  106. main()