Ubuntu通过docker安装任意版本ROS + 一键启动教程
前言:
众所周知,不同的Ubuntu版本能安装的ROS版本是不一样的,Ubuntu22.04只能安装ROS2的各个版本,如果想使用ROS1只能在Ubuntu20.04及以下版本安装。通过Docker安装ROS可以无视系统版本安装任意版本的ROS,并且实现很好的隔离,甚至多个ROS版本共存也可以。
(在鱼香ROS中有一键安装docker和通过docker安装ROS的指令:小鱼的一键安装系列,但是中间可能会遇到一些问题,例如因为镜像源问题卡在拉取镜上,或者想根据自己的需求对容器做一些设置不知道怎么修改,本教程会详细介绍具体是如何安装的,并且对于每个参数都有详细的介绍)
通过Docker安装ROS首先得知道Docker怎么用,建议先通过一些其他的教程了解一下docker和一些基本的使用。
- 一、安装Docker
- 二、拉取镜像
- 三、创建容器
- 四、使用容器
- 4.1 通过命令运行【不推荐】
- 4.2 一键启动【推荐】
一、安装Docker
建议直接使用小鱼的一键安装系列
(或者自行寻找其他的安装教程,也要找教程安装一下Docker显卡驱动,方便以后在Docker中使用显卡)
二、拉取镜像
sudo docker pull osrf/ros:noetic-desktop-full
本教程以ROS-noetic版本为例,其他版本自行更换对应的镜像名称。
(一般ROS镜像命名都是osrf/ros:版本号-desktop-full
)
其他常用版本:
osrf/ros:melodic-desktop
- ROS Melodic 桌面全功能版
osrf/ros:kinetic-desktop
- ROS Kinetic 桌面全功能版
osrf/ros:humble-desktop
- ROS2 Humble 桌面全功能版
osrf/ros:foxy-desktop
- ROS2 Foxy 桌面全功能版
(全功能版可以加-full后缀,也可以不使用osrf/ros:的镜像,自己找一些其他的)
【如果遇到拉取镜像失败的情况,则需要换源】
拉取镜像时出现报错:docker: Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers).
docker的官方源国内封了,导致无法拉取到镜像。当更换国内的主流镜像源后可能会发现还是有这样的问题,因为很多常见的国内镜像源,例如阿里云中科大等等的docker镜像都关闭了。 所以只能从网上找别人搭的或者自己搭镜像源,换源方法如下:
① 编辑配置文件:
sudo nano /etc/docker/daemon.json
② 添加镜像源
输入:
{
"registry-mirrors": [
"https://xxxxx.cn", # 请替换为自己找的镜像源
"https://xxxxx.cn", # 请替换为自己找的镜像源
"https://xxxxx.cn" # 请替换为自己找的镜像源
]
}
给一个目前(24年9月份)还能用的第三方源的帖子链接:
从Docker拉取镜像一直失败超时?这些解决方案帮你解决烦恼
(如果不能用了大家只能自己再找其他的了)
③ 重启docker
systemctl restart docker
三、创建容器
3.1. docker run创建
sudo docker run -dit
--gpus all
-e NVIDIA_DRIVER_CAPABILITIES=all
--name=
-v /dev:/dev
-v /home/:/home/
-v /tmp/.X11-unix:/tmp/.X11-unix
-e DISPLAY=unix$DISPLAY
-w /home/
osrf/ros:noetic-desktop-full
Tip1:上一行对应自己的镜像名,需要修改,通过sudo docker images查看
Tip2: 后面可以跟一些容器启动后想运行的命令(如果有命令上一行最后别忘了加换行符)
# 可选参数:
--privileged
--net=host
--restart=xxx
参数说明:(表示续行符,这里有一个小坑,如果复制到Windows的文本编辑器修改后再运行续行符会识别不了,因为两个系统的 “” 格式不太一样,建议在Ubuntu里面编辑文本)
【更换
-dit
:-d:在后台运行容器、-it: 交互式运行容器,分配一个伪终端。--gpus all
: 将所有可用的 GPU 硬件设备分配给容器
(从Docker19.03开始,–gpus 选项可以直接处理GPU分配,不再需要设置NVIDIA_VISIBLE_DEVICES 环境变量)-e NVIDIA_DRIVER_CAPABILITIES=all
:设置环境变量,允许容器内的所有 NVIDIA 驱动功能。--name=your_name
:为容器指定一个名称-v /dev:/dev
:将宿主机的 /dev 设备目录挂载到容器的 /dev 目录,允许容器访问宿主机的所有设备。(可以解决USB无法挂载问题)(也可以单独选择只挂载某些设备例如:声卡/dev/snd等等)-v /home/your_username:/home/your_username
:将宿主机的用户目录挂载到容器的同名目录,这样容器可以访问宿主机用户的文件。-v /tmp/.X11-unix:/tmp/.X11-unix
:将宿主机的 X11 sockets 目录挂载到容器,允许容器访问宿主机的图形用户界面会话。-e DISPLAY=unix$DISPLAY
:设置环境变量 DISPLAY,使其与宿主机的显示环境变量相同,对于图形应用程序来说是必要的。-w /home/your_username
:设置容器内的工作目录。osrf/ros:noetic-desktop-full
:镜像名称或者ID(改成自己对应的版本)
可选参数:
--privileged
:给予容器root权限,可以执行一些需要高级权限的操作(例如:
访问宿主机的所有设备节点(如/dev下的设备文件)、修改或加载内核模块、
访问宿主机的某些受保护的文件等等)。这会造成潜在的安全风险。因为容器内的进程可以直接影响到主机系统,如果恶意进程获得了容器的控制权,可能会对主机系统造成严重的损害,但是一般只是用来学习做实验的普通用户不太需要担心安全问题。--net=host
:让容器与宿主机的网络以host模式连接,host模式下,容器没有自己独立的网络空间,容器将直接使用宿主机的网络接口(此时与外部网络通信时无需做端口映射)。默认为桥接网络:每个容器有一个自己的独立IP地址。--restart=xxx
:
no
:默认策略,在容器退出时不重启容器
on-failure
:在容器非正常退出时,才会重启容器
on-failure:n
:容器非正常退出时重启容器,并指定重启次数(不指定次数会一直重启直到启动成功)
always
:只要容器退出就重启容器
unless-stopped
:在容器退出时总是重启容器,除非它被手动停止或 Docker 本身被停止
四、使用容器
【Docker用户权限问题】:默认情况下,需要使用sudo权限来运行Docker命令,通过将用户添加到Docker用户组,可以在无需sudo的情况下运行Docker命令。
(如果当前用户没有加入Docker用户组并且没有sudo权限的话,会报错:permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock:
)
(如果是通过鱼香ROS安装的Docker,应该是不会出现用户组的问题,我记着一键安装的时候就已经设置好了)
添加方法如下:
# Way1:将指定用户username加入到docker组
sudo gpasswd -a username docker
# Way2:将当前用户加入到docker组
sudo gpasswd -a $USER docker
newgrp docker #切换到docker组
4.1 通过命令运行【不推荐】
① 配置访问宿主机的 X11 服务器
说明:docker容器中打开gazebo等可视化页面需要访问宿主机的 X11 服务器。而X11服务默认只允许『来自本地的用户』启动的图形程序将图形显示在当前屏幕上。所以需要给docker添加访问权限(否则会报错No protocol specified),有以下几种方法:
# Way1:允许所有本地连接访问 X11 服务器
xhost +local: >> /dev/null
# Way2:单独给 docker 访问 X11 服务器的权限
xhost +local:docker
# Way3:单独给 docker 中的某个容器访问 X11 服务器的权限
xhost +local:`docker inspect --format='{{ .Config.Hostname }}' $containerId` # $containerId替换为容器ID
【注意:这个命令的效果是临时的,它将持续到 X11 服务器重启或 xhost -local:
命令被执行来撤销这个设置。最好每次都输入一下这个命令】
② 启动容器
sudo docker start 容器id/名称 #(noetic)
③ 进入容器
sudo docker exec -it noetic /bin/bash
# (输入 exit 可以退出容器)
④ source ros路径
source /opt/ros/noetic/setup.bash
# 每个终端都要输入这个命令source一下,或者:(如下)
# 添加到容器的.bashrc可避免每次都要输入【推荐】
echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
source ~/.bashrc
注意:要根据自己的ros版本修改这个路径,例如humble版本:echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
⑤ 测试ros是否运行成功
roscore
4.2 一键启动【推荐】
① 创建一个文件夹用于存放启动命令,然后cd进入
以 ~/.docker/setup
文件夹为例
cd ~/.docker/setup
② 创建启动文件并编辑内容
这步操作是允许用户只使用容器名对容器进行操作,省去输入docker的原生指令
sudo nano your_name # 名称可以自定义,推荐和容器同名(noetic)
文件中输入以下内容并保存:
xhost +local:docker
echo "请输入指令控制容器: 启动(s) 重启(r) 进入(e) 关闭(c):"
read choose
case $choose in
s) docker start ;;
r) docker restart ;;
e) docker exec -it /bin/bash;;
c) docker stop ;;
esac
newgrp docker
说明:
- 其中
xhost +local:docker
是给docker添加X11访问权限,也可以改为xhost +local: >> /dev/null
表示允许所有本地用户连接到 X11 - 其中
docker xxx
是对应docker启动/重启/进入容器/关命令,可以根据docker的指令添加一些其他的命令,例如删除容器等等 esac
是用来结束 case 语句的,别给删了。newgrp docker
表示将当前shell会话的用户组切换到docker组,可以不使用sudo运行docker指令(需要确保你的用户账户已经被添加到docker组,前文中的【Docker用户权限问题】有提到)。
注意: 修改
为你的自定义名称。
③ 赋予文件可执行权限
sudo chmod +x 文件名(your_name)
④ 在~/.bashrc 中添加该文件所在路径
echo 'export PATH=$PATH:/home/your_username/.docker/setup' >> ~/.bashrc
⑤ 使用
设置好后任意终端中输入容器名(noetic)
即可进入容器,进入容器后先一次性设置一下ROS的source:
echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
最后退出(输入exit
)重新进入容器即可正常使用ros
其他注意事项:
进入ROS容器后先sudo apt-get update
更新一下源,否则可能无法在容器内通过apt install
安装其他包