Ros1中的pub和sub是如何建立连接的?

Ros1中的pub和sub是如何建立连接的?

先上时序图,一睹为快

请添加图片描述

连接拓扑关系

请添加图片描述

简要描述连接拓扑关系:

pub<–>rosmaster: pub节点进程与rosmaster使用xmlrpc机制进程通讯,xmlrpc是基于xml格式和http协议的一种rpc(remote procedure call)。

sub<–>rosmaster: 同pub节点。

pub<–>sub: 节点间使用socket(tcp/udp传输层协议)进行连接

详细流程探究

方法

源码: 下载ros源码并编译(可参考上篇文章),也可以直接使用ros wiki链接进行操作。

断点调试:

  1. 节点连接主要是在ros_comm/roscpp,所以修改roscpp下的CMakeLists文件,增加编译debug选项(add_definitions("-Wall -g"))。
  2. 编译源码,将libroscpp.so放到的你ros环境的lib目录下(例如:/opt/ros/melodic/lib)。
  3. 在ros的tutorial中编写talker、listener示例(注意两个的CMakeLists也要增加add_definitions("-Wall -g"))。
  4. gdb运行talker、listener。

流程描述

talker主要代码:

    ros::init(argc, args, "talker");
    ros::NodeHandle n;
    ros::Publisher pub = n.advertise<talker::Num>("Num", 1000);

listener主要代码

    ros::init(argc, args, "listener");
    ros::NodeHandle n;
    ros::Subscriber sub = n.subscribe("Num", 1000, NumCallback);

可以发现相同的代码为ros::init()、ros::NodeHandle n;

ros::init()流程主要是进行命名空间的mapping、注册退出回调、ros::console日志模块初始化,network初始化(主要根据传参来设置host、tcpros_server_port端口)、master初始化(主要根据传参和环境变量来设置master的uri)、this_node的初始化,file_log的初始化,param的初始化,这部分抽时间单独写一篇。
在这里插入图片描述
ros::NodeHandle n; 包含了NodeHandle的构造函数,在NodeHandle的构造函数里调用了construct()内部函数,然后执行ros::start(),启动整个通信框架(这里有个意思的点是,使用引用计数来统计NodeHandle构造的次数(构造函数中++,析构函数–,这个引用计数属于文件对象隶属于node_handle.cpp),首次构造会进行ros::start,析构函数中当引用计数为0时进行ros::shutdown;

比较重要的时ros::start(), 启动ros整个通信框架,主要启动TopicManager、PollManager、ConnectionManager, XMLRPCManager.

ConnectionManager.start: 启动tcpros的服务端执行(执行tcpros的bind,listen,此处服务端bind的port值为0,让kernel自动分配端口,然后保存端口,当sub上线的时候通过xmlrpc经过rosmaster将端口发送到给sub,然后sub进行connect连接)。

Q1: tcpserver的port端口产生?
A1: 端口默认是从入参中__tcpros_server_port=xxx获得,如果启动时无该参数,则port为0,此时使用listen监听socket时,内核会自动分配端口,随后通过getsockname获取自动分配的port。

Q2: tcpserver的ip地址怎么产生?
A2: network::getHost获取,默认从入参__hostname=xxx获得,如果启动参数无该参数,则使用gethostname获取本端ip地址。

Q3: tcpclient如果获取服务端的ip和端口?
A3: 首先对于pub/sub来讲,pub属于tcpserver端,sub属于tcpclient端;tcpserver在nodehandle构造的时候进行listen启动;tcpclient端什么时候进行connect呢,只有当pub和sub配对之后才进行(配对意味着pub执行了advertise,sub执行了subscribe); 那又分为两种情况,第一种情况先advertise后subscribe,此时sub进行subscribe会使用requestTopic的xmlrpc调用至rosmaster,rosmaster通过xmlrpc调用至pub,最终将pub的port和ip返回至sub,然后进行connect;
第二种情况,先subscribe再advertise,此时pub进行advertise后,会触发pubupdate(传递pub的port和ip),然后使用xmlrpc远程调用至rosmaster,rosmaster然后通过xmlrpc远程调用sub,进而sub注册的回调函数被调用,在回调函数中执行connect;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值