DAY 6 ROS 通讯架构2

前言

今天我们要来讲 ROS 中最为核心的部分,ROS 提供了 四种通讯方式,分别为 Topic、Service、Parameter Service 、Actionlib

Topic

在人跟人的沟通上,通常我们会订出一个话题才会开始聊天,你总不可能跟一个人没话题的乱聊吧,不然这是没有意义的,而在 ROS 也是这样的,假设我们现在有 A、B 两个节点,此时 A 需要跟 B 说 嗨,这时 A node 便被称为发布者 publisher ,B被称为订阅者 subscriber 现在我们来看下面这张图, A 发布 HI 给 Topic 给 B ,而B去接收到 Hi 这个讯息。

但是你以为你发出去的讯息对方一定当会收到吗? Topic 他是一个异步的通讯方式,这是什麽意思? 这就像是你平常去密学妹讯息一样,你发出去的讯息,他不一定会看的到一样,但是你不管对方有没有收到,你仍会持续的发送。

在 ROS 中也是如此,从下图来看,我们的相机 node 将 我们的 RGB 资料给传递给 影像处理 node 来进行处理,当我们的 影像处理 node 没有收到任何讯息时,他就不会去进行动作,此时他可以去干其他事情,而当我们的 相机 node 发送讯号过来时,我们的 影像处理 node 就必须去做事情了

但是如果一个 topic 他同时还受其他的 node 订阅时,他会有影响吗? 当然是不会的,就跟你可以同时跟多个妹子一起聊天依样,会有影响吗? 不会的,机器也是依样,我们这时多了一个 display node 来查看当前的影像,如果你觉得你熟悉的话,他就是在 Gazboo 这个模拟器中的使用情形。

当然多对多也是可以的,只要你电脑跑得动都是可以的。

接下来我们来看一些 Topic 的相关指令

指令 作用
rostopic list 列出当前所有的 topic
rostopic info topic_name 显示某个 topic 的属性讯息
rostopic echo topic_name 显示某个 topic 的内容
rostopic pub topic_name ... 向某个 topic 发布内容
rostopic bw topic_name 查看某个 topic 的带宽
rostopic hz topic_name 查看某个 topic 的频率
rostopic find topic_type 查找某个类型的 topic
rostopic type topic_name 查看某个 topic 的类型(msg)

message

在 Topic 中他有很严格的讯息格式,在 ROS 中 message 其实是一种数据的格式,他定义於 .msg 档中,我们发的每一条讯息都要去遵守这个格式。

他有 bool、int8、int16、int32、int64、uint、float32、float64、string、time、duration、header、array、vector(可变长度的array)

下面这边是一个 msg 的范例

std_msg/Header header
    uint32 seq
    time stamp
    string frame_id
uint32 height
uint32 width
string encoding
uint8 is_bigendian
uint32 step
uint8[] data

接下来来看 MSG 的相关指令

rosmsg 指令 作用
rosmsg list 列出系统上所有的msg
rosmsg show msg_name 显示某个msg的内容

Service

Topic 他是一个单向传递的一种方式,但是有时候这种方式并不能满足我们的需求,假设我现在有一个人脸识别的机器人,他有一个功能是透过你的照片来判断人脸,而这个功能在没有抓到人脸的时候是不需要去运行的,但是当我们用 topic 的方式时,我们就会一直等啊等地持续的运行,这样子非常的消耗资源。接下来要讲的 Service 就可以完美的解决这个问题。

Service 他是一种请求查询式的服务架构,他跟 Topic 最大的区别变在於他是双向的,他不仅可以发送讯息还可以接受到反馈,所以 Service 可以分成两部分,客户端跟服务器端,客户端透过发送请求给服务器端来取得一个回复。

Service 他是采取同步的通讯方式,也就是说 Node A 在发出请求後,会等到 Node B 的回复後,才会继续做事情,Node A 在等待的过程中是处於封闭的状态,这样的通讯规则不会造成传递冲突或是高系统资源的使用,只有在接受请求才执行,是十分好的一种方法。

最後我们来讲一些常用的指令

rosservice 指令 作用
rosservice list 显示服务列表
rosservice info 印出服务讯息
rosservice type 印出服务类型
rosservice uri 印出服务 ROSRPC uri
rosservice find 按造服务的类型找服务
rosservice call 使用所提供的 args 调用服务
rosservice args 印出服务参数

Topic VS Service

在这边我们把 Topic 跟 Service 来做一个比对

名称 Topic Service
通讯方式 异步通讯 同步通讯
原理 TCP/IP TCP/IP
通讯方式 Publish-Subscribe Request-Reply
映射关系 Publish-Subscribe(多对多) Request-Reply(多对一)
特点 接受者收到资讯会回调(Callback) 远程过程呼叫(RPC)服务器端的服务
应用场景 连续、高频的资讯发布 偶尔使用的功能/具体的任务
举例 雷达 开关传感器、拍照

SRV

SRV 他是 Service 的一种讯息格式,跟 MSG 是很像的东西, 他被定义在 .src 文件中,SRV 文件它包含请求跟回应的格式,这边以追踪人体来当作范例

bool start_detect
---
my_pkg/HumanPose[] pose_data

上面是请求的格式,下面是回应的格式,中间用三个短横来区隔。

在定义完 SRV 跟 MSG 後,这边有两个文件需要注意一下,我们需要添加一些依赖上去,第一个是package.xml ,其中 ** ** 是需要添加的地方

<build_depend>** message_generation **</build_depend>
<run_depend>** message_runtime **</run_depend>

第二个是 CMakeList.txt

find_package(...roscpp rospy std_msgs ** message_generation **)
catkin_package(
...
CATJIN_DEPENDS ** message_runtime ** ...
...)
add_message_file(
FILES
** DetectHuman.srv **
** HumanPose.msg **
** JointPos.msg **)
** generate_messages(DEPENDENCIES std_msgs) **

最後我们来讲一些常用的指令

rossrv 指令 作用
rossrv show 显示服务描述
rossrv list 列出所有服务
rossrv md5 显示服务md5sum
rossrv package 列出 package 中的服务
rossrv packages 列出含服务的 package

Parameter server

我们在之前启动 master 的时候,有提到说参数服务器 Parameter server ,他是会一起被启动的,那他到底在干嘛呢?他负责维护一个字典,他跟 topic 跟 service 都是不太一样的,他是节点用来存参数,他可以提供任意节点进行调用。

如果你有学过 python,他就是里面的 dict 的那种概念,每一组 key 都会对应到一组 value,我们通常会将一些不太会需要修改的值给丢上去,而 Parameter server 的设定可以分成指令、launch文件、 node 三种方式

命令

rosparam 指令 作用
rosparam set param_key param_value 设置参数
rosparam get param_key 显示参数
rosparam load file_name 从文件读取参数
rosparam dump file_name 存参数到文件里
rosparam delete 删除参数
rosparam list 列出参数名称

launch

在 launch 文件中有很多标签,跟 参数服务器有关的就只有 param 跟 rosparam,但是param 只会设定一个参数,可以看下面的例子

<param name="publish_frequency" value="20.0"/>

在这边可以看到这边是去指定说 "publish_frequency" 他的值是 20.0,或是他有另一种方式

<param name="robot_description" command="$(find xacro)/xacro.py $(find robot_sim_demo)/urdf/robot.xacro" />

这边他并没有说 value 是多少,而是一个命令,他的意思是 xacro.py 这个程序去执行 robot.xacro 这个文件得到的结果就是我们的值。

另一种标签 rosparam 他的用法就比较固定,一般是先指定一个 yaml 文件,然後对她使用 command,在下面这个例子中,可以看成是 `rosparam load xbot-u_control.yaml```

 <rosparam file="$(find robot_sim_demo)/param/xbot-u_control.yaml" command="load"/>

node

除了前面两种用法,还有一种方法是修改 ROS 的程序码,也就是利用 API 来使用参数服务器,这个会在後面跟 ROS CPP 、 PY 的地方一起说明。

Action

接下来来说最後一种 ROS 的通讯方式,他也是最为麻烦(复杂)的方式,他跟 Service 很像,但是因为 Service 太过於简单,有时候是不合适的,像是一台汽车再开的时候,他一直往前开,但是突然出现一个人,我们需要紧急的停止汽车,这时如果是 Service 他是无法中途停止的,但是 Action 却可以,这是因为他多了一个机制,就是在服务器端在跑的时候,他是会时时的吐资讯给你,你也可以中途去丢指令给他,让他知道需要中断,这样你可以知道服务器端是不是死了,或是跑很慢,所以这个是比较适合现今许多较为复杂的架构去做使用的,其通常用在长时间、需要中断的任务之中。

.action 档

.action 档包含了三个部分,分别是目标、回复、结果。

  • 目标
    • 机器人在运动时,应该要有一个明确的目标,像是设定、方向、角度、速度等等,从而让机器人完动作任务。
  • 回复
    • 在机器人运动的过程中,他会一直回传现在机器人的状态,可以让我们即时去做调整(赛车游戏)
  • 结果
    • 当做完任务时,机器人将结果回传给我们,让我们得到完整的资讯,包括时长、最终位置等等。

这边以洗碗机器人来当作范例

我们先去定义说我们要让哪一台洗碗机器人去做事,然後在过程中回传(feedback)说现在做几%了,最後会回传一个结果给我们,跟我们说他洗了多少个碗

# Define the goal
uint32 dishwasher_id # Specify which dishwasher we want to use
---
# Define the result
uint32 total_dishes_cleaned
---
# Define a feedback message
float32 percent_complete

以上就是 Action 这种通讯方式的讲解。

结论

到现在为止,我们了解了 ROS 中的四种通讯方式,我们可以来比较这四种通讯方式,来思
考说每一种通讯方式的优缺点和他适合用在哪边,在正确的地方用正确的通讯方式,这样整个 ROS 的通讯
会更加的有效率,我们的机器人也会更加的灵活 www

#Arm Arm Platforms


<<:  离职倒数10天:做产品才知道政治敏感不只存在两岸之间

>>:  Day 6 被动搜查(3)-Google Hacking、shadon、.git 泄漏

伪类与伪元素-30天学会HTML+CSS,制作精美网站

昨天介绍了各种选择器,今天介绍伪类及伪元素样式设定,可以让画面有更多的样式变化,也减少html co...

每个人都该学的30个Python技巧|技巧 15:新增或删除串列元素(字幕、衬乐、练习)

今天已经是教串列中的第三篇了~之前讲到如何建立还有读取串列元素,不但可以只提取一个,还可以一次读取很...

Day 13 [Python ML、Pandas] 创建、读取和写入

Introduction 在这个课程里,会学到最热门的资料分析套件,pandas Getting S...

< 关於 React: 开始打地基| LifeCycle 生命圈>

09-10-2021 Mounting 当组件被初始化,第一次被放入DOM时。 ComponentD...

【D30】结尾:佳肴上桌

本日程序码使用:d30.py 这边结合第29天的下单功能,以及第28天的制作组合单,让这个组合单的...