• 【自动驾驶】碰撞检测算法


    参考链接:

    【自动驾驶】碰撞检测算法 - 知乎

    【规划】Box2d::HasOverlap() 碰撞检测接口详解_lemon_zy的博客-CSDN博客_box2d碰撞检测

    一个常用方法即为超平面分离定理(Hyperplane Separation Theorem),用于检测N维欧几里得空间内的凸集是否存在交集,严格的定义可以参考维基百科。其二维情形被称为分离轴定理(Separating Axis Theorem),简要描述如下:

    两个平面凸集不相交的充要条件是,存在某条直线(即分离轴),使得两平面在直线上的投影不相交,类似的可以写出否命题。显然,要证明相交我们需要穷尽所有的直线,这是不可能的。幸运的是,对于凸多边形,我们只需要检查其边所在的直线是否为分离线(不是分离轴)即可。(大家可以思考一下对于凹多边形和圆怎么实现)

    自动驾驶的范畴内,对于障碍物一般用平面矩形表示(更高精度的会用平面凸多边形),对于两个矩形来说,我们只需要遍历4条边(每个矩形各自相邻的两条边)即可,只要这四条边有一条为分离轴那么两个矩形就不相交。相反,若两个矩形相交,则四条边都不是分离轴(比较自车和目标轮廓在分离轴上投影长度之和的一半,与投影距离的大小,投影距离全部小于投影及有重叠hasOverLap),即他们在上面的投影都有重合。

    为了高效地表示平面矩形,我们一般会这样定义:

    1. struct Box2d {
    2. float center_x_;
    3. float center_y_;
    4. float length_;
    5. float width_;
    6. float half_length_;
    7. float half_width_;
    8. float heading_;
    9. float cos_heading_;
    10. float sin_heading_;
    11. float min_x_;
    12. float max_x_;
    13. float min_y_;
    14. float max_y_;
    15. struct Vec2d corners_[4];
    16. };

    投影原理:针对自车两条相邻边和障碍物相邻的两条边做投影

     我们只需要比较自车和目标轮廓在分离轴上投影长度之和的一半,与投影距离的大小,即可判断二者投影有没有相交。显然,自车在分离轴上的投影长度为length_。

    以下代码是对应Vehicle相邻的两条边上的投影计算

    1. std::abs(shift_x * cos_heading_ + shift_y * sin_heading_) <=
    2. std::abs(dx3 * cos_heading_ + dy3 * sin_heading_) +
    3. std::abs(dx4 * cos_heading_ + dy4 * sin_heading_) +
    4. half_length_ &&
    5. std::abs(shift_x * sin_heading_ - shift_y * cos_heading_) <=
    6. std::abs(dx3 * sin_heading_ - dy3 * cos_heading_) +
    7. std::abs(dx4 * sin_heading_ - dy4 * cos_heading_) +
    8. half_width_

     即vehicle任意一点不在obstacle对应的橙色虚线框内。

     

    以下代码是对应Obstacle相邻的两条边上的投影计算

    1. std::abs(shift_x * box.cos_heading() + shift_y * box.sin_heading()) <=
    2. std::abs(dx1 * box.cos_heading() + dy1 * box.sin_heading()) +
    3. std::abs(dx2 * box.cos_heading() + dy2 * box.sin_heading()) +
    4. box.half_length() &&
    5. std::abs(shift_x * box.sin_heading() - shift_y * box.cos_heading()) <=
    6. std::abs(dx1 * box.sin_heading() - dy1 * box.cos_heading()) +
    7. std::abs(dx2 * box.sin_heading() - dy2 * box.cos_heading()) +
    8. box.half_width()

     

    Box2d::HasOverlap(const Box2d &box) 

    1. bool Box2d::HasOverlap(const Box2d &box) const {
    2. if (box.max_x() < min_x() || box.min_x() > max_x() || box.max_y() < min_y() ||
    3. box.min_y() > max_y()) {
    4. return false;
    5. }
    6. const double shift_x = box.center_x() - center_.x();
    7. const double shift_y = box.center_y() - center_.y();
    8. const double dx1 = cos_heading_ * half_length_;
    9. const double dy1 = sin_heading_ * half_length_;
    10. const double dx2 = sin_heading_ * half_width_;
    11. const double dy2 = -cos_heading_ * half_width_;
    12. const double dx3 = box.cos_heading() * box.half_length();
    13. const double dy3 = box.sin_heading() * box.half_length();
    14. const double dx4 = box.sin_heading() * box.half_width();
    15. const double dy4 = -box.cos_heading() * box.half_width();
    16. return std::abs(shift_x * cos_heading_ + shift_y * sin_heading_) <=
    17. std::abs(dx3 * cos_heading_ + dy3 * sin_heading_) +
    18. std::abs(dx4 * cos_heading_ + dy4 * sin_heading_) +
    19. half_length_ &&
    20. std::abs(shift_x * sin_heading_ - shift_y * cos_heading_) <=
    21. std::abs(dx3 * sin_heading_ - dy3 * cos_heading_) +
    22. std::abs(dx4 * sin_heading_ - dy4 * cos_heading_) +
    23. half_width_ &&
    24. std::abs(shift_x * box.cos_heading() + shift_y * box.sin_heading()) <=
    25. std::abs(dx1 * box.cos_heading() + dy1 * box.sin_heading()) +
    26. std::abs(dx2 * box.cos_heading() + dy2 * box.sin_heading()) +
    27. box.half_length() &&
    28. std::abs(shift_x * box.sin_heading() - shift_y * box.cos_heading()) <=
    29. std::abs(dx1 * box.sin_heading() - dy1 * box.cos_heading()) +
    30. std::abs(dx2 * box.sin_heading() - dy2 * box.cos_heading()) +
    31. box.half_width();
    32. }

     

  • 相关阅读:
    Nodejs -- Express中间件的概念及基本使用
    数字信号处理2: 离散信号与系统的频谱分析
    Rust 原生类型
    数字通信测量仪器5201数据网络测试仪
    同为科技(TOWE)智能机柜PDU助力上海华为数据中心完善机房末端配电
    Git远程仓库和多人协作介绍及使用
    Redis 图形化桌面客户端
    入手不亏,4款简单易用的典藏软件,真正的电脑利器
    驱动开发:内核扫描SSDT挂钩状态
    我是如何使用ChatGPT和CoPilot作为编码助手的
  • 原文地址:https://blog.csdn.net/zhengshifeng123/article/details/125659950