本文档面向初次接触 roboto_inference 包的开发者,帮助你在 10 分钟内完成从源码编译到让机器人执行第一条策略的完整流程。阅读前请确保你已具备基础的 ROS 2 和 Linux 命令行知识。如需先了解项目整体定位与能力边界,请参阅 Overview。
项目能力速览
roboto_inference 是一个基于 ROS 2 的实时策略推理节点,核心任务是将训练好的强化学习策略(ONNX 格式)转换为机器人关节力矩指令。节点启动后,会通过双线程架构并行处理模型推理与电机控制:推理线程以固定频率读取 IMU、关节状态与外部指令,组装观测值并送入 ONNX Runtime;控制线程以更高频率将策略输出的动作通过 CAN/CANFD 总线下发至 23 个电机。系统默认订阅手柄(/joy)与速度指令(/cmd_vel)话题,同时提供一系列 ROS 2 服务用于安全地初始化硬件、启停推理和故障恢复。
Sources: package.xml, CMakeLists.txt, inference_node.hpp
系统要求与依赖
在开始编译前,请确认你的开发环境满足以下条件。依赖按功能划分为系统工具链、ROS 2 生态、数学与日志库、第三方推理库四组。
| 依赖类别 | 具体组件 | 最低版本/说明 |
|---|---|---|
| 操作系统与编译器 | Ubuntu + GCC/Clang | Ubuntu 22.04 或同等 Linux 发行版;支持 C++17 |
| 构建系统 | CMake + ament_cmake | 3.16+ |
| ROS 2 | rclcpp, sensor_msgs, geometry_msgs, std_srvs | Humble 或 Rolling |
| 硬件驱动包 | roboto_motors, roboto_imu | 同工作空间内可找到 |
| 数学与序列化 | Eigen3, yaml-cpp, cnpy | Eigen3 3.3+;cnpy 与 yaml-cpp 已内置在 thirdparty/ |
| 日志与绑定 | spdlog, fmt, pybind11 | pybind11 用于编译 Python 绑定模块 robot_py |
| 推理引擎 | ONNX Runtime | 1.21.0,已按 x64 与 aarch64 分别内置在 thirdparty/ |
由于 ONNX Runtime 与 cnpy 的预编译库已随仓库提供,你无需手动安装它们;CMake 会根据 CMAKE_SYSTEM_PROCESSOR 自动选择 x64 或 aarch64 版本。若你在 x86 工作站上交叉编译或仅做算法验证,同样可以直接编译通过。
Sources: CMakeLists.txt, package.xml
仓库结构与关键路径
快速熟悉仓库布局能帮助你精准定位配置文件与模型文件。以下是初学者最需要关注的目录与文件:
roboto_inference/
├── config/
│ ├── inference.yaml # 默认推理配置(单策略)
│ ├── inference_getup.yaml # 多策略示例:行走 + 起身
│ └── robot.yaml # 电机与 IMU 硬件参数
├── launch/
│ └── inference.launch.py # ROS 2 Launch 入口
├── models/
│ ├── policy.onnx # 默认行走策略
│ ├── policy_getup.onnx # 起身策略
│ └── ... # 其他策略模型
├── motions/
│ └── getup.npz # 动作参考轨迹(供 MotionLoader 使用)
├── src/
│ ├── inference_node.cpp # 推理与观测堆叠逻辑
│ ├── robot_interface.cpp # 硬件抽象实现
│ └── utils/ # 运动学映射、线程池、动作加载
└── thirdparty/
├── onnxruntime-linux-* # ONNX Runtime 预编译库
└── yaml-cpp-0.8.0 # YAML 解析库源码
Sources: get_dir_structure
编译与构建
整个包使用标准 ROS 2 工作流编译。如果你将本包放在 ROS 2 工作空间的 src/ 目录下,执行以下命令即可完成 Release 模式构建:
cd ~/your_ros2_ws
colcon build --packages-select roboto_inference --cmake-args -DCMAKE_BUILD_TYPE=Release
构建成功后,会生成三个关键产物:
roboto_inference_node—— 主可执行节点;libr robot.a与libutils.a—— 静态库,供其他模块链接;robot_py*.so—— Python 绑定模块,安装后可通过import robot在脚本中访问底层接口。
编译时会自动将 launch/、config/、models/、motions/ 安装到 install/roboto_inference/share/roboto_inference/ 下,因此启动时无需手动指定绝对路径。
Sources: CMakeLists.txt
启动节点
最简单的方式是通过 Launch 文件启动,它会自动加载默认配置并创建 inference_node:
ros2 launch roboto_inference inference.launch.py
该 Launch 文件仅做一件事:将 config/inference.yaml 作为参数列表传给节点。若你想尝试其他策略组合(例如同时加载行走策略与起身策略),只需修改 Launch 文件中的 configs 路径,或临时覆盖参数:
ros2 launch roboto_inference inference.launch.py \
params_file:=$(pwd)/config/inference_getup.yaml
下表列出初学者最常接触的配置文件及其适用场景,帮助你在第一次启动时选择正确的 YAML:
| 配置文件 | 加载策略 | 适用场景 | 特殊说明 |
|---|---|---|---|
inference.yaml |
policy.onnx |
基础行走 | 单策略,帧堆叠 10,适合首次上电验证 |
inference_getup.yaml |
policy.onnx + policy_getup.onnx |
行走 + 自动起身 | 多策略,motion_names 提供起身参考轨迹 |
inference_interrupt.yaml |
policy_interrupt.onnx |
带中断保护的行走 | 观测布局包含 interrupt:1,支持外部急停覆盖 |
inference_amp.yaml |
policy_amp.onnx |
AMP 风格运动 | 对抗性运动先验策略 |
inference_attn_enc.yaml |
policy_attn_enc.onnx |
注意力编码器策略 | 需要与对应模型维度匹配的观测布局 |
Sources: inference.launch.py, inference.yaml, inference_getup.yaml
安全启动流程
节点启动后不会立即驱动电机,这是刻意设计的安全边界。完整的上电到运动流程如下:
flowchart TD
A[启动 inference_node] --> B{电机已初始化?}
B -->|否| C[调用 /init_motors 服务]
C --> D[调用 /reset_joints 服务]
D --> E[调用 /start_inference 服务]
E --> F[节点进入实时双线程循环]
B -->|是| E
F --> G[订阅 /joy 或 /cmd_vel 控制机器人]
G --> H[调用 /stop_inference 停止]
H --> I[调用 /deinit_motors 下电]
各阶段对应的 ROS 2 命令如下。请在终端中逐行执行,并观察节点日志输出确认成功:
# 1. 初始化电机与 IMU(建立 CAN 通信、检查硬件在线)
ros2 service call /init_motors std_srvs/srv/Trigger
# 2. 将关节复位到默认姿态(防止初始姿态偏差导致策略发散)
ros2 service call /reset_joints std_srvs/srv/Trigger
# 3. 启动推理循环(此时策略开始输出动作)
ros2 service call /start_inference std_srvs/srv/Trigger
若需要紧急停止,可直接调用:
ros2 service call /stop_inference std_srvs/srv/Trigger
停止推理后电机仍保持使能;如需完全下电释放关节,则调用 /deinit_motors。
Sources: inference_node.hpp, robot_interface.hpp
配置文件最简解读
第一次启动前,你至少需要理解 inference.yaml 中的三项核心参数,其余参数可保持默认值:
model_names:字符串数组,按顺序指定models/目录下的 ONNX 文件名。系统会为每个模型创建独立的PolicyRuntime上下文。obs_layouts:观测源布局字符串,格式为name:size,name:size,...。常见源包括ang_vel(角速度,3 维)、gravity_b(机体重力向量,3 维)、cmd_vel(速度指令,3 维)、dof_pos(关节位置,23 维)、dof_vel(关节速度,23 维)、last_action(上一帧动作,23 维)。该布局必须与 ONNX 模型的输入维度严格一致,否则节点会在初始化阶段抛出ONNX input size mismatch异常。frame_stacks:整数数组,与model_names一一对应,表示历史帧堆叠数量。例如10意味着将最近 10 帧观测按obs_stack_orders指定的格式拼接后送入模型。
robot.yaml 则负责描述硬件拓扑:23 个电机的 CAN 接口分配(can0 ~ can3)、IMU 串口、电机零偏与方向系数、闭环解耦所需的关节映射等。只要你的机器人机械结构未变,通常无需修改此文件;若更换了电机类型或 IMU 型号,才需要调整对应字段。
Sources: inference.yaml, robot.yaml, ros_interface.cpp
验证节点运行状态
成功启动推理后,可通过以下 ROS 2 命令验证数据流是否正常:
# 查看当前发布的关节动作指令(策略输出)
ros2 topic echo /action
# 查看 IMU 数据是否被正确转发
ros2 topic echo /imu
# 查看关节状态反馈
ros2 topic echo /joint_states
# 实时检查节点服务列表
ros2 service list | grep inference
若 /action 话题持续输出非零的 position 字段,且数值在 joint_limits 范围内平滑变化,说明策略推理与动作发布链路均已正常工作。
Sources: inference_node.hpp
常见问题速查
| 现象 | 可能原因 | 快速排查 |
|---|---|---|
编译失败,提示找不到 roboto_motors |
依赖包未放在同一工作空间 | 确认 roboto_motors 与 roboto_imu 已在 src/ 中并先执行 colcon build |
启动即报错 Motors not initialized |
未调用 /init_motors 就读取关节状态 |
检查是否在安全启动流程中漏掉了初始化服务 |
ONNX input size mismatch |
观测布局与模型输入维度不一致 | 核对 obs_layouts 中各源维度之和乘以 frame_stacks 是否等于 ONNX 输入 |
| 推理启动后机器人剧烈抖动 | 初始姿态与 joint_default_angle 偏差过大 |
先调用 /reset_joints 让关节回到默认姿态再启动推理 |
| 电机无响应但服务返回成功 | CAN 接口权限不足 | 确认已执行 sudo setcap cap_net_raw+ep 给节点二进制,或以 root 运行 |
Sources: inference_node.hpp, robot_interface.hpp
下一步
完成 Quick Start 后,你已能让机器人执行基础行走策略。若准备深入理解实时线程调度、多策略热切换或硬件通信细节,建议按以下顺序继续阅读:
- 硬件准备与电机初始化 —— 了解电机 ID 配置、CAN 接线与上电检查清单。
- 手柄与指令控制入门 —— 学习如何通过
/joy与/cmd_vel发送速度指令,以及死区与限位参数的含义。 - Launch 文件与启动配置 —— 掌握多配置切换、参数覆盖与生产环境启动的最佳实践。
- 系统架构总览 —— 从架构层面理解
InferenceNode、RobotInterface与 ROS 2 交互的完整数据流。
如果你在配置过程中遇到未列出的异常,建议先检查节点日志中的 RCLCPP_INFO 输出,其中会打印当前加载的策略名称、观测维度、act_alpha 等关键运行时信息,便于与配置文件进行交叉核对。