ROS的工作空间overlay机制


官方的介绍请见,Overlaying with catkin workspaces,以下系自己理解,有误请指正。

Overlaying refers to building and using a ROS package from source on top of an existing version of that same package. In this way your new or modified version of the package "overlays" the installed one.

覆盖是指在同一个包的现有版本之上从源代码构建和使用 ROS 包。这样,您的新版本或修改版本的软件包“覆盖”了已安装的版本。

简单来说,就是允许存在不同版本的ROS Package。

单层覆盖

通常情况下,使用apt安装的ROS二进制包会在/opt/ros//下,不能进行源码更改。此时需要修改功能,只能从源码重新编译。

catkin_ws为例,使用

$catkin_make

会打印

-- This workspace overlays: /opt/ros/noetic

/opt/ros/noetic中的ROS包会被catkin_ws中的同名包覆盖掉,下次使用ros相关工具调用使用的就是catkin_ws中源码编译的版本。

多层覆盖

涉及到多工作空间时,会在.bashrc中添加source ${workspace}/devel/setup.bash。可能会有同名包出现在多个工作空间,且各不相同。首先推荐是,按照工程划分工作空间,每次只source某一个工作空间,这样不容易出问题。

如果非要同时source多个工作空间,那么顺序上,在.bashrc中排在后面的工作空间会覆盖掉前面的工作空间。

source /opt/ros/noetic/setup.bash
source ~/1_ws/devel/setup.bash  #工作空间1
source ~/2_ws/devel/setup.bash  #工作空间2
source ~/3_ws/devel/setup.bash  #工作空间3

#如果出现同名包,rosrun时会使用工作空间3的

在环境变量上,前面的会覆盖掉后面的

$echo $ROS_PACKAGE_PATH
/home/user/catkin_ws/src:/opt/ros/noetic/share

容易出的问题

写在前面,如果而非要多层覆盖,那么建议按顺序修改编译。如果出现问题,首先查找多个工作空间下的同名包是否被依赖,根据实际需要修改.bashrc中的工作空间顺序,调整覆盖顺序,重新按顺序编译一般可以解决

按顺序多层覆盖,同时不按顺序修改和编译,容易导致同名依赖出现问题。根据举例

1_ws/
  src/
    package_1 
    package_2  # depends on package_a
  devel/
    ...
2_ws/
  src/
    package_1
  devel/
    ...

先有1_wspackage_2依赖package_1,正常编译。新增2_ws,其中删减了某个头文件的package_1覆盖1_ws中的package_1。此时package_2依赖的是1_ws中的还是2_ws中的?

这时新搞一个工作空间,再次依赖package_1,依赖的是那个?

如果再有一个package_3,同时依赖package_2package_1,分别依赖的是哪个?

这时候再修改编译pacakge_1package_2呢,对pacakge_3的有什么影响?

我反正是不知道。混乱的情况有无数种,我们不需要理清混乱的规律,从源头好好规划避免混乱才是解决问题的方式。

下面附官方的说明,里面也有官方的建议

Underlayed build artifacts shine through

With catkin, overlay only means that where similarly named build artifacts (e.g. c++ header files) exist in overlay_ws_overlay and overlay_ws, those in overlay_ws_overlay will be used. Differently named artifacts, or artifacts deleted in the overlaying packages, can still visible to dependent packages. This depends on whether the dependent package depends on one package in the underlay workspace that has not been overlayed. The same goes for the overlaying package itself, i.e. cpp files may compile using headers of the overlayed package under the circumstances described above.

So as a consequence, if overlay_ws/src/package_a defines a header file that overlay_ws_overlay/src/package_a does not define, this header file will still be usable by any package in overlay_ws_overlay. It is not hidden by the overlay. The only way to prevent this for sure is to not use overlaying. Else users must be careful not to remove build artifacts in overlaying packages.

Dependent packages in overlay are not rebuild

The other limitation is that package_b, which depends on package_a, will with this setup never be rebuild, meaning it will not use any build artifacts of overlay_ws_overlay/src/package_a. This can cause certain kinds of failures.

To be on the safe side, users need to make sure that all such packages that depend on an overlaying package are also present as source in the overlaying workspace. This can also be achieved in the example above by creating a symbolic link from overlay_ws_overlay/src/ to overlay_ws/src/package_b.