ROS自主导航学习———ROS通信机制

前言

前面ROS很多都忘记了 ,现在来重新回顾一下内容

ROS 中的基本通信机制主要有如下三种实现策略:

  • 话题通信(发布订阅模式)

  • 服务通信(请求响应模式)

  • 参数服务器(参数共享模式)

  • Action通信

ROS常用API

第 3 章 ROS通信机制进阶 · GitBookhttp://www.autolabor.com.cn/book/ROSTutorials/di-3-zhang-ros-tong-xin-ji-zhi-jin-jie.html

话题通信(发布订阅模式)

以发布订阅的方式实现不同节点之间数据交互的通信模式。

话题通信实现模型是比较复杂的,该模型如下图所示,该模型中涉及到三个角色:

  • ROS Master (管理者)
  • Talker (发布者)
  • Listener (订阅者)

ROS Master 负责保管 Talker 和 Listener 注册的信息,并匹配话题相同的 Talker 与 Listener,帮助 Talker 与 Listener 建立连接,连接建立后,Talker 可以发布消息,且发布的消息会被 Listener 订阅

ROS中的通信方式中,topic是常用的一种。对于实时性、周期性的消息,使用topic来传输是最佳的选择。topic是一种点对点的单向通信方式,这里的“点”指的是node,也就是说node之间可以通过topic方式来传递信息。topic要经历下面几步的初始化过程:首先,publisher节点和subscriber节点都要到节点管理器进行注册,然后publisher会发布topic,subscriber在master的指挥下会订阅该topic,从而建立起sub-pub之间的通信。注意整个过程是单向的。

其中在话题通信中值得注意的是

  • Subscriber接收消息会进行处理,一般这个过程叫做回调(Callback)。所谓回调就是提前定义好了一个处理函数(写在代码中),当有消息来就会触发这个处理函数,函数会对消息进行处理
  • ROS是一种分布式的架构,一个topic可以被多个节点同时发布,也可以同时被多个节点接收。

话题通信的基本操作

代码

//topic_pub1.cpp
#include"ros/ros.h"
#include<std_msgs/String.h>
#include<sstream>

int main(int args ,char *argv[])
{
    //设置编码 会在终端输出信息 防止乱码
    setlocale(LC_ALL,"");

     //初始化 ROS 节点:命名(唯一)  节点命名不能重复
    // 参数1和参数2 后期为节点传值会使用
    // 参数3 是节点名称,是一个标识符,需要保证运行后,在 ROS 网络拓扑中唯一
    ros::init(args,argv,"talker");

    //实例化句柄该类封装了 ROS 中的一些常用功能
    ros::NodeHandle nh;

     //实例化 发布者 对象
    //泛型: 发布的消息类型
    //参数1: 要发布到的话题
    //参数2: 队列中最大保存的消息数,超出此阀值时,先进的先销毁(时间早的先销毁)

    //n.advertise通过NodeHandle的对象n告诉ROS系统我要创建一个可以发布信息的对象了。这个信息是什么类型的呢?
    //<std_msgs::String>告诉ROS我要发布的是标准信息中的String类型。
    //那些信息叫啥名字呢?名字叫chatter。这个chatter就是我们之前提到的topic!

    ros::Publisher pub=nh.advertise<std_msgs::String>("chatter",10);

    std_msgs::String msg;

    std::string msg_fromt="day day up";
    int count =0; //计数器
    //逻辑(一秒10次) 可以制定循环的频率
    //程序如果在不断地发布信息,那么有时候我会想控制发布的信息的快慢,这行表示你希望你发布信息的速度为10Hz。
    //这个函数要和ros::Rate r.sleep()配合使用才能达到控制速度目的
    ros::Rate r(10);

    while(ros::ok())
    {
        std::stringstream ss;

        ss<<msg_fromt<<count;
        msg.data=ss.str();

        //发布消息
        pub.publish(msg);

        //输出消息
        ROS_INFO("发送的消息:%s",msg.data.c_str());

        r.sleep();
        count++;

        //回调函数
        ros::spinOnce();

    }
    return 0;
}
//topic_sub1.cpp
// 1.包含头文件 
#include "ros/ros.h"
#include "std_msgs/String.h"

void doMsg(const std_msgs::String::ConstPtr& msg_p){
    ROS_INFO("我听见:%s",msg_p->data.c_str());

}
int main(int argc, char  *argv[])
{
    setlocale(LC_ALL,"");
    //2.初始化 ROS 节点:命名(唯一)
    ros::init(argc,argv,"listener");
    //3.实例化 ROS 句柄
    ros::NodeHandle nh;

    //4.实例化 订阅者 对象
    ros::Subscriber sub = nh.subscribe<std_msgs::String>("chatter",10,doMsg);
    //5.处理订阅的消息(回调函数)

    //     6.设置循环调用回调函数
    ros::spin();//循环读取接收的数据,并调用回调函数处理

    return 0;
}

话题通信自定义msg  

ROS 中通过 std_msgs 封装了一些原生的数据类型,比如:String、Int32、Int64、Char、Bool、Empty.... 但是,这些数据一般只包含一个 data 字段,结构的单一意味着功能上的局限性,当传输一些复杂的数据,比如: 激光雷达的信息... std_msgs 由于描述性较差而显得力不从心,这种场景下可以使用自定义的消息类型

其中  ros::spin() 是进入了循环执行回调函数,而 r

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值