使用Docker部署带GPU加速的ROS Desktop

最近需要折腾ROS,而ROS对Archlinux的支持可不是一般的差。曾经尝试过使用ROS官方上的安装方式[1]安装ROS Desktop,结果用yay安装了半天,不是网络错误就是依赖无法解析。于是想到了使用Docker部署ROS Desktop。

一开始还打算使用一个Ubuntu Docker镜像,然后再在里面慢慢搭建ROS的,结果一看ROS Wiki文档[2],好家伙,原来早就做好这种镜像了,还有带NVIDIA CUDA加速的。于是一步一步按照教程来就好啦。不过除了官方的文档,我们还需要做些优化才能很好地利用各种features。

准备安装

首先我们需要在主机上安装NVIDIA为各发行版打包好的Docker镜像。对于NVIDIA支持的各发行版,可使用软件包管理器安装nvidia-docker2软件包。而对于Archlinux,可从AUR安装:

yay -S nvidia-docker

还需安装libglvnd软件包:

sudo pacman -S libglvnd

自定义Docker镜像

创建一个文件夹my_ros_image并进入,创建Dockerfile文件:

mkdir my_ros_image & cd my_ros_image
touch Dockerfile

编辑Dockerfile文件,以定制我们的Docker镜像:

FROM osrf/ros:melodic-desktop-full

# nvidia-container-runtime
ENV NVIDIA_VISIBLE_DEVICES \
    ${NVIDIA_VISIBLE_DEVICES:-all}
ENV NVIDIA_DRIVER_CAPABILITIES \
    ${NVIDIA_DRIVER_CAPABILITIES:+$NVIDIA_DRIVER_CAPABILITIES,}graphics

FROM后面的是要基于哪个包定制镜像。这里我们使用的是ROS Melodic版本的,全部的镜像可以参照https://hub.docker.com/r/osrf/ros/tags?page=1&ordering=last_updated。最新的版本是noetic-desktop-full,相应地替换为osrf/ros:noetic-desktop-full即可基于Noetic制作镜像。

然后进入Dockerfile的文件夹,开始拉取和制作镜像:(别忘了第二行命令后面的点,表示在当前目录建立Docker镜像)

cd my_ros_image/
sudo docker build -t my_ros_image_melodic .

启动镜像

编写以下脚本启动镜像。

#!/bin/bash

XAUTH=/tmp/.docker.xauth
if [ ! -f $XAUTH ]
then
    xauth_list=$(xauth nlist :0 | sed -e 's/^..../ffff/')
    if [ ! -z "$xauth_list" ]
    then
        echo $xauth_list | xauth -f $XAUTH nmerge -
    else
        touch $XAUTH
    fi
    chmod a+r $XAUTH
fi

docker run -it \
    --env="DISPLAY=$DISPLAY" \
    --env="QT_X11_NO_MITSHM=1" \
    --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
    --env="XAUTHORITY=$XAUTH" \
    --volume="$XAUTH:$XAUTH" \
    --runtime=nvidia \
    my_melodic_image \
    bash

给这个脚本赋予相应的权限:

chmod a+x ./start.sh

然后执行,即可启动一个ROS容器。

测试镜像

简单地,先启动这个容器,就会进入到这个容器的命令行界面。然后在容器内执行:

roscore > /dev/null & rosrun rviz rviz

如出现图形化界面,即启动成功。

其他技巧

在两个shell内执行命令

调试ROS的时候,我们可能需要不止两个shell,而若直接attach到容器,实际上访问的是一个shell。要启动另外一个容器里的shell,只需让容器再启动一个bash就可以了:

sudo docker exec -it CONTAINER_ID bash

CONTAINER_ID在每次容器启动时都不一样,你可能需要通过sudo docker ps来获取其ID。

首先通过正常方式开启shell
然后通过id启动另一个bash进程

Bash:命令找不到(Command not found)

默认情况下ROS的环境是由Docker建立的,在容器启动时即告诉容器里的系统应该如何初始化。所以直接启动bash是不会初始化ROS环境的。要使bash打开时初始化,仿照官方的ROS安装教程[3],需要在容器里执行:

echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
source ~/.bashrc

那么bash启动时即自动初始化ROS环境,即可解决命令找不到的错误了。但是这对于Docker镜像的更改只是临时的,请查看下一小节永久保存镜像。

永久保存镜像

有时候我们对镜像进行了修改,而Docker镜像一旦退出,其状态就不可保存,一切将恢复成原来的样子。若需要保存镜像,我们需要执行:

sudo docker commit CONTAINER_ID my_ros_image_noetic

CONTAINER_ID在每次容器启动时都不一样,你可能需要通过sudo docker ps来获取其ID。my_ros_image_noetic替换成你的镜像名称。

映射主机目录

很简单,在启动脚本文件里加上一行:--volume /主机目录:/镜像目录即可,要注意处理好目录权限问题。

脚注和参考链接

[1] ROS Wiki 的方法是:使用yay从AUR仓库安装ros-version-desktop。链接:http://wiki.ros.org/melodic/Installation/ArchLinux
[2] ROS Hardware Acceleration:http://wiki.ros.org/docker/Tutorials/Hardware%20Acceleration#nvidia-docker2
[3] ROS安装教程-配置环境http://wiki.ros.org/noetic/Installation/Ubuntu#noetic.2FInstallation.2FDebEnvironment.Environment_setup

发表评论