
我一直觉得VINS-Fusion 这种项目跑通本身不难难的是在 Ubuntu20.04 上把它从头编译起来。VINS-Fusion 是港科大沈劭劼老师团队开源的多传感器融合框架核心解决的是单目/双目相机加 IMU 的状态估计问题在无人机、AR、自动驾驶、移动机器人这些领域都有人拿它当底层定位模块用。但网上大量教程还停留在 Ubuntu16.04 ROS Kinetic 时代照搬到 20.04 上大概率会翻车。这篇文章就把我从一个干净的 Ubuntu20.04 系统开始装 ROS Noetic、编译 VINS-Fusion、跑通 EuRoC 数据集的完整过程写出来包括我踩过的坑和最终可行的修复方案。如果你正准备折腾 SLAM或者需要在 20.04 上复现这个经典项目这篇应该能帮你省下好几个晚上。1. 为什么在Ubuntu20.04上运行VINS-Fusion会卡壳1.1 VINS-Fusion是什么能解决什么问题VINS-Fusion 是 VINS-Mono 的升级版全称是 Visual-Inertial Navigation System with Sensor Fusion基于优化方法做状态估计采用滑动窗口 边缘化的思路把视觉重投影误差和 IMU 预积分误差放在一起做紧耦合优化。与 VINS-Mono 最大的区别是支持更多传感器组合单目IMU、双目IMU、甚至双目IMUGPS 的融合。代码里还带有 pose graph 回环检测节点可以消除长时间运行累积的漂移所以在学术界和工业界的定位都很经典。在 20.04 上部署它很多新手不理解为什么会有这么多问题。其实不是 VINS-Fusion 代码本身有多复杂而是它最早面向的环境和现在主流的系统环境确实有代差。20.04 对应的是 ROS Noetic默认 Python 3.8默认依赖链全面切到 OpenCV 4而 VINS-Fusion 早期源码大量使用 OpenCV 2/3 时代的 API比如 CV_BGR2GRAY 之类的宏在 OpenCV 4 里全被删了。这一条就足以让第一次编译的人直接心态爆炸。1.2 部署难点ROS、OpenCV、Ceres三者的版本纠缠Ubuntu20.04 上跑 VINS-Fusion本质上是在处理三个组件的兼容性问题。组件Ubuntu18.04 / Melodic 时代Ubuntu20.04 / Noetic 时代默认 Python2.73.8默认 OpenCVOpenCV 3.2随 ROS 安装OpenCV 4.2系统 apt 源cv_bridge默认针对 OpenCV3 编译默认针对 OpenCV4 编译Ceres Solver低于 1.13 也行建议 1.14.0 以上主要坑点VINS 源码直接编译基本无碍OpenCV API 全面变更必须改源码ROS Noetic 的 cv_bridge 链接的是 OpenCV4VINS-Fusion 源码里用的却是 OpenCV3 风格接口导致编译时报出大量 CV_xxx was not declared 的错误。即使你把 OpenCV 相关的宏全部替换掉还可能出现 Ceres 版本过旧导致优化器接口不匹配或者 Eigen3 头文件路径不对导致找不到头文件。这三个问题叠在一起看起来就像一座山。我当时的第一建议是不要在 Ubuntu20.04 上硬扛老版本而是顺应新系统的环境。VINS-Fusion 的源码是活的改几个 API 兼容 OpenCV4 完全可行网上很多成功案例也证明了这条路能走通。下面我把完整的操作流程写出来。2. 环境准备从系统到ROS Noetic2.1 系统与硬件配置建议先说硬件。跑 EuRoC 数据集不用 GPUCPU 够用就行。我建议至少 8GB 内存、4 核 CPU磁盘预留 30GB 左右。因为编译 ROS 和相关依赖会占用不少空间数据集一个 bag 文件也要几个 GB。我自己最初在虚拟机上跑分配 8GB 内存和 4 个核心编译花了大概二十分钟跑 MH_01 数据集时 CPU 占用在 60%~80% 左右还算流畅。如果你用的是物理机体验会更好。需要注意的一点是如果你在虚拟机里跑默认网络配置可能会导致 rosdep 失败或者 apt 更新卡住。建议先把虚拟机网络切成桥接模式或者确保 NAT 模式下 DNS 能正常工作后面会说到怎么排查。2.2 安装ROS Noetic的完整流程Ubuntu20.04 对应的 ROS 版本是 Noetic注意不要装成 Melodic否则 apt 源里根本没有对应包。先设置软件源建议直接用国内镜像速度快很多。以清华源为例sudo sh -c echo deb https://mirrors.tuna.tsinghua.edu.cn/ros/ubuntu $(lsb_release -sc) main /etc/apt/sources.list.d/ros-latest.list然后添加 ROS 的 GPG 密钥。这一步在清华镜像上的路径是sudo apt install curl -y curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key | sudo apt-key add -如果你在访问 raw.githubusercontent.com 时网络不稳定可以试试把密钥下载后本地添加或者直接跳过密钥验证的做法不推荐。正常网络环境下这个命令没什么问题多试几次或者换个时间点基本能成功。接着更新并安装完整桌面版sudo apt update sudo apt install ros-noetic-desktop-full -y这一步会装很多东西包括 rviz、tf、gmapping、导航栈等SLAM 调试时都用得上。装完以后写环境变量echo source /opt/ros/noetic/setup.bash ~/.bashrc source ~/.bashrc然后安装基础依赖工具sudo apt install python3-rosdep python3-rosinstall python3-rosinstall-generator python3-wstool build-essential -y2.3 初始化rosdep的踩坑记录很多人在 rosdep 这一步卡住。rosdep 的职责是给当前工作空间的源码包自动解析并安装依赖项理论上非常重要。但在国内网络环境下rosdep init 和 rosdep update 经常访问失败。我遇到的情况是执行sudo rosdep init时提示无法下载 rosdistro 的配置文件或者执行rosdep update时卡在某个步骤超时。解决办法有两个方向第一个方向是检查网络本身。如果你用的是虚拟机先确认宿主机网络正常虚拟机内能 ping 通网关和 DNS。很多时候是 DNS 配置太旧把它改成 8.8.8.8 和 114.114.114.114 就能解决大部分超时问题。第二个方向是使用国内社区提供的 rosdepc 工具。这个工具本质上是把 rosdep 的源切到了国内镜像用法和 rosdep 差不多sudo pip3 install rosdepc sudo rosdepc init rosdepc update如果你后续编译的包不多也可以暂时跳过 rosdep。VINS-Fusion 的依赖其实就那几个用 apt 手动装好 OpenCV、Ceres、Eigen 之后不一定非要走 rosdep 这一步。我实际编译时就发现只要关键依赖都齐了rosdep 更像是一个锦上添花的检查器卡住时不用死磕。3. 编译VINS-Fusion前必须装好的三个依赖3.1 OpenCV与cv_bridge的版本纠缠OpenCV 是整个问题的核心。Ubuntu20.04 自带的 apt 源里 OpenCV 版本是 4.2。而 ROS Noetic 的 cv_bridge 默认链接的也是 OpenCV4所以在 20.04 上想把 cv_bridge 换成 OpenCV3 非常麻烦需要手动重新编译 cv_bridge而且很容易把 ROS 环境搞乱。我的建议是不要绕就顺着 OpenCV4 走改 VINS-Fusion 的源码去适配它。先确认当前系统里 OpenCV 的版本pkg-config --modversion opencv4如果你看到 4.2.0说明系统 OpenCV 就位。ROS 里 cv_bridge 链接的 OpenCV 版本可以这样查ldd /opt/ros/noetic/lib/libcv_bridge.so | grep opencv在 Ubuntu20.04 上基本都会显示 libopencv_core.so.4.2。确认这一点之后后面编译时如果报 OpenCV 相关错误就知道一定是源码兼容问题而不是环境问题。3.2 Eigen和Ceres Solver的安装与版本确认Eigen 是矩阵运算库VINS-Fusion 的整个优化过程都在和 Eigen 打交道。安装很简单sudo apt install libeigen3-dev -y但很多项目默认找的头文件路径是 /usr/include/Eigen而 apt 装的 Eigen 实际在 /usr/include/eigen3/Eigen 下面导致编译时报 Eigen/Core not found 之类的错误。解决办法是建一个软链接sudo ln -s /usr/include/eigen3/Eigen /usr/include/Eigen这个坑在编译 VINS-Fusion 时几乎必踩先建好省得后面烦躁。Ceres Solver 是 VINS-Fusion 用来做非线性优化的后端官方推荐 1.14.0 版本。Ubuntu20.04 的 apt 源里正好是 1.14.0直接装就行sudo apt install libceres-dev libgoogle-glog-dev libgflags-dev libsuitesparse-dev -y装完确认版本dpkg -l | grep libceres如果你看到版本号像 1.14.0-1ubuntu5那就没问题。如果系统里没有这个版本的包可以到 Ceres 官方仓库拉源码自己编译但依赖项比较多没必要20.04 的 apt 源已经照顾得很全面了。3.3 创建catkin工作空间并拉取源码依赖装好以后开始建工作空间。VINS-Fusion 官方推荐用 catkin 构建我习惯用 catkin_make简单直接mkdir -p ~/vins_ws/src cd ~/vins_ws/src git clone https://github.com/HKUST-Aerial-Robotics/VINS-Fusion.git cd ~/vins_ws catkin_make如果你之前没有安装 catkin 工具链执行sudo apt install ros-noetic-catkin -y装一下。第一次 catkin_make 之前最好先 source 一次环境变量source /opt/ros/noetic/setup.bash否则会提示找不到 catkin 或者 rosbuild。第一次编译大概率会失败别慌下面就是重点修复环节。4. 源码编译与OpenCV4兼容性修复4.1 第一次编译失败现场我第一次编译的时候报错信息刷了整整两屏。比较有代表性的错误是这样的error: CV_BGR2GRAY was not declared in this scope error: CV_RGB2GRAY was not declared in this scope error: CV_FONT_HERSHEY_SIMPLEX was not declared in this scope error: CV_LOAD_IMAGE_GRAYSCALE was not declared in this scope error: CV_CALIB_CB_ADAPTIVE_THRESH was not declared in this scope原因并不复杂OpenCV 从 3.x 开始就把大量常量定义从 C 风格的宏改成了枚举类型到 OpenCV4 之后更是直接删掉了旧宏。VINS-Fusion 源码写于 OpenCV3 时代自然全用的是旧写法。所以我们需要逐个把旧宏替换成 OpenCV4 的新接口。4.2 修改源码适配OpenCV4的完整方案需要修改的文件主要集中在三个包vins_estimator、pose_graph、camera_model。我用到的替换规则整理如下旧写法OpenCV2/3新写法OpenCV4CV_BGR2GRAYcv::COLOR_BGR2GRAYCV_RGB2GRAYcv::COLOR_RGB2GRAYCV_GRAY2RGBcv::COLOR_GRAY2RGBCV_GRAY2BGRcv::COLOR_GRAY2BGRCV_BGR2RGBcv::COLOR_BGR2RGBCV_RGB2BGRcv::COLOR_RGB2BGRCV_RGBA2RGBcv::COLOR_RGBA2RGBCV_BGR2HSVcv::COLOR_BGR2HSVCV_FONT_HERSHEY_SIMPLEXcv::FONT_HERSHEY_SIMPLEXCV_LOAD_IMAGE_GRAYSCALEcv::IMREAD_GRAYSCALECV_LOAD_IMAGE_COLORcv::IMREAD_COLORCV_CALIB_CB_ADAPTIVE_THRESHcv::CALIB_CB_ADAPTIVE_THRESHCV_CALIB_CB_NORMALIZE_IMAGEcv::CALIB_CB_NORMALIZE_IMAGECV_CALIB_CB_FILTER_QUADScv::CALIB_CB_FILTER_QUADSCV_CALIB_CB_FAST_CHECKcv::CALIB_CB_FAST_CHECKCV_WINDOW_NORMALcv::WINDOW_NORMALCV_FILLEDcv::FILLEDCV_AAcv::LINE_AA手动改的话文件比较多用 sed 批量替换比较高效。注意先备份原始源码cd ~/vins_ws/src/VINS-Fusion cp -r . ../VINS-Fusion_backup然后执行下面的替换命令一行一个规则或者直接写成脚本grep -rl CV_BGR2GRAY . --include*.cpp --include*.h | xargs sed -i s/CV_BGR2GRAY/cv::COLOR_BGR2GRAY/g grep -rl CV_RGB2GRAY . --include*.cpp --include*.h | xargs sed -i s/CV_RGB2GRAY/cv::COLOR_RGB2GRAY/g grep -rl CV_GRAY2RGB . --include*.cpp --include*.h | xargs sed -i s/CV_GRAY2RGB/cv::COLOR_GRAY2RGB/g grep -rl CV_GRAY2BGR . --include*.cpp --include*.h | xargs sed -i s/CV_GRAY2BGR/cv::COLOR_GRAY2BGR/g grep -rl CV_FONT_HERSHEY_SIMPLEX . --include*.cpp --include*.h | xargs sed -i s/CV_FONT_HERSHEY_SIMPLEX/cv::FONT_HERSHEY_SIMPLEX/g grep -rl CV_LOAD_IMAGE_GRAYSCALE . --include*.cpp --include*.h | xargs sed -i s/CV_LOAD_IMAGE_GRAYSCALE/cv::IMREAD_GRAYSCALE/g grep -rl CV_LOAD_IMAGE_COLOR . --include*.cpp --include*.h | xargs sed -i s/CV_LOAD_IMAGE_COLOR/cv::IMREAD_COLOR/g grep -rl CV_CALIB_CB_ADAPTIVE_THRESH . --include*.cpp --include*.h | xargs sed -i s/CV_CALIB_CB_ADAPTIVE_THRESH/cv::CALIB_CB_ADAPTIVE_THRESH/g grep -rl CV_CALIB_CB_NORMALIZE_IMAGE . --include*.cpp --include*.h | xargs sed -i s/CV_CALIB_CB_NORMALIZE_IMAGE/cv::CALIB_CB_NORMALIZE_IMAGE/g grep -rl CV_CALIB_CB_FILTER_QUADS . --include*.cpp --include*.h | xargs sed -i s/CV_CALIB_CB_FILTER_QUADS/cv::CALIB_CB_FILTER_QUADS/g grep -rl CV_CALIB_CB_FAST_CHECK . --include*.cpp --include*.h | xargs sed -i s/CV_CALIB_CB_FAST_CHECK/cv::CALIB_CB_FAST_CHECK/g grep -rl CV_WINDOW_NORMAL . --include*.cpp --include*.h | xargs sed -i s/CV_WINDOW_NORMAL/cv::WINDOW_NORMAL/g grep -rl CV_FILLED . --include*.cpp --include*.h | xargs sed -i s/CV_FILLED/cv::FILLED/g grep -rl CV_AA . --include*.cpp --include*.h | xargs sed -i s/CV_AA/cv::LINE_AA/g grep -rl CV_RGB2BGR . --include*.cpp --include*.h | xargs sed -i s/CV_RGB2BGR/cv::COLOR_RGB2BGR/g grep -rl CV_BGR2RGB . --include*.cpp --include*.h | xargs sed -i s/CV_BGR2RGB/cv::COLOR_BGR2RGB/g grep -rl CV_RGBA2RGB . --include*.cpp --include*.h | xargs sed -i s/CV_RGBA2RGB/cv::COLOR_RGBA2RGB/g grep -rl CV_BGR2HSV . --include*.cpp --include*.h | xargs sed -i s/CV_BGR2HSV/cv::COLOR_BGR2HSV/g替换完了以后还有两个额外的地方要手动检查。第一个是 camera_model 里的 CameraFactory.cpp有些代码会有CV_LOAD_IMAGE_UNCHANGED这种宏对应 OpenCV4 的新写法兼容也可以但为了保险起见直接改成cv::IMREAD_ANYCOLOR或者cv::IMREAD_UNCHANGED根据上下文判断。我倾向于改成cv::IMREAD_UNCHANGED因为它在读取相机标定图片时不会把灰度图强行转三通道。第二个是 visualization.cpp 里画箭头、画坐标系的代码可能用到cv::line、cv::circle、cv::putText这些函数。OpenCV4 下这些函数接口基本没变但如果出现CV_AA这种抗锯齿参数就需要替换成cv::LINE_AA上面的 sed 命令已经覆盖到了。还有一个常见的附带问题OpenCV4 的findChessboardCorners和 3.x 的返回值行为有细微差异。VINS-Fusion 依赖 camera_model 这个子模块做标定如果报 Assertion failed (npoints 0)多半是检测到的棋盘角点数量不对这种时候优先检查图片路径是否指向了正确的标定图片不要急着改代码。改完以后重新编译cd ~/vins_ws catkin_make如果一切顺利你会看到三个主要可执行文件生成的结果vins_estimator、pose_graph、camera_model 对应相关的库。我实际编译时中间还踩了一个小坑vins_estimator 编译到一半报 fatal error: ceres/ceres.h: No such file or directory。这是因为 Ceres 虽然装了但 catkin 环境没有自动把它加进 include path。解决方案是手动确认一下ls /usr/include/ceres/ceres.h如果这个文件存在说明库装到了不存在就得重新执行sudo apt install libceres-dev。4.3 编译通过后的检查清单编译完成不是终点我建议你按下面这个清单快速验证一下环境确认 ~/vins_ws/devel/lib/vins_estimator/ 下存在 vins_estimator 可执行文件。确认 ~/vins_ws/devel/lib/pose_graph/ 下存在 pose_graph 可执行文件。执行source ~/vins_ws/devel/setup.bash然后运行rospack find vins_estimator能输出路径说明 ROS 已经识别到工作空间。开一个终端启动roscore另一个终端尝试rosrun vins_estimator vins_estimator能起来不崩溃说明主程序没问题。到这个阶段最艰难的编译环节就过去了。5. 跑通Euroc数据集从launch到Rviz5.1 数据集下载与回放准备VINS-Fusion 官方文档推荐使用 EuRoC MAV 数据集。这个数据集是无人机在室内外场景采集的包含双目图像、IMU 数据和真值轨迹。MH_01 到 MH_05 是机械车间场景V1_01 到 V2_03 是房间场景。对新手来说我强烈建议先用 MH_01_easy 练手这个序列短、光照稳定跑起来不容易出问题。数据集下载下来是一个压缩包解压后里面是 bag 文件。回放前可以先检查一下 bag 里的话题名rosbag info MH_01_easy.bag正常情况下能看到 /cam0/image_raw、/cam1/image_raw、/imu0 这几个话题。VINS-Fusion 的 euroc.launch 默认订阅的就是这些名字所以不需要改配置直接播放就行。5.2 启动VINS-Fusion的三个节点跑通数据集的标准流程是开三个终端第一个终端启动 vins_estimator 估计器同时会打开 Rviz 可视化界面source /opt/ros/noetic/setup.bash source ~/vins_ws/devel/setup.bash roslaunch vins_estimator euroc.launch如果正常你会看到 Rviz 窗口出现并且终端打印 VINS Initializing... 之类的信息。第二个终端启动 pose_graph 节点。这个节点负责回环检测和全局位姿图优化如果只跑短序列不启动也可以但启动后能明显看到轨迹回环修正的过程source ~/vins_ws/devel/setup.bash roslaunch pose_graph pose_graph.launch第三个终端回放数据rosbag play MH_01_easy.bag注意播放时不要加-l循环参数否则时间戳会回到起点VINS-Fusion 对连续时间戳的约束比较敏感循环播放容易导致初始化混乱。我见过不少人加了-l以后轨迹在 Rviz 里反复跳变排查了半天才发现是循环播放惹的祸。正常回放时Rviz 里会逐渐画出相机的运动轨迹。等 bag 播放完轨迹会稳定在初始位置附近MH_01 由于本身是闭环场景你可以看到回环检测触发后终点轨迹被修正到起点附近。5.3 常见运行错误与排查速查表我把实际操作中容易遇到的现象、背后原因和处理办法整理成了一个速查表可以用 CTRLF 直接搜。现象可能原因解决办法编译时报 CV_xxx not declared源码未适配 OpenCV4按 4.2 节 sed 替换后重新编译编译时报 ceres/ceres.h not found未安装 Ceres 或路径不对sudo apt install libceres-dev重新 catkin_makeRviz 窗口空白无轨迹未启动 pose_graph或话题订阅不对检查 Rviz 左侧话题列表确认 /vins_estimator/path 有数据回放 bag 后没有任何 VIO 输出bag 话题名与配置不一致用 rosbag info 查看话题名修改 config 文件轨迹基本正确但误差大相机内参、外参或 IMU 噪声参数不对检查 config/euroc/euroc_config.yaml 参数是否与数据集对应跑 MH_05 时系统卡顿或崩溃长序列数据量大内存不足先跑 MH_01/MH_02或者减少 Rviz 显示的点云点数报错 No transform between /cam0 and /imu0TF 关系缺失确认 launch 文件里是否有必要的 TF 发布EuRoC 数据包里一般不发布 TF官方 launch 已处理这里特别展开说一下 TF 的问题。很多人在 Rviz 里看到轨迹在世界坐标系下但 IMU 坐标系和相机坐标系的变换关系显示不出来就觉得 VINS-Fusion 出 bug 了。实际上 VINS-Fusion 在估计器内部自己维护了 IMU 到相机的外参并不依赖外部 TF。你只需要在 Rviz 里把 Fixed Frame 设置为 world 或者 odom然后用 /vins_estimator 发布的 path 和 odometry 看效果就行。如果非要看到相机坐标轴在 Rviz 里显示需要在配置文件的body_T_cam参数正确的前提下再添加一个静态 TF broadcaster这个属于锦上添花新手可以先忽略。6. 进阶从跑通数据到接自己的传感器6.1 相机与IMU标定的几个关键点跑通 EuRoC 数据集之后大多数人的下一步是接自己的相机和 IMU。这一步的坑比编译还多。VINS-Fusion 是一个对参数非常敏感的算法相机内参、畸变系数、IMU 噪声密度、IMU 到相机的旋转和平移外参任何一个参数不对都会导致初始化发散或者轨迹漂移。我建议用 Kalibr 做相机和 IMU 的联合标定。VINS-Fusion 的配置文件里需要填写的核心参数包括IMU 噪声标准差gyr_noise、gyr_bias、acc_noise、acc_bias相机内参fx、fy、cx、cy 和畸变系数 k1、k2、p1、p2IMU 到相机的外参T_imu_cam 或者 body_T_cam标定采集数据时要保证运动激励充分。所谓充分不是让相机乱甩而是让三个轴的角速度和线速度都有明显变化同时避免纯旋转或者纯平移。我见过最典型的问题是采集数据时运动太温柔IMU 加速度激励不够导致标定结果里的 acc_noise 非常小VINS-Fusion 一跑起来轨迹就不稳定。在改配置的时候注意一个细节配置文件里imu_rate要和你实际 IMU 发布的频率一致cam0_rate要和图像频率一致。很多人在数据集上跑得挺好换成自己的传感器就崩就是频率填错。EuRoC 数据集里 IMU 是 200Hz相机是 20Hz如果你用自己的频率一定要把这两个值一起改掉。6.2 和ORB-SLAM3等SLAM方案部署的对比因为经常有人同时折腾 ORB-SLAM3 和 VINS-Fusion我这里多说一句。ORB-SLAM3 是基于特征点法的 VIO 方案VINS-Fusion 是基于直接法像素对齐 IMU 紧耦合的方案两者在精度、鲁棒性和计算资源消耗上的表现差异很大。部署层面的区别也很明显ORB-SLAM3 依赖 Pangolin、DBoW2、g2o 这些库而 VINS-Fusion 依赖 Ceres、Eigen、OpenCV两边几乎没有共同的第三方库依赖。如果你想在同一个 Ubuntu20.04 上同时部署这两个框架建议把它们放在不同的 catkin 工作空间或者至少在编译时分开。因为 ORB-SLAM3 编译时会修改一些 OpenCV 相关的编译选项如果和 VINS-Fusion 混用同一个 build 目录容易造成缓存冲突出现各种莫名其妙的链接错误。我吃过这个亏最后把 ~/vins_ws 和 ~/orbslam_ws 分开才消停。6.3 调参方向与性能监控跑通之后如果觉得精度或者资源占用不理想可以从下面几个方向入手图像分辨率EuRoC 的相机分辨率是 752x480实际运行不开源不会很占 CPU。如果自己的相机是 1080p建议先降到 640x480 再进 VINS-Fusion效果不会差太多但 CPU 占用能降一半。滑窗大小配置文件里的max_solver_size和keyframe_parallax可以控制滑窗大小和关键帧选取阈值。关键帧平移阈值调大系统会更轻快但精度会略降。IMU 和图像的同步VINS-Fusion 要求图像和 IMU 的时间戳尽量同步。如果两者时间偏差超过一个图像周期初始化阶段会非常不稳定建议在驱动层先做时间戳同步或者在数据预处理里用 Tic-Toc 函数打印耗时判断延迟。用 rqt_graph 可以看到节点之间的消息流用 rqt_plot 可以画出 IMU 角速度、加速度曲线这些工具对排查数据质量问题很有帮助。我在实际部署中还有一个体会跑通 EuRoC 数据集只是一只脚踏进了门真正考验 VINS-Fusion 的是你自己传感器数据的质量。如果标定做扎实了、时间戳对齐了、运动激励充分VINS-Fusion 在多数室内外环境下都能给你一个相当稳定的里程计输出。反过来如果标定数据随便采、参数随便填代码本身再稳也救不回来。建议把 4.2 节的源码改动和 5.3 节的排查表存下来以后再部署或者帮别人解决问题时能少走不少弯路。