真机推理部署
当前 KMD 真机链路由三个进程组成:机器人端运行 vlahost,GPU 服务器运行 OpenPI 策略服务器和推理客户端。机器人端只负责提供状态、相机画面和动作接口,不需要安装完整的 OpenPI 训练环境。
部署架构
机器人(ROS 2) GPU 服务器
┌─────────────────────┐ GET /state ┌──────────────────────────┐
│ vlahost │ ◄───────────── │ OpenPI 推理客户端 │
│ - 关节与末端状态 │ 状态 + 图像 │ - 组装观测与语言指令 │
│ - 四宫格相机图像 │ ─────────────► │ - 调用策略服务器 │
│ - 动作话题发布 │ POST /action │ - 下发关节动作 │
└─────────────────────┘ ◄───────────── └────────────┬─────────────┘
│ WebSocket
┌─────────────▼─────────────┐
│ OpenPI 策略服务器 │
│ 加载 checkpoint 并推理 │
└───────────────────────────┘
数据接口
当前部署适配以下数据格式:
- 三路相机:
cam_high、cam_left_wrist、cam_right_wrist。 - 16 维关节状态:
[左臂 7 关节, 左夹爪, 右臂 7 关节, 右夹爪]。 - 16 维关节动作:维度和顺序与关节状态一致。
- 模型内部关节角使用角度制,机器人 ROS 反馈和动作使用弧度制,客户端负责单位转换。
vlahost 从四宫格图像中默认取用以下区域:
| 四宫格区域 | 模型相机字段 |
|---|---|
| 右上 | cam_left_wrist |
| 左下 | cam_right_wrist |
| 右下 | cam_high |
| 左上 | 忽略 |
如果实际相机排列不同,需要在推理客户端中调整映射或裁剪参数。
GET /state 响应
vlahost 将 ROS 2 话题中的最新状态和 JPEG 图像编码为 JSON:
{
"stamp": 123456789,
"joint_states": {
"positions": ["14 joint values"],
"velocities": ["14 joint values"],
"efforts": ["14 joint values"],
"est_joint_force": ["14 joint values"]
},
"eef_left": {
"position": {"x": 0, "y": 0, "z": 0},
"orientation": {"x": 0, "y": 0, "z": 0, "w": 1}
},
"eef_right": {
"position": {"x": 0, "y": 0, "z": 0},
"orientation": {"x": 0, "y": 0, "z": 0, "w": 1}
},
"quad_image": {"format": "jpeg", "data": "<base64>"}
}
POST /action 请求
EEF 控制请求格式:
{
"eef_left": [0, 0, 0, 0, 0, 0],
"eef_right": [0, 0, 0, 0, 0, 0],
"gripper_left": 0.0,
"gripper_right": 0.0
}
16 维关节空间 checkpoint 使用:
{
"joint_actions": ["16 joint action values in radians"]
}
当前 openpi-kmd 客户端会发送 joint_actions,两个项目的 README 也定义了该字段;但本次下载的 vlahost/vlahost/server.py 中 ActionRequest 仍只包含 EEF 与夹爪字段。正式使用 16 维关节动作前,请确认部署的 vlahost 版本已经实现 joint_actions 的解析和机器人控制话题发布。
1. 在机器人端安装 vlahost
机器人端需要 ROS 2、FastAPI,并能够收到机器人状态与相机话题:
git clone https://github.com/KLMmotion/vlahost.git
ln -s /path/to/vlahost ~/ros_ws/src/vlahost
cd ~/ros_ws
colcon build --packages-select vlahost
source install/setup.bash
vlahost 默认订阅:
| 话题 | 类型 | 内容 |
|---|---|---|
/info/joint_feedback | marvin_msgs/Jointfeedback | 双臂关节反馈 |
/info/eef_left | geometry_msgs/PoseStamped | 左末端位姿 |
/info/eef_right | geometry_msgs/PoseStamped | 右末端位姿 |
quad_tile/compressed | sensor_msgs/CompressedImage | 四宫格相机 JPEG 图像 |
EEF 控制模式下,vlahost 默认发布:
| 话题 | 类型 | 内容 |
|---|---|---|
/control/target_poseL_model | geometry_msgs/PoseStamped | 左末端目标位姿 |
/control/target_poseR_model | geometry_msgs/PoseStamped | 右末端目标位姿 |
control/gripperValueL | std_msgs/Float32 | 左夹爪目标值 |
control/gripperValueR | std_msgs/Float32 | 右夹爪目标值 |
control/eef_constraint | std_msgs/Int16MultiArray | 末端约束参数 |
2. 启动机器人端服务
source ~/ros_ws/install/setup.bash
ros2 launch vlahost vlahost_server.launch.py host:=0.0.0.0 port:=8000
服务提供以下 HTTP 接口:
| 接口 | 用途 |
|---|---|
GET / | 浏览器调试页和实时相机预览 |
GET /health | 服务健康检查 |
GET /state | 获取关节、末端状态和四宫格图像 |
POST /action | 下发 EEF 或 16 维关节动作 |
在 GPU 服务器或同一局域网内的电脑访问:
http://<ROBOT_HOST>:8000/health
返回正常后再启动策略服务器和推理客户端。
3. 启动策略服务器
GPU 服务器需准备训练完成的 checkpoint,并确认其中包含:
<checkpoint_step>/model.safetensors
<checkpoint_step>/assets/<asset_id>/norm_stats.json
从 openpi-kmd 根目录启动:
uv run scripts/serve_policy_kmd_joint.py \
--checkpoint-dir /ABS/PATH/TO/CHECKPOINT_STEP \
--repo-id <dataset_id> \
--asset-id <asset_id> \
--port 8000
--repo-id 和 --asset-id 通常填写训练数据集使用的 ID;--asset-id 必须与 checkpoint 中归一化统计目录一致。策略服务器监听 0.0.0.0:8000。
4. 启动推理客户端
在能够同时访问机器人端 vlahost 和策略服务器的 GPU 服务器上执行:
uv run python vla_helpers/openpi_client_policy_http_kmd_joint.py \
--robot-server-url http://<ROBOT_HOST>:8000 \
--policy-host localhost \
--policy-port 8000 \
--task-prompt "pick and place"