XTDrone PX4 仿真平台|使用Docker快速部署仿真环境
- Docker简介
- NVIDIA驱动安装
- NVIDIA-Docker安装
- Docker镜像下载与使用
- Docker与宿主机建立ROS通信
- 宿主机安装 XTDrone 源码
宿主机系统环境Ubuntu20.04
Docker简介
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。NVIDIA 改进了原始的Docker,便于容器使用NVIDIA GPU。由于仿真环境的配置需要安装很多库,对于新手不太友好,因此我们提供了Docker镜像,便于开发者使用。尽管Docker理论上适配多种操作系统,但由于后续算法开发仍建议在本地进行,因此操作系统仍需使用Ubuntu。
NVIDIA驱动安装
nvidia-docker需要宿主机已经安装nvidia驱动,为了与镜像的驱动版本保持一致,开发者需要安装470版本,以下安装方式的前提是之前没有安装或是通过apt安装的nvidia驱动。如果之前是其他方法安装的驱动,要根据具体情况更改驱动版本。
安装 nvidia-driver-470 指令
sudo apt install nvidia-driver-470
查看GPU型号
jk-jone@JKKC:~$ lspci | grep -i nvidia
01:00.0 3D controller: NVIDIA Corporation Device 1f9c (rev a1)
查看当前NVIDIA驱动版本
sudo dpkg --list | grep nvidia-*
或者
cat /proc/driver/nvidia/version
jk-jone@JKKC:~$ sudo dpkg --list | grep nvidia-*
jk-jone@JKKC:~$
jk-jone@JKKC:~$ cat /proc/driver/nvidia/version
cat: /proc/driver/nvidia/version: 没有那个文件或目录
像这样则表示没有安装NVIDIA驱动
sudo apt install nvidia-driver-470
用这个装就行了
安装过程会有进度条
看到这个表示安装成功
NVIDIA-Docker安装
之后安装nvidia-docker
curl https://get.docker.com | sh && sudo systemctl --now enable docker
distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
&& curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update
sudo apt-get install -y nvidia-docker2
sudo systemctl restart docker
通过运行如下命令测试Docker使用安装成功
sudo docker run --rm --gpus all nvidia/cuda:11.0.3-base-ubuntu20.04 nvidia-smi
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error running hook #0: error running hook: exit status 1, stdout: , stderr: Auto-detected mode as ‘legacy’
nvidia-container-cli: initialization error: nvml error: driver not loaded: unknown.
出现了这个问题
翻了很多帖子,最后在github上 NVIDIA/nvidia-docker/issues/1648 找到答案。
是gpu的持久模式(nvidia-persistenced daemon)并未开启。
nvidia-smi
查询显卡资源的时候
报错
jk-jone@JKKC:~$ nvidia-smi -a
NVIDIA-SMI has failed because it couldn’t communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.
可能是内核版本更新的问题,导致新版本内核和原来显卡驱动不匹配
查看已安装内核
jk-jone@JKKC:~$ dpkg --get-selections |grep linux-image
linux-image-5.14.0-1051-oem deinstall
linux-image-5.14.0-1054-oem deinstall
linux-image-5.14.0-1058-oem install
linux-image-5.14.0-1059-oem install
linux-image-oem-20.04 install
查看正在使用的内核
uname -a
jk-jone@JKKC:~$ uname -a
Linux JKKC 5.14.0-1059-oem #67-Ubuntu SMP Mon Mar 13 14:22:10 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
显示为 5.14.0-1059
不知道安装nvidia驱动时的内核版本
不知道是不是不匹配造成的
只需执行两条命令就好
sudo apt-get install dkms
查看驱动版本
ls /usr/src | grep nvidia
jk-jone@JKKC:~$ ls /usr/src | grep nvidia
nvidia-470.182.03
sudo dkms install -m nvidia -v 470.182.03(470.182.03表示的是驱动版本号)
jk-jone@JKKC:~$ sudo dkms install -m nvidia -v 470.182.03
Module nvidia/470.182.03 already installed on kernel 5.14.0-1059-oem/x86_64
所以不是内核不匹配造成的
重启下电脑试试
呵呵,画面出来了
nvidia-smi -a
查询自己的 Persistence Mode 是否开启
果然 Persistence Mode 为 Disabled
使用root权限执行如下命令:
nvidia-smi -pm ENABLED
再次用下面的命令,来查看Docker是否安装成功
sudo docker run --rm --gpus all nvidia/cuda:11.0.3-base-ubuntu20.04 nvidia-smi
Wed Apr 12 02:47:12 2023
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 470.182.03 Driver Version: 470.182.03 CUDA Version: 11.4 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|===============================+======================+======================|
| 0 NVIDIA GeForce ... Off | 00000000:01:00.0 Off | N/A |
| N/A 50C P8 N/A / N/A | 9MiB / 1878MiB | 0% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
+-----------------------------------------------------------------------------+
出现这个就成功了。
Docker镜像下载与使用
从百度网盘下载Docker镜像(链接: https://pan.baidu.com/s/1qaPuKFydFvsBe2oDZLlU4A 密码: 81rc),而后导入镜像
等着下载吧,预计要24小时。。。
终于下载完了
下面开始导入这个镜像
sudo docker load -i xtdrone_1_3.rar
95129a5fe07e: Loading layer 65.52MB/65.52MB
f3f12f2889b0: Loading layer 17.53MB/17.53MB
2c768c2ad850: Loading layer 30.71MB/30.71MB
e82a7dc25c17: Loading layer 3.072kB/3.072kB
2863a6496c38: Loading layer 17.92kB/17.92kB
3918dccbaa08: Loading layer 47.43MB/47.43MB
9610ed45e688: Loading layer 1.656GB/1.656GB
385852a2f535: Loading layer 5.977GB/5.977GB
bea0f71cf4bc: Loading layer 2.585GB/2.585GB
Loaded image: xtdrone:1.3
这样表示导入成功了
查看当前镜像,发现有xtdrone:1.3
sudo docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
xtdrone 1.3 f54bca7d5ef3 8 months ago 10.3GB
nvidia/cuda 11.0.3-base-ubuntu20.04 8017f5c31b74 8 months ago 122MB
bestwu/wechat latest e0d1be7e13bf 2 years ago 865MB
导入只需一次,之后启动即可
注意,有些电脑需要在启动docker前输入xhost local:root,否则Gazebo无法启动。
xhost local:root
使用docker镜像
sudo docker run --runtime=nvidia --rm -it -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY -e XAUTHORITY -e NVIDIA_DRIVER_CAPABILITIES=all xtdrone:1.3
GAZEBO_PLUGIN_PATH :/root/PX4_Firmware/build/px4_sitl_default/build_gazebo
GAZEBO_MODEL_PATH :/root/PX4_Firmware//Tools/sitl_gazebo/models
LD_LIBRARY_PATH /root/catkin_ws/devel/lib:/opt/ros/melodic/lib:/usr/local/nvidia/lib:/usr/local/nvidia/lib64:/root/PX4_Firmware/build/px4_sitl_default/build_gazebo
root@0915cb8d4af4:/#
这些是镜像里的环境配置
退出容器的话,直接exit就行
exit
启动一个节点看是否整体配置成功
roslaunch px4 indoor1.launch
gazebo正常打开,出现无人机,说明前面配置的没有问题
不要开多个Docker容器,一是占用资源,二是ROS通信的配置更为复杂。Docker中实现划分窗格的方式有很多,推荐使用tmux
tmux的使用资源链接:http://www.ruanyifeng.com/blog/2019/10/tmux.html
首先进入docker按上面的方法,然后再通过tmux划分窗格,即可
下面测试在docker环境下,通过键盘控制无人机解锁,然后起飞,悬停的功能。
在一个窗格运行
roslaunch px4 indoor1.launch
注意,用ctrl+c关闭仿真进程,有可能没有把Gazebo的相关进程关干净,这样再启动仿真时可能会报错。如果出现这种情况,可以用killall -9 gzclient,killall -9 gzserver 这两个命令强行关闭gazebo所有进程
Gazebo启动后,在另一个窗格运行
cd ~/XTDrone/communication/
python multirotor_communication.py iris 0
root@4f62517fe7f4:~/XTDrone/communication# python multirotor_communication.py iris 0
iris_0: communication initialized
表示与0号iris建立通信成功
与0号iris建立通信后,在另一个窗格运行
cd ~/XTDrone/control/keyboard
python multirotor_keyboard_control.py iris 1 vel
下面即可通过键盘控制无人机
可以通过键盘控制1架iris的解锁/上锁(arm/disarm),修改飞行模式,飞机速度等
使用offboard模式起飞,这时起飞速度要大于0.3m/s才能起飞(即:upward velocity 需要大于0.3)。注意,飞机要先解锁才能起飞!飞到一定高度后可以切换为‘hover’模式悬停
按i把向上速度加到0.3以上,再按b切offboard模式,最后按t解锁。
无人机起飞成功!
Docker与宿主机建立ROS通信
在Docker里写代码与调试是比较麻烦的,因此我们建议Docker只是提供了仿真环境,所有仿真数据通过ROS话题与服务传输到宿主机,算法的开发测试还是在宿主机进行。
首先获取docker的ip地址
apt install net-tools
ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 148 bytes 214036 (214.0 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 97 bytes 7656 (7.6 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
通过查询,docker的ip是 172.17.0.2
将ip地址(示例为172.17.0.2) 写入docker的.bashrc(gedit有时可能会问题,因此使用vim)
vim ~/.bashrc
在source /opt/ros/melodic/setup.bash上一行加入
export ROS_MASTER_URI=http://localhost:11311
export ROS_IP=172.17.0.2 #根据ipconfig结果填写
同理修改宿主机的.bashrc,假设宿主机的ip地址为192.168.1.1
gedit ~/.bashrc
export ROS_MASTER_URI=http://172.17.0.2:11311#根据docker的ipconfig结果填写
export ROS_IP=192.168.1.1
检测通信是否成功
可以在docker中运行 indoor1.launch 文件
然后在宿主机上查看topic 列表
rostopic list
出现很多消息,则表示通信成功了
或者 查看 node的列表
rosnode list
宿主机安装 XTDrone 源码
git clone https://gitee.com/robin_shaun/XTDrone.git
正克隆到 ‘XTDrone’…
remote: Enumerating objects: 11446, done.
remote: Counting objects: 100% (3609/3609), done.
remote: Compressing objects: 100% (1765/1765), done.
remote: Total 11446 (delta 1795), reused 3461 (delta 1691), pack-reused 7837
接收对象中: 100% (11446/11446), 552.53 MiB | 2.12 MiB/s, 完成.
处理 delta 中: 100% (5027/5027), 完成.
正在更新文件: 100% (3874/3874), 完成.
cd XTDrone
git checkout 1_13_2
分支 ‘1_13_2’ 设置为跟踪来自 ‘origin’ 的远程分支 ‘1_13_2’。
切换到一个新分支 ‘1_13_2’
git submodule update --init --recursive
子模组 ‘coordination/task_assignment’(https://gitee.com/robin_shaun/multi-uav-task-assignment-benchmark)已对路径 ‘coordination/task_assignment’ 注册
子模组 ‘sensing/object_detection_and_tracking/darknet_ros’(https://gitee.com/robin_shaun/darknet_ros_yolov4)已对路径 ‘sensing/object_detection_and_tracking/darknet_ros’ 注册
正克隆到 ‘/home/jk-jone/XTDrone/coordination/task_assignment’…
正克隆到 ‘/home/jk-jone/XTDrone/sensing/object_detection_and_tracking/darknet_ros’…
子模组路径 ‘coordination/task_assignment’:检出 ‘57e251bbc6d889743c0ce3f5b4552a68c0fdc0e4’
子模组路径 ‘sensing/object_detection_and_tracking/darknet_ros’:检出 ‘3f380008e1190348d3846904503832f18bd30395’