#include #include "basic/basic.h" #include "geo/private/util/math_util.h" #include "geo/private/util/angle_util.h" namespace ns { namespace geo { double point_2_point_distance(const Position& point_1, const Position& point_2) { double x_difference = point_1.x - point_2.x; double y_difference = point_1.y - point_2.y; return sqrt(x_difference * x_difference + y_difference * y_difference); } double calculate_relative_angle(const Position& reference_position, const double& reference_angle, const Position& target_position) { double bearing_angle = atan2(target_position.y - reference_position.y, target_position.x - reference_position.x); return angle_modulus(angle_modulus(bearing_angle) - angle_modulus(reference_angle)); } double angle_modulus(double angle) { return std::fmod(angle + 2 * c_pi(), 2 * c_pi()); } bool is_inside_or_on_polygon(const Eigen::Vector2d& p, const Eigen::Matrix2Xd& v) { const Eigen::Index n = v.cols(); int cnt = 0; double py = p(1); bool rel_j = (v(1, n - 1) <= py); for (Eigen::Index i = 0, j = n - 1; i < n; ++i, j = i - 1) { bool rel_i = (v(1, i) <= py); if (rel_i != rel_j) { Eigen::Matrix2d m; m << p - v.col(i), v.col(j) - v.col(i); double det = m.determinant(); if (std::abs(det) < 1.e-6) { // on the edge i => j return true; } // increase the count only when the point is on the left side of the // segment cnt += (int)((v(1, i) < v(1, j)) == (det < 0)); } else if (v(1, i) == py) { if (v(1, j) == py) { // i => j is horizontal if ((p(0) - v(0, i)) * (p(0) - v(0, j)) <= 0) { // on the edge return true; } } else if (p(0) == v(0, i)) { // exactly on the vertex return true; } } rel_j = rel_i; } return ((cnt & 1) == 1); } Eigen::Matrix2Xd get_outline(const Eigen::Vector2d& pos, double yaw, double length, double width) { Eigen::Matrix2Xd vehicle_outline(2, 5); vehicle_outline.col(0) = pos; const auto h_l = length / 2; const auto h_w = width / 2; const Eigen::Vector2d v_y(std::cos(yaw), std::sin(yaw)); const Eigen::Vector2d v_v_y(std::cos(yaw + EIGEN_PI / 2), std::sin(yaw + EIGEN_PI / 2)); Eigen::Vector2d p_f = pos + h_l * v_y; Eigen::Vector2d p_r = pos - h_l * v_y; // point front left vehicle_outline.col(1) = p_f + h_w * v_v_y; // point front right vehicle_outline.col(2) = p_f - h_w * v_v_y; // point rear left vehicle_outline.col(3) = p_r + h_w * v_v_y; // point rear right vehicle_outline.col(4) = p_r - h_w * v_v_y; return vehicle_outline; } double distance(const Eigen::Vector2d& l_ps, const Eigen::Vector2d& l_pe, const Eigen::Vector2d& p) { auto line = l_pe - l_ps; auto a = l_pe - p; auto b = l_ps - p; auto sqr = [](double x) { return x * x; }; const double inv_sqrlen = 1. / line.squaredNorm(); const double t = (line(0) * a(0) + line(1) * a(1)) * inv_sqrlen; double sqr_dist; if (t < 0.) { sqr_dist = a.squaredNorm(); } else if (t <= 1.) { sqr_dist = sqr(line(0) * b(1) - line(1) * b(0)) * inv_sqrlen; } else { // t>1. sqr_dist = b.squaredNorm(); } return std::sqrt(sqr_dist); } // Get vector to vector angel double get_angle_v2v(const Eigen::Vector2d& v1, const Eigen::Vector2d& v2) { Eigen::Matrix2d m; m << v1, v2; double a = std::atan2(m.determinant(), v1.dot(v2)); // normalize to [0, 2π] if (a < 0) { a += 2 * EIGEN_PI; } return a; } double get_heading(const Eigen::Vector2d& v1, const Eigen::Vector2d& v2) { double dx = v2.x() - v1.x(); double dy = v2.y() - v1.y(); return std::atan2(dy, dx); } } // namespace geo } // namespace ns