ROS入门
1. Robot Operating System
1.1. 简介
ROS是一个适用于机器人编程的框架,这个框架把原本松散的零部件耦合在了一起,为他们提供了通信架构。ROS虽然叫做操作系统,但并非Windows、Mac那样通常意义的操作系统,它只是连接了操作系统和你开发的ROS应用程序,所以它也算是一个中间件,基于ROS的应用程序之间建立起了沟通的桥梁,所以也是运行在Linux上的运行时环境,在这个环境上,机器人的感知、决策、控制算法可以更好的组织和运行。
以上几个关键词(框架、中间件、操作系统、运行时环境)都可以用来描述ROS的特性,作为初学者我们不必深究这些概念,随着你越来越多的使用ROS,就能够体会到它的作用。
1.2. 历代ROS版本
ROS1.0版本发布于2010年, 基于PR2机器人开发了一系列机器人相关的基础软件包。 随后
ROS版本迭代频繁, 目前已经发布到了Lunar。 目前使用人数最多的是Kinetic和Indigo这两个
Long Term Support版本。
ROS版本 | 发布时间 |
---|---|
Lunar Loggerhead | 2017.5 |
Kinetic Kame | 2016.5 |
Jade Turtle | 2015.5 |
Indigo lgloo | 2014.7 |
Hydro Medusa | 2013.9 |
Groovy Galapagos | 2012.12 |
Fuerte Turtle | 2012.4 |
Electric Emys | 2011.8 |
Diamondback | 2011.3 |
C Turtle | 2010.8 |
Box TurtleBox Turtle | 2010.3 |
1.3. ROS特点
ROS具有这些特点:
-
分布式 点对点
ROS采用了分布式的框架,通过点对点的设计让机器人的进程可以分别运行,便于模块化的修改和定制,提高了系统的容错能力。
-
多种语言支持
ROS支持多种编程语言。C++、Pyhton已经在ROS中实现编译,是目前应用最广的ROS开发语言,Lisp、C#、Java等语言的测试库也已经实现。为了支持多语言编程,ROS采用了一种语言中立的接口定义语言来实现各模块之间消息传送。通俗的理解就是,ROS的通信格式和用哪种编程语言来写无关,它使用的是自身定义的一套通信接口。
-
开源社区
ROS具有一个庞大的社区ROS WIKI,这个网站将会始终伴随着你ROS开发,无论是查阅功能包的参数、搜索问题还是。当前使用ROS开发的软件包已经达到数千万个,相关的机器人已经多达上千款。此外,ROS遵从BSD协议,对个人和商业应用及修改完全免费。这也促进了ROS的流行。
1.4. ROS优缺点
ROS为我们开发机器人带来了许多方便, 然而它也确实存在一些问题:
优点 | 缺点 |
---|---|
提供框架、 工具和功能 | 通信实时性能有限 |
方便移植 | 系统稳定性尚不满足工业级要求 |
庞大的用户群体 | 安全性上没有防护措施 |
免费开源 | 仅支持Linux(Ubuntu) |
总体来说, ROS更适合科研和开源用户使用, 如果在工业场景应用( 例如无人驾驶) 还需要
做优化和定制。 为了解决实际应用的问题, ROS2.0做了很大的改进, 目前正在开发之中, 未
来表现如何值得期待。
2. 安装
3. 编译
3.1. Catkin特点
Catkin是基于CMake的编译构建系统,具有以下特点:
- Catkin沿用了包管理的传统像
find_package()
基础结构,pkg-config
- 扩展了CMake,例如
- 软件包编译后无需安装就可使用
- 自动生成
find_package()
代码,pkg-config
文件 - 解决了多个软件包构建顺序问题
一个Catkin的软件包(package)必须要包括两个文件:
- package.xml: 包括了package的描述信息
- name, description, version, maintainer(s), license
- opt. authors, url’s, dependencies, plugins, etc…
- CMakeLists.txt: 构建package所需的CMake文件
- 调用Catkin的函数/宏
- 解析
package.xml
- 找到其他依赖的catkin软件包
- 将本软件包添加到环境变量
3.2. Catkin工作原理
catkin编译的工作流程如下:
- 首先在工作空间
catkin_ws/src/
下递归的查找其中每一个ROS的package。 - package中会有
package.xml
和CMakeLists.txt
文件,Catkin(CMake)编译系统依据CMakeLists.txt
文件,从而生成makefiles
(放在catkin_ws/build/
)。 - 然后
make
刚刚生成的makefiles
等文件,编译链接生成可执行文件(放在catkin_ws/devel
)。
也就是说,Catkin就是将cmake
与make
指令做了一个封装从而完成整个编译过程的工具。catkin有比较突出的优点,主要是:
- 操作更加简单
- 一次配置,多次使用
- 跨依赖项目编译
3.3. 使用catkin_make
进行编译
要用catkin编译一个工程或软件包,只需要用catkin_make
指令。一般当我们写完代码,执行一次catkin_make
进行编译,调用系统自动完成编译和链接过程,构建生成目标文件。编译的一般性流程如下,在1.5节我们编译ROS-Academy-for-Beginners教学包就是这样的流程。
1 | $ cd ~/catkin_ws #回到工作空间,catkin_make必须在工作空间下执行 |
注意: catkin编译之前需要回到工作空间目录,catkin_make
在其他路径下编译不会成功。编译完成后,如果有新的目标文件产生(原来没有),那么一般紧跟着要source刷新环境,使得系统能够找到刚才编译生成的ROS可执行文件。这个细节比较容易遗漏,致使后面出现可执行文件无法打开等错误。
catkin_make
命令也有一些可选参数,例如:
1 | catkin_make [args] |
4. Catkin工作空间
Catkin工作空间是创建、修改、编译catkin软件包的目录。catkin的工作空间,直观的形容就是一个仓库,里面装载着ROS的各种项目工程,便于系统组织管理调用。在可视化图形界面里是一个文件夹。我们自己写的ROS代码通常就放在工作空间中,本节就来介绍catkin工作空间的结构。
4.1. Catkin工作空间结构
catkin的结构十分清晰,具体的catkin工作空间结构图如下。初看起来catkin工作空间看起来极其复杂,其实不然,catkin工作空间的结构其实非常清晰。
在工作空间下用tree命令,显示文件结构。
1 | $ cd ~/catkin_ws |
结果为:
1 | ─ build |
通过tree命令可以看到catkin工作空间的结构,它包括了src
、build
、devel
三个路径,在有些编译选项下也可能包括其他。但这三个文件夹是catkin编译系统默认的。它们的具体作用如下:
- src/: ROS的catkin软件包(源代码包)
- build/: catkin(CMake)的缓存信息和中间文件
- devel/: 生成的目标文件(包括头文件,动态链接库,静态链接库,可执行文件等)、环境变量
在编译过程中,它们的工作流程如图:
后两个路径由catkin系统自动生成、管理,我们日常的开发一般不会去涉及,而主要用到的是src文件夹,我们写的ROS程序、网上下载的ROS源代码包都存放在这里。
在编译时,catkin编译系统会递归的查找和编译src/
下的每一个源代码包。因此你也可以把几个源代码包放到同一个文件夹下,如下图所示:
4.2. 小结
catkin工作空间基本就是以上的结构,package是catkin工作空间的基本单元,我们在ROS开发时,写好代码,然后catkin_make,系统就会完成所有编译构建的工作。至于更详细的package内容,我们将在下节继续介绍。
5. Package软件包
我们调用catkin_make
编译的对象就是一个个ROS的package,也就是说任何ROS程序只有组织成package才能编译。所以package也是ROS源代码存放的地方,任何ROS的代码无论是C++还是Python都要放到package中,这样才能正常的编译和运行。
一个package可以编译出来多个目标文件(ROS可执行程序、动态静态库、头文件等等)。
5.1. package结构
一个package下常见的文件、路径有:
1 | ├── CMakeLists.txt #package的编译规则(必须) |
其中定义package的是CMakeLists.txt
和package.xml
,这两个文件是package中必不可少的。catkin编译系统在编译前,首先就要解析这两个文件。这两个文件就定义了一个package。
- CMakeLists.txt: 定义package的包名、依赖、源文件、目标文件等编译规则,是package不可少的成分
- package.xml: 描述package的包名、版本号、作者、依赖等信息,是package不可少的成分
- src/: 存放ROS的源代码,包括C++的源码和(.cpp)以及Python的module(.py)
- include/: 存放C++源码对应的头文件
- scripts/: 存放可执行脚本,例如shell脚本(.sh)、Python脚本(.py)
- msg/: 存放自定义格式的消息(.msg)
- srv/: 存放自定义格式的服务(.srv)
- models/: 存放机器人或仿真场景的3D模型(.sda, .stl, .dae等)
- urdf/: 存放机器人的模型描述(.urdf或.xacro)
- launch/: 存放launch文件(.launch或.xml)
通常ROS文件组织都是按照以上的形式,这是约定俗成的命名习惯,建议遵守。以上路径中,只有CMakeLists.txt
和package.xml
是必须的,其余路径根据软件包是否需要来决定。
5.2. package的创建
创建一个package需要在catkin_ws/src
下,用到catkin_create_pkg
命令,用法是:
catkin_create_pkg package depends
其中package是包名,depends是依赖的包名,可以依赖多个软件包。
例如,新建一个package叫做test_pkg
,依赖roscpp、rospy、std_msgs(常用依赖)。
1 | $ catkin_create_pkg test_pkg roscpp rospy std_msgs |
这样就会在当前路径下新建test_pkg
软件包,包括:
1 | ├── CMakeLists.txt |
catkin_create_pkg
帮你完成了软件包的初始化,填充好了CMakeLists.txt
和package.xml
,并且将依赖项填进了这两个文件中。
5.3. package相关命令
5.3.1. rospack
rospack是对package管理的工具,命令的用法如下:
rostopic命令 | 作用 |
---|---|
rospack help |
显示rospack的用法 |
rospack list |
列出本机所有package |
rospack depends [package] |
显示package的依赖包 |
rospack find [package] |
定位某个package |
rospack profile |
刷新所有package的位置记录 |
以上命令如果package缺省,则默认为当前目录(如果当前目录包含package.xml)
5.3.2. roscd
roscd
命令类似与Linux系统的cd
,改进之处在于roscd
可以直接cd
到ROS的软件包。
rostopic命令 | 作用 |
---|---|
roscd [pacakge] |
cd到ROS package所在路径 |
5.3.3. rosls
rosls
也可以视为Linux指令ls
的改进版,可以直接ls
ROS软件包的内容。
rosls命令 | 作用 |
---|---|
rosls [pacakge] |
列出pacakge下的文件 |
5.3.4. rosdep
rosdep
是用于管理ROS package依赖项的命令行工具,用法如下:
rosdep命令 | 作用 |
---|---|
rosdep check [pacakge] |
检查package的依赖是否满足 |
rosdep install [pacakge] |
安装pacakge的依赖 |
rosdep db |
生成和显示依赖数据库 |
rosdep init |
初始化/etc/ros/rosdep中的源 |
rosdep keys |
检查package的依赖是否满足 |
rosdep update |
更新本地的rosdep数据库 |
一个较常使用的命令是rosdep install --from-paths src --ignore-src --rosdistro=kinetic -y
,用于安装工作空间中src
路径下所有package的依赖项(由pacakge.xml文件指定)。
6. CMakeLists.txt
6.1. CMakeLists.txt作用
CMakeLists.txt
原本是Cmake编译系统的规则文件,而Catkin编译系统基本沿用了CMake的编译风格,只是针对ROS工程添加了一些宏定义。所以在写法上,catkin的CMakeLists.txt
与CMake的基本一致。
这个文件直接规定了这个package要依赖哪些package,要编译生成哪些目标,如何编译等等流程。所以CMakeLists.txt
非常重要,它指定了由源码到目标文件的规则,catkin编译系统在工作时首先会找到每个package下的CMakeLists.txt
,然后按照规则来编译构建。
6.2. CMakeLists.txt写法
CMakeLists.txt
的基本语法都还是按照CMake,而Catkin在其中加入了少量的宏,总体的结构如下:
1 | cmake_minimum_required() #CMake的版本号 |
如果你从未接触过CMake的语法,请阅读《CMake实践》:https://github.com/Akagi201/learning-cmake/blob/master/docs/cmake-practice.pdf 。掌握CMake语法对于理解ROS工程很有帮助。
7. package.xml
package.xml
也是一个catkin的package必备文件,它是这个软件包的描述文件,在较早的ROS版本(rosbuild编译系统)中,这个文件叫做manifest.xml
,用于描述pacakge的基本信息。如果你在网上看到一些ROS项目里包含着manifest.xml
,那么它多半是hydro版本之前的项目了。
7.1. package.xml作用
pacakge.xml
包含了package的名称、版本号、内容描述、维护人员、软件许可、编译构建工具、编译依赖、运行依赖等信息。
实际上rospack find
、rosdep
等命令之所以能快速定位和分析出package的依赖项信息,就是直接读取了每一个pacakge中的package.xml
文件。它为用户提供了快速了解一个pacakge的渠道。
7.2. package.xml写法
pacakge.xml
遵循xml标签文本的写法,由于版本更迭原因,现在有两种格式并存(format1与format2),不过区别不大。老版本(format1)的pacakge.xml
通常包含以下标签:
1 | <pacakge> 根标记文件 |
说明:其中1-6为必备标签,1是根标签,嵌套了其余的所有标签,2-6为包的各种属性,7-9为编译相关信息。
在新版本(format2)中,包含的标签为:
1 | <pacakge> 根标记文件 |
由此看见新版本的pacakge.xml
格式上增加了 、、、 ,相当于将之前的build和run依赖项描述进行了细分。
目前Indigo、Kinetic、Lunar等版本的ROS都同时支持两种版本的package.xml
,所以无论选哪种格式都可以。
7.3. pacakge.xml例子
为了说明pacakge.xml写法,还是以turtlesim软件包为例,其pacakge.xml
文件内容如下,我们添加了相关的注释:
1 | <!--本示例为老版本的pacakge.xml--> |
以上内容是老版本(format1)的写法,如果要写成新版本(format2)则可以改为:
1 |
|
8. Metapackage
8.1. Metapackage介绍
在一些ROS的教学资料和博客里,你可能还会看到一个Stack(功能包集)的概念,它指的是将多个功能接近、甚至相互依赖的软件包的放到一个集合中去。但Stack这个概念在Hydro之后就取消了,取而代之的就是Metapackage。尽管换了个马甲,但它的作用没变,都是把一些相近的功能模块、软件包放到一起。
ROS里常见的Metapacakge有:
Metapacakge名称 | 描述 | 链接 |
---|---|---|
navigation | 导航相关的功能包集 | https://github.com/ros-planning/navigation |
moveit | 运动规划相关的(主要是机械臂)功能包集 | https://github.com/ros-planning/moveit |
image_pipeline | 图像获取、处理相关的功能包集 | https://github.com/ros-perception/image_common |
vision_opencv | ROS与OpenCV交互的功能包集 | https://github.com/ros-perception/vision_opencv |
turtlebot | Turtlebot机器人相关的功能包集 | https://github.com/turtlebot/turtlebot |
pr2_robot | pr2机器人驱动功能包集 | https://github.com/PR2/pr2_robot |
… | … | … |
以上列举了一些常见的功能包集,例如navigation、turtlebot,他们都是用于某一方面的功能,以navigation metapackage(官方介绍里仍然沿用stack的叫法)为例,它包括了以下软件包:
包名 | 功能 | |
---|---|---|
navigation | Metapacakge,依赖以下所有pacakge | |
amcl | 定位 | |
fake_localization | 定位 | |
map_server | 提供地图 | |
move_base | 路径规划节点 | |
nav_core | 路径规划的接口类 | |
base_local_planner | 局部规划 | |
dwa_local_planner | 局部规划 | |
… | … | … |
具体功能介绍,我们留到第九章,这里只看一个软件包navigation。这个navigation就是一个简单的pacakge,里面只有几个文件,但由于它依赖了其他所有的软件包。Catkin编译系统会明白,这些软件包都属于navigation metapacakge。
这个道理并不难理解,比如我们在安装ROS时,用到了sudo apt-get install ros-kinetic-desktop-full
命令,由于它依赖了ROS所有的核心组件,我们在安装时也就能够安装整个ROS。
8.2. Metapackage写法
我们以ROS-Academy-for-beginners为例介绍meteapckage的写法,在教学包内,有一个ros-academy-for-beginners
软件包,该包即为一个metapacakge,其中有且仅有两个文件:CMakeLists.txt
和pacakge.xml
。
CMakeLists.txt
写法如下:
1 | cmake_minimum_required(VERSION 2.8.3) |
pacakge.xml
写法如下:
1 | <package> |
metapacakge中的以上两个文件和普通pacakge不同点是:
CMakeLists.txt
:加入了catkin_metapackage()宏,指定本软件包为一个metapacakge。package.xml
:标签将所有软件包列为依赖项,标签中添加标签声明。
metapacakge在我们实际开发一个大工程时可能有用
9. 其他常见文件类型
在ROS的pacakge中,还有其他许多常见的文件类型,这里做个总结。
9.1. launch文件
launch文件一般以.launch或.xml结尾,它对ROS需要运行程序进行了打包,通过一句命令来启动。一般launch文件中会指定要启动哪些package下的哪些可执行程序,指定以什么参数启动,以及一些管理控制的命令。 launch文件通常放在软件包的launch/
路径中中。 launch文件的具体写法见3.2节。
9.2. msg/srv/action文件
ROS程序中有可能有一些自定义的消息/服务/动作文件,为程序的发者所设计的数据结构,这类的文件以.msg
,.srv
,.action
结尾,通常放在package的msg/
,srv/
,action/
路径下。
msg文件写法见3.4节,srv文件写法见3.6节。
9.3. urdf/xacro文件
urdf/xacro文件是机器人模型的描述文件,以.urdf或.xacro结尾。它定义了机器人的连杆和关节的信息,以及它们之间的位置、角度等信息,通过urdf文件可以将机器人的物理连接信息表示出来。并在可视化调试和仿真中显示。
urdf文件的写法见第七章。
9.4. yaml文件
yaml文件一般存储了ROS需要加载的参数信息,一些属性的配置。通常在launch文件或程序中读取.yaml文件,把参数加载到参数服务器上。通常我们会把yaml文件存放在param/
路径下
9.5. dae/stl文件
dae或stl文件是3D模型文件,机器人的urdf或仿真环境通常会引用这类文件,它们描述了机器人的三维模型。相比urdf文件简单定义的性状,dae/stl文件可以定义复杂的模型,可以直接从solidworks或其他建模软件导出机器人装配模型,从而显示出更加精确的外形。
9.6. rviz文件
rviz文件本质上是固定格式的文本文件,其中存储了RViz窗口的配置(显示哪些控件、视角、参数)。通常rviz文件不需要我们去手动修改,而是直接在RViz工具里保存,下次运行时直接读取。