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. 发布方
  2. 接收方
  3. 数据(此处为普通文本)

流程:

  1. 编写发布方实现;
  2. 编写订阅方实现;
  3. 编辑配置文件;
  4. 编译并执行。

 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;
}

 配置

 执行

  1. ctrl+shift+B
  2. roscore
  3. cd 文件夹
  4. 编译source ./devel/setup.bash
  5. 运行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;
}

 配置

 执行

  1. 编译
  2. 启动 roscore;
  3. 启动发布节点;
  4. 启动订阅节点。

 3.计算图

命令行:rqt_graph

 

posted on 2021-07-12 16:03  蔡军帅  阅读(896)  评论(0编辑  收藏  举报