utils.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. """
  2. utils for collision check
  3. @author: huiming zhou
  4. """
  5. import math
  6. import numpy as np
  7. import pyrr
  8. import os
  9. import sys
  10. sys.path.append(os.path.dirname(os.path.abspath(__file__)) +
  11. "/../../Sampling-based Planning/")
  12. from rrt_2D import env
  13. from rrt_2D.rrt import Node
  14. class Utils:
  15. def __init__(self):
  16. self.env = env.Env()
  17. self.delta = 0.2
  18. self.obs_circle = self.env.obs_circle
  19. self.obs_rectangle = self.env.obs_rectangle
  20. self.obs_boundary = self.env.obs_boundary
  21. self.obs_vertex = self.get_obs_vertex()
  22. def get_obs_vertex(self):
  23. delta = self.delta
  24. obs_list = []
  25. for (ox, oy, w, h) in self.obs_rectangle:
  26. vertex_list = [[ox - delta, oy - delta],
  27. [ox + w + delta, oy - delta],
  28. [ox + w + delta, oy + h + delta],
  29. [ox - delta, oy + h + delta]]
  30. obs_list.append(vertex_list)
  31. return obs_list
  32. def is_intersect_segment(self, start, end, a, b):
  33. o, d = self.get_ray(start, end)
  34. v1 = [o[0] - a[0], o[1] - a[1]]
  35. v2 = [b[0] - a[0], b[1] - a[1]]
  36. v3 = [-d[1], d[0]]
  37. div = np.dot(v2, v3)
  38. if div == 0:
  39. div = 0.01
  40. t1 = np.linalg.norm(np.cross(v2, v1)) / div
  41. t2 = np.dot(v1, v3) / div
  42. if t1 >= 0 and 0 <= t2 <= 1:
  43. shot = Node((o[0] + t1 * d[0], o[1] + t1 * d[1]))
  44. dist_obs = self.get_dist(start, shot)
  45. dist_seg = self.get_dist(start, end)
  46. if dist_obs <= dist_seg:
  47. return True
  48. return False
  49. def is_collision(self, start, end):
  50. if self.is_inside_obs(start) or self.is_inside_obs(end):
  51. return True
  52. for (v1, v2, v3, v4) in self.obs_vertex:
  53. if self.is_intersect_segment(start, end, v1, v2) \
  54. or self.is_intersect_segment(start, end, v2, v3) \
  55. or self.is_intersect_segment(start, end, v3, v4) \
  56. or self.is_intersect_segment(start, end, v4, v1):
  57. return True
  58. return False
  59. def is_inside_obs(self, node):
  60. delta = self.delta
  61. for (x, y, r) in self.obs_circle:
  62. if math.hypot(node.x - x, node.y - y) <= r + delta:
  63. return True
  64. for (x, y, w, h) in self.obs_rectangle:
  65. if 0 <= node.x - (x - delta) <= w + 2 * delta \
  66. and 0 <= node.y - (y - delta) <= h + 2 * delta:
  67. return True
  68. for (x, y, w, h) in self.obs_boundary:
  69. if 0 <= node.x - (x - delta) <= w + 2 * delta \
  70. and 0 <= node.y - (y - delta) <= h + 2 * delta:
  71. return True
  72. return False
  73. @staticmethod
  74. def get_ray(start, end):
  75. orig = [start.x, start.y]
  76. direc = [end.x - start.x, end.y - start.y]
  77. return orig, direc
  78. @staticmethod
  79. def get_dist(start, end):
  80. return math.hypot(end.x - start.x, end.y - start.y)