V0.2 — 把 mock skills 换成真正自主的 Stretch

v0.1 证明了 ANIMA 认知栈在语言输入下能跑通;v0.2 要把底下的 mock skills 换成真自主执行的机器人——每次运行都从 MJCF 查物体位姿、算 IK、步进物理,不是脚本重放。

选型上走了一次 pivot,值得记录。

Pivot:从 ROS 2 + Gazebo 改到纯 Python MuJoCo

原方案是 Docker + ROS 2 Humble + Gazebo Harmonic + MoveIt 2 + Nav2——标准"重型"机器人栈。

执行时发现三个问题:

  1. hello-robot 官方不提供 stretch_moveit2 的 apt 包或 GitHub 配置,要自己写 SRDF + kinematics config(3–5 小时工作量)
  2. stretch_mujoco 的 Python API 本身已经够用:sim.pull_camera_data() → RGB 帧;sim.move_to(Actuators.lift, pos) + wait_until_at_setpoint → 关节位置控制;sim.set_base_velocity(v, ω) → 底盘速度。Stretch 手臂只有 5 DoF(lift Z + arm 伸缩 + wrist yaw/pitch/roll),分析 IK 10 行代码内能搞定
  3. Nav2 对封闭的单房间 + 走廊场景明显过重

新方案:纯 Python stretch_mujoco API + 分析 IK + unicycle PID。ANIMA 的 L3 skill 直接调 stretch_mujoco,不启动任何 ROS 节点。

这个选择顺带给了几个好处:

  • MuJoCo 原生支持 macOS,开发机也能跑,不再被 Linux 云主机的 VSCode Remote SSH 绑死
  • 部署简化到三个进程(FastAPI + Next.js + MuJoCo),不再需要 rosdep / colcon / DDS 调参
  • 真机迁移路径不被堵死:v1.x 想上 ROS 只需把 SimSkillBehaviour 换成 Ros2SkillBehaviour,上层 py_trees 编排零改

原本的 ROS 2 Humble + stretch_ros2 workspace 保留不删,当作未来接真机的参考。

L3 技能层落地六个原语

新增 SimSkillBehaviour 基类 + 六个具体 skill,共享一个 blackboard dict:

  • locate — 在仿真里查目标 body 位姿
  • navigate — unicycle PID,带 align / approach 两段 hysteresis 避震荡
  • grasp — 分析 IK + 闭合爪
  • lift — 抬起到安全高度
  • deliver — 导到床边位
  • release — 打开爪子

同时在 L2 Planner 里加了"仿真不可用时自动回落到 v0.1 mock skill"的兜底,保证本地零配置也能跑。

仿真视图进前端

后端新增 sim/manager.py 持有 StretchMujocoSimulator,并自己渲染 demo_view 第三人称相机。stretch_mujoco 的 camera pipeline 不暴露自定义 MJCF 相机,所以绕过它直接用 mujoco.Renderer

三条路由:

  • /api/sim/mjpeg — multipart MJPEG 流
  • /api/sim/reset — 场景归位
  • /api/sim/status — 状态探针

前端加一个 SimulationView.tsx<img> 接 MJPEG + Reset 按钮),整体布局从三列扩到四列(nav / sim live / intent+BT / factors)。

L5 数据开始驱动评估

l5_assessment.py 里,p_skill 从固定 0.91 改成"从 pea_log.jsonl 读滑窗真实成功率"——PEA 终于开始喂回 GOA 计算,不再是静态常数。

部署

Hetzner(89.167.35.145),三个 systemd 单元 + nginx 反代:/ 到 Next.js prod,/api 到 FastAPI,/ws 走 FastAPI WebSocket upgrade;/api/sim/ 路径关 nginx buffering 让 MJPEG 实时传。

验收(端到端脚本)

  • 打开 http://89.167.35.145,看到病房场景(床、床头柜、水杯、Stretch 初始位)
  • 输入"我想喝水" → L0–L5 依次高亮 → TaskSpec 产出 DRINK_WATER → 行为树六节点转 green
  • MJPEG 看到 Stretch 自主导航 → 臂伸到杯 → 合爪 → 抬起 → 返回床边(每次重算 IK,不是重放
  • 五因素随过程更新,PEA 新增 outcome=success 记录
  • Reset Sim 按钮 → 2 秒内归位

推到后续版本

  • 6 个场景分支逻辑(CALL_HELP / ADJUST_TV 等)→ v0.3
  • 失败 fallback 叙事 → v0.3
  • 非 DRINK_WATER 场景视频 → v0.4