Add Wall-X serving and Turtle2 TCP WebSocket bridge
Pre-commit / pre-commit (push) Canceled after 0s

This commit is contained in:
2026-09-23 21:04:17 +08:00
parent 6764e8f12f
commit d1cc7d96ad
40 changed files with 8591 additions and 40 deletions
+84
View File
@@ -0,0 +1,84 @@
# Wall-X 重新训练后部署到 Turtle2:完整迁移流程
本流程对应 `/home/xiehaolv/huanghuagui/zhanyifeng/wall-x` 的当前 serving 与 TCP/WebSocket 桥接代码。当前已验收的目标 checkpoint 是 `/home/xiehaolv/huanghuagui/wall-x-model/finetuned/1`。实际启动命令见 [TURTLE2_STARTUP.md](TURTLE2_STARTUP.md)。训练侧的 `config.yml` 是训练快照,部署时保留原件;推理参数改在启动命令或部署代码中。
## 一、先判断这次究竟改变了什么
| 训练变化 | 部署时必须核对或修改 |
| --- | --- |
| 只改学习率、batch size、epoch、随机种子,数据格式和动作定义不变 | 更换 checkpoint 路径及其同目录 `config.yml`;核对 LoRA 参数、归一化文件和实际推理结果。桥接接口通常不变。 |
| 换数据集,但仍为三路相机、右臂 7D 原始状态/动作 | 更新训练配置中的数据根目录、`repo_id`、`norm_stats_path`、任务文本及相机 key mapping;部署使用新 checkpoint 自带的 normalizer,并更新 serving 的 `norm-key` 与任务文本。 |
| 相机数量、名称、顺序或实际安装位置变化 | 更新训练数据的相机映射与 serving `cam-names`;核对机器人发图顺序及桥接 `camera_left`/`camera_front`/`camera_right` 的物理对应。先做逐路图像检查,不要直接执行动作。 |
| `action_horizon_flow` 变化 | serving 和桥接两处 `--action-horizon` 都改为新值;重新计算动作裁剪与插值后的包长,并运行协议检查。启动脚本现会拒绝与训练配置不一致的 serving 长度。 |
| 绝对/相对动作、欧拉角/6D 旋转、左右臂、关节/末端、夹爪范围变化 | 训练配置、归一化、serving 的动作重建、桥接的 7D `follow{1,2}_pos` 协议都要重新验收。不能只替换权重路径。 |
| LoRA 的 rank、alpha、`use_rslora` 或目标模块变化 | 从训练服务器导出实际使用的 LoRA JSON 为 checkpoint 内的 `lora_config.json`;加载器依据 rank 和 alpha 计算合并系数。若使用逐层不同缩放,当前加载器会拒绝,需实现并测试后才能部署。 |
## 二、训练前检查数据和配置
1. 保留一份原始 LeRobot v3 数据。当前训练配置指向 LeRobot v2.1 数据目录;继续使用同一训练环境时,先生成其可读取的 v2.1 训练副本,不要把 v3 目录直接写成 v2.1 路径。
2. 核对每条 episode 的三路视频能解码、帧数与 `observation.state`/`action` 对齐,并剔除明显不合格的示教。当前物理映射是 camera1 左臂固定视角、camera2 面部视角、camera3 右臂视角。
3. 当前训练 key mapping 为:`observation.images.faceImg → face_view`,`observation.images.leftImg → left_wrist_view`,`observation.images.rightImg → right_wrist_view`,`observation.state → state`,`action → action`。换数据集后按**新数据的真实字段**更新;字段名相同并不能证明镜头位置相同。
4. 确认机器人状态和示教动作的坐标系、单位、夹爪开合方向相同。当前模型训练右臂,训练数据原始状态/动作为 7D;当前配置在训练加载时把欧拉角转换为 6D,并把动作转为相对当前末端的表示,最终形成“位置 3+旋转 6+夹爪 1+填充 16”的 26D 布局。
5. 在训练服务器上更新 `data.lerobot_config.root`、`repo_id`、`data.norm_stats_path`、`data.key_mappings.camera`、图像分辨率、`task.action_horizon` 和 `task.action_horizon_flow`。如果只改优化超参数,仍核对保存出的 `config.yml` 这些字段未意外变化。
6. `norm_stats.json` 与 normalizer 必须由**这次训练所用的数据和配置**生成。当前 6D 配置部署时优先读取 checkpoint 内的 `normalizer_action.pth` 与 `normalizer_propri.pth`;不要沿用上一模型的两个 `.pth`。
7. 保存训练实际使用的 LoRA JSON,记录 `lora_r`、`lora_alpha`、`use_rslora` 和目标模块。不要只保存配置文件的绝对路径,训练服务器路径到部署服务器通常不可达。
## 三、把 checkpoint 导出到部署服务器
为每次训练创建独立目录,例如 `/home/xiehaolv/huanghuagui/wall-x-model/finetuned/<新版本>`。不要覆盖正在部署的 checkpoint。至少保留:
```text
model.safetensors # 或受加载器支持的 pytorch_model_fsdp.bin
config.yml # 对应这次训练的原始配置
config.json # 模型结构
preprocessor_config.json
tokenizer.json
tokenizer_config.json
vocab.json # 若本次 tokenizer 导出包含该文件
normalizer_action.pth
normalizer_propri.pth
lora_config.json # 从这次训练实际使用的 LoRA JSON 原样复制
```
`norm_stats.json`、`global_step.pth` 可一并保留,便于审计。`optimizer.pt`、`scheduler.pt`、`rng_state.pt` 不参与推理加载,可以不传到部署服务器。若训练保存的是仅含 LoRA adapter 的轻量文件,而不是该项目预期的完整 checkpoint,当前 `run_serving.sh` 不能直接当完整模型加载;先按训练代码的导出流程补齐基础权重。
当前 checkpoint `1` 具有完整 `model.safetensors`、配置、processor 和 normalizer,但**缺少训练原始 `lora_config.json`**。部署代码会兼容旧模型,警告后暂按 `alpha/r=2` 合并。其 LoRA 权重 rank 为 16;只有核对训练原始 JSON 的 alpha 为 32 且 `use_rslora=false`,才能确认这个系数。若原始 JSON 不在手,不要把示例配置当作训练凭据。
## 四、部署前静态核对
在部署服务器进入仓库目录:
```bash
cd /home/xiehaolv/huanghuagui/zhanyifeng/wall-x
export WALLX_TEST_CHECKPOINT=/home/xiehaolv/huanghuagui/wall-x-model/finetuned/1
export WALLX_TEST_PYTHON=/home/xiehaolv/huanghuagui/conda-envs/wallox_0.5/bin/python
PYTHONDONTWRITEBYTECODE=1 "$WALLX_TEST_PYTHON" -m pytest -q \
tests/test_lora_scale.py \
tests/test_tcp_ws_bridge.py \
tests/test_run_serving_contract.py \
tests/test_turtle2_inference_input.py
```
这些测试当前以 checkpoint `1` 的 32 步、三相机布局为基准;换成动作长度、相机数或特征布局不同的 checkpoint 时,应先更新相应测试的期望值,再运行。即使测试通过,也要继续做一次不发送动作的真实模型推理,因为测试不会证明新权重本身能完成抓取任务。
核对 `config.yml` 的 `task.dof_config`、`task.agent_pos_config`、`task.action_horizon_flow`、`data.key_mappings.camera` 和 `data.lerobot_config.repo_id`。将 serving 的 `--model-config.norm-key` 设置为 checkpoint 内 normalizer 的数据集键。当前键为 `pick_paper_lerobot_v21_3cam`;如果新 checkpoint 的键变了,要同步修改启动命令。
## 五、更新启动命令与不发送动作的推理
在 [TURTLE2_STARTUP.md](TURTLE2_STARTUP.md) 中将 `--checkpoint-path` 与 `--train-config-path` 都指向新目录;将服务端、桥接端的 `--action-horizon` 设为训练的 `task.action_horizon_flow`;相机名称、`norm-key`、任务指令同步为新训练实际值。保持 `--serialize-actions`。桥接端只接受序列化的 `follow2_pos`;它会拒绝缺少该字段的原始 `predict_action`,避免按旧布局误读填充维。
先启动 serving,观察 LoRA 合并日志和 `load_state_dict result: <All keys matched successfully>`。当前模型可能打印“词嵌入表被裁剪”和“checkpoint 内的 normalizer 参数未直接用作模型权重”:它们分别来自当前流式动作 tokenizer 与单独加载的 normalizer;需要关注是否还有其他非预期未匹配权重。若 LoRA scale 出现缺少 metadata 的警告,先核对上一步的训练 JSON。
然后启动**不带** `--allow-send` 的桥接端,在 `arm-pc` 以单包模式发送真实相机和状态。核对三路画面朝向、日志中的 `recv state`、serving 返回行数、桥接的 `predicted follow2 T=<插值后长度>`、右臂首尾目标及夹爪范围。对于当前 32 步、`action-end-ratio=0.2`、插值倍数 32,桥接预期返回 192 点。模型推理可用不等于动作方向正确,现场仍须验证坐标与夹爪符号。
## 六、单包真机与连续执行
单包时停止 dry-run 桥接进程,按启动页相同命令增加 `--allow-send`,保留 `--max-action-cycles 1`、`--require-right-feedback`、`--clip-action-delta` 和当前小幅位置/旋转限制。现场人员确认机器人周围无障碍、右臂控制器已使能、升降柱目标高度合适,能即时急停。观察 `/follow2_pos_back` 与 `/joint_information2`,并核对夹爪开合方向与物体接触情况。
单包结果符合预期后,才把 `--max-action-cycles` 改为 `0` 进入连续推理;`0` 意味着不限动作包数。当前桥接的反馈检查只验证右臂末端是否发生运动,**不提供可靠的物品滑脱检测或有限次数自动重抓**。如果任务需要这些能力,应单独设计感知判定和执行状态机,而不能把 `max-action-cycles` 当作重抓次数。
停止顺序:机器人端先退出,再停止桥接端和 serving。保留上一版 checkpoint 与其匹配的启动命令作为回退入口;回退必须同时恢复权重、训练配置、动作长度、相机和 normalizer 参数,不能只切换 `model.safetensors`。
## 七、当前验证范围
在部署服务器 GPU 1 上,checkpoint `1` 已完成载入,日志显示 72 组 LoRA 合并和 `<All keys matched successfully>`。三路 448×448 合成图像已通过完整回环:TCP 状态/图像输入 → WebSocket serving → Turtle 动作序列化 → TCP 动作回传;返回包含 `follow1_pos`、`follow2_pos`、`head_pos`、`lift`、`car_pose`,右臂轨迹为 192 点,左臂 192 点均保持输入位姿。另有 12 项回归测试通过。三路 448×448 图像此前触发的 1024 token 截断已修复为推理时保留完整图像 token。回环只把动作发给本机合成客户端,没有连接或驱动机器人。真实相机内容、抓取效果、右臂执行方向、夹爪范围和训练原始 LoRA alpha 仍需要现场与训练产物确认。