机器人操作系统——Robot Operating System(ROS)
2009年一篇发表在ICRA开源软件Workshop上的文章ROS: an open-source Robot Operating System( 译文),让ROS走入了广大研究人员的视野。发展到今天的2019年,已经有了十年左右的历史, ROS系统已经在越来越多的机器人系统中得到了成功的应用。虽然ROS系统目前还存在着各种各样的问题,但在国内的机器人玩家中已经有了逐渐普及的趋势。 本系列文章就是要管窥ROS一二。
我从2015年毕业开始接触ROS,如果以一句话来概括它,我认为它是一个"进程间的通信框架"。借助订阅者模式和服务器模式,用户可以方便的开发自己的机器人应用。ROS还提供了丰富的工具, 可以方便的管理代码,编译执行,使得我们可以通过一堆脚本把各个相对独立的部分整合起来,构建一个复杂的机器人系统。由于ROS是运行在Linux内核上的应用框架,对系统资源的要求较高, 而且实时性较差。此外,ROS的设计初衷是为了机器人研究人员提供一个松耦合的开发框架,在安全性方面欠缺考虑。但是,因为ROS的开放,使得它在学者和工程师中间得以流行。
网络上已经有很多ROS的教程了,有官方的、有原创的、也有翻译的,参差不齐。写本系列文章并不想让读者有一种"又是一个ROS教程"的感觉,我还是希望能够有一些干货在里面的。 本系列的文章是我个人对官方教程以及相关源码的解读,算是我的入门笔记。内容安排如下:
- 第一部分:ROS入门。这一部分是对官方Wiki上入门教程的整理,目的是快速了解ROS能做什么,如何使用ROS系统。
- 第二部分:ROS进阶。本部分进一步介绍ROS中的一些高级概念,包括如何实现一个插件系统,机器人的坐标系框架tf。
- 第三部分:机器人模型与可视化。主要是介绍ROS中用于描述机器人模型的URDF语言。
- 第四部分:Gazebo与仿真。介绍ROS系统中的一个常用的仿真系统Gazebo。
- 第五部分:Turtlebot与机器人系统。以开放平台Turtlebot的仿真过程和相关源码分析,对上述四个部分中的内容做个总结,了解如何构建一个复杂的机器人系统。
从2017年的10月份开始断断续续的写本系列的文章,到2019年1月2日完成初稿。ROS系统已经从第10版的Kinetic Kame发布到了第12版的Melodic Morenia。本打算把SLAM、导航等技术相关的包也放在这里介绍的, 但在写第五部分的过程中发现这些内容还挺多的,而且所使用的技术未必一定在ROS系统框架下。而且将它们放在这里有点违背本系列文章作为ROS系统入门材料的初衷,所以最后决定将它们独立出去, 只保留第五部分作为一个简单的总结和铺垫。
第一部分:ROS入门
按照一般写书和文章的套路,会先写一个介绍ROS系统的概述部分,但我们还是把这个ROS入门部分放在了最前面。主要是想让读者先体会一下ROS系统, 个人觉得这比上来就讲ROS中的各种概念要有趣一点点。
本部分是为了快速了解ROS主要功能特性而编写的,相关内容主要是对官方Wiki的翻译,根据我个人的理解, 对其内容进行了一些重新的组织。暂时删去了官方入门文章中关于ROS文件系统、roslaunch、以及数据记录和回放的部分。
ROS的安装和初体验 | 目前最新版本是Lunar Loggerhead,它是官方发布的第11个版本。但是这里我们主要以第10版Kinetic Kame为例介绍各种ROS系统相关的内容。之所以选它, 是因为Kinetic是目前最新的长期维护版本(LTS),官方说法是将一直持续到2021年。 |
创建和编译Package | Package是ROS系统中对软件的基本组织单位,我们可以把它看做是一个可以完成某项功能的模块。每个Package都有一个自己的目录, 在其目录下都一个package.xml文件描述Package的作者信息以依赖关系,和一个CMakeLists.txt记录了Package的各种编译和构建规则。 ROS为我们提供了catkin_create_pkg工具,可以方便快捷的创建一个Package。当然,不嫌麻烦的话我们也可以自己从头撸一个出来。 |
ROS的Graph和Node | ROS把系统中运行的进程以及相互之间的通信关系抽象成了图(Graph)。Node实际上就是一个独立运行的进程,相互之间主要有Topic和Service两种通信方式。 |
简单的Topic发布者和订阅者 | 我们一般都是用c++或者python作为ROS系统程序的开发语言。roscpp和rospy是两种语言的API,通过它们我们可以请求一些ROS系统的资源和方法。 其实本文可以和下面关于msg文件的文章写在一起的,但为了强调整个编译和运行过程,我们还是专门写了一节。 |
创建msg文件 | msg文件是ROS系统中Topic通信机制的基础,通过msg文件我们自定义各种类型的消息。Topic则是一种订阅者模式下的通信机制,由发布者发布某一Topic的消息, 订阅者只要订阅了该消息,就可以接受发布者广播出来的数据。而消息的具体数据格式则是由msg文件进行描述的。 |
简单的Service服务器和客户端 | Service是ROS系统中Node之间的另一种主要的通信方式。它也需要一个文件来描述提供服务的接口的输入和输出数据,这个文件就是srv文件。 本文的例程实现了一个计算两个数的和的服务器。 |
第二部分:ROS进阶
在本部分中,我们介绍一些ROS的高级概念。其中关于插件系统和Nodelet的介绍主要是提高系统的可扩展性以及运行效率。坐标系是机器人系统中的一个核心概念, 它描述了机器人的各个部件以及与世界环境的相对关系,ROS系统提供了tf框架来解决复杂的坐标变换的问题。
Action | ROS提供了两种基本的节点之间通信方式:发布和订阅主题、 请求服务,它们各有优缺点。有时我们还希望能够兼具两种机制的特征,ROS就提供了Action机制。 本质上它仍然是一种Topic机制,只是通过actionlib进行了封装。在服务器和客户端之间通过goal, cancel, status, feedback, result五个主题实现Action机制。 |
录包与回放 | ros bag |
ROS插件系统pluginlib | pluginlib为ROS应用程序提供了插件系统,使得我们可以在应用程序中针对一个基类也就是插件的接口编程。借助pluginlib我们可以动态的加载C++类型,提高了应用程序的可扩展性。 尤其对机器人中各种可以相互替换的传感器执行器的建模和驱动实现有很大的帮助。 |
Nodelet | 为了提高需要传输图像等数据量较大的消息时的系统效率,ROS提供了一种Nodelet的机制。该机制借助roscpp的优化特点,将多个模块运行在一台机器上的一个节点中, 实现共享指针传输达到零内存拷贝的目的,从而提高了系统效率。 |
tf:坐标变换库 | 这是一篇2013年发表在TePRA上介绍tf库的文章。全面介绍了tf库的功能和设计思想。虽然目前ROS推荐使用tf2了, 但作为tf库设计的早期文章,我们可以了解到tf最初的设计需求和设计理念。 原文下载 |
简单的tf广播者和监听者 | 机器人往往涉及到多个坐标系,如何方便高效的管理这些坐标系是关系到机器人系统能够正常运行的关键问题。ROS提供了tf的工具来管理多个坐标系之间的变换关系。 |
第三部分:机器人模型与可视化
我们在做机器人控制的时候,很多时候就只有一个模型。控制实际机器人的时候,我们需要模型的各个参数来实时解算机器人的状态; 在做机器人仿真的时候,我们不仅要计算机器人的状态,还要能够直观的把机器人的形体展示出来。
本部分中,我们讨论ROS中用来描述机器人模型的URDF(Unified Robot Discription Format),这是一个基于XML标记语言的描述方式。 它用link和joint标签来描述机器人的各个布局以及它们之间的连接关系,整个机器人被表示称为了一棵树的形式。
URDF和机器人模型(一) | 本文介绍如何使用URDF描述一个机器人,并通过工具rviz来查看机器人的模型。 URDF不仅提供了球、圆柱、长方体等基本的形状外,还可以加载mesh文件来展示复杂的3D模型。 |
URDF和机器人模型(二) | 机器人模型除了用于直观的图形显示之外,还需要描述各个部分的质量,连接部分的摩擦、阻尼等等物理特性。此外我们还需要描述机器人的碰撞模型, 在控制实际机器人时用于判定其一个特定的姿态是否成立,在做仿真的时候用于计算各种接触力。 |
URDF解析器 | 前两节中,我们介绍了如何使用URDF来描述机器人的模型。但要在程序中使用模型,我们还需要能够从描述文件中解析出机器人的各种参数。 本文中,我们介绍如何在程序中访问机器人模型,用于实际的机器人控制当中。 |
在rviz中自由的摩擦 | 在前面几节的文章中,我们用的都是官方教程'urdf_tutorial'中的'display.launch'文件启动rviz并渲染机器人的。 在本文中,我们将详细分析这个launch文件都开启了什么node,它们都完成了什么功能。然后编写一些C++的程序和launch文件替换掉官方教程。 |
Xacro | 大多数情况下,机器人的各个Link和Joint之间只是存在一些细微的差异。如果我们为每一个部件和关节都写一个描述就会显得很繁琐,而且容易出错。 Xacro为我们提供了三种工具可以一定程度上简化urdf文件。这三种工具是:定义变量、数学表达式、可带参数的宏定义。 |
第四部分:Gazebo与仿真
Gazebo最早是在2002年,由南加州大学的Andrew Howard和他的学生NateKoenig开发的。在接下来的几年中Nate在完成他的PhD学位的同时开发着Gazebo。 在2009年,Willow公司的一个高级研究工程师JohnHsu,把ROS和PR2与Gazebo整合在一起。自此Gazebo就成为了ROS社区中的一个基本工具。 在2011年的春天,Willow Garage公司开始为Gazebo的开发提供商业支持。在2012年,开源机器人联盟(Open Source Robotics Foundation, OSRF)从Willow Garage公司脱离出来,同时接管了Gazebo项目。
Gazebo是一个3D动力学仿真器,能够准确的高效的模拟工作在复杂室内和室外环境的机器人。与游戏引擎类似,Gazebo提供了更真实的物理仿真, 一系列的传感器,以及用户和程序接口。 本部分的文章主要是对Gazebo官方教程中的Beginner和Intermediate部分的翻译和整理, 旨在介绍Gazebo的各种特性,和基本的使用方法。
用Gazebo的GUI创建机器人 | 在本文中,我们将利用Gazebo的GUI工具,模型编辑器,来创建一个简单的机器人。它是一个轮式的小车,有一个传感器可以探测前方事物并跟随它移动。 GUI工具能帮助我们实现一些简单的模型,对于复杂的机器人使用SDF文件来描述更为方便。本文的主要目的是介绍Gazebo的GUI界面, 所以还是从模型编辑器开始我们的Gazebo之旅。 主要参考官方教程[1] [2] |
用SDF文件模拟激光雷达 | 在上一篇文章中,我们介绍了如何使用Gazebo提供的模型编辑器来创建一个机器人模型,并在仿真中使用。 个人任务这个过程是很繁琐的,尤其是在机器人比较复杂的时候,推荐尽量使用SDF文件来描述机器人。在本文中,我们将用SDF文件来描述一个激光雷达,模拟传感器数据, 添加Mesh文件以获得更好的视觉体验和更真实的仿真效果。代码下载 |
Gazebo的仿真插件 | Gazebo通过插件(Plugin)的机制实现灵活的扩展功能。它的插件实际上是一个个的动态链接库,使得我们可以通过C++接触到Gazebo的方方面面。 而插件又是相对独立的,开发人员可以方便共享,使用时也可以方便的插入系统或者从系统中移除。 本文在上一篇文章中实现的激光传感器的基础上,实现了一个插件用来控制传感器的扫描速度。 |
通过ROS开启Gazebo的世界 | 为了达到真实世界与仿真世界之间自如切换,我们需要研究一下如何在ROS系统中控制Gazebo以及其仿真的机器人模型。 本文中,我们介绍通过roslaunch打开仿真世界,并导入URDF描述的机器人模型。 |
Gazebo + ros_control | 到目前为止,我们的机器人还是软软的趴在地上。本文中,我们将具体介绍插件gazebo_ros_control,通过ros_control为机器人添加控制器来让我们的机器人动起来。 ros_control是ROS中一种比较常用的控制器管理和实现的框架。gazebo_ros_control是Gazebo的一个插件,用来根据设定装载合适的硬件接口和控制器。 这些设定就是在URDF文件中的<transmission>标签中描述的内容,该标签是URDF针对ros_control专门设计的。 |
关于Gazebo的介绍就先到这里,以后会有一个专题来讲仿真。
第五部分:Turtlebot与机器人系统
Turtlebot是一款经典的小车机器人了。它是Melonee Wise和Tully Foote在2010年做出来的,是很多ROS教程的研究对象。 也是要感谢Turtlebot的开源,使得我们有了一个系统的玩具,涉及到了机器人中的控制、定位、建图、导航等方方面面的内容,可以说是麻雀虽小五脏俱全。下面是各种Turtlebot相关的链接:
本部分通过Turtlebot的源码来一窥机器人眼中的世界。主要是想了解一个移动机器人系统都有哪些组成部分,各个部分都扮演着什么样的角色,相互之间是如何相互协调工作的, 也是以一个例子对上述内容做一个总结。因为手头上没有一台Turtlebot,所以本部分主要是在仿真的基础上介绍。
Turtlebot你好! | 本文是对网络上各种入门教程的浓缩,介绍一下仿真环境的搭建和运行。这里先跟Turtlebot打个招呼,让它在Gazebo的世界中摩擦摩擦,之后的文章都是讲Turtlebot自由摩擦背后的故事。 |
Turtlebot的描述模型 | 建立机器人模型应该是进行仿真的第一步工作,因为它将是我们以后开发算法的控制对象。本文详细分析了Turtlebot的描述模型,以及相关描述文件的组织方式。 |
Kobuki控制插件 | Kobuki控制插件是Gazebo世界中的Turtlebot底盘与ROS的接口,我们通过该插件控制底盘运动,获取底盘上的传感器在仿真世界中的数据。本文详细解析Kobuki控制插件的源码。 |
Kinect控制插件 | Kinect是微软出品的一款双目/深度摄像头,早期与XBox一起用于体感游戏风靡一时。为了在Gazebo环境中模拟Kinect,Gazebo官方为之提供了一个插件。 |
召唤Turtlebot | 本文中我们将详细介绍召唤Turtlebot时的launch文件都做了些什么事情。 |
Turtlebot眼中的世界 | Turtlebot官方提供了在Gazebo环境下仿真建图和定位导航的两个demo,本文介绍运行这两个demo的launch文件,目的是了解ROS系统是如何让这些功能模块运转起来的。 至于具体的建图算法我们将在SLAM算法主题中予以介绍。 |