1. 项目缘起与整体方案拆解
1.1 这套组合到底在解决什么问题
手里有一台 D435i,想跑 VINS-mono 做视觉惯性里程计,同时还要用 Kalibr 做标定——这个需求在机器人、无人机、AR/VR 圈子里非常典型。D435i 本身自带 IMU 和双目红外相机,硬件上天然适合做 VIO(视觉惯性里程计),但原厂出厂标定参数精度有限,直接拿来跑 VINS-mono 往往会出现轨迹漂移、尺度跳变、初始化失败等问题。所以核心诉求就两个:一是让 VINS-mono 在 D435i 上稳定跑起来,二是用 Kalibr 做一套高精度的相机-IMU 联合标定,把外参和时间偏移校准到位。
这套方案适合谁?适合正在做 SLAM 算法验证的开发者、做无人机室内定位的工程师、以及需要高精度位姿估计的机器人方向同学。如果你刚接触 VIO,建议先把 VINS-mono 的论文和 Kalibr 的 wiki 过一遍,再动手操作,否则遇到报错会无从下手。
1.2 为什么选 VINS-mono 而不是其他方案
VINS-mono 是香港科技大学沈劭劼团队开源的一套单目/双目视觉惯性紧耦合里程计,它的优势在于:
- 紧耦合:视觉和 IMU 在优化框架里联合优化,不是松耦合的简单叠加,精度更高。
- 在线估计外参和时间偏移:即使标定不够完美,它也能在线优化一部分参数。
- 回环检测:支持重定位和全局优化,长时间运行不会累积太大漂移。
- 社区成熟:遇到问题基本都能搜到解决方案。
相比之下,ORB-SLAM3 虽然也支持 IMU,但配置更复杂;VINS-Fusion 支持更多传感器组合,但对 D435i 这种消费级设备来说,VINS-mono 已经够用。选 VINS-mono 的核心逻辑是:在精度、易用性和社区支持之间取平衡。
1.3 为什么标定必须用 Kalibr
很多人会问:D435i 出厂不是有标定参数吗?为什么还要自己标?原因有三:
第一,出厂标定是在特定温度、特定距离下做的,实际使用环境不同,参数会漂。第二,VINS-mono 需要的是相机-IMU 之间的外参(旋转和平移)以及时间偏移,这些参数出厂不一定给全。第三,Kalibr 支持多相机+IMU 的联合标定,能同时优化相机内参、外参、IMU 噪声参数和时间偏移,精度比单独标相机再标 IMU 高一个档次。
注意:Kalibr 标定对数据采集要求很高,标定板要清晰、运动要充分激励各轴、光照要均匀。如果采集数据质量差,标定结果还不如出厂参数。
1.4 整体流程概览
整个项目分两大块:标定和运行。标定又分相机标定和相机-IMU 联合标定。运行部分包括环境配置、参数文件修改、启动测试和结果评估。下面这张表把关键步骤和对应工具列清楚:
| 阶段 | 任务 | 工具 | 输出 |
|---|---|---|---|
| 准备 | 系统环境、ROS、依赖安装 | apt、源码编译 | 可运行环境 |
| 标定 | 相机内参标定 | Kalibr | camchain.yaml |
| 标定 | 相机-IMU 联合标定 | Kalibr | camchain-imucam.yaml |
| 配置 | VINS-mono 参数文件 | 手动编辑 | config.yaml |
| 运行 | 启动 VINS-mono | roslaunch | 轨迹、位姿 |
| 评估 | 轨迹对比、精度分析 | evo | 误差曲线 |
这个流程看起来线性,但实际操作中经常要来回迭代。比如标定结果不好,要重新采集数据;VINS 跑飞了,要回头检查标定参数。所以别指望一次成功,预留足够时间。
2. 环境搭建与依赖安装的实操细节
2.1 系统版本和 ROS 选择
D435i + VINS-mono + Kalibr 这套组合对系统版本比较敏感。我实测下来,Ubuntu 18.04 + ROS Melodic是最稳的组合,Ubuntu 20.04 + ROS Noetic 也能跑,但 Kalibr 的编译会遇到一些依赖问题,需要手动打补丁。如果你刚开始搭环境,强烈建议用 18.04,能省掉大量排查时间。
ROS 安装用官方脚本就行,注意安装ros-melodic-desktop-full,因为 Kalibr 和 VINS 都需要 rviz、rqt 这些可视化工具。安装完成后别忘了source /opt/ros/melodic/setup.bash,并写进.bashrc。
2.2 D435i 驱动安装与测试
D435i 在 ROS 下的驱动有两种:realsense-ros官方包和librealsense底层库。推荐用 apt 安装:
sudo apt install ros-melodic-realsense2-camera sudo apt install ros-melodic-realsense2-description装完后插上 D435i,运行:
roslaunch realsense2_camera rs_camera.launch然后在另一个终端rostopic list,应该能看到/camera/color/image_raw、/camera/imu、/camera/infra1/image_rect_raw等话题。如果 IMU 话题没有数据,检查一下 launch 文件里unite_imu_method参数,设成linear_interpolation或copy。
实操心得:D435i 的 IMU 默认频率是 200Hz,但实际发布可能不稳定。建议在 launch 文件里把
gyro_fps和accel_fps都设成 200,并且开启enable_gyro和enable_accel。另外,D435i 的 IMU 和相机之间有硬件同步,但 ROS 驱动里不一定默认开启,需要确认enable_sync参数。
2.3 Kalibr 编译与依赖坑
Kalibr 的编译是这套流程里最容易卡住的地方。官方推荐用 ROS 的 catkin 工作空间编译,但依赖比较多:
sudo apt install python-setuptools python-rosinstall ipython libeigen3-dev libboost-all-dev doxygen libopencv-dev ros-melodic-vision-opencv ros-melodic-image-transport-plugins ros-melodic-cmake-modules software-properties-common libpoco-dev python-matplotlib python-scipy python-git python-pip ipython libtbb-dev libblas-dev liblapack-dev python-catkin-tools libv4l-dev然后创建 catkin 工作空间,把 Kalibr 源码放进去编译。编译过程中最常见的报错是Eigen 版本冲突和OpenCV 版本不匹配。如果遇到error: ‘Eigen::...’ has no member,检查/usr/include/eigen3的版本,Kalibr 需要 Eigen 3.3 以上。如果遇到 OpenCV 报错,确认cv_bridge和系统 OpenCV 版本一致。
另一个坑是 Python 版本。Kalibr 的标定脚本是 Python 2 写的,Ubuntu 18.04 默认 Python 2.7,没问题。但如果你用 20.04,默认 Python 3,需要改一堆脚本,非常麻烦。所以再次强调:用 18.04。
2.4 VINS-mono 编译与 Ceres 依赖
VINS-mono 依赖 Ceres Solver 做非线性优化。Ceres 的安装有两种方式:apt 和源码编译。推荐源码编译,因为 apt 版本可能和 VINS 要求的版本不一致。
sudo apt install libgoogle-glog-dev libgflags-dev libatlas-base-dev libsuitesparse-dev git clone https://ceres-solver.googlesource.com/ceres-solver cd ceres-solver mkdir build && cd build cmake .. make -j4 sudo make install编译 VINS-mono 时,把它放进 catkin 工作空间的src目录,然后catkin_make。如果报错fatal error: ceres/ceres.h: No such file,说明 Ceres 没装好或者路径不对。检查/usr/local/include/ceres是否存在。
注意:VINS-mono 对 OpenCV 版本也有要求,推荐 3.3.1 或 3.4.x。Ubuntu 18.04 默认 OpenCV 3.2,可能不够,需要手动升级。升级 OpenCV 是个大工程,建议用脚本或者 Docker 镜像,避免污染系统环境。
3. Kalibr 标定的完整实操流程
3.1 标定板制作与参数确认
Kalibr 支持多种标定板,最常用的是AprilGrid和Checkerboard。AprilGrid 的优点是检测更稳定,对遮挡和光照变化鲁棒,推荐优先用。标定板参数包括:网格行列数、格子尺寸、标签间距等。这些参数必须和实际打印的标定板完全一致,否则标定结果直接废掉。
我一般用 A3 纸打印 AprilGrid,贴在硬纸板上,确保平整。打印时注意不要缩放,用实际尺寸。然后用卷尺量一下格子边长,确认和配置文件一致。
3.2 相机内参标定步骤
相机内参标定相对简单,用 Kalibr 的kalibr_calibrate_cameras命令:
rosrun kalibr kalibr_calibrate_cameras --bag camera.bag --topics /camera/infra1/image_rect_raw /camera/infra2/image_rect_raw --models pinhole-radtan pinhole-radtan --target aprilgrid.yaml这里用的是双目红外相机,模型选pinhole-radtan,因为 D435i 的红外相机是针孔模型加径向切向畸变。采集数据时,拿着标定板在相机视野内缓慢移动,覆盖整个画面,包括边缘和角落。每个位置停留一两秒,让相机拍清楚。
实操心得:采集数据时不要只在一个距离上晃,要远近结合。近处激励畸变参数,远处激励焦距参数。另外,标定板不要反光,光照要均匀,避免阴影。如果标定结果的重投影误差大于 0.3 像素,建议重新采集。
3.3 相机-IMU 联合标定
联合标定是重头戏,命令是kalibr_calibrate_imu_camera:
rosrun kalibr kalibr_calibrate_imu_camera --bag imu_cam.bag --cam camchain.yaml --imu imu.yaml --target aprilgrid.yaml这里需要提前准备好imu.yaml,里面包含 IMU 的噪声参数和频率。噪声参数可以先填出厂值或者经验值,Kalibr 会在标定过程中优化。
采集数据时,运动要充分激励所有轴:绕 X、Y、Z 轴分别旋转,同时做平移运动。不要只在一个平面上晃,那样某些轴的外参估计不准。整个采集过程大概 60-90 秒,太短激励不充分,太长会累积漂移。
注意:联合标定对时间同步要求很高。D435i 的 IMU 和相机时间戳如果不同步,标定结果会很差。建议在采集前检查 ROS 话题的时间戳,确认 IMU 和图像的时间差在毫秒级。如果差太多,需要在驱动里开启硬件同步。
3.4 标定结果解读与验证
标定完成后,Kalibr 会输出camchain-imucam.yaml,里面包含相机-IMU 的外参矩阵和时间偏移。重点看几个指标:
- 重投影误差:小于 0.3 像素算合格。
- IMU 噪声参数:和出厂值对比,如果差一个数量级,说明采集数据有问题。
- 时间偏移:一般在几毫秒以内,如果超过 10ms,检查时间同步。
验证方法是把标定结果代入 VINS-mono 跑一段数据,看轨迹是否平滑、尺度是否稳定。如果轨迹跳变严重,回头检查标定参数。
4. VINS-mono 配置与运行调试
4.1 参数文件修改要点
VINS-mono 的配置文件在config目录下,主要改这几个:
- topic:改成 D435i 实际发布的话题名。
- cam0/cam1:填入 Kalibr 标定得到的相机内参和畸变系数。
- imu:填入 IMU 噪声参数。
- extrinsic:填入相机-IMU 外参。
- td:时间偏移,Kalibr 会给。
这些参数必须和标定结果一致,否则 VINS 跑不起来或者跑飞。
4.2 启动运行与数据录制
启动 VINS-mono:
roslaunch vins_estimator realsense_color.launch roslaunch vins_estimator vins_rviz.launch然后播放录好的 bag 或者直接实时运行。如果实时运行,拿着 D435i 缓慢移动,让 VINS 初始化。初始化成功后,rviz 里会显示轨迹和特征点。
实操心得:VINS 初始化需要足够的运动激励,不要拿着相机静止不动。建议先做几个平移和旋转动作,让 IMU 和视觉都激励起来。初始化成功后,再正常移动。
4.3 轨迹评估与精度分析
用evo工具评估轨迹精度:
evo_traj bag result.bag /vins_estimator/odometry --plot evo_ape groundtruth.txt result.txt -va --plot重点看 ATE(绝对轨迹误差)和 RPE(相对位姿误差)。如果误差大,检查标定参数、时间同步和 IMU 噪声。
5. 常见问题与排查技巧实录
5.1 标定失败与报错处理
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 标定板检测不到 | 光照差、标定板不平 | 改善光照、压平标定板 |
| 重投影误差大 | 采集数据质量差 | 重新采集,覆盖全画面 |
| IMU 噪声参数异常 | 时间不同步 | 检查硬件同步 |
| 编译报错 | 依赖版本冲突 | 用 Docker 或降级系统 |
5.2 VINS 跑飞与初始化失败
VINS 跑飞最常见的原因是标定参数不准和时间不同步。排查顺序:先检查话题时间戳,再检查外参矩阵,最后检查 IMU 噪声。如果初始化一直失败,试着降低init_threshold或者增加运动激励。
5.3 性能优化与实用技巧
- 降低图像分辨率可以提高运行速度,但会损失精度。
- 开启回环检测能减少长时间漂移。
- 用
rosbag record录制数据时,加上--buffsize参数避免丢帧。
最后分享一个小技巧:如果 Kalibr 标定结果不理想,可以先用出厂参数跑 VINS,看轨迹是否可接受。如果出厂参数就能跑,说明标定不是瓶颈,可以把精力放在其他优化上。