💥 刚体碰撞检测#
Genesis 为刚体提供了高效、功能丰富的碰撞检测和接触生成管线。Python 实现位于 genesis/engine/solvers/rigid/collider_decomp.py。本页提供对算法构建块的概念性概述,以便您理解、扩展或调试代码。
范围。 重点在于刚体-刚体交互。软体/粒子碰撞依赖于其他求解器,位于
genesis/engine/coupler.py等文件中。
管线概述#
整个过程可以分为三个连续阶段:
AABB 更新 – 为每个几何体更新世界空间的轴对齐边界框。
粗阶段 (Sweep-and-Prune) – 基于 AABB 快速排除明显不相交的几何体对,输出可能的碰撞对。
精阶段 – 使用特定原语算法、SDF、MPR 或 GJK 为每个保留的对稳健地计算实际接触流形(法线、穿透深度、位置等)。
Collider 通过公共的 detection() 方法协调所有三个阶段:
collider.detection() # 更新 AABB → SAP 粗阶段 → 精阶段
每个阶段在以下各节中描述。
1 · AABB 更新#
辅助内核 _func_update_aabbs() 将工作委托给 RigidSolver._func_update_geom_aabbs()。它为每个几何体计算一个紧密的世界空间 AABB,并将结果存储在 geoms_state[..].aabb_min / aabb_max 中。
为什么每帧都要做这件事?
刚体移动 ⇒ 它们的边界框发生变化。
AABB 重叠检查是粗阶段的基石。
2 · 粗阶段 – Sweep & Prune#
粗阶段在 _func_broad_phase() 中实现。它是经典 Sweep-and-Prune(又称 Sort-and-Sweep)的 N·log N 插入排序变体:
将每个 AABB 投影到单个轴(当前为 X 轴),并将其 min 和 max 端点插入可排序缓冲区。
热启动 – 端点已经几乎从上一帧排序好 ⇒ 插入排序几乎呈线性。
遍历排序后的缓冲区,维护一个与当前端点重叠的区间活动集。
当
min_a穿过max_b内部时,我们就有一个潜在的对(geom_a, geom_b)。
额外的过滤步骤移除物理上不可能或明确禁用的对:
相同连杆 / 相邻连杆过滤。
contype/conaffinity位掩码。相对于世界都固定的连杆对。
休眠支持 – 除非与激活体碰撞,否则忽略休眠体。
保留的对存储在 broad_collision_pairs 和 n_broad_pairs 中。
3 · 精阶段 – 接触流形生成#
精阶段分为四个专门的内核:
内核 |
何时运行 |
目的 |
|---|---|---|
|
一般凸-凸 & 平面-凸 |
使用 MPR(Minkowski Portal Refinement)的默认路径,带有符号距离场查询回退。当 |
|
平面-盒体 & 盒体-盒体 |
具有一对凸几何体解析解的专门处理程序。 |
|
至少一个几何体是高度场地形 |
每个支撑单元生成多个接触点。 |
|
至少一个几何体是非凸的 |
通过 SDF 顶点/边缘采样处理网格 ↔ 凸体或网格 ↔ 网格碰撞。 |
3.1 凸体-凸体#
3.1.1. GJK#
GJK 配合 EPA 是许多物理引擎中广泛使用的接触检测算法,因为它具有以下优点:
完全在 GPU 上运行,得益于无分支的支持映射原语。
每个形状只需要一个支持函数 – 无需面邻接或特征缓存。
当几何体不接触时给出分离距离。
在许多实现中经过验证的数值鲁棒性。
在 Genesis 中,当 RigidOptions 中的 use_gjk_collision 选项设置为 True 时启用。此外,Genesis 通过以下措施增强 GJK 的鲁棒性。
对运行时的单纯形和多面体进行彻底的退化检查。
鲁棒的面法线估计。
鲁棒的穿透深度上下界估计。
Genesis 使用预计算的 Support Field 加速支持查询(参见 Support Field)。
通过在第一个接触法线周围进行小姿态扰动启用多接触生成。每对最多存储五个接触点 (_n_contacts_per_pair = 5)。
3.1.2. MPR#
MPR 是另一个被物理引擎广泛采用的接触检测算法。尽管它与 GJK 共享大部分优点,但当几何体不碰撞时它不给出分离距离,并且由于在许多实现中没有得到充分验证,可能容易受到数值错误和退化的影响。
在 Genesis 中,MPR 在深度穿透时通过符号距离场回退进行了改进。
与 GJK 一样,Genesis 使用预计算的 Support Field 加速 MPR 的支持查询,并通过在第一个接触法线周围进行小姿态扰动来检测多个接触点。因此,每对最多存储五个接触点 (_n_contacts_per_pair = 5)。
3.2 非凸对象#
对于三角形网格或分解的凸簇,管线使用离线预烘焙的符号距离场(SDF)。算法采样
顶点(顶点-面接触),然后
边缘(边缘-边缘接触)
并保留最深的穿透。如果已经找到顶点接触,则跳过成本高昂的边缘遍历。
3.3 平面 ↔ 盒体 特殊情况#
移植了 Mujoco 的解析平面-盒体和盒体-盒体例程,以获得额外的稳定性,并避免当盒体平放在平面上时的退化情况。
接触数据布局#
成功的接触被推送到数组结构体字段 contact_data:
字段 |
含义 |
|---|---|
|
几何体索引 |
|
正深度(≤ 0 表示分离) |
|
世界空间单位向量,从 B 指向 A |
|
相互穿透的中点 |
|
有效库仑系数(取两者最大值) |
|
求解器调整常数 |
n_contacts 以原子方式递增,以便 GPU 内核可以并行追加。
热启动与缓存#
为了提高时间相干性,我们为每对几何体缓存先前最深顶点的 ID 和最后已知的分离法线。缓存被咨询以播种 MPR 搜索方向,并在对在粗阶段分离时清除。
休眠#
启用此功能后,仅属于休眠体的接触被保留但不再每帧重新评估 (n_contacts_hibernated)。这大大减少了具有大型静态背景场景中的 GPU 工作量。
调整参数#
选项 |
默认值 |
效果 |
|---|---|---|
|
4096 |
粗阶段对的上限(每环境) |
|
|
多接触搜索的扰动角度 |
|
|
重复接触拒绝半径 |
|
|
当一个形状包围另一个时从 MPR 切换到 SDF 的阈值 |
进一步阅读#
Support Field – 支持映射形状的离线加速结构。