3.3 工作空间的覆盖

ROS允许多个工作空间并存,每个工作空间的创建、编译、运行方法都相同,用户可以在不同项目的工作空间中创建所需要的功能包。但有一种情况:不同的工作空间中可能存在相同命名的功能包,如果这些工作空间的环境变量都已经设置,那么在使用该功能包的时候,是否会发生冲突?如果不会,ROS又会帮我们选择哪一个功能包呢?

3.3.1 ROS中工作空间的覆盖

ROS的工作空间有一个机制——Overlaying,即工作空间的覆盖。所有工作空间的路径会依次在ROS_PACKAGE_PATH环境变量中记录,当设置多个工作空间的环境变量后,新设置的路径在ROS_PACKAGE_PATH中会自动放置在最前端。在运行时,ROS会优先查找最前端的工作空间中是否存在指定的功能包,如果不存在,就顺序向后查找其他工作空间,直到最后一个工作空间为止。

可以通过以下命令查看所有ROS相关的环境变量,其中包含我们最为关心的ROS_PACKAGE_PATH(见图3-8)。


$ env | grep ros

图3-8 查看所有ROS相关的环境变量

3.3.2 工作空间覆盖示例

例如我们通过以下命令安装了ros-kinetic-ros-tutorials功能包:


$ sudo apt-get install ros-kinetic-ros-tutorials

安装完成后使用rospack命令查看功能包所放置的工作空间(见图3-9)。

图3-9 查找功能包的存放路径

roscpp_tutorials是ros-tutorials中的一个功能包,此时该功能包存放于ROS的默认工作空间下。接下来,我们在自己的catkin_ws工作空间中也放置一个同名的功能包,可以在GitHub上下载ros-tutorials功能包的源码:


$ cd ~/catkin_ws/src
$ git clone git://github.com/ros/ros_tutorials.git

然后编译catkin_ws工作空间并设置环境变量:


$ cd ~/catkin_ws
$ catkin_make
$ source ./devel/setup.bash

环境变量设置成功后再来查看roscpp_tutorials功能包的位置(见图3-10)。现在,ROS查找到的roscpp_tutorials功能包就在我们创建的catkin_ws工作空间下,这是因为在ROS_PACKAGE_PATH环境变量中,catkin_ws工作空间的路径在系统工作空间路径之前。

图3-10 查找功能包的存放路径

这种覆盖机制可以让我们在开发过程中轻松替换系统或其他工作空间中原有的功能包,但是也存在一些潜在的风险,比如在如下结构的两个工作空间中:


catkin_ws/
  src/
    package_a
    package_b  # depends on package_a
  devel/
    ...
overlay_ws/
  src/
    package_a
  devel/
    ...

如果工作空间overlay_ws中的package_a功能包覆盖了catkin_ws中的package_a,由于package_b功能包是唯一的,而且无法知晓所依赖的package_a是否发生变化,从而导致package_b功能包产生潜在的风险。