碰撞检测 | 图解线段几何与线段相交检测原理(附ROS C++可视化)

目录

  • 0 专栏介绍
  • 1 线段与线段相交检测
  • 2 线段与圆相交检测
  • 3 线段与矩形相交检测
  • 4 算法仿真与可视化
    • 4.1 核心算法
    • 4.2 仿真实验

0 专栏介绍

🔥课设、毕设、创新竞赛必备!🔥本专栏涉及更高阶的运动规划算法轨迹优化实战,包括:曲线生成、碰撞检测、安全走廊、优化建模(QP、SQP、NMPC、iLQR等)、轨迹优化(梯度法、曲线法等),每个算法都包含代码实现加深理解

🚀详情:运动规划实战进阶:轨迹优化篇


本期实现如下的碰撞检测效果

在这里插入图片描述

1 线段与线段相交检测

线段相交检测是广义多边形计算几何的基础,一般分为两个步骤:快速排斥跨立实验

  • 快速排斥

    如图所示,快速排斥通过检测两条线段对应的轴对齐包围盒来快速检测潜在的相交可能性,如果两个AABB不重叠,则表明一定不相交,否则需要进一步进行跨立实验

在这里插入图片描述

  • 跨立实验

    跨立实验通过向量积运算判断线段的跨立性:设两条线段的起始点分别为 s 1 \boldsymbol{s}_1 s1 e 1 \boldsymbol{e}_1 e1 s 2 \boldsymbol{s}_2 s2 e 2 \boldsymbol{e}_2 e2,选定其中一条线段 s 1 e 1 = e 1 − s 1 \boldsymbol{s}_1\boldsymbol{e}_1=\boldsymbol{e}_1-\boldsymbol{s}_1 s1e1=e1s1和该线段端点与另一条线段的两个端点连成的向量 s 1 s 2 \boldsymbol{s}_1\boldsymbol{s}_2 s1s2 s 1 e 2 \boldsymbol{s}_1\boldsymbol{e}_2 s1e2,若 ( s 1 e 1 × s 1 s 2 ) ⋅ ( s 1 e 1 × s 1 e 2 ) < 0 \left( \boldsymbol{s}_1\boldsymbol{e}_1\times \boldsymbol{s}_1\boldsymbol{s}_2 \right) \cdot \left( \boldsymbol{s}_1\boldsymbol{e}_1\times \boldsymbol{s}_1\boldsymbol{e}_2 \right) <0 (s1e1×s1s2)(s1e1×s1e2)<0则表明另一条线段的两个端点分布在当前线段左右两侧,称线段 s 2 e 2 \boldsymbol{s}_2\boldsymbol{e}_2 s2e2跨立线段 s 1 e 1 \boldsymbol{s}_1\boldsymbol{e}_1 s1e1当前仅当两条线段互相跨立时,线段相交

在这里插入图片描述

算法流程如下所示

在这里插入图片描述

2 线段与圆相交检测

如图所示,设线段参数方程为

x = s + t ⋅ ( e − s ) , t ∈ [ 0 , 1 ] \boldsymbol{x}=\boldsymbol{s}+t\cdot \left( \boldsymbol{e}-\boldsymbol{s} \right) , t\in \left[ 0,1 \right] x=s+t(es),t[0,1]

圆的方程为

∥ x − c ∥ 2 = r 2 \left\| \boldsymbol{x}-\boldsymbol{c} \right\| ^2=r^2 xc2=r2

联立可得

∥ e − s ∥ 2 t 2 + 2 ( e − s ) T ( s − c ) t + ∥ s − c ∥ 2 − r 2 = 0 \left\| \boldsymbol{e}-\boldsymbol{s} \right\| ^2t^2+2\left( \boldsymbol{e}-\boldsymbol{s} \right) ^T\left( \boldsymbol{s}-\boldsymbol{c} \right) t+\left\| \boldsymbol{s}-\boldsymbol{c} \right\| ^2-r^2=0 es2t2+2(es)T(sc)t+sc2r2=0

该二次方程的判别式为 Δ \varDelta Δ,若 Δ < 0 \varDelta <0 Δ<0则一定不相交;若 Δ ⩾ 0 \varDelta \geqslant 0 Δ0 ∃ t ∈ [ 0 , 1 ] \exists t\in \left[ 0,1 \right] t[0,1]则相交,其中区间限制保证了线段相交而非直线相交。

在这里插入图片描述

3 线段与矩形相交检测

线段与多边形是否相交可以简单地通过两两线段的相交检测判定,但对于矩形而言,可以特化为两步

  1. 若线段端点在矩形内部则一定相交;
  2. 若线段与矩形对角线相交则一定相交。当上述两步都不相交时说明线段与矩形相离。

步骤2与线段相交检测相同,这里仅介绍步骤1。

在这里插入图片描述

如图所示,对于轴对齐包围盒,仅需要对端点进行AABB碰撞检测即可;对于旋转包围盒,则按照圆-矩形碰撞检测的思路,将中心向量 v \boldsymbol{v} v绕矩形中心反向旋转 α \alpha α,再按AABB碰撞检测即可。可以参考:

  • 碰撞检测 | 详解圆-矩形碰撞检测与N圆覆盖模型(附ROS C++可视化)
  • 碰撞检测 | 详解矩形AABB与OBB碰撞检测算法(附ROS C++可视化)

4 算法仿真与可视化

4.1 核心算法

核心算法如下所示

  • 线段与线段相交检测

    bool VLineSegment::isLineIntersaction(const Ogre::Vector3& start, const Ogre::Vector3& end) const
    {
      if (length_ <= kMathEpsilon || std::hypot(start.x - end.x, start.y - end.y) <= kMathEpsilon)
        return false;
      if (_endPointTest(start, end))
        return true;
      if (!_rapidTest(start, end))
        return false;
      if (_straddleTest(start, end))
        return true;
      return false;
    }
    
  • 线段与圆相交检测

    auto isCollisionWithCircle = [&](const Ogre::Vector3& center, const float radius) -> bool {
         if (std::hypot(center.x - start_.x, center.y - start_.y) < radius)
           return true;
         if (std::hypot(center.x - end_.x, center.y - end_.y) < radius)
           return true;
         const float a = innerProduct(end_ - start_, end_ - start_);
         const float b = 2 * innerProduct(end_ - start_, start_ - center);
         const float c = innerProduct(start_ - center, start_ - center) - radius * radius;
         const float delta = b * b - 4 * a * c;
         if (delta < kMathEpsilon)
           return false;
         const float t1 = (-b + std::sqrt(delta)) / (2 * a);
         const float t2 = (-b - std::sqrt(delta)) / (2 * a);
         if (isWithin(t1, 0.0f, 1.0f) || isWithin(t2, 0.0f, 1.0f))
           return true;
         return false;
       };
    
     auto other_circle = std::dynamic_pointer_cast<VCircle>(other);
     const auto& other_circle_center = other_circle->center();
     const auto& other_circle_radius = other_circle->radius();
     return isCollisionWithCircle(other_circle_center, other_circle_radius);
    
  • 线段与矩形相交检测

    const auto other_rect = std::dynamic_pointer_cast<VRectangle>(other);
    const float cos_angle = other_rect->cos_angle();
    const float sin_angle = other_rect->sin_angle();
    const float cx = other_rect->center().x, cy = other_rect->center().y;
    const float half_l = 0.5f * std::fabs(other_rect->length()), half_w = 0.5f * std::fabs(other_rect->width());
    
    auto isPointInRect = [&](const Ogre::Vector3& pt) -> bool {
      const float pt2rect_x = pt.x - cx;
      const float pt2rect_y = pt.y - cy;
      const float rx = pt2rect_x * cos_angle + pt2rect_y * sin_angle + cx;
      const float ry = -pt2rect_x * sin_angle + pt2rect_y * cos_angle + cy;
      return (rx <= cx + half_l && rx >= cx - half_l && ry <= cy + half_w && ry >= cy - half_w);
    };
    if (isPointInRect(start_) || isPointInRect(end_))
      return true;
    
    const float theta = -2 * std::atan(half_w / half_l);
    const auto lt_pt = other_rect->left_top_point();
    const auto rb_pt = 2 * other_rect->center() - lt_pt;
    const auto lt2center = lt_pt - other_rect->center();
    const Ogre::Vector3 lb_pt(lt2center.x * std::cos(theta) - lt2center.y * std::sin(theta) + cx,
                              lt2center.x * std::sin(theta) + lt2center.y * std::cos(theta) + cy, 0.0f);
    const auto rt_pt = 2 * other_rect->center() - lb_pt;
    
    if (isLineIntersaction(lt_pt, rb_pt) || isLineIntersaction(rt_pt, lb_pt))
      return true;
    
    return false;
    

4.2 仿真实验

通过Rviz->Add New Tool添加Polygon Simulation插件

s

开启碰撞检测功能后,验证 N N N圆覆盖碰撞检测算法

  • 线段与线段相交检测

在这里插入图片描述

  • 线段与圆相交检测

在这里插入图片描述

  • 线段与矩形相交检测

在这里插入图片描述

完整工程代码请联系下方博主名片获取


🔥 更多精彩专栏

  • 《ROS从入门到精通》
  • 《Pytorch深度学习实战》
  • 《机器学习强基计划》
  • 《运动规划实战精讲》

👇源码获取 · 技术交流 · 抱团学习 · 咨询分享 请联系👇

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/879090.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

吸浮毛宠物空气净化器推荐,希喂、小米、有哈宠物空气净化器测评

养猫需谨慎&#xff0c;不然就要做猫奴一辈子啦&#xff01;上次堂妹来我家住几天&#xff0c;刚开始还担心和猫处不来&#xff0c;不敢去摸它&#xff0c;走的时候已经约好下次来看它的时间&#xff0c;笑死我了。毕竟猫咪这么可爱&#xff0c;很少有人可以抵抗它的魅力。 这不…

想要一劳永逸地消除 AI 幻觉,该如何做?

作者:老余捞鱼 原创不易,转载请标明出处及原作者。 写在前面的话: 尽管 LLMs 基于存储、检索和生成(RAG)的方法在某些情况下能够提供准确的回答,但在面对名词短语碰撞时,RAG方法可能会因为语义相似性而失效。为了解决这个问题,本文提出了命名实体过滤(NEF)作…

SpringBoot启动成功,但端口启动失败

目录 一、问题展示 二、问题分析 2.1.端口与Tomcat的关系 2.2.问题分析 三、SpringBoot常见知识记录 3.1.SpringBoot项目常用jar包 3.1.1.必要性jar包 3.1.2.选择性jar包 3.2.标签的作用及取值 3.2.1.compile&#xff08;编译范围&#xff09; 3.2.2.provided…

Maya---机械模型制作

材质效果&#xff08;4&#xff09;_哔哩哔哩_bilibili 三角面 四边面 多边面 *游戏允许出现三角面和四边面 游戏中一般是低模&#xff08;几千个面&#xff09; 动漫及影视是高模 机械由单独零件组合而成&#xff0c;需独立制作 低面模型到高面模型 卡线是为了将模型保…

[JavaEE] 网络初识(网络通信 及 TCP / UDP / IP 封装分用 )

Author&#xff1a;MTingle major:人工智能 --------------------------------------- Build your hopes like a tower! 文章目录 目录 文章目录 一. 网络通信基础 1. 局域网LAN 2. ⼴域⽹WAN 3. IP地址 4. 端口号 二.协议 1. 五元组 2. 协议分层 协议分层的优点: 3. OSI七层协…

mongoDB-1

文章目录 一、疑似坑1.11.2 mongo ops manager1.3 mongo features视图固定大小集合&#xff08;有点类似ringbuffer数据结构&#xff0c;capped collections&#xff09;(聚簇集合)clustered collection(类比到Mysql的聚簇索引)聚合管道 aggregation pipelineWiredTiger (默认存…

STM32中的计时与延时

前言 在裸机开发中,延时作为一种规定循环周期的方式经常被使用,其中尤以HAL库官方提供的HAL_Delay为甚。刚入门的小白可能会觉得既然有官方提供的延时函数,而且精度也还挺好,为什么不用呢?实际上HAL_Delay中有不少坑,而这些也只是HAL库中无数坑的其中一些。想从坑里跳出来…

【3D打印】使用simplify 3D切片更改Gcode手动断电续打、掉电、未打完继续打印、补救

一、问题描述 有些时候会遇到3D打印机没料但机器还在继续打、掉电重启后未正常恢复打印、挤出机端没有料但断料检测未触发等情况。我们又不想打印放弃&#xff0c;但又想继续之前的进度打印。 这时候我们需要更改3D打印文件的Gcode参数来进行继续打印。 至于什么是Gcode&…

帕金森遗传给子女的概率大吗?揭开真相,守护健康未来

在健康话题日益受到关注的今天&#xff0c;帕金森病这一神经系统疾病常常引发公众的广泛讨论。尤其是当谈及帕金森病是否会遗传给子女时&#xff0c;许多家庭都充满了担忧和疑惑。那么&#xff0c;帕金森病遗传给子女的概率究竟有多大&#xff1f;今天&#xff0c;我们就来揭开…

2024 年浙江省网络安全行业网络安全运维工程师项目 职业技能竞赛网络安全运维工程师(决赛样题)

2024年浙江省网络安全行业网络安全运维工程师项目 职业技能竞赛网络安全运维工程师&#xff08;决赛样题&#xff09; 应急响应&#xff1a;1 通过流量分析&#xff0c;找到攻击者的 IP 地址2 找到攻击者下载的恶意文件的 32 位小写 md5 值3 找到攻击者登录后台的 URI4 找到攻击…

Unity 给模型贴上照片

Unity将真实世界的照片贴图到模型上 原因 模拟仿真&#xff0c;直接使用照片肯定是效果最好的&#xff0c;省下做材质了 直接拖动即可 导入图片到Unity中将图片修改为Sprite模式直接将图片拖动到Scene面板的物体上即可 注意&#xff1a;是将图片拖动到Scene面板的物体上&a…

婚礼弹幕上墙阳光正好,爱意正浓,打造一场出圈的唯美婚礼!

原文地址 婚礼现场的弹幕功能可以给整个场景增添温暖和喜庆的氛围。通过手机发送祝福&#xff0c;让亲友可以即时将祝福传达给新人&#xff0c;同时这些祝福以弹幕的形式在大屏幕上滚动展示&#xff0c;增加了现场互动的乐趣。墙上新闻搭配的功能则更加抢眼&#xff0c;不仅可…

k8s中的存储

目录 一 configmap 1.1 configmap的功能 1.2 configmap的使用场景 1.3 configmap创建方式 1.3.1 字面值创建 1.3.2 通过文件创建 1.3.3 通过目录创建 1.3.4 通过yaml文件创建 1.3.5 configmap的使用方式 1.3.5.1 使用configmap填充环境变量 1.3.5.2 通过数据卷使用c…

kubernetes技术详解,带你深入了解k8s

目录 一、Kubernetes简介 1.1 容器编排应用 1.2 Kubernetes简介 1.3 k8s的设计架构 1.3.1 k8s各个组件的用途 1.3.2 k8s各组件之间的调用关系 1.3.3 k8s的常用名词概念 1.3.4 k8s的分层结构 二、k8s集群环境搭建 2.1 k8s中容器的管理方式 2.2 k8s环境部署 2.2.1 禁用…

定位HardFault

一、HardFault定义 STM32出现HardFault_Handler硬件错误的原因主要有两个方面&#xff1a; 1、内存溢出或者访问越界。&#xff08;包括使用野指针&#xff09; 2、堆栈溢出。 二、定位HardFault步骤 1. 判断所使用堆栈&#xff1a; 发生异常之后可首先查看LR寄存器中的值…

SAP B1 单据页面自定义 - 用户界面编辑字段

背景 接《SAP B1 基础实操 - 用户定义字段 (UDF)》&#xff0c;在设置完自定义字段后&#xff0c;如下图&#xff0c;通过打开【用户定义字段】可打开表单右侧的自定义字段页。然而再开打一页附加页面操作繁复&#xff0c;若是客户常用的定义字段&#xff0c;也可以把这些用户…

pytest 接口测试

pytest 核心重点 读取excel&#xff08;xfile --> read&#xff09; 函数循环执行( pytest 装饰器&#xff0c;自动解析&#xff0c;一个个单独执行&#xff09; 接口关联&#xff08;Template 处理参数变量&#xff09; pytest 是什么 .py文件名 用 test_开头&#xff0c;…

【计算机网络】HTTP相关问题与解答

此篇文章内容会不定期更新&#xff0c;仅作为学习过程中的笔记记录 目录 一、HTTP请求和响应报文是怎样的&#xff1f; 1、请求报文 2、响应报文 二、HTTP请求方法有哪些&#xff1f; GET HEAD POST PUT DELETE PATCH OPTIONS TRACE CONNECT 三、GET请求与POST请…

linux cmake版本升级教程(Centos7)

有时候,当前系统的cmake版本,并一定能满足编译要求,所以需要进行升级到高于某个版本才能正常编译。本章教程,主要在centos7上进行升级cmake版本。 一、查看当前的cmake版本 cmake --version二、下载指定版本的cmake wget https://github.com/Kitware/CMake/releases/down…

Element UI:初步探索 Vue.js 的高效 UI 框架

Element UI&#xff1a;初步探索 Vue.js 的高效 UI 框架 一 . ElementUI 基本使用1.1 Element 介绍1.2 Element 快速入门1.3 基础布局1.4 容器布局1.5 表单组件1.6 表格组件1.6.1 基础表格1.6.2 带斑马纹表格1.6.3 带边框表格1.6.4 带状态的表格 1.7 导航栏组件讲解 二 . 学生列…