Files
chenlin f3a8a38acd
web-platform-ci / Standalone decision service (no cloud credentials) (push) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
lekiwi-compatibility / cpu-compatibility (push) Has been cancelled
web-platform-ci / Standalone decision service (no cloud credentials) (pull_request) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (pull_request) Has been cancelled
web-platform-ci / Playwright E2E (pull_request) Has been cancelled
lekiwi-compatibility / cpu-compatibility (pull_request) Has been cancelled
feat: release v1.0.1 CADWorld 网站与 LeKiwi 智能抓放
集成同源 BYOK 会话隔离、精简模型设置、官方订阅入口和 HTTPS 发布运维;保留本地训练/调参与控制能力。同步 npm 版本及 CHANGELOG,记录公网真实 API 验收仍待用户凭据。
2026-09-24 09:57:41 +08:00
..

LeKiwi 仿真示例

目标:通过统一机器人接口连接 LeRobot 0.6.1 的上层控制逻辑。此目录不包含实体硬件驱动、相机或 RL 训练任务。相同 A 资产还可在主工作台「控制台 → LeKiwi 智能抓放」运行有限场景任务,见 模型任务与物理验收;不使用外控桥作为模型服务。

可重建模型输入

source .venv/bin/activate
python examples/lekiwi/prepare_assets.py --source /path/to/LeKiwi
# 或明确允许下载固定版本所需文件(不会克隆整个仓库)
python examples/lekiwi/prepare_assets.py --download

生成 build/lekiwi/lekiwi-v1.zip、原始 URDF/资源副本、SHA-256 清单及 Apache-2.0 许可证。原参考仓库保持只读;常规前端构建不下载任何资产。

资产重建脚本适用源:SIGRobotics-UIUC/LeKiwi 的 efa608d7ee5a495a4803b1d28cd0c955b4f1e033;URDF SHA-256 见 robot_profiles/lekiwi-v1.json。网页显式选择 profile 时也支持换色、显示名、XML 重排和等价数值等非机械变体;固定运动链、物理属性与全部源网格仍须匹配。几何/动力学或拓扑改变不能套用旧 profile,New_urdf 两包的新七关节臂属于此边界。详见 变体检查结果与适配边界。

动力学边界

  • CAD 轮 STL 每个 314,244 面,超出 MuJoCo STL 解码器的 200,000 面限制。现已通过不减面的 OBJ 兼容层完整恢复三轮 CAD 视觉,并随轮轴运动;原始 STL、派生资源与哈希可完整导出。简化轮毂/每轮 12 个被动滚子仍用于动力学,不以视觉细节冒充精确三角面碰撞。见 完整网格与性能边界。
  • 九个主执行器:5 个臂位置伺服、夹爪位置伺服、3 个轮速度伺服;另外 36 个滚子 hinge 不加电机。仅通过物理接触驱动车体,不强写底盘位姿/速度。
  • CAD +Y 朝前,在 canonical 基座中旋转 -90°。简化三轮按理想 0.125 m 轮距、0.05 m 半径布置;并非沿用 CAD 不等距的轮轴位置。
  • 原始 CAD 的 17.324 kg 惯性估计不用于动力学。仿真采用 2.2 kg 基座、按 profile 给出的臂段/轮质量、简化碰撞和保守限位。惯性、摩擦、增益均为仿真估计,不代表实体标定。
  • 当前碰撞配方为 revision 4:从整臂 18 个原始视觉网格(含固定舵机/附件)离线 CoACD 分解成 538 个凸包,再按轴承配合区切分成 1,220 个独立碰撞凸包,替代旧臂胶囊和手工分段。保持视觉坐标变换、夹爪空隙、零附加碰撞质量与显式惯性。工具隔离在 build/venvs/collision,浏览器仅使用生成数据。来源、许可证、缓存/参数和重建方法见 碰撞数据说明。
  • 不再整对排除相邻连杆:显式启用 5,581 对结构凸包接触,包括 SO_ARM100_08k_Mirror-v1 / SO_ARM100_08k_116_Square-v1。跨区域凸包先切分,只对完全落入关节轴承/舵机配合区域的部分保留局部例外,以免装配重叠锁死关节;非相邻碰撞保持启用。细化为 1 ms 物理步长,未放宽 500 ms 安全阈值。凸分解仍有误差,不等于逐三角形精确碰撞或所有姿态无穿入保证。
  • 自碰撞会阻挡不可能到达的目标,动作确认值不等于实测关节角;遇阻时目标/实测不一致是正常反馈。这不是自动避障或无碰撞路径规划,也没有关闭全臂自碰撞、缩小肩关节范围来隐藏问题。
  • CAD 夹爪轴已反向,使开度增大确实张开;内部关节范围为 -0.18…0.9 rad,LeRobot 的 0–100 开度接口不变。当前配方闭合端测试间隙约 1.47 mm,另有指面间接触保护;不会通过关闭自碰撞来允许两指交叉。
  • 平地低速控制、静态障碍阻挡和夹爪指尖/物体接触经过真实浏览器 WASM 验证;不保证崎岖地形、可靠抓取、相机、训练或 sim-to-real 策略迁移。MuJoCo 使用软接触,受力时允许小量穿入,瞬态大小取决于速度/载荷;这与缺少碰撞体导致整体穿过不同,高速/薄物体也不属于已验证范围。

更新碰撞体后必须重新转换模型

  1. 退出 Python 控制脚本,停止外控;刷新前端页面加载新代码。
  2. 重新导入 build/lekiwi/lekiwi-v1.zip 中的原始 URDF,显式选择 LeKiwi v1(仿真专用),重新“转换并加载”。源 ZIP 没变,不必重新下载;不要继续使用旧的已转换 MJCF/缓存模型。旧 MJCF 会提示从原始 URDF 重新转换。
  3. 在检查器勾选“显示碰撞几何”,可查看橙色凸包,确认覆盖两侧指尖、臂座、Square、Mirror、其他臂段和固定附件;此开关仅影响显示,不开关物理碰撞。
  4. 重新连接桥接、播放并允许外部控制,再启动键盘脚本。v 张开、b 闭合;可以先用 --gripper-speed 25 低速检查。

网页关节滑条不是物理运动

旧关节滑条是暂停后直接写 qpos 的姿态编辑器,会绕过物理积分,碰撞体不能阻止这种“瞬移”。现在启用机器人 profile 时,关节角只读、禁用关节拖动/单独重置关节、禁止直接位姿写入和忽略关节限位;要运动请播放后调整“执行器”目标,或使用键盘/外控。普通非 profile 模型仍保留原姿态编辑功能。“重置仿真”仍可用,并保留撤销外控和 epoch 更新。外控期间继续禁止手动执行器写入。

完整演示

从仓库根目录执行:

source .venv/bin/activate  # Python 3.12
python -m pip install -e ./control_bridge
python examples/lekiwi/setup_lerobot.py  # 固定 CPU 依赖,仅写 build/venvs/lerobot/
npm ci
npm run dev
  1. 将 build/lekiwi/lekiwi-v1.zip 导入工作台,在 URDF 对话框显式选择 LeKiwi v1(仿真专用),点击“转换并加载”。若已导入可兼容 MJCF,在“控制台 → 开源项目 / 外部控制”选择 profile 并重新编译。
  2. 另一终端用 .venv/bin/python -m mujoco_control_bridge 启动本机服务。复制启动时显示的 token,在工作台填入 http://127.0.0.1:8766 和 token,点击“连接桥接”。
  3. 点击“播放”,再点击“允许外部控制”。外控锁定 1×;手动关节/执行器写入不可用,原 Python/ONNX 停止。
  4. 第三个终端设置同一 token,运行真正的 LeRobot 插件示例:
read -rsp '控制 token: ' MUJOCO_CONTROL_TOKEN; echo
export MUJOCO_CONTROL_TOKEN
export MUJOCO_CONTROL_ENDPOINT=http://127.0.0.1:8766
env -u PYTHONPATH PYTHONNOUSERSITE=1 build/venvs/lerobot/bin/python \
  examples/lekiwi/demo_control.py --duration 60

脚本保留“读状态 → 合成动作 → 发送 → 节拍等待”的上游 30 Hz 循环形状,九个通道一起运动,输出确认目标、实测反馈、时间和延迟统计。不运行硬件构造函数,不初始化串口/相机/GPU。

脚本退出会自动暂停。重新演示必须再次播放并授权;重置、模型重载、页面隐藏/退出、控制进程崩溃和超时也不会自动恢复。

键盘演示(包括从 demo_control.py 切换过来)必须再次完成 播放 → 允许外部控制 → 启动脚本。授权不会自动播放;确认按钮已变为“暂停”、外控状态为“等待 Python 控制者”,再执行:

env -u PYTHONPATH PYTHONNOUSERSITE=1 build/venvs/lerobot/bin/python \
  examples/lekiwi/teleoperate_sim.py

底盘 + 机械臂键盘控制

原 LeKiwi 仓库主要提供硬件/CAD/URDF,其 README 的遥操作方案是 WASD + leader arm:键盘控制底盘,SO-ARM leader 的六路位置控制从臂。当前仿真已经实现五个臂关节和夹爪的执行器、单位换算与反馈;这里用键盘关节点动替代实体 leader,无需安装硬件驱动或更换桥接;但更新碰撞配方仍须按上文重新转换模型。

在运行脚本的 Linux 交互终端使用小写按键:

按键 功能 LeRobot 动作通道
w / s 底盘前进 / 后退 x.vel
a / d 底盘左移 / 右移 y.vel
z / x 底盘左转 / 右转 theta.vel
r / f 底盘速度升档 / 降档(不改变臂速度) —
u / j 肩部旋转角增大 / 减小 arm_shoulder_pan.pos
i / k 肩部俯仰角增大 / 减小 arm_shoulder_lift.pos
o / l 肘部角度增大 / 减小 arm_elbow_flex.pos
t / g 腕部俯仰角增大 / 减小 arm_wrist_flex.pos
y / h 腕部旋转角增大 / 减小 arm_wrist_roll.pos
v / b 夹爪张开 / 闭合 arm_gripper.pos
空格 清除按键脉冲,底盘停止、机械臂保持最后确认目标 —
q / Ctrl+C 退出、释放控制权并暂停仿真 —
  • 臂按键是关节空间点动,不是末端 XYZ/逆运动学控制。五个关节使用度,夹爪使用 0–100 开度;角度正负不代表相机画面中的上下左右。
  • 初始目标来自实测姿态,不会启动即归零。每轮 30 Hz 将底盘速度与臂增量合成一条动作;关节/夹爪限幅由现有 profile 执行,下一轮从确认后的目标累加,避免到限位后积累不可见的超限目标。
  • 默认臂速度为 20 度/秒、夹爪速度为 50 百分点/秒,可用下列参数调慢(上限分别为 90 和 100,必须大于零)。控制循环卡顿不会补发大幅角度跳变。
env -u PYTHONPATH PYTHONNOUSERSITE=1 build/venvs/lerobot/bin/python \
  examples/lekiwi/teleoperate_sim.py --arm-speed 5 --gripper-speed 25

终端输入是 180 ms 脉冲,不是系统级按下/松开监听;点按为小步调整,长按依赖系统键盘重复,组合键只是重叠脉冲。脉冲过期后底盘速度归零、机械臂保持最后确认目标,脚本仍持续发送动作。空格不会退出授权,也不会将机械臂归零;真正停止仿真请按 q 或在页面停止外控。请并排显示浏览器和终端,保持仿真页面可见;隐藏/最小化页面会撤销授权。

底盘和机械臂必须由同一个控制循环合成动作,不能分别启动两个 Python 控制者;外控期间也不能同时用网页执行器滑条写入。碰到其他臂段/安装板后不会继续到达目标;完整 CAD 下可用运动范围可能比声明的关节上下限窄,遇阻应反向点动,而不是扩大限位或禁用碰撞。

后续接实体 leader 的接入点

若要复用上游 SO100/SO101 leader,保留 lekiwi_sim 作为被控机器人,只替换机械臂输入源:在 leader 已连接、完成硬件校准且 use_degrees=True 的前提下,将 leader.get_action() 的 shoulder_pan.pos 等六路键名加 arm_ 前缀,再与底盘动作合并后调用同一个 robot.send_action()。不要启动实体 LeKiwi follower/ZMQ 服务,也不要把归一化的 -100…100 臂角当成度。

这只是接口接入说明,当前终端脚本未实现串口 leader 模式,也未做硬件验证;接入前还需核对真实 leader 与仿真 profile 的零位/方向、限位和每步速度限制。当前模型不保证可靠抓取或 sim-to-real 一致性。

连接时提示“机器人观测超过 500ms 未更新”

这表示本机桥接可访问,但未收到浏览器端新的机器人观测;不是 LeRobot 安装或 Python 导入错误。桥接连接成功不等于仿真正在运行。

  1. 将浏览器和终端并排显示,保持仿真页面可见,不要切换到其他浏览器标签、最小化或完全遮住仿真窗口。页面隐藏会撤销授权;若显示“未连接”,先重新连接桥接。
  2. 查看“机器人观测状态”。若显示“已暂停(非实时观测)”或播放按钮仍为“播放”,先点击 播放,再点击 允许外部控制。前一个脚本退出、停止外控或超时后都会暂停,不能只重新运行 Python。
  3. 确认仿真时间持续增加、观测年龄低于 500 ms,状态显示“等待 Python 控制者”,然后在终端重跑脚本。等待 Python 连接本身没有 500 ms 倒计时;这个阈值检查的是观测新鲜度,取得租约后还会检查动作是否持续更新。
  4. 若正在播放且页面可见时观测仍持续过期,检查页面错误和主线程卡顿;必要时重新加载模型并连接、播放、授权。不要通过增大 SDK HTTP 超时来绕过:HTTP 超时与 500 ms 观测/动作安全看门狗是两回事。

旧版桥接会将暂停超过 500 ms 也报成“观测过期”;修复后会明确提示“仿真已暂停;请先在浏览器点击‘播放’,再点击‘允许外部控制’”。更新代码后需重启 python -m mujoco_control_bridge,并在页面重新连接、播放、授权;若服务生成了新 token,请同时更新浏览器和终端中的 token。

回归和证据

source .venv/bin/activate
npm run test:control-bridge
build/venvs/lerobot/bin/python -m unittest discover -s integrations/lerobot/tests -v
LEROBOT_PYTHON="$PWD/build/venvs/lerobot/bin/python" npm run test:e2e:lekiwi
# 仅物理测试(不需 LeRobot)
npx playwright test -c web_platform/playwright.lekiwi.config.ts lekiwi.physics.spec.ts lekiwi.gripper.spec.ts lekiwi.armCollision.spec.ts lekiwi.fullCollision.spec.ts

专用套件不是 mock:整臂 18 个视觉网格的 108 次独立 CAD 表面接触探针,六关节各两个有界目标扫掠,Mirror/Square 主体接触阻挡/脱离及禁止直接 qpos 写入;真实 WASM 3.11.0 的 30 仿真秒站稳、正负三轴运动、臂/夹爪、墙体阻挡、两侧 CAD 指尖探针接触、开度与实际指间距同向、张开空隙不误碰撞、闭合被物体阻挡以及指面自碰撞、上臂下压时与自身臂座组件的真实接触/穿入量及反向脱离(完整模型中安装板或肩部结构夹片先于底座本体接触);真实 Python/LeRobot、PTY 终端底盘 + 六路臂/夹爪正反点动、无输入保持与退出撤权、完整工作台文件导入→编译→授权→60 秒控制;另含旧控制回调、reset、新 epoch、崩溃、重载/回滚、隐藏和 JS 冻结恢复。

build/e2e/lekiwi/ 保存 XML、物理轨迹、60 秒 JSON(RTT、新鲜度、FPS/步进预算、JS/WASM 堆容量)和截图。普通 E2E 不下载资产或安装 LeRobot;专用 CI 缺依赖即失败,不静默跳过。

软件 WebGL 比物理计算慢:外控物理/传输独立调度;检测到 SwiftShader 等软件渲染时关闭阴影、3D 显示上限 5 FPS,观测仍约 30 Hz。不能把此模式当作锁步 RL 或硬实时系统。性能实测、兼容矩阵和限制见 机器人接口。