PotentialField.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. """
  2. Potential_Field
  3. @author: huiming zhou
  4. """
  5. import os
  6. import sys
  7. import numpy as np
  8. import matplotlib.pyplot as plt
  9. from collections import deque
  10. sys.path.append(os.path.dirname(os.path.abspath(__file__)) +
  11. "/../../Search_based_Planning/")
  12. from Search_2D import plotting
  13. from Search_2D import env
  14. class PF:
  15. def __init__(self, s_start, s_goal):
  16. self.s_start = s_start
  17. self.s_goal = s_goal
  18. self.kp = 5.0
  19. self.eta = 400
  20. self.r = 30.0
  21. self.OL = 10
  22. self.rr = 2
  23. self.Env = env.Env()
  24. self.Plot = plotting.Plotting(s_start, s_goal)
  25. self.u_set = self.Env.motions # feasible input set
  26. self.obs = self.Env.obs # position of obstacles
  27. self.x = self.Env.x_range
  28. self.y = self.Env.y_range
  29. def run(self):
  30. pmap, minx, miny = self.calc_potential_field()
  31. d = np.hypot(self.s_start[0] - self.s_goal[0],
  32. self.s_start[1] - self.s_goal[1])
  33. ix = self.s_start[0] - minx
  34. iy = self.s_start[1] - miny
  35. gix = self.s_goal[0] - minx
  36. giy = self.s_goal[1] - miny
  37. self.draw_heatmap(pmap)
  38. plt.gcf().canvas.mpl_connect('key_release_event',
  39. lambda event: [exit(0) if event.key == 'escape' else None])
  40. plt.plot(ix, iy, "sk")
  41. plt.plot(gix, giy, "sm")
  42. rx, ry = [self.s_start[0]], [self.s_goal[0]]
  43. ids_rec = deque()
  44. while d >= 1:
  45. minp = float("inf")
  46. minix, miniy = -1, -1
  47. for u in self.u_set:
  48. inx = int(ix + u[0])
  49. iny = int(iy + u[1])
  50. if inx >= len(pmap) or iny >= len(pmap[0]) or inx < 0 or iny < 0:
  51. p = float("inf")
  52. print("test")
  53. else:
  54. p = pmap[inx][iny]
  55. if minp > p:
  56. minp = p
  57. minix = inx
  58. miniy = iny
  59. ix = minix
  60. iy = miniy
  61. xp = ix + minx
  62. yp = iy + miny
  63. d = np.hypot(self.s_goal[0] - xp, self.s_goal[1] - yp)
  64. rx.append(xp)
  65. ry.append(yp)
  66. if self.is_oscillation(ids_rec, ix, iy):
  67. print("Oscillation detected at ({},{})!".format(ix, iy))
  68. break
  69. plt.plot(ix, iy, ".r")
  70. plt.pause(0.01)
  71. return rx, ry
  72. def calc_potential_field(self):
  73. minx = 0
  74. miny = 0
  75. maxx = self.x - 1
  76. maxy = self.y - 1
  77. xw = maxx - minx
  78. yw = maxy - miny
  79. pmap = [[0.0 for i in range(yw)] for i in range(xw)]
  80. for ix in range(xw):
  81. x = ix + minx
  82. for iy in range(yw):
  83. y = iy + miny
  84. ug = self.calc_attractive_potential(x, y)
  85. uo = self.calc_repulsive_potential(x, y)
  86. uf = ug + uo
  87. pmap[ix][iy] = uf
  88. return pmap, minx, miny
  89. def calc_attractive_potential(self, x, y):
  90. return 0.5 * self.kp * \
  91. np.hypot(x - self.s_goal[0], y - self.s_goal[1])
  92. def calc_repulsive_potential(self, x, y):
  93. dmin = float("inf")
  94. for s in self.obs:
  95. d = np.hypot(x - s[0], y - s[1])
  96. if dmin >= d:
  97. dmin = d
  98. # calc repulsive potential
  99. dq = dmin
  100. if dq <= self.rr:
  101. if dq <= 0.8:
  102. dq = 0.8
  103. return 0.5 * self.eta * (1.0 / dq - 1.0 / self.rr) ** 2
  104. else:
  105. return 0.0
  106. def is_oscillation(self, ids_rec, ix, iy):
  107. ids_rec.append((ix, iy))
  108. if len(ids_rec) > self.OL:
  109. ids_rec.popleft()
  110. ids_set = set()
  111. for s in ids_rec:
  112. if s in ids_set:
  113. return True
  114. else:
  115. ids_set.add(s)
  116. return False
  117. @staticmethod
  118. def draw_heatmap(data):
  119. data = np.array(data).T
  120. plt.pcolor(data, vmax=100.0, cmap=plt.cm.Blues)
  121. def main():
  122. s_start = (5, 5)
  123. s_goal = (45, 25)
  124. pf = PF(s_start, s_goal)
  125. plt.grid(True)
  126. plt.axis("equal")
  127. _, _ = pf.run()
  128. plt.show()
  129. if __name__ == '__main__':
  130. print(__file__ + " start!!")
  131. main()