# RDK X5 BPU 部署测试

这个目录是 RobotLab BPU `.bin` 的隔离部署路径，不覆盖现有 ONNX/fastcpp
部署脚本。

当前包含：

- `bpu_policy.py`：BPU policy wrapper，默认使用 `cpp_dnn_api_x5` C++ DNN API 后端。
- `cpp/`：C++ DNN API 推理库源码、板端编译脚本和纯 C++ benchmark。
- `deploy_go1_robotlab_bpu_x5_fastcpp.py`：基于现有 `lab_fastcpp` 状态机的 BPU 版本。

## 重要限制

不要用 `hobot_dnn.pyeasy_dnn` 直接跑这个模型。这个 BPU 模型的输入是
`featuremap`，板端实测 `pyeasy_dnn.forward()` 会产生明显错误的 action，
和 `hrt_model_exec infer` 不一致。

当前默认不再使用 `bpu_infer_lib` 做实机推理，而是用 C++ 直接调用 DNN API。
部署脚本使用的 C++ 调用顺序是：

```bash
hbDNNInitializeFromFiles -> hbDNNGetModelHandle -> hbDNNInfer -> hbDNNWaitTaskDone -> hbDNNReleaseTask
```

这个路径已经用 `00000.bin` 验证，输出和 `hrt_model_exec infer` 对齐。

`bpu_infer_lib.forward(False)` 在当前板端会从 C runtime 向 stdout 每帧打印
`duplicate model infer is not supported in one batch` / `invalid model`。
虽然输出和 `hrt_model_exec infer` 一致，但这说明 task 提交方式不干净。旧 Python
fallback 保留为 `BpuInferLibPythonPolicy`，只用于对照，不作为默认部署路径。

这个判断参考 D-Robotics RDK X5 runtime sample：

- `03_misc/run_resnet50_feature.sh` 是官方 featuremap 输入模型示例，流程是
  prepare feature tensor -> infer success -> task done。
- 性能测量示例在循环中每帧执行 `hbDNNInfer` 后，立刻
  `hbDNNWaitTaskDone(task_handle, 0)`，再 `hbDNNReleaseTask(task_handle)` 并把
  task handle 置空。

`bpu_infer_lib` 的 Python API 没有直接暴露 `hbDNNReleaseTask`，所以这里改成
C++ shared library，并由 Python 通过 `ctypes` 调用。

板端编译：

```bash
cd /root/go1_pro_deploy/deploy_45dim_rl_gym/bpu_deploy_x5/cpp
bash build_board.sh
```

## 模型路径

默认模型：

```text
deploy_45dim_rl_gym/bpu_quantization/mapper_output_6500_gemm/policy_robotlab_6500_int16_gemm.bin
```

输入输出：

- 输入：`obs_4d [1, 1, 1, 450]`，float32 featuremap
- 输出：`actions [1, 12, 1, 1]`，float32，脚本会 flatten 成 12 维 action

## 板端准备

同步仓库和模型后，在板端确认：

```bash
cd /root/go1_pro_deploy
ls deploy_45dim_rl_gym/bpu_quantization/mapper_output_6500_gemm/policy_robotlab_6500_int16_gemm.bin
ls deploy_45dim_rl_gym/bpu_quantization/calibration_data/00000.bin
ls deploy_45dim_rl_gym/bpu_deploy_x5/cpp/libbpu_dnn_policy.so
```

如果 `mapper_output_6500_gemm/` 没有同步到 git，需要手动把 `.bin` 放到对应路径，
或用 `--bpu-model` 指定绝对路径。

## 纯离线 BPU 自检

先不连接机器人，确认 C++ BPU 后端输出和 `hrt_model_exec infer` 的参考值一致：

```bash
cd /root/go1_pro_deploy
PYTHONPATH=/root/go1_pro_deploy \
python3 deploy_45dim_rl_gym/bpu_deploy_x5/test_bpu_policy.py \
  --check-reference-00000 \
  --repeat 1000
```

通过时应看到：

```text
reference_max_abs_diff 0.0
```

当前板端 `root@192.168.150.167` 已验证：

```text
reference_max_abs_diff 4.76837158203125e-07
reference_mean_abs_diff 3.071812386679085e-07
repeat=1000 avg_ms=1.019592  # Python ctypes -> C++ DNN API
duplicate_errors=0
```

纯 C++ benchmark：

```bash
cd /root/go1_pro_deploy/deploy_45dim_rl_gym/bpu_deploy_x5/cpp
./bpu_dnn_bench
```

当前板端结果：

```text
reference_max_abs_diff 0
repeat=1000 cpp_avg_ms=0.711932
duplicate_errors=0
```

## 离线推理检查

先不要接电机控制，只运行 BPU inference：

```bash
cd /root/go1_pro_deploy
PYTHONPATH=/root/go1_pro_sdk:/root/go1_pro_deploy \
python3 deploy_45dim_rl_gym/bpu_deploy_x5/deploy_go1_robotlab_bpu_x5_fastcpp.py \
  --infer-check \
  --log-dir logs \
  --print-every 50 \
  --max-steps 500
```

这一步仍会连接 MCU 读取状态，但不会发送电机指令。

## 悬空状态机测试

只有 `--infer-check` 日志确认 action 正常后，再悬空测试状态机。先不加
`--enable-rl`，R2 只能走到 `INFER_TEST`，不会进入 RL 控制：

```bash
cd /root/go1_pro_deploy
PYTHONPATH=/root/go1_pro_sdk:/root/go1_pro_deploy \
python3 deploy_45dim_rl_gym/bpu_deploy_x5/deploy_go1_robotlab_bpu_x5_fastcpp.py \
  --kill-sport \
  --log-dir logs \
  --kp 28 --kd 0.7 \
  --kp-cal 20 --kd-cal 1.0 \
  --power-factor 7 \
  --position-protect-limit 0.0 \
  --action-clip 5.0 \
  --action-trip-limit 8.0 \
  --action-hard-trip-limit 16.0 \
  --max-target-step 0.025 \
  --max-roll-deg 35 \
  --max-pitch-deg 35 \
  --swap-vy-yaw \
  --rc-vx-scale 0.5 \
  --rc-vy-scale 0.5 \
  --rc-wz-scale 1.0
```

确认 `OBS_TEST` 和 `INFER_TEST` 正常后，才允许加 `--enable-rl` 做悬空 RL：

```bash
cd /root/go1_pro_deploy
PYTHONPATH=/root/go1_pro_sdk:/root/go1_pro_deploy \
python3 deploy_45dim_rl_gym/bpu_deploy_x5/deploy_go1_robotlab_bpu_x5_fastcpp.py \
  --kill-sport \
  --enable-rl \
  --log-dir logs \
  --kp 28 --kd 0.7 \
  --kp-cal 20 --kd-cal 1.0 \
  --power-factor 7 \
  --position-protect-limit 0.0 \
  --action-clip 5.0 \
  --action-trip-limit 8.0 \
  --action-hard-trip-limit 16.0 \
  --max-target-step 0.025 \
  --max-roll-deg 35 \
  --max-pitch-deg 35 \
  --swap-vy-yaw \
  --rc-vx-scale 0.5 \
  --rc-vy-scale 0.5 \
  --rc-wz-scale 1.0
```

地面测试不要直接从 BPU 版本开始；先用同参数 ONNX 版本确认行为，再做 BPU/ONNX
对照。
