1. 系统概述与硬件准备

1.1 VINS-Fusion简介

VINS-Fusion(Visual-Inertial Navigation System Fusion)是由香港科技大学沈劭劼团队开发的开源视觉惯性SLAM系统。它支持多种传感器配置,包括单目+IMU、双目+IMU、纯双目等模式,具有以下特点:

  • 高精度定位:融合视觉和惯性信息,实现厘米级定位精度

  • 实时性能:优化后的代码结构,支持实时运行

  • 多传感器支持:兼容多种相机和IMU硬件

  • 全局优化:支持闭环检测和重定位

1.2 Intel RealSense D455特性

D455是Intel推出的主动立体视觉深度相机,相比前代产品具有以下优势:

  • 双目红外相机:两个全局快门红外相机,分辨率最高1280x800

  • 高精度IMU:内置BMI055 6轴IMU,采样率最高400Hz

  • 主动红外投影:增强低纹理环境下的特征提取

  • 硬件同步:图像和IMU数据硬件级时间同步

1.3 硬件清单

  • Intel RealSense D455摄像头 ×1

  • 三脚架或手持支架 ×1

  • AprilTag标定板(6×6网格,标签尺寸12cm)

  • Ubuntu 18.04/20.04计算机(推荐i5以上CPU,8GB以上内存)


2. 环境搭建与驱动安装

2.1 ROS环境配置

首先确保已安装ROS(本文以Ubuntu 20.04 + ROS Noetic为例):

# 添加ROS源
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

# 更新并安装ROS
sudo apt update
sudo apt install ros-noetic-desktop-full

# 初始化rosdep
sudo rosdep init
rosdep update

# 设置环境变量
echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
source ~/.bashrc

2.2 创建工作空间

# 创建工作空间目录
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src

# 初始化工作空间
catkin_init_workspace

# 编译空工作空间
cd ~/catkin_ws
catkin_make

# 设置工作空间环境变量
echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc

2.3 安装Intel RealSense SDK

sudo apt-get update
sudo apt-get install libssl-dev libusb-1.0-0-dev libgtk-3-dev \
  libglfw3-dev libgl1-mesa-dev libglu1-mesa-dev

# 克隆librealsense
cd ~
git clone https://github.com/IntelRealSense/librealsense.git
cd librealsense

# 安装内核补丁(必须!用于精确的IMU时间戳)
./scripts/patch-realsense-ubuntu-lts.sh

# 编译安装
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLES=true
make -j$(nproc)
sudo make install

2.4 安装realsense-ros

cd ~/catkin_ws/src
git clone https://github.com/IntelRealSense/realsense-ros.git
cd realsense-ros
git checkout 2.3.2  # 使用稳定版本

# 编译
cd ~/catkin_ws
catkin_make -j$(nproc) -DCMAKE_BUILD_TYPE=Release

2.5 安装VINS-Fusion

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

# 安装依赖
sudo apt-get install ros-${ROS_DISTRO}-cv-bridge ros-${ROS_DISTRO}-tf \
  ros-${ROS_DISTRO}-message-filters ros-${ROS_DISTRO}-image-transport

# 编译
cd ~/catkin_ws
catkin_make -j$(nproc)

2.6 安装Kalibr标定工具

使用Docker方式安装Kalibr(避免依赖冲突):

# 安装Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER

# 重新登录使权限生效
exit

# 拉取Kalibr镜像
docker pull stereolabs/kalibr

# 创建工作目录
mkdir -p ~/kalibr_workspace

3. 相机参数优化与红外投影仪处理

3.1 红外投影仪问题分析

Intel RealSense D455在默认配置下会开启红外激光投影仪,在图像上产生密集的散斑图案。这些图案虽然有助于深度计算,但对VINS-Fusion的特征提取会产生严重干扰:

  • 特征点数量爆炸:散斑会产生大量伪特征点

  • 特征跟踪不稳定:散斑随视角变化而变化

  • 计算负担增加:过多特征点导致计算负载上升

3.2 禁用红外投影仪

创建专用的相机启动文件 rs_d455_vins.launch:

<?xml version="1.0"?>
<launch>
  <arg name="camera" default="camera"/>
  <arg name="serial_no" default=""/>
  
  <group ns="$(arg camera)">
    <include file="$(find realsense2_camera)/launch/rs_camera.launch">
      <!-- 基础配置 -->
      <arg name="serial_no" value="$(arg serial_no)"/>
      <arg name="camera" value="$(arg camera)"/>
      
      <!-- 同步和IMU配置 -->
      <arg name="enable_sync" value="true"/>
      <arg name="unite_imu_method" value="linear_interpolation"/>
      
      <!-- 流配置:仅启用双目红外和IMU -->
      <arg name="enable_color" value="false"/>
      <arg name="enable_depth" value="false"/>
      <arg name="enable_infra1" value="true"/>
      <arg name="enable_infra2" value="true"/>
      <arg name="enable_gyro" value="true"/>
      <arg name="enable_accel" value="true"/>
      
      <!-- 关键:禁用红外投影仪 -->
      <arg name="emitter_enabled" value="false"/>
      
      <!-- 图像参数 -->
      <arg name="infra_width" value="640"/>
      <arg name="infra_height" value="480"/>
      <arg name="infra_fps" value="30"/>
      
      <!-- IMU参数 -->
      <arg name="gyro_fps" value="200"/>
      <arg name="accel_fps" value="200"/>
      
      <!-- 其他配置 -->
      <arg name="publish_tf" value="false"/>
      <arg name="initial_reset" value="true"/>
      <arg name="filters" value="pointcloud"/>
    </include>
  </group>
</launch>

3.3 验证投影仪已禁用

启动相机并验证图像质量:

# 启动相机
roslaunch your_package rs_d455_vins.launch

# 查看图像(应无散斑图案)
rqt_image_view

在rqt_image_view中订阅/camera/infra1/image_raw和/camera/infra2/image_raw,确认图像清晰无干扰。


4. AprilTag标定板准备

4.1 创建标定板配置文件

创建文件 apriltag_6x6_80x80cm.yaml:

target_type: 'apriltag'  # 标定板类型
tagCols: 6               # 水平方向Tag数量
tagRows: 6               # 垂直方向Tag数量
tagSize: 0.12            # 单个Tag边长(米)
tagSpacing: 0.3          # Tag间距系数(实际间距 = tagSize * tagSpacing)

参数说明:

  • tagSize: 实际打印的Tag边长,建议8-15cm

  • tagSpacing: 相邻Tag中心距离 = tagSize * (1 + tagSpacing)

4.2 生成并打印标定板

# 进入Kalibr Docker容器
docker run -it -v ~/kalibr_workspace:/root/kalibr_workspace stereolabs/kalibr

# 生成PDF标定板
cd /root/kalibr_workspace
kalibr_create_target_pdf \
  --type apriltag \
  --nx 6 \
  --ny 6 \
  --tsize 0.12 \
  --tspace 0.3

生成的PDF文件位于~/kalibr_workspace/target.pdf,打印后贴在平整的硬质板上。

4.3 标定板安装要求

  • 平整度:标定板必须绝对平整,建议使用亚克力板或铝板

  • 尺寸:根据实际打印尺寸修改tagSize参数

  • 照明:确保标定过程中光照均匀,避免反光

  • 对比度:打印时使用高对比度黑白印刷


5. 数据采集与标定流程

5.1 相机启动

# 启动相机(投影仪已禁用)
roslaunch your_package rs_d455_vins.launch

# 验证数据流
rostopic list | grep camera

5.2 录制标定数据

# 进入工作目录
cd ~/kalibr_workspace

# 录制bag文件
rosbag record -O d455_calib.bag \
  /camera/infra1/image_raw \
  /camera/infra2/image_raw \
  /camera/imu

采集技巧:

  1. 将标定板固定在平整墙面上或手持

  2. 缓慢移动相机,保持标定板在视野内

  3. 采集时长为60-90秒

  4. 运动类型应包括:

    • 左右平移(cover视场边缘)

    • 上下平移

    • 前后平移

    • 俯仰旋转

    • 偏航旋转

    • 滚转旋转

  5. 确保每个Tag在不同位置和角度被充分观测

5.3 相机内参标定

# 进入Kalibr容器
docker run -it -v ~/kalibr_workspace:/root/kalibr_workspace stereolabs/kalibr

cd /root/kalibr_workspace

# 执行双目内参标定
kalibr_calibrate_cameras \
  --bag d455_calib.bag \
  --topics /camera/infra1/image_raw /camera/infra2/image_raw \
  --models pinhole-radtan pinhole-radtan \
  --target apriltag_6x6_80x80cm.yaml \
  --approx-sync 0.05 \
  --show-extraction

参数说明:

  • --models: 相机模型,pinhole-radtan适用于大多数镜头

  • --approx-sync: 允许的最大时间差(秒)

  • --show-extraction: 显示特征提取过程

标定完成后生成:

  • camchain-d455_calib.yaml: 相机参数文件

  • report-cam-d455_calib.pdf: 标定报告

5.4 相机-IMU联合标定

# 使用上一步的相机标定结果
kalibr_calibrate_imu_camera \
  --bag d455_calib.bag \
  --cams camchain-d455_calib.yaml \
  --target apriltag_6x6_80x80cm.yaml \
  --imu /camera/imu \
  --imu-models scale-misalignment \
  --timeoffset-padding 0.1 \
  --reprojection-sigma 1.0

生成文件:

  • results-imucam-d455_calib.yaml: 完整的标定结果

  • report-imucam-d455_calib.pdf: 联合标定报告

5.5 标定结果分析

打开PDF报告检查以下指标:

  • 重投影误差:应小于0.2像素

  • 时间偏移:通常在±10ms以内

  • IMU噪声密度:符合D455的典型值

  • 外参估计不确定性:标准差应较小


6. VINS-Fusion配置文件生成

6.1 解析标定结果

从results-imucam-d455_calib.yaml中提取关键参数:

#!/usr/bin/env python
import yaml

with open('results-imucam-d455_calib.yaml', 'r') as f:
    data = yaml.safe_load(f)

# 相机0内参
cam0_intrinsics = data['cam0']['intrinsics']
cam0_distortion = data['cam0']['distortion_coeffs']

# 相机1内参
cam1_intrinsics = data['cam1']['intrinsics']
cam1_distortion = data['cam1']['distortion_coeffs']

# 双目外参(cam0到cam1)
T_cam0_cam1 = data['cam1']['T_cn_cnm1']

# IMU到cam0的外参(注意方向)
T_imu_cam0 = data['cam0']['T_cam_imu']  # T_cam0_imu的逆

# IMU噪声参数
acc_n = data['imu0']['noise_density']['accelerometer']
gyr_n = data['imu0']['noise_density']['gyroscope']
acc_w = data['imu0']['random_walk']['accelerometer']
gyr_w = data['imu0']['random_walk']['gyroscope']

print("相机内参:")
print(f"cam0: {cam0_intrinsics}")
print(f"cam1: {cam1_intrinsics}")

6.2 创建VINS-Fusion配置文件

创建 d455_stereo_imu_config.yaml:

%YAML:1.0

#=================================================
# 通用参数
#=================================================
imu_topic: "/camera/imu"
image0_topic: "/camera/infra1/image_raw"
image1_topic: "/camera/infra2/image_raw"
output_path: "/home/$(env USER)/vins_output/"

#=================================================
# 相机模型
#=================================================
model_type: PINHOLE
camera_name: "d455_stereo"
image_width: 640
image_height: 480

#=================================================
# 左目相机参数
#=================================================
cam0:
  # 内参 [fx, fy, cx, cy]
  intrinsics: [387.12, 387.12, 320.5, 240.5]  # 替换为标定值
  
  # 畸变系数 [k1, k2, p1, p2]
  distortion_parameters: [0.0, 0.0, 0.0, 0.0]  # 替换为标定值
  
  # 畸变模型
  distortion_model: "radtan"

#=================================================
# 右目相机参数
#=================================================
cam1:
  # 内参 [fx, fy, cx, cy]
  intrinsics: [387.12, 387.12, 320.5, 240.5]  # 替换为标定值
  
  # 畸变系数 [k1, k2, p1, p2]
  distortion_parameters: [0.0, 0.0, 0.0, 0.0]  # 替换为标定值
  
  # 畸变模型
  distortion_model: "radtan"
  
  # 外参: cam0到cam1的变换矩阵
  T_cn_cnm1:
    - [0.9998, -0.0023, 0.0012, -0.095]  # 旋转矩阵 + 平移
    - [0.0023, 0.9999, -0.0015, 0.001]
    - [-0.0012, 0.0015, 0.9999, 0.001]
    - [0.0, 0.0, 0.0, 1.0]

#=================================================
# IMU到相机的变换
#=================================================
# 注意: body_T_cam0 是 IMU坐标系到cam0坐标系的变换
# 如果标定给出的是 T_cam0_imu,需要取逆
body_T_cam0:
  - [0.9999, -0.0015, 0.0012, 0.025]  # 旋转矩阵 + 平移
  - [0.0015, 0.9999, -0.0023, -0.003]
  - [-0.0012, 0.0023, 0.9999, 0.015]
  - [0.0, 0.0, 0.0, 1.0]

#=================================================
# IMU参数
#=================================================
imu:
  # 加速度计噪声密度 (m/s^2/sqrt(Hz))
  acc_n: 0.02
  
  # 陀螺仪噪声密度 (rad/s/sqrt(Hz))
  gyr_n: 0.002
  
  # 加速度计随机游走 (m/s^2/s/sqrt(Hz))
  acc_w: 0.0002
  
  # 陀螺仪随机游走 (rad/s/s/sqrt(Hz))
  gyr_w: 4.0e-06

#=================================================
# 特征提取参数
#=================================================
# 最大特征点数量
max_cnt: 150

# 特征点之间最小距离(像素)
min_dist: 30

# 图像频率(Hz)
freq: 10

# 基础矩阵阈值
F_threshold: 1.0

# 是否显示跟踪
show_track: true

#=================================================
# 优化参数
#=================================================
# 是否使用IMU
use_imu: true

# 优化窗口大小
max_solver_time: 0.04
max_num_iterations: 8

# 关键帧距离
keyframe_parallax: 10.0

# 闭环检测
loop_closure: 1

# 全局优化频率
global_optimization_frequency: 10

#=================================================
# 其他参数
#=================================================
# 时间偏移估计
estimate_td: true

# 外部参数估计
estimate_extrinsic: 1  # 0: 固定, 1: 在线估计, 2: 初始值优化

# 是否将特征点发布为PointCloud
publish_pointcloud: true

# 是否发布特征图像
publish_image: true

6.3 参数修正与验证

重要提示:body_T_cam0是标定中最容易出错的部分。如果标定后轨迹发散,尝试取反平移向量


7. 系统运行与性能优化

7.1 启动相机

# 终端1: 启动相机
roslaunch your_package rs_d455_vins.launch

# 验证数据
rostopic hz /camera/imu
rostopic hz /camera/infra1/image_raw

7.2 启动VINS-Fusion

# 终端2: 启动RVIZ可视化
roslaunch vins vins_rviz.launch

# 终端3: 启动VINS节点
rosrun vins vins_node ~/catkin_ws/src/VINS-Fusion/config/d455_stereo_imu_config.yaml

7.3 性能调优参数

根据实际运行情况调整配置文件:

特征提取优化:

# 低纹理环境
max_cnt: 200      # 增加特征点数量
min_dist: 20      # 降低最小距离

# 高纹理环境
max_cnt: 100      # 减少特征点数量
min_dist: 40      # 增加最小距离

IMU权重调整:

# 如果视觉退化(黑暗、快速运动)
acc_n: 0.01       # 降低IMU噪声(提高权重)
gyr_n: 0.001

# 如果IMU噪声大
acc_n: 0.05       # 提高IMU噪声(降低权重)
gyr_n: 0.005

7.4 性能评估

使用EVO工具评估轨迹精度:

# 安装evo
pip install evo --upgrade --no-binary evo

# 评估ATE
evo_ape tum groundtruth.txt vins_estimate.txt -p

# 评估RPE
evo_rpe tum groundtruth.txt vins_estimate.txt -p

8. 常见问题与解决方案

8.1 标定失败问题

问题:特征点提取不足,标定失败

解决方案:

  1. 检查标定板打印质量,确保黑白对比度足够

  2. 调整相机曝光:rosrun dynamic_reconfigure dynparam set /camera/stereo_module exposure 200

  3. 增加环境光照,避免反光

  4. 确保运动速度足够慢,减少运动模糊

8.2 VINS轨迹发散

问题:VINS运行后轨迹立即发散或快速漂移

解决方案:

  1. 检查外参方向:尝试将body_T_cam0的平移向量取反

    # 原值
    translate: [0.025, -0.003, 0.015]
    # 取反
    translate: [-0.025, 0.003, -0.015]
  2. 检查IMU噪声参数:使用Kalibr标定结果中的噪声密度

  3. 禁用在线外参估计:设置estimate_extrinsic: 0

  4. 验证时间同步:检查图像和IMU时间戳是否同步

8.3 图像上的散斑问题

问题:图像上仍然有散斑图案

解决方案:

  1. 确认emitter_enabled: false已设置

  2. 使用动态重配置实时关闭:

    rosrun rqt_reconfigure rqt_reconfigure
    # 找到camera/stereo_module,取消勾选emitter_enabled
  3. 硬件方式:用黑色胶带遮挡投影仪窗口

8.4 性能问题

问题:VINS运行卡顿,CPU占用过高

解决方案:

  1. 降低图像分辨率:infra_width:=320 infra_height:=240

  2. 降低帧率:infra_fps:=15

  3. 减少特征点:max_cnt: 100

  4. 禁用可视化:show_track: false

8.5 IMU时间戳问题

问题:IMU和图像时间不对齐

解决方案:

  1. 启用硬件同步:enable_sync:=true

  2. 启用IMU插值:unite_imu_method:=linear_interpolation

  3. 允许时间偏移估计:estimate_td: true


9. 总结与展望

9.1 总结

本文详细介绍了从零开始配置Intel RealSense D455双目相机与VINS-Fusion系统的完整流程,包括:

  1. 环境搭建:ROS、Realsense SDK、VINS-Fusion和Kalibr的安装配置

  2. 相机优化:禁用红外投影仪获得干净图像的方法

  3. 精确标定:基于AprilTag的双目和IMU联合标定流程

  4. 系统集成:VINS-Fusion配置文件的生成和优化

  5. 性能调优:针对不同环境的参数调整方法

通过本文的指导,读者可以成功搭建一套完整的视觉惯性SLAM系统,实现厘米级的定位精度。

9.2 优化建议

  1. 硬件升级:考虑使用更高性能的计算平台(如NVIDIA Jetson系列)

  2. 闭环检测:结合视觉词袋模型实现闭环检测

  3. 多传感器融合:接入GPS、轮速计等传感器提高鲁棒性

  4. 深度学习增强:使用深度学习特征点替代传统特征

9.3 参考文献

  1. Qin, T., et al. "VINS-Mono: A Robust and Versatile Monocular Visual-Inertial State Estimator." IEEE Transactions on Robotics, 2018.

  2. Rehder, J., et al. "Kalibr: A Calibration Toolbox for Visual-Inertial Sensor Systems." ICRA, 2016.

  3. Intel RealSense D455 Datasheet, 2020.

  4. Zhang, Z. "A Flexible New Technique for Camera Calibration." IEEE TPAMI, 2000.

9.4 资源链接


作者简介:本文作者为机器人SLAM领域开发者,长期从事视觉惯性里程计和三维重建研究。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐