使用D435i+Avia跑Fast-LIVO

本文详细记录了使用D435i+Avia硬件设备运行Fast-LIVO开源SLAM算法的过程,包括编译Fast-LIVO、安装依赖库、修改Livox驱动以实现时间戳同步、调整IMU坐标系以及修改D435i的launch文件。在实际操作中,通过imu_transformer功能包实现了相机IMU到雷达坐标系的转换,并展示了最终的建图效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

最近Fast-LIVO开源了,之前看它的论文的时候发现效果很优秀,于是用实验室现有的设备尝试一下。这里主要记录一下使用不带外触发功能的D435i + Avia跑Fast-LIVO的过程,为了适配代码,主要修改了雷达的驱动、相机的launch文件、以及使用了一个外部的rospkg对相机的IMU坐标系做了转换。

Fast-LIVO源码仓库:https://github.com/hku-mars/FAST-LIVO

自己搭建的设备如下:
f21db741cdd16c395bb19e5f49a9ecf

编译Fast-LIVO

安装Sophus库

git clone https://github.com/strasdat/Sophus.git
cd Sophus
git checkout a621ff

在make之前,先修改一个东西,因为这个版本的Sophus是有bug的,解决方法如下:

打开Sophus/sophus/so2.cpp文件,将代码修改如下

// SO2::SO2()
// {
//   unit_complex_.real() = 1.;
//   unit_complex_.imag() = 0.;
// }
 SO2::SO2() 
{ 
   unit_complex_.real(1.); 
   unit_complex_.imag(0.); 
 }

修改好之后再make

mkdir build && cd build && cmake ..
make
sudo make install

安装fmt库

git clone  https://github.com/fmtlib/fmt.git
cd fmt
mkdir build
cd build
cmake ..
sudo make install

安装Vikit库

mkdir fast-livo_ws
cd fast-livo_ws & mkdir src & cd src
git clone https://github.com/uzh-rpg/rpg_vikit.git

/src/rpg_vikit/vikit_common/CMakeLists.txt中添加

SET(Sophus_LIBRARIES libSophus.so)

否则待会编译的时候会报找不到一些库的错误

下载Fast-LIVO源码

git clone https://github.com/hku-mars/FAST-LIVO
cd ../
catkin_make

到这里就可以跑作者提供的数据集了,数据集下载可以在这里找到FAST-LIVO-Datasets

连接实物

这里我们使用自己的设备跑Fast-LIVO,我们的设备是realsense D435i + Livox Avia ,因为Fast-LIVO要求相机和IMU时钟同步,所以针对我们自己的设备需要做一些调整

image-20221127112950195

可以看到作者提供的数据集里面的各个传感器是严格时钟同步的

image-20221127113030400

livox驱动修改

livox原驱动中设置lidar、imu数据的时间戳均为基于雷达启动的时间开始的,而非基于系统的时间,而摄像头(包括本例中的RealSense)数据的时间戳通常是基于系统时间的。如果只是跑作者的数据集,便不需要改livox的ROS驱动;如果要跑自己的数据,就需要参考作者提供的修改方式进行处理。

  • livox官方驱动: https://github.com/Livox-SDK/livox_ros_driver
  • r3live作者提供的修改方案:https://github.com/ziv-lin/livox_ros_driver_for_R2LIVE

实际上我们可以直接使用r3live作者提供的修改方案,但是为了学习,我这里参考作者的方法自己下载了官方的驱动进行修改,我这里修改的这个版本和r3live作者提供的主要有如下区别:

  • 设置了宏定义编译,在CMakeLists.txt中通过应该宏定义开关可以选择编译官方原生的,还是我们自己修改过后的版本的
  • 仅修改雷达点云的时间戳。因为r3live作者他使用的是雷达内置的IMU,所以他把雷达的时间戳也改了,我这里没有使用雷达自带的IMU,所以没有改雷达IMU的时间戳以及它的重力尺度

其实主要是修改了livox_ros_driver中的lddc.cpp文件,修改方法如下:

1、在lddc.cpp文件开头,加入用于记录起始时间的相关变量

image-20221127125435256

2、在点云消息发布之前把时间戳修改

  • livox自定义消息类型

修改lddc.cpp中的PublishCustomPointcloud函数,在消息Publish之前加入如下片段

image-20221127130013126

  • PointCloud2消息类型

修改lddc.cpp中的PublishPointcloud2函数,在消息Publish之前加入如下片段

image-20221127125943787

  • CMakeLists.txt设置宏定义

添加宏定义变量如下:

image-20221127132344312

修改完成之后重新编译,之后启动我们自己修改的livox_ros_driver 即可

IMU坐标系转换

由于 Avia 雷达内置IMU,如果使用它自带的IMU,那么就不需要进行坐标调整,因为雷达内置的IMU的坐标系和雷达坐标系是一致的。

因为我们这里没有使用外部的时钟触发设备,所以我们这里选择使用相机内置的IMU,在相机的ros_warp中我们可以设置图像和IMU时钟同步,这样就可以免去使用一个外部时钟触发设备。但是,如果我们使用外部的IMU(如:D435i内置的IMU),相机中内置的IMU的坐标系是在相机坐标系下的,和雷达坐标系不一样,我们需要把IMU的坐标系转换到雷达坐标系下。

这里我们通过ROS中的imu_transformer功能包进行修改,这个包需要自行下载编译

  • imu_pipeline功能包集:https://github.com/ros-perception/imu_pipeline

对于imu_transformer功能包,注意修改启动文件ned_to_enu.launch中的静态变换target_frame字段。

image-20221127123410617

修改完成之后,重新编译即可。使用时,先启动imu_transformer的转换程序,再启动相机的ros_warp

image-20221127123943208

可以看到它把相机的IMU话题订阅了并重新转发了一次,转成了/trans/data,这个话题下的IMU数据和雷达坐标系是一致的

image-20221127124417913

后面在我们程序中可以直接订阅这个/trans/data话题即可

D435i launch文件修改

这里我自定义了一个launch文件如下:

<launch>

  <rosparam>
      /camera/motion_module/global_time_enabled: true
      /camera/rgb_camera/global_time_enabled: true
  </rosparam>

  <arg name="serial_no"           default=""/>
  <arg name="usb_port_id"         default=""/>
  <arg name="device_type"         default=""/>
  <arg name="json_file_path"      default=""/>
  <arg name="camera"              default="camera"/>
  <arg name="tf_prefix"           default="$(arg camera)"/>
  <arg name="external_manager"    default="false"/>
  <arg name="manager"             default="realsense2_camera_manager"/>
  <arg name="output"              default="screen"/>
  <arg name="respawn"              default="false"/>

  <arg name="fisheye_width"       default="-1"/>
  <arg name="fisheye_height"      default="-1"/>
  <arg name="enable_fisheye"      default="false"/>

  <arg name="depth_width"         default="640"/>
  <arg name="depth_height"        default="480"/>
  <arg name="enable_depth"        default="false"/>

  <arg name="confidence_width"    default="-1"/>
  <arg name="confidence_height"   default="-1"/>
  <arg name="enable_confidence"   default="false"/>
  <arg name="confidence_fps"      default="-1"/>

  <!-- 红外摄像头 -->
  <arg name="infra_width"         default="640"/>
  <arg name="infra_height"        default="480"/>
  <arg name="enable_infra"        default="false"/>
  <arg name="enable_infra1"       default="false"/>
  <arg name="enable_infra2"       default="false"/>
  <arg name="infra_rgb"           default="false"/>

  <!-- RGB摄像头 -->
  <arg name="color_width"         default="640"/>
  <arg name="color_height"        default="480"/>
  <arg name="enable_color"        default="true"/>

  <arg name="fisheye_fps"         default="-1"/>
  <arg name="depth_fps"           default="30"/>
  <arg name="infra_fps"           default="30"/>
  <arg name="color_fps"           default="30"/>

  <!-- 开启IMU -->
  <arg name="gyro_fps"            default="200"/>
  <arg name="accel_fps"           default="200"/>
  <arg name="enable_gyro"         default="true"/>
  <arg name="enable_accel"        default="true"/>

  <arg name="enable_pointcloud"         default="false"/>
  <arg name="pointcloud_texture_stream" default="RS2_STREAM_COLOR"/>
  <arg name="pointcloud_texture_index"  default="0"/>
  <arg name="allow_no_texture_points"   default="false"/>
  <arg name="ordered_pc"                default="false"/>

  <!-- 开启时间戳同步 -->
  <arg name="enable_sync"               default="true"/>
  <arg name="align_depth"               default="false"/>

  <arg name="publish_tf"                default="true"/>
  <arg name="tf_publish_rate"           default="0"/>

  <arg name="filters"                   default=""/>
  <arg name="clip_distance"             default="-2"/>
  <arg name="linear_accel_cov"          default="0.01"/>
  <arg name="initial_reset"             default="false"/>
  <arg name="reconnect_timeout"         default="6.0"/>
  <arg name="wait_for_device_timeout"   default="-1.0"/>

  <!-- 陀螺仪与加速度联合发布的时候的对齐方式,这里采用了线性插值的方式 -->
  <arg name="unite_imu_method"          default="linear_interpolation"/>
  <!-- <arg name="unite_imu_method"          default="copy"/> -->
  <arg name="topic_odom_in"             default="odom_in"/>
  <arg name="calib_odom_file"           default=""/>
  <arg name="publish_odom_tf"           default="true"/>

  <arg name="stereo_module/exposure/1"  default="7500"/>
  <arg name="stereo_module/gain/1"      default="16"/>
  <arg name="stereo_module/exposure/2"  default="1"/>
  <arg name="stereo_module/gain/2"      default="16"/>
  
  <include file="$(find imu_transformer)/launch/ned_to_enu.launch"/>

  <group ns="$(arg camera)">
    <include file="$(find realsense2_camera)/launch/includes/nodelet.launch.xml">
      <arg name="tf_prefix"                value="$(arg tf_prefix)"/>
      <arg name="external_manager"         value="$(arg external_manager)"/>
      <arg name="manager"                  value="$(arg manager)"/>
      <arg name="output"                   value="$(arg output)"/>
      <arg name="respawn"                  value="$(arg respawn)"/>
      <arg name="serial_no"                value="$(arg serial_no)"/>
      <arg name="usb_port_id"              value="$(arg usb_port_id)"/>
      <arg name="device_type"              value="$(arg device_type)"/>
      <arg name="json_file_path"           value="$(arg json_file_path)"/>

      <arg name="enable_pointcloud"        value="$(arg enable_pointcloud)"/>
      <arg name="pointcloud_texture_stream" value="$(arg pointcloud_texture_stream)"/>
      <arg name="pointcloud_texture_index"  value="$(arg pointcloud_texture_index)"/>
      <arg name="enable_sync"              value="$(arg enable_sync)"/>
      <arg name="align_depth"              value="$(arg align_depth)"/>

      <arg name="fisheye_width"            value="$(arg fisheye_width)"/>
      <arg name="fisheye_height"           value="$(arg fisheye_height)"/>
      <arg name="enable_fisheye"           value="$(arg enable_fisheye)"/>

      <arg name="depth_width"              value="$(arg depth_width)"/>
      <arg name="depth_height"             value="$(arg depth_height)"/>
      <arg name="enable_depth"             value="$(arg enable_depth)"/>

      <arg name="confidence_width"         value="$(arg confidence_width)"/>
      <arg name="confidence_height"        value="$(arg confidence_height)"/>
      <arg name="enable_confidence"        value="$(arg enable_confidence)"/>
      <arg name="confidence_fps"           value="$(arg confidence_fps)"/>

      <arg name="color_width"              value="$(arg color_width)"/>
      <arg name="color_height"             value="$(arg color_height)"/>
      <arg name="enable_color"             value="$(arg enable_color)"/>

      <arg name="infra_width"              value="$(arg infra_width)"/>
      <arg name="infra_height"             value="$(arg infra_height)"/>
      <arg name="enable_infra"             value="$(arg enable_infra)"/>
      <arg name="enable_infra1"            value="$(arg enable_infra1)"/>
      <arg name="enable_infra2"            value="$(arg enable_infra2)"/>
      <arg name="infra_rgb"                value="$(arg infra_rgb)"/>

      <arg name="fisheye_fps"              value="$(arg fisheye_fps)"/>
      <arg name="depth_fps"                value="$(arg depth_fps)"/>
      <arg name="infra_fps"                value="$(arg infra_fps)"/>
      <arg name="color_fps"                value="$(arg color_fps)"/>
      <arg name="gyro_fps"                 value="$(arg gyro_fps)"/>
      <arg name="accel_fps"                value="$(arg accel_fps)"/>
      <arg name="enable_gyro"              value="$(arg enable_gyro)"/>
      <arg name="enable_accel"             value="$(arg enable_accel)"/>

      <arg name="publish_tf"               value="$(arg publish_tf)"/>
      <arg name="tf_publish_rate"          value="$(arg tf_publish_rate)"/>

      <arg name="filters"                  value="$(arg filters)"/>
      <arg name="clip_distance"            value="$(arg clip_distance)"/>
      <arg name="linear_accel_cov"         value="$(arg linear_accel_cov)"/>
      <arg name="initial_reset"            value="$(arg initial_reset)"/>
      <arg name="reconnect_timeout"        value="$(arg reconnect_timeout)"/>
      <arg name="wait_for_device_timeout"  value="$(arg wait_for_device_timeout)"/>
      <arg name="unite_imu_method"         value="$(arg unite_imu_method)"/>
      <arg name="topic_odom_in"            value="$(arg topic_odom_in)"/>
      <arg name="calib_odom_file"          value="$(arg calib_odom_file)"/>
      <arg name="publish_odom_tf"          value="$(arg publish_odom_tf)"/>
      <arg name="stereo_module/exposure/1" value="$(arg stereo_module/exposure/1)"/>
      <arg name="stereo_module/gain/1"     value="$(arg stereo_module/gain/1)"/>
      <arg name="stereo_module/exposure/2" value="$(arg stereo_module/exposure/2)"/>
      <arg name="stereo_module/gain/2"     value="$(arg stereo_module/gain/2)"/>

      <arg name="allow_no_texture_points"  value="$(arg allow_no_texture_points)"/>
      <arg name="ordered_pc"               value="$(arg ordered_pc)"/>
    </include>
  </group>
</launch>

主要注意以下几个地方:

1、为了保证image和IMU的时钟同步需要添加下面几个参数

image-20221127134816375

2、开启IMU中的角速度和加速度联合发布,以及时间戳同步

image-20221127134917612

3、设置陀螺仪与加速度联合发布的时候的对齐方式

image-20221127134947367

运行

roslaunch realsense2_camera rs_livox.launch # 启动相机,这里我把imu_transform包也放到这个launch文件中启动了
roslaunch livox_ros_driver livox_lidar_msg.launch # 启动雷达
roslaunch fast_livo mapping_avi_we.launch # 启动fast_livo

建图效果如下,发现这个Fast-LIVO建图的时候比较卡,可能是作者还没优化好,针对低性能设备做优化也是一个重要的需求!

0

<think>我们有一个配置文件,现在需要修改它以适应基于Livox AVIA LiDAR的SLAM系统,同时接入ROS节点中的相机和雷达数据并进行建图。 根据上一个配置文件,我们需要关注以下几个部分: 1. 通用参数(common)部分:设置图像、雷达和IMU的话题,以及启用相应的传感器。 2. 外参标定(extrin_calib):需要提供相机与雷达之间的外参(旋转矩阵Rcl和平移向量Pcl)。 3. 预处理(preprocess):设置雷达类型为Livox Avia(lidar_type: 1)以及扫描线数(scan_line: 6)等。 4. 其他参数根据实际场景调整。 由于问题中要求接入ROS节点中的相机和雷达数据,我们需要确保: - 图像话题(img_topic)设置为实际相机发布的话题,例如"/left_camera/image"(根据实际修改)。 - 雷达话题(lid_topic)设置为实际Livox AVIA雷达发布的话题,例如"/livox/lidar"。 - IMU话题(imu_topic)设置为实际IMU发布的话题,例如"/livox/imu"。 - 启用图像(img_en: 1)和雷达(lidar_en: 1)。 另外,外参标定部分(extrin_calib)需要提供准确的相机到雷达的旋转矩阵(Rcl)和平移向量(Pcl)。如果不知道,需要进行标定。 修改步骤: 1. 修改`common`部分: - 确保`img_en`和`lidar_en`都为1(启用)。 - 设置正确的话题名称。 2. 修改`extrin_calib`部分: - 提供相机到雷达的外参(Rcl和Pcl)。如果不知道,可以先用单位矩阵和零向量,然后通过标定获取。 3. 在`preprocess`部分: - `lidar_type`设置为1(代表Livox Avia)。 - 其他参数如`point_filter_num`(下采样率)、`filter_size_surf`(表面滤波尺寸)等根据实际调整。 4. 根据实际需求调整其他参数,例如`vio`(视觉惯性里程计)部分,因为现在有相机数据,所以VIO相关参数也会影响性能。 5. 如果要保存地图,可以设置`pcd_save_en`为true,并调整`interval`参数(例如设置为10,每10帧保存一次,避免内存溢出)。 注意:由于同时使用相机和雷达,这是一个多传感器融合的SLAM系统,因此要确保时间同步(通过`time_offset`参数调整)和外参标定准确。 下面是一个修改后的示例(基于上一个配置文件,修改关键部分):</think>以下是针对基于 Livox AVIA LiDAR 的 SLAM 系统接入 ROS 节点相机/雷达数据并进行建图的配置文件修改指南: ### 关键修改步骤(基于原配置文件) #### 1. **传感器话题配置** (`common:` 部分) ```yaml common: img_topic: "/camera/color/image_raw" # 修改为实际相机话题 lid_topic: "/livox/lidar" # Livox AVIA 默认话题 imu_topic: "/livox/imu" # Livox 内置IMU话题 img_en: 1 # 必须启用相机 lidar_en: 1 # 必须启用LiDAR ``` #### 2. **外参标定** (`extrin_calib:` 部分) ```yaml extrin_calib: extrinsic_T: [0.1, 0.05, -0.08] # 实测相机-雷达平移 extrinsic_R: [0.99,0.05,-0.1, -0.06,0.99,0.05, 0.1,-0.04,0.99] # 实测旋转矩阵 Rcl: [0.9962,-0.087,0.0012, 0.087,0.9962,0.005, -0.0016,-0.005,1.0] # 相机-雷达旋转 Pcl: [0.15, 0.02, -0.1] # 相机-雷达平移 ``` #### 3. **预处理优化** (`preprocess:` 部分) ```yaml preprocess: point_filter_num: 2 # 增加采样率减轻计算负载 filter_size_surf: 0.2 # 增大滤波尺寸适应Livox特性 lidar_type: 1 # 明确指定Livox Avia(类型1) scan_line: 6 # Avia实际扫描线数 blind: 1.0 # 增大盲区过滤近距离噪声 ``` #### 4. **多传感器融合** (`vio:` 部分) ```yaml vio: max_iterations: 8 # 增加迭代提升精度 img_point_cov: 50 # 降低协方差增强视觉权重 exposure_estimate_en: true # 必须启用曝光补偿 ``` #### 5. **建图优化** (`lio:` 和 `local_map:` 部分) ```yaml lio: voxel_size: 0.3 # 减小体素尺寸提升细节 max_points_num: 100 # 增加点云密度 local_map: map_sliding_en: true # 启用滑动窗口减少内存占用 sliding_thresh: 5 # 降低滑动阈值适应动态场景 ``` #### 6. **输出设置** (`pcd_save:` 部分) ```yaml pcd_save: pcd_save_en: true # 启用地图保存 interval: 100 # 每100帧保存一个分块 filter_size_pcd: 0.1 # 减小滤波保留细节 ``` ### 完整配置文件示例 ```yaml common: img_topic: "/camera/color/image_raw" lid_topic: "/livox/lidar" imu_topic: "/livox/imu" img_en: 1 lidar_en: 1 extrin_calib: extrinsic_T: [0.1, 0.05, -0.08] extrinsic_R: [0.99,0.05,-0.1, -0.06,0.99,0.05, 0.1,-0.04,0.99] Rcl: [0.9962,-0.087,0.0012, 0.087,0.9962,0.005, -0.0016,-0.005,1.0] Pcl: [0.15, 0.02, -0.1] preprocess: point_filter_num: 2 filter_size_surf: 0.2 lidar_type: 1 scan_line: 6 blind: 1.0 lio: voxel_size: 0.3 max_points_num: 100 # 其余参数保持默认... pcd_save: pcd_save_en: true interval: 100 filter_size_pcd: 0.1 ``` ### 部署验证步骤 1. **传感器校准**: - 使用`lidar_camera_calibration`工具标定外参 - 通过`imu_utils`标定IMU噪声参数 2. **ROS启动命令**: ```bash roslaunch fast_lio mapping.launch config:=/path/to/your_modified_config.yaml ``` 3. **实时监控**: ```bash rviz -d $(rospack find fast_lio)/rviz_cfg/lio.rviz ``` > **注意**:实际值需根据传感器安装位置和场景动态调整,建议初始值误差不超过±15%
评论 54
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值