前提
最近在处理多个ROS工作空间的时候遇到了一点小问题。总结来说,就是项目启动的时候,需要先启动工作空间A下的某个功能包,再启动工作空间B下的某个工作空间,并且由于使用ROS的pluglib机制和自定义的controller,导致工作空间A启动的时候需要能找到工作空间B下的一些文件。
但是ROS中如果我们在终端或者shell脚本中如果前后source两个不同工作空间下的devel/setup.bash,只有最后一个是生效的。
下面进行情况说明并且介绍解决方案。
测试
首先创建两个工作空间,每个工作空间创建两个功能包,功能包的实现可以是最简单的,因为本测试并不涉及到实际的业务逻辑。
── launch_workspace.sh
├── README.md
├── workspace_one # 工作空间one
│ ├── build
│ ├── devel
│ └── src
│ ├── package_one_a
│ └── package_one_b
└── workspace_two # 工作空间two
├── build
├── devel
└── src
├── package_two_a
└── package_two_b
不source任何工作空间
创建号两个工作空间后,分别在两个工作空间直接catkin_make
,此时,需要打印两个环境变量
可以看到,当我们并没有source
工作空间下的setup.bash
文件时,没有找到对应的ros package
,这就会影响对应roslaunch
和 rospack
找功能包的命令。
source一个工作空间
现在我们source第一个工作空间
source workspace_one/devel/setup.zsh
echo $CMAKE_PREFIX_PATH
# /home/ros/00-Docs-test/00-source/workspace_one/devel:/opt/ros/noetic:/opt/openrobots:
echo $ROS_PACKAGE_PATH
# /home/ros/00-Docs-test/00-source/workspace_one/src:/opt/ros/noetic/share
可以看到workspace-one和全局/opt/ros/noetic
的环境变量,此时workspace-one和全局的包都是可以找到的,也是可以正常启动对应的节点和launch文件的
source两个工作空间
现在我们source第二个工作空间
source workspace_two/devel/setup.zsh
echo $CMAKE_PREFIX_PATH
# /home/ros/00-Docs-test/00-source/workspace_two/devel:/opt/ros/noetic:/opt/openrobots
echo $ROS_PACKAGE_PATH
# /home/ros/00-Docs-test/00-source/workspace_two/src:/opt/ros/noetic/share
可以发现第一个工作空间已经被覆盖掉了
如何同时source两个工作空间?
ROS1本身有一个overlay机制,其中全局的环境/opt/ros/noetic
作为underlay
,而source的个人的工作空间作为overlay,用来覆盖全局环境中的同名功能包。
此时,我们是可以利用前后两次的source不同工作空间下的环境变量,达到启动不同节点的目的。
问题重现
但是本次的实际情况下,我们工作空间one下的A功能包,会去查找工作空间two下的功能包B,如果source第一个工作空间,那么找不到工作空间two下的功能包B,如果source第二个工作空间,那么第一个功能包A就启动不了。当然,前后source两个的话以最后一个为准。
解决办法1
首先删除工作空间two下的build和devel文件夹,然后在终端先source工作空间one下的环境变量,在进行catkin_make
rm -rf workspace_two/build workspace_two/deve
source workspace_one/devel/setup.zsh
cd workspace_two && catkin_make
# 此时我们在source workspace_two下的环境变量
source workspace_two/devel/setup.zsh
可以看到,现在是同时拥有两个工作空间的环境变量。也就同时满足了上述需求。
ROS会在catkin_make的时候检查当前的环境变量,并把当前的环境变量一起写入到编译后的文件中,这样source第二个工作空间的时候就直接把第一个工作空间给带上了。
解决办法2
直接修改第二个工作空间的devel/_setup_util.py
,添加上第一个工作空间的路径即可。
结论
在开发过程中,可以使用上述机制进行开发测试,但是实际部署的过程中还是尽量打包部署