ROS项目在Docker容器中的落地应用
疑问和解答 Q&A
Q: 为什么要使用Docker容器封装上位机ROS系统?
A: ROS是驾于Linux上的一套源操作系统,由于ROS的不同版本对宿主机有一定的影响,因此将ROS封装在一个容器中。
Q: 使用Docker容器的优缺点?
A: 这样的做法有很多的好处,一是不会影响到宿主机上原本的系统,使其保证干净复用性,二是操作部署方便简单,具有拓展易用性,三是为之后做多级联动集群灾备等做铺垫。 缺点是要注意设备主机与容器之间的网络连通性,遇到一些问题的时候不好判断是容器到宿主机之间的通信问题还是其他问题。
Q: 使用Docker容器部署ROS还有哪些为解决的问题?
A: 由于个人能力以及容器在Arm工控机对OpenGL版本的高度依赖,导致我们的容器部署 在Nvidia系列上位机上时,Rviz显示异常,但在X86上已完美解决。
Q: 对ROS在Docker上使用的展望?
A: 由于ROS1天生的缺陷,其实是没有办法做真正意义上的多机联动的,但是ROS2上使 用了DDS数据分发分布式通讯,解决了ROS1的中心化强依赖Master,做到了真正的去中心化,因此使用ROS2部署在Docker容器里面后有需求的话我们可以采用kubernetes做集群化统一管理。上述有些点其实已经在AutoWare.auto上得以实现,因此相信在不久的将来ROS可以普遍的容器化管理和使用。
案例
- 先决条件
X86工控机上或者Windows 10 WSL1/WSL2上安装Linux(Debian/Ubuntu/CentOS/OpenSUSE/Arch Linux)系统。 - 操作指南
这里使用一台干净的Ubuntu20.04进行测试,安装 ssh 启动后进行远程连接方便测试。
sudo apt install openssh-server
sudo service ssh start
安装 Docker-ce ,删除之前Ubuntu自带的Docker。
sudo apt remove docker docker-engine docker.io containerd runc
安装一些必要依赖。
sudo apt install -y \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
配置Docker-ce源,更新源。
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
sudo apt update
安装Docker-ce。
sudo apt install docker-ce docker-ce-cli containerd.io
将Docker加入 用户组,替换Docker国内源,重启Docker。
sudo usermod -aG docker $USER
cd /etc/docker
sudo vim daemon.json
{
"registry-mirrors": [
"https://hub-mirror.c.163.com",
"https://ustc-edu-cn.mirror.aliyuncs.com",
"https://ghcr.io",
"https://mirror.baidubce.com"
]
}
sudo systemctl restart docker
拉取构建portainer docker可视化镜像。
sudo docker pull portainer/portainer-ce
sudo docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock --restart=always --name prtainer portainer/portainer-ce
运行容器后在同网段的机器上访问docker所在主机IP:9000即可出现portainer 可视化WEB界面。
设置用户名和密码创建用户。
进入后点击Home。
连接本地docker主机即可看到本地镜像容器仓库。
在终端查看磁盘空间和内存大小,拉取运行使用JUDR镜像至少要预留15G的空间以及4G的内存。
拉取JUDR容器镜像,这里等待的时间较长由于镜像较大10个G左右,需要等待大概40分钟。
sudo docker pull cocoleng/jujon_docker_ros_x86
查看docker镜像。
sudo docker images
在Ubuntu系统上下载对应版本的Nomachine远程连接工具。
下载网址https://www.nomachine.com/download/linux&id=1
安装Nomachine。
sudo dpkg -i nomachine_7.8.2_1_amd64.deb
在你的Windows或者mac上也在上面网站上下载对应版本的nomachine, 安装后打开即可发现上面Ubuntu主机。
输入用户名和密码,后面全选OK即可。
使用nomachine登录到Ubuntu界面。
建立一个run.sh,一个exec.sh的脚本文件,并给予它们执行权限。
脚本文件命令解读:
在这里插入代码片
- xhost +localhost 开启没有图形界面的docker通过X11图像接口使用宿主机的OpenGL图形库显示图形界面。
- docker run #运行docker容器
- -idt #-it是进入命令行 -d是放在后台运行 这里其实是放在后台运行,并不会直接进入命令行,写-idt仅是个人习惯问题
- –device=/dev/dri #挂载图像显示的设备
- –device=/dev/ttyUSB0 --device=/dev/ttyUSB1 --device=/dev/video0 --device=/dev/video1 #挂载上位机到下位机连接的串口线、雷达、深度相机之类的设备。这里是用户最值得注意的地方,如果挂载没有的设备容器会启动失败,因此要自己去先查看设备串口设备是不是连接好,并且在宿主机下可以查看到
- –group-add video #深度相机扔到video组
- –hostname jubot #修改容器里面的hostname 不然默认显示容器id
- –volume=/tmp/.X11-unix:/tmp/.X11-unix #挂载图像显示的配置文件等
- -v /etc/udev/rules.d:/etc/udev/rules.d #挂载udev规则到容器,但是这里并没什么效果,因为docker暂时不支持挂载udev,先保留到这里吧 -v和 --volume的作用都是一样的
- –env=“DISPLAY=$DISPLAY” #设置容器内部DISPLAY显示到宿主机
- –privileged #特权模式,可以挂载未经验证的设备
- -p 2222:22 -p 8080:8080 -p 11311:11311 -p 34567:34567 #把容器内部的端口映射到宿主机,不然没办法访问容器内开启的一些走http或者一些走网络的服务,根据自身应用场景添加
- –name=JUDR_X86 #运行容器名称
- cocoleng/jujon_docker_ros_x86:latest #运行镜像
- /bin/bash #运行后进入的命令行是什么类型
- docker exec #进入容器
run.sh脚本文件,输入下面命令。
sudo xhost +localhost
sudo docker run -idt --device=/dev/dri --device=/dev/ttyUSB0 --device=/dev/ttyUSB1 --device=/dev/video0 --device=/dev/video1 --group-add video --hostname jubot --volume=/tmp/.X11-unix:/tmp/.X11-unix -v /etc/udev/rules.d:/etc/udev/rules.d --env="DISPLAY=$DISPLAY" --privileged -p 2222:22 -p 8080:8080 -p 11311:11311 -p 34567:34567 --name=JUDR_X86 cocoleng/jujon_docker_ros_x86:latest /bin/bash
exec.sh脚本文件,输入下面命令。
sudo docker exec -it JUDR_X86 /bin/bash
查看上述串口设备是否在宿主机上连接成功并识别到,注意,只有识别到的才可运行上述命令挂载到镜像,当然也可以不挂载,删除上述脚本中的–device挂载的串口设备即可。
接下来就可以运行并进入我们的容器了。
./run.sh
./exec.sh
如果显示下面界面即进入容器成功。
进入后需要给容器的设备权限,这里为了后续不出通信方面的问题就直接给最高权限吧。
sudo chmod 777 /dev/ttyUSB*
可以开启多个终端,每个终端想要进入容器只需要执行前面我们创建的exec.sh即可。
第一次运行launch文件的时候可能会出现下面警告,只需关掉重新执行或者等它自己找到TF节点,大概需要5-10秒。
没有警告的时候即可使用命令查看TF连接。
rosrun rqt_tf_tree rqt_tf_tree
使用命令启动建图节点测试雷达相机等节点是否工作正常。
roslaunch jubot_slam_navigation jubot_mapping_cartographer.launch
rosrun rviz rviz
选择容器中提前配置好的rviz启动文件即可显示下图效果。
在portainer中查看镜像运行的状态。
也可以通过portainer进入容器终端方便快捷的操作。
后续启动容器,删除容器,停止容器,运行容器,查看容器各项运行性能都可以在portainer上进行。