传统上,ROS 1的每一代系统都基于某一个版本的Ubuntu系统进行开发,而其依赖库规模庞大,再加上Python 2/3的转换问题,导致在不同版本的Linux系统上原生编译安装非对应版本的ROS较为困难。这主要体现在新版本系统往往没有提供部分旧版ROS所需的依赖包。理论上讲,我们可以自行编译这些依赖包,但可能比较麻烦(依赖问题)。
当然,通常来讲使用与系统版本最匹配的ROS版本是最佳选择。 但是,现实中往往会遇到因种种原因而难以实施ROS版本迁移的情况,本文主要是探讨这种情况下的解决方案。
关于Docker的介绍/安装可在这里查看。本解决方案可以说是让Docker发挥“轻量级虚拟机”的功效。(Docker本身当然并非传统意义上的“虚拟机”,此处仅说明用途)
值得庆幸的是,Docker Hub中已经有正规的ROS Docker Image提供。其中一个属于Docker Official Image,但其中的tag仅有较核心的、不带图形界面的ROS版本。更多的版本由OSRF上传,其中含有常用的desktop-full版本,理论上可以胜任所有使用ROS的工作。
ROS官方Wiki上也有关于如何在Docker中部署ROS的一些文档。以下列出了一些笔者自己实验中常用的命令以及遇到的问题和解决方案。
使用命令
$ docker run -it osrf/ros:kinetic-desktop-full bash
即可在docker中运行ROS。如需使用不同版本可参阅这里。
像这样调用docker
$ docker run -it \
--env="DISPLAY" \
--env="QT_X11_NO_MITSHM=1" \
--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
osrf/ros:kinetic-desktop-full \
rqt
即可实现利用主机的X Server显示图形界面。如果遇到类似于cannot connect to X server unix:0
这样的报错,则需在主机上使用xhost
工具,如xhost +local:root
来向容器提供X Server的访问权限。或者参考下一节的做法。
原理:在容器中安装好能够支持对应显卡的OpenGL实现库,如mesa、libglvnd等,再设法将显卡的有关硬件节点挂载在容器内,即可实现OpenGL图形加速。
可以使用OSRF官方出品的工具rocker来辅助。由于ROS Kinetic的容器仍然是Ubuntu 16.04的环境,其中的库版本较老或缺失,因此需要做比较多的patch,好在rocker可以基本将这个过程自动化。以下以NVIDIA为例作说明。
注意前提: 主机上已经安装好GPU驱动程序(Intel/AMD通常没什么问题,NVIDIA建议使用Ubuntu官方打包的推荐驱动,如nvidia-driver-460
)。
首先按NVIDIA的说明在主机上安装nvidia-docker2
,之后就可以使用类似于
$ rocker --nvidia --x11 osrf/ros:kinetic-desktop-full bash
这样的命令来启动环境。注意在加上--x11
参数之后,rocker会自动配置有关X11的env和volume,因此不需再手动添加上一节所写的那些参数。
还需要注意的是,在容器内部,最好添加如下的环境变量
$ export __GLX_VENDOR_LIBRARY_NAME=nvidia
以确保GLX程序(RViz、Gazebo等)选择使用NVIDIA的vendor library来进行渲染。如果是需要使用PRIME进行显卡切换的混合显卡设备,则可能还需要使用
$ export __NV_PRIME_RENDER_OFFLOAD=1
来正确启用NVIDIA进行渲染(参见)。
通过观察rocker运行时的输出可以发现,它主要是从NVIDIA发布的基于Ubuntu 16.04的libglvnd的docker image中把有关的库文件提取出来,放入标准的ROS Docker Image中。之所以要这么打补丁,一部分是因为Ubuntu 16.04的官方源中并没有标准的libglvnd提供(应该是年代问题)。
理论上讲,使用非NVIDIA进行图形加速应该更简单,因为驱动开源。然而,还是因为Ubuntu 16.04可能太老,其mesa库很可能无法支持较新的显卡,所以笔者没有测试成功,但理论上讲,如果能够给Docker Image打上新版的mesa,那么再配合上设备节点的挂载(--device
参数),应该就能够实现使用Intel/AMD的图形加速了。