目录
摘要
一、ROS2 消息类型到底是什么?
1.1 ROS2 节点之间靠消息通信
1.2 geometry_msgs::msg::Twist vel_cmd; 为什么这样写?
1.3 ROS2 消息类型的命名规则
1.4 如果想简写,可以使用 using
二、ROS2 里面常见消息类型分类
2.1 std_msgs:基础数据消息
(1)适合传递简单数据
(2)常见使用场景
2.2 geometry_msgs:几何运动相关消息
(1)机器人运动控制中非常常见
(2)常见消息含义表格总结
(3)geometry_msgs::msg::Twist 描述机器人速度
(4)geometry_msgs::msg::Pose 描述机器人位姿
(5)geometry_msgs::msg::PoseStamped 带时间戳和坐标系的位姿
(6)geometry_msgs::msg::Point 描述三维空间中的一个点
(7)geometry_msgs::msg::Quaternion 描述姿态和旋转
(8)geometry_msgs::msg::Vector3 描述三维向量
(9)geometry_msgs::msg::TransformStamped 描述两个坐标系之间的变换关系
(1)导航系统中经常出现
(2)常见消息含义
2.4 sensor_msgs:传感器相关消息
(1)雷达、IMU、相机、点云都在这里
(2)常见消息含义
三、总结
3.1 ROS2 消息类型整体总结
3.2 常见消息包对比表
3.3 geometry_msgs 常见消息对比表
3.4 geometry_msgs 一句话记忆表
3.5 常见坐标系对比表
3.6 常见 TF 关系总结表
摘要
在 ROS2 中,节点之间并不是直接传递 C++ 普通变量,而是通过 消息类型 Message 进行通信。比如控制机器人运动时,经常会看到:
geometry_msgs::msg::Twist vel_cmd;
这句代码的意思是:创建一个 ROS2 速度控制消息对象,用来描述机器人的线速度和角速度。
本文将从这句代码出发,系统讲解 ROS2 中消息类型的命名规则、常见消息包、Twist 的内部结构、发布器写法、订阅器写法,以及如何在终端查看消息字段,帮助初学者真正看懂 ROS2 话题通信代码。
一、ROS2 消息类型到底是什么?
1.1 ROS2 节点之间靠消息通信

节点不是直接传变量,而是传消息
在普通 C++ 程序中,函数之间可以直接传递变量,比如:
int speed = 10;
但是 ROS2 是分布式机器人系统,通常会有多个节点同时运行,例如:
这些节点之间不能简单地通过普通变量通信,而是通过 ROS2 的通信机制传递数据。
最常见的方式就是:
话题 Topic + 消息 Message
例如:
/cmd_vel
这个话题通常用来发布机器人速度控制命令。
它使用的消息类型一般是:
geometry_msgs::msg::Twist
所以可以理解为:
/cmd_vel 是话题名字
geometry_msgs::msg::Twist 是话题里面传输的数据格式
1.2 geometry_msgs::msg::Twist vel_cmd; 为什么这样写?
它的本质是定义一个消息对象
这句代码:
geometry_msgs::msg::Twist vel_cmd;
本质上和普通 C++ 变量定义类似。
例如:
int age;
double speed;
std::string name;
对应到 ROS2 中就是:
geometry_msgs::msg::Twist vel_cmd;
可以拆成:
消息类型 变量名;
也就是:
geometry_msgs::msg::Twist vel_cmd;
其中:
geometry_msgs::msg::Twist
是消息类型。
vel_cmd
是自己定义的变量名。
1.3 ROS2 消息类型的命名规则
一般格式是:功能包名::msg::消息名
ROS2 C++ 中,消息类型一般采用下面这种格式:
功能包名::msg::消息名
例如:
geometry_msgs::msg::Twist
std_msgs::msg::String
nav_msgs::msg::Odometry
sensor_msgs::msg::LaserScan
以:
geometry_msgs::msg::Twist
为例,可以拆成三部分:
所以:
geometry_msgs::msg::Twist
表示:
geometry_msgs 功能包下面的 Twist 消息类型
这也是为什么不能随便写成:
Twist vel_cmd;
因为编译器默认并不知道 Twist 是谁,必须告诉它这个类型来自哪里。
1.4 如果想简写,可以使用 using
初学 ROS2 时,最推荐写完整形式:
geometry_msgs::msg::Twist vel_cmd;
这种写法虽然长一点,但是含义最清楚。
如果后面代码中频繁使用,也可以写:
using geometry_msgs::msg::Twist;
Twist vel_cmd;
或者写成类型别名:
using TwistMsg = geometry_msgs::msg::Twist;
TwistMsg vel_cmd;
不过在学习阶段,建议先保持完整写法,这样更容易理解消息来自哪个功能包。
二、ROS2 里面常见消息类型分类

2.1 std_msgs:基础数据消息
(1)适合传递简单数据
std_msgs 可以理解为 ROS2 中比较基础的一类消息,常用于传递字符串、整数、浮点数、布尔值等简单数据。
常见类型如下:
std_msgs::msg::String
std_msgs::msg::Int32
std_msgs::msg::Float64
std_msgs::msg::Bool
例如定义一个字符串消息:
std_msgs::msg::String msg;
msg.data = "hello ros2";
其中:
msg.data
才是真正保存字符串内容的字段。
(2)常见使用场景
std_msgs 常用于一些简单话题,例如:
例如:
std_msgs::msg::Bool flag;
flag.data = true;
表示发布一个布尔类型消息。
2.2 geometry_msgs:几何运动相关消息

(1)机器人运动控制中非常常见
geometry_msgs 是机器人开发中非常核心的一类消息,主要用于描述:
常见类型如下:
geometry_msgs::msg::Twist
geometry_msgs::msg::Pose
geometry_msgs::msg::PoseStamped
geometry_msgs::msg::Point
geometry_msgs::msg::Quaternion
geometry_msgs::msg::Vector3
geometry_msgs::msg::TransformStamped
(2)常见消息含义表格总结
| Twist | 描述速度,包括线速度和角速度 |
| Pose | 描述位姿,包括位置和姿态 |
| PoseStamped | 带时间戳和坐标系的位姿 |
| Point | 三维空间点坐标 |
| Quaternion | 四元数姿态 |
| Vector3 | 三维向量 |
| TransformStamped | 坐标系之间的变换关系 |
| Twist | 描述速度 | linear、angular | /cmd_vel 速度控制 |
| Pose | 描述位姿 | position、orientation | 机器人当前位置、目标位姿 |
| PoseStamped | 带时间和坐标系的位姿 | header、pose | 导航目标、路径点、定位结果 |
| Point | 描述空间点 | x、y、z | 目标点、障碍物点、坐标点 |
| Quaternion | 描述姿态旋转 | x、y、z、w | 机器人朝向、坐标旋转 |
| Vector3 | 描述三维向量 | x、y、z | 速度、角速度、加速度、方向量 |
| TransformStamped | 描述坐标系变换 | header、child_frame_id、transform | TF 坐标变换 |
(3)geometry_msgs::msg::Twist 描述机器人速度

Twist 用来描述机器人的运动速度,通常用于控制机器人底盘运动,最常见的话题是:
/cmd_vel
它里面包含两部分:
Vector3 linear // 线速度
Vector3 angular // 角速度
完整字段是:
vel_cmd.linear.x
vel_cmd.linear.y
vel_cmd.linear.z
vel_cmd.angular.x
vel_cmd.angular.y
vel_cmd.angular.z
对于大多数地面移动机器人,最常用的是:
vel_cmd.linear.x // 前进 / 后退速度
vel_cmd.angular.z // 左转 / 右转角速度
例如:
geometry_msgs::msg::Twist vel_cmd;
vel_cmd.linear.x = 0.2;
vel_cmd.angular.z = 0.0;
表示机器人以 0.2 m/s 向前运动,不旋转。
如果写成:
vel_cmd.linear.x = 0.0;
vel_cmd.angular.z = 0.5;
表示机器人不前进,只进行原地旋转。
所以 Twist 可以理解为:
Twist = 线速度 + 角速度
(4)geometry_msgs::msg::Pose 描述机器人位姿
Pose 用来描述一个物体或者机器人在空间中的 位置和姿态。
它包含两部分:
Point position // 位置
Quaternion orientation // 姿态
完整字段是:
pose.position.x
pose.position.y
pose.position.z
pose.orientation.x
pose.orientation.y
pose.orientation.z
pose.orientation.w
其中:
position
表示位置,也就是机器人在哪里。
orientation
表示姿态,也就是机器人朝向哪里。
例如:
geometry_msgs::msg::Pose pose;
pose.position.x = 1.0;
pose.position.y = 2.0;
pose.position.z = 0.0;
pose.orientation.w = 1.0;
表示机器人位于:
x = 1.0
y = 2.0
z = 0.0
姿态使用四元数表示。
对于二维移动机器人来说,通常重点关注:
pose.position.x
pose.position.y
pose.orientation
因为地面机器人一般在平面上运动,z 方向变化较少。
(5)geometry_msgs::msg::PoseStamped 带时间戳和坐标系的位姿
PoseStamped 可以理解为:
PoseStamped = Header + Pose
也就是在 Pose 的基础上增加了时间戳和坐标系信息。
它的结构大概是:
std_msgs::msg::Header header
geometry_msgs::msg::Pose pose
常用字段有:
pose_stamped.header.stamp
pose_stamped.header.frame_id
pose_stamped.pose.position.x
pose_stamped.pose.position.y
pose_stamped.pose.position.z
pose_stamped.pose.orientation.x
pose_stamped.pose.orientation.y
pose_stamped.pose.orientation.z
pose_stamped.pose.orientation.w
其中:
header.stamp
表示这个位姿对应的时间。
header.frame_id
表示这个位姿属于哪个坐标系。
例如:
geometry_msgs::msg::PoseStamped target_pose;
target_pose.header.frame_id = "map";
target_pose.header.stamp = this->now();
target_pose.pose.position.x = 3.0;
target_pose.pose.position.y = 2.0;
target_pose.pose.orientation.w = 1.0;
表示:
机器人目标点在 map 坐标系下,位置是 (3.0, 2.0)。
PoseStamped 在导航里面非常常见,例如:
相比 Pose,PoseStamped 更完整,因为它说明了:
这个位姿是什么时候的?
这个位姿属于哪个坐标系?
(6)geometry_msgs::msg::Point 描述三维空间中的一个点
Point 用来表示三维空间中的一个坐标点。
它只有三个字段:
point.x
point.y
point.z
例如:
geometry_msgs::msg::Point point;
point.x = 1.0;
point.y = 2.0;
point.z = 0.0;
表示空间中的一个点:
(1.0, 2.0, 0.0)
Point 常用于:
需要注意的是,Point 只表示位置,不表示朝向。
也就是说:
(7)geometry_msgs::msg::Quaternion 描述姿态和旋转
Quaternion 用来描述三维空间中的姿态,也就是物体的朝向。
它包含四个字段:
quaternion.x
quaternion.y
quaternion.z
quaternion.w
例如:
geometry_msgs::msg::Quaternion q;
q.x = 0.0;
q.y = 0.0;
q.z = 0.0;
q.w = 1.0;
这通常表示没有旋转,也就是默认朝向。
在机器人中,姿态有很多表示方式,比如:
ROS2 中很多消息默认使用四元数表示姿态,例如:
Pose.orientation
Odometry.pose.pose.orientation
TransformStamped.transform.rotation
对于地面移动机器人来说,最常关心的是 yaw,也就是绕 z 轴的旋转角。
但是在 ROS2 消息中,通常不是直接存 yaw,而是存成四元数:
orientation.x
orientation.y
orientation.z
orientation.w
所以实际开发中,经常需要在:
yaw 角
和:
Quaternion 四元数
之间进行转换。
(8)geometry_msgs::msg::Vector3 描述三维向量
Vector3 用来描述三维向量,包含三个字段:
vector.x
vector.y
vector.z
例如:
geometry_msgs::msg::Vector3 vec;
vec.x = 1.0;
vec.y = 0.0;
vec.z = 0.0;
它看起来和 Point 很像,都是:
x
y
z
但是含义不一样。
Point 表示一个空间位置:
我在哪里?
Vector3 表示一个方向量或物理量:
比如 Twist 里面就用到了 Vector3:
geometry_msgs::msg::Twist vel_cmd;
vel_cmd.linear.x = 0.2;
vel_cmd.angular.z = 0.5;
这里的:
linear
angular
本质上都是 Vector3 类型。
所以:
Twist.linear.x
Twist.angular.z
能够成立,是因为 linear 和 angular 都是 Vector3。
(9)geometry_msgs::msg::TransformStamped 描述两个坐标系之间的变换关系
TransformStamped 用来描述一个坐标系到另一个坐标系之间的关系。
它可以理解为:
TransformStamped = Header + child_frame_id + Transform
常见结构如下:
header.stamp
header.frame_id
child_frame_id
transform.translation.x
transform.translation.y
transform.translation.z
transform.rotation.x
transform.rotation.y
transform.rotation.z
transform.rotation.w
其中:
header.frame_id
表示父坐标系。
child_frame_id
表示子坐标系。
transform.translation
表示两个坐标系之间的位置偏移。
transform.rotation
表示两个坐标系之间的旋转关系。
例如:
geometry_msgs::msg::TransformStamped transform;
transform.header.stamp = this->now();
transform.header.frame_id = "odom";
transform.child_frame_id = "base_link";
transform.transform.translation.x = 1.0;
transform.transform.translation.y = 2.0;
transform.transform.translation.z = 0.0;
transform.transform.rotation.w = 1.0;
这表示:
base_link 坐标系
相对于:
odom 坐标系
的位置偏移是:
x = 1.0
y = 2.0
z = 0.0
TransformStamped 在 TF 坐标变换中非常重要,常见坐标系对比表如下:
| map | 地图坐标系 / 全局坐标系 | 表示机器人在整张地图中的全局位置 | 不跟机器人动,通常固定在地图上 | SLAM、AMCL、定位系统、导航系统 | 全局定位、全局路径规划、导航目标点 |
| odom | 里程计坐标系 | 表示机器人从启动位置开始,通过里程计连续推算出来的位置 | 不跟机器人一起动,但以启动附近为参考 | 轮式里程计、视觉里程计、IMU 融合、机器人底盘 | 短时间连续定位、局部运动控制、速度估计 |
| base_link | 机器人本体坐标系 | 表示机器人自身的坐标系,通常固定在机器人底盘中心 | 跟机器人一起移动和旋转 | 机器人 URDF、底盘模型、TF 发布器 | 描述机器人自身位置、速度方向、传感器安装位置 |
| laser | 激光雷达坐标系 | 表示激光雷达自身的坐标系 | 跟机器人一起动,因为雷达安装在机器人上 | 激光雷达驱动、静态 TF | 描述 /scan 雷达数据、障碍物检测、建图导航 |
| camera_link | 相机坐标系 | 表示相机本体或相机安装位置的坐标系 | 跟机器人一起动,因为相机安装在机器人上 | 相机驱动、深度相机驱动、静态 TF | 图像、深度图、点云、视觉识别 |
| imu_link | IMU 坐标系 | 表示 IMU 传感器自身的坐标系 | 跟机器人一起动,因为 IMU 安装在机器人上 | IMU 驱动、静态 TF | 姿态估计、角速度、线加速度、惯性导航 |
| map -> odom | 地图坐标系到里程计坐标系的变换 | 通常由定位系统发布,用来修正里程计漂移 |
| odom -> base_link | 里程计坐标系到机器人本体坐标系的变换 | 通常由里程计发布,表示机器人连续运动位置 |
| base_link -> laser | 机器人本体到激光雷达的安装关系 | 通常是静态 TF,表示雷达装在机器人哪个位置 |
| base_link -> camera_link | 机器人本体到相机的安装关系 | 通常是静态 TF,表示相机装在机器人哪个位置 |
| base_link -> imu_link | 机器人本体到 IMU 的安装关系 | 通常是静态 TF,表示 IMU 装在机器人哪个位置 |
这些坐标系之间的关系,通常就是通过 TransformStamped 发布出去的。
2.3 nav_msgs:导航、定位、建图相关消息
(1)导航系统中经常出现
nav_msgs 主要用于机器人导航、定位、路径规划、地图构建等任务。
常见类型如下:
nav_msgs::msg::Odometry
nav_msgs::msg::Path
nav_msgs::msg::OccupancyGrid
(2)常见消息含义
| Odometry | 里程计信息,包括机器人位姿和速度 |
| Path | 路径信息,由一串位姿点组成 |
| OccupancyGrid | 栅格地图,常用于 SLAM 和导航 |
例如:
nav_msgs::msg::Odometry odom;
Odometry 里面通常包含两类核心信息:
pose // 机器人当前位姿
twist // 机器人当前速度
也就是说,里程计消息不仅可以描述机器人现在在哪里,还可以描述机器人当前运动速度是多少。
2.4 sensor_msgs:传感器相关消息
(1)雷达、IMU、相机、点云都在这里
sensor_msgs 主要用于传递传感器数据。
常见类型如下:
sensor_msgs::msg::LaserScan
sensor_msgs::msg::Imu
sensor_msgs::msg::Image
sensor_msgs::msg::PointCloud2
sensor_msgs::msg::JointState
sensor_msgs::msg::NavSatFix
(2)常见消息含义
| LaserScan | 二维激光雷达数据 |
| Imu | IMU 数据,包括角速度、线加速度、姿态等 |
| Image | 相机图像数据 |
| PointCloud2 | 点云数据,常用于 3D 激光雷达 |
| JointState | 关节状态,机械臂、轮子编码器都可能用到 |
| NavSatFix | GPS 定位数据 |
例如:
sensor_msgs::msg::LaserScan scan;
通常用于二维激光雷达话题,例如:
/scan
而:
sensor_msgs::msg::Imu imu;
通常用于 IMU 话题,例如:
/imu
三、总结
3.1 ROS2 消息类型整体总结
在 ROS2 中,节点之间并不是直接传递普通 C++ 变量,而是通过 消息类型 Message 进行通信。
比如:
geometry_msgs::msg::Twist vel_cmd;
这句代码的意思是:
创建一个 geometry_msgs 功能包下的 Twist 消息对象,变量名叫 vel_cmd。
它可以拆成:
| geometry_msgs | 消息所在功能包 |
| msg | 表示这是消息类型 |
| Twist | 具体消息名称 |
| vel_cmd | 自己定义的消息对象名 |
ROS2 中常见消息类型通常采用下面这种格式:
功能包名::msg::消息名 变量名;
例如:
std_msgs::msg::String msg;
geometry_msgs::msg::Twist vel_cmd;
nav_msgs::msg::Odometry odom;
sensor_msgs::msg::LaserScan scan;
3.2 常见消息包对比表
| std_msgs | 基础数据消息 | 传递简单数据,例如字符串、整数、小数、布尔值 | String、Int32、Float64、Bool |
| geometry_msgs | 几何运动消息 | 描述速度、位置、姿态、坐标点、坐标变换 | Twist、Pose、PoseStamped、Point、Quaternion、Vector3、TransformStamped |
| nav_msgs | 导航相关消息 | 描述里程计、路径、地图等导航信息 | Odometry、Path、OccupancyGrid |
| sensor_msgs | 传感器消息 | 描述雷达、IMU、相机、点云、GPS 等传感器数据 | LaserScan、Imu、Image、PointCloud2、JointState、NavSatFix |
3.3 geometry_msgs 常见消息对比表
| Twist | 速度消息 | 线速度 + 角速度 | linear、angular | /cmd_vel 速度控制 |
| Pose | 位姿消息 | 位置 + 姿态 | position、orientation | 机器人当前位置、目标位姿 |
| PoseStamped | 带时间戳和坐标系的位姿 | Header + Pose | header、pose | 导航目标点、路径点、定位结果 |
| Point | 三维空间点 | x、y、z 坐标 | x、y、z | 目标点、障碍物点、路径点 |
| Quaternion | 四元数姿态 | x、y、z、w | x、y、z、w | 描述机器人朝向、坐标旋转 |
| Vector3 | 三维向量 | x、y、z 分量 | x、y、z | 速度、角速度、加速度、方向量 |
| TransformStamped | 坐标系变换 | 时间戳 + 父子坐标系 + 平移旋转 | header、child_frame_id、transform | TF 坐标变换 |
3.4 geometry_msgs 一句话记忆表
| Twist | 描述机器人怎么运动,也就是速度 |
| Pose | 描述机器人在哪里、朝向哪里 |
| PoseStamped | 描述机器人在某个时间、某个坐标系下的位姿 |
| Point | 只描述一个点在哪里 |
| Quaternion | 描述物体或机器人朝向哪里 |
| Vector3 | 描述一个三维方向量或物理量 |
| TransformStamped | 描述两个坐标系之间的位置和旋转关系 |
3.5 常见坐标系对比表
| map | 地图坐标系 / 全局坐标系 | 不跟机器人动 | 全局定位、全局路径规划、导航目标点 |
| odom | 里程计坐标系 | 不跟机器人一起动,但会随着里程计连续推算 | 短时间连续定位、局部运动控制 |
| base_link | 机器人本体坐标系 | 跟机器人一起移动和旋转 | 描述机器人自身位置、速度方向、传感器安装基准 |
| laser | 激光雷达坐标系 | 跟机器人一起动 | 描述激光雷达数据、障碍物检测 |
| camera_link | 相机坐标系 | 跟机器人一起动 | 图像、深度图、点云、视觉识别 |
| imu_link | IMU 坐标系 | 跟机器人一起动 | 姿态估计、角速度、线加速度 |
3.6 常见 TF 关系总结表
| map -> odom | 地图坐标系到里程计坐标系的变换 | SLAM、AMCL、定位系统 |
| odom -> base_link | 里程计坐标系到机器人本体坐标系的变换 | 轮式里程计、视觉里程计、底盘节点 |
| base_link -> laser | 机器人本体到激光雷达的安装关系 | 静态 TF、URDF |
| base_link -> camera_link | 机器人本体到相机的安装关系 | 静态 TF、URDF |
| base_link -> imu_link | 机器人本体到 IMU 的安装关系 | 静态 TF、URDF |
这些坐标系之间的关系,通常就是通过:
geometry_msgs::msg::TransformStamped
发布出去的。


