Skip to content

mingren11/ct-lio

 
 

Repository files navigation

ct-lio (Docker 适配版)

CT-LIO(Continuous-Time LiDAR-Inertial Odometry)是一套连续时间 LiDAR-IMU 紧耦合里程计:用 ct-icp 的 LiDAR 约束与 IMU 数据通过 ESKF(松耦合)融合,对快速运动鲁棒;同时提供 ct-icp 的解析求导与自动求导两种实现,以及简单的退化检测。算法对 lidar–imu 不严格时间同步的设备也能工作良好。

本仓库是在上游 chengwei0427/ct-lio 基础上的 Docker 化 + 工程适配 fork,主要面向 Robosense RS16「staircase」数据集调通。下文以 Docker 工作流为主线;若想在宿主机原生编译,见文末「附:原生编译」。


本仓库相对上游的改动

  1. 重力对齐初始化(修复地图歪斜) 上游 ESKF 初始化时把初始姿态 R_ 留为单位阵,世界系直接等于初始 IMU 体坐标系——传感器有安装倾角时整张地图就是歪的。本仓库在 src/algo/eskf.hppSetInitialConditions 中,用静止段估计的重力方向构造初始旋转,使世界系 Z 轴竖直向上、重力固定为 (0,0,-|g|)。初始化成功时会打印对齐后的 yaw/pitch/roll 与世界系重力,便于核对。

  2. 完整 Docker 环境 + 三个脚本(见下),改源码后秒级增量编译,无需重建镜像

  3. 面向 Robosense RS16 staircase 的参数与配置config/mapping.yaml),lidar/imu topic、外参、体素尺寸等已按该数据集设好。


快速上手(Docker,推荐)

源码以 volume 实时挂载进常驻容器,因此改完 src/ 只需在容器内增量 catkin_make(秒级),不必重建镜像

脚本 作用 何时运行
scripts/build_env.sh 构建环境镜像(ROS Noetic + Ceres 2.1.0 等重依赖,约 10–20 分钟) 首次;或改了 Dockerfile / 根 CMakeLists.txt / cmake/ / 依赖
scripts/compile.sh 常驻容器内增量编译 src/(秒级) 每次改了 src/ 下的 .cpp / .h
scripts/run.sh 启动算法节点 + RViz,并播放 rosbag 跑数据时

环境要求

项目 要求
宿主机系统 Ubuntu 20.04 / 22.04
Docker ≥ 24.0
NVIDIA 驱动 ≥ 525
NVIDIA Container Toolkit 已安装并配置
显示环境 X11(用于 RViz)

用法

# 1) 首次:构建镜像(仅一次,或依赖/Dockerfile 变更时)
./scripts/build_env.sh

# 2) 改完 src/ 源码后:秒级增量编译(不重建镜像)
./scripts/compile.sh

# 3) 把 rosbag 放进 bags/ 后运行(容器内对应 /bags/)
./scripts/run.sh                       # 默认播放 bags/2022-08-30-20-33-52_0.bag
./scripts/run.sh other.bag             # 播放 bags/other.bag
./scripts/run.sh other.bag -r 0.5      # 半速播放(额外参数透传给 rosbag play)

run.sh 会自动:xhost +local:docker 授权 X11 → 拉起常驻容器 → 后台 roslaunch(算法节点 + RViz + 静态 TF,roslaunch 自动拉起 roscore,日志在容器内 /tmp/launch.log)→ 前台播放 rosbag(Ctrl-C 结束)。

rosbag 播放控制:空格暂停/继续,s 单帧步进,-r 0.5 半速。

常用运维命令

docker compose exec ct-lio bash                    # 进容器手动操作
docker compose exec ct-lio pkill -f roslaunch      # 停止后台算法节点/RViz
docker compose down                                # 停止并删除容器
docker compose exec ct-lio grep -c 'Low convincing' /tmp/launch.log   # 统计退化帧

目录结构

ct-lio/
├── bags/               # rosbag 数据(只读挂载进容器,不打包进镜像)
├── config/
│   └── mapping.yaml    # 算法参数(挂载进容器,改后无需编译)
├── docker/
│   ├── entrypoint.sh   # 容器入口,source ROS 环境
│   └── patch_cmake.py  # 构建时去除 packages.cmake 里的硬编码路径
├── docs/
│   └── 使用说明.md     # 详细中文使用说明
├── launch/
│   ├── run_eskf.launch
│   └── rviz.rviz
├── scripts/
│   ├── build_env.sh    # 构建镜像
│   ├── compile.sh      # 增量编译
│   └── run.sh          # 运行
├── src/                # C++ 源码(挂载进容器,改后用 compile.sh 编译)
├── Dockerfile
└── docker-compose.yml

参数配置(config/mapping.yaml

配置文件挂载进容器,改后无需编译,重新 ./scripts/run.sh 即可生效

preprocess:
  lidar_type: 4          # 1=Livox AVIA, 2=Velodyne, 3=Ouster, 4=Robosense, 5=Pandar
  point_filter_num: 1    # 每 N 个点取 1 个(预过滤)
  blind: 0.01            # 剔除雷达原点附近 blind 米内的点

common:
  imu_topic: /imu/data        # IMU topic
  lid_topic: /rslidar_points  # LiDAR topic

mapping:
  extrinsic_est_en: true                 # true=在线估计外参
  extrinsic_T: [0.065, 0.0, -0.05]       # LiDAR→IMU 平移(米)
  extrinsic_R: [1,0,0, 0,-1,0, 0,0,-1]   # LiDAR→IMU 旋转矩阵(行优先)

odometry:
  surf_res: 0.2               # 降采样体素大小(米),越小点越密
  size_voxel_map: 0.2         # 地图体素大小(米)
  max_dist_to_plane_icp: 0.1  # 点到平面最大匹配距离(米)
  min_number_neighbors: 20    # 邻域有效所需最少邻居数(稀疏雷达可调小,如 RS16 → 6)
  max_num_residuals: 3000     # 每帧最多使用残差数
  min_num_residuals: 300      # 残差少于此数仅告警(不影响求解)
  max_num_iteration: 15       # ICP 外层最大迭代次数
  motion_compensation: CONSTANT_VELOCITY  # NONE / CONSTANT_VELOCITY / ITERATIVE / CONTINUOUS

motion_compensationNONE 不补偿;CONSTANT_VELOCITY 匀速假设(不依赖 IMU);ITERATIVE 迭代补偿;CONTINUOUS 连续时间补偿(精度最高,依赖 IMU)。


适配新数据集

  1. 查看 topic:docker compose exec ct-lio rosbag info /bags/your.bag

  2. config/mapping.yamlimu_topiclid_topiclidar_type

  3. 按实际安装填 extrinsic_Textrinsic_R

  4. 时间戳模式src/apps/main_eskf.cpp 第 82 行)——改完需 ./scripts/compile.sh

    // 正常数据集(header 时间戳为帧起始)
    lio->pushData(cloud_out, std::make_pair(msg->header.stamp.toSec(), convert->getTimeSpan()));
    // 部分数据集(header 时间戳为帧结束,如 staircase)
    lio->pushData(cloud_out, std::make_pair(msg->header.stamp.toSec() - convert->getTimeSpan(), convert->getTimeSpan()));
  5. 切换解析求导/自动求导:src/liw/lio/lidarodom.cpp#define USE_ANALYTICAL_DERIVATE


注意事项(重点)

  • 外参 extrinsic_R 极其关键。 旋转矩阵错误会导致 IMU 轴向与 LiDAR 不一致、轨迹严重漂移,务必以标定结果为准。地图歪斜先排查重力对齐(见本仓库改动 1),再排查外参。
  • Failed to find match for field 'time'. 表示 rosbag 中缺少每点时间戳,会影响前/后向传播,需确认雷达驱动输出逐点时间。
  • 退化告警 Low convincing result 出现在几何特征不足处(长走廊、空旷区)。少量(<10%)正常;大量出现说明外参或参数需调整。
  • not enough keypoints selected in ct-icp 只是告警:代码仍会照常求解,仅当残差数 < min_num_residuals 时打印。稀疏雷达(如 RS16)残差偏少时可调小 min_number_neighbors(20 → 6 左右)以真正增加残差,或调低 min_num_residuals
  • NCLT 数据集 运行前需调整 src/preprocess/cloud_convert/cloud_convert.cc 中的时间尺度 static double tm_scale(默认 1e9,NCLT 用 1e6),改后需 ./scripts/compile.sh
  • bags/config/ 均为只读挂载,容器内不能写入;如需临时改 config,先 cp/tmp/ 再加载。
  • 挂载范围:compose 只挂 src/config/launch/不挂 cmake/(否则会覆盖镜像里已 patch 的 packages.cmake)。改 cmake/Dockerfile./scripts/build_env.sh
  • RViz 无法弹窗 时,确认宿主机已执行 xhost +local:dockerDISPLAY 正确、NVIDIA Container Toolkit 已生效。

镜像构建原理(Dockerfile)

  • 基于 osrf/ros:noetic-desktop-full
  • Ceres 2.1.0 源码编译:Ubuntu 20.04 的 apt 仅提供 Ceres 1.14,而本项目要求 Ceres 2,故在镜像内从源码编译。
  • livox_ros_driver 与 ct-lio 放在同一 catkin workspace,先编译它生成消息头,再编译整个 workspace。
  • docker/patch_cmake.py:上游 cmake/packages.cmake 含两处硬编码开发者路径(Ceres、g2o),构建时用 Python 字符串替换去除(用 Python 而非 sed,避免 shell 展开 cmake 的 ${} 变量)。
  • docker-compose.ymlruntime: nvidia + 挂载 /tmp/.X11-unix 实现 RViz 的 GPU 硬件加速渲染;network_mode: host;容器以 sleep infinity 常驻,便于 exec 进去增量编译与运行。

更详细的中文说明见 docs/使用说明.md


运行结果示例(来自上游)

数据集 说明
Velodyne 32, NCLT
Ouster-32, multi-layer office(左:ours,右:fast-lio2)
Robosense RS16, staircase_crazy_rotation(左:PV-LIO,右:ours)

RS16 staircase 数据可从 Baidu Pan (password:4kpf)Google Drive 下载。


附:原生编译(不用 Docker)

cd ~/your_ros_ws/src
git clone <this-repo> ct-lio
cd ..
# 编译前确认依赖正确(可在 ./cmake/packages.cmake 调整 Ceres / g2o 路径)
catkin_make
source devel/setup.bash
roslaunch ct_lio run_eskf.launch
rosbag play your.bag

依赖:Ubuntu ≥ 18.04、ROS ≥ Melodic、PCL ≥ 1.8、Eigen ≥ 3.3.4、Ceres 2、g2o。

时间分析:运行后 ./log/ 下会生成耗时日志,python3 ./scripts/all_time.py 可绘图。


致谢 / Related Works

About

CT-LIO: Continuous-Time LiDAR-Inertial Odometry

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • C++ 89.5%
  • CMake 7.5%
  • Shell 1.2%
  • Other 1.8%