Files
dex_workbench/L20_TRACKING.md
T
chenlin 8e7ab5fc76 feat(tracking): v0.1.2 双手轨迹回放与 GUI 预览
支持 L20 右手模型身份与严格浮动控制覆盖层,新增完整轨迹受限回放、时间拉伸及可选 GUI 显示。

验证:88 项 CPU/USD 回归、Ruff、格式与独立暂存审查通过。历史 80 倍降速回放完成 2x32000 步;整合后 GUI E2E 和完整 pre-commit 未执行,相关边界见 L20_TRACKING.md。

右手 USD、示教数据、媒体和日志未纳入提交;资产存储及许可仍待确认。保留原控制与安全阈值。
2026-09-14 13:57:57 +08:00

449 lines
35 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# L20 左手轨迹跟踪:数据交付与准备入口
本页保留左手验证历史。新增右手入口、实际转换/回放证据与发布限制见
[`右手资产说明`](assets/robots/dex_hand/linkerhand_g20_right/README.md);左右共用校验器与控制入口,显式绑定hand_side。
HDF5右手差异见独立契约第10节(右thumb联动1.03,不能套用左1.02)。
本轮准备门禁新增 `NewtonArticulationRootAPI` 注册上下文;**旧prepared覆盖层需重新生成**。
左手源资产未改,本轮额外左small两轮480步回归PASS,指标与历史baseline一致。
## 本次可用范围与验证状态
提供 **CPU 数据接口、资产清单、浮动控制覆盖层和实验性动力学跟踪入口**,不是完成的 RL 环境。
覆盖层和控制数学有 CPU/USD 静态验证;**注册 schema 覆盖层的单环境合成轨迹动力学 smoke 已 PASS**。
此前启动顺序、异常退出码和 schema 默认值保留问题已修复;后续授权重测完成两轮各480步。
后续还完成4秒/10mm/0.1rad的合成 HDF5 文件加载与两轮各960步验收,并消除了旧世界 anchor 的
CreateJoint 警告(见第4节)。通过范围仅限指定资产、后端、参数及两种合成参考,不代表真实专家轨迹、
任意运动或 RL 环境验收。
保留 `Template-Dex-Workbench-v0` / Cartpole 及其 checkpoint。没有新训练任务、物体、奖励、策略或训练结果。
实际组合资产检查发现:
- 当前入口 `assets/robots/dex_hand/linkerhand_g20_left/linkerhand_g20_left/linkerhand_g20_left.usda`
是**世界固定基座**,尽管转换缓存写 `fix_base: false`
- 22 个刚体、21 个 revolute 关节,另有一个世界 fixed joint;根 link 为 `hand_base_link`
**21 是导入状态关节数,不是独立执行器数**。实际名称、排序、限位、驱动属性、质量惯量见
[`tracking_manifest.json`](assets/robots/dex_hand/linkerhand_g20_left/tracking_manifest.json)。
- 原始 URDF(清单记录其 SHA-256,未修改)含 5 个 mimic
`thumb_ip = 1.02 * thumb_mcp``index/middle/ring/pinky` 各自 `dip = 0.89 * pip`offset 均为 0 rad。
- **纠正前轮结论**:安装的 Isaac Sim 6.0.1 / PhysX 110.1.13 原生解析 `NewtonMimicAPI`
`PhysxMimicJointAPI` 已弃用。原资产的五个 Newton 方程正确,不能因缺少 Physx 前缀就认定缺约束。
依据包括安装 schema、PhysX migration checker/tests,以及 PhysX 插件中的 `parseNewtonMimicJoints`
对应解析诊断。它们是支持性证据,**不是本资产的动力学执行证明**。
清单改为 `MIMIC_SCHEMA_PRESENT_RUNTIME_UNVERIFIED`,仍 `dynamic_replay_ready=false`
- 原资产五个从动关节同时有独立 angular drive。新 `prepared.py` 覆盖层保留原生 Newton 约束,
去掉这五个 DriveAPI 并将其 stiffness/damping/maxForce 置零;仅 16 个模型独立关节接收目标。
不新增第二套约束、不修改原始 USD/URDF,不改变关节限位、质量、惯量、碰撞或变换。
16 是根据该模型推导的实验控制映射,**不是已确认的硬件电机数**。
- `require_dynamic_replay_ready()` 仍拒绝仅凭数据 JSON 启动控制。实验入口 `track_l20.py` 另行检查实际
覆盖层、源包哈希、逐项结构与约束、已启用后端版本、运行时从动增益和被动联动响应;不是改状态位绕过。
`--floating-overlay` 仍仅是拓扑诊断,不应直接 Play。新 `prepared` 覆盖层也不是自带悬浮能力的资产:
必须配合实验控制器才有受限重力补偿;本次有合成参考的仿真跟踪指标,但不宣称可训练或 Sim2Real 有效。
## 1. 给数据同事的 HDF5 契约:`l20_tracking_v1`
可直接分享的独立说明见 [`HDF5_REQUIREMENTS.md`](HDF5_REQUIREMENTS.md),发送时请同时附同版模型清单。
这是本仓库的跟踪专用接口,不宣称已实现全项目 DexSchema。交付**重定向后的机器人参考状态**,
不是原始人手关键点,不是实测执行器命令。先交一条短样例,不要求物体、图片、力矩或速度。
```text
demonstrations.hdf5
├── attrs
│ ├── schema_version = "l20_tracking_v1"
│ ├── embodiment = "L20"
│ ├── hand_side = "left"
│ ├── asset_sha256 = "<双方约定的清单 asset_sha256>"
│ ├── root_link = "hand_base_link"
│ ├── provenance = "expert_retargeted" 或 "synthetic"
│ ├── source_description = "采集/重定向版本、世界原点/朝向、校准来源、质量说明"
│ ├── metric_scale_provenance = "米制尺度如何获得,是否估算及可信程度"
│ └── scale_to_meters = 1.0 # 浮点标量,已应用的源尺度系数,不一定是1
├── metadata
│ ├── joint_names UTF-8 [J]
│ └── world_from_source float64 [4,4]
└── episodes
└── demo_000000 # demo_ + 六位数字;可有多条
├── time float64 [T]
├── wrist_position float32 [T,3]
├── wrist_quaternion float32 [T,4]
├── joint_position float32 [T,J]
└── valid bool [T]
```
### 坐标、单位和身份
- 所有字符串非空 UTF-8。`joint_names` 必须是 HDF5 UTF-8 string dtype,不能使用 ASCII byte arrays。
- `J` 来自约定的机器人清单,不从 L20 名称推断。`joint_names` 必须**逐项等于清单 `joints[].name` 的排序**。
此排序为名字字典序,不是 Isaac 的 DOF 顺序;后续 Adapter 必须再显式按名称映射。
- 根部位置对应 `hand_base_link` **link 原点**(不是质量中心、人手腕点或模型 default prim 原点)。
人手腕点到机器人根 link 的变换由重定向端应用;不能交付后再隐式猜测。
- 位置单位 **m**,关节角 **rad**,时间 **s**;世界系右手、Z 向上。
世界原点、X/Y 朝向及源相机/重建坐标约定必须在 `source_description` 中注明并与仿真场景对齐。
一个文件共享一个源世界校准;相机/校准改变时另建文件,世界系不随腕部移动。
- 四元数排列 **wxyz**,表示 root-link 局部向量到世界向量的主动旋转。
有效帧必须单位化(范数容差 `1e-4`);相邻有效帧四元数点积必须非负,避免符号翻转。
- `world_from_source` 表示已经应用的刚体变换:
`p_world = R * (scale_to_meters * p_source) + t`。该矩阵不包含尺度;平移单位为 m。
导出数据已在世界系,读取器**不会再次应用矩阵或尺度**。姿态同样已转换。
`scale_to_meters` 必须为有限正浮点数;不能把估算尺度写成实测。
- `asset_sha256` 是**完整本地 USD 依赖包**的内容身份,不是仅入口文件 SHA。
清单按相对入口目录的 POSIX 文件名排序,对每个 `relative_path + NUL + file_sha256 + LF` 的 UTF-8
记录累积 SHA-256。包含 USD 层和解析到的资源,重定位整个包身份不变;任何依赖内容/名称变化会改变身份。
清单本身不属于 USD 依赖;独立记录源 URDF SHA。不要把固定版与浮动 overlay 的包哈希混用。
### 时间、缺失和状态语义
- 每条至少 2 帧,`time[0] == 0`,严格递增;所有字段使用同一时间轴、同一 T。
允许非均匀采样,保留真实时间戳。不同步数据必须先由交付方明确对齐。
- `joint_position` 包含所有列出的参考关节状态,包括 mimic 从动关节;不据此认定全部可独立驱动。
带清单校验会检查有效帧限位(容差 `1e-6` rad)以及已记录的 URDF mimic 等式(容差 `1e-3` rad)。
不静默换序、裁剪角度、补关节或归零修复。新数据误差超容差时应确认重定向质量,而非放宽验收。
- 缺失/低可信帧必须 `valid=false`。本版本所有数值 payload 均要求有限(包括无效帧);无效帧可用有限占位,
但绝不能标成有效数据。无效四元数不要求单位化。至少一帧有效;完全缺失字段不能省略或静默补真值。
- 读取器拒绝 NaN/Inf、重复名字、错误 shape/dtype、非单调时间、不合法刚体矩阵、未知版本/来源类别等。
元数据文字存在不证明标定正确,仍需人工核对来源。
- API `sample()` 对腕位置/关节角线性插值,对姿态 shortest-arc SLERP;不外推。
输出四元数重新保持相邻符号连续;这不能恢复降采样丢失的旋转圈数或高频运动,频率需按轨迹带宽选择。
**任何查询范围跨过/触及无效帧均拒绝**,包括仅查询无效间隙两侧的稀疏点。必须显式分割有效片段。
CLI 重采样仅接受全有效 episode,不自动分段;输出从 0 开始的等间隔网格,离网格的尾帧省略。
- 速度/加速度非必填。本次不估算并保存速度,不把未来派生值冒充硬件测量。
## 2. 本地命令
在仓库根目录运行。独立 namespace 包 `dex_workbench_tracking` **不导入** `dex_workbench` 的任务注册,
CPU 验证不要求 Kit/GPU。普通 Python 需要 numpy/h5py;本机系统 Python 缺 h5py,以下用已有 Isaac 启动器。
安装环境可选 `pip install -e 'source/dex_workbench[tracking]'`,本次没有安装/升级任何依赖。
也可不安装,使用:
```bash
export PYTHONPATH="$PWD/source/dex_workbench${PYTHONPATH:+:$PYTHONPATH}"
ASSET=assets/robots/dex_hand/linkerhand_g20_left/linkerhand_g20_left/linkerhand_g20_left.usda
MANIFEST=assets/robots/dex_hand/linkerhand_g20_left/tracking_manifest.json
# 复查真实组合资产;输出必须是尚不存在的路径
~/isaacsim/python.sh -m dex_workbench_tracking.asset "$ASSET" --output /tmp/l20-inspected.json
# 如有原始 URDF,用显式本地路径对照(不是运行时必需依赖)
# ... --source-urdf "$SOURCE_URDF" --output /tmp/l20-with-urdf.json
# 生成明确标为 synthetic 的 2 秒参考样例,121 帧;不是专家数据或动态控制验收
~/isaacsim/python.sh -m dex_workbench_tracking.cli synthetic \
--manifest "$MANIFEST" --output /tmp/l20-synthetic.hdf5
~/isaacsim/python.sh -m dex_workbench_tracking.cli validate \
/tmp/l20-synthetic.hdf5 --manifest "$MANIFEST"
~/isaacsim/python.sh -m dex_workbench_tracking.cli resample \
/tmp/l20-synthetic.hdf5 --manifest "$MANIFEST" --hz 240 --output /tmp/l20-resampled.hdf5
# 动态准备门禁:预期非零退出且 BLOCKED;直接 Python 返回2,本机 python.sh 将非零映射为1
~/isaacsim/python.sh -m dex_workbench_tracking.cli replay-check --manifest "$MANIFEST"
# 不提供 manifest 仅作结构检查,输出 asset_compatibility=NOT_CHECKED
~/isaacsim/python.sh -m dex_workbench_tracking.cli validate /path/to/demonstrations.hdf5
# 生成诊断层:保留原入口、fixed_base_setup.usda 和其他依赖原始字节
~/isaacsim/python.sh -m dex_workbench_tracking.asset "$ASSET" \
--floating-overlay /tmp/l20-floating.usda --output /tmp/l20-floating-manifest.json
# 仅在没有冲突的 GPU/Kit 作业时运行;本次因已有 GUI 实例而未执行
# 此入口只验证 Isaac Lab 引用后 root/关节/初始有限变换,不运行物理、reset 或 replay
# --help 的 AppLauncher 参数以本地 Isaac Lab 为准;默认 headless,单场景,seed=42
timeout 300s ~/isaacsim/python.sh scripts/tracking/inspect_l20_scene.py /tmp/l20-floating.usda --headless
# CPU 单测;第二组还需要 pxr(已有 Isaac Python 提供)
~/isaacsim/python.sh -m unittest discover -s source/dex_workbench/tests -p 'test_tracking_trajectory.py' -v
~/isaacsim/python.sh -m unittest discover -s source/dex_workbench/tests -p 'test_tracking_asset.py' -v
```
所有生成入口拒绝覆盖已有文件。HDF5 CLI 先在目标目录的临时文件中写入并校验,成功后以硬链接发布;
文件系统须支持硬链接,否则明确失败,不回退为覆盖写入。校验失败不留下目标文件。
示例输出位置是临时产物,不应加入 Git;分享给同事时标清 synthetic。
清单 snapshot 绑定当前依赖字节,资产变化后必须重新生成、审查并与数据方更新版本,不直接沿用旧哈希。
普通 `validate` 的 PASS 只证明契约;即使带清单 PASS,`dynamic_replay` 仍为 BLOCKED。
## 3. 实验性 PhysX 浮动跟踪(单环境合成轨迹 smoke PASS)
```bash
# 调用方显式选择本机插件;这些路径不是可移植资产依赖,其他安装应替换。
# 多版本安装须人工选定一个 PhysX 插件,不能把多条路径合并为一个参数。
PHYSX_PLUGIN=$(find "$HOME/isaacsim/extscache" -path '*/plugins/PhysxSchema/resources/plugInfo.json' -print)
NEWTON_PLUGIN="$HOME/isaacsim/exts/omni.usd.schema.newton/usd/schema/newton/newton_usd_schemas/plugInfo.json"
# 必须用原始数据/source manifest;覆盖层身份另外记录,不能静默改 HDF5 asset_sha256
# 必须用新输出路径;旧覆盖层需重新生成,不覆盖已有文件。
~/isaacsim/python.sh -m dex_workbench_tracking.prepared "$ASSET" \
--manifest "$MANIFEST" --output /tmp/l20-tracking-registered.usda \
--schema-plugin-path "$PHYSX_PLUGIN" --schema-plugin-path "$NEWTON_PLUGIN"
# 对已生成的实际 USD 重新检查;使用同样的插件上下文,不是读取 ready 状态位
~/isaacsim/python.sh -m dex_workbench_tracking.prepared /tmp/l20-tracking-registered.usda \
--manifest "$MANIFEST" --schema-plugin-path "$PHYSX_PLUGIN" --schema-plugin-path "$NEWTON_PLUGIN"
# 先协调关闭/释放用户 GUI 会话;注册 schema 覆盖层已通过一次限定的合成轨迹验收。
timeout 300s ~/isaacsim/python.sh scripts/tracking/track_l20.py /tmp/l20-tracking-registered.usda \
--manifest "$MANIFEST" --execute-experimental --headless --steps 480
# 默认使用明确标注的 synthetic 轨迹;已有合格 HDF5 时可加:
# --hdf5 /path/to/demonstrations.hdf5 --episode demo_000000
~/isaacsim/python.sh -m unittest discover -s source/dex_workbench/tests -p 'test_tracking_*.py' -v
```
### 修复过程记录(历史失败保留)
- 旧覆盖层启动命令(单手、seed42、`--steps 480`、两次回放目标、外部 `timeout 300s`)实际执行失败,
没有进入 scene/reset/physics loop,没有跟踪误差指标或 PASS JSON。
- 初次启动:`pxr` 在 App 前导入,Kit 报 USD registry/free 崩溃,启动器退出1。
两个诊断入口均已改为先启动 App,再在 `try/finally` 内进行 USD 检查;资产门禁仍早于 scene/控制。
- 第一次重试:App 启动成功但退出0且**没有 PASS**。确认 `SimulationApp.close()` 的 fast shutdown
会掩盖进行中的异常;该次是失败,不是通过。已添加异常 traceback 和 `close(exit_code=1)`
- 第二次重试:退出1,明确报告旧 anchor 的 `physxArticulation:sleepThreshold` 默认值不一致。
注册 PhysX 的纯 CPU 复现表明:移除 API 后旧 anchor 的三个未显式写入的默认值消失;
root 默认值与原值一致,但严格保留检查正确拒绝旧 anchor 差异。没有通过放宽检查来修复。
- 修复:移除 API 前快照全部已解析 articulation 属性(含 schema fallback),在旧 anchor 和新 root
显式保留原值;记录 authoring schema context。跨上下文检查拒绝并要求重新生成。
不带插件选项的纯静态输出标为 `STATIC_ONLY_SCHEMA_UNREGISTERED`,不能推荐用于运行时。
- **CPU 回归 60 项通过**(原57项加启动/异常退出与隔离注册 schema 测试),无跳过;
新注册覆盖层生成和复查通过,source bundle SHA 不变。该修复交付内未做第三次 GPU 重试,增益和断言未放宽。
- 本机诊断日志:`/tmp/l20-runtime-PpD1Ah/{smoke,retry1,retry2,schema-default-repro,tests}.log`
新覆盖层 `/tmp/l20-runtime-PpD1Ah/registered-tracking.usda` 当时仅静态验证。它们是临时制品,不提交。
修复交付后另获用户授权的 GPU 验收结果如下。
### 修正覆盖层的授权重测:PASS
实际命令(仓库根目录,未更改增益或断言):
```bash
PYTHONPATH=source/dex_workbench timeout 300s ~/isaacsim/python.sh \
scripts/tracking/track_l20.py /tmp/l20-runtime-PpD1Ah/registered-tracking.usda \
--manifest assets/robots/dex_hand/linkerhand_g20_left/tracking_manifest.json \
--execute-experimental --headless --steps 480
```
- Isaac Sim 6.0.1 / PhysX 110.1.13、RTX5080seed42、num_envs1、240Hz、synthetic、两轮各480步。
- 退出0且有完整 PASS JSON;两次 reset、位姿/关节/速度重复性、非零运动、有限值、限位与联动断言通过。
- 两轮输出相同的汇总指标(这不承诺跨运行 GPU 确定性):
| 误差 | 最大值 | RMS |
| --- | ---: | ---: |
| 腕部位置 | 0.000492342 m | 0.000299964 m |
| 腕部姿态 | 0.003755143 rad | 0.002314660 rad |
| 各帧最大关节误差 | 0.008628675 rad | 0.005612279 rad |
| 各帧最大 mimic 残差 | 0.000221643 rad | 0.000059707 rad |
- 源包 SHA `6c8f35358f481cf604ee802588017f30c1661c0f38e1187c49e5340db3830538`
覆盖层 SHA `ca874b29e4ee4f7c211d17c3e190487b0d6cc103dbe57035371d49fa64e98269`
- 日志 `/tmp/l20-registered-retest-N90YMI/smoke.log`SHA256
`b763f3abe35c780304a5a4bb587cdc639f63ab4fc4469e6ccde8551b10ff436d`;退出记录同目录 `result.txt`
测试后未发现 Kit 进程,GPU占用739MiB(测试前708MiB);这不证明所有资源位级恢复。
- 仍有警告:旧 fixed joint 的 body transforms 不重合、TGS external-force iteration 配置、
16/21 actuator 数量、protobuf 重复注册和 visualizer 配置缺失。16/21对应有意保留的5个被动关节;
其余警告未靠关闭检查消除,尤其 fixed joint 警告需在扩大运动范围前进一步核验。
- 仅为2mm平移、0.01rad转动、小幅手指合成参考的 smoke;未测试真实 HDF5、大范围运动、接触、
多环境、训练或硬件。静态清单仍保留 runtime-unverified;本次证据不自动授权任意后续运行。
### 模型/版本门禁
- 验证 source manifest 的完整依赖包、关节列表、限位、质量记录与当前源 USD 一致;源 URDF 哈希和
五个方程必须为本轮已核验版本。重新检查五个实际 Newton leader 路径、系数、启用状态和单自由度轴;
拒绝重复 legacy mimic、未知约束、独立从动电机以及覆盖层额外物理编辑。
本诊断仅接受静态资产:所有属性(含允许修改默认值的字段)均不得带时间采样。
- `NewtonMimicAPI`: `q_follower = coef0 + coef1*q_leader`。revolute 的 coef0 用**度**,换为接口 rad
coef1 无量纲。单 DOF 的轴由各自 RevoluteJoint 定义,不新增 rotX/rotY token。
旧 Physx 约定为 `q_follower + gearing*q_leader + offset = 0`,不能把正 multiplier 直接当 gearing。
- 静态检查默认允许尚未注册的 codeless schema 元数据;运行时必须真正注册 NewtonMimicAPI、启用
`omni.physx`,版本严格为 **110.1.13**。其他版本须重新核验,不静默降级/重复约束。
- 当前 Isaac Lab 使用 `ProxyArray.torch`、root pose **xyzw**、index 写入方法;HDF5 始终 **wxyz**
在运行入口显式转换。旧版 Lab 未验证,不承诺兼容。
- 本地依据(相对于 Isaac Sim 安装目录;未复制供应商实现):
`extscache/omni.usd.schema.physx-*/plugins/PhysxSchema/resources/schema.usda` 的 PhysxMimicJointAPI
`exts/omni.usd.schema.newton/usd/schema/newton/newton_usd_schemas/generatedSchema.usda` 的 NewtonMimicAPI
`extscache/omni.physx.asset_validator-*/omni/physxassetvalidator/scripts/newtonMigrationChecker.py`
`tests/newtonMigrationCheckerTest.py``extscache/omni.physx-*/bin/libomni.physx.plugin.so` 的 native parser 标识。
本轮读取了上述代码/二进制字符串,**未执行供应商 GPU 集成测试**。
### 控制与验收边界
- 单环境、seed42、240Hz;默认两次各480步,普通模式单次允许100–1200步,外部 timeout 300秒。
显式完整文件模式的有限步数/预算例外见第5节;不会自动扩大默认范围。
只创建手,无物体、桌面、任务注册或训练。不逐步 teleport;仅 reset 写 root/joint 初值并清零速度、
wrench 与目标缓冲、轨迹时间,之后只发 master q_target 和 root COM wrench。
- 世界系 PD 跟踪 link 原点;输出作用在 root COM,补上 `(p_link-p_rootCOM)×F_PD`
全手重力补偿为 `sum(-m*g)``sum((p_bodyCOM-p_rootCOM)×(-m*g))`,重力维持 `(0,0,-9.81)`
不是对整个手逐刚体取消重力;根部吸收补偿,手指仍承受物理重力/反作用。
- **所有参数待校准**:位置 P/D=100 N/m、10 N·s/m,姿态 P/D=0.2 N·m/rad、0.02 N·m·s/rad
总力/力矩范数上限20N/1N·m(含重力项),需留至少20%静态重力余量。
16 个 master 的 implicit drive P/D=3/0.1,仿真 effort cap=0.2N·m、velocity cap=0.5rad/s
不改变 follower 限位或增加 armature。不是实测安全参数。
- 可用 `--limits` 指定 `control.Limits` 字段 JSON(有限正值,SI),默认参考速度限制
0.05m/s、0.5rad/s、各关节0.5rad/s;位置不超过起点0.1m。超限/无效片段直接拒绝,不裁剪成成功。
- 每帧检查有限值、速度、限位(0.01rad容差)、五条 mimic 残差<0.002rad,腕误差<0.05m/0.5rad、
关节误差<0.2rad。这些是预设诊断失败阈值,不是高质量跟踪指标。输出各项 max/RMS 原始指标。
每条 mimic 的 leader/follower 都必须有>0.002rad真实运动,根部需>0.5mm平移和>0.002rad转动,
避免静止关节让缺约束假通过。输入需激励全部 mimic leader,纯静止/局部手指数据不适合此诊断。
- 两次 reset 初值误差<=1e-6;重放的根部位姿/关节位置逐项差<=1e-3,
根部线速度/角速度及关节速度逐项差<=1e-3m/s 或 rad/s);不承诺 GPU 位级确定性。
任一失败非零退出,`finally` 关闭本次 App,不修改其他进程或原资产。
- **仍需扩展验证**:本次小幅合成参考的被动联动响应、跟踪与重复性已通过;真实轨迹、更大运动、
接触/自碰撞及跨运行稳定性尚未验证。任何失败需保留日志并诊断,不能放宽阈值充作通过。
后续再做少量并行环境、真实 HDF5、BC/PPO;硬件可控映射仍需外部确认。
本轮仅有上述合成参考的动力学误差实测,没有训练质量声明。没有提交/推送、版本升级或硬件动作。
## 4. 扩范围 HDF5 诊断(本轮预先固定的测试条件)
- 新覆盖层仅将原有、已禁用的**叶节点世界 fixed joint**设为 inactive,阻止它继续进入活动关节解析;
根部仍为 `hand_base_link`。旧 anchor 的属性、关系和 schema 默认值保留,`TraverseAll` 仍逐项检查;
其他节点的活动状态、树结构与时间采样门禁不得改变。原始 USD 未修改,旧覆盖层需重新生成。
`asset --floating-overlay` 仍仅禁用 anchor,用于拓扑诊断,不是本轮推荐的 prepared 控制资产。
- 原警告与 world/local joint frames 不重合有关:原 world frame 为原点,spawn 后手根在 z=0.4m
`jointEnabled=false` 不阻止解析阶段报告该警告。去激活不是改变局部变换以掩盖警告。
- 新命名合成 profile `range_4s`60Hz241帧,4秒,`s(t)=sin²(pi*t/4)` 往返;
X向位移 `0.01*s` 米、Z保持0.4米、世界Z轴转角 `0.1*s` rad。
独立关节正向幅度 `min(0.1rad, 0.25*upper_limit)`,从动关节按源 mimic 计算。
解析曲线端点速度为0;采样后的线性/SLERP插值不保证连续加速度。明确为 synthetic,非专家。
- 默认 `small` profile 保持原来的2秒/2mm/0.01rad和关节幅度,未改变默认参考或控制器。
- 测试前固定:第1次新覆盖层 small,2x480步;第2次从磁盘载入 `range_4s` HDF52x960步。
每次单环境、seed42、240Hz、timeout300秒;不调增益/阈值,不将失败后减小幅度算通过。
- 新入口在 spawn 后要求旧 anchor inactive、仅21个活动 revolute joints;运行时仍断言非固定基座、
22刚体、21状态关节、16独立控制目标与5个被动从动响应。PASS另记录HDF5 SHA/来源和活动关节数。
```bash
# 使用第3节显式插件选项重新生成新的覆盖层,例如 /tmp/l20-range/tracking.usda
~/isaacsim/python.sh -m dex_workbench_tracking.cli synthetic --manifest "$MANIFEST" \
--profile range_4s --output /tmp/l20-range/range.hdf5
~/isaacsim/python.sh -m dex_workbench_tracking.cli validate /tmp/l20-range/range.hdf5 --manifest "$MANIFEST"
timeout 300s ~/isaacsim/python.sh scripts/tracking/track_l20.py /tmp/l20-range/tracking.usda \
--manifest "$MANIFEST" --execute-experimental --headless --steps 960 \
--hdf5 /tmp/l20-range/range.hdf5 --episode demo_000000
```
### 本轮结果:两个限定 GPU 用例均 PASS
- 第1次命令:上述 `track_l20.py /tmp/l20-range/tracking.usda`,不传 `--hdf5`
`--steps 480`,其余参数相同。第2次完整执行上方 `--steps 960 --hdf5 ...` 命令。
两次均退出0、有明确 PASS JSON、两轮期望步数及有限指标;没有第三次运行,没有调参或放宽断言。
- 两次均输出 `world_anchor_inactive=true``active_state_joint_count=21`
`runtime_is_fixed_base=false`;两轮 reset/状态/速度重复性、非零运动与 mimic 断言通过。
两份日志均不再出现 `CreateJoint` / `disjointed body transforms`。小幅用例 max/RMS 汇总与
第3节历史基线逐值相同,支持此叶节点去激活在本用例的动力学等效性,不承诺任意场景等效。
- HDF5 用例确实从磁盘读取 `range_4s`,输出 `reference_source=hdf5``provenance=synthetic`
60Hz的241帧按原时间戳插值至240Hz、961个参考点,执行960步/轮。
- **68项 CPU/USD 回归通过,无跳过**,包括活动树/anchor/time samples、注册上下文、
实际L20清单下新profile的schema/限位/mimic/速度/来源与拒绝覆盖。
| 最大误差(两轮各自相同汇总) | 小幅基线 | range_4s HDF5 |
| --- | ---: | ---: |
| 腕部位置 | 0.000492342 m | 0.001044980 m |
| 腕部姿态 | 0.003755143 rad | 0.009153232 rad |
| 各帧最大关节误差 | 0.008628675 rad | 0.010852285 rad |
| 各帧最大 mimic 残差 | 0.000221643 rad | 0.000195338 rad |
HDF5用例 RMS 依次为 `0.000646705 m``0.006378398 rad``0.007675343 rad``0.000050099 rad`
所有控制/参考上限与基线一致;这只是受限诊断误差,不是训练成功率或真机指标。
制品(临时,不提交):
- `/tmp/l20-range/{small,hdf5}.log``{small,hdf5}-metrics.json`、对应 `*-result.txt`
`acceptance-evidence.log`、CPU `tests-final.log`、各次 `preflight*.log` / `postflight*.log`
- 新覆盖层完整包 SHA `6179feb7a112c74b73bc003be6b0159757ed6ab3a9e2cb7015333e09225dc319`
原始源包身份仍为第3节的 `6c8f...0538`
- `/tmp/l20-range/range.hdf5` SHA256
`9678a19a7bb983ceaf6ad715016fe784b001544de0dec1876831d986eb870072`,不是专家文件。
- small日志 SHA256 `6e395fedf0796440ffc2f2fefac5661d97cb63ce6d015ebad0f8399e8e20f0f4`
HDF5日志 SHA256 `10d255845d828e664d76f7d0119e5c2b5530cf696a1333afd41f39b95dd7c5f3`
两次测试前后均未发现Kit残留;显存分别736→723MiB、734→775MiB,不承诺所有资源位级恢复。
仍有TGS外力迭代、16/21 actuator5个被动关节)、protobuf重复注册、visualizer/MaterialX与usdrt警告;
未关闭日志或放宽检查。更大范围、负向/多轴腕部运动、接触、真实专家文件、多环境、训练与硬件均未验证。
完整 pre-commit 仍因未安装工具而 NOT_RUN;本次独立审查仍由父会话执行。
## 5. 显式扩范围与完整专家参考回放
默认工作半径仍为起点周围 **0.1m**,普通模式步数上限仍为 **1200**(默认480)。
`--workspace-radius 0.8` 仅覆盖工作半径,不改变增益、力/力矩、参考速度、实测安全界限或误差阈值。
`--full-episode` 必须同时提供 HDF5,允许每轮最多 **32000** 步,并要求所选 episode 的完整末时刻
`steps/240` 一致;拒绝截尾、超时长外推或离网格的完整回放请求。始终两轮、单环境、seed42。
CPU `stretch-time` 仅将原始时间戳乘以有限且>=1的系数;保留全部样本、位姿/关节几何路径、有效掩码、
关节顺序、已应用的坐标变换和来源类别。在说明中追加系数与输入文件 SHA256,不将专家标成合成数据。
输入仍须严格匹配清单;**没有通用强制替换哈希的选项**。源包身份算法不同的交付必须先独立核对
原始 URDF 全部 link/joint、仿真依赖和交付说明,并保留原文件及绑定依据,再生成仅本地使用的派生文件。
```bash
# BOUND 是已经独立审查并严格绑定右手清单的本地派生文件,不是未经核验的原始交付。
# EVIDENCE 是仓库外持久目录;输出必须尚不存在。
MANIFEST=assets/robots/dex_hand/linkerhand_g20_right/tracking_manifest.json
~/isaacsim/python.sh -m dex_workbench_tracking.cli stretch-time "$BOUND" \
--manifest "$MANIFEST" --factor 80 --output "$EVIDENCE/slow80.hdf5"
~/isaacsim/python.sh -m dex_workbench_tracking.cli validate "$EVIDENCE/slow80.hdf5" --manifest "$MANIFEST"
# 下面是需单独授权600秒资源预算、且确认无其他Kit/GPU任务时的完整实验命令;不是自动重试授权。
timeout --kill-after=15s 600s ~/isaacsim/python.sh scripts/tracking/track_l20.py \
assets/robots/dex_hand/linkerhand_g20_right/tracking.usda --manifest "$MANIFEST" \
--hdf5 "$EVIDENCE/slow80.hdf5" --steps 32000 --full-episode --workspace-radius 0.8 \
--execute-experimental --headless
```
本次指定51帧专家参考原长1.666667秒,统一80倍慢放后完整133.333333秒/轮;不再次应用
`world_from_source`,不裁剪、重居中或改变关节轨迹。入口只创建手,没有地面/物体,世界Z为负不需要增添场景。
成功必须同时具备退出0、明确PASS、两轮完整32000步、全部原有动态/重置/位姿与速度重复性门禁;
失败输出记录阶段、已执行步数及可用的最后误差/速度。超时或缺少最终PASS不是成功,不为通过而继续调参。
慢放结果仅适用于该派生参考,不证明专家原速、接触任务、训练质量或Sim2Real有效。
### 恢复后的单次授权完整回放:PASS2026-09-14
此前中断运行只恢复出启动记录,没有结束/退出/PASS证据,结果保持未知;未将其算作通过。
用户另行允许的一次600秒预算运行完成上述命令:384秒退出0,明确PASS,完整两轮各32000步。
Isaac Sim `6.0.1-rc.7`、PhysX `110.1.13`、RTX5080,所有原有运行时与重复性断言通过。
两轮各自的 max/RMS 汇总相同(不宣称跨运行GPU确定性):
| 误差 | 最大值 | RMS |
| --- | ---: | ---: |
| 腕位置 | 0.004234530 m | 0.001592088 m |
| 腕姿态 | 0.013369173 rad | 0.006896696 rad |
| 各帧最大关节误差 | 0.011143208 rad | 0.007029774 rad |
| 各帧最大mimic残差 | 0.000231490 rad | 0.000100007 rad |
- 原文件SHA256 `bd9321096803fbb64f590b4fdeb9056edc11ac446a7e16458c509beedc8b9552`
本地80倍派生文件SHA256 `8f584c7409698394429737d509924013b8b90700117f8af2fb22465223dc1815`
- 原始22个link/21个joint逐元素核对、右USD依赖包、51个原样本及Data/左右资产文件字节保留通过。
准备层包SHA `3e2071a60496b23bed252f4e2fc6e1d4540eecc8098578506419b5eb594f7da0`
- 持久制品目录标识 `expert-replay-recovery-20260914/recovered-20260914T033624Z`
`expert.log``expert-metrics.json``expert-result.txt``exact-command.txt`、绑定脚本/原始诊断/哈希清单。
完整存储路径见本次交付报告;未提交数据/日志。原始日志SHA256
`c6557269ffe3583ed113b3a1dcf3be6f4f3791bcff36a67798fbb4dcf1f48446`
- 新鲜81项CPU回归无跳过、Ruff/格式/diff检查通过。额外的原时间网格与慢放网格数值相等审计
**NOT MET**8个关节插值值差1个float32 ULP,另2个近零消差值差约2.3e-18/2.6e-18rad。
保留失败证据,不为其加入索引特例或放宽运行门禁;51原始样本仍逐值完全相同。
- 启动前后无Kit/compute进程;没有再次启动、调增益或改轨迹。仍有TGS外力迭代、16/21 actuator
5个被动关节)、visualizer/MaterialX/usdrt警告。未做原速、多环境、任务/训练或硬件验收。
- 上述恢复回放阶段未暂存、提交、推送或升级版本;后续v0.1.2本地提交准备不代表完整发布门禁通过。
## 6. 可选GUI展示(v0.1.2
同一入口新增 `--gui`,复用生产轨迹采样、控制、reset、两轮重复性及所有身份/安全门禁。
默认仍headless、不渲染;`--gui` 与显式 `--headless``--viz none` 冲突时启动前报错。
GUI使用Kit visualizer,物理步长仍为1/240秒,仅每8步渲染(另在reset后初始渲染一次),不改时间戳或慢放系数。
不要同时启动第二个Kit/GPU会话;只有旧会话退出且另获600秒预算授权后才运行:
```bash
export PYTHONPATH="$PWD/source/dex_workbench${PYTHONPATH:+:$PYTHONPATH}"
# SLOW80_HDF5 由调用方提供:已独立绑定同版右清单、按第5节80倍慢放的文件;不是自动绑定原始交付。
RIGHT=assets/robots/dex_hand/linkerhand_g20_right
timeout --kill-after=15s 600s ~/isaacsim/python.sh scripts/tracking/track_l20.py \
"$RIGHT/tracking.usda" --manifest "$RIGHT/tracking_manifest.json" \
--hdf5 "$SLOW80_HDF5" --steps 32000 --full-episode --workspace-radius 0.8 \
--execute-experimental --gui
```
显示设置独立于物理,位于 `dex_workbench_tracking/preview.py`
- 白色Dome强度700key/fill分别800/300、角度12/20度、XYZ旋转(-35,25,25)/(50,-40,-120)度。
- 全episode腕路径为青色(0.1,0.8,1.0)线性曲线,恒定宽度0.002m;不改参考点。
- 固定相机target为完整路径包围盒中心,eye偏移(1.15,-1.35,0.95)m;不逐帧跟随或重居中轨迹。
- 面向相机的10m方形暗背景位于target背后2m,仅自己的非反射emissive材质(0.055,0.065,0.08)。
无RigidBody/Collision API,不修改手的任何材质,不增加任务物体/桌面/碰撞或改变控制。
用户已确认仓库外展示克隆中的明亮手掌/手指与暗背景可见。
本次将其纯展示代码整合为可复用选项并加CPU/USD不变量检查;**整合后的CLI GUI E2E为NOT_RUN**
没有为提交准备再次启动Kit/GPU,也未打断用户现有GUI。克隆截图不能替代最终源码运行验收。
生成的右USD、原始URDF/标定/网格、专家HDF5、视频/日志均不随代码提交;仅右README和两个JSON元数据纳入。
干净克隆仍需经授权取得同哈希右资产并重建prepared层;右资产测试/回放在缺依赖时BLOCKED,不计skip为PASS。
完整pre-commit因工具缺失NOT_RUN;本地版本提交不是存储、许可、硬件或完整Release就绪声明。