保姆级教程:在Ubuntu 20.04上从零跑通VINS-Mono与EUROC数据集(避坑eigen/ceres版本冲突)
从零到精通: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 init或rosdep 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 常见编译问题解决
如果在编译过程中遇到问题,以下是一些常见错误及其解决方案:
-
Eigen版本冲突:
error: 'Eigen::aligned_allocator' has not been declared解决方案:确保已安装Eigen 3.3.9,并且系统优先使用这个版本。
-
Ceres-Solver链接错误:
undefined reference to `ceres::Problem::Problem()'解决方案:检查Ceres安装是否正确,确保CMake能找到正确的Ceres版本。
-
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目录中。可以使用以下工具进一步分析:
-
轨迹可视化:
evo_traj tum pose_graph.txt --plot -
与真值比较: 首先发布数据集的真值轨迹:
roslaunch benchmark_publisher publish.launch sequence_name:=MH_04_difficult然后使用evo工具比较:
evo_ape tum groundtruth.txt pose_graph.txt -va --plot -
查看节点关系:
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主要由三个部分组成:
-
测量预处理:
- 图像特征检测与跟踪
- IMU数据积分与预积分
- 视觉-惯性数据时间对齐
-
滑动窗口优化:
- 基于滑动窗口的紧耦合视觉惯性联合优化
- 边缘化处理维持固定计算量
-
位姿图优化:
- 闭环检测
- 全局位姿图优化
- 四自由度位姿图优化(忽略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 性能优化技巧
-
多线程处理: VINS-Mono使用多线程架构,将前端跟踪和后端优化分离,提高系统吞吐量。
-
自适应特征提取: 根据场景复杂度动态调整提取的特征点数量,平衡精度和效率。
-
边缘化策略: 当滑动窗口满时,选择性地边缘化旧状态而不是简单地丢弃,保留历史信息。
6. 扩展应用与进阶方向
掌握了VINS-Mono的基本使用后,你可以进一步探索以下方向:
6.1 与其他SLAM系统集成
VINS-Mono可以与其他SLAM系统结合,例如:
- 与激光SLAM融合:将VINS-Mono的估计结果作为激光SLAM的初始猜测
- 多相机系统:扩展VINS-Mono支持多相机配置
- 语义信息融合:加入语义分割结果提高闭环检测准确性
6.2 部署到实际平台
要将VINS-Mono部署到实际机器人或无人机上,需要考虑:
-
传感器标定:
- 相机-IMU外参标定
- 相机内参标定
- 时间同步校准
-
实时性优化:
- 代码层面的优化(如SIMD指令使用)
- 降低图像分辨率或特征点数量
- 调整滑动窗口大小
-
鲁棒性提升:
- 添加故障检测与恢复机制
- 改进异常值剔除策略
- 动态环境处理
6.3 算法改进与创新
基于VINS-Mono的开源实现,你可以尝试以下改进:
-
前端改进:
- 替换特征提取算法(如用深度学习特征代替传统特征)
- 加入光流预测模块提高跟踪鲁棒性
-
后端改进:
- 尝试不同的优化框架(如GTSAM代替Ceres)
- 加入边缘化先验的协方差调整策略
-
新功能添加:
- 集成GPS或其他全局传感器
- 添加语义SLAM层
- 实现动态物体检测与跟踪
7. 调试技巧与实用工具
在实际使用VINS-Mono过程中,掌握有效的调试方法能显著提高工作效率。
7.1 ROS调试工具
-
rqt工具集:
rqt提供多种可视化插件,包括:
- rqt_bag:查看bag文件内容
- rqt_console:查看ROS日志
- rqt_plot:绘制数据曲线
-
rosbag工具:
- 录制特定话题:
rosbag record -O my_recording.bag /topic1 /topic2 - 检查bag文件内容:
rosbag info my_recording.bag
- 录制特定话题:
-
rostopic工具:
- 查看活跃话题:
rostopic list - 查看话题消息:
rostopic echo /topic_name
- 查看活跃话题:
7.2 性能分析工具
-
时间测量: 使用ROS的
ros::Time测量代码段执行时间:ros::Time start = ros::Time::now(); // 你的代码 ros::Time end = ros::Time::now(); ROS_INFO("耗时: %f 秒", (end - start).toSec()); -
CPU性能分析: 使用
top或htop监控CPU使用情况:htop -
内存分析: 使用
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 容器化开发优势
- 环境一致性:确保团队成员使用完全相同的依赖版本
- 快速部署:新成员可以在几分钟内获得可工作的环境
- 隔离性:不影响主机系统配置
- 版本控制:Dockerfile可以与代码一起版本控制
9. 实际项目中的经验分享
在多个实际项目中应用VINS-Mono后,我总结了一些宝贵经验:
-
传感器选择至关重要:
- 相机:全局快门相机比卷帘快门更适合快速运动
- IMU:消费级IMU(如BMI160)与工业级IMU(如ADIS16470)性能差异显著
-
标定质量决定上限:
- 相机-IMU外参标定误差应小于1cm和1°
- 时间同步误差应小于1ms
- 建议使用Kalibr工具进行标定
-
初始化阶段特别关键:
- 确保初始化时有足够的视差运动
- 避免纯旋转运动初始化
- 可以考虑手动初始化模式
-
光照变化处理:
- 在强烈光照变化场景下,特征跟踪容易失败
- 可以尝试自适应阈值或直方图均衡化预处理
-
动态物体影响:
- 移动物体会引入错误特征匹配
- 考虑添加简单的动态物体检测或使用鲁棒核函数
-
计算资源分配:
- 在资源受限平台上,可以降低图像分辨率或特征点数量
- 调整滑动窗口大小平衡精度和效率
-
长期运行稳定性:
- 定期重置或重新初始化可以防止误差累积
- 添加简单的场景识别模块有助于检测跟踪失败
-
多传感器融合:
- 加入轮速计或GPS可以抑制纯视觉惯性系统的漂移
- 简单的启发式规则(如零速更新)也能显著改善性能
更多推荐


所有评论(0)