1.Publisher(发布者)与subscriber(订阅者)关系。
Publisher的主要作用是对于指定话题发布特定数据类型的消息。
下面是利用代码实现一个节点,节点创建一个Publisher并发布字符串“Hello world”,其详细内容如下:
#include <sstream>
#include "ros/ros.h" **1**
#include "std_msgs/String.h" **1**
int main (int argc,char **argv)
{
//ROS节点初始化
ros::init(argc,argv,"talker"); **2**
//创建节点句柄
ros::NodeHandle n; **3**
//创建一个Publisher,发布名为chatter的topic,消息类型为std_msgs::String
ros::Publisher chatter_pub=n.advertise<std_msgs::String>("chatter",1000); **4**
//设置循环的频率
ros::Rate loop_rate(10); **5**
int count=0;
while(ros::ok()) **6**
{
//初始化std_msgs::String类型的消息
std_msgs::String msg; **7**
std::Stringstream ss; **7**
ss<<"hello world"<<count; **7**
msg.data=ss.str(); **7**
//发布消息
ROS_INFO("%s",msg.data.c_str()); **8**
chatter_pub.publish(msg); **9**
//循环等待回调函数
ros::spinOnce(); **10**
//按照循环频率延时
loop_rate.sleep(); **11**
++count;
}
return 0;
}
代码说明:
“1”:“ros/ros.h”包含了大部分ROS中通用的头文件
“2”:初始化ROS节点,init函数包含三个参数,前两个参数是命令行或launch文件输入的参数;第三个参数定义了Publisher节点的名称,而且该名称在运行的ROS中必须是独一无二的,不允许同时存在相同名称的两个节点。
“3”:创建一个节点句柄,方便对节点资源的使用和管理。
“4”:在ROS master注册一个Publisher,并告诉系统Publisher节点将会发布以chatter为话题的String类型消息。第二个参数表示消息队列的大小,当消息数量超过队列大小时,ROS会自动删除队列中最早入对的消息。
“5”:设置循环的频率,单位是Hz。
“6”:进入节点的主循环,遇到异常的状况便会返回false,跳出循环。异常情况包括:
- 收到SIGINT信号(Ctrl+c)
- 被另外一个相同名称的节点踢掉线
- 节点调用了关闭函数ros::shutdown()
- 所有ros::NodeHandles句柄被销毁
“7”: 初始化即将发布的消息。
“8”:ROS_INFO类似与C/C++中的printf/cout函数,用来打印日志信息。
“9”:发布封装完毕的消息msg。消息发布后,Master会查找订阅该话题的节点,并且帮助两个节点建立连接,完成消息的传输。
“10”:用来处理节点订阅话题的所有回调函数
“11”:调用休眠函数使节点进入睡眠在台。但是10Hz的睡眠时间过后,节点又会开始下一阶段的循环工作
总结Publisher的流程,为:
- 初始化ROS节点
- 向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型。
- 按照一定频率循环发布消息
创建Subscriber:
创建一个Subscriber以订阅Publisher节点发布的“Hello world”字符串,其源码为:
#include "ros/ros.h"
#include "std_msgs/String.h"
//接收到订阅的消息后,会进入消息回调函数
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
//将接收到的消息打印出来
ROS_INFO("I heard: [%s]",msg->data.c_str());
}
int main(int argc,char **argv)
{
//初始化ROS节点
ros::init(argc,argv,"listener");
//创建节点句柄
ros::NodeHandle n;
//创建一个Subscriber,订阅名为chatter的话题,注册回调函数chatterCallback
ros::Subscriber sub=n.subscribe("chatter",1000,chatterCallback);
//循环等待回调函数
ros::spin();
return 0;
}
Subscriber的实现简要流程:
- 初始化ROS节点
- 订阅需要的话题
- 循环等待话题消息,接收到消息后进入回调函数
- 在回调函数中完成消息处理