You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

math_util.cpp 4.3 kB

2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #include <cmath>
  2. #include "basic/basic.h"
  3. #include "geo/private/util/math_util.h"
  4. #include "geo/private/util/angle_util.h"
  5. namespace ns
  6. {
  7. namespace geo
  8. {
  9. double point_2_point_distance(const Position& point_1, const Position& point_2)
  10. {
  11. double x_difference = point_1.x - point_2.x;
  12. double y_difference = point_1.y - point_2.y;
  13. return sqrt(x_difference * x_difference + y_difference * y_difference);
  14. }
  15. double calculate_relative_angle(const Position& reference_position,
  16. const double& reference_angle,
  17. const Position& target_position)
  18. {
  19. double bearing_angle = atan2(target_position.y - reference_position.y,
  20. target_position.x - reference_position.x);
  21. return angle_modulus(angle_modulus(bearing_angle) -
  22. angle_modulus(reference_angle));
  23. }
  24. double angle_modulus(double angle)
  25. {
  26. return std::fmod(angle + 2 * c_pi(), 2 * c_pi());
  27. }
  28. bool is_inside_or_on_polygon(const Eigen::Vector2d& p, const Eigen::Matrix2Xd& v)
  29. {
  30. const Eigen::Index n = v.cols();
  31. int cnt = 0;
  32. double py = p(1);
  33. bool rel_j = (v(1, n - 1) <= py);
  34. for (Eigen::Index i = 0, j = n - 1; i < n; ++i, j = i - 1)
  35. {
  36. bool rel_i = (v(1, i) <= py);
  37. if (rel_i != rel_j)
  38. {
  39. Eigen::Matrix2d m;
  40. m << p - v.col(i), v.col(j) - v.col(i);
  41. double det = m.determinant();
  42. if (std::abs(det) < 1.e-6)
  43. {
  44. // on the edge i => j
  45. return true;
  46. }
  47. // increase the count only when the point is on the left side of the
  48. // segment
  49. cnt += (int)((v(1, i) < v(1, j)) == (det < 0));
  50. }
  51. else if (v(1, i) == py)
  52. {
  53. if (v(1, j) == py)
  54. {
  55. // i => j is horizontal
  56. if ((p(0) - v(0, i)) * (p(0) - v(0, j)) <= 0)
  57. {
  58. // on the edge
  59. return true;
  60. }
  61. }
  62. else if (p(0) == v(0, i))
  63. {
  64. // exactly on the vertex
  65. return true;
  66. }
  67. }
  68. rel_j = rel_i;
  69. }
  70. return ((cnt & 1) == 1);
  71. }
  72. Eigen::Matrix2Xd get_outline(const Eigen::Vector2d& pos,
  73. double yaw, double length, double width)
  74. {
  75. Eigen::Matrix2Xd vehicle_outline(2, 5);
  76. vehicle_outline.col(0) = pos;
  77. const auto h_l = length / 2;
  78. const auto h_w = width / 2;
  79. const Eigen::Vector2d v_y(std::cos(yaw), std::sin(yaw));
  80. const Eigen::Vector2d v_v_y(std::cos(yaw + EIGEN_PI / 2),
  81. std::sin(yaw + EIGEN_PI / 2));
  82. Eigen::Vector2d p_f = pos + h_l * v_y;
  83. Eigen::Vector2d p_r = pos - h_l * v_y;
  84. // point front left
  85. vehicle_outline.col(1) = p_f + h_w * v_v_y;
  86. // point front right
  87. vehicle_outline.col(2) = p_f - h_w * v_v_y;
  88. // point rear left
  89. vehicle_outline.col(3) = p_r + h_w * v_v_y;
  90. // point rear right
  91. vehicle_outline.col(4) = p_r - h_w * v_v_y;
  92. return vehicle_outline;
  93. }
  94. double distance(const Eigen::Vector2d& l_ps,
  95. const Eigen::Vector2d& l_pe,
  96. const Eigen::Vector2d& p)
  97. {
  98. auto line = l_pe - l_ps;
  99. auto a = l_pe - p;
  100. auto b = l_ps - p;
  101. auto sqr = [](double x) { return x * x; };
  102. const double inv_sqrlen = 1. / line.squaredNorm();
  103. const double t = (line(0) * a(0) + line(1) * a(1)) * inv_sqrlen;
  104. double sqr_dist;
  105. if (t < 0.)
  106. {
  107. sqr_dist = a.squaredNorm();
  108. }
  109. else if (t <= 1.)
  110. {
  111. sqr_dist = sqr(line(0) * b(1) - line(1) * b(0)) * inv_sqrlen;
  112. }
  113. else
  114. {
  115. // t>1.
  116. sqr_dist = b.squaredNorm();
  117. }
  118. return std::sqrt(sqr_dist);
  119. }
  120. // Get vector to vector angel
  121. double get_angle_v2v(const Eigen::Vector2d& v1, const Eigen::Vector2d& v2)
  122. {
  123. Eigen::Matrix2d m;
  124. m << v1, v2;
  125. double a = std::atan2(m.determinant(), v1.dot(v2));
  126. // normalize to [0, 2π]
  127. if (a < 0)
  128. {
  129. a += 2 * EIGEN_PI;
  130. }
  131. return a;
  132. }
  133. double get_heading(const Eigen::Vector2d& v1, const Eigen::Vector2d& v2)
  134. {
  135. double dx = v2.x() - v1.x();
  136. double dy = v2.y() - v1.y();
  137. return std::atan2(dy, dx);
  138. }
  139. } // namespace geo
  140. } // namespace ns