初接触ROS时,对其文件结构容易产生困惑和混淆,比如
catkin_ws
到底是什么?catkin_ws/src
目录下存放的是什么?catkin_ws/src
路径下怎么还会有其他的src/
目录,这些src
应该存放哪些代码?- 工作空间是什么?功能包是什么?他们是怎么创建的?
- …
这篇文章就对以上这些问题进行回答。
1. 什么是ROS的工作空间
使用ROS实现机器人开发的主要手段是写代码,这些代码文件存放的空间就是工作空间。
工作空间(workspace)是一个用于存放工程开发相关文件的文件夹。目前,ROS默认使用的是Catkin编译系统(在CMake的基础上拓展得到的,将 cmake 与 make 指令做了一个封装从而完成整个编译过程)。在Catkin编译系统下,一个典型的工作空间一般包含四个目录空间:src
、devel
、build
、install
,结构如下
workspace_folder/
|—— src/
|—— CMakeLists.txt
|—— package_1/
|—— CMakeLists.txt
|—— package.xml
|—— ......
|—— package_2/
|—— CMakeLists.txt
|—— package.xml
|—— ......
|—— devel/
|—— setup.bash
|—— ......
|—— build/
|—— ......
|—— install/
src
: 代码空间(Source Space),最常用、最重要的文件夹,用来存储所有ROS功能包(package)的源文件。build
: 编译空间(Build Space),由catkin_make
命令自动生成,用来存储工作空间编译过程中产生的缓存信息和中间文件。devel
: 开发空间(Development Space),由catkin_make
命令自动生成,用来放置编译生成的可执行文件。install
: 安装空间(Install Space),不是必需的,很多工作空间没有该文件夹。编译成功后,可以使用make install
命令将可执行文件安装到该空间中,运行该空间中的环境变量脚本,即可在终端中运行这些可执行文件。
工作空间并不是整个ROS开发所在的空间,不同的项目可以有各自的工作空间,只需要配置各自的环境变量即可(source devel/setup.bash
)。
2. 什么是ROS的功能包
功能包(package)是ROS中的基本单元,包含ROS节点、库、配置文件等。
一个功能包的典型文件结构如下:
config
:功能包的配置文件,用户创建。include
:需要用到的头文件。scripts
:可以直接运行的Python脚本。src
:需要编译的C++代码。launch
:所有启动文件。msg
:自定义的消息类型。srv
:自定义的服务类型。action
:自定义的动作指令。CMakeLists.txt
:Catkin编译器编译功能包的规则。package.xml
: 功能包清单,可得到该package的名称、版本号、信息描述、作者信息和许可信息等。更重要的,<build_depend> ... </build_depend>
标签定义了代码编译所依赖的其它功能包,<exec_depend> ... </exec_depend>
标签定义了可执行程序运行时所依赖的其它功能包。
上面的这些文件夹并不是每一个都要有,根据需要创建即可,比如不需要运行python文件,就不用scripts
文件夹。此外,也可以自定义其他的文件夹。
ROS针对功能包的常用命令如下:
catkin_create_pkg # 创建功能包
catkin_make # 编译工作空间中的功能包
rospack # 获取功能包的信息
rosdep # 自动安装功能包依赖的其它包
roscd # 功能包目录跳转
roscp # 拷贝功能包中的文件
rosed # 编辑功能包中的文件
rosrun # 运行功能包中的可执行文件
roslaunch # 运行启动文件
3. 创建工作空间
mkdir -p ~/catkin_ws/src #使用系统命令创建工作空间目录
cd ~/catkin_ws/src
catkin_init_workspace # ROS的工作空间初始化命令
创建完成后,在工作空间的根目录下使用catkin_make
命令编译整个工作空间:
cd ~/catkin_ws # 回到工作空间的根目录
catkin_make # 编译整个工作空间
编译中,工作空间的根目录会自动产生devel
和build
两个文件夹即其中的文件。
编译完成后,在devel文件夹中已经产生几个setuo.*sh
形式的环境变量设置脚本,使用source
命令运行这些脚本,可以使工作空间中的环境变量生效。
source devel/setup.bash
检查环境变量是否生效:
echo $ROS_PACKAGE_PATH
如果打印的路径中包含当前工作空间中的路径,则说明环境变量设置成功。
注意:
source
命令设置的环境变量只能在当前终端生效,如果希望在所有终端生效,需要在终端配置文件中加入环境变量设置:echo "source /home/xxx/catkin_ws/devel/setup.bash" >> ~/.bashrc
4. 创建功能包
ROS不允许功能包的嵌套,多个功能包必须平行放置在代码空间(
src
)中。
ROS直接创建功能包的命令catkin_create_pkg
,用法:
catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
即需要输入功能包名称和所依赖的其它功能包。
进入代码空间,创建功能包:
cd ~/catkin_ws/src
catkin_create_pkg leraning_communication std_msgs rospy roscpp
回到工作空间根目录进行编译,设置环境变量:
cd ~/catkin_ws
catkin_make
source ~/catkin_ws/devel/setup.bash
一个功能包就这样创建完成了。
5. 工作空间的覆盖
ROS允许多个工作空间并存,用户可在不同项目的工作空间创建所需要的功能包,但这样的话可能会遇到一种情况:不同的工作空间中可能存在同名的功能包,如果这些工作空间的环境变量已经设置,那么在使用该功能包的时候,ROS如何解决冲突?
答案就是 ROS的工作空间覆盖机制(Overlaying)。
所有工作空间的路径会依次在ROS_PACKAGE_PATH
环境变量中记录,当设置多个工作空间的环境变量后,新设置的路径在ROS_PACKAGE_PATH
中会自动放置在最前端,在运行时,ROS会优先查找在最前端的工作空间中是否存在指定的功能包,如果不存在就顺序向后查找其他工作空间,直到最后一个工作空间为止。
注意:如果除了
source /home/xxx/catkin_ws/devel/setup.bash
之外,还使用export ROS_PACKAGE_PATH=${ROS_PACKAGE_PATH}: ~/ORB_SLAM/ORB_SLAM2/Examples/ROS
命令在~/.bashrc
中固定了终端的环境变量,那么需要注意先后顺序,~/.bashrc
文件中越靠下的路径在ROS_PACKAGE_PATH
中越靠前。
查看所有ROS相关的环境变量命令:env | grep ros
;
查看ROS_PACKAGE_PATH变量的值:echo $ROS_PACKAGE_PATH
。
参考
- 胡春旭. ROS机器人开发实践. 北京:机械工业出版社,2018.5