E1 · 模型、坐标、状态与时间#
Learning home · Newton Physics contents
Course text is primarily Chinese, with English terminology and summaries. The original content is preserved.
先修:对象导读。应用路线读第 1–5、7–9 节;原理路线连同第 6、10 节一起读。本章完成 A1、A2,并交付 B0 的配置/空间量/惯量基础与 B4 的时间/积分基础。约束方程、完整求解过程和数值误差分析留在 E3,不把本章当作完整动力学课程。
阅读基线为 Newton 1.6.1、固定提交 713fecdc41caf0c9d726f5c016939f36e66e3dff。Newton Python API、Warp 数组/内核运行时、具体 Solver 后端是三个层次;候选 Warp 1.18.0 不是本章实测环境。SolverMuJoCo 还涉及 MuJoCo/MuJoCo Warp 的单独身份。本章仅核对官方源码、文件身份和片段语法,没有执行引擎、导入资产、仿真实验或性能测试。 本文的数字算例是公式推导,不是测量结果。
1. 先决定谁描述结构、谁保存状态#
Newton 将可编辑模型组装与设备数组分开。ModelBuilder 的 add_link、add_joint_*、add_shape_* 把结构写入构建器;finalize(device=...) 验证结构、组织索引并将模型数据转到指定 Warp 设备。修改构建器不会自动修改已生成 Model。固定拓扑的参数更新也需按相应 Solver 的通知协议处理,不能将 Model 理解为任意写入后自动传播的 Python 配置。
对象 |
本章关注的内容 |
创建/消费位置 |
所有权与边界 |
|---|---|---|---|
|
body、shape、joint、articulation 与初始值 |
组装后 |
构建阶段的 Python 数据;添加拓扑后重新 finalize |
|
质量、惯量、形状、索引及初始 |
Solver 构造、 |
设备数组;初始值与当前 State 是不同数组 |
|
粒子/刚体/关节位置、速度与力缓冲 |
|
新 state 克隆模型初值;没有通用仿真时钟字段 |
|
目标、广义力等时变输入 |
|
默认克隆; |
|
碰撞生成和接触缓存 |
|
接触几何是对某次状态采样的结果,不等于步后状态 |
|
推进、约束处理及后端内部数据 |
|
支持能力、权威状态表示和历史缓冲随 Solver 改变 |
依据:finalize、state/control 分配、官方双摆调用链。Model 的 set_gravity 要求随后通知 Solver,见参数更新入口。
body、shape、joint 与 articulation#
add_body() 是便利入口:它创建一个 link、一条连接 world 的 FREE joint,以及单体 articulation。多体机构用 add_link 加各条 joint,再用 add_articulation 组织。body ID、shape ID、joint ID、坐标数组起始位置不是同一个编号空间。 add_body(label="block") 的返回值是 body ID,不是 joint_q 的下标。实现
shape 的 xform 相对于所属 body;body 的 xform 是世界位姿。body=-1 的 shape 属于静态世界几何。add_shape_box 的 hx/hy/hz 是半边长,不是全尺寸。一个 body 可以有多个 shape;形状的视觉开关、碰撞开关和质量贡献需分别检查。shape 契约、box 半边长
静态世界 shape、由 FIXED joint 约束的 body、is_kinematic=True 的 body 是不同建模方式。KINEMATIC 是用户指定运动、不受外力推进的刚体;公共积分 kernel 会把输入位姿/速度原样复制到输出,仅赋一个非零速度不会自动生成 kinematic 轨迹。本版本存储的 body flag 是 DYNAMIC 或 KINEMATIC,不能凭其他引擎经验猜一个 STATIC flag。is_static=True 是 shape 的零质量贡献选项,也不等于冻结它所属的动态 body。flags、kinematic 分支
2. 坐标与姿态:先写定义,再代数计算#
本文定义 \(T_{WB}=(R_{WB},p_{WB})\) 为将 body 坐标变到 world 的刚体变换:
旋转矩阵满足 \(R^TR=I\)、\(\det R=1\);向量只乘 \(R\),点还要加 \(p\)。因此局部 shape 位姿要和 body 位姿组合,不能直接当作世界坐标。关节的 parent_xform、child_xform 分别在父/子 body 局部系中定义关节锚点;可运动变换夹在两者之间:\(T_{WC}=T_{WP}T_{PJ_p}T_{J_pJ_c}(q)T_{CJ_c}^{-1}\)。源码对应 X_wpj * X_j * inverse(X_cj)。关节递推
Newton 默认右手系、Z-up,ModelBuilder(up_axis=...) 可指定其他 up 轴。显式 gravity=(gx,gy,gz) 不受 up 轴约束;省略时才默认沿 up 的反向取 9.81 m/s²。换 up 轴时,要一起检查重力、地面、资产方向和相机,不只是改绘图。轴系与重力、构造参数
量 |
Newton API 表示 |
单位/约定 |
|---|---|---|
位置、COM、形状长度 |
|
m;必须标注 frame |
旋转 |
|
单位四元数,标量在最后;\(q\) 与 \(-q\) 表示同一旋转 |
revolute 坐标/速度 |
|
rad / rad·s⁻¹ |
prismatic 坐标/速度 |
同上 |
m / m·s⁻¹ |
质量、密度、惯量 |
|
kg、kg·m⁻³、kg·m² |
外力/力矩、时间步 |
|
N / N·m;s |
四元数为 \(q=(\hat a\sin(\theta/2),\cos(\theta/2))\),其中 \(\hat a\) 是单位轴,\(\theta\) 用弧度。不能将 [roll,pitch,yaw] 塞进 quaternion 的前三项。MJCF 文件四元数采用 wxyz,Newton 导入器会显式重排为 xyzw;原生 wp.quat 调用则由使用者保证顺序。MJCF Euler 的角度单位还取决于 compiler,文件角度约定不是 State 的关节角单位。四元数约定、MJCF 姿态解析、compiler angle
3. 质量和惯量如何进入 Model#
body_com 是 body 局部系中的质心位置 \(c^B\);body_q 的平移是 body 原点的世界位置。世界质心为 \(c^W=p_{WB}+R_{WB}c^B\)。body_inertia 是绕 COM、在 body 局部方向表达的 \(3\times3\) 惯量;公共积分函数将世界角速度/力矩旋回局部系后使用该矩阵。字段、积分中的惯量坐标
对质量 \(m\)、COM 惯量 \(I_C\) 的刚体,换表达方向 \(R\)、再从 COM 换到偏移为 \(d\) 的平行轴:
这是质量分布的几何关系;不是随意把每个对角元乘相同系数。组合多个 shape 时先用 \(c=\sum_i m_i c_i/\sum_i m_i\) 得到新 COM,再将每个形状的旋转惯量平移到该点相加。Builder 的 _update_body_mass 正是这条路径。惯量变换、累加质量与 COM
默认 shape density 为 1000 kg/m³。shape 只有在非 static、密度大于零、附着于 body 且该 body 未锁惯量时才计算并累加质量。若你已经显式给定 body 的 mass/com/inertia,再添加有密度的 shape,会额外增加质量;lock_inertia=True 可禁止后续 shape 修改这三项,但它不阻止 fixed-joint 合并时的质量汇总。默认密度、累加条件、lock 语义
手算检查。 均匀实心 box 的全尺寸为 \((2h_x,2h_y,2h_z)\):
其余对角项循环置换,COM 在 shape 中心。取半边长 \((0.10,0.05,0.025)\) m、密度 1000 kg/m³,则质量为 1 kg;COM 三个主惯量分别约为 \((0.00104167,0.00354167,0.00416667)\) kg·m²。若将 shape 放在 body 局部 (0.10,0,0),COM 会随之偏移,但仅由该 shape 构成的 body 绕其 COM 惯量不因此增加平行轴项。算法参见box 质量/惯量。
物理上非退化三维刚体的惯量应对称正定,主惯量还满足三角不等式。不要用负惯量或乱填很小的数来“调稳定”。Builder 的 balance_inertia、bound_mass、bound_inertia 以及 finalize 的校正可能改变输入数据,因此应将导入前数据与最终 Model 字段分开记录;校正通过不等于测得了真实物体参数。校正设置、finalize 说明
4. 导入资产不是照搬文件名#
原生入口是 builder.add_urdf、add_mjcf、add_usd。导入器把各自文件语义变成 Newton 的 bodies/shapes/joints;之后仍要检查所选 Solver 是否支持生成的字段。文件解析成功不能证明驱动、接触或闭环行为等价于原宿主。
入口 |
此版本要核对的选项/行为 |
读入后需要保留的记录 |
|---|---|---|
|
源单位、根连接方式、最终 body/joint 标签与索引;不要把 visual mesh 默认当 collider |
|
compiler angle、inertiafromgeom、 |
compiler 与显式 inertial 的优先关系、最终惯量、solver 不支持的属性 |
|
|
stage 元数据、物理 schema、路径到实体映射及所有导入警告 |
缩放必须和质量假设一起说#
几何相似、均匀缩放因子 \(s>0\),若保持密度,理论上长度乘 \(s\)、质量乘 \(s^3\)、COM 惯量乘 \(s^5\);若保持质量,惯量乘 \(s^2\)。这是两种不同假设。
v1.6.1 的 URDF 显式 <inertial> 路径将 COM 长度乘 scale、惯量乘 scale**2,显式 mass 原样读取;MJCF 显式 inertial 路径也是如此。不能以为对已有显式质量的机器人设置 scale=2 会自动令质量变为 8 倍。几何/密度推导走另一条路径。URDF 处理、MJCF 处理
USD 的版本限制必须保留#
该版本对 legacy 刚体/collider 导入仍要求 metersPerUnit=1.0、kilogramsPerUnit=1.0;非单位元数据会触发警告。粒子分支存在 SI 转换,但与 legacy 刚体混合时采用不同路径。不能把“读取了 metadata”写成“所有 USD 自动换算正确”。对本章的刚体资产,应事先把几何与物理量统一到米/千克,并令元数据一致;仅改 metadata 而不转换内容同样错误。实际分支与警告
资产维护记录至少包括原始 URL/提交、作者与许可、尺寸/单位、视觉和碰撞网格是否相同、质量来源、导入选项、坐标变换以及哪些属性被忽略。引擎的 Apache-2.0 许可不会自动覆盖外部机器人/网格;本仓示例只使用原创 primitive,不分发第三方资产。
5. 配置维度不等于速度维度#
设配置是 \(q\in\mathcal Q\),广义速度是 \(v\in\mathbb R^{n_v}\)。四元数用 4 个数表示 3 个旋转自由度,因此一般有 \(\dot q=N(q)v\),而不是对所有关节都成立的 q += dt * qd。
joint type |
配置坐标数 |
速度自由度数 |
解释 |
|---|---|---|---|
PRISMATIC / REVOLUTE |
1 |
1 |
一条平移/转动轴 |
BALL |
4 |
3 |
quaternion 与角速度 |
FREE / DISTANCE |
7 |
6 |
平移 + quaternion;DISTANCE 仍有额外约束语义,数组长度不表示无约束 |
FIXED |
0 |
0 |
相对位姿固定;body 仍可随父体运动 |
D6 |
所配置轴数 |
所配置轴数 |
不必恰好 6;查构建后 layout |
依据:JointType 与 dof_count。ROD 的材料槽和 VBD 路径在 E6 讨论,不混入普通六维自由关节表。
每条关节分别使用 model.joint_q_start[j:j+2]、joint_qd_start[j:j+2] 定位;两个数组都有末尾 sentinel。joint_coord_count 与 joint_dof_count 才是全数组分配尺寸。不能用 joint ID 当 q 下标,不能拿 q 的切片切 qd,也不要在导入/合并/多 world 后假定旧索引仍有效。起始表定义
State 同时能容纳 body_q/body_qd 和 joint_q/joint_qd,但存在数组不代表它是当前更新的权威状态:
XPBD 使用 maximal coordinates,即逐 body 位姿/速度加关节约束。
step推进 body 字段;要获取对应的 generalized joint 数值,显式用newton.eval_ik(model, state, state.joint_q, state.joint_qd)做状态重建。eval_fk(model, joint_q, joint_qd, state)从关节输入更新 body 字段;它不是自动复制传入 q/qd 到 State 的万能同步器,也不是动力学步进。SolverMuJoCo/Featherstone 使用 generalized coordinates,不能把只改 body pose 当作有效机器人 reset。SolverMuJoCo 的同步周期和后端状态还需单独核查。
依据:坐标表示分类、FK 输出契约、IK 输入/输出契约、MuJoCo reset 同步说明。这里的 eval_ik 是从已有 body 状态重建关节数值,不是给末端目标求机器人的规划器;目标 IK 留给 E2。
6. 读懂六维速度与力:顺序、frame、参考点#
字段 |
前三项 / 后三项 |
表达方向与参考点 |
|---|---|---|
|
\(v_C\) / \(\omega\) |
都在 world 表达;线速度参考点是该 body COM |
|
\(f\) / \(\tau_C\) |
world 力与绕 COM 的力矩;外部输入缓冲,不是总接触反力 |
FREE/DISTANCE 的 |
相对线速度 / 相对角速度 |
child COM 参考的关节速度,表达在 joint parent frame;父体运动由递推另行加入 |
FREE/DISTANCE 的 |
力 / 力矩 |
本版本 API 指定 world 表达、child COM 参考;不能因数组与 qd 等长就假定可直接点乘算功率 |
依据:State 字段、关节递推实际换系、Control 的特殊约定。Warp 的底层空间向量 helper 通常 angular-first;Newton 公共数组是 linear-first。应使用 Newton 对应转换 helper 的约定,或明确重排后再调用 Warp,不能直接把 body_qd 当作 Warp 的任意 twist 输入。布局适配实现
同一刚体上的换点。 所有量先表达在同一 world 方向,令 \(r=p_{new}-p_{old}\),则:
力矩负号来自同一力作用点 \(P\):\(\tau_O=(P-O)\times f\),把参考点从 old 换到 new,力臂就减去 \(r\)。因此从 COM 速度取 body 原点速度,令 \(r=-R_{WB}c^B\);得到 \(v_B=v_C-\omega\times R_{WB}c^B\)。从作用点 P 的力写入 COM wrench 时,则 \(\tau_C=\tau_P+(P-C)\times f\)。
源码纠错记录。 固定版本 conventions primer 对 r=new-old 打印了力矩加号,和上述参考点定义不一致;同文 body/spatial mapping 的一条 twist 公式与前文定义也有符号冲突。本章不照抄这两条,而用明确的点定义推导,并对照 XPBD joint force kernel 的 r_c=joint_point-COM 及实际 r_c cross f 累加。transform_wrench 的 +p cross f 使用的是 source frame 原点在 destination frame 中的位置,是另一种变换定义,不与上面的换点负号矛盾。
手算:COM 在原点,力 \(f=(0,10,0)\) N 作用于 \(P=(0.2,0,0)\) m,则绕 COM 的力矩为 \((0,0,2)\) N·m;把参考点移到 P 后力矩应为零。这比背诵一条未说明 r 方向的公式更可靠。
7. 时间步、子步和 Solver 迭代分清#
调用者维护时间,dt 的单位为秒。若一帧物理时长为 \(H\),分为 \(N\) 个子步,则每次 step 传 \(h=H/N\),一帧累计推进 \(H\)。渲染 FPS、控制更新周期、接触重算周期可以不同,必须分别记录。Solver 的 iterations 是一次 step 内部的约束迭代次数,不会让物理时间推进 iterations 倍。
例如设渲染/控制帧 \(H=1/60\) s、\(N=4\),则 \(h=1/240\) s;若控制命令整帧保持,是 60 Hz 零阶保持输入。将控制器放到每个子步会改变为 240 Hz 更新的离散系统,不能只称作“同一控制”。这些是教学参数,不复用为 DexLab 的实测配置。官方 frame/substep 定义、时间累计位置
原生 XPBD 示例的顺序为:
state_in(t) → clear_forces → 写入本子步外力/控制
→ collide(state_in, contacts)
→ solver.step(..., h) → state_out(t+h)
→ 交换 Python 引用 → 更新调用者的时间
注意 clear_forces() 只清 State 的 particle/body 外力缓冲,不清 Control 的目标/关节力,不清 solver 历史,不重置位置。持续外力应在每次清理之后重新写入;写完马上 clear 会把输入擦掉。实现
采样必须标注阶段。 步前 collide 得到的接触位置/法线属于输入位姿;步后 body pose 属于 \(t+h\)。把二者拼成一条观测而不标阶段会误判接触位置。需要步后几何时再次 collide;需要该次求解的接触冲量/力则走 solver 的观测接口,不能用重新生成的几何替代。本章只确定数据时序,接触 force/impulse 语义在 E3 完整展开。XPBD step 输入契约
双缓冲与引用不是数据复制#
state_0, state_1 = state_1, state_0 交换的是 Python 名称。保存 old_pose = state_0.body_q 只得到同一设备数组的另一个引用;后续这个 buffer 被写入时,所谓历史也会变化。保存 pose 应 wp.clone(state_0.body_q);保存全部已分配 State 数组可 snapshot=model.state(); snapshot.assign(state_0),前提是两者布局/扩展属性匹配。State.assign 会检查缺失数组,不拷贝 solver 或任意 Python 的控制器变量。assign
CUDA graph 还捕获具体设备数组的使用关系;奇数子步的 Python 引用交换不能直接推广成 graph replay 的正确循环。该版本 State.assign 示例专门处理最后一步的复制。最小例子使用普通循环、不做 capture,graph 专题在 E5。
8. 重置和快照:选择你要恢复的层次#
需求 |
要保存/恢复什么 |
能作出的承诺 |
|---|---|---|
只回放几何 |
body/particle pose 与时间标签 |
能显示历史形状,不能从中恢复完整动力学 |
恢复公开 State |
相同布局的全部 State 数组,必要时 FK/IK 同步 |
公开物理状态恢复;不自动含控制器/RNG/后端历史 |
回到模型初始条件 |
新 |
是重新初始化;不等于任意时刻快照继续 |
完全相同的续算 |
上述状态 + 后端缓存/激活/历史 + 控制器/RNG/步数/调度/运行配置 |
必须依 Solver 的序列化契约与未来验证证明;本章未作此承诺 |
SolverBase.reset(state, ...) 默认只做 mask 规范处理、没有通用物理复位实现。SolverMuJoCo override 会把所选 joint state 设回 Model 默认并清理 warm-start、act、ctrl、外力等后端数组;因此“先恢复任意中途快照,再无条件调用 reset”可能把你恢复的关节状态覆盖掉。不要跨 Solver 发明统一 reset 语义。base reset、MuJoCo reset
body_q_prev 已弃用,源码要求应用显式 clone 所需历史。Solver 内部自行管理前一姿态,公开 State 不能因此被当成所有内部历史的容器。弃用说明
本章的 最小例子 选择简单可审查的语义:构造一个偏心 primitive 自由体,保存 t=0 的 State,展示一帧普通双缓冲循环,随后恢复两个 buffer、重建 Control/Contacts 和 XPBD Solver 并归零时钟。它展示冷启动式复位,不展示中途快照的逐位一致续算;文件仅做语法检查,所有原生调用均未执行。
9. 原生例子与故障定位#
例子只有一个自由体与地面,没有外部资产、窗口、训练或评分器。主形状半边长、密度与第 3 节手算一致,局部 shape 偏移让 body_com 与 body 原点不同。预期 q/qd 尺寸 7/6 来自 FREE joint 构造规则,不是一次运行输出。
表面症状 |
首先读哪些量 |
典型错误与修改方向 |
|---|---|---|
模型尺寸差 1000 倍 |
文件单位、scale、shape 半边长 |
把 mm 当 m;避免同时修改文件和 importer scale 两次换算 |
静止模型 COM 不在几何中心 |
|
COM 本来就相对 body 原点;先检查质量分布,不强行归零 |
新加碰撞壳后质量增加 |
density、 |
手工质量与 shape 质量被叠加 |
设置 q 后渲染没变化 |
权威 q/body 字段、FK 调用及读取的 buffer |
改了 generalized q,但 maximal pose 未同步;或读取旧 buffer |
q 和 qd 切片长度不同 |
joint type、两套 start 表 |
quaternion 冗余坐标;用同一下标切两套数组 |
“保存的上一帧”跟着变化 |
Python 引用、设备数组、clone |
别名不是快照 |
kinematic body 有速度却不移动 |
body flag、用户轨迹更新位置 |
用户指定运动分支只传递状态,需自己更新位姿和一致速度 |
换 solver 后 reset 无效 |
solver reset 实现、权威状态和缓存 |
base reset 不是通用复位;不要只清 body pose |
只加 iterations 后模拟变快 |
调用者时钟与 dt 累加位置 |
迭代次数被错误算作物理子步 |
力矩方向相反 |
r 的方向、参考点、frame、linear/angular 顺序 |
区分换参考点与换坐标的 transform |
10. 从积分源码理解 B4 的起点#
先限定 无约束刚体预测阶段。公共 integrate_rigid_body 把速度视为 world COM 线速度与 world 角速度;对质量非零的动态体,先更新速度再更新 COM:
这是半隐式 Euler 的速度后位置顺序。转动在 body 系计算陀螺项:
随后用世界角速度左乘 quaternion 增量并归一化:
源码在计算新 quaternion 之后 对输出角速度乘 1-angular_damping*h;所以上式中的 \(\widetilde\omega\) 是阻尼前中间量。示例显式设 angular_damping=0,避免把该差别隐藏在默认值中。逐行实现
XPBD 会在这个预测后进行约束修正,并进一步更新速度;不能因其预测器是半隐式 Euler 就把整个 XPBD 算法等同于无约束 Euler,也不能把 XPBD 类说明中的 implicit 当作通用 Backward Euler/Newton 法实现证据。完整约束和恢复系数路径在 E3 展开。预测调用、类与支持限制
单位检查有助于发现错误:\(hf/m\) 为 m/s,\(hI^{-1}\tau\) 为 rad/s。时间步减小、迭代增多和浮点精度提高处理不同误差;没有“只增迭代就必然稳定准确”的结论。离散误差、约束残差、碰撞采样误差、接触模型差距需在 E3 分开讨论。本阶段没有进行时间步或求解器对照实验。
11. 阅读练习与参考答案#
一个 FREE 根和两个 REVOLUTE 关节,不计 padding,q/qd 各多少元素?为何不可逐项相加积分?
第 3 节的 box 全部长度乘 2,若仍按密度生成惯量,质量和 \(I_{xx}\) 变多少?若走显式 URDF inertial 路径呢?
\(c^B=(0.1,0,0)\)、姿态单位、\(v_C=0\)、\(\omega=(0,0,2)\),body 原点速度是什么?
saved=state_0后做双缓冲交换两次,为何 saved 不一定是历史?如何保存 State 的数组?为什么 XPBD 步后对
state.joint_q的直接读取可能是旧值?eval_ik在这里做什么?若一帧 0.02 s、5 个子步、每步 8 次迭代,一帧推进多久?外力在何时写?
有一个 USD stage 声明厘米单位,本版本为什么不能仅依据 importer 返回成功就验收尺寸?
想恢复 MuJoCo 后端中途快照,为什么不能无条件追加
solver.reset(state)?
参考答案与源码定位
q 为 \(7+1+1=9\),qd 为 \(6+1+1=8\);FREE quaternion 用 4 个数表示旋转,角速度只有 3 维,需相应姿态积分映射。看第 5 节。
固定密度:质量 \(8\) kg,惯量乘 \(32\),\(I_{xx}\approx0.0333333\) kg·m²;显式 inertial 路径的质量仍 1 kg,惯量乘 \(4\),\(I_{xx}\approx0.00416667\) kg·m²。两者对应不同缩放假设,不是导入器同一结果。
\(v_B=v_C-\omega\times c^B=(0,-0.2,0)\) m/s。质心线速度为零不代表 body 原点静止。
saved 是同一个 State 对象;旧 buffer 会再成为输出并被覆盖。先分配同布局 State,再
snapshot.assign(state_0);这仍不含 solver/private/controller 状态。XPBD 推进 maximal body 数据,不自动保证 generalized 数组刷新;
eval_ik从 body pose/twist 重建 joint q/qd,不求给定末端目标的控制动作。每步 \(h=0.004\) s,5 步合计 0.02 s;8 次迭代不增加物理时间。外力在每个子步 clear_forces 之后、step 之前写入。
legacy 刚体路径会警告非单位 stage metadata,粒子路径与刚体路径不同;必须检查已转换的资产数据、metadata、最终 shape/质量字段及警告,不能把成功返回当作正确 SI 单位的证据。
override 会把所选 joint state 置回 Model 初值并清 warm-start/act/ctrl 等后端数据;这会破坏任意中途状态的继续语义。先确定是初始化复位还是精确续算,并按具体后端的完整契约实现。
12. 本章验收与下一步#
验证记录列出源码身份、链接锚点、原创 Python 文件和 Markdown 片段的语法检查。静态审查涵盖 A1/A2 的建模/资产、状态/时间契约,B0/B4 只交付本章声明的基础子集;未把任何物理或性能性质标成运行验收。
接下来 E2 从这些状态与布局进入 Control、原生驱动、机器人 FK/目标 IK 和任务时序;E3 延续空间量及积分基础,展开接触/约束/求解器/力观测。实验案例最终复用 DexLab,总入口见 Sim Atlas。