ROS话题通信案例(一)——发布者订阅者传递消息(C++)
参考视频:【奥特学园】ROS机器人入门课程《ROS理论与实践》零基础教程_哔哩哔哩_bilibili
参考文档:http://www.autolabor.com.cn/book/ROSTutorials/
话题通信实现模型是比较复杂的,该模型如下图所示,该模型中涉及到三个角色:
- ROS Master (管理者)
- Talker (发布者)
- Listener (订阅者)
ROS Master 负责保管 Talker 和 Listener 注册的信息,并匹配话题相同的 Talker 与 Listener,帮助 Talker 与 Listener 建立连接,连接建立后,Talker 可以发布消息,且发布的消息会被 Listener 订阅。
需求:
编写发布订阅实现,要求发布方以10HZ(每秒10次)的频率发布文本消息,订阅方订阅消息并将消息内容打印输出。
分析:
在模型实现中,ROS master 不需要实现,而连接的建立也已经被封装了,需要关注的关键点有三个:
- 发布方
- 接收方
- 数据(此处为普通文本)
流程:
- 编写发布方实现;
- 编写订阅方实现;
- 编辑配置文件;
- 编译并执行。
1.发布方发布消息
#include "ros/ros.h" #include "std_msgs/String.h" /* 发布方实现: 1.包含头文件; ROS中文本类型 ----> std_msgs/String.h 2.初始化ROS节点; 3.创建节点句柄; 4.创建发布者对象; 5.编写发布逻辑并发布数据v */ int main(int argc, char *argv[]) { // 2.初始化ROS节点; ros::init(argc, argv,"erGouZi"); // 3.创建节点句柄; ros::NodeHandle nh; // 4.创建发布者对象; ros::Publisher pub = nh.advertise<std_msgs::String>("House",10); // 5.编写发布逻辑并发布数据v //先创建被发布的消息 std_msgs::String msg; //编写循环,循环中发布数据 while(ros::ok()) { msg.data="hello,I'm erGouZi"; pub.publish(msg); } return 0; }
配置
执行
- ctrl+shift+B
- roscore
- cd 文件夹
- 编译source ./devel/setup.bash
- 运行rosrun 包 映射名
打印出发布的消息并编号
#include "ros/ros.h" #include "std_msgs/String.h" #include <sstream> /* 发布方实现: 1.包含头文件; ROS中文本类型 ----> std_msgs/String.h 2.初始化ROS节点; 3.创建节点句柄; 4.创建发布者对象; 5.编写发布逻辑并发布数据v */ int main(int argc, char *argv[]) { setlocale(LC_ALL,""); // 2.初始化ROS节点; ros::init(argc, argv,"erGouZi"); // 3.创建节点句柄; ros::NodeHandle nh; // 4.创建发布者对象; ros::Publisher pub = nh.advertise<std_msgs::String>("House",10); // 5.编写发布逻辑并发布数据; //要求以 10HZ 的频率发布数据,并且文本后添加编号 //先创建被发布的消息 std_msgs::String msg; //发布频率 ros::Rate rate(10); //设置编号 int count = 0; //休眠以防没注册完已发布数据 ros::Duration(3).sleep(); //编写循环,循环中发布数据 while(ros::ok()) { count++; //msg.data="hello,I'm erGouZi"; //实现字符串凭借数字 std::stringstream ss; ss << "hello ...>" <<count; msg.data = ss.str(); pub.publish(msg); //添加日志 ROS_INFO("发布的数据是:%s",ss.str().c_str()); rate.sleep(); ros::spinOnce();//官方建议,处理回调函数 } return 0; }
执行
2.订阅者订阅消息
#include "ros/ros.h" #include "std_msgs/String.h" /* 订阅方实现: 1.包含头文件; ROS中文本类型 ----> std_msgs/String.h 2.初始化ROS节点; 3.创建节点句柄; 4.创建订阅方对象; 5.处理订阅的数据。 6.spin()函数 */ void doMsg(const std_msgs::String::ConstPtr &msg) { //通过msg获取并操作订阅到的数据 ROS_INFO("翠花订阅的数据:%s",msg->data.c_str()); } int main(int argc, char *argv[]) { setlocale(LC_ALL,""); // 2.初始化ROS节点; ros::init(argc,argv,"cuiHua"); // 3.创建节点句柄; ros::NodeHandle nh; // 4.创建订阅方对象; ros::Subscriber sub = nh.subscribe("House",10,doMsg); // 5.处理订阅的数据。 ros::spin(); return 0; }
配置
执行
- 编译
- 启动 roscore;
- 启动发布节点;
- 启动订阅节点。
3.计算图
命令行:rqt_graph