ROS2 自定义消息接口
ROS2 自定义消息接口:五步完成(含无人机集群示例)
本文以无人机(UAV)集群通信为例,从零开始完成 ROS 2 自定义消息接口(topic/message)的创建、编译、验证与使用。最终会得到一个接口包 onboard_msgs,内含两类消息:OnboardCommand 与 OnboardState。
适用环境(示例命令为 Linux + bash):
- ROS 2 Humble
- 已创建工作空间
~/ros2_ws并包含src目录 - 构建工具:colcon;构建类型:
ament_cmake
五步法总览
- 创建接口包(ament_cmake + rosidl)
- 在
msg/目录编写消息(.msg) - 配置
CMakeLists.txt - 配置
package.xml - 编译并验证接口
1) 创建接口包
1 | cd ~/ros2_ws/src |
–dependencies后面跟接口定义的消息所需的依赖,rosidl_default_generators为必须项
进入包目录并创建接口文件夹:
1 | cd onboard_msgs |
2) 定义消息(.msg)
2) 定义消息(.msg)
根据无人机集群业务,定义三个消息:命令、参数、多机状态。
根据无人机集群业务,定义两类消息:命令与多机状态。msg/OnboardCommand.msg
在 msg/OnboardCommand.msg 中:
1 | uint16 target_id # 目标无人机编号 |
uint16 target_id # 目标无人机编号
在 msg/OnboardState.msg 中:
1 | uint16 uav_id # 无人机编号 |
建议的包结构(节选):
1 | onboard_msgs/ |
3) 配置 CMakeLists.txt
在包根目录打开 CMakeLists.txt,加入如下关键段落(保留已有的最低模板行):
1 | cmake_minimum_required(VERSION 3.8) |
4) 配置 package.xml
确保依赖与接口生成组声明完整:
1 |
|
5) 编译与环境加载
在工作空间根目录编译该包,并加载环境:
1 | cd ~/ros2_ws |
验证接口是否可见:
1 | ros2 interface list | grep onboard_msgs |
查看具体定义:
1 | ros2 interface show onboard_msgs/msg/OnboardCommand |
CLI 快速试用(发布/回显)
使用 ros2 topic pub 和 ros2 topic echo 快速验证消息格式与编解码是否正常。
发布一条命令到 /uav/cmd:
1 | ros2 topic pub /uav/cmd onboard_msgs/msg/OnboardCommand \ |
回显无人机状态(若已有节点发布到 /uav/state):
1 | ros2 topic echo /uav/state onboard_msgs/msg/OnboardState |
提示:在 bash 中传 JSON 时,注意对双引号进行转义,或改用 YAML 多行字面量方式避免转义错误。
在其他包中使用该接口(CMake 示例)
若有消费该消息的 C++ 包,需在其 CMakeLists.txt 中:
1 | find_package(ament_cmake REQUIRED) |
并在 package.xml 中添加:
1 | <depend>onboard_msgs</depend> |
常见错误与排查
- 忘记在
CMakeLists.txt的rosidl_generate_interfaces中加入新.msg文件 → 重新添加后再colcon build。 - 未在
package.xml中加入<depend>rosidl_default_runtime</depend>→ 其它包找不到生成的类型。 - 构建后未
source install/setup.bash→ 终端会找不到接口定义。 - CLI 发布 JSON 参数时引号转义错误 → 建议用单引号包裹、内部双引号转义,或改用 YAML 方式。
- 多机/多命名空间未区分 → 为每架 UAV 使用不同命名空间(如
/uav1/..、/uav2/..)。
参考
- ROS 2 Interface Definition: https://design.ros2.org/articles/interface_definition.html
- Tutorials: https://docs.ros2.org
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Dreamer Island!




