摘要
ROS机器人操作系统在机器人应用领域很流行,依托代码开源和模块间协作等特性,给机器人开发者带来了很大的方便。我们的机器人“miiboo”中的大部分程序也采用ROS进行开发,所以本文就重点对ROS基础知识进行详细的讲解,给不熟悉ROS的朋友起到一个抛砖引玉的作用。本章节主要内容:
2.ROS系统整体架构
由于ROS系统的组织架构比较复杂,简单从一个方面来说明很难说清楚。按照ROS官方的说法,我们可以从3个方面来理解ROS系统整体架构,这3个方面分别是文件系统级、计算图级、开源社区级。
2.1.从文件系统级理解ROS架构
如果你是刚刚接手ROS方面的开发或项目,你肯定会觉得ROS中的各种概念非常奇怪,但是当你对ROS的使用熟练之后,你就觉得这些概念很好理解了。与其他操作系统相似,一个ROS程序的不同组件要被放在不同的文件夹下,这些文件夹是根据不同的功能来对文件进行组织的,如图3。
(图3)文件系统级理解ROS架构
(1)工作空间
工作空间是一个包含功能包、可编辑源文件和编译包的文件夹,当你想同时编译不同的功能包时非常有用,并且可以保存本地开发包。当然,用户可以根据自己的需要创建多个工作空间,在每个工作空间中开发不同用途的功能包。不过作为学习,我们先以一个工作空间为例。如图3,我们创建了一个名为catkin_ws的工作空间,该工作空间下会有3个文件夹:src、build、devel。
src源文件空间:这个文件夹放置各个功能包和一个用于这些功能包的CMake配置文件CMakeLists.txt。这里做一下说明,由于ROS中的源码采用catkin工具进行编译,而catkin工具又是基于cmake技术的,所以我们会在src源文件空间和各个功能包中都会见到一个文件CMakeLists.txt,这个文件就是起编译配置的作用。
build编译空间:这个文件夹放置CMake和catkin编译功能包时产生的缓存、配置、中间文件等。
devel开发空间:这个文件夹放置编译好的可执行程序,这些可执行程序是不需要安装就能直接运行的。一旦功能包源码编译和测试通过后,可以将这些编译好的可执行文件直接导出与其他开发人员分享。
(2)功能包
功能包是ROS中软件组织的基本形式,一个功能包具有用于创建ROS程序的最小结构和最少内容,它可以包含ROS运行的进程(节点)、配置文件等。如图3,一个功能包中主要包含这几个文件:
CMakeLists.txt功能包配置文件:用于这个功能包cmake编译时的配置文件。
package.xml功能包清单文件:用xml的标签格式标记这个功能包的各类相关信息,比如包的名称、依赖关系等。主要作用是为了更容易的安装和分发功能包。
include/<package_name>功能包头文件目录:你可以把你的功能包程序包含的*.h头文件放在这里,include下之所以还要加一级路径<package_name>是为了更好的区分自己定义的头文件和系统标准头文件,<package_name>用实际功能包的名称替代。不过这个文件夹不是必要项,比如有些程序没有头文件的情况。
msg非标准消息定义目录:消息是ROS中一个进程(节点)发送到其他进程(节点)的信息,消息类型是消息的数据结构,ROS系统提供了很多标准类型的消息可以直接使用,如果你要使用一些非标准类型的消息,就需要自己来定义该类型的消息,并把定义的文件放在这里。不过这个文件夹不是必要项,比如程序中只使用标准类型的消息的情况。
srv服务类型定义目录:服务是ROS中进程(节点)间的请求/响应通信过程,服务类型是服务请求/响应的数据结构,服务类型的定义放在这里。如果要调用此服务,你需要使用该功能包名称和服务名称。不过这个文件夹不是必要项,比如程序中不使用服务的情况。
scripts可执行脚本文件存放目录:这里用于存放bash、python或其他脚本的可执行文件。不过这个文件夹不是必要项,比如程序中不使用可执行脚本的情况。
launch文件目录:这里用于存放*.launch文件,*.launch文件用于启动ROS功能包中的一个或多个节点,在含有多个节点启动的大型项目中很有用。不过这个文件夹不是必要项,节点也可以不通过launch文件启动。
src功能包中节点源文件存放目录:一个功能包中可以有多个进程(节点)程序来完成不同的功能,每个进程(节点)程序都是可以单独运行的,这里用于存放这些进程(节点)程序的源文件,你可以在这里再创建文件夹和文件来按你的需求组织源文件,源文件可以用c++、python等来书写。
为了创建、修改、使用功能包,ROS给我们提供了一些实用的工具,常用的有下面这些工具。
rospack:用于获取信息或在系统中查找工作空间。
catkin_create_pkg:用于在工作空间的src源空间下创建一个新的功能包。
catkin_make:用于编译工作空间中的功能包。
rosdep:用于安装功能包的系统依赖项。
rqt_dep:用于查看功能包的依赖关系图。
关于这些工具命令的具体使用方法,会在后面的章节中结合实例进行具体的讲解。这里只是先介绍给大家,让大家有个概念上的了解,感兴趣的朋友也可以自己上网了解这些命令的具体用法。
(3)消息
消息是ROS中一个进程(节点)发送到其他进程(节点)的信息,消息类型是消息的数据结构,ROS系统提供了很多标准类型的消息可以直接使用,如果你要使用一些非标准类型的消息,就需要自己来定义该类型的消息。
ROS使用了一种精简的消息类型描述语言来描述ROS进程(节点)发布的数据值。通过这种描述语言对消息类型的定义,ROS可以在不同的编程语言(如c++、python等)书写的程序中使用此消息。不管是ROS系统提供的标准类型消息,还是用户自定义的非标准类型消息,定义文件都是以*.msg作为扩展名。消息类型的定义分为两个主要部分:字段的数据类型和字段的名称,简单点说就是结构体中的变量类型和变量名称。比如下面的一个示例消息定义文件example.msg的内容,如图4,int32、float32、string就是字段的数据类型,id、vel、name就是字段的名称。
(图4)一个示例消息定义文件
在大多数情况下,我们都可以使用ROS系统提供的标准类型的消息来完成任务,这得益于ROS系统提供了丰富的标准类型的消息。经常用到的类型包括:基本类型(std_msgs)、通用类型(sensor_msgs、geometry_msgs、nav_msgs、actionlib_msgs),如图5。
(图5)ROS系统提供的常用标准类型的消息
不难发现std_msgs下面定义的是经ROS封装后的最基本的数据类型,比如Bool、Char、Int16等;sensor_msgs下面定义的是跟传感器数据相关的数据类型,比如Image对应的就是摄像头的数据类型,Imu对应的就是IMU传感器的数据类型,LaserScan对应的就是激光雷达的数据类型,PointCloud对应的就是点云扫描传感器(如深度相机)的数据类型,Range对应的就是距离测量传感器(如超声波、红外测距)的数据类型;geometry_msgs下定义的是跟几何有关的数据类型,比如Pose用来描述机器人在空间的位姿,Quaternion用四元数描述空间方向,Transform用来描述不同坐标系之间的转移关系,Twist用来描述机器人运动时的位姿、速度等状态信息;nav_msgs下定义的是跟机器人导航相关的数据类型,比如OccupancyGrid是栅格地图的数据类型,Odometry是机器人通过轮式码盘或其他方式融合得到的里程计的数据类型,Path是路径规划算法计算得到的导航路劲的数据类型;actionlib_msgs下定义的是actionlib控制过程相关的数据类型,比如GoalID描述发送出去的导航目标的ID号,GoalStatus描述执行导航目标过程的过程状态信息。如果想了解更多ROS系统的消息类型的细节,最好的方式是去ROS wiki看官方的文档,链接如下:
http://wiki.ros.org/common_msgs/
(4)服务
服务是ROS中进程(节点)间的请求/响应通信过程,服务类型是服务请求/响应的数据结构。服务类型的定义借鉴了消息类型的定义方式,所以这里就不在赘述了。区别在于,消息数据是ROS进程(节点)间多对多广播式通信过程中传递的信息;服务数据是ROS进程(节点)间点对点的请求/响应通信过程传递的信息。
2.2.从计算图级理解ROS架构
ROS会创建一个连接所有进程(节点)的网络,其中的任何进程(节点)都可以访问此网络,并通过该网络与其他进程(节点)交互,获取其他进程(节点)发布的信息,并将自身数据发布到网络上,这个计算图网络中的节点(node)、主题(topic)、服务(server)等都要有唯一的名称做标识,如图6。
(图6)计算图级理解ROS架构
(1)节点
节点是主要的计算执行进程,功能包中创建的每个可执行程序在被启动加载到系统进程中后,该进程就是一个ROS节点,如图6中的node1、node2、node3等都是节点(node)。节点都是各自独立的可执行文件,能够通过主题(topic)、服务(server)或参数服务器(parameter server)与其他节点通信。ROS通过使用节点将代码和功能解耦,提高了系统的容错力和可维护性。所以你最好让每一个节点都具有特定的单一的功能,而不是创建一个包罗万象的大节点。节点如果用c++进行编写,需要用到ROS提供的库roscpp;节点如果用python进行编写,需要用到ROS提供的库rospy。
ROS提供了处理节点的工具,用于节点信息、状态、可用性等的查询操作,例如可以用下面的命令对正在运行的节点进行操作。
rosnode info <node_name>:用于输出当前节点信息。
rosnode kill <node_name>:用于杀死正在运行节点进程来结束节点的运行。
rosnode list:用于列出当前活动的节点。
rosnode machine <hostname>:用于列出指定计算机上运行的节点。
rosnode ping <node_name>:用于测试节点间的网络连通性。
rosnode cleanup:用于将无法访问节点的注册信息清除。
关于这些工具命令的具体使用方法,会在后面的章节中结合实例进行具体的讲解。这里只是先介绍给大家,让大家有个概念上的了解,感兴趣的朋友也可以自己上网了解这些命令的具体用法。
(2)消息
节点通过消息(message)完成彼此的沟通。消息包含一个节点发送给其他节点的信息数据。关于消息类型的知识在前面已经讲述了,这里就不再展开。
ROS提供了获取消息相关信息的命令工具,这里列举出一些常用的命令,来具体看看吧。
rosmsg show <message_type>:用于显示一条消息的字段。
rosmsg list:用于列出所有消息。
rosmsg package <package _name>:用于列出功能包的所有消息。
rosmsg packages:用于列出所有具有该消息的功能包。
rosmsg users <message_type>:用于搜索使用该消息类型的代码文件。
rosmsg md5 <message_type>:用于显示一条消息的MD5求和结果。
关于这些工具命令的具体使用方法,会在后面的章节中结合实例进行具体的讲解。这里只是先介绍给大家,让大家有个概念上的了解,感兴趣的朋友也可以自己上网了解这些命令的具体用法。
(3)主题
每个消息都必须发布到相应的主题(topic),通过主题来实现在ROS计算图网络中的路由转发。当一个节点发送数据时,我们就说该节点正在向主题发布消息;节点可以通过订阅某个主题,接收来自其他节点的消息。通过主题进行消息路由不需要节点之间直接连接,这就意味着发布者节点和订阅者节点之间不需要知道彼此是否存在,这样就保证了发布者节点与订阅者节点之间的解耦合。同一个主题可以有多个订阅者也可以有多个发布者,不过要注意必须使用不同的节点发布同一个主题。每个主题都是强类型的,不管是发布消息到主题还是从主题中订阅消息,发布者和订阅者定义的消息类型必须与主题的消息类型相匹配。
ROS提供了操作主题的命令工具,这里列举出一些常用的命令,来具体看看吧。
rostopic bw </topic_name>:用于显示主题所使用的带宽。
rostopic echo </topic_name>:用于将主题中的消息数据输出到屏幕。
rostopic find <message_type>:用于按照消息类型查找主题。
rostopic hz </topic_name>:用于显示主题的发布频率。
rostopic info </topic_name>:用于输出活动主题、发布的主题、主题订阅者和服务的信息。
rostopic list:用于列出当前活动主题的列表。
rostopic pub </topic_name> <message_type> <args>:用于通过命令行将数据发布到主题。
rostopic type </topic_name>:用于输出主题中发布的消息类型。
关于这些工具命令的具体使用方法,会在后面的章节中结合实例进行具体的讲解。这里只是先介绍给大家,让大家有个概念上的了解,感兴趣的朋友也可以自己上网了解这些命令的具体用法。
(4)服务
在一些特殊的场合,节点间需要点对点的高效率通信并及时获取应答,这个时候就需要用服务的方式进行交互。提供服务的节点叫服务端,向服务端发起请求并等待响应的节点叫客户端,客户端发起一次请求并得到服务端的一次响应,这样就完成了一次服务通信过程,例如图6中,node1向node3发起一次请求,并得到node3返回给node1的响应。服务通信过程中服务的数据类型需要用户自己定义,与消息不同,节点并不提供标准服务类型。服务类型的定义文件都是以*.srv为扩展名,并且被放在功能包的srv/文件夹下。
ROS提供了操作服务的命令工具,这里列举出一些常用的命令,来具体看看吧。
rosservice call </service_name> <args>:用于通过命令行参数调用服务。
rosservice find <service_type>:用于根据服务类型查询服务。
rosservice info </service_name>:用于输出服务信息。
rosservice list:用于列出活动服务清单。
rosservice type </service_name>:用于输出服务类型。
rosservice uri </service_name>:用于输出服务的ROSRPC URI。
关于这些工具命令的具体使用方法,会在后面的章节中结合实例进行具体的讲解。这里只是先介绍给大家,让大家有个概念上的了解,感兴趣的朋友也可以自己上网了解这些命令的具体用法。
(5)节点管理器
节点管理器(master)用于节点的名称注册和查找等,也负责设置节点间的通信。如果在你的整个ROS系统中没有节点管理器,就不会有节点、消息、服务之间的通信。由于ROS本身就是一个分布式的网络系统,所以你可以在某台计算机上运行节点管理器,在这台计算机和其他台计算机上运行节点。
ROS中提供了跟节点管理器相关的命令行工具,就是roscre。
roscore:用于启动节点管理器,这个命令会加载ROS节点管理器和其他ROS核心组件。
关于这些工具命令的具体使用方法,会在后面的章节中结合实例进行具体的讲解。这里只是先介绍给大家,让大家有个概念上的了解,感兴趣的朋友也可以自己上网了解这些命令的具体用法。
(6)参数服务器
参数服务器(parameter server)能够使数据通过关键词存储在一个系统的核心位置。通过使用参数,就能够在节点运行时动态配置节点或改变节点的工作任务。参数服务器是可通过网络访问的共享的多变量字典,节点使用此服务器来存储和检索运行时的参数。
ROS中关于参数服务器的命令行工具,请看下面的常用命令。
rosparam list:用于列出参数服务器中的所有参数。
rosparam get <parameter_name>:用于获取参数服务器中的参数值。
rosparam set <parameter_name> <value>:用于设置参数服务器中参数的值。
rosparam delete <parameter_name>:用于将参数从参数服务器中删除。
rosparam dump <file>:用于将参数服务器的参数保存到一个文件。
rosparam load <file>:用于从文件将参数加载到参数服务器。
关于这些工具命令的具体使用方法,会在后面的章节中结合实例进行具体的讲解。这里只是先介绍给大家,让大家有个概念上的了解,感兴趣的朋友也可以自己上网了解这些命令的具体用法。
(7)消息记录包
消息记录包(bag)是一种用于保存和回放ROS消息数据的文件格式。消息记录包是一种用于存储数据的重要机制,它可以帮助记录一些难以收集的传感器数据,然后通过反复回放数据进行算法的性能开发和测试。ROS创建的消息记录包文件以*.bag为扩展名,通过播放、停止、后退操作该文件,可以像实时会话一样在ROS中再现情景,便于算法的反复调试。
ROS提供消息记录包相关的命令行工具,请看下面的常用命令。
rosbag <args>:用来录制、播放和执行操作。
关于这些工具命令的具体使用方法,会在后面的章节中结合实例进行具体的讲解。这里只是先介绍给大家,让大家有个概念上的了解,感兴趣的朋友也可以自己上网了解这些命令的具体用法。
2.3.从开源社区级理解ROS架构
ROS开源社区级的概念主要是ROS资源,即通过各个独立的网络社区分享ROS方面的软件和知识。
(1)ROS发行版
ROS发行版跟Linux发行版起类似的作用,ROS发行版是内置了一系列常用功能包的ROS系统安装包,可以被直接安装到我们的操作系统中。如图7,是ROS的各个发行版。
(图7)ROS的各个发行版
(2)ROS软件代码库
ROS依赖于开源或共享软件的源代码,这些代码由不同的机构共享与发布,比如github源码共享,ubuntu软件仓库等等。如图8,是ROS软件代码库的社区组织形式。
(图8)ROS软件代码库的社区组织形式
(3)ROS文档社区
ROS wiki是记录有关ROS系统各种文档的主要论坛社区,任何人都可以注册账户、贡献自己的文件、提供更正或更新、编写教程及其他行为。感兴趣可以进入ROS wiki的主页面瞧瞧http://wiki.ros.org/。
(4)ROS问答社区
ROS开发者可以通过这个资源去提问和寻找ROS相关的答案,ROS Answer主页面
后记
------SLAM+语音机器人DIY系列【目录】快速导览------
第1章:Linux基础
第2章:ROS入门
第3章:感知与大脑
第4章:差分底盘设计
第5章:树莓派3开发环境搭建
第6章:SLAM建图与自主避障导航
2.google-cartographer机器人SLAM建图
第7章:语音交互与自然语言处理
第8章:高阶拓展
2.centos7下部署Django(nginx+uwsgi+django+python3)
----------------文章将持续更新,敬请关注-----------------
如果大家对博文的相关类容感兴趣,或有什么技术疑问,欢迎加入下面的《SLAM+语音机器人DIY》QQ技术交流群,一起讨论学习^_^