Planning-碰撞检测之GJK

article/2025/9/25 0:28:03

原文:dyn4j:GJK (Gilbert–Johnson–Keerthi)

目录

  • 1. Minkowski Sum(明可夫斯基和)
  • 2. Simplex
  • 3. support函数
  • 4. 构建Simplex

G J K GJK GJK S A T SAT SAT一样用于检测凸多边形,和 S A T SAT SAT不同, G J K GJK GJK可以处理任意形状的凸多边形,然而 S A T SAT SAT处理圆的碰撞检测时需要用不同的算法。

1. Minkowski Sum(明可夫斯基和)

G J K GJK GJK是基于 M i n k o w s k i Minkowski Minkowski S u m Sum Sum概念上的,即形状1的所有点和形状2的所有点之和。
A + B = { a + b ∣ a ∈ A , b ∈ B } A + B = \{a + b | a \in A, b \in B \} A+B={a+baA,bB}
如果 s h a p e A shape A shapeA B B B是凸的,则它们的和也是凸的
相应的可以定义它们的差运算:
A − B = { a − b ∣ a ∈ A , b ∈ B } A - B = \{a - b | a \in A, b \in B \} AB={abaA,bB}
如果两个形状重叠,进行 M i n k o w s k i Minkowski Minkowski S u m Sum Sum后的形状包含原点 M i n k o w s k i Minkowski Minkowski S u m Sum Sum的运算是 s h a p e shape shape A A A的每个顶点和 s h a p e shape shape B B B的所有顶点求和(或求差)。所得到点的外包络即是运算所得形状。
在这里插入图片描述
在这里插入图片描述

2. Simplex

单纯形是代数拓扑中的基本概念,单纯形是三角形和四面体的一种泛化,一个 k k k维单纯形是指包含 ( k + 1 ) (k+1) (k+1)个节点的凸多面体。不需要计算 M i n k o w s k i Minkowski Minkowski S u m Sum Sum,只需要计算 M i n k o w s k i Minkowski Minkowski S u m Sum Sum是否包含原点,如果包含原点则两个形状重叠,否则不重叠。在 M i n k o w s k i S u m Minkowski \;\; Sum MinkowskiSum得到的形状中迭代的构建 S i m p l e x Simplex Simplex,判断 S i m p l e x Simplex Simplex是否包含原点,包含则重叠,否则不重叠。

3. support函数

s u p p o r t support support函数返回两个形状 M i n k o w s k i Minkowski Minkowski S u m Sum Sum的一个点用以构建 S i m p l e x Simplex Simplex s h a p e 1 shape1 shape1的点减去 s h a p e 2 shape2 shape2的点可以得到一个 M i n k o w s k i Minkowski Minkowski S u m Sum Sum的一个点,但我们不希望得到重复的点。使用 s u p p o r t support support函数得到 s h a p e shape shape在一个 d i r e c t i o n direction direction(方向)上的最远点,然后在不同的方向上得到另一个不同的点。在 d i r e c t i o n direction direction上选择最远点可以使生成的 S i m p l e x Simplex Simplex的面积最大化以增加包含原点的几率增加算法收敛速度。使用这种方法得到的点在 M i n k o w s k i Minkowski Minkowski S u m Sum Sum的边上,因此如果得到的点不包含原点则 M i n k o w s k i Minkowski Minkowski S u m Sum Sum不包含原点。

Public Point support(Shape shape1, Shape shape2, Vector d) {// d is a vector direction(doesn't have to normalized)// get points on the edge of the shapes in opposite directionPoint p1 = shape1.getFarthestPointInDirection(d);Point p2 = shape2.getFarthestPointInDirection(d.negative());// perform the Minkowski SumPoint p3 = p1.subtract(p2);// p3 is now a point in Minkowski space on the edge of the Minkowski Differencereturn p3;
}

4. 构建Simplex

首先选择三个点构造 S i m p l e x Simplex Simplex,如果包含原点,则两个多边形重叠,否则重新选择点构建新的 S i m p l e x Simplex Simplex。由 s u p p o r t support support函数可知,需要一个 d i r e c t i o n direction direction来选择 M i n k o w s k i Minkowski Minkowski S u m Sum Sum点,任意的 d i r e c t i o n direction direction都是可以的,但是选择两个多边形的中心点的向量方向是较优的选择。

Vector d = // choose a search direction
// get the first Minkowski Difference point
Simplex.add(support(A, B, d));
// negate d for the next point
d.negate();
// start looping
while (true) {// add a new point to the simplex because we haven't terminated yetSimplex.add(support(A, B, d));// make sure that the last point we added actually passed the originif (Simplex.geLast().dot(d) <= 0) {// if the point added last was not past the origin in the direction of d // then the Minkowski Sum cannot possibly contain the origin since// the last point added is on the edge of Minkowski Differencereturn false;} else {// otherwise we need to determine if the origin is in the current simplexif (Simplex.contains(ORIGIN)) {// if it does then we know there is a collisionreturn true;} else {// otherwise we cannot be certain so find the edge who is closest to the// origin and use its normal (in the direction of the origin) as the new// d and continue the loopd = getDirection(Simplex);}}
}

Simplex.geLast().dot(d) <= 0的解释:
S i m p l e x Simplex Simplex最新得到的点是 M i n k o w s k i Minkowski Minkowski S u m Sum Sum在给定方向上的最远点,如果这个点没有 e n c l o s e enclose enclose原点,则 M i n k o w s k i Minkowski Minkowski S u m Sum Sum不会包含原点。如下图, d i r e c t i o n direction direction ( − 1 , 0 ) (-1, 0) (1,0),点 p ( 1 , − 4 ) p(1, -4) p(1,4)是在 d i r e c t i o n direction direction上的最远点。点 p p p d d d上的投影是-1,原点在 d d d上的投影是0,由于 p p p M i n k o w s k i Minkowski Minkowski S u m Sum Sum是最远点,所以其不会包含原点。
在这里插入图片描述

当得到两个 M i n k o w s k i Minkowski Minkowski S u m Sum Sum点时,如下图中左图, B B B是第一个点, A A A是第二个点, A A A B B B M i n k o w s k i Minkowski Minkowski S u m Sum Sum包络上的点,如果 o r i g i n origin origin R 1 R1 R1或者 R 4 R4 R4区域,则 M i n k o w s k i Minkowski Minkowski S u m Sum Sum不包含原点,Simplex.geLast().dot(d) <= 0 返回 t r u e true true。由图可知, o r i g i n origin origin R 3 R3 R3区域内,因此需要计算 A B AB AB p e r p e t u a l a r perpetualar perpetualar v e c t o r vector vector应该指向 R 3 R3 R3
A B = B − A A O = O − A p e r p = ( A B × A O ) × A B AB = B - A \\ AO = O - A \\ perp = (AB \times AO) \times AB AB=BAAO=OAperp=(AB×AO)×AB
如右图,此时 s u p p o r t support support函数得到新的 M i n k o w s k i Minkowski Minkowski S u m Sum Sum A A A,点 B B B是第二点(左图中的 A A A),点 C C C是第一个点(左图中的 B B B), o r i g i n origin origin可能存在于 R 3 R3 R3 R 4 R4 R4 R 5 R5 R5中,计算 ( A C × A B ) × A B (AC \times AB) \times AB (AC×AB)×AB生成 A B p e r p ABperp ABperp,计算 A B p e r p ⋅ ( A O ) ABperp \cdot (AO) ABperp(AO)判断 o r i g i n origin origin是否在 R 4 R4 R4,计算 ( A B × A C ) × A C (AB \times AC) \times AC (AB×AC)×AC生成 A C p e r p ACperp ACperp,计算 A C p e r p ⋅ ( A O ) ACperp \cdot (AO) ACperp(AO)判断 o r i g i n origin origin是否在 R 3 R3 R3
在这里插入图片描述
在这里插入图片描述

Vector d = // choose a search direction
// get the first Minkowski Sum point
Simple.add(support(A, B, d));
// nagate d for the next point
d.negate();
// start loop
while (true) {// add a new point to the simplex because we haven't terminated yetSimple.add(support(A, B d));// make sure that the last point added actually passed the originif (Simple.getLast().dot(d) <= 0) {// if the point added last was not past the origin in the direction of d // then the Minkowski Sum cannot possibly contain the origin since// the last point added is on the edge of Minkowski Differencereturn false;} else {// otherwise determine if the origin is in the current simplexif (containsOrigin(Simple, d)) {// if it does, there is a collisionreturn true;}}
}public boolean containOrign(Simples s, Vector d) {// get the last point added to the simplexa = Simplex.getLast(); // the last point// compute AO (same thing as -A)ao = a.negate();if (Simplex.points.size == 3) {// in triangle case// get point B and Cb = Simplex.getB(); // the second pointc = Simplex.getC(); // the first point// compute the edgesab = b - a;ac = c - a;// compute the normalsabPerp = tripleProduct(ac, ab, ab);acPerp = tripltProdect(ab, ac, ac);// is the origin in R4if (adPerp.dot(ao) > 0) {// remove point CSimplex.remove(c);// set the new direction to ABPerpd.set(abPerp);} else {// is the origin in R3if (acPerp.dot(ao) > 0) {// remove point BSimples.remove(b);// set the new direction to ACPerpd.set(acPerp);} else {// otherwise origin in R5, there is a collisionreturn true;}}} else {// in line segment caseb = Simplex.getB();// compute ABab = b -a;// get the perp to AB in the direction of the originabPerp = tripleProduct(ab, ao, ab);// set the direction to ABPerpd.set(abPerp);}return false;
}

http://chatgpt.dhexx.cn/article/gKvosVaB.shtml

相关文章

GJK算法

转自&#xff1a;http://blog.sina.com.cn/s/blog_833d50630100xw1r.html GJK算法最初用来求三维空间中凸多面体的距离&#xff08;即最近距离&#xff09;&#xff0c;也因此经常用来做碰撞检测&#xff08;距离是否为0&#xff09;。后被推广到n维空间中求凸包之间的距离&…

碰撞检测GJK算法论文解析二

碰撞检测GJK算法论文解析二 The Theoretical Algorithm内容详解 初探The Distance Subalgorithm内容详解 Appendix Ⅱ涉及的概念内容详解 接上文&#xff0c;本篇文章讲解GJK算法论文的第四、第五部分前半部分&#xff0c;这是整个算法最为核心的部分。第四部分阐述了算法的核心…

碰撞检测GJK算法论文解析三

碰撞检测GJK算法论文解析三 再探Appendix Ⅱ内容详解 再探The Distance Subalgorithm内容详解过程1过程2过程3 这里要先纠正上篇文章的一些错误&#xff0c;就是上篇文章的最后其实并没有证明定理3&#xff0c;而只是给出了仿射集系数向量 λ \lambda λ的解的形式&#xff0c;…

GJK碰撞检测(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

物理引擎学习04-GJK计算多边形之间的最近距离

计算多边形之间的最近距离&#xff0c;才是GJK算法原本的目的。只有两个多边形不相交&#xff0c;计算最近距离才有效。如果相交&#xff0c;则最近距离无效&#xff0c;但是可以使用EPA算法要计算碰撞深度。本文的写作目的&#xff0c;主要是对GJK算法的理解和应用。对算法本身…

python碰撞检测算法_GJK碰撞检测算法

现实世界里我们对于是否碰撞的判断可以说极其容易而且准确,比如下图。在二进制的世界里,一切就没这么直观了。 GJK(Gilbert-Johnson-Keerthi Distance Algorithm) GJK 就是此次要实现的碰撞检测算法。如果对碰撞算法有过了解的话,大概率听过另一个碰撞检测算法 SAT(Separati…

【计算几何】凸多面体重叠判断算法:GJK 算法详解 C++代码实现二维情形的凸多边形重叠判断

文章目录 一、GJK 算法简介二、前置知识2.1 二维向量的点乘和叉乘2.2 三维向量叉乘2.3 凸多边形2.4 闵可夫斯基差2.5 单纯形2.6 Support 函数 三、GJK 算法讲解3.1 熟悉 GJK 算法流程3.1.1 多边形重叠的情形3.1.2 多边形不重叠的情形 3.2 总结 GJK 算法步骤3.3 讲解 GJK 算法细…

GJK 算法

GJK 算法(Gilbert–Johnson–Keerthi) 翻译自&#xff1a;http://www.dyn4j.org/2010/04/gjk-gilbert-johnson-keerthi/ 今天&#xff0c;我将讨论dyn4j项目随附的其他碰撞检测算法。您可以找到很多GJK文档&#xff0c;但是其中很多实际上是技术性的&#xff0c;主要是因为它…

碰撞检测算法之GJK算法

简介 参考&#xff1a; 碰撞检测算法之GJK算法 - 知乎 (zhihu.com) 运筹优化】凸多面体重叠判断算法&#xff1a;GJK 算法详解 & C代码实现二维情形的凸多边形重叠判断_c 凸多边形_WSKH0929的博客-CSDN博客 物理引擎学习03-GJK碰撞检测算法基础gjk算法游蓝海的博客-CSDN博客…

物理引擎学习05-GJK和EPA计算穿透向量

EPA&#xff0c;是扩展多边形算法(Epanding Polytop Algorithm) &#xff0c;用来计算两个多边形碰撞的穿透深度和方向&#xff0c;可用于将两个发生碰撞的多边形分离。本文的写作目的&#xff0c;主要是对GJK和EPA算法的理解和应用。对算法本身感兴趣的朋友&#xff0c;可以阅…

物理引擎学习03-GJK碰撞检测算法基础

GJK是由Gilbert&#xff0c;Johnson&#xff0c;Keerthi 三位前辈发明的&#xff0c;用来计算两个凸多面体之间的碰撞检测&#xff0c;以及最近距离。GJK算法可以在O(MN)的时间复杂度内&#xff0c;检测出碰撞&#xff0c;算法在每次迭代的过程中&#xff0c;都会优先选择靠近原…

碰撞检测——GJK算法

目录 碰撞检测——GJK算法 1.GJK算法的原理及思想 1.1 Minkowski Sum&#xff08;明可夫斯基和&#xff09; 1.2 Simplex 1.3 support函数 1.4 构建Simplex 2. GJK算法步骤 3. GJK算法的优缺点分析 4. GJK算法与其他相关算法的比较分析 4.1 GJK算法和SAT算法的比较 …

QPM 之悬浮窗设置信息

QPM 开源地址&#xff1a;https://github.com/ZhuoKeTeam/QPM 更多实用信息&#xff1a; 手机的基本信息AndroidManifest.xml 信息App 中所有的 SharePreference 信息可配置的开关网络接口 手机基础信息 再也不用 去手机的复杂界面查看各种数据&#xff1b;再也不用 下载 辅…

QPM访谈问题

QPM&#xff1a;Quantitative Project Management&#xff0c;量化项目管理 一、访谈问题 1、请简要介绍贵司的QPM管理的管理方式&#xff1f; 依据公司整体商业目标和CMMI要求&#xff0c;制定和部署了《量化项目管理过程》和相关的指南、模板。 在项目执行中&#xff0c;…

QPM 性能监控组件——总篇

QPM &#xff08;Quality Performance Monitor&#xff09; 是一个质量性能监控组件&#xff0c;可以很方便的查看当前 App 的性能和常用数据。目前主要运行在 Android 平台上&#xff0c;通过集成 QPM 组件&#xff0c;可以在 App 中通过悬浮窗可视化相关实时数据。意在帮助广…

IDEA快捷键显示参数提示

一、IDEA显示参数的提示 1、理想状态是这样 2、某度了半天 都是让画show parameter 那个勾的&#xff0c;不是我想要的 IDEA默认的快捷键提示是 " ctrl p"&#xff0c;但是我改成eclipse的快捷键后就没有提示了 File---->settings---->keymap 需要给ecli…

Idea设置代码自动提示快捷键

使用eclipse都习惯使用快捷键ALT/ 来代码自动提示&#xff0c;后来使用IntelliJ Idea这个快捷键并不管用&#xff0c;十分不便&#xff0c;这里记录如何使更改idea代码自动提示快捷键。 哪个是代码自动提示快捷键 File–》Settings–》KeyMap(快捷键ctrlalts)进入快捷键设置界…

IDEA提示方法参数的快捷键

在写Java方法的时候有时想让软件提示一下方法的参数&#xff0c;解决方法是将鼠标放置到方法括号里&#xff0c;按下ctrlp&#xff0c;即可显示方法参数

idea 设置代码提示快捷键

Settings->Keymap 搜索框内搜索 completion Main Menu-Code-Code Completion-Basic 设置成对应的快捷键&#xff0c;如 Alt/

IDEA的使用—常用快捷键

IDEA常用快捷键 具体详解视频见于&#xff08;【零基础 快速学Java】韩顺平 零基础30天学会Java&#xff09; 文章目录 前言一、IDEA快捷键是什么&#xff1f;二、IDEA快捷键的设置 1.快捷键12.快捷键23.快捷键3总结 前言 IDEA快捷键能够提升编程速度以及防止出现书写代码时的低…