从零到精通:Ubuntu 20.04下VINS-Mono与EUROC数据集实战全解析

当你第一次接触视觉惯性里程计(VIO)时,VINS-Mono无疑是最值得尝试的开源项目之一。作为香港科技大学空中机器人团队开发的经典算法,它不仅在学术界被广泛引用,也在工业界有着诸多应用。然而,对于刚入门SLAM的新手来说,从零开始配置环境到成功运行算法,往往会遇到各种"坑"——特别是那些令人头疼的依赖库版本冲突问题。

本文将带你一步步走过这个完整流程,特别针对Ubuntu 20.04系统环境,解决eigen、ceres-solver等库的版本兼容性问题。不同于简略的安装笔记,我们会深入每个步骤背后的原理,解释为什么需要特定版本,以及遇到问题时如何排查和解决。最终目标不仅是让你能成功运行VINS-Mono处理EUROC数据集,更要理解整个过程中的关键环节。

1. 环境准备与ROS安装

在开始之前,确保你有一台运行Ubuntu 20.04的电脑或虚拟机。这个版本被选作基础是因为它在长期支持(LTS)周期内,同时对新硬件的兼容性较好。我们将从最基础的ROS安装开始,这是整个项目的基石。

1.1 系统基础配置

首先更新系统软件包并安装一些基础工具:

sudo apt update && sudo apt upgrade -y
sudo apt install -y git cmake build-essential curl wget

接下来,我们需要设置正确的软件源。Ubuntu 20.04默认使用focal仓库,但为了确保ROS安装顺利,建议检查并确认你的/etc/apt/sources.list中包含以下行:

deb http://archive.ubuntu.com/ubuntu focal main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu focal-updates main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu focal-backports main restricted universe multiverse
deb http://security.ubuntu.com/ubuntu focal-security main restricted universe multiverse

1.2 ROS Noetic安装

VINS-Mono需要ROS作为消息传递和可视化框架。对于Ubuntu 20.04,我们使用ROS Noetic版本:

sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
sudo apt update
sudo apt install -y ros-noetic-desktop-full

安装完成后,初始化rosdep并设置环境变量:

sudo rosdep init
rosdep update
echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
source ~/.bashrc

注意:如果在rosdep initrosdep update步骤遇到网络问题,可以尝试使用国内镜像源,或者手动下载相关规则文件。

1.3 创建工作空间

创建一个独立的工作空间来存放VINS-Mono及其依赖:

mkdir -p ~/vins_ws/src
cd ~/vins_ws
catkin_make
echo "source ~/vins_ws/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc

这个工作空间将包含我们后续编译的所有ROS包,保持环境整洁有序。

2. 关键依赖库的安装与版本管理

依赖库的版本冲突是导致VINS-Mono编译失败的最常见原因。我们将详细讲解每个关键库的作用、所需版本以及安装方法。

2.1 Eigen库安装

Eigen是一个C++模板库,用于线性代数运算。VINS-Mono需要Eigen 3.3.4或更高版本,而Ubuntu 20.04默认仓库中的版本(3.3.7)通常可以工作,但为了确保最佳兼容性,我们推荐从源码安装特定版本:

cd ~
wget https://gitlab.com/libeigen/eigen/-/archive/3.3.9/eigen-3.3.9.tar.gz
tar -xzvf eigen-3.3.9.tar.gz
cd eigen-3.3.9
mkdir build && cd build
cmake ..
sudo make install

安装完成后,检查Eigen版本:

pkg-config --modversion eigen3

应该输出3.3.9。如果系统中有多个Eigen版本,可以通过设置环境变量来指定使用哪个版本:

export EIGEN3_INCLUDE_DIR=/usr/local/include/eigen3

2.2 Ceres-Solver安装

Ceres-Solver是一个非线性优化库,VINS-Mono使用它进行状态估计。我们需要1.14.0版本:

sudo apt install -y libgoogle-glog-dev libgflags-dev libatlas-base-dev libsuitesparse-dev
cd ~
wget https://github.com/ceres-solver/ceres-solver/archive/refs/tags/1.14.0.tar.gz
tar -xzvf 1.14.0.tar.gz
cd ceres-solver-1.14.0
mkdir build && cd build
cmake .. -DBUILD_TESTING=OFF -DBUILD_EXAMPLES=OFF
make -j$(nproc)
sudo make install

提示:如果在编译Ceres时遇到Eigen版本不兼容的错误,请确保已正确安装Eigen 3.3.9,并且系统PATH中不包含其他Eigen版本。

2.3 OpenCV安装

VINS-Mono需要OpenCV来处理图像数据。虽然Ubuntu 20.04默认提供OpenCV 4.2.0,但VINS-Mono对3.x和4.x版本都兼容。我们可以直接安装预编译版本:

sudo apt install -y libopencv-dev python3-opencv

验证安装:

pkg-config --modversion opencv

如果显示4.2.0或更高版本,就可以继续。如果需要特定版本,可以从源码编译,但通常预编译版本足够使用。

2.4 其他依赖

安装一些额外的工具和库:

sudo apt install -y python3-catkin-tools ros-noetic-cv-bridge ros-noetic-tf ros-noetic-message-filters ros-noetic-image-transport

这些包将在后续的ROS节点通信和图像处理中使用。

3. VINS-Mono源码获取与编译

现在我们已经准备好了所有依赖,可以开始获取和编译VINS-Mono源码了。

3.1 克隆源码

进入工作空间的src目录并克隆VINS-Mono仓库:

cd ~/vins_ws/src
git clone https://github.com/HKUST-Aerial-Robotics/VINS-Mono.git

VINS-Mono有几个重要的子模块,也需要初始化:

cd VINS-Mono
git submodule update --init --recursive

3.2 修改配置文件

在编译之前,我们需要根据我们的环境调整一些配置。打开~/vins_ws/src/VINS-Mono/config/euroc/euroc_config.yaml,修改以下内容:

# 修改结果保存路径
pose_graph_save_path: "/home/YOUR_USERNAME/vins_output/pose_graph"

# 确保相机参数与EUROC数据集匹配
image_width: 752
image_height: 480

YOUR_USERNAME替换为你的实际用户名,并确保vins_output目录存在:

mkdir -p ~/vins_output/pose_graph

3.3 编译VINS-Mono

返回工作空间根目录并开始编译:

cd ~/vins_ws
catkin_make -j$(nproc)

编译过程可能会花费一些时间,取决于你的硬件配置。如果一切顺利,你应该看到类似以下的输出:

[ 98%] Built target vins_node
[100%] Built target pose_graph_node

3.4 常见编译问题解决

如果在编译过程中遇到问题,以下是一些常见错误及其解决方案:

  1. Eigen版本冲突

    error: 'Eigen::aligned_allocator' has not been declared
    

    解决方案:确保已安装Eigen 3.3.9,并且系统优先使用这个版本。

  2. Ceres-Solver链接错误

    undefined reference to `ceres::Problem::Problem()'
    

    解决方案:检查Ceres安装是否正确,确保CMake能找到正确的Ceres版本。

  3. OpenCV相关错误

    fatal error: opencv2/core.hpp: No such file or directory
    

    解决方案:确认OpenCV安装正确,并设置正确的OpenCV_DIR环境变量。

如果遇到其他问题,可以尝试清理并重新编译:

cd ~/vins_ws
rm -rf build devel
catkin_make

4. 运行VINS-Mono处理EUROC数据集

现在我们已经成功编译了VINS-Mono,接下来将使用EUROC数据集进行测试。EUROC数据集包含来自微型飞行器(MAV)的视觉惯性数据,非常适合VINS-Mono这样的视觉惯性里程计算法。

4.1 获取EUROC数据集

从官方网站下载MH_04_difficult.bag文件:

mkdir -p ~/dataset
cd ~/dataset
wget http://robotics.ethz.ch/~asl-datasets/ijrr_euroc_mav_dataset/machine_hall/MH_04_difficult/MH_04_difficult.bag

如果下载速度慢,可以尝试寻找国内镜像或使用其他下载工具。

4.2 运行VINS-Mono

我们需要开启三个终端来运行VINS-Mono的不同组件。在每个新终端中,首先执行:

source ~/vins_ws/devel/setup.bash

终端1 - 运行VINS节点

roslaunch vins_estimator euroc.launch

这个节点负责处理图像和IMU数据,进行状态估计。

终端2 - 运行位姿图优化节点

roslaunch pose_graph euroc.launch

这个节点负责闭环检测和全局优化。

终端3 - 播放数据集

rosbag play ~/dataset/MH_04_difficult.bag

现在你应该能在RViz中看到算法实时估计的轨迹和地图点。

4.3 结果分析与可视化

VINS-Mono运行完成后,结果会保存在之前配置的~/vins_output/pose_graph目录中。可以使用以下工具进一步分析:

  1. 轨迹可视化

    evo_traj tum pose_graph.txt --plot
    
  2. 与真值比较: 首先发布数据集的真值轨迹:

    roslaunch benchmark_publisher publish.launch sequence_name:=MH_04_difficult
    

    然后使用evo工具比较:

    evo_ape tum groundtruth.txt pose_graph.txt -va --plot
    
  3. 查看节点关系

    rqt_graph
    

    这将显示ROS节点之间的连接关系。

4.4 性能调优与参数调整

为了获得更好的性能,可以调整VINS-Mono的参数。主要配置文件位于:

~/vins_ws/src/VINS-Mono/config/euroc/euroc_config.yaml

一些关键参数及其影响:

参数 默认值 说明
max_cnt 150 每帧图像提取的特征点最大数量
min_dist 30 特征点之间的最小像素距离
freq 10 估计器输出频率(Hz)
window_size 10 滑动窗口大小
keyframe_parallax 10.0 关键帧选择的最小视差(像素)

调整这些参数会影响算法的精度和计算效率,需要根据具体应用场景进行权衡。

5. 深入理解VINS-Mono架构与原理

成功运行VINS-Mono后,让我们深入了解一下它的核心架构和工作原理,这有助于更好地使用和修改这个系统。

5.1 系统架构概述

VINS-Mono主要由三个部分组成:

  1. 测量预处理

    • 图像特征检测与跟踪
    • IMU数据积分与预积分
    • 视觉-惯性数据时间对齐
  2. 滑动窗口优化

    • 基于滑动窗口的紧耦合视觉惯性联合优化
    • 边缘化处理维持固定计算量
  3. 位姿图优化

    • 闭环检测
    • 全局位姿图优化
    • 四自由度位姿图优化(忽略roll和pitch的可观性)

5.2 关键算法细节

特征提取与匹配: VINS-Mono使用KLT光流算法跟踪特征点,而不是传统的特征描述子匹配。这种方法计算效率更高,更适合实时系统。

// 特征跟踪核心代码片段
cv::calcOpticalFlowPyrLK(prev_img, cur_img, prev_pts, cur_pts, status, err, win_size, 3, term_criteria, 0, 0.001);

IMU预积分: 为了高效处理高频IMU数据,VINS-Mono使用预积分技术,将多个IMU测量累积为一个相对运动约束:

$$ \Delta R_{ij} = \prod_{k=i}^{j-1} Exp((\tilde{\omega}_k - b^g_k)\Delta t) $$

其中$\tilde{\omega}_k$是角速度测量,$b^g_k$是陀螺仪偏置。

紧耦合优化: VINS-Mono的优化问题可以表示为:

$$ \min_{\mathcal{X}} \left( \sum_{k\in\mathcal{B}} |r_{\mathcal{B}}(z_{k+1}^k,\mathcal{X})|{P{k+1}^k}^2 + \sum_{(l,j)\in\mathcal{C}} \rho(|r_{\mathcal{C}}(z_l^j,\mathcal{X})|_{P_l^j}^2) \right) $$

其中$\mathcal{B}$是IMU测量集合,$\mathcal{C}$是视觉测量集合,$\rho$是Huber鲁棒核函数。

5.3 性能优化技巧

  1. 多线程处理: VINS-Mono使用多线程架构,将前端跟踪和后端优化分离,提高系统吞吐量。

  2. 自适应特征提取: 根据场景复杂度动态调整提取的特征点数量,平衡精度和效率。

  3. 边缘化策略: 当滑动窗口满时,选择性地边缘化旧状态而不是简单地丢弃,保留历史信息。

6. 扩展应用与进阶方向

掌握了VINS-Mono的基本使用后,你可以进一步探索以下方向:

6.1 与其他SLAM系统集成

VINS-Mono可以与其他SLAM系统结合,例如:

  • 与激光SLAM融合:将VINS-Mono的估计结果作为激光SLAM的初始猜测
  • 多相机系统:扩展VINS-Mono支持多相机配置
  • 语义信息融合:加入语义分割结果提高闭环检测准确性

6.2 部署到实际平台

要将VINS-Mono部署到实际机器人或无人机上,需要考虑:

  1. 传感器标定

    • 相机-IMU外参标定
    • 相机内参标定
    • 时间同步校准
  2. 实时性优化

    • 代码层面的优化(如SIMD指令使用)
    • 降低图像分辨率或特征点数量
    • 调整滑动窗口大小
  3. 鲁棒性提升

    • 添加故障检测与恢复机制
    • 改进异常值剔除策略
    • 动态环境处理

6.3 算法改进与创新

基于VINS-Mono的开源实现,你可以尝试以下改进:

  1. 前端改进

    • 替换特征提取算法(如用深度学习特征代替传统特征)
    • 加入光流预测模块提高跟踪鲁棒性
  2. 后端改进

    • 尝试不同的优化框架(如GTSAM代替Ceres)
    • 加入边缘化先验的协方差调整策略
  3. 新功能添加

    • 集成GPS或其他全局传感器
    • 添加语义SLAM层
    • 实现动态物体检测与跟踪

7. 调试技巧与实用工具

在实际使用VINS-Mono过程中,掌握有效的调试方法能显著提高工作效率。

7.1 ROS调试工具

  1. rqt工具集

    rqt
    

    提供多种可视化插件,包括:

    • rqt_bag:查看bag文件内容
    • rqt_console:查看ROS日志
    • rqt_plot:绘制数据曲线
  2. rosbag工具

    • 录制特定话题:
      rosbag record -O my_recording.bag /topic1 /topic2
      
    • 检查bag文件内容:
      rosbag info my_recording.bag
      
  3. rostopic工具

    • 查看活跃话题:
      rostopic list
      
    • 查看话题消息:
      rostopic echo /topic_name
      

7.2 性能分析工具

  1. 时间测量: 使用ROS的ros::Time测量代码段执行时间:

    ros::Time start = ros::Time::now();
    // 你的代码
    ros::Time end = ros::Time::now();
    ROS_INFO("耗时: %f 秒", (end - start).toSec());
    
  2. CPU性能分析: 使用tophtop监控CPU使用情况:

    htop
    
  3. 内存分析: 使用valgrind检测内存泄漏:

    valgrind --leak-check=full ./your_program
    

7.3 可视化工具比较

下表对比了几种常用的SLAM可视化工具:

工具 优点 缺点 适用场景
RViz 与ROS深度集成,可实时显示 3D渲染能力有限 ROS系统实时可视化
Pangolin 轻量级,高性能3D渲染 需要额外集成 快速原型开发
MATLAB 强大的数据分析功能 非实时,需要导出数据 离线分析与论文绘图
PlotJuggler 时间序列数据可视化强大 3D显示能力弱 传感器数据分析

8. 容器化与可重复研究

为了确保实验可重复性和方便团队协作,可以考虑将整个VINS-Mono环境容器化。

8.1 Docker基础配置

创建Dockerfile:

FROM osrf/ros:noetic-desktop-full

# 安装系统依赖
RUN apt-get update && apt-get install -y \
    git cmake build-essential curl wget \
    libgoogle-glog-dev libgflags-dev \
    libatlas-base-dev libsuitesparse-dev \
    python3-catkin-tools \
    ros-noetic-cv-bridge ros-noetic-tf \
    ros-noetic-message-filters ros-noetic-image-transport

# 安装Eigen
WORKDIR /tmp
RUN wget https://gitlab.com/libeigen/eigen/-/archive/3.3.9/eigen-3.3.9.tar.gz && \
    tar -xzvf eigen-3.3.9.tar.gz && \
    cd eigen-3.3.9 && \
    mkdir build && cd build && \
    cmake .. && make install

# 安装Ceres
RUN wget https://github.com/ceres-solver/ceres-solver/archive/refs/tags/1.14.0.tar.gz && \
    tar -xzvf 1.14.0.tar.gz && \
    cd ceres-solver-1.14.0 && \
    mkdir build && cd build && \
    cmake .. -DBUILD_TESTING=OFF -DBUILD_EXAMPLES=OFF && \
    make -j$(nproc) && make install

# 创建工作空间
RUN mkdir -p /root/vins_ws/src
WORKDIR /root/vins_ws
RUN /bin/bash -c '. /opt/ros/noetic/setup.bash; catkin_make'

# 克隆VINS-Mono
WORKDIR /root/vins_ws/src
RUN git clone https://github.com/HKUST-Aerial-Robotics/VINS-Mono.git && \
    cd VINS-Mono && \
    git submodule update --init --recursive

# 编译VINS-Mono
WORKDIR /root/vins_ws
RUN /bin/bash -c '. /opt/ros/noetic/setup.bash; catkin_make'

# 设置环境变量
RUN echo "source /root/vins_ws/devel/setup.bash" >> /root/.bashrc

CMD ["bash"]

构建并运行容器:

docker build -t vins-mono .
docker run -it --net=host --env="DISPLAY" --volume="$HOME/.Xauthority:/root/.Xauthority:rw" vins-mono

8.2 数据集挂载

为了在容器中使用主机上的数据集,可以添加卷挂载:

docker run -it --net=host --env="DISPLAY" --volume="$HOME/.Xauthority:/root/.Xauthority:rw" --volume="$HOME/dataset:/root/dataset" vins-mono

8.3 容器化开发优势

  1. 环境一致性:确保团队成员使用完全相同的依赖版本
  2. 快速部署:新成员可以在几分钟内获得可工作的环境
  3. 隔离性:不影响主机系统配置
  4. 版本控制:Dockerfile可以与代码一起版本控制

9. 实际项目中的经验分享

在多个实际项目中应用VINS-Mono后,我总结了一些宝贵经验:

  1. 传感器选择至关重要

    • 相机:全局快门相机比卷帘快门更适合快速运动
    • IMU:消费级IMU(如BMI160)与工业级IMU(如ADIS16470)性能差异显著
  2. 标定质量决定上限

    • 相机-IMU外参标定误差应小于1cm和1°
    • 时间同步误差应小于1ms
    • 建议使用Kalibr工具进行标定
  3. 初始化阶段特别关键

    • 确保初始化时有足够的视差运动
    • 避免纯旋转运动初始化
    • 可以考虑手动初始化模式
  4. 光照变化处理

    • 在强烈光照变化场景下,特征跟踪容易失败
    • 可以尝试自适应阈值或直方图均衡化预处理
  5. 动态物体影响

    • 移动物体会引入错误特征匹配
    • 考虑添加简单的动态物体检测或使用鲁棒核函数
  6. 计算资源分配

    • 在资源受限平台上,可以降低图像分辨率或特征点数量
    • 调整滑动窗口大小平衡精度和效率
  7. 长期运行稳定性

    • 定期重置或重新初始化可以防止误差累积
    • 添加简单的场景识别模块有助于检测跟踪失败
  8. 多传感器融合

    • 加入轮速计或GPS可以抑制纯视觉惯性系统的漂移
    • 简单的启发式规则(如零速更新)也能显著改善性能
Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐