news 2026/8/22 13:16:31

第231篇 碰撞检测算法——GJK/EPA和包围盒方法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第231篇 碰撞检测算法——GJK/EPA和包围盒方法

碰撞检测是运动规划中最频繁调用的子程序——RRT每次扩展节点要做碰撞检测,混合A*每次扩展运动基元要做碰撞检测,B样条优化每次迭代要做碰撞检测。说白了,碰撞检测的效率直接决定了整个规划算法的速度。

碰撞检测的问题定义很简单:给定两个几何体A和B,判断它们是否相交。但"简单"的前提是几何体的表示方式——如果是两个球体,距离公式一行代码搞定;如果是两个复杂的三角网格模型,计算量可能差几个数量级。

一、包围盒方法——快速粗筛

包围盒(Bounding Volume)是碰撞检测的第一道防线。用一个简单的几何体把复杂物体包起来,先判断包围盒是否相交——如果不相交,两个物体一定不相交,直接跳过精确检测。

常用的包围盒从简到复杂:

AABB(Axis-Aligned B Box):轴对齐包围盒,用(xmin,xmax,ymin,ymax,zmin,zmax)表示。相交检测只需6次比较——极快。缺点是不能旋转,物体旋转后包围盒要重新计算。

OBB(Oriented Bounding Box):有方向的包围盒,可以跟随物体旋转。比AABB更紧凑(贴合度更高),但相交检测需要做SAT(Separating Axis Theorem)——在15个候选分离轴上投影,计算量比AABB大5-10倍。

Bounding Sphere:包围球,用一个球心和半径表示。相交检测只需算一次距离。缺点是对细长物体(比如机械臂连杆)贴合度差。

# AABB相交检测——6次比较 def aabb_intersect(box_a, box_b): return (box_a.xmin <= box_b.xmax and box_a.xmax >= box_b.xmin and box_a.ymin <= box_b.ymax and box_a.ymax >= box_b.ymin and box_a.zmin <= box_b.zmax and box_a.zmax >= box_b.zmin)

工程上的标准做法:建立包围盒层次树(BVH, Bounding Volume Hierarchy)。把复杂物体分解为子部件,每个子部件有自己的包围盒,父节点的包围盒是所有子节点的并集。检测时从根节点开始——如果根节点的包围盒不相交,整棵子树都不用检测。

二、GJK算法——精确碰撞检测

GJK(Gilbert-Johnson-Keerthi)算法是精确碰撞检测的经典方法。它的核心思想很巧妙:不直接判断两个物体是否相交,而是计算它们的闵可夫斯基差(Minkowski Difference)是否包含原点。

闵可夫斯基差的定义:A ⊖ B = {a - b | a ∈ A, b ∈ B}。如果A和B相交,则存在a ∈ A和b ∈ B使得a = b,即a - b = 0——原点在闵可夫斯基差中。

GJK不需要显式计算整个闵可夫斯基差(那是个体积很大的几何体),而是迭代地找一个包含原点的simplex(单纯形——点、线段、三角形或四面体)。如果找到了,两个物体相交;如果找不到(simplex无法包含原点),不相交。

# GJK算法核心循环 def gjk(shape_a, shape_b): direction = (1, 0, 0) # 初始搜索方向 simplex = [support(shape_a, shape_b, direction)] direction = -simplex[0] # 朝向原点 while True: new_point = support(shape_a, shape_b, direction) if dot(new_point, direction) < 0: return False # 不相交 simplex.append(new_point) if contains_origin(simplex, direction): return True # 相交

GJK的关键操作是support函数:给定一个方向d,找到A中沿d方向最远的点和B中沿-d方向最远的点,两者之差就是闵可夫斯基差中沿d方向最远的点。对于凸形状,support函数可以在O(log N)时间内完成。

GJK的时间复杂度:迭代次数通常不超过10次(对3D凸形状),每次迭代调用一次support函数。总时间复杂度O(log N)——比暴力三角面片对比快得多。

三、EPA算法——碰撞深度计算

GJK只能告诉你"是否碰撞",不能告诉你"碰了多少"。如果你需要碰撞深度(penetration depth)——两个物体重叠了多少——用EPA(Expanding Polytope Algorithm)。

EPA在GJK找到的simplex基础上工作:

  1. 从GJK的simplex(一个包含原点的四面体)开始
  2. 找到离原点最近的面
  3. 在这个面的法线方向上做support查询,得到新点
  4. 用新点扩展多面体(添加新面,删除被遮挡的旧面)
  5. 重复直到最近面的距离收敛
# EPA的简化流程 def epa(gjk_simplex, shape_a, shape_b): polytope = Polytope(gjk_simplex) while True: face = polytope.closest_face_to_origin() new_point = support(shape_a, shape_b, face.normal) if dot(new_point, face.normal) - face.distance < epsilon: return face.distance # 碰撞深度 polytope.expand(new_point, face)

EPA的输出:碰撞深度(标量)和碰撞法线方向(向量)。这两个信息在物理仿真(计算接触力)和轨迹优化(计算排斥梯度)中很有用。

四、工程实践与开源库

FCL(Flexible Collision Library):ROS/MoveIt2的标配碰撞检测库。支持AABB/OBB包围盒、GJK/EPA精确检测、BVH层次加速。C++实现,性能好。

Bullet Physics:游戏引擎和机器人仿真(PyBullet)中常用。碰撞检测部分也是GJK+EPA。

Drake:MIT的机器人仿真库,碰撞检测用自研的Signed Distance Function方法——对凸形状用GJK,对非凸形状分解为凸部分分别检测。

性能参考数据:两个包含1000个三角面片的模型,FCL用BVH+GJK的碰撞检测约0.01-0.1ms。如果用原始三角面片两两对比(1000×1000=100万次检测),需要几十毫秒。BVH加速比在100-1000倍。

五、面试实战

Q:GJK算法的核心思想是什么?A:通过闵可夫斯基差判断两个凸形状是否相交——如果闵可夫斯基差包含原点则相交。GJK迭代地构建包含原点的simplex,不需要显式计算整个闵可夫斯基差。

Q:GJK只能处理凸形状吗?A:是的,GJK要求输入是凸形状。非凸形状需要先做凸分解(Convex Decomposition),分解成多个凸部分,再对每一对凸部分分别用GJK检测。VHACD是常用的凸分解算法。

Q:碰撞检测怎么加速?A:三层加速。第一层AABB包围盒粗筛(6次比较)。第二层BVH层次树剪枝(减少需要检测的物体对数量)。第三层GJK精确检测(迭代次数少,每次O(log N))。三层叠加后碰撞检测的加速比可达1000倍以上。

Q:你在项目中碰撞检测怎么做的?A:用FCL做碰撞检测。机械臂每个连杆用圆柱体包围盒,障碍物也用简化几何。BVH层次树在场景初始化时构建,机械臂移动时只更新连杆的包围盒位置。单次碰撞检测<0.05ms,规划一次调用约200-500次碰撞检测,总时间<20ms。

小结

碰撞检测三层架构:包围盒粗筛 → BVH层次树剪枝 → GJK/EPA精确检测。GJK通过闵可夫斯基差判断凸形状是否相交,EPA计算碰撞深度。FCL是机器人领域的标配库。

面试中碰撞检测的必考点:GJK的核心思想(闵可夫斯基差+support函数)、包围盒的层次和加速比、非凸形状的处理方法(凸分解)。

下一篇讲运动学约束规划——速度/加速度/加加速度限制的处理。


如果这篇文章对你有帮助,欢迎点赞、在看、转发三连。 你的支持是我持续更新的最大动力。

「机器人软件开发面试·从入门到精通」连载系列

上一篇:第230篇 机械臂运动规划——关节空间和笛卡尔空间的规划策略

下一篇预告:第232篇 运动学约束规划——速度/加速度/加加速度限制的处理

有任何问题欢迎评论区留言,我会尽量回复。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/22 13:16:21

华为认证HCIA/HCIP数通备考指南:从背题误区到实战能力提升

大家好&#xff0c;我是专注于网络技术分享的博主。最近在技术社区和备考圈里&#xff0c;经常看到关于华为认证HCIA/HCIP数通方向“好过”、“背题库就能上岸”的讨论&#xff0c;甚至流传着“几十页资料搞定”的说法。作为一名经历过完整认证流程并长期关注网络技术发展的从业…

作者头像 李华
网站建设 2026/8/22 13:14:11

CSI Tool 环境搭建与数据采集实战:从硬件选型到无线感知实验设计

1. 从“信号指纹”到环境感知&#xff1a;CSI Tool 究竟是什么&#xff1f; 如果你对无线通信、室内定位或者环境感知技术感兴趣&#xff0c;那你大概率听说过“信道状态信息”这个词。简单来说&#xff0c;当你的手机连接Wi-Fi时&#xff0c;它和路由器之间并非只有一条看不见…

作者头像 李华
网站建设 2026/8/22 13:13:24

基于 CX78GD024E 的 45W GaN 屏显快充参考设计解析

基于 CX78GD024E 的 45W GaN 屏显快充参考设计解析 随着 USB-PD 快充普及&#xff0c;充电器正从「能充」走向「看得见的快充」。一块小巧的 TFT/LED 屏&#xff0c;把充电功率、状态、保护信息实时呈现&#xff0c;既提升用户体验&#xff0c;也成了产品差异化的抓手。 本文以…

作者头像 李华
网站建设 2026/8/22 13:08:29

LLM智能体持久化记忆安全:注入-执行分离攻击原理与防御实践

1. 项目概述&#xff1a;当LLM智能体有了“记忆”&#xff0c;攻击也随之而来最近在折腾大语言模型智能体&#xff08;LLM Agents&#xff09;时&#xff0c;我遇到了一个既让人兴奋又让人头疼的问题&#xff1a;持久化记忆。简单来说&#xff0c;就是让智能体在多次对话或任务…

作者头像 李华