Bootstrap

【ROS理论与实践-赵虚左老师】Chap2 ROS通信机制

第二章 ROS通信机制

通信是ROS中的核心 Core

机器人是一种高度复杂的系统性实现,在机器人上可能集成各种传感器(雷达、摄像头、GPS…)以及运动控制实现,为了解耦合,在ROS中每一个功能点都是一个单独的进程,每一个进程都是独立运行的。更确切的讲,ROS是进程(也称为Nodes)的分布式框架。 因为这些进程甚至还可分布于不同主机,不同主机协同工作,从而分散计算压力。不过随之也有一个问题:
不同的进程是如何通信的?也即不同进程间如何实现数据交换的?在此我们就需要介绍一下ROS中的通信机制了。

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

话题通信 topic(发布订阅模式) 抖音知乎关注

服务通信service (请求响应模式) 访问互联网

参数服务器(参数共享模式) 公司小吃中心

2.1 话题通信(topic)

2.1.1 理论模型、概述和C++实现

话题通信是ROS中使用频率最高的一种通信模式,话题通信是基于发布订阅模式的,也即:一个节点发布消息,另一个节点订阅该消息。话题通信的应用场景也极其广泛,比如下面一个常见场景:

机器人在执行导航功能,使用的传感器是激光雷达,机器人会采集激光雷达感知到的信息并计算,然后生成运动控制信息驱动机器人底盘运动。

在上述场景中,就不止一次使用到了话题通信。

--------以激光雷达信息的采集处理为例,在 ROS 中有一个节点需要时时的发布当前雷达采集到的数据,导航模块中也有节点会订阅并解析雷达数据。
--------再以运动消息的发布为例,导航模块会根据传感器采集的数据时时的计算出运动控制信息并发布给底盘,底盘也可以有一个节点订阅运动信息并最终转换成控制电机的脉冲信号。
以此类推,像雷达、摄像头、GPS… 等等一些传感器数据的采集,也都是使用了话题通信,换言之,话题通信适用于不断更新的数据传输相关的应用场景。

核心要素三个:
发布方 订阅方 话题

话题 topic
发布方 订阅方 话题
作用:
用于不断更新的、少逻辑处理的数据传输场景。

流程
联想媒婆撮合

bar为话题名称
TIPS:
1.使用的协议有RPC和TCP
RPC协议是远程调用
2.步骤0和1没有顺序关系
3.talker和listener都可以存在多个
4.talker和listener建立连接后,master(管理匹配话题)就可以关闭了(也就是roscore可以关闭了)
5.上述实现流程已经封转了,以后直接调用即可。

master可以根据话题建立发布者和订阅者之间的连接

话题通信应用时需要注意的点
1.大部分实现已经被封装了
2.话题设置
3.关注发布者实现
4.关注订阅者实现
5.关注消息载体(两者通信使用的数据)

计算机或者程序都是对现实世界的仿真。。。学习的时候要善于将理论模型映射到现实模型,任何理论都来源于生活

补充3:

订阅时,第一条数据丢失

原因: 发送第一条数据时, publisher 还未在 roscore 注册完毕

解决: 注册后,加入休眠 ros::Duration(3.0).sleep(); 延迟第一条数据的发送

回调函数ROS中经常用到
每订阅到一个数据,回调函数就被执行一次
类似于中断函数,当订阅到消息后,回调函数才被调用

有点类似于小鬼子踩地雷后 地雷才爆炸,回调函数啥会被执行不是我们可以控制的,是外部相关机制控制的。
而普通函数的调用类似于打鬼子需要造子弹(造子弹可以看作一个函数)

计算图 显示的就是节点之间的关系

解耦合

解耦合的特点的一个体现:
不用语言书写的节点也是可以通信的
跨物种(手动狗头)

2.1.2 话题通信自定义msg

发布消息变为自定义类型
可以发布复合信息

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

自定义msg类似于C++的结构体

generate_messages(
DEPENDENCIES
std_msgs ##复合自定义消息类型中的每个字段数据类型都是最为基本的标准数据类型 也就是复合的消息实现需要依赖于标准消息实现
)

在这里插入图片描述
在这里插入图片描述
tips:如果2里面的功能包编写的有问题。编译一定会出问题 。但是如果2没问题3有问题则可能会出现编译也可以通过,但是运行不对,产生异常。
简单地理解为2是编译时的依赖,3为运行时的依赖。
package.xml中添加编译依赖与执行依赖
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

编译生成的中间文件 分为c++调用和python调用的

devel是开发文件夹

C++ 需要调用的中间文件(…/工作空间/devel/include/包名/xxx.h)
Python 需要调用的中间文件(…/工作空间/devel/lib/python3/dist-packages/包名/msg)

在这里插入图片描述

后续调用相关msg时,是从这些中间文件调用的

vscode配置一下
方便vscode找到相关的头文件 让vscode知道头文件在哪(head file)
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
这样就不会出现msg没有编译 cpp文件写好后 同时编译产生的头文件无法使用的问题。

在这里插入图片描述

在这里插入图片描855述

自定义消息类型的话需要在cmakelist多配置两行

add_dependencies(person_talker ${PROJECT_NAME}_generate_messages_cpp)
add_dependencies(person_listener ${PROJECT_NAME}_generate_messages_cpp)

话题通信

2.2 服务通信

服务通信也是ROS中一种极其常用的通信模式服务通信是基于请求响应模式的,是一种应答机制。也即: 一个节点A向另一个节点B发送请求,B接收处理请求并产生响应结果返回给A。比如如下场景:

机器人巡逻过程中,控制系统分析传感器数据发现可疑物体或人… 此时需要拍摄照片并留存。

在上述场景中,就使用到了服务通信。

一个节点需要向相机节点发送拍照请求,相机节点处理请求,并返回处理结果
与上述应用类似的,服务通信更适用于对时时性有要求、具有一定逻辑处理的应用场景。

概念
以请求响应的方式实现不同节点之间数据交互的通信模式。
类似于访问互联网

作用
用于偶然的、对实时性有要求、有一定逻辑处理需求的数据传输场景。

案例
实现两个数字的求和,客户端节点,运行会向服务器发送两个数字,服务器端节点接收两个数字求和并将结

2.2.1 服务通信理论模型

服务通信较之于话题通信更简单些,理论模型如下图所示,该模型中涉及到三个角色:

ROS master(管理者)
Server(服务端)
Client(客户端)

话题(也就是服务) 字符串形式

ROS Master 负责保管 Server 和 Client 注册的信息,并匹配话题相同的 Server 与 Client ,帮助 Server 与 Client 建立连接,连接建立后,Client 发送请求信息,Server 返回响应信息。

在这里插入图片描述
流程:
在这里插入图片描述
1234类比公司地址
3456类比公司服务电话

关注点;
0.
1.也用到了 话题也就是服务(bar) 话题 话题 都需要话题,保证服务端和客户端 有相同的话题
2.实现的时候,关注服务端 ~接收到请求(数据)如何处理
3.关注客户端怎么请求数据,接受到响应之后如何处理
4.涉及到中间的数据载体 请求和响应的数据需要设定成固定格式的 可能需要自己定义数据载体

整个流程由以下步骤实现:

0.Server注册
Server 启动后,会通过RPC在 ROS Master 中注册自身信息,其中包含提供的服务的名称。ROS Master 会将节点的注册信息加入到注册表中。

1.Client注册
Client 启动后,也会通过RPC在 ROS Master 中注册自身信息,包含需要请求的服务的名称。ROS Master 会将节点的注册信息加入到注册表中。

2.ROS Master实现信息匹配
ROS Master 会根据注册表中的信息匹配Server和 Client,并通过 RPC 向 Client 发送 Server 的 TCP 地址信息。

3.Client发送请求
Client 根据步骤2 响应的信息,使用 TCP 与 Server 建立网络连接,并发送请求数据。

4.Server发送响应
Server 接收、解析请求的数据,并产生响应结果返回给 Client。

注意:

1.客户端请求被处理时,需要保证服务器已经启动;
2.服务端和客户端都可以存在多个。
类似于多个公司和多个用户

2.2.2 服务通信自定义srv

定义srv文件
**srv 文件内的可用数据类型与 msg 文件一致,且定义 srv 实现流程与自定义 msg 实现流程类似,都是基于std_msgs标准+

在这里插入图片描述

在这里插入图片描述

argc是命令行总的参数个数
argv[]是argc个参数,其中第0个参数是程序的全名,以后的参数
命令行后面跟的用户输入的参数,

return
如果执行了return语句,那么后面的语句将会不执行。当前函数只要执行了return,之后的代码是不可能执行的
如果没到return,比如return 在 if里面,而if没满足条件,那有可能执行后面的语句

在这里插入图片描述

问题:
如果先启动客户端,那么会请求异常
需求:
如果先请求客户端,不要直接抛出异常,而是挂起,等待服务器启动后,再正常请求 这种问题很常见 因为节点一多 难免有些顺序不能保证

解决:
提供了内置函数 这些函数可以让客户端启动后挂起,等待服务端启动

在客户端发送请求前添加:client.waitForExistence();
或:ros::service::waitForService(“AddInts”);(话题名)
这是一个 阻塞式 函数,只有服务启动成功后才会继续执行

阻塞式函数

在这里插入图片描述

2.3 参数服务器

参数服务器在ROS中主要用于实现不同节点之间的数据共享。参数服务器相当于是独立于所有节点的一个公共容器,可以将数据存储在该容器中,被不同的节点调用,当然不同的节点也可以往其中存储数据,关于参数服务器的典型应用场景如下:

导航实现时,会进行路径规划,比如: 全局路径规划,设计一个从出发点到目标点的大致路径。本地路径规划,会根据当前路况生成时时的行进路径

上述场景中,全局路径规划和本地路径规划时,就会使用到参数服务器:

路径规划时,需要参考小车的尺寸,我们可以将这些尺寸信息存储到参数服务器,全局路径规划节点与本地路径规划节点都可以从参数服务器中调用这些参数
参数服务器,一般适用于存在数据共享的一些应用场景。

概念
以共享的方式实现不同节点之间数据交互的通信模式。

作用
存储一些多节点共享的数据,类似于全局变量。

案例
实现参数增 删 改 查操作。

77777
注意:参数服务器不是为高性能而设计的,因此最好用于存储静态的非二进制的简单数据

rosparam list 查看参数服务器的所有参数

rosparam get /radius 查看参数服务器中的某一个参数的值

1 参数增加与修改

在这里插入图片描述

2 参数查找

param(键,默认值)
存在,返回对应结果,否则返回默认值

    getParam(键,存储结果的变量)
        存在,返回 true,且将值赋值给参数2
        若果键不存在,那么返回值为 false,且不为参数2赋值

    getParamCached键,存储结果的变量)--提高变量获取效率
        存在,返回 true,且将值赋值给参数2
        若果键不存在,那么返回值为 false,且不为参数2赋值

    getParamNames(std::vector<std::string>)
        获取所有的键,并存储在参数 vector 中 

    hasParam(键)
        是否包含某个键,存在返回 true,否则返回 false

    searchParam(参数1,参数2)
        搜索键,参数1是被搜索的键,参数2存储搜索结果的变量

ros::param ----- 与 NodeHandle 类似

在这里插入图片描述

3 参数删除

删除参数的时候只能删一次。因为第一次已经删除了 所以第二次删除的时候会报删除失败的提示

参数操作(C++实现)

2.4 常用命令(基本用来测试 测试 测试)

机器人系统中启动的节点少则几个,多则十几个、几十个,不同的节点名称各异,通信时使用话题、服务、消息、参数等等都各不相同,一个显而易见的问题是: 当需要自定义节点和其他某个已经存在的节点通信时,如何获取对方的话题、以及消息载体的格式呢?

在 ROS 同提供了一些实用的命令行工具,可以用于获取不同节点的各类信息,常用的命令如下:

rosnode : 操作节点
rostopic : 操作话题
rosservice : 操作服务

rosmsg : 操作msg消息
rossrv : 操作srv消息
rosparam : 操作参数

2.4.1 rosnode

rosnode 是用于获取节点信息的命令

rosnode ping 测试到节点的连接状态
rosnode list 列出活动节点
rosnode info 打印节点信息
rosnode machine 列出指定设备上节点
rosnode kill 杀死某个节点
rosnode cleanup 清除不可连接的节点,也就是清除僵尸节点(已经关掉了节点,理论上节点已经死了,但是master还不知道)

2.4.2 rostopic(话题通信相关 topic)

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

rostopic包含rostopic命令行工具,用于显示有关ROS 主题的调试信息,包括发布者,订阅者,发布频率和ROS消息。它还包含一个实验性Python库,用于动态获取有关主题的信息并与之交互。

rostopic bw 显示主题使用的带宽
rostopic delay 显示带有 header 的主题延迟
rostopic echo 打印消息到屏幕
rostopic find 根据类型查找主题
rostopic hz 显示主题的发布频率
rostopic info 显示主题相关信息
rostopic list 显示所有活动状态下的主题
rostopic pub 将数据发布到主题
rostopic type 打印主题类型

2.4.4 rosservice(与服务通信相关 service)

rosservice包含用于列出和查询ROSServices的rosservice命令行工具。

调用部分服务时,如果对相关工作空间没有配置 path,需要进入工作空间调用 source ./devel/setup.bash

2.4.5 rosmsg(用在发布订阅模型中)

rosmsg是用于显示有关 ROS消息类型的 信息的命令行工具。

rosmsg 演示

rosmsg show 显示消息描述
rosmsg info 显示消息信息
rosmsg list 列出所有消息类型
rosmsg md5 显示 md5 加密后的消息
rosmsg package 显示某个功能包下的所有消息
rosmsg packages 列出包含消息的功能包

2.4.5 rossrv

rossrv是用于显示有关ROS服务类型的信息的命令行工具,与 rosmsg 使用语法高度雷同。

rossrv show 显示服务消息详情
rossrv info 显示服务消息类型的相关信息
rossrv list 列出所有服务信息类型 (在srv文件夹下

rossrv md5 显示 md5 加密后的服务消息
rossrv package 显示某个包下所有服务消息
rossrv packages 显示包含服务消息的所有包

查看自定义的消息载体 ,要查看的话一定要进入工作空间,刷新环境变量

2.4.6 rosparam

rosparam包含rosparam命令行工具,用于使用 YAML 编码文件在参数服务器上获取和设置ROS参数。

rosparam set 设置参数
rosparam get 获取参数
rosparam load 从外部文件加载参数
rosparam dump 将参数写出到外部文件
rosparam delete 删除参数
rosparam list 列出所有参数
在这里插入图片描述

2.5 通信机制实操

2.5.1 话题发布

机器人运动中常见的参数 六自由度
以机器人作参考坐标

在这里插入图片描述
小乌龟 线速度只有x 角速度只有偏航角z
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
roslaunch plumbing_test start_turtle.launch

在这里插入图片描述
在这里插入图片描述

后期需要添加功能包的配置
1
在这里插入图片描述
2
在这里插入图片描述

只要涉及到节点之间通信的,话题 和 消息载体是必不可少的

2.5.3

在这里插入图片描述

一般都是自定义srv文件 请求部分的数据和响应部分的数据会用三个—分开
可以概括为: 两个节点通过话题关联到一起,并使用某种类型的数据载体实现数据传输。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;