目前市面上许多教育版无人机的机载计算平台采用 NVIDIA Jetson Xavier NX。然而,NX 的 CPU 性能相对有限,在运行 VINS 算法时常出现 CPU 占用率过高甚至系统死机的情况。幸运的是,英伟达的开发板在 GPU 性能方面表现出色,因此可以通过部署 VINS-Fusion 的 GPU 加速版本,显著提升算法的运行速度与系统稳定性。

参考文档

本次共参考了3个CSDN上的教程,已有的教程不够完整,但是又能形成互补,所以本贴综合已有的教程,形成一个完善的教程。
1. NVIDIA Jetson Xavier NX开发板部署VINS-fusion-GPU
(作者:阿栋阿栋。主要参考这篇教程,步骤最清晰,但是缺少验证是否安装成功的步骤)

2. jeston xavier nx跑通vins-fusion GPU定位的ego_planner
(作者:什么时候能造钢铁侠啊。步骤有点多,细节不够具体)

3. Jetson Orin NX 开发指南(6): VINS-Fusion-gpu 的编译和运行
(作者:想要个小姑娘。是Orin NX与ubuntu20.04的教程,有些版本与18.04的不一样)

一、前提条件

开发板为NVIDIA Jetson Xavier NX,系统为ubuntu18.04,相机为realsense D435i。已经安装好了ROS、CUDA。

二、安装opencv GPU版本

关于 OpenCV 的安装需要特别谨慎,不建议频繁删除以前的库,因为多个项目使用的版本可能不同。建议做法:

  • 将常用的稳定版本安装在 /usr/local 下;

  • 将实验性或特定项目使用的版本安装在用户目录(如 ~/opencv-3.4.1)下,避免文件冲突。

我的 NX 开发板已经在 /usr/local 下安装了 OpenCV 3.3 版本。这次安装的 OpenCV 3.4 版本将安装在 home 目录下,以免不同版本文件起冲突。

(1)安装依赖(整理成一行的命令如下,可直接复制使用)

sudo apt-get install -y cmake libavcodec-dev libavformat-dev libavutil-dev libglew-dev libgtk2.0-dev libgtk-3-dev libjpeg-dev libpng-dev libpostproc-dev libswscale-dev libtbb-dev libtiff5-dev libv4l-dev libxvidcore-dev libx264-dev qt5-default zlib1g-dev libgl1 libglvnd-dev pkg-config libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev mesa-utils

(2)下载opencv源码
由于开发板通常无法直接访问 GitHub,建议先在笔记本电脑上下载压缩包,然后使用 scp 命令传输至开发板。

  1. 下载 OpenCV 3.4.1 源码包
  2. 使用 scp 命令传输到 NX 开发板(示例如下):
# scp .\压缩包名字 机载电脑的用户名@机载电脑的IP地址:机载电脑的某个目录
scp .\opencv-3.4.1.zip nvidia@172.31.6.110:~

传输完成后,在开发板的 home 目录中解压该压缩包,得到 opencv-3.4.1 文件夹。

(3)编译GPU版本的opencv
假设源码路径为 /home/nvidia/opencv-3.4.1,编译步骤如下:

cd ~/opencv-3.4.1
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE \
      -D CMAKE_INSTALL_PREFIX=/usr/local \  # 设置安装路径。这里可任意,因为不执行 make install。
      -D WITH_CUDA=ON \
      -D CUDA_ARCH_BIN=7.2 \                # NX/AGX 选 7.2,Nano/TX2 选 6.2
      -D CUDA_ARCH_PTX="" \
      -D ENABLE_FAST_MATH=ON \
      -D CUDA_FAST_MATH=ON \
      -D WITH_CUBLAS=ON \
      -D WITH_LIBV4L=ON \
      -D WITH_GSTREAMER=ON \
      -D WITH_GSTREAMER_0_10=OFF \
      -D WITH_QT=ON \
      -D WITH_OPENGL=ON \
      -D CUDA_NVCC_FLAGS="--expt-relaxed-constexpr" \
      -D WITH_TBB=ON \
      ../
make -j$(nproc)

注意:

  • 粘贴 cmake 命令时,请去掉行尾的 \ 符号,或直接将命令写为一行执行。
  • 若板载资源有限,可去掉 -j$(nproc) 改为 make,以减少内存占用。
  • 之所以安装的是 GPU 版 OpenCV,关键在于 cmake 阶段设置了 WITH_CUDA=ON,并且系统存在 CUDA 工具链。

(4)常见编译错误及解决方案
错误信息:

error Please include the appropriate gl headers before including cuda_gl_interop.h

解决措施: 编辑文件 /usr/local/cuda/include/cuda_gl_interop.h,修改第 62~68 行为以下内容:

sudo vim /usr/local/cuda/include/cuda_gl_interop.h

修改后:

//#if defined(__arm__) || defined(__aarch64__)
//#ifndef GL_VERSION
//#error Please include the appropriate gl headers before including cuda_gl_interop.h
//#endif
//#else
 
 #include <GL/gl.h>

//#endif

保存退出后重新执行 make。

(5)验证 OpenCV 的GPU版本是否编译成功
进入 build 目录后执行:

cd ~/opencv-3.4.1/build
bin/opencv_version --verbose

如果输出中包含类似以下内容:

Use Cuda: YES (ver 11.4)
CUDA Device: NVIDIA Xavier (Arch 7.2)

则说明 OpenCV 已成功编译并启用了 CUDA 支持。

三、安装对应的CV-Bridge

cv_bridge 是 ROS 中连接 ROS 图像消息 (sensor_msgs/Image)OpenCV 图像格式 (cv::Mat) 的桥梁。

如果你的 OpenCV 是自己编译的 GPU 版本,那么系统自带的 cv_bridge 很可能是针对旧版或 CPU 版编译的,会导致版本冲突或找不到头文件,因此需要重新编译一份对应版本的 cv_bridge。

(1)下载源码
进入 vision_opencv 官方仓库,选择与自己 ROS 版本对应的分支。例如:

  • ROS Melodic → 选择 melodic 分支
  • ROS Noetic → 选择 noetic 分支

由于本教程使用 Ubuntu 18.04 + ROS Melodic,因此选择 melodic 分支。
在这里插入图片描述
你可以直接在电脑端下载该分支的 ZIP 压缩包,或使用命令行:

git clone -b melodic https://github.com/ros-perception/vision_opencv.git

如果开发板无法连接 GitHub,可以先在笔记本上下载压缩包,然后使用 scp 命令传输到机载电脑:

scp ./vision_opencv-melodic.zip nvidia@172.31.6.110:~

传输后解压为 vision_opencv 文件夹:

unzip vision_opencv-melodic.zip
mv vision_opencv-melodic vision_opencv

(2)修改为自己刚刚安装的opencv路径
由于系统内可能有多个版本的 OpenCV,需要手动指定刚刚编译好的 GPU 版本路径。

编辑 cv_bridge 功能包的 CMakeLists.txt 文件:

gedit vision_opencv/cv_bridge/CMakeLists.txt

find_package(OpenCV 3 REQUIRED) 之前,添加以下一行:

set(OpenCV_DIR "/home/nvidia/opencv-3.4.1/build")

注意事项:

  • 路径要与你前面编译的 OpenCV 实际位置一致;

  • 不要遗漏 /build 目录,否则会找不到 OpenCVConfig.cmake 文件。

(3)编译源码
进入 cv_bridge 目录并执行编译:

cd vision_opencv/cv_bridge
mkdir build
cd build
cmake ..
make -j$(nproc)
sudo make install

(4)验证是否安装成功

输入

rospack find cv_bridge

得到

/opt/ros/melodic/share/cv_bridge

四、编译安装Vin-fusion GPU

(1)下载源码
新建一个工作空间,例如vins_gpu_ws,进入工作空间并获取 GPU 版本的 VINS-Fusion 源码:

cd ~/vins_gpu_ws/src 
git clone https://github.com/pjrambo/VINS-Fusion-gpu

如果开发板网络不稳定,也可以在本地电脑上下载后用 scp 传输到板子上,方式与之前安装 OpenCV 时相同。

(2)修改CMakeLists.txt—— 指定 GPU 版 OpenCV 与自编译 CV-Bridge

由于 ROS 默认会链接系统版本的 OpenCV 和 cv_bridge,而我们前面已经编译了新的 GPU 版 OpenCV 自定义 cv_bridge,因此需要在相关模块的 CMakeLists.txt 中显式指定路径。

分别修改以下三个文件:
1、第一处,修改camera_models的CMakeLists文件,改一行:

gedit VINS-Fusion-gpu/camera_models/CMakeLists.txt

在最前面添加:

set(OpenCV_DIR "/home/nvidia/opencv/opencv-3.4.1/build")

如图所示
在这里插入图片描述

2、第二处,修改loop_fusion的CMakeLists文件,改三行:

gedit VINS-Fusion-gpu/loop_fusion/CMakeLists.txt

在最前面添加:

set(OpenCV_DIR "/home/nvidia/opencv/opencv-3.4.1/build")
set(cv_bridge_DIR /usr/local/share/cv_bridge/cmake)  

并且把原工程的opencv路径改成自己的,原github工程写的路径是include(/home/dji/opencv/build/OpenCVConfig.cmake),如图所示:
在这里插入图片描述

3、第三处,修改vins_estimator的CMakeLists文件,改三行:

gedit VINS-Fusion-gpu/vins_estimator/CMakeLists.txt

在最前面添加:

set(OpenCV_DIR "/home/nvidia/opencv/opencv-3.4.1/build")
set(cv_bridge_DIR /usr/local/share/cv_bridge/cmake)  

并且把原工程的opencv路径改成自己的,原github工程写的路径是include(/home/dji/opencv/build/OpenCVConfig.cmake),如图所示:
在这里插入图片描述

提示:
这样做的意义是让编译系统始终使用你手动编译的 GPU 版 OpenCV 和自定义 cv_bridge。

(3)编译源码

进入工作空间并开始编译:

cd ~/vins_gpu_ws
# 由于其他库会依赖camera_models,所以用catkin build编译得先单独编译该模块
catkin build camera_models
catkin build

(4)可能遇到的报错及解决方案

报错:

double free or corruption (out)

问题原因:
经调试发现,该问题通常出现在使用 cv::FileStorage fsSettings 读取 YAML 文件中矩阵类型数据时。
这往往是因为系统中混用了不同版本的 OpenCV(例如部分模块仍然调用系统旧版库),导致内存分配不一致。

解决措施:
修改VINS-Fusion/vins_estimator/src/estimator/parameters.cpp文件,该文件里面会使用fsSettings["body_T_cam0"]fsSettings["body_T_cam1"]从yaml文件读取数值,赋值给变量,这里会出现问题,因此都修改为手动输入矩阵参数。

需要修改143行和178行,143行修改前:
在这里插入图片描述
143行修改后:
在这里插入图片描述
178行修改前:
在这里插入图片描述
178行修改后:
在这里插入图片描述

注意: 总而言之,手动输入矩阵数据,替代从 YAML 文件读取。这两个矩阵是相机的外参,在realsense_stereo_imu_config.yaml中有写,假如没有的话,先看第五章的(1)配置 D435i相机文件。例如,以下是我的相机外参数据:

在这里插入图片描述

五、验证是否安装成功

(1)配置 D435i相机文件
创建/home/nvidia/vins_gpu_ws/src/VINS-Fusion-gpu/config/realsense_d435i/文件夹,用于存储三个yaml文件。
在这里插入图片描述
这三个yaml文件来源于VINS-Fuison,可以直接从本地直接复制过来。

在这里插入图片描述
如果本地没有VINS-Fusion文件夹,可以去 VINS-Fusion 的 github 网站上查看对应 realsense d435i 的配置文件。VINS-Fusion官方仓库
在这里插入图片描述

回到我们的vins_gpu_ws工作空间,粘贴上述三个文件之后,需要有一点改动。

  • 其中 left.yaml 和right.yaml 文件配置相对于 VINS-Fuison 未做修改。
  • 在realsense_stereo_imu_config.yaml 文件中添加两行:
use_gpu: 1
use_gpu_acc_flow: 1

在这里插入图片描述

当然,其他相机的配置文件设置和上面的内容是一致的,因为这是 VINS-Fuion 源码中需要读取的参数的内容和格式,为了达到更高的精度,往往需要对相机进行标定,标定完成后修改配置文件中的内外参和时延,从而提高估计精度,标定的方法可以参考

d435i 相机和imu标定_d435i imu标定_想要个小姑娘的博客-CSDN博客

当然,在此标定可以在后面熟悉 VINS-Fusion 的使用之后在进行,由于我们这里只是介绍如何使用 VINS-Fusion-gpu 测试真实数据,因此标定可以不进行(也不推荐现在进行,很费时间)。

(2)通过 launch 文件运行 realsense 相机
首先必须安装 librealsense 和 realsense-ros,已经安装的可以忽略。参考以下两篇文章(分别针对 Ubuntu 系统和 Jetson 系列的系统)

1. Ubuntu 20.04 配置 realsense_ubuntu安装realsense2-CSDN博客
2. Jetson Orin NX 开发指南(4): 安装 CUDA 和 Realsense_想要个小姑娘的博客-CSDN博客

安装完成后确保能够正常使用 ROS 启动 realsense 相机,并能够正确读取到相机数据和 IMU 数据,配置方式同样参考上面两篇文章。

接下来在 ~/vins_gpu_ws/src/vins-fusion-gpu/src/VINS-Fusion-gpu/vins_estimator/launch/ 路径下创建一个 launch 文件

cd ~/vins_gpu_ws/src/vins-fusion-gpu/src/VINS-Fusion-gpu/vins_estimator/launch/
touch realsense_d435i.launch

在 launch 文件中输入以下内容

<launch>
    <node name="vins_estimator" pkg="vins" type="vins_node" output="screen" args="$(find vins)/../config/realsense_d435i/realsense_stereo_imu_config.yaml" />
    <node name="loop_fusion" pkg="loop_fusion" type="loop_fusion_node" output="screen" args="$(find vins)/../config/realsense_d435i/realsense_stereo_imu_config.yaml" />
</launch>

这样 launch 文件就配置完成了。

接下来创建三个终端,并 source 一下vins_gpu_ws工作空间(或者在~/.bashrc文件中激活,就不用每次都source了)

第一个终端输入

roslaunch vins vins_rviz.launch

第二个终端输入

roslaunch vins realsense_d435i.launch

第三个终端输入

roslaunch realsense2_camera rs_camera.launch

拿着无人机绕场第一圈,查看rviz轨迹:
在这里插入图片描述

最后使用jtop命令检查,是否真的启用了GPU资源。
在这里插入图片描述

可以看到正在占用 GPU 资源,也就是说 VINS-Fusion-gpu 成功运行了。

此外,需要注意 VINS-Fusion-gpu 的特征追踪图片的显示方式与 VINS-Fusion 有所不同,VINS-Fusion-gpu 是将特征追踪图像单独显示出来的,而在 VINS-Fusion 中,特征追踪图像是集成在 rviz 中显示的,如果需要将特征追踪的图像显示在 rviz 中,可以参考下文:

Ubuntu 20.04 配置 VINS-Fusion-gpu + OpenCV 4.6.0-CSDN博客

至此,VINS-Fusion-gpu 的配置工作完成了。

更多推荐