ROS系列学习(二)通信机制

ROS中的通信机制包括话题、服务和参数服务器。话题通信基于发布订阅模式,适合不断更新的数据传输,如激光雷达信息。服务通信采用请求响应模式,适用于有一定逻辑处理需求的场景。参数服务器则用于不同节点间的数据共享。文章详细介绍了话题通信的理论模型、代码实现及自定义msg的创建与调用,服务通信的工作流程,以及自定义srv的使用,并探讨了参数服务器的功能和应用实例。
摘要由CSDN通过智能技术生成

ROS系列学习(二)通信机制

在学会如何创建工作空间和节点后,需要掌握的是如何建立这些节点之间的通信。ROS的基本通信机制主要有三种实现策略:
1.话题通信(发布订阅模式)
2.服务通信(请求响应模式)
3.参数服务器(参数共享模式)


一、话题通信

话题通信是ROS中使用频率最高的一种通信模式,话题通信是基于发布订阅模式的,也即:一个节点发布消息,另一个节点订阅该消息。
1.概念:以发布订阅的方式实现不同节点之间数据交互的通信模式。
2.作用:用于不断更新的、少逻辑处理的数据传输场景。
3.实例
1).实现最基本的发布订阅模型,发布方以固定频率发送一段文本,订阅方接收文本并输出。
2).实现对自定义消息的发布与订阅。

理论模型

话题通信的理论模型主要包括三个对象:
1.管理者(ROS Master)
2.发布者(Publisher)
3.订阅者(Subscriber)

ROS Master负责保管Publisher和Subscriber注册的信息,并匹配话题相同的Publisher与Subscriber,帮助二者建立连接,连接建立后,Publisher可以发布消息,且发布的消息会被Subscriber订阅。
在这里插入图片描述
整个通信过程的流程如下:
1.Publisher注册
publisher通过RPC向ROS Master发送注册信息,包括发布信息以及话题名称,ROS Master将publisher的注册信息注册到注册表中。
2.Subscriber注册
3.ROS Master匹配注册信息
ROS Master根据注册表内的信息匹配Publisher和Subscriber,并通过RPC向Subscriber发送Publisher的地址信息。
4.Subscriber向Publisher发送请求
Subscriber和Publisher成功匹配,Subscriber收到Publisher的地址后,向Publisher发送连接请求,传输订阅的话题名称,消息类型和通信协议(TCP/UDP)。
5.Publisher确定请求
Subscriber收到Subscriber的请求之后,通过RPC向Subscriber确认连接信息,并发送自身的TCP地址信息。
6.Subscriber和Publisher建立连接
Subscriber和Publisher根据TCP协议建立连接。
7.Publisher向Subscriber发布消息
注意1:上述实现流程中,前五步使用的RPC协议,最后两步使用的是TCP协议。
注意2:Publisher与 Subscriber的启动无先后顺序要求。
注意3:Publisher与 Subscriber都可以有多个。
注意4:Publisher与Subscriber连接建立后,不再需要ROS Master。也即,即便关闭ROS Master,Publisher与Subscriber照常通信。

话题通信的代码实现

1.Publisher(C++)

*/
 // 1.包含头文件 
 #include "ros/ros.h"
 #include "std_msgs/String.h" //普通文本类型的消息
 #include 
 
 int main(int argc, char  *argv[])
 {
      
 //设置编码
setlocale(LC_ALL,"");

//2.初始化 ROS 节点:命名(唯一)
// 参数1和参数2 后期为节点传值会使用
// 参数3 是节点名称,是一个标识符,需要保证运行后,在 ROS 网络拓扑中唯一
ros::init(argc,argv,"talker");
//3.实例化 ROS 句柄
ros::NodeHandle nh;//该类封装了 ROS 中的一些常用功能

//4.实例化 发布者 对象
//泛型: 发布的消息类型
//参数1: 要发布到的话题
//参数2: 队列中最大保存的消息数,超出此阀值时,先进的先销毁(时间早的先销毁)
ros::Publisher pub = nh.advertise("chatter",10);

//5.组织被发布的数据,并编写逻辑发布数据
//数据(动态组织)
std_msgs::String msg;
// msg.data = "你好啊!!!";
std::string msg_front = "Hello 你好!"; //消息前缀
int count = 0; //消息计数器

//逻辑(一秒10次)
ros::Rate r(1);

//节点不死
while (ros::ok())
{
   
    //使用 stringstream 拼接字符串与编号
    std::stringstream ss;
    ss << msg_front << count;
    msg.data = ss.str();
    //发布消息
    pub.publish(msg);
    //加入调试,打印发送的消息
    ROS_INFO("发送的消息:%s",msg.data.c_str());

    //根据前面制定的发送贫频率自动休眠 休眠时间 = 1/频率;
    r.sleep();
    count++;//循环结束前,让 count 自增
    //暂无应用
    ros::spinOnce();
}


return 0;
}

2.Subscriber(C++)

/*
 需求: 实现基本的话题通信,一方发布数据,一方接收数据,
      实现的关键点:
      1.发送方
      2.接收方
      3.数据(此处为普通文本)
 
 
 消息订阅方:
    订阅话题并打印接收到的消息

实现流程:
    1.包含头文件 
    2.初始化 ROS 节点:命名(唯一)
    3.实例化 ROS 句柄
    4.实例化 订阅者 对象
    5.处理订阅的消息(回调函数)
    6.设置循环调用回调函数

*/
// 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());
// 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("chatter",10,doMsg);
//5.处理订阅的消息(回调函数)

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

return 0;
}

3.配置 CMakeLists.txt

 add_executable(Hello_pub src/Hello_pub.cpp)
 add_executable(Hello_sub src/Hello_sub.cpp)
 
 target_link_libraries(Hello_pub ${catkin_LIBRARIES}s)
 target_link_libraries(Hello_sub ${catkin_LIBRARIES}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值