上一篇我们已经接触过工作空间的概念,并简单了解体验了一点构建包、测试包的流程,此篇会深入一点学习工作空间相关内容。
前言
一个工作空间是包含了ROS 2的功能包的目录(文件夹),在使用ROS 2之前我们得激活一下目标工作空间的环境变量(source environment),这样我们才能在终端中正常的使用这些功能包。
下面简单介绍下underlay和overlay这俩概念(其实也是借鉴了物理网络和逻辑网络的相关理念),后文会继续提到,不能装作看不到啊。
在ROS 2的上下文中,underlay指的是ROS 2工作空间的基础层。它包含了ROS 2系统中常用和核心的软件包,通常是ROS 2安装的一部分或者是ROS 2发行版默认包含的一些软件包。而overlay则是一个可以添加新的包而不影响现有ROS 2工作区的工作空间(辅助工作空间,也可以叫第二工作空间);underlay中包含着overlay的依赖包;overlay中的包会覆盖underlay中的包。
对于我们初学者来说,有点高深了,莫慌,咱边学边练,边学边掌握。
动动手
激活环境变量
我们安装的主ROS工作空间可能就是underlay(ROS工作空间基础层),但是不要认为情况都是这样,主ROS工作空间不一定都是underlay,也有可能是由overlay(辅助工作空间)承担。
我们通过下面的命令激活下环境变量:
$source /opt/ros/iron/setup.bash
创建一个新的目录
我们最好为每一个新的工作空间创建一个新的目录文件夹,名字叫啥无所谓,但最好能突出该工作空间的目的。当然,我们也可以不必创建那么多新的工作空间,我们可以在一个工作空间的src路径下添加我们的各种目的功能包。由于上一篇我们已经创建了一个工作空间,下面创建的命令我们看一下就行。
$mkdir -p ~/ros2_ws/src
$cd ~/ros2_ws/src
下载示例
上一篇我们已经通过git clone或下载zip的方式将官方提供的例子文件都弄到了ros2_ws/src文件夹下,现在我们即将再次clone一份例子到src文件夹下,执行下面命令(终端得cd到src路径下, -b的意思不是二进制版本啊小伙伴们(我就怕你们会这么想~),而是对应的ROS 发行版本(ROS branch,分支),因为不同版本都有对应的例子文件,会有些区别,不能搞岔了):
$git clone https://github.com/ros/ros_tutorials.git -b iron
我们熟悉的小海龟例子就在turtlesim这个包里面(后面还是继续拿它说事),仓库中(githup上对应该例子的文件夹存储网络地址)另外三个文件夹包没有被编译,因为它们里面都包含了COLCON_IGNORE文件(无内容,空文件),在上一篇我们在最后曾经提到COLCON_IGNORE的事情。
到目前为止,我们已经万事俱备,但是此时的工作空间还不是实际意义上的功能完整,我们还需解决一些软件包的依赖问题,等这东风也准备好了,我们就可以构建我们的工作空间了。
解决依赖项问题
我们最好在构建工作空间之前养成检查依赖项的好习惯(虽然有时的确有点多余),如果工程很大,构建起来往往很费时,你不希望在等待一俩个小时之后给你回了个失败才意识到是依赖项不全的原因吧。
首先终端进入到我们的工作空间根路径下再进行依赖项的工作:
$rosdep install -i --from-path src --rosdistro iron -y
如果返回#All required rosdeps installed successfully这样的字眼说明真的万事俱备了,如果你碰到了下面的情况,说明我们之前安装的东西还不全呐,根据它的提示逐项进行。
如果在安装更新的过程中出现下面的几种超时情况:
那么要庆幸自己又有机会去解决一个陌生的问题啦。
解决rosdep update 超时问题
其实原因大家也能猜个七七八八,git资源链接里面的https://raw.githubusercontent.com访问不了,还是不友好的网络环境导致。我主要参考了此篇文章才解决掉的,当然啦,网上的文章都是解决ROS 1的问题,我们是ROS 2,所以需要根据实际情况做些调整(比较少),步骤简述如下。
1. 将rosdistro clone到自己的家目录下(我的是/home/mike):
$git clone https://github.com/ros/rosdistro.git
下载完成后(如果github clone失败请往上翻找到解决办法),我们检查下:
里面包含了很多ROS版本,包括我们的iron,那就对了;
2. 修改4个文件
2.1 20-default.list
$cd /home/mike/rosdistro/rosdep/sources.list.d/
$sudo gedit 20-default.list
之前的内容是:
修改后的内容是:
2.2 gbpdistro_support.py
$sudo gedit /usr/lib/python3/dist-packages/rosdep2/gbpdistro_support.py
找到宏FUERTE_GBPDISTRO_URL,替换后的内容为:
FUERTE_GBPDISTRO_URL = 'file:///home/mike/rosdistro/' \
'releases/fuerte.yaml'
2.3 rep3.py
$sudo gedit /usr/lib/python3/dist-packages/rosdep2/rep3.py
找到宏REP3_TARGETS_URL,替换后的内容为:
REP3_TARGETS_URL = 'file:///home/mike/rosdistro/releases/targets.yaml'
2.4 __init__.py
sudo gedit /usr/lib/python3/dist-packages/rosdistro/__init__.py
找到宏DEFAULT_INDEX_URL,替换后的内容为:
DEFAULT_INDEX_URL = 'file:///home/mike/rosdistro/index-v4.yaml'
3. 替换20-default.list
如果你之前执行过sudo rosdep init命令,那么在/etc/ros/rosdep/sources.list.d路径下会生成一个20-default.list文件,我们将第一步修改好的该同名文件覆盖掉/etc/ros/rosdep/sources.list.d/20-default.list即可:
sudo cp /home/mike/rosdistro/rosdep/sources.list.d/20-default.list /etc/ros/rosdep/sources.list.d/
最后我们再来执行一次rosdep update:
搞定!
我们继续解决依赖项的问题,执行下面的命令(终端切换到工作空间根目录ros2_ws):
$rosdep install -i --from-path src --rosdistro iron -y
构建工作空间(用colcon)
还是保持在工作空间的根路径下(ros2_ws),执行如下命令进行构建:
$colcon build
因为我没有将ros2_ws/src路径下的examples文件夹删除,所以连同这次的都一块构建了,我们可以在安装ros2_ws/install路径下看到我们熟悉的turtlesim,
补充
colcon构建的其他有用参数:
--packages-up-to构建所需的包及其所有依赖项,但不是整个工作空间(以节省时间);
--symlink-install避免了每次调整python脚本时都需要重新构建;
--event-handlers console_direct+在构建时显示控制台输出(也可以在日志目录中找到);
--executor sequential顺序逐个处理包,而不是使用并行机制。
激活overlay空间
我们重新打开一个终端(如果在刚才执行colcon build的终端执行source命令可能会引起莫名其妙的问题,大家可以试试看会有什么问题出现),通过老方法进行激活环境变量(可以在任何路径):
$source /opt/ros/iron/setup.bash
在工作空间ros2_ws下按照下面的命令激活overlay(会覆盖工作空间基础层underlay):
$source install/local_setup.bash
补充
通过激活overlay的local_setup.bash仅会将overlay层中可用的功能包添加到环境中去,如果我们激活ROS 2安装路径下的setup.bash那么就是将underlay层中可用的功能包添加到环境中去,这样一来,我们就可以以激活脚本的不同而灵活使用两种工作空间了。
因此,我们先激活ROS 2主安装路径下的setup.bash,再激活overlay层的local_setup.bash,就像我们上面做的那样,其实与我们直接激活ros2_ws路径下的setup.bash效果是一样的,那是因为ros2_ws路径下的setup.bash已经包含了underlay基础层的环境。(不大理解也没关系啊)
我们现在就可以启动小海龟节点了:
$ros2 run turtlesim turtlesim_node
但是,目前会存在一个问题,我们在ROS 2刚开始的文章里已经运行过小海龟例子N遍了,那时游动的小海龟可是根正苗红,它就是我们在安装ROS 2时自带的(underlay基础层空间),而我们今天又创建了一个工作空间(overlay上层空间)ros2_ws,里面又构建了一个小海龟例子(到这个地方,是不是关于underlay和overlay的概念突然就清晰明了了),那我们启动的这个turtlesim_node节点到底是根正苗红underlay里面的小海龟呢还是ros2_ws(overlay里面)的小海龟呢???
为了进一步明确这种问题,我们需要修改小海龟窗口上面的主题名称来区别。
修改overlay空间(ros2_ws)
利用gedit打开ros2_ws/src/ros_tutorials/turtlesim/src/turtle_frame.cpp,找到第52行,将窗口标题修改成“MyTurtleSim”,你也可以取个其他与“TurtleSim”不一样的名字。
修改完成之后我们重新构建一下功能包, 正好试用下上文提到的单独构建一个功能包的参数命令:
$colcon build --packages-up-to turtlesim
切换到执行过overlay空间中source install/local_setup.bash的终端 ,再次启动小海龟:
$ros2 run turtlesim turtlesim_node
我们在执行underlay空间source /opt/ros/iron/setup.bash命令的终端也启动小海龟:
通过上面的现象可以看到,overlay(ros2_ws)空间中的修改 并没有影响到underlay空间中的内容(如果在overlay那个终端重新source underlay的setup,露脸的是根正苗红还是?自己try下),你看,多好,距离产生美嘛。
在平时的开发中,为了节省时间和环境资源,我们还是尽量使用overlay空间,因为没必要每次开发调试个别的功能包而加载所有的依赖和资源吧。
本篇完。