ROS2 自定义消息接口:五步完成(含无人机集群示例)

本文以无人机(UAV)集群通信为例,从零开始完成 ROS 2 自定义消息接口(topic/message)的创建、编译、验证与使用。最终会得到一个接口包 onboard_msgs,内含两类消息:OnboardCommandOnboardState

适用环境(示例命令为 Linux + bash):

  • ROS 2 Humble
  • 已创建工作空间 ~/ros2_ws 并包含 src 目录
  • 构建工具:colcon;构建类型:ament_cmake

五步法总览

  1. 创建接口包(ament_cmake + rosidl)
  2. msg/ 目录编写消息(.msg)
  3. 配置 CMakeLists.txt
  4. 配置 package.xml
  5. 编译并验证接口

1) 创建接口包

1
2
3
4
5
cd ~/ros2_ws/src
ros2 pkg create onboard_msgs \
--build-type ament_cmake \
--dependencies rosidl_default_generators\
--license Apache-2.0

–dependencies后面跟接口定义的消息所需的依赖,rosidl_default_generators为必须项

进入包目录并创建接口文件夹:

1
2
cd onboard_msgs
mkdir -p msg

2) 定义消息(.msg)

2) 定义消息(.msg)

根据无人机集群业务,定义三个消息:命令、参数、多机状态。
根据无人机集群业务,定义两类消息:命令与多机状态。
msg/OnboardCommand.msg
msg/OnboardCommand.msg 中:

1
2
3
uint16 target_id   # 目标无人机编号
string name # 命令名称
string params # 命令参数(JSON 格式)

uint16 target_id # 目标无人机编号
msg/OnboardState.msg 中:

1
2
3
4
5
6
7
uint16 uav_id     # 无人机编号

float64 lat_deg # 纬度
float64 lon_deg # 经度
float64 alt_msl # 平均海平面高度

float32 battery # 电量百分比

建议的包结构(节选):

1
2
3
4
5
6
onboard_msgs/
├─ CMakeLists.txt
├─ package.xml
└─ msg/
├─ OnboardCommand.msg
└─ OnboardState.msg

3) 配置 CMakeLists.txt

在包根目录打开 CMakeLists.txt,加入如下关键段落(保留已有的最低模板行):

1
2
3
4
5
6
7
8
9
10
11
12
13
cmake_minimum_required(VERSION 3.8)
project(onboard_msgs)

find_package(ament_cmake REQUIRED)
find_package(rosidl_default_generators REQUIRED)

# 声明需要生成的接口
rosidl_generate_interfaces(${PROJECT_NAME}
"msg/OnboardCommand.msg"
"msg/OnboardState.msg"
)

ament_package()

4) 配置 package.xml

确保依赖与接口生成组声明完整:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>onboard_msgs</name>
<version>0.0.1</version>
<description>TO DO</description>
<maintainer email="you@example.com">Your Name</maintainer>
<license>Apache-2.0</license>

<!-- 构建工具 -->
<buildtool_depend>ament_cmake</buildtool_depend>
<!-- 用于生成接口代码 -->
<buildtool_depend>rosidl_default_generators</buildtool_depend>

<!-- 运行期 -->
<!-- 用于供其它包调用接口 -->
<depend>rosidl_default_runtime</depend>

<!-- 用于声明该功能包是一个消息接口功能包,必须包含 -->
<member_of_group>rosidl_interface_packages</member_of_group>

<export>
<build_type>ament_cmake</build_type>
</export>
</package>

5) 编译与环境加载

在工作空间根目录编译该包,并加载环境:

1
2
3
cd ~/ros2_ws
colcon build --packages-select onboard_msgs
source install/setup.bash

验证接口是否可见:

1
ros2 interface list | grep onboard_msgs

查看具体定义:

1
2
ros2 interface show onboard_msgs/msg/OnboardCommand
ros2 interface show onboard_msgs/msg/OnboardState

CLI 快速试用(发布/回显)

使用 ros2 topic pubros2 topic echo 快速验证消息格式与编解码是否正常。

发布一条命令到 /uav/cmd

1
2
ros2 topic pub /uav/cmd onboard_msgs/msg/OnboardCommand \
'{target_id: 1, name: "Takeoff", params: "{\"alt\": 5.0}"}'

回显无人机状态(若已有节点发布到 /uav/state):

1
ros2 topic echo /uav/state onboard_msgs/msg/OnboardState

提示:在 bash 中传 JSON 时,注意对双引号进行转义,或改用 YAML 多行字面量方式避免转义错误。


在其他包中使用该接口(CMake 示例)

若有消费该消息的 C++ 包,需在其 CMakeLists.txt 中:

1
2
3
4
5
6
7
8
9
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(onboard_msgs REQUIRED)

add_executable(my_node src/my_node.cpp)
ament_target_dependencies(my_node rclcpp onboard_msgs)
install(TARGETS my_node DESTINATION lib/${PROJECT_NAME})

ament_package()

并在 package.xml 中添加:

1
<depend>onboard_msgs</depend>

常见错误与排查

  • 忘记在 CMakeLists.txtrosidl_generate_interfaces 中加入新 .msg 文件 → 重新添加后再 colcon build
  • 未在 package.xml 中加入 <depend>rosidl_default_runtime</depend> → 其它包找不到生成的类型。
  • 构建后未 source install/setup.bash → 终端会找不到接口定义。
  • CLI 发布 JSON 参数时引号转义错误 → 建议用单引号包裹、内部双引号转义,或改用 YAML 方式。
  • 多机/多命名空间未区分 → 为每架 UAV 使用不同命名空间(如 /uav1/../uav2/..)。

参考