Skip to content
 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

102 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Related Works and Extended Application

SLAM:

  1. ikd-Tree: A state-of-art dynamic KD-Tree for 3D kNN search.
  2. R2LIVE: A high-precision LiDAR-inertial-Vision fusion work using FAST-LIO as LiDAR-inertial front-end.
  3. LI_Init: A robust, real-time LiDAR-inertial initialization and synchronization package..
  4. FAST-LIO-LOCALIZATION: The integration of FAST-LIO with Re-localization function module.
  5. FAST-LIVO | FAST-LIVO2: A state-of-art LiDAR-inertial-visual odometry (LIVO) system with high computational efficiency, robustness, and pixel-level accuracy.

Control and Plan:

  1. IKFOM: A Toolbox for fast and high-precision on-manifold Kalman filter.
  2. UAV Avoiding Dynamic Obstacles: One of the implementation of FAST-LIO in robot's planning.
  3. UGV Demo: Model Predictive Control for Trajectory Tracking on Differentiable Manifolds.
  4. Bubble Planner: Planning High-speed Smooth Quadrotor Trajectories using Receding Corridors.

GPU Acceleration (Metal / CUDA)

This fork adds optional GPU acceleration via Apple Metal (macOS) and NVIDIA CUDA (Linux/Windows) for the computational bottleneck in FAST-LIO2: the h_share_model() function, which performs per-point plane fitting, residual computation, and Jacobian construction every ESKF iteration.

Key design: The GPU backend is entirely optional. The system automatically selects the best available backend: Metal on macOS, CUDA on Linux/Windows with NVIDIA GPU, or CPU fallback everywhere else — with zero code changes required.

Architecture

A ComputeBackend abstraction (include/compute/compute_backend.h) defines 7 GPU-amenable kernels:

Kernel Operation Description
1 batch_transform_points Body-to-world point transformation with LiDAR-IMU extrinsic
2 batch_plane_fit Per-point least-squares plane fitting (5 neighbors)
3 batch_compute_residuals Point-to-plane residual + validity scoring
4 batch_build_jacobian ESKF measurement Jacobian (Mx12) construction
5 compute_HTH H^T * H parallel reduction (Mx12 -> 12x12)
6 compute_HTh H^T * h parallel reduction (Mx12 + Mx1 -> 12x1)
7 batch_undistort_points IMU motion compensation per LiDAR point

Plus a fused pipeline (fused_h_share_model) that chains kernels 1-6 keeping data on the GPU.

Implementations:

  • include/compute/cpu_backend.h — CPU reference using Eigen (always available)
  • include/compute/metal_backend.mm — Metal GPU backend (macOS with Metal-capable GPU)
  • include/compute/metal/kernels.metal — 9 Metal compute shaders
  • include/compute/cuda/cuda_backend.cu — CUDA GPU backend (NVIDIA GPU with CUDA toolkit)
  • include/compute/cuda/kernels.cu — 9 CUDA compute kernels

Performance (Apple M3 Pro)

Fused h_share_model pipeline (superkernel — 2 GPU dispatches, end-to-end):

Points CPU Metal Speedup
1,000 0.41 ms 0.077 ms 5.3x
5,000 2.0 ms 0.16 ms 12.8x
10,000 4.1 ms 0.25 ms 16.5x
50,000 20.2 ms 0.88 ms 23.1x
100,000 40.3 ms 1.79 ms 22.5x

Isolated plane fitting (the single biggest bottleneck kernel):

Points CPU Metal Speedup
10,000 3.7 ms 9 us 414x
100,000 37 ms 13 us 2,866x
500,000 186 ms 22 us 8,593x

Validation shows 100% feature count agreement and HTH trace ratio of 1.000 between CPU and Metal backends at all tested sizes (1k-500k points).

Compatibility — Cross-Platform

GPU backends will not affect builds on unsupported systems. The safety guarantees:

  1. CMake gating: Metal compilation is wrapped in if(APPLE) + find_library(Metal). CUDA compilation uses check_language(CUDA). On systems without a supported GPU, only the CPU backend is compiled.
  2. Factory pattern: create_backend("cpu") always works. create_backend("metal") and create_backend("cuda") return nullptr on unsupported systems. create_default_backend() selects the best available backend automatically (Metal > CUDA > CPU).
  3. Header guards: The CPU backend's factory functions are guarded by #if !defined(HAS_METAL) && !defined(HAS_CUDA). GPU-linked targets define the appropriate macro and provide their own factory implementations.
  4. No new dependencies: Metal uses Apple system frameworks (Metal.framework, Foundation.framework). CUDA requires the NVIDIA CUDA Toolkit (>= 11.0). The CPU backend has no additional dependencies beyond Eigen.

Building the Test Suite

macOS (Metal)

# Prerequisites: Xcode Command Line Tools (includes Metal compiler)
xcode-select --install

# Debug build (for testing)
cmake -S test -B test/build
cmake --build test/build -j$(sysctl -n hw.ncpu)

# Release build (for benchmarks)
cmake -S test -B test/build-release -DCMAKE_BUILD_TYPE=Release
cmake --build test/build-release -j$(sysctl -n hw.ncpu)

# Run all tests (85 total: 74 core + 11 Metal)
./test/build/test_so3_math           # 17 tests - SO(3) math operations
./test/build/test_plane_estimation   #  6 tests - Plane fitting
./test/build/test_ikd_tree           # 14 tests - ikd-Tree operations
./test/build/test_compute_backend    # 26 tests - CPU compute backend
./test/build/test_metal_backend      # 11 tests - Metal GPU backend

# Run benchmarks (includes CPU vs Metal validation + timing)
./test/build-release/bench_metal_backend

Linux with NVIDIA GPU (CUDA)

# Prerequisites: CUDA Toolkit >= 11.0, CMake >= 3.18
# Install CUDA: https://developer.nvidia.com/cuda-downloads

# Debug build (for testing)
cmake -S test -B test/build
cmake --build test/build -j$(nproc)

# Release build (for benchmarks)
cmake -S test -B test/build-release -DCMAKE_BUILD_TYPE=Release
cmake --build test/build-release -j$(nproc)

# Run all tests (85 total: 74 core + 11 CUDA)
./test/build/test_so3_math           # 17 tests - SO(3) math operations
./test/build/test_plane_estimation   #  6 tests - Plane fitting
./test/build/test_ikd_tree           # 14 tests - ikd-Tree operations
./test/build/test_compute_backend    # 26 tests - CPU compute backend
./test/build/test_cuda_backend       # 11 tests - CUDA GPU backend

# Run benchmarks (includes CPU vs CUDA validation + timing)
./test/build-release/bench_cuda_backend

On platforms without a supported GPU, the GPU-specific test/benchmark targets are simply not generated by CMake. All core tests build and run normally.

Technical Notes

  • Float precision on GPU, double on CPU: Both Metal and CUDA shaders use float32 for per-point operations (transform, plane fit, residual, Jacobian). The Jacobian matrix H is float on the GPU and converted to double during readback. HTH/HTh reductions accumulate in float on the GPU with block/threadgroup partial sums, then the final reduction across blocks happens on the CPU in double.
  • Cholesky solver for plane fitting: Both GPU backends use Cholesky decomposition of the 3x3 normal equations matrix (A^T*A) with coordinate pre-scaling for numerical stability. This matches the CPU's colPivHouseholderQr results at 100% validity agreement.
  • Zero-copy on Apple Silicon: The Metal backend uses shared memory (MTLResourceStorageModeShared), enabling zero-copy buffer access between CPU and GPU on unified memory architectures.
  • CUDA architecture support: The CUDA backend targets compute capabilities 6.0 through 9.0 (Pascal through Hopper/Ada). Shared memory reduction uses 256 threads per block with 78 upper-triangle elements for symmetric HTH accumulation.
  • CUDA-specific optimizations: The CUDA kernels go beyond a direct Metal port with NVIDIA-specific intrinsics and host-side optimizations:
    • __ldg() read-only texture cache loads on all global memory reads (doubles effective cache bandwidth)
    • __fmaf_rn() fused multiply-add throughout all linear algebra (faster and more precise than separate mul+add)
    • rsqrtf() hardware reciprocal square root instead of sqrt + division
    • sincosf() simultaneous sin/cos in Rodrigues rotation
    • Closed-form upper-triangle index mapping (eliminates divergent loop in HTH reduction)
    • #pragma unroll on critical inner loops (shared memory loads, matrix ops, reduction)
    • Persistent GPU buffer pool (eliminates ~600us/call of cudaMalloc/cudaFree overhead)
    • Pinned (page-locked) host memory for DMA transfers (2-3x faster than pageable)
    • CUDA streams with cudaMemcpyAsync — single sync point instead of 4 per pipeline call
    • Pre-reserved host vectors to avoid heap thrashing during feature compaction

CUDA Backend (Experimental)

Note: The CUDA backend has been written and compiles, but has not yet been tested on actual NVIDIA hardware. The development machine is an Apple M3 Pro (Metal only). The kernel logic is a direct port of the validated Metal shaders with CUDA-specific optimizations layered on top. If you have access to an NVIDIA GPU and encounter issues, please open an issue.

Prerequisites:

  • NVIDIA GPU (compute capability >= 6.0 — Pascal or newer)
  • CUDA Toolkit >= 11.0 (download)
  • CMake >= 3.18

Building with CUDA (mainline FAST-LIO):

On a Linux system with CUDA installed, the standard catkin_make build will automatically detect CUDA and enable the GPU backend:

cd ~/$A_ROS_DIR$/src
git clone https://github.com/hku-mars/FAST_LIO.git
cd FAST_LIO
git submodule update --init
cd ../..
catkin_make
source devel/setup.bash

CMake will print CUDA GPU backend: ENABLED during configuration. At runtime, the node will log:

[ INFO] GPU compute backend: CUDA (NVIDIA GeForce RTX XXXX)

If CUDA is not detected (no GPU, no toolkit), the build falls back to CPU automatically — no code changes needed.

What to expect: The GPU accelerates the h_share_model() function which runs every ESKF iteration (typically 3-4 times per LiDAR scan). The k-NN search against the ikd-tree remains on the CPU (it's a pointer-based structure that doesn't parallelize to GPU). For scans with 10k+ points, the GPU should provide a significant speedup on the plane fitting + Jacobian construction + HTH/HTh reduction portion.

Known limitations:

  • Untested on real hardware — correctness is inferred from Metal validation (identical kernel logic)
  • No CUDA benchmarks yet (contributions welcome!)
  • The n > dof_Measurement path in the ESKF (< 24 valid features, extremely rare) falls back to CPU
  • Targets architectures 60-90; if your GPU is older than Pascal, you may need to add your arch to CMakeLists.txt

FAST-LIO

FAST-LIO (Fast LiDAR-Inertial Odometry) is a computationally efficient and robust LiDAR-inertial odometry package. It fuses LiDAR feature points with IMU data using a tightly-coupled iterated extended Kalman filter to allow robust navigation in fast-motion, noisy or cluttered environments where degeneration occurs. Our package address many key issues:

  1. Fast iterated Kalman filter for odometry optimization;
  2. Automaticaly initialized at most steady environments;
  3. Parallel KD-Tree Search to decrease the computation;

FAST-LIO 2.0 (2021-07-05 Update)

Related video: FAST-LIO2, FAST-LIO1

Pipeline:

New Features:

  1. Incremental mapping using ikd-Tree, achieve faster speed and over 100Hz LiDAR rate.
  2. Direct odometry (scan to map) on Raw LiDAR points (feature extraction can be disabled), achieving better accuracy.
  3. Since no requirements for feature extraction, FAST-LIO2 can support many types of LiDAR including spinning (Velodyne, Ouster) and solid-state (Livox Avia, Horizon, MID-70) LiDARs, and can be easily extended to support more LiDARs.
  4. Support external IMU.
  5. Support ARM-based platforms including Khadas VIM3, Nivida TX2, Raspberry Pi 4B(8G RAM).

Related papers:

FAST-LIO2: Fast Direct LiDAR-inertial Odometry

FAST-LIO: A Fast, Robust LiDAR-inertial Odometry Package by Tightly-Coupled Iterated Kalman Filter

Contributors

Wei Xu 徐威Yixi Cai 蔡逸熙Dongjiao He 贺东娇Fangcheng Zhu 朱方程Jiarong Lin 林家荣Zheng Liu 刘政, Borong Yuan

1. Prerequisites

1.1 Ubuntu and ROS

Ubuntu >= 16.04

For Ubuntu 18.04 or higher, the default PCL and Eigen is enough for FAST-LIO to work normally.

ROS >= Melodic. ROS Installation

1.2. PCL && Eigen

PCL >= 1.8, Follow PCL Installation.

Eigen >= 3.3.4, Follow Eigen Installation.

1.3. livox_ros_driver

Follow livox_ros_driver Installation.

Remarks:

  • Since the FAST-LIO must support Livox serials LiDAR firstly, so the livox_ros_driver must be installed and sourced before run any FAST-LIO luanch file.
  • How to source? The easiest way is add the line source $Livox_ros_driver_dir$/devel/setup.bash to the end of file ~/.bashrc, where $Livox_ros_driver_dir$ is the directory of the livox ros driver workspace (should be the ws_livox directory if you completely followed the livox official document).

2. Build

If you want to use docker conatiner to run fastlio2, please install the docker on you machine. Follow Docker Installation.

2.1 Docker Container

User can create a new script with anyname by the following command in linux:

touch <your_custom_name>.sh

Place the following code inside the <your_custom_name>.sh script.

#!/bin/bash
mkdir docker_ws
# Script to run ROS Kinetic with GUI support in Docker

# Allow X server to be accessed from the local machine
xhost +local:

# Container name
CONTAINER_NAME="fastlio2"

# Run the Docker container
docker run -itd \
  --name=$CONTAINER_NAME \
  --user mars_ugv \
  --network host \
  --ipc=host \
  -v /home/$USER/docker_ws:/home/mars_ugv/docker_ws \
  --privileged \
  --env="QT_X11_NO_MITSHM=1" \
  --volume="/etc/localtime:/etc/localtime:ro" \
  -v /dev/bus/usb:/dev/bus/usb \
  --device=/dev/dri \
  --group-add video \
  -v /tmp/.X11-unix:/tmp/.X11-unix \
  --env="DISPLAY=$DISPLAY" \
  kenny0407/marslab_fastlio2:latest \
  /bin/bash

execute the following command to grant execute permissions to the script, making it runnable:

sudo chmod +x <your_custom_name>.sh

execute the following command to download the image and create the container.

./<your_custom_name>.sh

Script explanation:

  • The docker run command provided below creates a container with a tag, using an image from Docker Hub. The download duration for this image can differ depending on the user's network speed.
  • This command also establishes a new workspace called docker_ws, which serves as a shared folder between the Docker container and the host machine. This means that if users wish to run the rosbag example, they need to download the rosbag file and place it in the docker_ws directory on their host machine.
  • Subsequently, a folder with the same name inside the Docker container will receive this file. Users can then easily play the file within Docker.
  • In this example, we've shared the network of the host machine with the Docker container. Consequently, if users execute the rostopic list command, they will observe identical output whether they run it on the host machine or inside the Docker container."

2.2 Build from source

Clone the repository and catkin_make:

    cd ~/$A_ROS_DIR$/src
    git clone https://github.com/hku-mars/FAST_LIO.git
    cd FAST_LIO
    git submodule update --init
    cd ../..
    catkin_make
    source devel/setup.bash
  • Remember to source the livox_ros_driver before build (follow 1.3 livox_ros_driver)
  • If you want to use a custom build of PCL, add the following line to ~/.bashrc export PCL_ROOT={CUSTOM_PCL_PATH}

3. Directly run

Noted:

A. Please make sure the IMU and LiDAR are Synchronized, that's important.

B. The warning message "Failed to find match for field 'time'." means the timestamps of each LiDAR points are missed in the rosbag file. That is important for the forward propagation and backwark propagation.

C. We recommend to set the extrinsic_est_en to false if the extrinsic is give. As for the extrinsic initiallization, please refer to our recent work: Robust Real-time LiDAR-inertial Initialization.

3.1 For Avia

Connect to your PC to Livox Avia LiDAR by following Livox-ros-driver installation, then

    cd ~/$FAST_LIO_ROS_DIR$
    source devel/setup.bash
    roslaunch fast_lio mapping_avia.launch
    roslaunch livox_ros_driver livox_lidar_msg.launch
  • For livox serials, FAST-LIO only support the data collected by the livox_lidar_msg.launch since only its livox_ros_driver/CustomMsg data structure produces the timestamp of each LiDAR point which is very important for the motion undistortion. livox_lidar.launch can not produce it right now.
  • If you want to change the frame rate, please modify the publish_freq parameter in the livox_lidar_msg.launch of Livox-ros-driver before make the livox_ros_driver pakage.

3.2 For Livox serials with external IMU

mapping_avia.launch theratically supports mid-70, mid-40 or other livox serial LiDAR, but need to setup some parameters befor run:

Edit config/avia.yaml to set the below parameters:

  1. LiDAR point cloud topic name: lid_topic
  2. IMU topic name: imu_topic
  3. Translational extrinsic: extrinsic_T
  4. Rotational extrinsic: extrinsic_R (only support rotation matrix)
  • The extrinsic parameters in FAST-LIO is defined as the LiDAR's pose (position and rotation matrix) in IMU body frame (i.e. the IMU is the base frame). They can be found in the official manual.
  • FAST-LIO produces a very simple software time sync for livox LiDAR, set parameter time_sync_en to ture to turn on. But turn on ONLY IF external time synchronization is really not possible, since the software time sync cannot make sure accuracy.

3.3 For Velodyne or Ouster (Velodyne as an example)

Step A: Setup before run

Edit config/velodyne.yaml to set the below parameters:

  1. LiDAR point cloud topic name: lid_topic
  2. IMU topic name: imu_topic (both internal and external, 6-aixes or 9-axies are fine)
  3. Set the parameter timestamp_unit based on the unit of time (Velodyne) or t (Ouster) field in PoindCloud2 rostopic
  4. Line number (we tested 16, 32 and 64 line, but not tested 128 or above): scan_line
  5. Translational extrinsic: extrinsic_T
  6. Rotational extrinsic: extrinsic_R (only support rotation matrix)
  • The extrinsic parameters in FAST-LIO is defined as the LiDAR's pose (position and rotation matrix) in IMU body frame (i.e. the IMU is the base frame).

Step B: Run below

    cd ~/$FAST_LIO_ROS_DIR$
    source devel/setup.bash
    roslaunch fast_lio mapping_velodyne.launch

Step C: Run LiDAR's ros driver or play rosbag.

3.4 For MARSIM Simulator

Install MARSIM: https://github.com/hku-mars/MARSIM and run MARSIM as below

cd ~/$MARSIM_ROS_DIR$
roslaunch test_interface single_drone_avia.launch

Then Run FAST-LIO:

roslaunch fast_lio mapping_marsim.launch

3.5 PCD file save

Set pcd_save_enable in launchfile to 1. All the scans (in global frame) will be accumulated and saved to the file FAST_LIO/PCD/scans.pcd after the FAST-LIO is terminated. pcl_viewer scans.pcd can visualize the point clouds.

Tips for pcl_viewer:

  • change what to visualize/color by pressing keyboard 1,2,3,4,5 when pcl_viewer is running.
    1 is all random
    2 is X values
    3 is Y values
    4 is Z values
    5 is intensity

4. Rosbag Example

4.1 Livox Avia Rosbag

Files: Can be downloaded from google drive

Run:

roslaunch fast_lio mapping_avia.launch
rosbag play YOUR_DOWNLOADED.bag

4.2 Velodyne HDL-32E Rosbag

NCLT Dataset: Original bin file can be found here.

We produce Rosbag Files and a python script to generate Rosbag files: python3 sensordata_to_rosbag_fastlio.py bin_file_dir bag_name.bag

Run:

roslaunch fast_lio mapping_velodyne.launch
rosbag play YOUR_DOWNLOADED.bag

5.Implementation on UAV

In order to validate the robustness and computational efficiency of FAST-LIO in actual mobile robots, we build a small-scale quadrotor which can carry a Livox Avia LiDAR with 70 degree FoV and a DJI Manifold 2-C onboard computer with a 1.8 GHz Intel i7-8550U CPU and 8 G RAM, as shown in below.

The main structure of this UAV is 3d printed (Aluminum or PLA), the .stl file will be open-sourced in the future.

6.Acknowledgments

Thanks for LOAM(J. Zhang and S. Singh. LOAM: Lidar Odometry and Mapping in Real-time), Livox_Mapping, LINS and Loam_Livox.

About

A computationally efficient and robust LiDAR-inertial odometry (LIO) package

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages