rerunrobot/README.md

342 lines
12 KiB
Markdown
Raw Permalink 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.

# HUSKY: Humanoid Skateboarding System via Physics-Aware Whole-Body Control
基于 [HUSKY](https://arxiv.org/abs/2602.03205) 思路的人形滑板全身控制实验代码mjlab 训练、`rsl_rl` 与 MuJoCo 评测脚本。本仓库包含个人开发与 **Docker** 封装。
**目录:** [`src/mjlab_husky`](src/mjlab_husky) · [`rsl_rl/`](rsl_rl/) · [`dataset/`](dataset/) · [`test_scene/`](test_scene/) · [`ckpts/`](ckpts/)
---
## 本地安装Ubuntu 22.04,推荐 `uv`
```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
git clone https://github.com/<你的用户名>/humanoid_skateboarding.git
cd humanoid_skateboarding
uv sync && uv pip install -e .
```
**可选LeRobot v3 导出 / 边播边录** 需要额外安装 `lerobot`(不在默认依赖里,以免与现有 PyTorch/CUDA 栈冲突):
```bash
uv pip install lerobot
```
若安装 `lerobot` 等包后出现 `import torch`**NCCL 符号错误**(例如 `undefined symbol: ncclDevCommDestroy`):多为 **`nvidia-nccl-cu12``torch`cu13并存**,二者都往 `site-packages/nvidia/nccl/lib/``libnccl.so.2`,旧库覆盖了新库。可卸载 cu12 并重装 cu13 的 NCCL
```bash
uv pip uninstall nvidia-nccl-cu12
uv pip install --force-reinstall "nvidia-nccl-cu13>=2.29"
```
---
## 训练
```bash
cd humanoid_skateboarding
uv run train Mjlab-Skater-Flat-Unitree-G1 --env.scene.num-envs 4096
```
查看全部参数:
```bash
uv run train Mjlab-Skater-Flat-Unitree-G1 --help
```
---
## 回放 `play`
任务名固定为 **`Mjlab-Skater-Flat-Unitree-G1`**(注册在 `mjlab_husky.tasks`)。
### 通用
```bash
uv run play Mjlab-Skater-Flat-Unitree-G1 --checkpoint_file ckpts/test.pt
```
- **`--viewer auto`**(默认):有 `DISPLAY` / `WAYLAND_DISPLAY` 时用 **native**,否则 **rerun**
- **`--viewer native`**:本机有图形界面时使用 MuJoCo 原生窗口。
- **`--viewer rerun`**Rerun Web Viewer无头服务器常用
- **`--viewer rerun_native`**:同一套 mjlab 仿真与策略步进,**同时**打开仓库自带的 **MuJoCo 原生 viewer**`NativeMujocoViewer` / GLFW并把离屏相机 / qpos **推到 Rerun**。与「两个进程各跑一套仿真」无关:仍是 **单一 `env`/单一仿真循环**。**不能**与 `--lerobot-record` 共用。
- **`--viewer viser`**Viser浏览器三维面板另一种自带前端
- **`--viewer rerun_viser`****同一进程、单一仿真**,同时在浏览器里打开 **Rerun**`--rerun-web-port` / `--rerun-grpc-port`)与 **Viser mjlab 面板**`--viser-port`)。三者各占不同端口;适合 RoboHub 左 Rerun、右 Mujoco 双 iframe。
- **注意**`rerun_native` 里的 **native 是 GLFW 桌面窗口,不占用 HTTP 端口**;若你要「两个端口都是网页服务」,用 **`rerun_viser`**,不要用 `rerun_native` 来凑端口。
`rerun_native` 示例(端口与 `rerun` 相同,见下节 SSH 转发):
```bash
uv run play Mjlab-Skater-Flat-Unitree-G1 --checkpoint_file ckpts/test.pt \
--viewer rerun_native --rerun-web-port 18080 --rerun-grpc-port 19876
```
`rerun_viser` 示例(**三个端口**Rerun Web、Rerun gRPC、Viser互不重复
```bash
uv run play Mjlab-Skater-Flat-Unitree-G1 --checkpoint_file ckpts/test.pt \
--viewer rerun_viser \
--rerun-web-port 18080 \
--rerun-grpc-port 19876 \
--viser-port 19090
```
远程浏览器需 **三个** 本地转发(把示例端口换成你实际用的):
```bash
ssh -N \
-L 18080:127.0.0.1:18080 \
-L 19876:127.0.0.1:19876 \
-L 19090:127.0.0.1:19090 \
user@云主机
```
**SSH / 无桌面 / RoboHub 技能里 `RuntimeError: … DISPLAY`**
`rerun_native` 里的「自带 viewer」是 **本机 X11/Wayland 上的 GLFW 窗口**,不是 Rerun 网页。若 shell 里 **没有** `DISPLAY``WAYLAND_DISPLAY`(很多容器/编排默认不传),会报错。处理方式:
- **只想要浏览器里看 Rerun**(单后端、无 MuJoCo 小窗):用 `--viewer rerun`
- **仍要 `rerun_native` 但机器无物理桌面**:可装 `xvfb` 用虚拟显示,例如:
`xvfb-run -a uv run play Mjlab-Skater-Flat-Unitree-G1 ... --viewer rerun_native`
(具体以你镜像是否已含 `xvfb` 为准。)
- **RoboHub 侧**:需在技能/容器环境注入 `DISPLAY` 或把启动命令包在 `xvfb-run` 里,否则与本地终端直跑表现一致。
完整参数:
```bash
uv run play Mjlab-Skater-Flat-Unitree-G1 --help
```
### 无头 OpenGLMuJoCo 离屏相机)
在无 `DISPLAY` / `WAYLAND_DISPLAY` 的 Linux 上,`play` 等在 **`import mujoco` 之前** 调用 `mujlab_husky/mujoco_gl.py`:未设置 `MUJOCO_GL` 时默认 **`osmesa`**。仅设 `MUJOCO_GL` 不够:无头时 PyOpenGL 仍可能按 `linux`**GLX**,导致 `glGetError` / `eglQueryString`;因此脚本会同步设置 **`PYOPENGL_PLATFORM=osmesa`**(或在你使用 `MUJOCO_GL=egl` 时为 **`egl`**)。可按需手动指定:
```bash
export MUJOCO_GL=egl # GPU + 可用 NVIDIA EGL 时(更快)
# 未设置时由 mujoco_gl 默认 osmesa或显式 CPU 光栅:
export MUJOCO_GL=osmesa # 需系统已装 libosmesa6见下
```
**UbuntuOSMesa**:若仍报 OpenGL / `glGetError`,请先安装运行时:
```bash
sudo apt-get update && sudo apt-get install -y libosmesa6
```
若报错 **`mjENBL_MULTICCD`**:来自 **MuJoCo Python 枚举与 `mujoco-warp` Git 修订不一致**。本项目用 PyPI `mujoco==3.8.x` 时,`uv.lock` 已将 **`mujoco-warp` 固定为上游标签 `v3.8.0`**;若在别处自行 `uv lock --upgrade-package mjlab`,需再次确认锁里两处一致。
### Rerun端口与远程浏览器
Rerun 需要 **两个端口****Web**(默认 `8080`+ **gRPC**(默认多为 `9876`,以终端打印为准)。
**浏览器与 `play` 在同一台机器**:直接打开终端里 **`http://127.0.0.1:<web_port>/?url=...`** 完整链接(不要只打开无 `?url=` 的首页)。
**浏览器在自己电脑、`play` 在云主机**:必须在本机做 **SSH 双端口转发**(把 `user@host` 换成你的登录方式,端口与 `play` 一致):
```bash
ssh -N -L 8080:127.0.0.1:8080 -L 9876:127.0.0.1:9876 user@云主机IP
```
若使用 `~/.ssh/config` 里的 `Host` 别名(例如 `Seoul`
```bash
ssh -N -L 8080:127.0.0.1:8080 -L 9876:127.0.0.1:9876 Seoul
```
指定密钥时:
```bash
ssh -i ~/.ssh/你的_key -N -L 8080:127.0.0.1:8080 -L 9876:127.0.0.1:9876 ubuntu@云主机IP
```
**本机 8080/9876 已被占用**时,改用空闲本地端口,并同时改 `?url=` 里 gRPC 端口,例如:
```bash
ssh -N -L 18080:127.0.0.1:18080 -L 19876:127.0.0.1:19876 user@云主机IP
```
云主机上 `play` 需一致:
```bash
uv run play Mjlab-Skater-Flat-Unitree-G1 --checkpoint_file ckpts/test.pt \
--viewer rerun \
--rerun-web-port 18080 \
--rerun-grpc-port 19876
```
**不经 SSH、浏览器直连公网**:安全组放行 Web + gRPC 端口,并指定(示例):
```bash
uv run play ... --viewer rerun --rerun-connect-host <云主机公网IP>
```
### Rerun 常用性能参数(可选)
```bash
uv run play Mjlab-Skater-Flat-Unitree-G1 --checkpoint_file ckpts/test.pt \
--viewer rerun \
--rerun-viewer-width 640 --rerun-viewer-height 360 \
--rerun-camera-log-stride 4 --rerun-qpos-log-stride 8 \
--rerun-camera-max-side 480 \
--no-rerun-open-browser
```
说明:本项目 CLI 使用 **tyro**,布尔开关一般为 **`--xxx` / `--no-xxx`**(例如 `--lerobot-record`、`--no-rerun-open-browser`),不要写成 `--lerobot-record True`
---
## LeRobot v3 数据(`lerobot_data/`
LeRobot **v3****Parquet + `meta/`**(不是 HDF5。本仓库提供两种方式写入 **`observation.state`qposfloat32 向量)**。
### 1离线批量导出不跑 Rerun
需已 `uv pip install lerobot`
```bash
uv run python -m mjlab_husky.scripts.export_lerobot_qpos \
--task-id Mjlab-Skater-Flat-Unitree-G1 \
--checkpoint-file ckpts/test.pt \
--out-dir lerobot_data \
--dataset-name mjlab_husky_skater_qpos \
--episodes 1 \
--steps-per-episode 1000 \
--overwrite
```
### 2`play` + Rerun 同时边播边录
```bash
uv run play Mjlab-Skater-Flat-Unitree-G1 \
--checkpoint_file ckpts/test.pt \
--viewer rerun \
--rerun-web-port 18080 \
--rerun-grpc-port 19876 \
--lerobot-record \
--lerobot-out-dir lerobot_data \
--lerobot-dataset-name mjlab_husky_live \
--lerobot-overwrite
```
要点:
- **`--lerobot-overwrite`**:每次启动会 **删除** 同名数据集目录;要 **累积** 多次运行,请 **去掉** 该参数,或换 `--lerobot-dataset-name`
- 默认每录满 **`--lerobot-steps-per-episode`**(默认 1000帧会 `save_episode()` 一次;仿真里多次 `reset` **不会**自动切分,除非打开 **`--lerobot-save-on-env-reset`**。
- 退出 `play`(如 Ctrl+C时会 `finalize()`,避免 Parquet 不完整。
按仿真每次 `done -> reset` 存成一个 LeRobot episode
```bash
uv run play Mjlab-Skater-Flat-Unitree-G1 ... --lerobot-record --lerobot-save-on-env-reset
```
### 检查数据集是否可读(行数 / episode
```bash
uv run python -c "
from pathlib import Path
import json
info = json.loads(Path('lerobot_data/mjlab_husky_live/meta/info.json').read_text())
print('total_episodes', info.get('total_episodes'), 'total_frames', info.get('total_frames'))
"
```
---
## Docker推荐
基础环境Ubuntu 22.04、CUDA 13、`uv` 与项目依赖。镜像 **`MUJOCO_GL=egl`**,默认 **`CMD`** 为 **Rerun** 回放(`--no-rerun-open-browser`)。
**构建**
```bash
docker build -t husky-skate:latest .
```
**GPU 运行**(需 [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html)
```bash
docker run --gpus all -it --rm -p 8080:8080 -p 9876:9876 husky-skate:latest
```
在**宿主机浏览器**打开容器日志里打印的 **`http://127.0.0.1:8080/?url=...`**(若浏览器不在宿主机,需自行把对应端口转发到本机)。
**宿主机 8080/9876 已被占用**(例如已有其他容器映射):换主机端口 + 覆盖容器内 `play` 端口,例如:
```bash
docker run --gpus all -it --rm -p 18080:18080 -p 19876:19876 husky-skate:latest \
uv run play Mjlab-Skater-Flat-Unitree-G1 --checkpoint_file ckpts/test.pt \
--viewer rerun \
--rerun-web-port 18080 \
--rerun-grpc-port 19876 \
--no-rerun-open-browser
```
**仅 CPU**(较慢)
```bash
docker run -it --rm -p 8080:8080 -p 9876:9876 husky-skate:latest
```
**进入容器 Shell**
```bash
docker run --gpus all -it --rm --entrypoint /bin/bash husky-skate:latest
```
**容器内训练**
```bash
docker run --gpus all -it --rm husky-skate:latest \
uv run train Mjlab-Skater-Flat-Unitree-G1 --env.scene.num-envs 4096
```
**(可选)容器内录 LeRobot**:需先安装 `lerobot`,并把目录挂载出来,例如:
```bash
docker run --gpus all -it --rm \
-p 18080:18080 -p 19876:19876 \
-v "$(pwd)/lerobot_data:/app/lerobot_data" \
husky-skate:latest \
bash -lc 'uv pip install lerobot && uv run play Mjlab-Skater-Flat-Unitree-G1 \
--checkpoint_file ckpts/test.pt --viewer rerun \
--rerun-web-port 18080 --rerun-grpc-port 19876 --no-rerun-open-browser \
--lerobot-record --lerobot-out-dir lerobot_data --lerobot-dataset-name mjlab_docker_live \
--lerobot-overwrite'
```
---
## PyTorch / CUDA 提示
若日志出现 **driver too old如 12080**`torch.cuda.is_available()``False`,多为 **PyTorch cu13x 与当前驱动 API 不匹配**。可选:
- 安装与驱动匹配的 **cu12x** 轮子,例如:
`uv pip install torch torchvision --index-url https://download.pytorch.org/whl/cu124`
- 或升级宿主机 NVIDIA 驱动以匹配当前 PyTorch 所要求的 CUDA。
仿真侧 **Warp/MuJoCo** 仍可能显示 `cpu`,与 **`torch.cuda.is_available()``play` 选的 device** 一致。
---
## 轻量 MuJoCo 评测
```bash
bash test_scene/sim.sh your-onnx-path
```
| Viser | MuJoCo |
|-------|--------|
| ![](media/viser.gif) | ![](media/mjc.gif) |
---
## 论文引用(原论文)
```bibtex
@article{han2026husky,
title={HUSKY: Humanoid Skateboarding System via Physics-Aware Whole-Body Control},
author={Jinrui Han and Dewei Wang and Chenyun Zhang and Xinzhe Liu and Ping Luo and Chenjia Bai and Xuelong Li},
journal={arXiv preprint arXiv:2602.03205},
year={2026}
}
```