理解ROS
介绍ROS的一些核心概念。
- 首先运行roscore启动ROS节点管理器,然后才能启动rosrun的其他节点:
$roscore
Roscore会启动一个ROS Master,一个ROS参数服务器和一个名为rosout的日志节点。如果使用roslaunch启动ROS节点,那么roslaunch会检测roscore是否启动,并自动启动roscore。
整个ROS系统由一个节点管理器和多个相对独立的节点组成,能够提供运动规划,机械臂控制等诸多功能。
ROS的系统架构
ROS从架构视角上可以分为操作系统层、中间件层和应用层三个层级。ROS的系统架构如下图所示。
在操作系统层,ROS基于Ubuntu进行构建。
在中间件层,ROS基于TCPROS、UDPROS进行通信,TCPROS、UDPROS是基于TCP、UDP的ROS应用层数据协议,用于解析话题和服务的二进制数据流。
在应用层,ROS基于节点管理器进行节点的发现、发布/订阅、请求/响应等,并记录其他节点的位置,然后将这些信息通知给需要建立连接的节点。ROS基于XML-RPC协议进行节点通信。
ROS源代码位于https://github.com/ros/rosdistro下。
ROS从设计视角上可以分为三个层级:开源社区级,文件系统级和计算图集。具体介绍可以看我的另一篇博文ROS学习笔记(一)ROS系统架构
·程序包package
工作空间的所有程序包均位于工作空间的src目录下,一个工作空间下可以包含多个程序包。
如果存在程序包集,那么程序包应与程序包集在同一级目录
理解节点管理器
节点管理器(通过roscore启动)可以理解为ROS的神经中枢,节点在启动时注册到节点管理器上,节点管理器对节点进行管理,并帮助节点找到彼此。节点管理器不参与节点之间的消息传递。
roscore启动过程主要完成:
- 启动节点管理利器,节点管理器主要用于查询节点,实现消息服务在各个节点之间的连接;
- 启动参数服务器,参数服务器用于设置和查询参数;
- 启动日志节点rosout,记录所有消息的收发和stdout、stderr。
理解节点
ROS将程序包中可执行文件的运行实例称为节点(Node),节点本质上就是执行运算任务的进程。
- 启动节点
ROS支持rosrun、roulaunch两种方式启动节点,两者的区别在于:
rosrun一次只能启动一个节点,若启动节点前节点管理器没有启动,则启动节点会失败。
利用rosrun可直接启动程序包中的节点,其中节点名为CMakeList.txt文件中的add_executable宏定义的可执行文件名,启动方法如下:
$roslaunch [程序包名] [节点名称]
roslaunch可以通过launch文件一次启动多个节点,如果启动节点时没有节点管理器正在运行,则roslaunch会自动启动节点管理器,如果已经有节点管理器在运行,则连接已启动的节点管理器。
任何包含两个及以上节点的程序包都可以利用launch文件来指定和配置需要使用的节点,launch文件本质上是一以launch为后缀的XML文件,应位于launch目录下。
利用roslaunch调用程序包的launch文件启动节点,方法如下:
$roslaunch [选项] [程序包名] [可变参数]
- 查看节点信息
通过rosnode可以查看节点的相关信息。
查看当前运行节点列表的方法如下:
$rosnode list
理解话题
节点之间的通信可通过消息(Message)进行传递,而消息则封装在话题(Topic)中,话题本质上是对套接字(Socket)的一种封装。消息以发布(publish)/订阅(subscribe)的模式进行传递,一个节点可以向一个给定的话题发布消息,另一个节点可以订阅给定话题中特定消息类型的消息。发布者和订阅者可通过话题实现解耦。
在ROS中话题必须是唯一的,否则消息路由就会产生错误。
话题可以利用可视化工具rqt_graph进行查看。
调试过程中,可通过命令行将消息发布到话题上。
理解消息
在ROS中,消息本质上是一种节点间传递信息的数据类型。
ROS利用了简单的、与开发语言无关的接口来描述模块间传递的消息。
利用消息机制可以很好地实现分布式节点之间的通信,也有利于开发者实现高内聚、低耦合的代码。
- 消息类型
每个消息都属于一个特定的程序包,消息类型的命名方式为:
程序包名/消息名
如:geometry_msgs/Twist
消息类型每行的声明必须包含两部分:域和变量;域定义的消息的数据类型,变量定义了域的名称。域可以是独立域或者符合域。
- 查看消息
利用rosmsg可以查看消息。
如:rosmsg show [消息类型]
- 手动发布消息(同手动发布话题)
理解服务
服务是ROS的另外一种通信机制,它与消息的区别在于消息是单向的,没有相应的概念,每一个消息都与一个话题相关,该话题可以有多个发布者和订阅者,消息既可以一对多,也可以多对多;服务是双向的,一个节点向另一个节点发送消息并等待响应,而且服务的响应也返回同一个节点。
- 服务类型
服务文件是一个后缀名为srv并描述服务类型的文本文件,存放在程序包的srv目录下。服务文件由请求、响应两部分构成,请求和响应之间通过“---”隔开。
服务的每行声明与消息类型格式一样。
- 查看服务
通过rosservice可以查看服务的信息,常见的用法如下:
查看服务列表
$rosservice list
理解动作
如之前介绍,服务的响应是同步的,这在执行一些耗时较短的任务时没有问题,但在执行一些耗时较长的任务,如让机械臂从A点运动到B点时,服务就会造成线程的阻塞。
为了解决这一问题,ROS提供了动作(Action)执行耗时长的异步任务,动作除了请求是异步的之外,还能查看任务进度并取消任务等。
- 动作类型
ROS的动作由后缀为action的文本文件进行定义,动作文件包含goal、result、feedback三部分的内容。三者之间通过“---”隔开。如下所示:
#goal
int32 total
---
#result
int32 sum
---
#feedback
- 动作状态
ROS的动作采用Client/Server架构的设计,可通过ActionClient、ActionServer来完成动作的通信。
动作在机械臂、定位、及导航等场景中应用广泛。
理解参数
ROS通过参数服务器来存储和操作数据,参数服务器可以存储整型、浮点型、布尔型、字典型、列表型等类型的数据,节点可以通过接口实时地存储和获取参数,但考虑到可读性,参数以静态非二进制的形式存在,性能并不算高,参数服务器是节点管理器的一部分。
参数既可以用rosparam来进行管理,也可以在launch文件中配置,还可以通过代码进行动态配置。