PotentialField.py 4.2 KB

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