E1 · 建模、坐标、状态与时间#
学完本章,应能从一份模型说明构造原生对象,解释几何、惯量和状态分别存在哪里,并在正确的时间边界读取它们。先修是对象导读与基本向量/矩阵运算。应用路线读第 1–7 节与示例;源码路线同时完成公式推导、实现追踪和最后的练习。
本章固定阅读 ovphysx-0.6.3 对应提交 da950a3537927784951853c66618036f332ca0ce,其中 SDK 头文件是 5.11.0。标签、头文件、实际链接二进制和 Isaac Sim/UniSim 宿主版本分别记录,不能相互替代。以下使用普通 CPU 场景的 C++ SDK 接口;启用并初始化 Direct GPU API 后,若干 CPU 状态访问接口不适用,不能照搬本章片段。版本定义与状态接口限制是核对入口。
交付范围是 A1、A2 以及 B0 的刚体数据/坐标基础、B4 的时间边界。接触装配、PGS/TGS 的方程与完整积分路径属于 E3;可微、GPU、完整机器人导入及运行安装验收不由本章替代。这里没有进行物理实验。
1. 先把模型拆成对象和职责#
PxPhysics 创建资源,PxScene 管理一次仿真的对象集合、重力、调度及求解配置。PxRigidActor 提供世界位姿并引用 Shape;PxShape 描述碰撞/查询几何、局部位姿、材料和过滤标志。视觉网格、相机材质、USD/URDF 文件名和任务状态不是这些接口的同义字段。
层 |
原生入口 |
存储什么 / 不应混入什么 |
|---|---|---|
物理实例 |
|
SDK 对象工厂;创建时的 tolerances scale |
场景 |
|
重力、CPU dispatcher、filter shader、求解配置;不是渲染窗口 |
静态刚体 |
|
静态几何的 Actor 世界位姿;不积分动态质量/速度 |
动态刚体 |
|
质量、惯量、速度、力、睡眠等;默认创建对象不等于已添加到 Scene |
运动学刚体 |
|
由应用给目标位姿;不由施加的力决定运动 |
碰撞形状 |
|
几何、Actor 内的局部位姿、材料;不会自动刷新刚体质量惯量 |
关节树 |
|
根连杆和树状子连杆、入关节;不要把它当作独立动态 Actor 数组 |
材料 |
|
物理接触参数;不是渲染颜色/PBR 材料 |
来源:对象创建、材料工厂、articulation 创建。本章只用这些原生层次,不建立统一跨引擎模型类。
生命周期不是“把指针交给 Scene 就不用管”#
createShape 返回的 Shape 有一份引用;attachShape 成功后增加一份引用;detachShape 减少引用。常见顺序是创建 → 检查附着成功 → 释放应用的创建引用,由 Actor 保留附着引用。要继续修改局部位姿,优先创建 exclusive Shape;已附着的 shared Shape 不可修改。Actor/Shape/Material 的 SDK 指针不是值快照,释放后应用保存的裸指针会失效。创建引用与可变性、附着与拆卸。
按依赖关闭:先结束尚未取回的物理步,再释放使用中的对象/场景及资源,最后释放 Physics 和 Foundation;不要在 simulate 与 fetchResults 之间释放 Scene。本章示例把 Scene、Physics、Material 的创建和销毁交给宿主,明确返回 Actor 的释放责任,避免隐含的全局所有者。Scene 释放限制、Physics 与 Foundation 生命周期。
2. 几何、cooking 与资产边界#
原生几何尺寸#
PxBoxGeometry(hx, hy, hz) 使用半边长。PxCapsuleGeometry(radius, halfHeight) 的圆柱段长度为 2 * halfHeight,本地长轴是 X;加上两端半球后全长为 2 * (halfHeight + radius)。把“Z-up 场景”误写成“胶囊沿 Z”会得到旋转了 90° 的碰撞体。Box、Capsule。
Shape 的 eSIMULATION_SHAPE 与 eSCENE_QUERY_SHAPE 分别控制参与物理碰撞和 raycast/overlap/sweep 等查询。一个只参与查询的几何能被射线命中,不代表能支撑物体。eTRIGGER_SHAPE 与 simulation 标志不能同时打开;需要两者时建立两个 Shape。eVISUALIZATION 是 SDK 调试绘制标志,不是宿主视觉模型。Shape flags。
Mesh 数据怎样进入碰撞系统#
一条可审计的资产路径是:
宿主/应用解析资产:把源文件的顶点、索引、单位、朝向和变换解释成数组;保留文件哈希、许可、尺度、碰撞近似方法。
选择碰撞表示:primitive、convex hull 或 triangle mesh。视觉三角形不一定适合作为动态碰撞表示。
填原生 descriptor:例如
PxTriangleMeshDesc或PxConvexMeshDesc;数组元素数、步幅、索引格式、退化几何都属于输入契约。Cooking:
PxCookTriangleMesh/PxCookConvexMesh转成供碰撞查询使用的数据,检查 bool 和 cooking result;再由 Physics 创建 mesh。也可用PxCreateTriangleMesh/PxCreateConvexMesh直接创建,调用方提供 insertion callback。建立 Shape 并附着:geometry 引用 mesh,Shape 再引用 geometry/材料;核对 local pose 与 collision/query flags,最后显式计算或设置质量属性。
Cooking 的职责是处理碰撞数据,不是自动理解 URDF link/joint、USD stage、视觉材质或机器人执行器。宿主导入器可能做缩放、凸分解、关节映射和惯量替换,这些必须另记导入器版本与参数,不能统称为“PhysX 默认”。Cooking 原生声明、triangle mesh 路径。
不要从旧的形状限制推出“一切动态三角网格都不支持”。 本基线的 attachShape 注释仍列出非运动学动态 Actor 的 triangle mesh/heightfield/plane 限制;但同一固定树的官方 SnippetSDF在 cooking descriptor 中提供 SDF,并创建带三角网格的动态刚体。它还区分 CPU/GPU 场景分支。所以普通碰撞网格与 SDF 碰撞数据要分别核对;SDF 的构造质量、分辨率、接触路径和具体限制留到 E3/E6,本章只用 primitive。几何路径适用、cooking 成功、模型物理合理性是三个不同检查,视觉导入成功不能替代其中任何一个。
PxMeshScale 是网格几何的缩放表达;PxTransform 是刚性旋转/平移,不含任意缩放。资产换单位时需一致修改几何和质量属性,不能仅缩放渲染节点。不要把 mesh/shape 指针复制当作复制 mesh 数据或转移资源所有权。网格尺度、Transform 字段。仓库示例使用原创 primitive,没有新增第三方模型文件;引入资产时在 THIRD_PARTY.md 记录许可和修改。
3. 单位、轴系和姿态#
一个场景选一套一致量纲#
本章采用米、千克、秒(m/kg/s),角度为 rad。若基本长度、质量、时间单位分别是 L、M、T,则速度为 L/T,加速度为 L/T²,密度为 M/L³,惯量为 ML²,力为 ML/T²,力矩为 ML²/T²。对于相同物理物体,米改成厘米、质量和秒不变时:位置、速度、重力的数值乘 100;惯量乘 10⁴;密度除 10⁶。若是真的把物体放大且保持密度,质量又要随尺寸的三次方变化,不要与单位换算混为一谈。
PxTolerancesScale.length 和 .speed 用来建立若干容差/阈值的参考尺度,不替你转换模型、质量或重力。默认 length=1、speed=10;厘米尺度的 length 通常设 100。PxSceneDesc 在这份源码中重力默认是零;官方 HelloWorld 自己设置了重力。因此不能以为创建 Scene 后就自动得到地球重力。尺度定义、Scene 默认构造。
世界“向上”由建模与应用共同约定;选 Y-up 就配 (0, -9.81, 0),选 Z-up 就配 (0, 0, -9.81),并转换资产、相机和控制坐标。primitive 的固有轴线与世界上方向独立。C++ PxReal 在本基线是 float,不能因某个宿主 Python 数组是 float64 就宣称物理核心 FP64。标量类型。
PxQuat 与变换方向#
PxQuat(x, y, z, w) 把实部放在最后;单位四元数为 (0,0,0,1)。轴角构造器输入 rad 和单位轴。四元数需保持单位长度,q 与 -q 表示同一旋转;四元数有四个存储分量但只有三个旋转自由度,不能把四个分量分别当欧拉角速度积分。构造器。
约定 T_WA 把 Actor 坐标的点变换到世界,T_AS 把 Shape 坐标的点变换到 Actor,T_AC 把质心惯性坐标的点变换到 Actor,则:
数学量 |
C++ 原生读取 |
返回语义 |
|---|---|---|
|
|
Actor 在世界中的位姿 |
|
|
Shape 在 Actor 内的位姿 |
|
|
质心及惯性主轴在 Actor 内的位姿 |
|
|
Shape → 世界的复合变换 |
|
|
质心惯性坐标 → 世界 |
PxTransform::transform(point) 做 q.rotate(point) + p,复合变换按“先右边,后左边”。位置使用 transform;方向/速度只做旋转时使用 rotate,不要把平移加到方向上。默认 PxTransform() 不初始化为单位变换,显式写 PxTransform(PxIdentity)。实现、点和变换复合。
源码阅读注意:个别注释方向不够一致,例如 setLocalPose 的参数句和 getRootGlobalPose 的摘要。这里按 getter 的对象语义、变换乘法和实际实现核对:root getter 返回根连杆 getGlobalPose(),没有取逆。不要仅凭一句“world to actor”自行把根位姿反转。Shape getter、root 实现。
4. 质量、质心和惯量是独立参数#
setCMassLocalPose 改变质量坐标相对 Actor 的位置和方向,不会移动 Actor。setMass 只改质量,不会连带重算惯量;attachShape 或修改 Shape 局部位姿也不会自动重算它。质量 API、Shape 位姿与惯量。
SDK 存 getMassSpaceInertiaTensor() 的三个对角值 I_x,I_y,I_z,它们定义在以质心为原点、按惯性主轴定向的质量坐标中。若从 CAD 得到 Actor 坐标下、关于质心的完整惯量矩阵,应先检查对称性、物理合理性和单位,再对角化:
R_AC 的朝向放到 setCMassLocalPose 的旋转部分,三个特征值放到 setMassSpaceInertiaTensor;不能直接丢弃非对角元素。若输入惯量是关于 Actor 原点 O,需先用平行轴定理转换到质心 C,且全部在同一坐标系表示:
这两式是刚体质量几何的关系,不是 PhysX 接触求解器方程。本章假设普通有限质量刚体;API 中质量 0 对 PxRigidDynamic 表示无限质量,惯量某项 0 表示该轴无限惯量,不是无质量/自由转动。PxArticulationLink 不允许这些 0 值。惯量接口特殊值。
由几何构造均匀密度刚体时可调用 PxRigidBodyExt::updateMassAndInertia(body, density);默认只纳入 simulation Shape,可选纳入非 simulation Shape。它会写质量、质心和惯量,应检查 bool。实现先合成各 Shape 质量矩,再计算质心并对角化;不提供 massLocalPose 时使用计算得到的质心,而不是强制 Actor 原点。源码能纠正“参数注释里的默认 (0,0,0) 就是最终质心”的误读。扩展接口、质心与对角化实现、最终写回。
以均匀长方体半边长 (a,b,c) 为例,体积 8abc,质量 m=8ρabc,质心惯量 I_x=m(b²+c²)/3,其余循环置换。边长 1 m、密度 1 kg/m³ 时,质量 1 kg,三项惯量均为 1/6 kg·m²。这是理解参数的解析例子,没有作为物理运行结果。
为什么 Actor 原点速度不等于 getLinearVelocity#
线速度 getter 返回质心速度,以世界方向表达;角速度也用于世界方向下的刚体速度关系。对世界点 P:
PxRigidBodyExt::getVelocityAtPos 先把质心局部位置变到世界,再用上式求点速度。因此不能用 Actor 原点位置的差分直接检查质心速度,除非原点与质心重合或转动项为零。改了质心局部位姿,SDK 也不会自动调整已经保存的线速度。getter、点速度实现。
5. 状态维度与 articulation 索引#
刚体不是一条 SDK 统一 q 数组#
一个自由刚体的姿态可以保存 3 个位置分量和 4 个四元数分量;速度是 3 个线速度加 3 个角速度。7 个姿态标量不意味着 7 个机械自由度。质量、惯量和 Shape 几何是模型属性;力、kinematic target、睡眠状态又不能由这 13 个数推回。PxTransform 内部字段顺序是 q 再 p,勿对对象直接 memcpy 成自己约定的 [p,q] 数组。
对象 |
配置/状态表达 |
读取/设置注意事项 |
|---|---|---|
|
世界位姿;不作为动态速度状态 |
移动静态 Actor 可能重建优化结构,不适合连续移动障碍 |
普通 |
Actor 位姿、COM 线速度、角速度 |
|
kinematic dynamic |
当前位姿 + 待执行的 target |
|
fixed-base articulation |
|
基座没有额外自由运动 DOF,但根位姿仍需有明确坐标 |
floating-base articulation |
上述关节量 + 根 Actor 位姿 7 个分量 + 根 COM 线/角速度 6 个分量 |
|
来源:瞬时设姿、kinematic target、DOF 定义。这个 n 是关节状态数组的长度,不是以每根 link 各 7 个分量拼接得到的大小。
Tree、joint frame 与 cache 排列#
一个 articulation 是以 root 为起点的连杆树。每条非根 link 的 inbound joint 有 parent/child 两个局部关节坐标,分别相对各自的 Actor frame;不能把它们填成世界位姿或质心位姿。关节类型与各轴 motion 在入 Scene 前配置,默认关节类型为 undefined、motion 为 locked。eTWIST/eSWING1/eSWING2 分别对应局部 X/Y/Z 旋转,eX/eY/eZ 对应平移;锁住的轴不应当被当作自由状态槽位。joint frame/type/motion、axis/type 枚举。
jointPosition/jointVelocity 的长度都是 getDofs();旋转用 rad/rad·s⁻¹,平移用 L/L·s⁻¹。球关节缓存使用原生按轴的位置量,本版要求每轴位置在 [-π, π],不是每个球关节追加四元数。revolute 与 revolute-unwrapped 的绕圈表示也不同。cache 字段、joint type。
加入 Scene 后读取 getLinkIndex() 和 getInboundJointDof();低层 link 索引按广度优先生成,可能不同于创建顺序。按低层 link 顺序累加各入关节 DOF,再在关节内按 PxArticulationAxis::Enum 排列有效轴。举例:低层 link 0,1,2,3 的 DOF 数为 0,1,2,1 时,关节数组偏移分别为“无”、0、1、3;link 2 占槽位 1、2。保存模型名称→link→轴→DOF 的显式映射,不能排序名称后直接写 cache。link index、cache 索引规则。
Cache 是有生命周期的数据缓冲,不是模型本身#
字段 / 操作 |
数据与权限 |
易错点 |
|---|---|---|
|
articulation 在 Scene 中才创建有效 cache;调用方负责释放 |
改结构后应释放重建,不能沿用旧大小/索引 |
|
把指定状态复制到 cache |
只更新 flags 选中的内容;不能假定所有数组有效 |
|
将指定可写状态应用回 articulation |
不能在物理步运行中调用;会按约定触发唤醒 |
|
root Actor 世界位姿 |
不是 COM 位姿 |
|
root COM 的世界线/角速度 |
与 actor origin 不同 |
|
每 link 的 COM 速度,世界表达,读取用 |
|
|
清 cache 指定的数据区域 |
不直接修改 articulation,也不把 root 四元数设成单位旋转 |
eALL 只包含其枚举定义中的状态位;本版不包含 joint force、joint target、link force/torque。目标和外力等字段有自己的读写权限,不能把 eALL 当作整个控制系统快照。flags 定义、空间量/根数据、cache 生命周期与读写。
6. 重置、快照与“状态已经刷新”#
重置是一份应用契约:将哪些对象恢复成什么状态,控制器与时间如何同步。SDK 中瞬移一个 Actor 不等于重置整个环境。
对于本章示例限定的普通、已在 Scene 中、启用 simulation 的独立动态刚体:在上一轮 fetchResults 完成后,设初始 Actor 位姿、COM 线速度与角速度;按使用的 force mode 清理力/力矩累加器;明确睡眠/唤醒策略;再重置应用控制器、计时器和观测缓存。持续外力标志 eRETAIN_ACCELERATIONS 会影响跨步清理,不能仅关闭该标志就假定下一步外力为零。刚体的 putToSleep() 会清速度、力和 wake counter;若目标初始速度非零,就不能拿它作为“通用 reset 最后一步”。保留外力语义、累加器清理、睡眠。
Kinematic 的 target 与当前 pose 分开;setGlobalPose 不能自动表达本轮目标轨迹。articulation 应恢复根状态和 reduced joint state,而不是逐 link 强行覆盖位姿。两条原生路径要分开:
Cache 路径:创建/读取合法 cache;只覆盖自己想恢复的字段;用
ePOSITION | eVELOCITY | eROOT_TRANSFORM | eROOT_VELOCITIES等明确 mask 应用。applyCache负责对应连杆状态更新。Non-cache 路径:批量调用 root / joint setters 后,用
updateKinematic(ePOSITION)更新位置和速度;若只改速度,则用eVELOCITY。完成后再查询 link 状态或启动下一步。
不要零填整个 cache 后直接用 eALL 应用:既可能生成非法 root 四元数,也把你未打算修改的量清掉。模型结构、关节轴顺序、cache 版本必须与保存时一致。更新语义、applyCache 等价关系。
可以区分三种保存物:
保存物 |
应用需要记录的内容 |
能支持什么 |
|---|---|---|
状态记录 |
位姿、速度、关节数组、root、稳定对象/轴 ID、采样时间 |
可解释的观测或指定状态重置 |
环境恢复记录 |
上述状态 + model/hash、所有相关控制目标/外力、睡眠策略、控制器状态、随机数状态、步计数 |
定义清楚的应用重启;仍需验证恢复行为 |
SDK 对象序列化 |
完整 |
对象图恢复,不自动包含宿主控制器、相机或应用时钟 |
PxSerialization::complete 会补齐 shape/material/mesh、joint/actor 等依赖。二进制输入还要求内存对齐和兼容的序列化格式;不支持序列化正在仿真的 Scene 中的对象。不能仅凭一个 collection 或 cache 宣称接触历史、内部缓存与外部程序状态都恢复,并保证逐位相同的后续轨迹。本阶段未作这类运行验证。依赖规则、二进制兼容与阶段要求、序列化限制。
7. 一个物理步的时间与访问边界#
先定义物理时钟 t_k、固定步长 h>0,以及由应用维护的整数步计数 k。一次成功提交并取回的 simulate(h) / fetchResults(true) 推进一次物理步;fetchResults 不是又推进一次。物理时间可按 k*h 计算,wall time 是执行所耗的时间,渲染帧率与二者都不同。配对协议。
阶段 |
本章采用的保守访问约定 |
输出属于什么时刻 |
|---|---|---|
上一轮 fetch 已完成 |
读取状态 |
控制使用 |
|
计算任务已启动;执行与物理数据无关的应用工作 |
不把“函数返回”当作 |
|
仅查询是否完成计算 |
不交换/公开最终读取状态,不能替代 fetch |
|
等待、交付结果/回调;检查返回、错误回调和 errorState |
成功且无错误后读 |
应用复制观测 |
复制需要保存的值,标注 k+1、h、坐标与对象 ID |
渲染/记录消费这份观测,不长期持有临时数组 |
不要把“用 lockRead/lockWrite 包住”理解为可以在任意物理阶段读写:线程互斥与 SDK 阶段限制是两回事。具体 API 有 split simulation 和回调阶段例外;本章统一在 fetch 完成后访问,例外留给后续扩展专题。check/fetch 区别、锁契约、getter 阶段限制。
源码路线按以下路径读,而不是仅搜索 API 名字:
NpScene::simulate转发simulateOrCollide(..., eADVANCE)。simulateOrCollide检查上轮阶段是 complete、dt 为正,建立当前任务;非法重复 simulate 会报错。NpScene::checkResults只等待完成事件。NpScene::fetchResults核查阶段、等待完成、处理接触回调和前后同步,然后结束这一轮访问阶段。
入口:simulate、转发、完成事件、fetch 实现。此处只审查公开时间/状态协议,没有把调度入口冒充接触求解与积分算法的完整追踪。
时间步、子步与求解迭代是三种控制量#
若控制周期为 H,一个控制周期分成 n 个外部物理子步时,h=H/n;应用执行 n 次完整的 simulate(h) / fetchResults。控制器可以每 H 更新一次并按契约保持输入,也可以每 h 更新一次,两者得到不同的闭环系统。kinematic target 是单步目标,外力也有跨步清理/保留语义,因此“保持输入”要按原生接口重新施加,不能只把 n 改大。
setSolverIterationCounts(position, velocity) 是约束求解预算;它不会把应用时钟变成 n 个独立 step。TGS 的 position iterations 有自己的时间处理方式,还存在每迭代施加外力的 scene flag;它仍不等价于外部重新调用多轮碰撞与 fetch。后续 E3 要沿 PGS/TGS 分支核实这些差异,当前不把某个迭代数换算成另一引擎的求解次数。迭代入口、TGS 外力时机选项。
固定步长只让协议明确,不自动保证稳定或精确。碰撞几何尺度、质量比、驱动增益、初始穿透、接触正则化及 solver 都会影响结果;本章不提供未经运行验证的“安全 dt”。若显示循环落后,应用应明确积累剩余 wall time、限制每显示帧可做的物理步数,并记录是否丢弃时间;不能悄悄把大 wall delta 直接当物理步长。
8. 最小 C++ 阅读片段#
examples/e1_state_boundary.cpp 包含三个独立函数:创建均匀 Box(展示 Shape 引用与质量设置)、读取 Actor/COM/Shape 世界位姿、配对推进一次物理步。它假设调用方已建立 SDK、Scene、dispatcher、filter shader 与 material,并保持这些对象有效;使用普通 CPU Scene,未启用 Direct GPU API。
示例是原生 API 教学片段,不是可直接启动的程序或 reset 框架;没有 main、没有循环试验或评分。片段已用匹配固定提交的公开头文件通过 g++ -fsyntax-only,未链接/运行 SDK;命令和范围见验证记录。语法/类型检查即使通过,也不验证 SDK 链接、资源销毁、运行错误或物理结果。
9. 易错点与定位顺序#
现象或误读 |
先核对的边界 |
|---|---|
看起来接触,实际穿过去 |
visual geometry 与 simulation Shape 是否同一表示;flags、cooking 是否成功 |
盒子尺寸大一倍、胶囊方向不对 |
Box 半边长;capsule 本地 X 轴;shape local pose |
改质量后运动异常 |
setMass 是否同时配套了正确惯量;单位与 COM 主轴是否一致 |
改 shape 后重心不变 |
Shape 操作不自动更新质量属性,显式计算/指定 |
reset 后第一帧 link pose 是旧的 |
non-cache articulation setters 后是否 updateKinematic |
cache 写错关节 |
是否用入 Scene 后低层索引和有效轴映射;不是创建顺序 |
下一步仍有力或突然移动 |
外力保留标志、累加器、旧控制目标、kinematic target 与控制器状态 |
看似线程安全仍报访问错误 |
互斥锁不能替代 fetch 和 SDK 阶段规则 |
状态坐标不一致 |
Actor pose、COM 速度、Shape local pose 是否混装为同一 frame |
只看到 float64 Python 数据 |
宿主数组类型不能证明原生 PxReal 或求解精度 |
10. 阅读练习与答案#
世界 Actor 位姿为
(1,0,0)且无旋转;Shape local pose 为(0,2,0)且无旋转;COM local pose 为(0,0,0.5)。三个世界原点在哪里?哪个用作getLinearVelocity的参考点?把同一个米制模型改为厘米制而质量单位不变:为什么惯量不是乘 100?为何只设置 tolerances scale 不够?
setMass(2)之后读出的 inertia 仍与之前相同,是错误吗?setMass(0)能代表无质量传感器吗?一个 floating-base articulation 有两个单自由度关节。
getDofs()为多少?root pose 和 root velocity 应存多少标量?能否按两个 link 的创建顺序复制 cache?调用
zeroCache再applyCache(eALL)能否得到单位 root pose、零控制目标、无外力的完整环境重置?checkResults(true)返回 true 后立刻读位姿,和fetchResults(true)后读位姿等价吗?若把 H=0.02 s 分成 4 步,时钟和目标更新怎样记录?定位源码中的两个注释歧义:默认 massLocalPose 和 root global pose 方向,如何用实现判断?
答案与源码核对点
Actor 原点
(1,0,0),Shape 原点(1,2,0),COM 原点(1,0,0.5)。线速度对应最后一个点;其他点速度还需要角速度叉乘位移。惯量量纲是 ML²,长度数字乘 100 时惯量乘 10⁴;密度数字除 10⁶。scale 只影响若干参考阈值,几何、重力、密度、惯量仍需应用一致换算。
不是错误,
setMass不更新 inertia;若希望相应改变质量分布,调用合适的扩展函数或自己提供一致值。0 是该 API 的无限质量特殊值,不能表示无质量。getDofs()==2,不含基座 6 DOF。root pose 存位置 3 + quaternion 4,root velocity 存线 3 + 角 3。缓存要用低层 link index 和轴映射;创建顺序没有这个保证。不能。zeroCache 只清缓冲,零四元数也不是单位旋转;eALL 不含所有控制/外力字段,应用控制器和时钟更不在其中。应使用合法 root pose、明确 mask 和环境重置契约。
不等价,check 只检查完成,没有完成 fetch 的结果交付过程。四轮完整 simulate/fetch 的 h=0.005 s,总计推进 0.02 s;写清控制是在 H 更新保持还是每 h 更新,kinematic target/力如何按子步提交。
computeMassAndDiagInertia在未锁定 COM 时调用getCenterOfMass();root getter 返回 root 的getGlobalPose()。分别以它们和 PxTransform 的组合语义为准,保留歧义说明,不照搬相冲突的短注释。
下一步#
E2 在这些对象、坐标与采样约定之上展开驱动、关节映射、机器人接口和任务控制;E3 展开接触/材料组合、约束和 PGS/TGS 的积分数值语义。两者都保留 native C++ 入口和宿主边界。未来实验案例链接到 DexLab,本章没有产生新实验结果。