当前位置:主页 > 网页传世 > 正文

ExBot易科机器人实验室

2018-10-13

ExBot易科机器人实验室

1. ROS结构

今天扯一下ros吧。抛开ros生态圈不讲,单表ros软件。(1)作为通信中间件的ros是怎么玩的。ros软件提供了一个通信中间件来实现分布式系统的构建。那么既然是通信中间件,ros的通信机制是怎么实现的呢?单从文档上看,ros提供了订阅发布的通信机制,也就是有个发布者发布一个topic,订阅者订阅这个topic,当有发布者就某个topic 发布message的时候,订阅这个topic的订阅者就可以收到这个message 了。当订阅者收到这个消息的时候,通过一个自定义的回调函数来处理消息,来完成自己的业务。那么这个过程是具体是如何实现的呢?那就需要看源代码了。看源代码的过程中你会很容易骂人的,这个要忍住,但千万不要抱着看佛祖的心态看,从通信中间件或者说软件设计的角度来讲,ros绝非一流水平。话归正传,据我有限的认知,ros是这样实现订阅发布机制的。第一个概念,就是交易,订阅者和发布者是如何达成交易的呢?当然是在市场上呀,市场在哪里,当然就是master这个程序了,没有master就没有交易。那么第一个问题来了,订阅者和发布者怎么去的市场呢?从外表看不出来呀,没错,外表看不出来,你在源码里搜master-uri就找到了,当你在环境变量里搜master-uri也能找到。这个常量包含了ip和port的信息。有了这个信息你就会找到master 了。有了地址下一步是怎么去,肯定是socket了,并且不是普通的socket而是经过打扮的xmlrpcclient,既然做买卖那就得像个买卖人,要不然master那里的xmlrpcserver不搭理你。于是你打扮好了,到了master,你说我要adviser 一个topic,xmlrpcserver是个好公仆,有求必应,来做个登记吧,ip,port,upd or tcp,topic,登记完卖家就回家了,建立了一个tcp or udp的server,守在电话旁等买家。买家也是这么去的市场,到那先登记自己的信息,然后就问都是谁卖闺女,查到地址后,回家就去建立与卖家的链接,闺女就源源不断的送了过来。说完做买卖,再说仓库,也就是消息缓冲区模型,送来这么多闺女我该怎么放,怎么用呢?说实话,我还没看到,但无外乎如下几种,先进先出队列,后进先出队列,后进先出的环形队列,再有就是没有队列只能放一个只要最新的;ros是那一种呢?记住这个仓库在发送和接收端都存在,要并发不阻塞实现异步并发就得这么处理,收支两条线。加个评论:ros的这种做法,既不是完全得data centric,也不是完全的event driven,因为它兼有两者得特性。所以就缺少了dds的qos,随便交易,是个闺女都有人卖,至少也要看个年龄吧。再有就是不能把event driven的实时性彻底发挥出来。这个不怪它,机器人的信息交互本来就复杂,想要易用只能这样了,但无论如何也比傻乎乎的player/stage强,也比韩国人民在opros里设计的美好实现靠笨拙的cobra更好用。

2. ROS消息

(2)ros里的消息

通信中间件的目的有很多,其中一个就是将易错的部分封装,让使用者避免出错,socket编程是容易出错的,容易出错的地方也有很多,其中一个就是将带结构的数据序列化为无结构的字节流以及从无结构的字节流里重构数据结构,这两个行为,你可以叫它编码和解码,也可以叫打包和解包。

为什么说这个易错呢?很多人不理解,不就是把各种数据类型放到一个字符型数组里吗?不就是再从字符型数组弄出各种数据类型吗?小心点,就行了。那我只能告诉你,你用这样的态度能够解决问题靠的是幸运,而不是技术。这里我就不阐述容易错的地方在哪里了。直接说ros是怎么干的吧。那就是抽象,用中性语言定义消息,让交互双方在文本空间达成一致,记住是文本空间,仅供人类阅读,协议结果就是.msg和.srv那些文件(我们常用的裸奔做法是,写个文本文件,画个两行的表格,第一行每个格子里写个名字叫字段名,对应的第二行标示数据类型,如果穿上内裤的话,就加点注释解释每一个字段的含义,不过这跟裸奔也差不多,我看过太多这样的美其名曰的应用层协议了,很多人没感觉有问题,那我告诉你,那是没出门,你可能还要辩解说,我和别人通信的好好的呀,那我也只能说,那是你俩都在澡堂子,一起出门试试)。好了,有了这个协议,这个穿着西装革履谈做出的协议,ros会帮你脱衣服的,第一步,利用代码生成工具帮你生成在代码空间一致的依赖编程语言的消息定义头文件,如.h文件,好了,大家放心的编码吧;第二步,ros在运行期间帮你解码编码,在运行期间达成一致。最后需要解释的是有两点:

(1)ros肯定是生成了自定义消息的cpp文件的,要不然谁来打包和解析呀,至于什么时候自动生成而又删除了的,轻变SF传奇,这个读makefile什么的应该不难发现,当然我还没发现。

(2)ros在实际传送的每个消息里都包含了一个消息头,这个头至少包含了一个包标示字段、一个校验码段、一个包大小段。这是裸奔的内容,想在其他不支持ros的系统上做rosnode,必须要了解这个,当然还要理解美其名曰naming service的闺女交易。

3. ROS Node

(3)node

在一个机器人软件中,有各种各样的node。别抢答,各种各样不是指localization,slam ,action这些功能的多种多样,而是指有消息的生产者,消费者,以及消费又生产的深加工者。先插一句吧,这次讨论涉及到这样的一个问题,在用ros构建一个机器人软件时,仅仅从功能划分的角度来构建node是否合适。是否还需要考虑让消息的流动更顺畅,让node更简洁高效呢?先说node是怎么跑的吧。当你建立一个node后,要么它按照一个固定的周期运行,要么它阻塞等待事件发生,由事件驱动运行。无论是那种,node都要干活,node干的什么活呢?callback queue里的活。这个callback queue里的callback是哪里来的呢?常见的是subscriber的callback,当然还有其他的,包括publisher的,service的。那这些callback是什么时候被调用的呢。那就是spin()或者spinonce()。spin调用在queue 里所有的availiable的callback,如果没有availible的,它就阻塞。spinonce,显然只调用一次,看看有没有准备好的callback,有就调用,没有就返回。那什么是availible的、准备好的呢?对于subscribe,准备好的就是那些有新消息的subscriber的callback。现在如果你明白了上述node的运行机理。你在感到舒服之余,请准备接收心烦的问题。1)第一个问题就是,如果subscriber没有收到新消息,那么它的callback就不会被执行。如果你想每次都运行callback呢?对不起,没办法,不是virgin我不娶。