在Robot Operating System (ROS)中,发布与订阅是一种基于主题的异步消息传递机制,用于节点间的通信。ROS的设计是围绕着这一概念,它允许不同节点之间解耦,每个节点专注于自己的任务,通过发布和订阅消息来与其他节点交互。
### 发布者 (Publisher)
发布者是向特定主题发送消息的节点。这些消息可以是传感器读数、控制指令、状态更新等。发布者不需要知道谁(如果有的话)正在监听这些消息,只需要关注发送消息本身。
#### 如何创建一个发布者:
1. **初始化ROS节点**:每个ROS节点在开始之前都需要初始化,通常是通过`ros::init()`函数或在Python中通过`rospy.init_node()`。
2. **创建发布者对象**:在C++中,你可以使用`ros::NodeHandle`来创建一个`ros::Publisher`对象。在Python中,你可以使用`rospy.Publisher()`。
3. **设置消息类型**:发布者需要知道它将要发送的消息类型,例如`std_msgs/String`或`sensor_msgs/Image`。
4. **发布消息**:一旦创建了发布者,你就可以在需要的时候调用它的`publish()`方法来发送消息。
### 订阅者 (Subscriber)
订阅者是监听特定主题的节点,当主题上有新消息时,订阅者会收到这些消息。订阅者通过回调函数处理这些消息,该函数会在每次接收到新消息时被调用。
#### 如何创建一个订阅者:
1. **初始化ROS节点**:同样地,订阅者也需要初始化ROS节点。
2. **创建订阅者对象**:使用`ros::NodeHandle`在C++中创建`ros::Subscriber`对象,在Python中使用`rospy.Subscriber()`。
3. **设置回调函数**:订阅者需要一个回调函数,这个函数将在每次接收到新消息时被调用。这个函数的签名应该与所接收的消息类型相匹配。
4. **处理消息**:在回调函数中,你可以处理接收到的消息,比如显示信息、存储数据或触发某些行为。
### 示例代码
以下是一个简单的C++示例,展示如何创建一个发布者和一个订阅者:
#include "ros/ros.h"
#include "std_msgs/String.h"// 发布者
void publishMessage() {ros::NodeHandle n;ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);std_msgs::String msg;msg.data = "Hello ROS!";while (ros::ok()) {chatter_pub.publish(msg);ros::Duration(1).sleep();}
}// 订阅者
void chatterCallback(const std_msgs::String::ConstPtr& msg) {ROS_INFO("I heard: [%s]", msg->data.c_str());
}int main(int argc, char **argv) {ros::init(argc, argv, "subscriber_node");ros::NodeHandle n;ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);ros::spin();return 0;
}
在这个例子中,`publishMessage`函数创建了一个发布者,它向`chatter`主题发送字符串消息。`chatterCallback`函数是订阅者的回调函数,它会打印出从`chatter`主题接收到的消息。
### 注意事项
- 在C++中,`ros::spin()`或`ros::spinOnce()`通常用于让节点保持活跃,处理传入的消息。在Python中,这通常是在`rospy.init_node()`之后隐式处理的。
- 节点必须在发布或订阅消息之前被初始化。
- 消息类型必须在发布和订阅之间一致。
- 主题名称在发布者和订阅者之间也必须匹配。