Files
Mujoco_WASM/docs/robot-interface.md
T
chenlin 3ad29356c9
web-platform-ci / TypeScript, lint, unit, build (push) Waiting to run
web-platform-ci / Playwright E2E (push) Waiting to run
lekiwi-compatibility / cpu-compatibility (push) Waiting to run
feat(lekiwi): release V0.10.1 初步集成 LeKiwi,优化碰撞模型
集成通用机器人数值接口、本机控制桥、LeRobot 插件和统一键盘遥操作。采用离线 CoACD 全臂碰撞配方 revision 4、局部装配区切分与结构自接触,限制直接关节位姿写入并保留安全看门狗。同步版本号、变更记录、来源许可证和兼容性验证。
2026-09-20 14:42:30 +08:00

14 KiB
Raw Blame History

机器人接口 V1:实时控制与任务层分离

能力与兼容矩阵

已验证内容 不支持 / 不承诺
RobotDescriptor/Action/Observation 通用 SI 标量、单关节与 LeKiwi 后端 任意远程可执行插件
LeKiwi profile v1 三轮底盘、五个臂关节、夹爪、实测反馈、reset 实机标定、可靠抓取、崎岖地形或 sim-to-real 保证
lerobot_robot_mujoco 实际 LeRobot 0.6.1 的 Robot/Config、发现、工厂、九维控制循环 冒充硬件 ZMQ 服务、官方所有 CLI 原样运行
仿真 官方浏览器 MuJoCo WASM 3.11.0 用原生 MuJoCo 测试代替浏览器物理验收
环境 Ubuntu 24.04 x86_64、Python 3.12、CPU torch 2.11.0+cpu / torchvision 0.26.0+cpu 修改既有训练 .venv 或加载物理机器人
V1 能力标志 lockstep=falsecameras=falsetraining=false 相机、LeRobot 数据采集、Gym/RL 训练

普通 MJCF/URDF、Pyodide 控制器和 Go2 ONNX/训练链保持独立。未知模型不会因关节数相似自动套用 LeKiwi。平台自己的有界遥测 CSV/JSON 仍可使用,但不是 LeRobot dataset。

运行链路

LeRobot Robot / 通用 SimRobotClient(同步 HTTP
  → 本机 aiohttp broker(认证、租约、限流)
  → 浏览器 ExternalControlClientWS,仅数值消息)
  → RobotRuntime(校验、最新目标邮箱、watchdog
  → MuJoCoRobotAdapter + ModelBindings
  → 固定 dt 的 mj_step → 实测 observation / applied ACK

ModelBindings 缓存关节/执行器名称、qpos/dof 地址和标量传动约束,复用于 Python 和 Go2 绑定。Embind 临时查询句柄及时释放;关节 ID 不直接当作 qpos/dof 地址。

ControlArbiter 只有 manual | python | policy | external 一个所有者。每次 claim 创建新的身份票据,旧 Python dispose/step、旧 ONNX 结果或旧 socket 回调不能覆盖新控制者。非所有者退出不清除另一个控制者的目标。

外控使用同一 JS 线程上的约 120 Hz 物理调度器,仍按模型固定 dt 积分并遵循单次 8 ms / 100 步追帧预算;网络事件只入队,不在物理步内 await。普通手动/Python/ONNX 保留原渲染驱动步进。观测约 30 Hz,WS 独立发送;React 完整快照约 5 Hz,不用 UI 帧率充当控制/观测时钟。

外控绘制上限 30 FPS。检测到 SwiftShader/llvmpipe 等软件渲染时,profile 关闭阴影,外控绘制上限 5 FPS,为物理/通信留出主线程时间;几何和接触动力学不变。仍非硬实时:主线程卡顿/系统休眠时不能保证及时回调,恢复后先拒绝过期动作。

协议与身份

权威结构:JSON Schema共享 fixture。不要根据本页重新发明字段名称。

  • descriptorprotocolVersion=1profileId/profileVersionmodelFingerprintframeactionChannels/observationChannelscapabilities
  • 通道:id/unit/min/max/mode。只接受有限标量;未知字段、额外通道、重复通道、bool、NaN/Infinity 被拒绝。
  • 身份:sessionId + modelEpoch + leaseId。重置递增 epoch;重载新建 session;租约只对当前授权代次有效。
  • action:身份、protocolVersion=1、递增 actionSeq 和完整 values
  • observationprotocolVersion/sessionId/modelEpoch/sequence/simTime/appliedActionSeq/paused/valuessequence 可在新 epoch 中重启,同 epoch 不可倒退。
  • action result:身份、actionSeq/simTime/values。它在物理步之后确认 接受的目标,不是实际位置;实际状态必须读 observation。

HTTP 与 WS

HTTP 前缀 /api/control/v1,均需要 Authorization: Bearer …

方法 / 路径 作用
GET /health 本机桥状态
GET /robot 当前 descriptor
GET /observation 新鲜的实测状态
POST /lease 用 session/epoch/fingerprint 申请单写入者租约
DELETE /lease 释放,带 X-Control-Lease
POST /action 完整 action,带 X-Control-Lease
POST /reset 请求新 epoch 的暂停状态,带 X-Control-Lease

WS /ws/control/v1:先发送 {type:"auth",token:…};注册 descriptor/状态,再交换带 request id 的 claim/action/release/reset RPC、结果和状态更新。以 ExternalControlClient.tsserver.py 为实现依据,SDK 用户无需手写 WS。

错误码:INVALID_MESSAGEINCOMPATIBLE_MODELUNSUPPORTEDUNAUTHORIZEDCONFLICTSTALEPAUSEDTIMEOUTSUPERSEDEDDISCONNECTED。缺能力显式失败,不伪造零图像或假训练支持。

LeKiwi 映射与校验

唯一参数源:lekiwi-v1.jsonPython 包通过 package-data 发布同一份 JSON。

  • canonical 机体系:X 前、Y 左、Z 上;CAD +Y 前向经 -π/2 绕 Z 转换。
  • 五个臂角:LeRobot 度 ↔ profile 符号/零偏修正后的 rad;夹爪 0–100 ↔ ratio 01 ↔ 关节 -0.18…0.9 rad。CAD 夹爪轴反向,使递增开度对应物理张开;闭合限位不再允许两指交叉。
  • 底盘 x.vel/y.vel 为 m/sLeRobot theta.vel 为 deg/s,通用接口为 rad/s。
  • 轮顺序 left/back/right,半径 0.05 m、基座半径 0.125 m;最大 4.601942363656923 rad/s,三轮同比缩放而非分别削顶。
  • LeRobot 九维反馈使用实测轮速里程计以兼容上游;通用 observation 另有真实机身位姿/速度,因此碰撞/打滑时两者可能不同。
  • LeRobot 部分动作仅保持最后 确认 的臂/夹爪目标,省略底盘速度为零。连接初始保持值来自实测观测。拒绝 use_degrees=False、相机配置、物理校准目录以及非法 scalar。

URDF 和整臂 18 个视觉 STL 必须匹配固定来源 SHA-256;导出 MJCF 必须含受支持的 profile、version、source SHA、platform_lekiwi_collision_revision=4 和当前 platform_lekiwi_collision_recipe_sha256(旧配方,包括 revision 3,必须从原始 URDF 重新转换)。再校验编译后的浮动根、关节/执行器、传动、轴向、限位、增益和力限等。缓存编辑继承当前显式 profile,校验失败保留旧场景但不恢复外部授权。

启用机器人 profile 后,关节角仅作实测显示:禁止 setJointPosition()resetJoints() 直接写 qpos,禁用关节拖动/单独重置关节,也禁止忽略关节限位;完整仿真 reset 的撤权/epoch 行为不变。旧滑条是暂停时的姿态编辑而非物理运动,任何碰撞体都不能防止这种直接插入。需要运动时播放仿真,通过执行器目标或外控驱动;普通非 profile 模型的姿态编辑不变,外控仍排斥手动执行器写入。

modelFingerprint 是最终输入 XML 字节的 SHA-256,不是语义哈希或所有 mesh 的合并内容哈希;资源另有 source-manifest.json。导出保留 platform_robot_profileplatform_robot_profile_versionplatform_robot_source_sha256,并添加 platform_robot_source_fingerprint 追溯已加载源。重新序列化/导入会重新计算指纹;标记不是签名,也不能代替运行时校验。需要限定精确模型时设置插件的 expected_model_fingerprint

停止、冻结与回滚

超过 500 ms 没有有效动作、观测过期、用户暂停/停止、控制者离线、页面隐藏/退出、模型替换都会撤销 lease/授权,清除待应用目标,停止轮目标、保持实测臂姿态并暂停。重新出现的 WS 事件也不能续期已经过期的租约;第一恢复物理步再次检查期限。心跳不等于新观测。

authorizationGeneration 隔离旧 release/stop/error/reset 的清理回调。新授权后迟到的旧消息不能把新 lease 清掉。reset 的 observation 序号在新 epoch 中可以从 1 重新开始;同 epoch 回退仍然拒绝。

浏览器 token 只在当前页面内存。本机 bearer token 不防已经获得 token 的本机恶意进程;不应开放到局域网/公网。详见 桥接安全边界

验证、性能与升级

  • 普通 CI:合成单关节真实 SDK→桥接→浏览器 WASM;协议、身份、超时、队列和现有功能测试。不下载 LeKiwi,不安装 LeRobot。
  • 独立 lekiwi-compatibility CI:固定资产 revision、固定 CPU 环境、实际上游发现/工厂、完整物理和工作台测试;依赖缺失即失败,不以 skip 通过。
  • revision 4 工作台实测(本机 Ubuntu 24.04、WASM 3.11.0、SwiftShader):60.022 s / 1800 次动作,仿真推进约 59.636 s;整轮“观测→动作确认→诊断回读”平均 22.6 ms、P95 75.2 ms、最大 151.9 ms;最大观测仿真时间间隔 136 ms,超时/丢弃为 0。外控活跃样本的软件渲染平均约 4.90 FPS;绘制间累计物理耗时最高 139.6 ms,60 次采样中 59 次出现 overBudget(至少一次调度仍有待追帧时间),不能宣称无超预算或硬实时。热身后 JS 堆采样约 132.56 MiB、WASM 堆容量 564592640 字节,首末采样无增长。完整碰撞与 1 ms 步长比旧简化模型开销更大;500 ms 看门狗、8 ms/100 步调度预算不变,这不是跨机器性能保证。
  • 专用测试记录逐秒 FPS、step budget、JS 堆、WASM 堆容量及实际机体移动。JSON、物理轨迹和截图输出到 build/e2e/lekiwi/;堆容量不等同于实际已用内存,60 秒稳定不等于长期无泄漏证明。
  • revision 4 从整臂 18 个视觉网格(包括焊接舵机/附件)离线 CoACD 生成 538 个凸包,再按配合区边界切分成 1,220 个碰撞凸包,替代旧胶囊/手工分段,显式启用 5,581 对相邻结构接触。仅保留有几何边界的装配配合例外,不整对排除相邻 body。生成/缓存、固定依赖、来源/许可证与审核边界见 碰撞数据说明
  • Mirror / Square 回归使用实际可达的肩旋 0/±0.8 rad:肘目标 1.3 rad 被挡在约 −0.07953 rad,接触点离轴约 71.8 mm(不是轴承锁死);峰值软穿入约 0.158 mm,稳定约 0.046 mm。反向到 +0.3 rad 后实测约 +0.29135,接触解除。
  • 上臂/臂座组件测试中,安装板或肩部结构夹片先于 Base_08q 本体阻挡:抬升目标 +0.6 rad,实测约 +0.119(肩旋 0/+0.243(肩旋 ±0.8);反向到 −0.3 后实测约 −0.2913、接触解除。完整几何下部分抬升/腕俯仰目标会提前遇阻;没有缩小声明的关节范围来隐藏问题。肩旋配合区跨边界凸包切分后,±0.942 rad 双向扫掠实测可达且无配合区接触,不再把轴承锁死冒充结构阻挡。
  • 夹爪闭合/半开/全开的指间距约 1.47/41.10/64.88 mm,三者无指间穿入接触,张开空隙不误封堵;静态 16 mm 球体阻挡闭合,峰值软穿入约 0.320 mm、稳定低于 0.020 mm。间距使用独立三角面距离 oracle:WASM 3.11 的一次薄凸包 mj_geomDistance 查询返回零,但两见证点相距超过 50 mm,不能拿该零值作真实间距;没有为通过测试而改 solver 或放宽间隙断言。
  • 另有原始 STL 六向极值的 108 次覆盖探针、六关节各两个目标(上下限的 60%)的 0.4 rad/s 扫掠及数值稳定性检查。这些是有限场景验证,不是全表面几何误差证明、所有关节组合的穷举、自动避障或可靠抓取保证。
  • 浏览器真实物理包括 30 秒站稳、±0.1 m/s 两秒位移约 0.195–0.199 m、双向转动、臂/夹爪以及墙体阻挡;另外测试真实 PTY 键盘输入、Pyodide 旧回调、重载/缓存回滚、reset、崩溃、隐藏事件、CDP 暂停整个 JS 执行后恢复。
  • 本次整臂回归:110 个文件 / 482 个 Vitest、7 个离线生成器单测;专用 LeKiwi 物理/插件/工作台 14 个 E2E 全部通过,无跳过,最终证据在 build/e2e/lekiwi-full-collision-final/。16 个桥接、19 个 LeRobot/键盘 Python 单测通过,命令见示例 README。旧普通浏览器与训练服务覆盖率记录不是本次重新执行结果,不混作当前碰撞验收。
  • 已知限制:开发诊断强制注入严重重叠 qpos 后的原生几何查询曾触发 WASM 2 GiB 上限/中止;不是受支持的运动路径,未修复引擎对任意穿透初态的健壮性。正常入口已禁止 profile qpos 瞬移,不应把有限动态回归解释为任意姿态保证。详见碰撞数据说明。
  • CI 配置增加隔离的离线分解重建检查;上述数字来自本机执行,不声称已运行远端 GitHub Actions。固定 revision 下载与本地参考目录重建得到相同 ZIP;wheel 已验证包含 canonical profile 和许可证。

升级上游/profile/依赖时:审查许可证与源码差异 → 更新 source hash/版本和映射 → 重建资产及 wheel → 跑跨语言 golden、真实物理、完整 60 秒及旧功能回归 → 更新约束文件、环境记录和 CHANGELOG。不要仅改版本号后绕过模型校验。

后续任务 / RL 层(尚未实现)

新增后端需要实现 RobotAdapter 的 describe/validateAction/applyAction/readObservation/safeStop/reset/dispose,使用可信代码显式注册;无需修改通用桥接。不要把可执行工厂放入用户导入 JSON。

在其上单独增加 task 层:原生 MuJoCo 后端、step(action,n_substeps)、seed/reset、reward/terminated/truncated、Gym wrapper,再做批量训练/策略部署。需要先验证原生与 WASM 的模型、单位、动作语义一致。当前实时浏览器 bridge 不能冒充确定性锁步或高吞吐训练环境。