碰撞检测3:碰撞检测算法之GJK算法

碰撞检测3:碰撞检测算法之GJK算法


在自动驾驶系统运动规划模块的碰撞检测中,通常分为 粗略碰撞检测 和 精细碰撞检测 两个步骤。

粗略碰撞检测用来将两个明显不相交的物体快速排除,使用 外接圆的包围形 或 轴对齐包围矩形(Axis Aligned Bounding Box,AABB)都是比较好的方式。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

精细碰撞检测则用来准确判断两个物体是否相交。分离轴定理(Separating Axis Theorem,SAT)是一种可用于精确判断两个物体是否相交的算法,不仅适用于 Box(矩形),还适用于 凸多边形(Polygon)。基于分离轴定理的算法原理简单,即只要能找到一条可将两个多边形分开的直线,则这两个多边形不相交。

在这里插入图片描述

在精细碰撞检测阶段,除了 SAT 算法,另外一个就是 GJK(Gilbert–Johnson–Keerthi)算法。相比 SAT 算法,GJK 算法更加高效。

在介绍 GJK 算法之前,我们需要先了解一些背景知识。

1、凸多边形

凸多边形的定义:对于平面上的一个多边形,如果延长它的任何一条边,都使整个多边形位于一边延长线的同侧,这样的多边形叫做凸多边形。

在这里插入图片描述

根据上述定义,人可以直观判断出一个多边形是否为凸多边形,但在程序中,如何判断一个多边形是否为凸多边形呢?

答案是利用向量的叉乘。如下图所示,根据多边形的顶点坐标,依次求出每条边的向量。

  • 若多边形的顶点是逆时针序列,则向量的叉乘 a x b,b x c,c x d,d x e,e x a 的结果均大于0;
  • 若多边形的顶点是顺时针序列,则向量叉乘的结果均小于0。
  • 但若同时存在大于0 和 小于0 的结果,则说明是凹多边形。

在这里插入图片描述

2、闵可夫斯基差

闵可夫斯基差,也可以叫做闵可夫斯基和,它的定义也很好理解,点集A与B的闵可夫斯基和被定义为:

A + B = {a + b | a ∈ A,b ∈ B}

如果 A 和 B 是两个凸多边形,则 A + B 也是凸多边形。

闵可夫斯基和从几何上的直观理解是A集合沿B的边际连续运动一周扫过的区域与B集合本身的并集,也可以是B沿着A的边界连续运动扫过区域与A自身的并集。

GJK算法用到的不是闵可夫斯基和,而是闵可夫斯基差,即:

A - B = {a - b | a ∈ A,b ∈ B}

虽然使用的是减法运算,但其仍然是闵可夫斯基和,相当于先对B中的所有点做负运算(相对原点的镜像),然后再与A做加法。

GJK算法的核心就是闵可夫斯基差,即若两个多边形相交,则它们的闵可夫斯基差必然包括原点

先来看两个例子。

对于两个不相交的多边形,shape1为矩形,shape2为三角形,如下图所示。

在这里插入图片描述

它们的闵可夫斯基差如下图所示,其闵可夫斯基差不包括原点,且两个多边形之间的距离就是其闵可夫斯基差到原点的距离。事实上,GJK 算法发明出来的初衷就是为了计算两个凸多边形之间的距离。

在这里插入图片描述

对于两个相交的多边形,shape1为矩形,shape2为三角形,如下图所示。

在这里插入图片描述

它们的闵可夫斯基差则如下图所示,可以看到,闵可夫斯基差是包括原点的。这也很好理解,两个相交的多边形,必然有一点既属于shape1,也属于shape2,相减则为原点(0,0)。

在这里插入图片描述

3、单纯形

k阶单纯形(simplex),指的是k维空间中的多胞形,该多胞形是k+1个顶点组成的凸包。

在GJK算法中,单纯形被大量使用。单纯形指的是点、线段、三角形或四面体。例如,0阶单纯形是点,1阶单纯形是线段,2阶单纯形是三角形,3阶单纯形是四面体。

在这里插入图片描述

对于2维空间的多边形,最多用到2阶单纯形。那单纯形到底有什么作用呢?

对于上面两个相交的多边形例子,实际应用中,其实不需要求出完整的闵可夫斯基差,只需要在闵可夫斯基差内形成一个多边形,如下图所示,并使这个多边形尽可能包围原点,这个多边形就称为单纯形。即假如单纯形包围原点,则闵可夫斯基差必然包围原点。

在这里插入图片描述

4、Support 函数

Support函数的作用是计算多边形在给定方向上的最远点。如下图所示,在向量 a 方向的最远点为 A 点,在向量 b 方向的最远点为 B 点。这里在寻找给定方向上的最远点时,需要用到向量的点乘。

在这里插入图片描述

为什么需要Support函数呢?这是因为在构建单纯形时,我们希望尽可能得到闵可夫斯基差的顶点,而不是其内部的一个点,这样产生的单纯形才能包含最大的区域,增加算法的快速收敛性。

如下图所示,在给定向量 a 方向上,shape1 的最远点为(4,2),在向量 -a 的方向上,shape2 的最远点为(5,3),这两个点作差即得到点(-1,-1)。利用这种方式得到的点都在闵可夫斯基差的边上。

在这里插入图片描述

5、向量的点乘和叉乘

理解向量的点乘和叉乘,如下图所示。向量的点乘用来判断两个向量是否同方向;向量的叉乘用来判断一点在一线段的左侧还是右侧。

在这里插入图片描述

有了上述背景知识,接下来理解 GJK 算法就比较容易了。

6、GJK 算法

下图是 GJK 算法的伪代码,其核心逻辑是:给定两个多边形 p 和 q,以及一个初始方向,通过迭代的方式构建、更新单纯形,并判断单纯形是否包含原点,若包含原点则两个多边形相交,否则不相交。

在这里插入图片描述

GJK 算法的具体步骤如下图所示。

在这里插入图片描述

我们还是通过一个例子来理解上述步骤。

步骤1:选取初始方向 dir(0,1),如下图所示;

步骤2:多边形 p 在初始方向上 dir 的最远点为(4,5),多边形 q 在 -dir 方向上的最远点为(1,0),因此第一个 support 点为(3,5);

在这里插入图片描述

步骤3:将初始方向取反 dir 变成(0,-1);

第一次循环:

步骤4a:根据迭代方向 dir(0,-1),得到第二个 support 点(3,-1),如下图所示;

在这里插入图片描述

步骤4b:新的 support 点(3,-1) 与 迭代方向(0,-1) 的点乘结果大于0,说明跨越原点了;

步骤4c:新的 support 点能够跨越原点,将其加到 simplex 中,此时 simplex 中有两个点;

步骤4d:以这两个点的直线的垂线朝向原点的方向(-1,0),作为下一次迭代方向,如下图所示;

在这里插入图片描述

第二次循环:

步骤4a:根据迭代方向 dir(-1,0),得到 support 点(-1,2),如上图所示;

步骤4b:新的 support 点(-1,2) 与 迭代方向(-1,0) 的点乘结果大于0,说明跨越原点了;

步骤4c:新的 support 点能够跨越原点,将其加到 simplex 中,此时 simplex 中有三个点;

步骤4d:这三个点组成的三角形没有包含原点,保留离原点最近的边上的两个点(-1,2)和(3,-1),同样以这两个点的直线的垂线朝向原点的方向,作为下一次迭代方向(-3,-4);

在这里插入图片描述

第三次循环:

步骤4a:根据迭代方向 dir(-3,-4),得到 support 点(-1,-1),如下图所示;

在这里插入图片描述

步骤4b:新的 support 点(-1,-1) 与 迭代方向(-3,-4) 的点乘结果大于0,说明跨越原点了;

步骤4c:新的 support 点能够跨越原点,将其加到 simplex 中,此时 simplex 中有三个点;

步骤4d:这三个点组成的三角形包含原点了,说明这两个多边形相交。到此结束。

从上面的示例中可以看出,GJK 是一中基于迭代的算法,其收敛速度取决于迭代方向。

到这里,我们对整个 GJK 算法步骤有了一个基本认识。但是,在上面的步骤4d中,如何判断三角形是否包含原点,如何查找下一个迭代方向,以及如何计算两个不相交的多边形之间的距离,还需要有更细化的工作,这里不再进行叙述,未来将直接把代码开源出来,敬请期待。

内容简介  《实时碰撞检测算法技术》详细阐述了与碰撞检测问题相关的高效解决方案及相应的数据结构和算法,主要包括:碰撞检测系统中的设计问题、数学和几何学入门、包围体、基本图元测试、层次包围体技术、空间划分、BSP树层次结构、凸体算法、基于GPU的碰撞检测、数值健壮性、几何健壮性以及优化操作。另外,《实时碰撞检测算法技术》还提供了相应的算法、代码以及伪代码,以帮助读者进一步理解计算方案的实现过程。  《实时碰撞检测算法技术》适合作为高等院校计算机及相关专业的教材和教学参考书,也可作为相关开发人员的自学教材和参考手册。第1章 概述1.1 内容概览1.2 关于本书的代码第2章 碰撞检测系统中的设计问题2.1 碰撞算法的设计因素2.2 应用程序中对象的表达方式2.3 查询类型2.4 环境模拟参数2.5 性能2.6 健壮性2.7 实现与使用的简洁性2.8 小结第3章 数学和几何学入门3.1 矩阵3.2 坐标系统和顶点3.3 向量3.4 质心坐标3.5 直线、光线和线段3.6 平面和半空间3.7 多边形3.8 多面体3.9 凸包计算3.10 域3.11 Minkowski和与Minkowski差3.12 小结第4章 包围体4.1 BV期望特征4.2 轴对齐包围盒4.3 Spheres球体4.4 方向包围盒4.5 球扫掠体4.6 半空间相交体4.7 其他类型的包围体4.8 小结第5章 基本图元测试5.1 最近点计算5.2 图元测试5.3 直线、光线和有向线段的相交测试5.4 其他类型的测试5.5 动态相交测试5.6 小结第6章 层次包围体技术6.1 层次结构设计问题6.2 层次结构的构建策略6.3 层次结构的遍历6.4 包围体层次结构示例6.5 合并包围体6.6 高效的树型表达方式及遍历6.7 通过缓存机制改善查询6.8 小结第7章 空间划分第8章 BSP树层次结构第9章 凸体算法第10章 基于GPU的碰撞检测第11章 数值健壮性第12章 几何健壮性第13章 优化操作参考文献
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值