首页 > 编程语言 >运动规划碰撞检测算法之GJK算法

运动规划碰撞检测算法之GJK算法

时间:2024-03-25 15:35:14浏览次数:30  
标签:多边形 原点 单纯形 碰撞检测 算法 夫斯基 GJK

运动规划碰撞检测算法之GJK算法

image

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

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

image

外接圆

image

image

基于AABB的碰撞检测

image

AABB 和 OBB

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

image

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

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

1、凸多边形

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

image

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

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

  • 若多边形的顶点是逆时针序列,则向量的叉乘 a x b,b x c,c x d,d x e,e x a 的结果均大于0;

  • 若多边形的顶点是顺时针序列,则向量叉乘的结果均小于0。

  • 但若同时存在大于0 和 小于0 的结果,则说明是凹多边形。

image

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为三角形,如下图所示。

image

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

image

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

image

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

image

3、单纯形

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

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

image

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

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

image

4、Support 函数

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

image

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

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

image

5、向量的点乘和叉乘

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

image

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

6、GJK 算法

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

image

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

image

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

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

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

image

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

第一次循环:

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

image

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

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

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

image

第二次循环:

步骤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);

image

第三次循环:

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

image

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

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

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

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

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

附赠自动驾驶学习资料和量产经验:链接

标签:多边形,原点,单纯形,碰撞检测,算法,夫斯基,GJK
From: https://www.cnblogs.com/autodriver/p/18094459

相关文章

  • 06天【代码随想录算法训练营34期】 第三章 哈希表part01(● 242.有效的字母异位词 ●
    242.有效的字母异位词思路:26位的array,每个分别对应a,b,c...,z,如果遇到一个字母就++,如果两个array一样则为anagramhint:toinitiateanarraywithnelementscarryingvalue0:arr=[]arr=[0foriinrange(n)]print(arr)classSolution:defisAnagram(self,......
  • 算法人生(10): 从“惰性求解”看“积极拖延”如何提高效率
    拖延也分积极拖延和消极拖延,虽然都叫拖延,但是他们的作用却不一样,消极拖延会降低人的工作或学习效率,但积极拖延却可以提高人的工作或学习效率。积极拖延指的是个体在面对任务时,选择暂时搁置一些活动,转而优先处理其他更有价值或者更利于个人发展的事情。而这个思路也正好跟“惰性......
  • 代码随想录算法训练营第五十七/天 | 516. 最长回文子序列,647. 回文子串
     动态规划最强总结篇!如今动态规划已经讲解了42道经典题目,共50篇文章,是时候做一篇总结了。关于动态规划,在专题第一篇关于动态规划,你该了解这些! (opensnewwindow)就说了动规五部曲,而且强调了五部对解动规题目至关重要!这是Carl做过一百多道动规题目总结出来的经验结晶啊......
  • 对焦取框算法
    1importcv22importnumpyasnp34#读取原始图像5original_image=cv2.imread('train16.png')67#高斯模糊处理8blurred_image=cv2.GaussianBlur(original_image,(5,5),0)910#计算新图像11new_image=cv2.subtract(original_image,blur......
  • 数据结构算法系列----对动态规划的感悟
    简介:   最近我一直在做和复习动态规划的题目,对动态规划有了一些新的理解和感悟。本文就是基于最近做的一些题目写的。一、动态规划的题目形式和选择   当题目是对于求某一串数字或者字符的最值时,一般就回想到三种解法,dfs暴搜、动态规划、贪心。在这三个之中显......
  • 用MATLAB实现nsgaII算法求解多目标问题
    一、nsgaII算法简介NSGA-II(非支配排序遗传算法II)是一种多目标优化算法,2000年由Srinivas,N.,Deb,Kalyanmoy提出,是一种效果非常好的多目标优化算法,尤其是其中的快速非支配排序,极大提高了算法的运行效率。其基本步骤如下:1.初始化种群:随机生成一个包含多个个体的初始种群。......
  • python实现时序平滑算法SG滤波器
    ......
  • m基于log-MPA检测算法的SCMA通信链路matlab误码率仿真
    1.算法仿真效果matlab2022a仿真结果如下:   2.算法涉及理论知识概要       稀疏码多址接入(SparseCodeMultipleAccess,SCMA)是一种非正交多址接入技术,它通过引入码本的稀疏性来实现多用户的高效接入。在SCMA系统中,多用户共享相同的时频资源,每个用户从自己的码本......
  • 代码随想录算法训练营第五十五天 | 583. 两个字符串的删除操作, 72. 编辑距离
    72.编辑距离 已解答中等 相关标签相关企业 给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。你可以对一个单词进行如下三种操作:插入一个字符删除一个字符替换一个字符 示例1:输入:word1="horse"......
  • 栅格地图路径规划:基于霸王龙优化算法(Tyrannosaurus optimization,TROA)的机器人路径规划
     一、机器人路径规划介绍移动机器人(Mobilerobot,MR)的路径规划是移动机器人研究的重要分支之,是对其进行控制的基础。根据环境信息的已知程度不同,路径规划分为基于环境信息已知的全局路径规划和基于环境信息未知或局部已知的局部路径规划。随着科技的快速发展以及机器人的大......