diff --git a/.gitignore b/.gitignore index 6e37921..204e62b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ deploy_45dim_rl_gym/bpu_quantization/calibration_data/ deploy_45dim_rl_gym/bpu_quantization/calibration_data_fast*/ deploy_45dim_rl_gym/bpu_quantization/calibration_data_*_gym_fast*/ deploy_45dim_rl_gym/bpu_quantization/calibration_data_*_gym_fast*_metadata.json +deploy_45dim_rl_gym/bpu_quantization/calibration_data_*_robotlab_fast*/ +deploy_45dim_rl_gym/bpu_quantization/calibration_data_*_robotlab_fast*_metadata.json deploy_45dim_rl_gym/bpu_quantization/mapper_output/ deploy_45dim_rl_gym/bpu_quantization/mapper_output_gemm/ deploy_45dim_rl_gym/bpu_quantization/mapper_output_*_gemm/ @@ -16,6 +18,7 @@ deploy_45dim_rl_gym/bpu_quantization/policy_[0-9]*_actions.onnx deploy_45dim_rl_gym/bpu_quantization/policy_[0-9]*_bpu4d.onnx deploy_45dim_rl_gym/bpu_quantization/policy_[0-9]*_bpu4d_gemm.onnx deploy_45dim_rl_gym/bpu_quantization/policy_[0-9]*_int16_gemm.yaml +deploy_45dim_rl_gym/bpu_quantization/policy_[0-9]*_int8_gemm.yaml deploy_45dim_rl_gym/bpu_quantization/policy_[0-9]*_opset11.onnx deploy_45dim_rl_gym/bpu_quantization/policy_robotlab_15000_bpu4d.onnx deploy_45dim_rl_gym/bpu_quantization/policy_robotlab_15000_bpu4d_gemm.onnx diff --git a/deploy_45dim_rl_gym/bpu_deploy_x5/README.md b/deploy_45dim_rl_gym/bpu_deploy_x5/README.md index 64ba1e3..dd5de79 100644 --- a/deploy_45dim_rl_gym/bpu_deploy_x5/README.md +++ b/deploy_45dim_rl_gym/bpu_deploy_x5/README.md @@ -7,7 +7,7 @@ - `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 版本。 +- `deploy_go1_robotlab_bpu_x5_fastcpp.py`:基于现有 `lab_fastcpp` 状态机的 BPU 版本,默认 26000。 ## 重要限制 @@ -52,7 +52,7 @@ bash build_board.sh 默认模型: ```text -deploy_45dim_rl_gym/bpu_quantization/mapper_output_6500_gemm/policy_robotlab_6500_int16_gemm.bin +deploy_45dim_rl_gym/bpu_quantization/mapper_output_26000_gemm/policy_robotlab_26000_int16_gemm.bin ``` 输入输出: @@ -66,12 +66,12 @@ deploy_45dim_rl_gym/bpu_quantization/mapper_output_6500_gemm/policy_robotlab_650 ```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/mapper_output_26000_gemm/policy_robotlab_26000_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` 放到对应路径, +如果 `mapper_output_26000_gemm/` 没有同步到 git,需要手动把 `.bin` 放到对应路径, 或用 `--bpu-model` 指定绝对路径。 ## 纯离线 BPU 自检 @@ -82,38 +82,32 @@ ls deploy_45dim_rl_gym/bpu_deploy_x5/cpp/libbpu_dnn_policy.so 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 \ + --bpu-model deploy_45dim_rl_gym/bpu_quantization/mapper_output_26000_gemm/policy_robotlab_26000_int16_gemm.bin \ + --input-bin deploy_45dim_rl_gym/bpu_quantization/calibration_data_26000_robotlab_fast64/00000.bin \ --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 +repeat=1000 avg_ms=... # Python ctypes -> C++ DNN API ``` 纯 C++ benchmark: ```bash cd /root/go1_pro_deploy/deploy_45dim_rl_gym/bpu_deploy_x5/cpp -./bpu_dnn_bench +./bpu_dnn_bench \ + /root/go1_pro_deploy/deploy_45dim_rl_gym/bpu_quantization/mapper_output_26000_gemm/policy_robotlab_26000_int16_gemm.bin \ + /root/go1_pro_deploy/deploy_45dim_rl_gym/bpu_quantization/calibration_data_26000_robotlab_fast64/00000.bin \ + 1000 ``` 当前板端结果: ```text -reference_max_abs_diff 0 -repeat=1000 cpp_avg_ms=0.711932 -duplicate_errors=0 +input_floats=450 output_floats=12 +repeat=1000 cpp_avg_ms=... ``` ## 离线推理检查 @@ -132,6 +126,18 @@ python3 deploy_45dim_rl_gym/bpu_deploy_x5/deploy_go1_robotlab_bpu_x5_fastcpp.py 这一步仍会连接 MCU 读取状态,但不会发送电机指令。 +如果要切回旧轮次: + +```bash +PYTHONPATH=/root/go1_pro_deploy \ +python3 deploy_45dim_rl_gym/bpu_deploy_x5/deploy_go1_robotlab_bpu_x5_fastcpp.py \ + --bpu-round 6500 + +PYTHONPATH=/root/go1_pro_deploy \ +python3 deploy_45dim_rl_gym/bpu_deploy_x5/deploy_go1_robotlab_bpu_x5_fastcpp.py \ + --bpu-round 15000 +``` + ## 悬空状态机测试 只有 `--infer-check` 日志确认 action 正常后,再悬空测试状态机。先不加 diff --git a/deploy_45dim_rl_gym/bpu_deploy_x5/deploy_go1_robotlab_bpu_x5_fastcpp.py b/deploy_45dim_rl_gym/bpu_deploy_x5/deploy_go1_robotlab_bpu_x5_fastcpp.py index ee67184..5fc94ff 100644 --- a/deploy_45dim_rl_gym/bpu_deploy_x5/deploy_go1_robotlab_bpu_x5_fastcpp.py +++ b/deploy_45dim_rl_gym/bpu_deploy_x5/deploy_go1_robotlab_bpu_x5_fastcpp.py @@ -5,7 +5,7 @@ Deploy the RoboGauge Go1 45-dim RobotLab BPU policy on Unitree Go1 PRO. This uses go1_pro_sdk direct MCU control, not LCM or the official Unitree SDK. Policy: - - policy_robotlab_6500_int16_gemm.bin + - policy_robotlab_26000_int16_gemm.bin by default - single-frame obs: 45 dims - BPU input: 10-frame history, 1x1x1x450 featuremap, stacked by observation terms - command scale: [1.0, 1.0, 1.0] @@ -66,10 +66,16 @@ except ImportError as exc: "PYTHONPATH=/root/go1_pro_sdk python3 setup.py build_ext --inplace" ) from exc -DEFAULT_BPU_MODEL = ( - HERE.parent / "bpu_quantization" / "mapper_output_6500_gemm" / - "policy_robotlab_6500_int16_gemm.bin" -) +BPU_MODEL_REGISTRY = { + "6500": HERE.parent / "bpu_quantization" / "mapper_output_6500_gemm" / + "policy_robotlab_6500_int16_gemm.bin", + "15000": HERE.parent / "bpu_quantization" / "mapper_output_gemm" / + "policy_robotlab_15000_int16_gemm.bin", + "26000": HERE.parent / "bpu_quantization" / "mapper_output_26000_gemm" / + "policy_robotlab_26000_int16_gemm.bin", +} +DEFAULT_BPU_ROUND = "26000" +DEFAULT_BPU_MODEL = BPU_MODEL_REGISTRY[DEFAULT_BPU_ROUND] LOWCMD_BACKEND = "cpp_lowcmd_cpp_lowstate" SPORT_KILL_CMD = ( 'ssh pi@192.168.123.161 "sudo pkill -9 -f keep_sport_alive; ' @@ -217,6 +223,38 @@ def validate_joint_order(): print(f" [{i:02d}] {sdk_name:4s} -> {policy_name:8s} default={q0:+.3f}") +def resolve_bpu_model(args): + if args.bpu_model: + return Path(args.bpu_model).expanduser().resolve() + key = str(args.bpu_round) + if key not in BPU_MODEL_REGISTRY: + choices = ", ".join(sorted(BPU_MODEL_REGISTRY)) + raise ValueError(f"Unknown --bpu-round {args.bpu_round!r}; choices: {choices}") + return BPU_MODEL_REGISTRY[key].expanduser().resolve() + + +def make_policy(args): + model_path = resolve_bpu_model(args) + policy = BpuInferLibPolicy( + model_path, + priority=args.bpu_priority, + bpu_cores=args.bpu_cores, + ) + if policy.input_size != POLICY_INPUT_DIM: + policy.close() + raise ValueError( + f"BPU model input has {policy.input_size} values, expected {POLICY_INPUT_DIM}. " + "Use a RobotLab 10-frame/450-dim .bin." + ) + if policy.output_size != NUM_ACTIONS: + policy.close() + raise ValueError( + f"BPU model output has {policy.output_size} values, expected exactly {NUM_ACTIONS}. " + "Compile an actions-only ONNX for deployment." + ) + return policy + + def apply_deadzone(value, deadzone): if deadzone <= 0.0: return float(value) @@ -346,7 +384,8 @@ class JsonlLogger: "num_obs": NUM_OBS, "history_len": HISTORY_LEN, "policy_backend": BpuInferLibPolicy.backend_name, - "bpu_model": str(Path(args.bpu_model).expanduser()), + "bpu_model": str(resolve_bpu_model(args)), + "bpu_round": args.bpu_round, "policy_input_dim": POLICY_INPUT_DIM, "bpu_input_shape": BPU_INPUT_SHAPE, "bpu_output_shape": BPU_OUTPUT_SHAPE, @@ -750,7 +789,7 @@ def run_infer_check(args): logger = JsonlLogger(args.log_dir, args) client = None try: - policy = BpuInferLibPolicy(args.bpu_model, priority=args.bpu_priority, bpu_cores=args.bpu_cores) + policy = make_policy(args) client, state = connect_client(args) obs_builder = ObsHistoryBuilder() cmd_filter = CommandFilter(args) @@ -845,7 +884,7 @@ def run_deploy(args): print(STARTUP_BANNER) input("Press Enter when ready...") - policy = BpuInferLibPolicy(args.bpu_model, priority=args.bpu_priority, bpu_cores=args.bpu_cores) + policy = make_policy(args) logger = JsonlLogger(args.log_dir, args) client = None state = None @@ -1162,8 +1201,11 @@ def run_deploy(args): def build_arg_parser(): parser = argparse.ArgumentParser(description="Deploy RoboGauge Go1 RobotLab BPU on Go1 PRO") - parser.add_argument("--bpu-model", default=str(DEFAULT_BPU_MODEL), - help="Path to policy_robotlab_6500_int16_gemm.bin") + parser.add_argument("--bpu-model", default="", + help="Path to a compiled RobotLab 10-frame BPU .bin; overrides --bpu-round") + parser.add_argument("--bpu-round", default=DEFAULT_BPU_ROUND, + choices=sorted(BPU_MODEL_REGISTRY), + help="Quick-select RobotLab BPU model round") parser.add_argument("--bpu-priority", type=int, default=0) parser.add_argument("--bpu-cores", type=int, nargs="+", default=[0], help="Reserved BPU core ids for future runtime scheduling") diff --git a/deploy_45dim_rl_gym/bpu_quantization/README.md b/deploy_45dim_rl_gym/bpu_quantization/README.md index 21c6fb8..e807a33 100644 --- a/deploy_45dim_rl_gym/bpu_quantization/README.md +++ b/deploy_45dim_rl_gym/bpu_quantization/README.md @@ -55,6 +55,30 @@ cd /Users/chenyouyuan/cyy_ws/deploy_go1_pro/deploy_45dim_rl_gym/bpu_quantization ./quantize_policy_x5.sh --samples 128 --compare-limit 128 ``` +速度优先 int8 对照: + +```bash +./quantize_policy_x5.sh --quant int8 +``` + +本次 `policy_35k` int8 结果不建议直接实机使用: + +- 产物:`mapper_output_35k_int8_gemm/policy_35k_int8_gemm.bin` +- `actions` cosine:`0.981343` +- L1/L2/Chebyshev:`0.053474 / 0.018129 / 0.113345` +- mapper 编译估计延迟:`314.2 us + 49.7 us` +- 板端 `hrt_model_exec perf` 实测:`1.583870 ms` +- 板端 C++ bench:`1.56478 ms` + +对比当前 int16: + +- `actions` cosine:`0.998524` +- 板端 `hrt_model_exec perf` 实测:`1.401526 ms` +- 板端 C++ bench:`1.37792 ms` + +结论:这个模型上默认 int8 既更慢,输出误差也更大。当前继续用 +`policy_35k_int16_gemm.bin` 更合理。 + Gym BPU 部署入口支持快速切换轮次: ```bash @@ -105,25 +129,31 @@ cd /root/go1_pro_deploy/deploy_45dim_rl_gym/bpu_deploy_x5/cpp 1000 ``` -已经完成 `policy_robotlab_15000.onnx` 和 `policy_robotlab_6500.onnx` 的 int16 -量化。RobotLab BPU 部署默认仍使用 6500 版本: +已经完成 `policy_robotlab_15000.onnx`、`policy_robotlab_6500.onnx` 和 +`policy_robotlab_26000.onnx` 的 int16 量化。RobotLab BPU 部署当前默认使用 +26000 版本: -- 原始模型:`../policy_robotlab_6500.onnx` +- 原始模型:`../policy_robotlab_26000.onnx` - 原始输入:`obs [1, 450]` - BPU 编译输入:`obs_4d [1, 1, 1, 450]` - BPU 输出:`actions [1, 12, 1, 1]` - Docker 镜像:`openexplorer/ai_toolchain_ubuntu_20_x5_cpu:v1.2.8` - `hb_mapper`:`1.24.3` - `hbdk`:`3.49.15` -- 当前产物:`mapper_output_6500_gemm/policy_robotlab_6500_int16_gemm.bin` +- 当前产物:`mapper_output_26000_gemm/policy_robotlab_26000_int16_gemm.bin` `mapper_output*/`、`.hb_check/`、校准数据、中间 ONNX、`hb_mapper` 日志都被 `.gitignore` 忽略;需要时按下面步骤重新生成。仓库里只保留脚本和 YAML 配置。 -6500 量化使用 `calibration_data_fast64/` 的 64 个真实样本。原因是 +26000 量化使用 `calibration_data_26000_robotlab_fast64/` 的 64 个真实样本。原因是 `hb_mapper` 会先尝试 calibration batch 8,但当前 4D featuremap 包装会被工具链 内部改成固定 batch 的 reshape,batch 8 失败后会退回 batch 1;用 64 样本可以把 -校准时间从 512 次 batch1 显著降下来。 +校准时间压到可接受范围。 + +如果你要回退到旧版: + +- `mapper_output_6500_gemm/policy_robotlab_6500_int16_gemm.bin` +- `mapper_output_gemm/policy_robotlab_15000_int16_gemm.bin` ## 1. 生成校准数据 diff --git a/deploy_45dim_rl_gym/bpu_quantization/policy_robotlab_26000_actions.onnx b/deploy_45dim_rl_gym/bpu_quantization/policy_robotlab_26000_actions.onnx new file mode 100644 index 0000000..cb04063 Binary files /dev/null and b/deploy_45dim_rl_gym/bpu_quantization/policy_robotlab_26000_actions.onnx differ diff --git a/deploy_45dim_rl_gym/bpu_quantization/policy_robotlab_26000_bpu4d.onnx b/deploy_45dim_rl_gym/bpu_quantization/policy_robotlab_26000_bpu4d.onnx new file mode 100644 index 0000000..e81261e Binary files /dev/null and b/deploy_45dim_rl_gym/bpu_quantization/policy_robotlab_26000_bpu4d.onnx differ diff --git a/deploy_45dim_rl_gym/bpu_quantization/policy_robotlab_26000_bpu4d_gemm.onnx b/deploy_45dim_rl_gym/bpu_quantization/policy_robotlab_26000_bpu4d_gemm.onnx new file mode 100644 index 0000000..d43f9c9 Binary files /dev/null and b/deploy_45dim_rl_gym/bpu_quantization/policy_robotlab_26000_bpu4d_gemm.onnx differ diff --git a/deploy_45dim_rl_gym/bpu_quantization/policy_robotlab_26000_int16_gemm.yaml b/deploy_45dim_rl_gym/bpu_quantization/policy_robotlab_26000_int16_gemm.yaml new file mode 100644 index 0000000..d3e37cd --- /dev/null +++ b/deploy_45dim_rl_gym/bpu_quantization/policy_robotlab_26000_int16_gemm.yaml @@ -0,0 +1,27 @@ +model_parameters: + onnx_model: "./policy_robotlab_26000_bpu4d_gemm.onnx" + march: "bayes-e" + layer_out_dump: false + working_dir: "mapper_output_26000_gemm" + output_model_file_prefix: "policy_robotlab_26000_int16_gemm" + +input_parameters: + input_name: "obs_4d" + input_shape: "1x1x1x450" + input_type_rt: "featuremap" + input_layout_rt: "NCHW" + input_type_train: "featuremap" + input_layout_train: "NCHW" + norm_type: "no_preprocess" + +calibration_parameters: + cal_data_dir: "./calibration_data_26000_robotlab_fast64" + cal_data_type: "float32" + calibration_type: "default" + optimization: "set_all_nodes_int16" + per_channel: true + +compiler_parameters: + compile_mode: "latency" + debug: false + optimize_level: "O3" diff --git a/deploy_45dim_rl_gym/bpu_quantization/policy_robotlab_26000_opset11.onnx b/deploy_45dim_rl_gym/bpu_quantization/policy_robotlab_26000_opset11.onnx new file mode 100644 index 0000000..fe2c4fe Binary files /dev/null and b/deploy_45dim_rl_gym/bpu_quantization/policy_robotlab_26000_opset11.onnx differ diff --git a/deploy_45dim_rl_gym/bpu_quantization/quantize_policy_x5.sh b/deploy_45dim_rl_gym/bpu_quantization/quantize_policy_x5.sh index ec825af..0e156de 100755 --- a/deploy_45dim_rl_gym/bpu_quantization/quantize_policy_x5.sh +++ b/deploy_45dim_rl_gym/bpu_quantization/quantize_policy_x5.sh @@ -12,6 +12,7 @@ FLAT_DIM="" SAMPLES=64 MIN_SAMPLES=32 LOG_PREFIX="rlgym_go1_deploy" +CAL_TAG="gym" DOCKER_IMAGE="openexplorer/ai_toolchain_ubuntu_20_x5_cpu:v1.2.8" COMPARE_LIMIT=64 RUN_CHECKER=1 @@ -33,6 +34,7 @@ Options: --samples N calibration sample count; default 64 for faster mapping --min-samples N minimum valid samples required; default 32 --log-prefix PREFIX log dir prefix below logs/, default rlgym_go1_deploy + --cal-tag TAG calibration dir tag, default gym --docker-image IMAGE D-Robotics CPU toolchain image --compare-limit N float ONNX equivalence sample count, default 64 --quant int16|int8 int16 keeps current conservative path; int8 omits set_all_nodes_int16 @@ -50,6 +52,7 @@ while [[ $# -gt 0 ]]; do --samples) SAMPLES="$2"; shift 2 ;; --min-samples) MIN_SAMPLES="$2"; shift 2 ;; --log-prefix) LOG_PREFIX="$2"; shift 2 ;; + --cal-tag) CAL_TAG="$2"; shift 2 ;; --docker-image) DOCKER_IMAGE="$2"; shift 2 ;; --compare-limit) COMPARE_LIMIT="$2"; shift 2 ;; --quant) QUANT="$2"; shift 2 ;; @@ -88,7 +91,7 @@ if [[ -z "${NAME}" ]]; then NAME="$(basename "${POLICY_ABS}" .onnx)" fi -CAL_DIR="calibration_data_${ROUND}_gym_fast${SAMPLES}" +CAL_DIR="calibration_data_${ROUND}_${CAL_TAG}_fast${SAMPLES}" if [[ "${QUANT}" = "int16" ]]; then OUTPUT_DIR="mapper_output_${ROUND}_gemm" OUTPUT_PREFIX="${NAME}_int16_gemm" diff --git a/deploy_45dim_rl_gym/deploy_go1_onnx_mujoco_lab.py b/deploy_45dim_rl_gym/deploy_go1_onnx_mujoco_lab.py index a567866..285b9bd 100644 --- a/deploy_45dim_rl_gym/deploy_go1_onnx_mujoco_lab.py +++ b/deploy_45dim_rl_gym/deploy_go1_onnx_mujoco_lab.py @@ -43,7 +43,7 @@ from mujoco import viewer # ── path setup ── SCRIPT_DIR = Path(__file__).resolve().parent -DEFAULT_ONNX = str(SCRIPT_DIR / "policy_robotlab_15000.onnx") +DEFAULT_ONNX = str(SCRIPT_DIR / "policy_robotlab_26000.onnx") ROBOT_XML = str(SCRIPT_DIR / "go1.xml") TERRAINS_DIR = SCRIPT_DIR / "terrains" diff --git a/deploy_45dim_rl_gym/policy_robotlab_19500.onnx b/deploy_45dim_rl_gym/policy_robotlab_19500.onnx new file mode 100644 index 0000000..f490020 Binary files /dev/null and b/deploy_45dim_rl_gym/policy_robotlab_19500.onnx differ diff --git a/deploy_45dim_rl_gym/policy_robotlab_26000.onnx b/deploy_45dim_rl_gym/policy_robotlab_26000.onnx new file mode 100644 index 0000000..cb04063 Binary files /dev/null and b/deploy_45dim_rl_gym/policy_robotlab_26000.onnx differ