ROS的全名是Robot Operating System,即机器人操作系统。虽然名字里有个“操作系统”,但它并不是独立的操作系统,而要依赖于宿主系统之上。这个宿主系统通常是Ubuntu,因为它在Ubuntu有现成的软件仓库,但是事实上只要是Linux/Unix都可以从源代码编译安装。
因此,ROS其实是运行在PC上的一套便于机器人开发的机制,它通常用作上位机(例如用于Parrot AR.Drone四轴飞行器时),也可以搭载在机器人上作为主控(例如Turtlebot机器人使用了搭载ROS的笔记本电脑作为主控)。
由于优秀的中文资料本来就少,何况ROS一直在迭代,有的情况变化很大,因此,还是强烈建议通过ROS官方网站的英文文档来学习ROS。相关学习资料和操作步骤附在文末。本文目的只是为入门提供一点知识储备。斜体内容可安全跳过,回头再看也不迟。
ROS运行机制
ROS内核
ROS内核(roscore)是ROS运行的基础,它里面有参数服务器(parameter server)。一个运行中的ROS有且仅有一个ROS内核,ROS上的一切都依赖于这个内核。
ROS底层的通信是通过HTTP完成的,因此ROS内核本质上是一个HTTP服务器,它的地址一般是http://localhost:11311/ ,即本机的11311端口。当需要连接到另一台计算机上运行的ROS时,只要连上该机的11311端口即可。
节点
节点(node)是ROS运行的基本单位,每个节点通常执行整个系统的一小部分功能,比如发送机器人位姿信息、发送控制信息、执行一定的计算任务等。
一个机器人的运行,依赖于节点彼此之间的协作。因此,有人说ROS是分布式的。
节点之间的通信,依靠消息(message)和服务(service)。
消息
通常,ROS系统中有若干主题(topic)。每个节点可以对主题进行订阅(subscribe)操作,也可以对主题进行发布(publish)操作。节点可以向某个主题发布消息,然后订阅了该主题的节点就会自动收到消息。
消息是有类型的。一类消息可以由一些基本数据结构组成。例如,表示姿态的Pose类型消息,就由6个64位浮点数组成,分别代表三维空间中姿态的六个参数。消息类型的定义写在msg文件里,格式很简单,十分类似C语言中变量的定义。具体请参考官方文档。
服务
服务是节点之间除消息以外的另一种通信方式。每个节点都可以创建服务。其它节点可以向该服务发出一个请求(request),负责这个服务的节点就要相应地返回一个应答(response)。
消息与服务的不同之处,在于服务必须是一对一的,一问一答,可靠性很高。消息则可以多对多,相比之下更公共。至于完成某项通信究竟用谁更好,还要结合具体情况来看。
服务也和消息一样,是有类型的。服务类型的定义写在srv文件里,格式与表示消息类型的msg文件类似,只不过要分别描述请求的类型和应答的类型。具体请参考官方文档。
数据和文件结构
以下这些东西是ROS在你硬盘上的样子。这里用catkin工作空间来讲解。
包集
ROS的那些包集(package)里包含了ROS运行所需要的资源,比如程序、消息和服务的类型定义等。
一个包集里包含一个package.xml文件,这个文件描述了这个包集的基本信息。如果是源码包,通常还有个CMakeLists.txt文件,这个文件提供编译和安装包集时需要的信息,比如有哪些文件需要编译、程序要调用哪些库等。
包集编译时,所有的消息类型、服务类型的C++和Python库都会重新生成,C++代码会重新编译,其它一些在CMakeLists.txt规定的任务都会执行。
当你在包集里新建一个C++文件时,请记得修改CMakeLists.txt;当你在包集里新建一个msg文件时,请记得修改CMakeLists.txt;当你在包集里新建一个srv文件时,请记得修改CMakeLists.txt;当你在包集里新建一个Python文件时,不必修改CMakeLists.txt。详见官方文档。
程序
ROS支持用C++和Python来写程序,相关的包集叫做roscpp 和rospy。当修改C++文件时,要编译整个包集;Python则不必。
ROS里运行的节点都是由程序创建的。一个包集里可以有很多个程序,但它们未必都包含节点,也有可能是其它工具,例如某个文件格式转换的工具。
消息类型与服务类型
这些就是之前提到的msg文件和srv文件。包集每次编译时,会生成它们对应的C++头文件和Python模块,编程时可方便地调用它们。
launch文件
当需要有很多节点同时启动时,一个个启动它们会比较累,这时如果写一个launch文件把这些节点都包括进去,那么只要启动一个launch文件,就相当于把这些节点都启动了。
包
包(bag)是ROS用来记录运行期间消息的格式。记录完以后,随时可以重放这些消息。我们可以用它来记录机器人运行时传感器的数据,留待运行结束以后分析。
ROS常用包集
这些不是ROS所必需的,但在实际中会经常用到。
TF
提供基本的位姿在不同坐标系中变换功能,例如某个点相对于各关节的坐标等,真的非常基本。
Actionlib
控制机器人时,消息和服务不能满足要求,还要有一种新的通信方式——动作(action)。动作类似于服务,但是节点在向服务发出请求后,会在接下来一段时间内获得一系列反馈信息,直到动作完成才会收到应答。
std_msgs和common_msgs
这里的std_msgs定义了一系列基本的消息类型,如字符串等;而common_msgs定义了一系列常用消息类型,例如姿态、传感器数据等。
URDF机器人模型
ROS里的机器人模型通常用URDF来描述。URDF包集会自动解析URDF文件,并转为程序可读的格式,供ROS其它节点使用。URDF是在ROS中描述一个机器人最方便的方式。
Rviz
ROS三维仿真工具,除了机器人本身,ROS的很多东西都可以在这里仿真,例如TF、点云等。
RQT
这是ROS很多图形界面的一个集合,它们会输出各种用于调试、诊断的信息。例如将传感器数据画到坐标里(rqt_plot)、绘制所有节点与消息的关系图(rqt_graph)等,共计不少于10种。
Moveit!
ROS最著名的用于运动规划(motion planning)的库。它可以为机器人的动作生成路径。
与各种库相连接的桥
很多常用的库,如果要连接到ROS里,可以使用桥(bridge)。像OpenCV这样的常用库,它的桥已经有人开发好了,可以直接安装到ROS。
当然也可以挑战一下自己写一个桥。
如何学习?
Nootrix发布有安装了ROS的Ubuntu虚拟机。如果你没有Linux系统的话,可以装个VirtualBox虚拟机跑。
ROS版本还是最新的Indigo Igloo为宜。上一个版本Hydro的教程也可以使用,但是代码未必通用。
再次强调一遍,要想学好ROS,请务必参照官方英文文档。
入门可以从文档的Tutorial部分开始,一点一点照着tutorial来,学完基本的以后再把常用包集的tutorial也刷一遍,这样差不多就会了。
对于特定的包集,最好的办法是找到它在ROS的网页,上面一般会有文档或链接。
遇到问题的话,请仔细查看相关库的文档,如无结果可用搜索引擎搜一搜自己遇到的问题,还是不行的话,可以到官方的问答站搜索问题或提问。
不过真要学好的话,最好还是用它来做一个机器人项目吧。