先说一个我自己的判断:在Ubuntu20.04上把VINS-Mono、VINS-Fusion、GVINS这一整套跑通,算法层面的门槛真不高,真正的拦路虎是版本生态的错位。这三个框架几乎都是基于Ubuntu16.04/18.04和ROS Melodic开发的,而20.04默认带的是ROS Noetic、OpenCV 4.2、Ceres 1.18,这一堆版本差直接把很多人卡在编译阶段。这篇文章就是我从零到一在20.04上把三套系统都搞定、并顺手摸清各种坑的记录,适合正在部署VINS系列做毕设或科研项目的同学参考。
我会按“准备环境、跑通Mono、理解Fusion、啃下GVINS、通用排障”这个顺序展开。全程用我实际验证过的方案,凡是需要改代码的地方都会明确说,凡是容易踩坑的地方都会反复强调。你不需要同时看完再动手,跟着章节走就行。
1. VINS系列在Ubuntu20.04上折腾的根因:版本错位而不是算法难
1.1 三个框架各自的定位和发布时间线
VINS-Mono是香港科技大学2017年前后开源的视觉惯性里程计,核心思路是把单目相机和IMU做紧耦合,在滑动窗口里联合优化位姿和地图点。这个项目对单目SLAM的工程化推动很大,很多后来者都参考过它的因子图结构和边缘化实现。
VINS-Fusion是同一团队随后推出的多传感器融合框架,它把VINS-Mono里的核心估计器抽象出来,支持单目+IMU、双目+IMU、双目+IMU+GPS等多种配置,还加入了全局的位姿图优化。它的改动不只是在Mono上加几个传感器选项,而是把整个系统结构重新整理了一遍。
GVINS则更进一步,在VINS-Mono的基础上把GNSS原始观测值(伪距、多普勒、载波相位)作为新的因子塞进紧耦合框架,和视觉、惯性一起做联合优化。这意味着它不像VINS-Fusion那样仅仅接收一个GPS位置解算结果,而是要处理接收机输出的原始测量数据。GNSS观测量本身有噪声、有周跳、有粗差,处理起来比单纯吃一个坐标要复杂得多。
三套系统的时间线决定了它们的依赖习惯:Mono时期大家还在用OpenCV 3.2和Ceres 1.13,Fusion和GVINS虽然晚一些,但官方文档里也只验证过Melodic。Noetic出来之后,OpenCV从3跳到4,一大堆C++接口改名,这些问题你迟早要面对。
1.2 两个系统版本之间的具体差异
| 组件 | Ubuntu18.04 + Melodic | Ubuntu20.04 + Noetic |
|---|---|---|
| OpenCV | 3.2 | 4.2 |
| Eigen | 3.3.4 | 3.3.7 |
| Ceres | 1.13 / 1.14 | 1.18 |
| cv_bridge | 基于OpenCV 3.2构建 | 基于OpenCV 4.2构建 |
| Python绑定 | Python2 | Python3 |
直观来看,Eigen从3.3.4到3.3.7几乎无缝,Ceres从1.14到1.18的API也基本兼容,这三个版本里真正伤筋动骨的是OpenCV的大版本升级。OpenCV 4把很多C接口的头文件去掉了,一些枚举常量改了名,部分函数的参数类型也变了。VINS系列的代码里大量使用cv::imread、cv::solvePnP这类API,大部分在4.x下还能跑,但像CV_LOAD_IMAGE_GRAYSCALE、CV_RGB2GRAY这种旧宏就直接不存在了。
更隐蔽的是cv_bridge。ROS Noetic系统自带的cv_bridge链接的是系统OpenCV 4.2,如果你的工作空间里又单独编译了一个OpenCV 3.4.x装到/usr/local,并且某些第三方包的CMakeLists里find_package(OpenCV 3 REQUIRED),就可能出现一条编译链用OpenCV 3、另一条用OpenCV 4的情况。编译阶段通常不报错,一跑起来就段错误或者图像全是黑的,排查起来非常烦。
1.3 三种路线怎么选
我在20.04上试过三条路,结论很明确。
路线上比较省心的方案是直接修改VINS系列源码来适配Noetic自带的OpenCV 4.2。这是实际操作中最推荐的方式。缺点是要动几处代码,但对理解和排错都有帮助。
第二条路是装双版本OpenCV,让老代码用3.x,ROS这边继续用4.x。这个方案看起来美,实际维护成本极高,find_package的OpenCV_DIR很容易指错,你还要在源码编译时单独指定路径,时间成本和心智负担都不低。
第三条路是Docker。如果你只是想在某个固定数据集上复现结果,Docker很合适;但要接自己的相机、IMU、GNSS接收机,需要把USB设备和GUI都透传到容器里,折腾起来并不比改源码省事。所以我下面的所有内容都基于“直接用Noetic自带的OpenCV 4.2 + 顺手改几行代码”这条主路线。
2. 基础环境准备:Eigen、Ceres、OpenCV、cv_bridge的选型和验证
2.1 Eigen和Ceres:系统包能满足需求,别乱动
先说结论:Ubuntu20.04上Eigen和Ceres直接用apt安装即可。
sudo apt update sudo apt install libeigen3-dev libceres-devEigen是一个纯头文件库,20.04源里的版本是3.3.7,满足VINS-Mono、VINS-Fusion、GVINS三套代码的要求。Ceres的库文件稍晚一些,apt源里大概是1.18.0,也比老项目要求的1.13/1.14更安全。很多人有个误区,觉得源码编译的Ceres一定比apt的好,但其实这两个库只要版本匹配,源码版和系统版对VINS系列来说没有本质区别。稳定性优先级高于“看起来新”。
2.2 OpenCV版本统一是重中之重
在开始编译前,必须先确认系统OpenCV版本。
pkg-config --modversion opencv4如果返回4.2.0,说明Noetic自带版本正常。这里我建议不要为了适配老代码特意去安装OpenCV 3.x。原因是cv_bridge、image_pipeline这些ROS基础包都是针对OpenCV 4.2编译好的,一旦你安装了一个OpenCV 3.x并配置了OpenCV_DIR,整个工作空间会发生混乱。
统一版本的另一个隐蔽点是编译顺序。如果你在一个catkin工作空间里同时放VINS源码和vision_opencv源码,并且把cv_bridge也重新编译了一遍,那你要保证所有package的find_package(OpenCV ...)都指向同一个路径。最稳的方式是:不搞双版本,直接用系统的4.2,VINS代码里遇到旧API就改一行,见一个改一个。
2.3 cv_bridge是运行期崩溃的一个高发点
cv_bridge是ROS里图像消息和OpenCV Mat之间的转换层。Noetic自带cv_bridge是用OpenCV 4.2编译出来的,这和你的目标一致。很多同学编译VINS都能过,但运行阶段一旦图像话题进来就崩溃,十有八九是cv_bridge和某个自定义库链接的OpenCV版本不一致。
判断方法很简单:编译成功后,在运行前执行rosversion cv_bridge,然后看它的依赖:
ldd /opt/ros/noetic/lib/libcv_bridge.so | grep opencv正常情况下应该全部指向/usr/lib/x86_64-linux-gnu/下的OpenCV 4.2库文件。如果指向/usr/local/lib下某个3.x版本,说明你之前手工装过OpenCV 3,把系统链接顺序污染了。
解决办法是把/usr/local/lib下旧OpenCV的软链接清掉或者在CMakeLists里明确指定find_package(OpenCV 4.2 REQUIRED)。这个坑我在Fusion上踩过一次,症状很反直觉:编译顺利通过,跑起来两秒就死。
2.4 环境检查清单和验证命令
在开始编译任何VINS项目前,建议先跑一遍下面的检查:
| 检查项 | 命令 | 期望结果 |
|---|---|---|
| ROS版本 | rosversion -d | noetic |
| OpenCV版本 | pkg-config --modversion opencv4 | 4.2.0 |
| Eigen版本 | pkg-config --modversion eigen3 | 3.3.7 |
| Ceres版本 | dpkg -l | grep libceres | libceres-dev 已安装 |
| cv_bridge依赖 | ldd /opt/ros/noetic/lib/libcv_bridge.so | grep opencv | 全部指向4.2 |
这套检查花不了两分钟,但能避免后面编译失败后反复回头找原因。我见过不少人在GitHub issue里问编译报错,一查环境,问题根本不是编译,而是Ceres没装或者Eigen版本不对。
3. VINS-Mono完整编译与跑通官方EuRoC数据集
3.1 创建独立工作空间并处理ar_demo的依赖
VINS-Mono是老工程,我强烈建议给它单独建一个workspace,不要和Fusion、GVINS混在一起。原因是Mono和Fusion的package里有些节点重名,混在一个工作空间里会互相覆盖。
mkdir -p ~/vins_mono_ws/src cd ~/vins_mono_ws/src git clone https://github.com/HKUST-Aerial-Robotics/VINS-Mono.git cd ~/vins_mono_ws rosdep install --from-paths src --ignore-src -r -y这里有个官方README没提的坑:VINS-Mono仓库里包含AR_Demo模块,它依赖ar_track_alvar,如果没装这个包,catkin_make会在编译AR_Demo时报错。直接补上:
sudo apt install ros-noetic-ar-track-alvar如果你不想装这个包,也可以把src/VINS-Mono/AR_Demo这个目录移出工作空间,不影响主系统运行。但既然官方仓库整体编译更省心,我建议直接装依赖。
3.2 catkin_make中的OpenCV 4适配点
接下来编译:
cd ~/vins_mono_ws catkin_makeNoetic环境下大概率会报几个OpenCV相关错误。最常见的两个:
第一个是CV_LOAD_IMAGE_GRAYSCALE未定义。OpenCV 4里这个宏已经被删掉,改成cv::IMREAD_GRAYSCALE。报错位置通常在feature_tracker.cpp或camera_model相关文件里,直接把旧宏替换成新宏即可。
第二个是CV_RGB2GRAY未定义。类似的处理方式,替换成cv::COLOR_RGB2GRAY。有时候头文件里的枚举名还带着CV_前缀,但OpenCV 4已经把它们移到cv::命名空间下,编译报错后看提示改就行。
如果你的版本还遇到openCV2/xfeatures2d找不到的问题,先检查是不是装了libopencv-contrib-dev。VINS-Mono早期代码里有人用到SIFT特征,但官方分支其实不依赖contrib。实在遇到再装:
sudo apt install libopencv-contrib-dev3.3 官方E开源数据集下载和launch配置
VINS-Mono官方推荐使用EuRoC MAV数据集,典型文件是MH_01_easy.bag,直接搜“EuRoC MAV 数据集下载”就能找到,大小在几个GB左右。下载后不需要解压,rosbag play直接播放。
启动核心节点:
roslaunch vins_estimator euroc.launcheuroc.launch放在vins_estimator/launch目录下,它内部通过config_file参数指定了euroc_config.yaml。这个yaml文件里定义了两个最重要的订阅话题:imu_topic: "/imu0"和image_topic: "/cam0/image_raw"。EuRoC数据包里恰好也是这两个话题名,所以能直接对得上。
另一个重要的启动文件是rviz显示的配置。euroc.launch一般会顺带启动rviz,如果没有自动弹出来,手动执行:
rosrun rviz rviz -d ~/vins_mono_ws/src/VINS-Mono/vins_estimator/rviz/rviz_euroc.rviz3.4 播放bag后的初始化观察
启动完launch后再打开一个终端播放bag:
rosbag play MH_01_easy.bag正常情况下终端会先打印等待IMU和图像的信息,然后随着bag播放,VINS经过一个短暂的初始化过程后开始输出位姿,rviz里会逐渐画出绿色轨迹。这里有一个非常常见的误导性现象:如果你在bag播放后十几秒里看不到轨迹,不一定是系统卡了,很可能是IMU初始化还没完成。EuRoC数据集的IMU数据比图像数据早很多,而且初始化需要充分的加速度激励。
如果等到bag播放了一半还是没有轨迹,先检查终端的VINS日志。看到一个“Init finish”类似的输出,就说明初始化已经过了,这时候应该有轨迹。日志位置和字段在不同版本略有差异,但核心意思是检查是否进入了正常估计状态。
3.5 运行期故障:图像话题频率和分辨率不匹配
VINS-Mono的视觉前端对图像帧率并不敏感,但对分辨率很敏感。euroc_config.yaml里写明了image_width: 752和image_height: 480,如果你的bag是其他分辨率,或者你是从自己的相机采集数据,一定先把这两项改成实际分辨率。否则特征提取出来全部越界,追踪框显示一片红,位姿直接飞掉。
还要注意图像编码。EuRoC数据包里的图像通常是mono8,而VINS-Mono在getImage函数里读取时用CV_LOAD_IMAGE_GRAYSCALE,默认会转成灰度。如果是彩色图像且编码是bgr8,处理逻辑本身能扛得住,但会多一次颜色转换。最让人困惑的是某些数据集的图像topic里同时发布了compressed和原始图像两种消息,VINS订阅的是原始图像,播放bag时要确认rosbag play没有把图像转成压缩格式。
4. VINS-Fusion:多传感器配置下的使用差异
4.1 先搞清楚Fusion相对Mono改了什么
VINS-Fusion不是简单地把Mono功能搬个家,它的几个重要变化直接影响使用方式。
第一,传感器配置更灵活。Mono只做了单目+IMU,Fusion把双目+IMU和单目+IMU都整合进了同一个vins_node,通过yaml配置切换。第二,增加了全球坐标融合模块,也就是global_fusion节点。第三,回环检测模块被拆得更清晰,定位估计和位姿图优化可以分开跑。
需要特别说明的是VINS-Fusion里的GPS融合,它接收的GNSS数据通常是NavSatFix类型,也就是已经解算出的经纬高坐标,在优化里作为位置观测因子使用。这和GVINS直接消费GNSS原始观测值有本质区别。所以如果你手头只有普通的GPS模块输出NMEA,VINS-Fusion这条链路还走得通,GVINS那条路则基本走不通,后面我会展开讲。
4.2 编译VINS-Fusion最容易踩的坑:和Mono共用工作空间
给Fusion也单独建一个工作空间。不要图省事直接塞进Mono的src里重新catkin_make,因为两者都有pose_graph这类同名节点,放到一起后生成的devel目录会互相覆盖,最后跑起来到底是什么版本你都搞不清。
mkdir -p ~/vins_fusion_ws/src cd ~/vins_fusion_ws/src git clone https://github.com/HKUST-Aerial-Robotics/VINS-Fusion.git cd ~/vins_fusion_ws catkin_make编译时同样会遇到OpenCV 4的API问题,处理方式和Mono一致。特别提醒一下,VINS-Fusion里的global_fusion节点编译时会用到GeographicLib相关的坐标转换逻辑,如果报找不到库,先安装:
sudo apt install ros-noetic-geographic-msgs geographiclib-tools4.3 用EuRoC bag运行单目和双目两种模式
先跑单目+IMU模式:
roslaunch vins_fusion vins_rviz.launch rosrun vins_fusion vins_node ~/vins_fusion_ws/src/VINS-Fusion/config/euroc/euroc_mono_imu_config.yaml再开一个终端播放bag,你会在rviz里看到和Mono类似的单目轨迹。要注意的是,VINS-Fusion默认启动的vins_rviz.launch只负责加载rviz界面,真正做估计的是你手动rosrun出来的vins_node。
接着跑双目+IMU模式。先把单目节点Ctrl+C停掉,然后执行:
rosrun vins_fusion vins_node ~/vins_fusion_ws/src/VINS-Fusion/config/euroc/euroc_stereo_imu_config.yaml同时播放同一个bag,可以看到双目模式在尺度估计和初始化速度上明显更稳。因为VINS-Mono在纯单目下会有尺度不可观的问题,IMU的加速度计虽然能约束尺度,但初始化阶段需要足够的运动激励,双目则基本不存在这个问题。两条轨迹放在一起对比,能明显感受到双目对Z轴方向漂移的抑制更强。
4.4 GPS融合的正确打开方式
跑双目+GPS融合之前,注意VINS-Fusion里对应的GPS topic默认是/gps,消息类型是sensor_msgs/NavSatFix。如果你自己录数据,需要把GPS接收机的NMEA输出转成NavSatFix消息再发布。在EuRoC数据集里并没有GPS数据,所以想实际验证这一节得找VINS-Fusion官方提供的带GPS的公开bag,或者在仿真里自己生成一个。
启动顺序是这样的:先启动vins_node(读双目+IMU配置),再启动global_fusion节点:
rosrun global_fusion global_fusion_nodeglobal_fusion节点会在GPS数据可用时,把GPS经纬高转换成局部坐标系下的位置约束,和VINS输出做一个融合平滑。这里有个使用习惯问题:如果你的GPS初始坐标给得很偏(比如数据采集时接收机还没收敛),融合结果会在一段时间内明显偏离纯VINS轨迹。官方代码里做的是WGS84到局部ENU的转换,它依赖一个初始参考点,这个参考点如果错了,后面所有GPS观测都会出现系统性偏差。
所以你第一次验证时,最好播放官方提供的数据包,直接用原始配置跑通。等确认整条链路没问题,再换自己的数据去调初始坐标和噪声参数。
5. GVINS:加入GNSS原始观测后的部署复杂度
5.1 GVINS在黑箱里到底多加了什么
GVINS全称是“Tightly Coupled GNSS-Visual-Inertial Fusion”,研究重点是让机器人在GNSS信号不全的环境里依然能稳定定位。它的底层逻辑我非常喜欢:GNSS信号不是只有“收敛后的位置”这一种用法,伪距、多普勒、载波相位这些原始观测量都可以直接进入优化。
对比来看,VINS-Fusion的GPS融合更像是在一个装好位置结果的服务器上二次加工;GVINS则是把GNSS接收机当成另一个传感器,在紧耦合框架里和视觉残差、IMU预积分残差一起做非线性优化。这带来两个直观结果:第一,GNSS可见卫星数很少时,GVINS依然能利用单颗卫星的伪距约束,不会因为位置解算失败就完全失去全局信息;第二,它对接收机硬件有硬性要求,必须能输出原始观测量,普通NMEA接收机喂不进去。
5.2 环境准备里的特殊依赖:RTKLIB
GVINS的GNSS部分大量复用了RTKLIB的代码,所以编译前必须先编译安装RTKLIB。这个步骤是整个GVINS部署里最容易出问题的地方。
cd ~/gvins_ws/src git clone https://github.com/HKUST-Aerial-Robotics/GVINS.gitGVINS仓库里自带RTKLIB相关代码目录(具体位置以你clone下来的版本为准,通常在仓库根目录下),进入目录后按README里的方式编译安装:
mkdir build && cd build cmake .. sudo make install这里有两个注意事项。第一,不是make完就结束,必须sudo make install,把生成的库安装到系统路径,否则后面GVINS编译时找不到RTKLIB的头文件和动态库。第二,不要用apt源里的RTKLIB替代,版本和接口都可能对不上,GVINS通常需要特定版本,直接替换很可能让自定义消息的解析逻辑崩溃。
如果你clone下来的仓库没有带RTKLIB目录,就需要去RTKLIB官方仓库单独拉一份,再按GVINS的README指引把源码放到指定位置。这个依赖关系不同分支会有些许差异,以仓库文档为准。
5.3 编译GVINS时的Noetic兼容点
GVINS的代码相对新,对OpenCV 4的适配比Mono和Fusion好一点,但仍存在老API问题。编译命令仍然是标准的:
cd ~/gvins_ws catkin_make如果报错集中在camera_model相关文件,处理方式参照Mono里的同名文件改动。如果报错集中在gnss_obs相关包,多半是RTKLIB没装好或者自定义消息生成失败。gnss_obs包里定义了自己的ROS消息类型,比如observation和ephemeris,这些消息在catkin_make时自动生成。如果你改了消息定义,一定要重新catkin_make,并且播放bag的客户端也要同步编译,否则会出现“消息类型不匹配”的运行时错误。
GVINS编译时还有一个细节:它的部分节点依赖gnss_msg里的服务定义,在运行时如果找不到对应服务名,会先打印一段错误然后再启动。这个不对系统运行造成致命影响,但会让第一次跑的人误以为出了问题。正确做法是先不管,等所有节点起来后看整体状态。
5.4 用官方bag验证GVINS
GVINS官方提供了配套的数据包,里面不仅包含相机图像和IMU数据,还包含GNSS原始观测和卫星星历,话题名通常是/imu0、/cam0/image_raw、/gnss_obs、/gnss_eph这样的自定义类型。播放方式类似:
roslaunch gvins_estimator gvins.launch rosbag play gvins_dataset.bag如果launch文件名和你下载到的仓库不太一样,去gvins_estimator/launch目录下看一眼,用那个文件即可。第一次跑通的关键不是命令,而是确认bag里确实有GNSS原始观测话题。你可以用下面的命令检查:
rosbag info gvins_dataset.bag如果输出里只有/gps/fix这种NavSatFix话题,没有/gnss_obs和/gnss_eph,那这个bag是喂不进去GVINS的。
在rviz里,GVINS会显示相机轨迹,同时还有一个标志表示当前GNSS解算状态。判断系统是否正常,不要只看轨迹画没画出来,要看日志里卫星数是否大于0、伪距残差是否在合理范围。
5.5 自己录GNSS数据时的三条血泪教训
第一个教训是接收机必须有原始观测输出能力。普通几百块的GPS模块只有定位结果(NMEA语句),没有原始观测量。GVINS需要的是类似u-blox F9P、NovAtel、Septentrio这些支持输出原始观测数据的接收机。买硬件之前一定要确认规格参数里写了“raw observation output”。
第二个教训是时间同步问题。GNSS观测值和图像、IMU必须在一个统一的时间基准下,否则融合时会出现明显的时间偏差。最简单的方式是让所有传感器都用主机的ROS时间,并在录制bag时把GNSS接收机的PPS脉冲一起采集进来做校时。
第三个教训是初始位置。GVINS需要知道一个比较准确的初始经纬高,用来把卫星位置和接收机位置放入同一个坐标系。如果初始位置偏出几十米到几百米,伪距残差会从一开始就很大,优化很难收敛到真实轨迹。官方代码里通常会在launch参数或配置文件中设置初始LLA,你要根据实际测试场地修改。
6. 三套系统通用的故障排查思路和调优经验
6.1 编译期错误速查表
我把自己在20.04上踩过的、以及平时在技术社区里频繁看到的编译错误整理成了一张对照表。遇到问题时先对号入座,能少走非常多弯路。
| 报错关键词 | 大概率原因 | 处理方式 |
|---|---|---|
CV_LOAD_IMAGE_GRAYSCALE未声明 | OpenCV 4删除了旧宏 | 替换为cv::IMREAD_GRAYSCALE |
CV_RGB2GRAY未声明 | OpenCV 4枚举改名 | 替换为cv::COLOR_RGB2GRAY |
ar_track_alvar找不到 | VINS-Mono的AR_Demo依赖缺失 | sudo apt install ros-noetic-ar-track-alvar |
GeographicLib找不到 | VINS-Fusion的global_fusion依赖缺失 | 安装ros-noetic-geographic-msgs |
CeresConfig.cmake找不到 | Ceres没装或路径不对 | sudo apt install libceres-dev |
libopencv_core.so.3.2找不到 | 编译时找的OpenCV版本和运行时不一致 | 统一使用系统OpenCV 4.2 |
tf/transform_datatypes.h不存在 | 老代码里包含旧版tf头文件 | 把#include <tf/transform_datatypes.h>改成#include <tf2_geometry_msgs/tf2_geometry_msgs.h>并按需调整 |
cv_bridge版本冲突 | 手工安装的OpenCV污染了ROS库路径 | 检查ldd /opt/ros/noetic/lib/libcv_bridge.so,清理/usr/local下多余OpenCV |
6.2 运行期崩溃和卡顿的通用排查链路
运行期问题比编译期更耗时。先说rviz崩溃。如果在20.04里打开rviz看轨迹时界面突然闪退,先试试这个经典命令:
export QT_X11_NO_MITSHM=1 rviz这个问题常见于VMware虚拟机或部分远程桌面环境,VINS本身并没有崩溃。
再说“节点开着、bag在播放、rviz里就是没有轨迹”。按下面顺序排查:
- 确认话题名对得上。
rostopic list查看实际话题,对照yaml里的imu_topic、image_topic和launch里的config_file路径。 - 确认图像话题有数据。
rostopic hz /cam0/image_raw如果输出频率为0,说明bag没播放成功或话题名不对。 - 确认IMU话题有数据。
rostopic hz /imu0同理。 - 确认config文件里的相机内参和实际数据集一致。EuRoC不同序列的外参和内参基本一致,但如果你换到TUM或自采数据,内参矩阵必须重新标定。
- 查看VINS终端日志,有没有输出“wait for image”或“wait for imu”。如果一直卡在这一步,是数据没进来;如果过了这一步又没位姿,是初始化不成功或优化发散。
运行很卡的问题则要看具体瓶颈。常用来定位的程序是htop。如果某个CPU核心已经打满,而其他核心闲着,说明系统并行性没利用起来;VINS的滑动窗口优化主要在单线程里跑,打满是正常的,但如果是连续打满几秒且轨迹还完全不动,可能是bag播放速度太快,可以用慢速播放:
rosbag play --rate=0.5 MH_01_easy.bag6.3 调参顺序:先跑通再谈性能
我见过太多人一上来就改process_frequency、调min_parallel_angle、改max_solver_time,最后连系统能不能跑通都没确认,直接在错误的方向上调参。正确顺序永远是:先用官方数据集和官方配置跑通,再改一个参数观察效果,最后才考虑性能优化。
几个关键的配置项值得记住。LOOP_CLOSURE控制回环检测,如果数据集里没有回环场景,开不开区别不大,但开着会增加计算量。ESTIMATE_EXTRINSIC控制外参是否在线估计,如果你用的是标定好的数据,建议设为0直接固定外参,否则初始化阶段会多出几个自由度,容易导致漂移。process_frequency控制状态估计的频率,降频能显著降低CPU占用,但轨迹实时性会变差。
如果你要在自己的机器人上跑实时系统,我建议先录一段包含充分运动激励的数据,离线跑通后再上真机。这样可以把算法问题和传感器硬件问题分开,省掉很多同时排查多个变量的时间。
最后再分享一个我实际使用中的习惯:三套系统的不同版本会带来不同的消息格式和launch行为,所以我会把每个workspace的devel/setup.bash路径写到自己的~/.bashrc注释里,用哪个系统就source哪个。不要在一个终端里同时source两个workspace,否则节点跑起来到底是哪套代码,可能连自己都分辨不清。先按我说的把Mono跑通,再对比Fusion,最后啃GVINS,这套顺序能让你对VINS系列的理解形成一个完整的链路。