GR00T-WholeBodyControl C++推理栈深度解析:从TensorRT ONNX推理到50Hz实时控制的完整流水线
【免费下载链接】GR00T-WholeBodyControlWelcome to GR00T Whole-Body Control (WBC)! This is a unified platform for developing and deploying advanced humanoid controllers. This includes: Decoupled WBC models used in NVIDIA Isaac-Gr00t, Gr00t N1.5 and N1.6 and GEAR-SONIC项目地址: https://gitcode.com/gh_mirrors/gr/GR00T-WholeBodyControl
GR00T-WholeBodyControl 是 NVIDIA 推出的人形机器人全身控制(WBC)统一平台,面向 Unitree G1 等机器人提供从神经网络推理到电机指令下发的完整部署方案。它的核心部署代码 g1_deploy_onnx_ref.cpp 用一个 C++20 单文件应用串起了 TensorRT 推理、ONNX Runtime 回退、50Hz 控制环与 500Hz 电机指令下发。本文带你完整读懂这条实时推理流水线:为什么要拆成四条实时线程、GPU 推理如何与 20ms 周期精确对齐、以及多模型(策略+编码器+规划器)如何协同工作。
整体架构:一条流水线,四个实时线程
部署程序的核心是G1Deploy类(g1_deploy_onnx_ref.cpp#L148-L164),它负责装配所有子系统:输入接口、TensorRT 策略引擎、可选的编码器与运动规划器、状态日志、输出接口等。整个程序通过 Unitree SDK 的CreateRecurrentThreadEx创建4 条定周期实时线程(g1_deploy_onnx_ref.cpp#L2580-L2588):
| 线程 | 频率 | 周期 | 职责 |
|---|---|---|---|
| Input | 100 Hz | 0.01 s | 轮询输入(键盘/手柄/ZMQ/ROS2),处理指令 |
| Control | 50 Hz | 0.02 s | 采集观测、运行策略推理、计算电机目标 |
| Planner | 10 Hz | 0.1 s | 重规划运动轨迹(可选) |
| Command Writer | 500 Hz | 0.002 s | 通过 DDS 下发电机指令 |
这种"频率解耦"是人形机器人实时系统的经典手法:神经推理只需 50Hz 决策,而电机闭环需要 500Hz 才能稳定平滑;低频规划器则负责生成整段动作序列,避免 10Hz 推理拖慢主循环。
控制环本身是一个三态状态机:INIT → WAIT_FOR_CONTROL → CONTROL。INIT 阶段等待机器人上报有效的LowState消息;收到操作员"启动"信号后进入 CONTROL,开始正式的"观测→推理→指令"循环;遇到停止指令或错误则退出。
TensorRT 推理引擎:推理栈的"地基"
推理引擎封装在 TRTInference/ 目录中,核心是 InferenceEngine.h 里的两个角色:
ConvertONNXToTRT():把训练产出的 ONNX 模型离线转换为 TensorRT 引擎,支持 FP32/FP16 精度与动态轴配置;转换产物带哈希校验,缓存命中时不会重复转换。TRTInferenceEngine类:运行时推理入口。对外提供SetInputData/GetOutputData及对应的Async 版本(绑定cudaStream_t流),内部用 pimpl 隐藏所有 TensorRT 细节。
性能优化的两个关键点:
- 锁页内存(Pinned Memory):输入输出缓冲区使用
TPinnedVector<T>(Utility.h),配合SetInputDataAsync在指定 CUDA 流上执行异步拷贝,让 CPU 准备下一帧观测的时间与 GPU 执行推理重叠; - CUDA 流编排:策略、编码器、规划器各自使用独立的
cudaStream,三者推理互不阻塞。
这套引擎同时保留 ONNX Runtime 路径(CMake 中 Findonnxruntime.cmake 与find_package(onnxruntime REQUIRED)并存),方便在无 GPU 环境下调试。
50Hz 控制环:20ms 里发生了什么
控制线程每个 20ms 周期执行的核心是CreatePolicyCommand()(g1_deploy_onnx_ref.cpp#L3096-L3133),一次完整 tick 的流程:
- 构建观测:把参考动作帧(关节位置/速度、锚点朝向)、IMU、上一帧动作等按 YAML 配置拼成观测向量。观测项的开关与顺序由 observation_config_example.yaml 声明,例如 29 维
motion_joint_positions+ 6 维motion_anchor_orientation,维度必须与 ONNX 模型输入精确匹配; - 类型转换:将 double 精度的观测缓冲逐元素转成 float,写入策略引擎的锁页输入缓冲(control_policy.hpp);
- GPU 推理:
policy_engine_->Infer()内部完成 CPU→GPU 拷贝、Enqueue()提交 TensorRT 执行、再异步取回动作缓冲; - 动作映射:把 IsaacLab 关节顺序的动作经
isaaclab_to_mujoco重排为硬件顺序,叠加动作缩放与默认关节角,生成MotorCommand(含 q_target / kp / kd)。
随后LowCommandWriter线程以 500Hz 把这条指令经 Unitree SDK 的 DDS 通道(LowCmd)下发给机器人;CurrentFrameAdvancement()则推进参考动作游标,若规划器产出了新动作,还会用 8 帧线性交叉淡入平滑切换(g1_deploy_onnx_ref.cpp#L3150-L3179)。
多模型推理协同:Policy + Encoder + Planner
GEAR-SONIC 的部署不是单一模型,而是一个三级推理栈,全部走同一套 TensorRT 引擎:
- 策略模型(Policy,50Hz):输入观测,输出 29 关节动作。对应 CLI 参数
--model/--policy-fp16; - 编码器(Encoder):把外部 token 流(如 VLA/视觉端点结果)编码为策略可用的
token_state,同样支持 FP16(--encoder-file/--encoder-fp16)。代码里对 token 有完整的安全监控:5 秒级心跳检查、超时告警、超时自动降级为零 token,避免网络抖动时机器人失控; - 规划器(Planner,10Hz):
LocalMotionPlannerBase及其 TensorRT 实现(localmotion_kplanner_tensorrt.hpp)在独立流上异步推理,输入当前 qpos、朝向、目标速度等张量,输出整段预测轨迹(mujoco_qpos_output),按 50Hz 重采样供控制环消费,实现"10Hz 规划 + 50Hz 跟踪"的层次式全身控制。
参考动作数据则由 reference/example/ 下的 CSV 动捕序列(如macarena_001__A545)预加载,格式可用 convert_motions.py 转换。
构建与部署:一键编译与常用命令
部署工程由 CMakeLists.txt 统一构建,要求C++20 +-O3 -ffast-math,并强依赖四个组件:TensorRT、ONNX Runtime、CUDA Toolkit(含 Jetson sbsa/aarch64 双架构自动探测,对 JetPack 6 有专门适配)以及 unitree_sdk2(DDS 通信)。环境准备脚本见 scripts/install_deps.sh 与 install_ros2_humble.sh。
常用运行命令(详见 docs/source/references/deployment_code.md):
just build # 构建整个部署工程 # 真机部署:策略 + 编码器 + 规划器三模型 just run g1_deploy_onnx_ref enP8p1s0 policy/release/model_decoder.onnx reference/example/ \ --obs-config policy/release/observation_config.yaml \ --encoder-file policy/release/model_encoder.onnx \ --planner-file planner/target_vel/V2/planner_sonic.onnx \ --input-type manager # 模型加载自检(打印输入输出张量信息) just run freq_test policy/example/model_step_000000.onnxMuJoCo 仿真验证时可加--disable-crc-check跳过 CRC 校验,配合python ../gear_sonic/scripts/run_sim_loop.py做闭环仿真。发布用的观测配置在 policy/release/observation_config.yaml 及low_latency变体中。
稳定性与安全:让 50Hz 循环"永不掉拍"
实时控制最怕"偶发卡顿",代码中有多处工程化保障:
- 错误监控:error_monitor.hpp 统一收集 DDS 通信、推理失败、高温等异常;
- 温度滞回保护:单个电机温度 ≥90° 触发保护、<85° 才恢复,避免抖动(g1_deploy_onnx_ref.cpp#L256-L259);
- Idle 自适应状态机:机器人被推离目标姿态时,按 0.10 rad / 0.05 rad 双阈值进入 ADAPTING/RECOVERING 状态,逐步拉回而不是硬切换;
- 状态日志:
StateLogger用环形缓冲 + CSV 持久化,便于离线复盘; - 输入缓冲标志位:VR/手部/上半身数据各带
has_*_data_标志,缺失时回落默认值而非报错,保证 50Hz 主循环不因单路输入故障中断。
总结
GR00T-WholeBodyControl 的 C++ 推理栈值得借鉴的正是这种分层解耦思路:TensorRT 引擎封装层只关心"输入张量进、输出张量出"的异步 GPU 推理;控制层以 50Hz 稳定消费策略输出;规划器与编码器各自在独立线程和 CUDA 流上运行;而 500Hz 指令写入线程只负责"搬运"最新指令。四层各司其职,任何一层抖动都不会传导给其他层——这也是它能在单块 Jetson 级 GPU 上跑满全身 29 关节实时控制的根本原因。想动手实践的话,建议从 docs/source/references/deployment_code.md 的完整命令清单和 gear_sonic_deploy/src/g1/g1_deploy_onnx_ref/ 的头文件注释入手,配合 MuJoCo 仿真验证后再上真机。
【免费下载链接】GR00T-WholeBodyControlWelcome to GR00T Whole-Body Control (WBC)! This is a unified platform for developing and deploying advanced humanoid controllers. This includes: Decoupled WBC models used in NVIDIA Isaac-Gr00t, Gr00t N1.5 and N1.6 and GEAR-SONIC项目地址: https://gitcode.com/gh_mirrors/gr/GR00T-WholeBodyControl
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考