📨 超级无敌具体详细讲解 ROS 中的消息(Message)+ C++ 示例
🧠 一、消息是什么?
📌 定义:
ROS 消息(Message)是 ROS 节点之间通信的数据单位。
无论你是用 Topic 传输数据、Service 传输参数,背后都在用消息类型来定义“数据长啥样”。
类似于编程语言中的结构体(
struct
),但语法更简洁。
🧩 二、消息的描述和类型
1. 消息是如何描述的?
ROS 使用一种简单的 .msg
文本文件来描述消息结构。
每一行写一个字段,格式如下:
<类型> <字段名>
例如:
int32 age
float64 height
string name
2. ROS 支持的基本消息类型
类型 | 含义 |
---|---|
int8 /int16 /int32 /int64 | 整型(有符号) |
uint8 /… | 整型(无符号) |
float32 /float64 | 浮点数 |
string | 字符串 |
bool | 布尔值 |
time /duration | 时间类型 |
Header | 标准消息头(含时间戳/坐标系) |
可以使用数组:
int32[] scores
string[3] colors
🛠 三、如何自定义消息类型(超级详细步骤)
📝 1. 创建 .msg
文件
在你的 ROS 包中创建目录:
mkdir -p my_package/msg
创建自定义消息文件 Person.msg
:
string name
int32 age
float64 height
🛠 2. 修改 CMakeLists.txt
(PS:学习ROS,C++&cmake是必须滴,煮啵也在考虑写一个cmake博文)
找到以下两处位置进行修改:
📌 添加依赖:
find_package(catkin REQUIRED COMPONENTS
std_msgs
message_generation
)
📌 注册消息:
add_message_files(
FILES
Person.msg
)
generate_messages(
DEPENDENCIES
std_msgs
)
📌 添加 catkin_package
:
catkin_package(
CATKIN_DEPENDS message_runtime std_msgs
)
🛠 3. 修改 package.xml
添加以下两行依赖:
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
🔨 4. 编译生成消息类型
cd ~/catkin_ws
catkin_make
source devel/setup.bash
🧑💻 四、如何在节点中使用消息(发布和订阅)
🐍 Python 发布者
#!/usr/bin/env python
import rospy
from std_msgs.msg import String
rospy.init_node('talker')
pub = rospy.Publisher('/chatter', String, queue_size=10)
rate = rospy.Rate(10)
while not rospy.is_shutdown():
msg = String()
msg.data = "Hello, ROS!"
pub.publish(msg)
rate.sleep()
🐍 Python 订阅者
#!/usr/bin/env python
import rospy
from std_msgs.msg import String
def callback(msg):
rospy.loginfo("Received: %s", msg.data)
rospy.init_node('listener')
sub = rospy.Subscriber('/chatter', String, callback)
rospy.spin()
🧑💻 C++ 发布者
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
int main(int argc, char **argv)
{
ros::init(argc, argv, "talker_cpp");
ros::NodeHandle nh;
ros::Publisher pub = nh.advertise<std_msgs::String>("chatter", 10);
ros::Rate loop_rate(10);
while (ros::ok())
{
std_msgs::String msg;
std::stringstream ss;
ss << "Hello from C++!";
msg.data = ss.str();
pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
🧑💻 C++ 订阅者
#include "ros/ros.h"
#include "std_msgs/String.h"
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
ROS_INFO("Received: [%s]", msg->data.c_str());
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "listener_cpp");
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe("chatter", 10, chatterCallback);
ros::spin();
return 0;
}
✳ 使用自定义消息(C++ 示例)
#include "ros/ros.h"
#include "my_package/Person.h"
int main(int argc, char **argv)
{
ros::init(argc, argv, "person_pub");
ros::NodeHandle nh;
ros::Publisher pub = nh.advertise<my_package::Person>("person_info", 10);
ros::Rate rate(1);
while (ros::ok())
{
my_package::Person p;
p.name = "Bob";
p.age = 30;
p.height = 1.75;
pub.publish(p);
rate.sleep();
}
return 0;
}
🎓 通俗解释时间!
🧠 比喻一:
如果 ROS 是一个机器人快递系统:
- 节点是快递员
- Topic 是传输通道
- 消息是快递包裹
- 消息的
.msg
就是包裹的规格清单
🧠 比喻二:
ROS 消息就像是“编程语言中的类”,但不带方法。
它是数据的“标准描述书”,所有节点根据这个描述来打包/解包消息。
✅ 总结对比表格
项目 | 内容 |
---|---|
消息是啥 | 节点之间通信的数据结构(类似 struct) |
消息定义在哪 | .msg 文件,用类型+字段名组合描述 |
支持哪些类型 | 基本类型、数组、嵌套类型、Header |
怎么自定义 | 创建 .msg → 配置 CMake → 修改 package.xml → 编译 |
怎么使用 | Publisher.publish() / Subscriber.callback() |
支持语言 | Python / C++ |
比喻 | 快递包裹、类的实例、接口协议 |