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

news2024/9/23 1:26:00

目录

  • 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深度学习实战》
  • 《机器学习强基计划》
  • 《运动规划实战精讲》

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[Java]maven从入门到进阶

介绍 apache旗下的开源项目,用于管理和构建java项目的工具 官网: Welcome to The Apache Software Foundation! 1.依赖管理 通过简单的配置, 就可以方便的管理项目依赖的资源(jar包), 避免版本冲突问题 优势: 基于项目对象模型(POM),通过一小段描述信息来管理项目的构建 2…

第六天旅游线路规划

第五天&#xff1a;从贾登峪返回乌鲁木齐&#xff1b; 第六天&#xff1a;从乌鲁木齐到天山天池&#xff0c;晚上回乌鲁木齐住宿。 第六天从乌鲁木齐到天山天池景区入口的的规划结果见下图&#xff1a; 1、行程安排 根据上面的耗时情况&#xff0c;规划一天的行程安排如下&a…

OFDM简介

OFDM(Orthogonal Frequency Division Multiplexing)全称为正交频分复用&#xff0c;在无线通信中被广泛应用。本文结合下图对OFDM的基本原理进行说明。 图1. OFDM信号生成流程示意图 上图为OFDM信号生成、传输和接收的整体流程图。结合该流程图对其中每一个模块进行详细说明。 …

Logstash 安装与部署(无坑版)

下载 版本对照关系&#xff1a;ElasticSearch 7.9.2 和 Logstash 7.9.2 &#xff1b; 官方下载地址 选择ElasticSearch版本一致的Logstash版本 https://www.elastic.co/cn/downloads/logstash 下载链接&#xff1a;https://artifacts.elastic.co/downloads/logstash/logst…

一、XML与Tomcat

文章目录 1. XML简介1.1 什么是XML1.2 XML的作用 2. XML语法2.1 文档声明2.2 xml 注释2.3 元素&#xff08;标签&#xff09;2.4 xml 属性2.5 语法规则2.5.1 所有XML元素都须有关闭标签&#xff08;也就是闭合&#xff09;2.5.2 XML 标签对大小写敏感2.5.3 XML 必须正确地嵌套2…

# windows 运行框输入mrt提示错误:Windows 找不到文件‘mrt‘。请确定文件名是否正确后,再试一次

windows 运行框输入mrt提示错误&#xff1a;Windows 找不到文件’mrt’。请确定文件名是否正确后&#xff0c;再试一次 一、错误描述&#xff1a; 当您在 windows 运行框中输入mrt并收到错误提示“Windows 找不到文件’mrt’。请确定文件名是否正确后,再试”时&#xff0c;这…

【无人机设计与控制】四旋翼无人机轨迹跟踪及避障Matlab代码

摘要 本文主要研究了四旋翼无人机在复杂环境中的轨迹跟踪与避障控制策略。通过Matlab/Simulink对四旋翼无人机进行了建模与仿真。系统集成了避障算法&#xff0c;使得无人机在执行任务时能够有效避开障碍物&#xff0c;保证飞行的安全性与稳定性。 理论 无人机飞行控制通常涉…

着色器 简介

着色器&#xff08;Shader&#xff09;是运行在 GPU 上的小程序。这些小程序为图形渲染管线的某个特定部分而运行。从基本意义上来说&#xff0c;着色器只是一种把输入转化为输出的程序。着色器也是一种非常独立的程序&#xff0c;因为它们之间不能相互通信&#xff1b;它们之间…

【JavaSE】--数组的定义与使用

文章目录 1. 数组的基本概念1.1 什么是数组1.2 数组的创建及初始化1.2.1 数组的创建1.2.2 数组的初始化 1.3 数组的使用1.3.1 数组中元素访问1.3.2 遍历数组 2. 数组是引用类型2.1 初识JVM的内存分布2.2 基本类型变量与引用类型变量的区别2.3 再谈引用变量2.4 认识null 3. 数组…

es的封装

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、类和接口介绍0.封装思想1.es的操作分类 二、创建索引1.成员变量2.构造函数2.添加字段3.发送请求4.创建索引总体代码 三.插入数据四.删除数据五.查询数据 前…

公共建筑能耗监测系统解决方案

jianzhunenghao 建筑节能监测系统公共建筑能耗监测系统建筑能耗监测系统节能监测系统能耗监测建筑能耗监测能耗分析能耗管理能耗预测能耗监控能耗监测平台建筑能耗 介绍 能耗监控系统是为耗电量、耗水量、耗气量&#xff08;天然气量或者煤气量&#xff09;、集中供热耗热量…

STHS34PF80高灵敏度红外感应器(2)----InfraredPD存在感应检测

STHS34PF80人体存在传感器.2--InfraredPD存在感应检测 概述视频教学样品申请完整代码下载硬件准备开启CRC串口设置开启X-CUBE-MEMS1InfraredPD文件InfraredPD算法库注意事项对应DEMOMX_MEMS_InitMX_MEMS_Processt_obj_comp&#xff08;补偿后的物体温度&#xff09;t_obj_chang…

清理C盘缓存,电脑缓存清理怎么一键删除,操作简单的教程

清理C盘缓存是维护电脑性能、释放磁盘空间的重要步骤。以下是一个详细且操作简单的教程&#xff0c;旨在帮助用户通过一键或几步操作完成C盘缓存的清理。 1.使用Windows系统自带工具 磁盘清理 1.打开磁盘清理工具&#xff1a; -按下“WinE”打开文件资源管理器…

数据结构与算法——Java实现 5.链表

目录 一、定义 链表的分类 二、性能 随机访问 插入或删除 三、单向链表 链表内部节点类 ① 增加&#xff08;插入&#xff09; 1.头插法 2.寻找最后一个节点位置 3.尾插法 4.根据索引位置插入 ② 删除 1.删除首个结点 2.获取链表的指定索引节点 3.删除链表指定索引元素节点 4.删…

【Java】【力扣】83.删除排序链表中的重复元素

题目 给定一个已排序的链表的头 head &#xff0c; 删除所有重复的元素&#xff0c;使每个元素只出现一次 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,1,2] 输出&#xff1a;[1,2]示例 2&#xff1a; 输入&#xff1a;head [1,1,2,3,3] 输出&#…

js 控制台自动 debugger

在全局文件中加入以下代码&#xff0c;即可打开控制台自动调试 setInterval(function() {check() }, 1000); var check function() {function doCheck() {(function() {}["constructor"]("debugger")())doCheck()}try {doCheck()} catch (err) {} }; che…

Flask-WTF的使用

组织一个 Flask 项目通常需要遵循一定的结构&#xff0c;以便代码清晰、可维护。下面是一个典型的 Flask 项目结构&#xff1a; my_flask_app/ │ ├── app/ │ ├── __init__.py │ ├── models.py │ ├── views.py │ ├── forms.py │ ├── templat…

T3打卡-天气识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 1.导入数据&#xff1a; #设置GPU import tensorflow as tf gpustf.config.list_physical_devices("GPU") if gpus:gpu0gpus[0]tf.config.experime…

Android OkHttp源码分析(一):为什么OkHttp的请求速度很快?为什么可以高扩展?为什么可以高并发

目录 一、为什么要使用OkHhttp? 在不使用OkHhttp之前&#xff0c;我们都是在使用什么&#xff1f;使用HttpURLConnection&#xff0c;那么我们看看HttpURLConnection发起一次请求&#xff0c;两次请求要花多长时间&#xff0c;而OkHttp花多长时间。HttpURLConnection会比okht…

【银河麒麟高级服务器操作系统实例】tcp_mem分析处理全过程内核参数调优参考

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://documentkylinos.cn 现象描述 系统中出现大量的TCP: out of memory…