Ultra-Fusion

sjtuyinjieMIT活跃维护

紧耦合多传感器融合 SLAM 框架,在传感器退化与时空扰动下仍能稳定运行,适合机器人和自动驾驶的定位建图。

Ultra-Fusion: A Resilient Tightly-Coupled Multi-Sensor Fusion SLAM Framework under Sensor Degradation and Spatiotemporal Perturbation

v0.1.3发布于 2026-07-18 09:01 UTC917star75fork同步于 2026-11-07 07:32 UTC

怎么上手

由 README 提炼,执行前请确认
sudo dpkg -i ultrafusion_0.1.3_amd64.deb
source /opt/ros/noetic/setup.bash
roscore
rosbag play /path/to/your.bag --clock
uf_node m3dgr
硬件要求按 README 说明

README 未说明显存或 GPU 型号要求;运行依赖 ROS1 Noetic 或 ROS2 Humble,官方提供 amd64 Debian 包。

有 Docker 镜像
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

紧耦合多传感器 SLAM 框架,在传感器退化与时空扰动下保持定位可用

紧耦合多传感器融合 SLAM 框架,在传感器退化与时空扰动下仍能稳定运行,适合机器人和自动驾驶的定位建图。

核心能力

  • 统一配置支持 WIO、VIO、LIO、LVIO 四种融合模式
  • 可选融合轮速计与 GNSS,并支持在线标定
  • 对异步传感器流按时间戳排序后送入同一滑窗优化器
  • 共享状态表示、边缘化与标定逻辑,减少重复实现
  • 同一 YAML 驱动的 uf_node 工作流覆盖 ROS1 与 ROS2

容易踩的坑

需要自行下载 M3DGR 等数据集的 rosbag,安装包不含数据;ROS1 需先启动 roscore 并用 --clock 播放 bag;未列出的序列可能需要重新调参。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v0.1.3
  1. v0.1.3Ultra-Fusion ROS1 Noetic v0.1.3最新正式版2026-07-18 · 2026-07-18 09:01 UTC

    Ultra-Fusion ROS1 Noetic v0.1.3

    This release is based on v0.1.2 and retains its existing functionality, with focused improvements for D360/UFO multi-camera replay.

    Highlights

    • Improves D360/UFO multi-camera replay stability.
    • Hardens synchronization, queues, exception handling, and shutdown.
    • Prevents rejected estimates from entering mapping outputs.
    • Retains opt-in map PCD export, disabled by default in every shipped profile.

    Validation

    • Validated through replay from the installed Debian package.

    Assets

    • ultrafusion_0.1.3_amd64.deb
    • ultrafusion_0.1.3_amd64.deb.sha256
    • SHA256: fe3c74d999a4f6bcf4d11be4c70e67aa48586c3b5cda2af37b521f8e37c8a84c
  2. v0.2.2Ultra-Fusion ROS2 Humble v0.2.22026-07-15 · 2026-07-15 15:36 UTC
    查看更新说明

    Ultra-Fusion ROS2 Humble v0.2.2

    This release improves the ROS2 Humble estimator runtime and adds opt-in LiDAR map PCD export.

    Highlights

    • Adds the same flag-gated map keyframe and map.pcd generation contract as ROS1. All shipped ROS2 profiles keep it disabled by default.
    • Preserves ROS2 Humble LIO, LWIO, LVWIO, VIO, and VIWO profiles while merging the latest ROS1 estimator reliability work.
    • Reduces LVWIO memory and copy overhead by moving LiDAR buffers, releasing retained visual frames, and compacting sampled-cloud capacity.
    • Hardens RGB-D depth-only initialization and invalid inverse-depth handling.
    • Makes visual outlier refinement transactional and improves GNSS input/configuration and ECEF-anchor handling.
    • Adds dedicated packaged Longtime02 LVWIO settings and regression coverage for sensor readiness, LiDAR quality, ZUPT behavior, marginalization lifetime, multi-camera selection, and runtime memory contracts.

    Map PCD configuration

    map_pcd:
      enable: false
      output_directory: "/tmp/Ultrafusion"
      translation_threshold_m: 2.0
      rotation_threshold_deg: 30.0
      service_name: "/ultrafusion/generate_map_pcd"
    

    With enable: true, keyframes are written under <output_directory>/keyframes/. Generate the combined map before stopping the node:

    ros2 service call /ultrafusion/generate_map_pcd std_srvs/srv/Trigger '{}'
    

    The result is <output_directory>/map.pcd. No directory, keyframe, or service is created while the flag is false.

    Assets

    • ultrafusion-ros2_0.2.2_amd64.deb — 3,632,516 bytes
    • ultrafusion-ros2_0.2.2_amd64.deb.sha256
    • SHA256: 243f88fa5e3d87fcd96a2b02c8561fca4d5e56419ab72ec0a3a731b0ea34cccc

    Install after both assets have been uploaded to this release:

    ./scripts/install_ultrafusion_ros2_deb.sh
    

    Validation

    • ROS2 build and CTest: 2/2 passed in the Humble environment.
    • Final Debian metadata, RUNPATH/SONAME, symlinks, bundled CPU-only Ceres, wrapper syntax, and runtime ldd checks passed with no unresolved library.
    • Rebuilding with the checked-in ROS2 packager in the target Humble runtime produced an extracted payload identical to the staged final package.
    • Installed-package bag replays covered LiDAR, IMU, wheel, RGB, and depth with clean shutdown and no backend solve failures.
    • Map export was checked with the flag disabled and enabled. The disabled path creates no map artifacts or service; the enabled path saves keyframes and generates a consistent combined map.pcd through the Trigger service.

    This release stages the .deb only. The published ROS2 runtime image remains ultrafusion-ros2:0.2.1; no 0.2.2 Docker tag or digest is claimed here.

  3. v0.1.2Ultra-Fusion ROS1 Noetic v0.1.22026-07-15 · 2026-07-15 15:36 UTC
    查看更新说明

    Ultra-Fusion ROS1 Noetic v0.1.2

    This release improves ROS1 Noetic runtime stability and performance and adds opt-in LiDAR map PCD export.

    Highlights

    • Adds flag-gated map recording. It is disabled in every shipped profile. When enabled, the first LiDAR world cloud is saved and a new keyframe is written after either the configured translation or rotation threshold is reached. A ROS Trigger service merges those keyframes into map.pcd.
    • Reduces LVWIO memory and copy overhead by moving LiDAR buffers, releasing retained visual frames, and compacting sampled-cloud capacity.
    • Hardens RGB-D depth-only initialization and rejects invalid depth or optimized inverse-depth values.
    • Makes visual outlier refinement transactional so a rejected refinement does not partially mutate estimator state or the marginalization prior.
    • Improves GNSS input/configuration validation and fixes the optimized ECEF anchor Jacobian.
    • Hardens ROS1 multi-camera synchronization, explicit camera_id-to-extrinsic selection, buffer ownership, bag drain, and clean shutdown behavior.
    • Adds estimator-policy and regression coverage for sensor readiness, LiDAR quality, ZUPT behavior, marginalization lifetime, and memory contracts.

    Map PCD configuration

    The released default remains safe and side-effect free:

    map_pcd:
      enable: false
      output_directory: "/tmp/Ultrafusion"
      translation_threshold_m: 2.0
      rotation_threshold_deg: 30.0
      service_name: "/ultrafusion/generate_map_pcd"
    

    With enable: true, keyframes are written under <output_directory>/keyframes/. Generate the combined map before stopping the node:

    rosservice call /ultrafusion/generate_map_pcd
    

    The result is <output_directory>/map.pcd. No directory, keyframe, or service is created while the flag is false.

    Assets

    • ultrafusion_0.1.2_amd64.deb — 3,152,792 bytes
    • ultrafusion_0.1.2_amd64.deb.sha256
    • SHA256: 625252c2fade99b3c3f7ca016e0bda7c4a604be4dc1a27c4af2d7798026dbce9

    Install after both assets have been uploaded to this release:

    ./scripts/install_ultrafusion_deb.sh
    

    Validation

    • ROS1 build and CTest: 2/2 passed in the Noetic environment.
    • Final Debian metadata, RUNPATH/SONAME, symlinks, bundled CPU-only Ceres, wrapper syntax, and runtime ldd checks passed with no unresolved library.
    • Rebuilding with the checked-in ROS1 packager in the target Noetic runtime produced an extracted payload identical to the staged final package.
    • Installed-package bag replays covered LiDAR, IMU, wheel, and RGB-D visual input with clean shutdown and no backend solve failures.
    • Map export was checked with the flag disabled and enabled. The disabled path creates no map artifacts or service; the enabled path saves keyframes and generates a consistent combined map.pcd through the Trigger service.
  4. v0.2.1Ultra-Fusion ROS2 Humble v0.2.12026-07-08 · 2026-07-08 13:45 UTC
    查看更新说明

    Ultra-Fusion ROS2 Humble v0.2.1

    This release fixes the ROS2 Humble runtime package for M3DGR VIO/VIWO and validates LVWIO in the public ROS2 Docker runtime.

    Fixes

    • Adds packaged M3DGR ROS2 VIO and VIWO profiles.
    • Bundles the ROS2 Docker-compatible CPU-only libceres.so.3 runtime dependency.
    • Fixes the uf_node wrapper ordering so ROS2 setup is sourced before set -u.
    • Fixes ROS2 RGB/depth feature ingestion for VIO/VIWO, including M3DGR 16UC1; compressedDepth decoding.

    Verified

    Tested inside the public ultrafusion-ros2:0.2.1 Docker runtime with M3DGR grass01_20s_ros2:

    • VIO: initialized and wrote 588 TUM poses.
    • VIWO: initialized, used wheel factors, and wrote 588 TUM poses.
    • LVWIO: LiDAR/wheel/visual path ran and wrote 196 TUM poses.
    • ldd /opt/ultrafusion/bin/uf_node has no not found entries.

    Assets

    • ultrafusion-ros2_0.2.1_amd64.deb
    • ultrafusion-ros2_0.2.1_amd64.deb.sha256

    Docker Images

    docker pull maotiandocker/ultrafusion-ros2:0.2.1
    docker pull registry.cn-hangzhou.aliyuncs.com/bit_robot_image/ultrafusion-ros2:0.2.1
    

    SHA256

    ede0c95ac64d6195b0c80062e2457b559fdb988c4de0ddb244faceb92d4b3a59  ultrafusion-ros2_0.2.1_amd64.deb
    
  5. v0.2.0Ultra-Fusion ROS2 Humble v0.2.02026-06-29 · 2026-06-29 18:43 UTC
    查看更新说明

    Ultra-Fusion ROS2 Humble v0.2.0

    This release adds the ROS2 Humble runtime package for M3DGR playback and visualization.

    Assets

    • ultrafusion-ros2_0.2.0_amd64.deb
    • ultrafusion-ros2_0.2.0_amd64.deb.sha256

    Docker Images

    docker pull maotiandocker/ultrafusion-ros2:0.2.0
    docker pull registry.cn-hangzhou.aliyuncs.com/bit_robot_image/ultrafusion-ros2:0.2.0
    

    M3DGR ROS2

    The M3DGR converter writes Livox CustomMsg packets as sensor_msgs/msg/PointCloud2 with per-point timestamp, tag, and line fields. Ultra-Fusion reads lidar_type: 7 as Livox PointCloud2 and publishes ROS2 visualization topics including /curr_cloud, /result_lidar_path, and /odom_lidar.

    SHA256

    0a589e6f739038e3e2fa83d6d444d0d84b638854114bc8f8d7f7ac4b2a1dd225  ultrafusion-ros2_0.2.0_amd64.deb
    

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    Ultra-Fusion: A Resilient Tightly-Coupled Multi-Sensor Fusion SLAM Framework under Sensor Degradation and Spatiotemporal Perturbation for Intelligent Transportation Systems

    Website Hugging Face arXiv Dataset Video License

    ROS1 Noetic ROS2 Humble Sensor Platform

    stars forks open issues issue resolution

    Core contributors: Yihong Tian, Junjie Zhang, Liuyang Li, and Jie Yin*


    Ultra-Fusion is a tightly-coupled multi-sensor SLAM framework for intelligent transportation systems (ITS). It targets real-world deployment where sensor degradation (poor illumination, LiDAR degeneracy, wheel slippage, GNSS outage) and spatiotemporal miscalibration are common.

    Within one configurable optimization framework, Ultra-Fusion supports WIO, VIO, LIO, and LVIO, with optional wheel/GNSS fusion and online calibration.

    Available releases:

    • v0.1.0 (ROS1 Noetic) — pre-built binaries to reproduce the paper benchmarks (§2.1–2.2).
    • v0.1.1 Ultra-Fusion-Omni (UFO) on ROS1 Noetic — omnidirectional multi-camera LVIO for 360° vision + LiDAR; D360 as example (§2.4, walkthrough).
    • v0.1.2 (ROS1 Noetic) — improves runtime reliability and performance and adds flag-gated map PCD export (release notes).
    • v0.1.3 (ROS1 Noetic) — retains v0.1.2 functionality and improves D360/UFO multi-camera replay stability (release notes).
    • v0.2.0 (ROS2 Humble) — same uf_node + YAML workflow on Ubuntu 22.04 (§2.3).
    • v0.2.1 (ROS2 Humble) — fixes the ROS2 Humble runtime for M3DGR VIO/VIWO and validates LVWIO in the public ROS2 Docker runtime.
    • v0.2.2 (ROS2 Humble) — brings the latest estimator improvements and the same opt-in map PCD workflow to ROS2 (release notes).

    Latest Debian assets:

    RuntimeAssetSHA256
    ROS1 Noeticultrafusion_0.1.3_amd64.debfe3c74d999a4f6bcf4d11be4c70e67aa48586c3b5cda2af37b521f8e37c8a84c
    ROS2 Humbleultrafusion-ros2_0.2.2_amd64.deb243f88fa5e3d87fcd96a2b02c8561fca4d5e56419ab72ec0a3a731b0ea34cccc

    More demos and releases are on the way — stay tuned.

    Contents


    Overview

    Our Goal

    We aim to provide a foundational SLAM system for the community: one configurable framework that unifies sensor setups and platforms (wheeled, legged, aerial), and stays ultra-resilient under sensor degradation, timing delays, and extrinsic calibration errors — instead of a pipeline limited to one robot or one sensor stack.

    Method Overview

    Ultra-Fusion timestamp-orders asynchronous sensor streams and converts them into optional factors inside one sliding-window optimizer, sharing state representation, marginalization, and calibration logic.


    Why Ultra-Fusion

    Compared with pipelines tied to a fixed sensor set, Ultra-Fusion focuses on:

    1. Configurability — one framework for WIO / VIO / LIO / LVIO (+ wheel / GNSS).
    2. Reliability — robust localization under corner-case sensor degradation.
    3. Deployability — long-duration and high-speed ITS operation.
    4. Transferability — validated on wheeled, legged, and aerial platforms.
    5. Dual middleware — ROS1 (Noetic) and ROS2 (Humble) runtimes share the same YAML-driven uf_node workflow.

    Benchmarks and Findings

    Ultra-Fusion is evaluated on five public benchmarks:

    Reported gains include competitive accuracy and improved localization availability under sensor degradation, calibration perturbation, and long-duration / high-speed operation.

    See the project website for videos, benchmark tables, and interactive demos!

    [!NOTE] This repository currently releases executable binaries and demos. Full source code will be released after paper acceptance. For related implementations, see Ground-Fusion and Ground-Fusion++.


    1. Prerequisites & Installation

    ROS1 vs ROS2 — which to choose?

    ROS1 NoeticROS2 Humble
    OSUbuntu 20.04Ubuntu 22.04
    Packagev0.1.3 (includes paper + UFO profiles)v0.2.2
    InstallDocker or NativeSame paths — pick the ROS2 image or deps script
    DataROS1 bags (rosbag play)ROS2 bags (ros2 bag play)
    ProfilesAll five benchmarks + UFO (visual_life)Any YAML profile — point topics at your ROS2 drivers (M3DGR example)
    Docs§2.1–2.2 · §2.4 UFO§2.3 · ros2 guide

    [!TIP] First time? Start with ROS1 v0.1.3 for the full benchmark suite and UFO profiles. Choose ROS2 v0.2.2 when your drivers or recordings are already on Humble.

    The paper release is v0.1.0 and v0.1.1 introduced Ultra-Fusion-Omni. The latest ROS1 package is v0.1.3. It is based on v0.1.2, retains the existing profiles and opt-in map PCD workflow, and improves D360/UFO multi-camera replay stability.


    Docker installation (recommended) ⭐

    Docker images ship only the ROS/runtime stack (middleware, RViz, Ceres, yaml-cpp, system libraries). Install the Ultra-Fusion .deb inside the container after starting it.

    Step 1 — Clone this repository (mounted as /workspace in the container)

    git clone https://github.com/sjtuyinjie/Ultra-Fusion.git
    cd Ultra-Fusion
    
    ROS1 Noetic (Ubuntu 20.04)

    Step 2 — Pull the image

    # Alibaba Cloud ACR (recommended in China):
    docker pull registry.cn-hangzhou.aliyuncs.com/bit_robot_image/ultrafusion:0.1.0
    
    # Docker Hub:
    docker pull maotiandocker/ultrafusion:0.1.0
    
    # Or build locally:
    docker build -t ultrafusion:0.1.0 .
    

    Step 3 — Start a container (RViz GUI enabled)

    Add -v /media:/media:ro if your rosbags live under /media on the host.

    xhost +local:docker
    
    docker run --rm -it --net=host --ipc=host \
      -e DISPLAY="${DISPLAY}" \
      -e QT_X11_NO_MITSHM=1 \
      -v /tmp/.X11-unix:/tmp/.X11-unix:rw \
      -v /media:/media:ro \
      -v "$(pwd)":/workspace \
      registry.cn-hangzhou.aliyuncs.com/bit_robot_image/ultrafusion:0.1.0
    

    Step 4 — Install Ultra-Fusion

    cd /workspace
    ./scripts/install_ultrafusion_deb.sh   # add --mirror if GitHub is slow
    source /opt/ros/noetic/setup.bash
    

    Step 5 — Verify

    which uf_node
    rviz -d /opt/ultrafusion/rviz/lio.rviz
    

    Proceed to §2 Running Ultra-Fusion.

    ROS2 Humble (Ubuntu 22.04)

    Same CMake-based uf_node runtime as ROS1; no colcon build is needed with the prebuilt .deb.

    The published runtime image remains 0.2.1; the installer now installs the 0.2.2 Debian package inside it. No 0.2.2 Docker image is claimed yet.

    StepCommand
    1. Pull imagedocker pull maotiandocker/ultrafusion-ros2:0.2.1 (ACR: registry.cn-hangzhou.aliyuncs.com/bit_robot_image/ultrafusion-ros2:0.2.1)
    2. Start containerSee block below
    3. Install .deb./scripts/install_ultrafusion_ros2_deb.sh
    4. Source ROS2source /opt/ros/humble/setup.bash
    5. Run§2.3
    xhost +local:docker
    
    docker run --rm -it --net=host --ipc=host \
      -e DISPLAY="${DISPLAY}" \
      -e QT_X11_NO_MITSHM=1 \
      -v /tmp/.X11-unix:/tmp/.X11-unix:rw \
      -v /media:/media:ro \
      -v "$(pwd)":/workspace \
      maotiandocker/ultrafusion-ros2:0.2.1
    
    cd /workspace
    ./scripts/install_ultrafusion_ros2_deb.sh
    source /opt/ros/humble/setup.bash
    

    Image digests and troubleshooting: docs/ros2_humble_m3dgr.md.


    Native installation

    For hosts that run Ultra-Fusion directly without Docker.

    ROS1 Noetic (Ubuntu 20.04)

    Step 1 — Clone and install dependencies

    git clone https://github.com/sjtuyinjie/Ultra-Fusion.git
    cd Ultra-Fusion
    ./scripts/install_native_deps.sh
    

    Installs ROS Noetic, PCL/OpenCV/Eigen, and builds Ceres 2.1.0 and yaml-cpp 0.8.0.

    Step 2 — Install Ultra-Fusion

    ./scripts/install_ultrafusion_deb.sh   # add --mirror if GitHub is slow
    

    Step 3 — Source ROS (required in every new shell)

    source /opt/ros/noetic/setup.bash
    

    Step 4 — Verify

    which uf_node
    rviz -d /opt/ultrafusion/rviz/lio.rviz
    

    Proceed to §2 Running Ultra-Fusion.

    ROS2 Humble (Ubuntu 22.04)

    Dependencies mirror Dockerfile.ros2.

    Step 1 — Clone and install dependencies

    git clone https://github.com/sjtuyinjie/Ultra-Fusion.git
    cd Ultra-Fusion
    ./scripts/install_native_ros2_deps.sh
    

    Installs ROS2 Humble, PCL/OpenCV/Eigen, rosbags, and builds Ceres 2.1.0 and yaml-cpp 0.8.0.

    Step 2 — Install Ultra-Fusion ROS2 package

    ./scripts/install_ultrafusion_ros2_deb.sh   # add --mirror if GitHub is slow
    

    Step 3 — Source ROS2 (required in every new shell)

    source /opt/ros/humble/setup.bash
    

    Step 4 — Verify

    which uf_node
    rviz2 -d /opt/ultrafusion/rviz/lio_ros2.rviz
    

    Proceed to §2.3 ROS2 runtime.


    Installed files

    ROS1 package (ultrafusion_*.deb):

    PathDescription
    /opt/ultrafusion/bin/uf_nodeMain executable
    /usr/bin/uf_node, /usr/bin/uf-nodeCLI shortcuts
    /opt/ultrafusion/config/m3dgrM3DGR profiles
    /opt/ultrafusion/config/m2pM2DGR-Plus profile
    /opt/ultrafusion/config/lvigMARS-LVIG profile
    /opt/ultrafusion/config/kaistKAIST profile
    /opt/ultrafusion/config/groundtourGrandTour profile
    /opt/ultrafusion/config/visual_lifeUFO reference profile—omni multi-camera LVIO (D360), included in v0.1.3
    /opt/ultrafusion/rviz/lio.rvizDefault RViz layout

    ROS2 package (ultrafusion-ros2_*.deb):

    PathDescription
    /opt/ultrafusion/bin/uf_nodeMain executable (ROS2 runtime)
    /opt/ultrafusion/bin/uf_ros2_adapterROS2 topic adapter
    /usr/bin/uf_node, /usr/bin/uf-ros2-adapterCLI wrappers
    /opt/ultrafusion/config/m3dgr/uf_m3dgr_ros2_*.yamlROS2 YAML profiles
    /opt/ultrafusion/rviz/lio_ros2.rvizRViz2 layout

    2. Run on Benchmarks & Your Device

    Each uf_node <shortcut> maps to a YAML under /opt/ultrafusion/config/. You can also pass a path directly: uf_node /path/to/config.yaml.

    RuntimeSource ROSPlay dataLaunchRViz
    ROS1source /opt/ros/noetic/setup.bashrosbag play … --clockuf_node <shortcut>rviz -d /opt/ultrafusion/rviz/lio.rviz
    ROS2source /opt/ros/humble/setup.bashros2 bag play … --clockuf_node /path/to/config.yamlrviz2 -d /opt/ultrafusion/rviz/lio_ros2.rviz

    ROS1 three-terminal workflow:

    TerminalCommand
    1roscore
    2rosbag play /path/to/your.bag --clock
    3uf_node <shortcut>

    §2.1–2.2 walk through ROS1 benchmarks; §2.3 covers the ROS2 runtime; §2.4 introduces Ultra-Fusion-Omni (UFO) for omnidirectional multi-camera rigs.

    2.1 M3DGR (ROS1)

    Wheeled benchmark with real and simulated sensor-degradation sequences. Download rosbags from the M3DGR sequence table, then launch:

    # Terminal 1
    roscore
    
    # Terminal 2
    rosbag play /media/path/to/your.bag --clock
    
    # Terminal 3
    uf_node m3dgr                  # default (= m3dgr_standard)
    # uf_node m3dgr_standard       # standard LVWIO profile
    # uf_node m3dgr_image_enhance  # stronger visual coupling
    

    Released profiles:

    CommandConfigRecommended sequences
    uf_node m3dgr.../m3dgr/uf_m3dgr_standard.yamlDefault M3DGR profile (alias of m3dgr_standard)
    uf_node m3dgr_standard.../m3dgr/uf_m3dgr_standard.yamlDynamic01, Varying-illu01, Dark01, Occlusion01
    uf_node m3dgr_image_enhance.../m3dgr/uf_m3dgr_image_enhance.yamlCorridor01, GNSS-denial01, Longtime01, Longtime02

    Legacy aliases uf_node m3dgr_01 and uf_node m3dgr_02 remain supported.

    Expected output (M3DGR) — live LiDAR map + trajectory in RViz:

    2.2 Other datasets (ROS1)

    Additional shortcuts for cross-platform reproducibility. Download rosbags first, then run the matching command. Sequences not listed may need parameter retuning.

    DatasetPlatformDownloaddemo sequences
    M2DGR-PlusWheeled groundSequence tableBridge_01, Bridge_02
    MARS-LVIGAerial UAVGoogle Drive rosbagsHKairport01–03, AMtown/AMvalley, HKisland
    KAIST Complex UrbanUrban drivingLiDAR + Stereo downloadurban25, urban35 (request access on the page)
    GrandTourLegged robotrosbag downloadSPX-2, SNOW-2, EIG-1
    CommandConfigRecommended sequences
    uf_node m2p.../m2p/uf_m2p.yamlM2DGR-Plus bridge1-style LVWIO
    uf_node lvig.../lvig/uf_lvig.yamlMARS-LVIG HKairport01 LVIO
    uf_node kaist.../kaist/uf_kaist.yamlKAIST urban25, urban35
    uf_node groundtour.../groundtour/uf_groundtour.yamlGrandTour SPX-2, SNOW-2, EIG-1

    Expected output (other datasets) — compare your RViz playback with:

    2.3 ROS2 Humble runtime

    The ROS2 Humble runtime uses the same uf_node + YAML workflow as ROS1: ros2 bag play (or live topics) and RViz2 for visualization. v0.2.2 includes LIO, LWIO, LVWIO, VIO, and VIWO profiles plus opt-in map PCD export. Any ROS2 dataset works once topics match a profile—copy a released YAML, edit common.* fields, and launch.

    Requires ROS2 install (Docker or Native).

    Two-terminal workflow:

    TerminalCommand
    1source /opt/ros/humble/setup.bash → uf_node /path/to/config.yaml --ros-args -p use_sim_time:=true
    2ros2 bag play /path/to/your_ros2_bag --clock

    Optional RViz2: rviz2 -d /opt/ultrafusion/rviz/lio_ros2.rviz (fixed frame: world).

    Adapt your own ROS2 data:

    cp /opt/ultrafusion/config/m3dgr/uf_m3dgr_ros2_lvwio.yaml /tmp/my_ros2.yaml
    # edit common.imu_topic, lid_topic, image topics, extrinsics, fusion switches
    uf_node /tmp/my_ros2.yaml
    

    Released ROS2 profiles live under /opt/ultrafusion/config/m3dgr/uf_m3dgr_ros2_*.yaml. To adapt a profile to your topics: §3.

    Example: M3DGR on ROS2

    M3DGR ships as ROS1 bags. Use the converter script to produce a ROS2 bag with standard common topics, then replay with any ROS2 profile that matches:

    python3 -m pip install --user rosbags
    
    python3 scripts/convert_m3dgr_ros1_to_ros2_common.py \
      --src /media/path/to/M3DGR/Grass01.bag \
      --dst /tmp/grass01_20s_ros2 \
      --duration 20 \
      --overwrite
    
    source /opt/ros/humble/setup.bash
    uf_node /opt/ultrafusion/config/m3dgr/uf_m3dgr_ros2_lvwio.yaml \
      --ros-args -p use_sim_time:=true
    
    source /opt/ros/humble/setup.bash
    ros2 bag play /tmp/grass01_20s_ros2 --clock
    

    Verify:

    rviz2 -d /opt/ultrafusion/rviz/lio_ros2.rviz
    ros2 topic echo /curr_cloud --once --field width
    ros2 topic echo /result_lidar_path --once --field header.frame_id
    

    Full-bag conversion, expected topics, and release checklist: docs/ros2_humble_m3dgr.md.

    2.4 Ultra-Fusion-Omni (UFO)

    Ultra-Fusion-Omni (UFO) is the omnidirectional release line of Ultra-Fusion (v0.1.1, ROS1 Noetic). It extends the paper stack with multi-camera LVIO for platforms whose vision and LiDAR are both 360° — full surround coverage instead of a single forward-looking camera.

    The public reference is Computer Vision Life D360: three fisheye cameras + Livox Mid-360 + IMU. Use the same workflow to adapt your own omni (or multi-camera) rig: copy a profile, map topics / calibration / extrinsics, then launch uf_node. Full walkthrough: docs/visual_life_d360.md. Field-by-field adaptation: §3.

    StepAction
    DownloadD360 bag (Baidu Netdisk), extraction code: thce
    Installv0.1.3 .deb from GitHub Releases (includes the UFO profiles introduced in v0.1.1)
    Configurecp -a /opt/ultrafusion/config/visual_life /tmp/my_rig — edit topics, camera*.yaml, multi_camera.modules[]
    Runuf_node visual_life or uf_node /path/to/config.yaml
    VerifyRViz fixed frame world; /result_path, /curr_cloud, /feature_reproject_cloud, /colored_lidar_cloud

    Multi-camera: set use_multi_camera: true and one multi_camera.modules[] entry per stream.

    3. Adapt to Your Device & Platform

    This section is the how-to for bringing Ultra-Fusion onto your own hardware — wheeled, legged, or aerial; single-camera, RGB-D, or omni multi-camera. Released shortcuts only alias YAML under /opt/ultrafusion/config/; adapting means copying the closest profile and rewriting it for your sensors, topics, calibration, and platform.

    Recommended adaptation flow:

    1. Pick a starting profile — same platform / sensor suite as yours (e.g. m3dgr for wheeled RGB-D + LiDAR; visual_life / UFO for 360° multi-camera + LiDAR; groundtour for legged; lvig for aerial).
    2. Copy the whole profile directory — keep camera-intrinsic files next to the main YAML (relative paths). Do not invent a minimal YAML; the runtime expects the full field set at startup.
    3. Map ROS topics — point common.* at your drivers (§3.1).
    4. Choose fusion mode — enable the sensors you actually have (§3.1).
    5. Fill intrinsics & extrinsics — cameras (§3.2), body–sensor transforms (§3.4); optional GNSS (§3.3).
    6. Set timing / online calibration — only if you need them (§3.5).
    7. Launch and verify — RViz trajectory / map topics; restart uf_node after every YAML edit.

    Omnidirectional multi-camera example (D360): §2.4 UFO, docs/visual_life_d360.md.

    WORK=/tmp/uf_config
    mkdir -p "$WORK"
    cp -a /opt/ultrafusion/config/m3dgr "$WORK"/   # or visual_life, groundtour, …
    
    CFG="$WORK/m3dgr/uf_m3dgr_standard.yaml"
    ${EDITOR:-nano} "$CFG"
    
    roscore &
    sleep 3
    uf_node "$CFG" &
    rosbag play /media/path/to/your.bag --clock
    

    uf_node reads YAML only at startup — restart it after any config change.

    3.1 Fusion modes

    Match the estimator to your sensor suite. Keep imu: 1 for the modes below. Visual sensing is selected by use_image. use_gf_standalone_vio is not the UF visual switch: in the current runtime it only selects the Ground-Fusion standalone backend for pure VIO (use_lidar: 0, use_image: 1, wheel: 0). Ultra-Fusion also has its own native VIO/VIWO/LVIO/LVWIO path; keep use_gf_standalone_vio: false for those UF modes.

    Target modeuse_lidaruse_imagewheeluse_gf_standalone_vioRuntime path
    UF lvwio111falseNative UF LiDAR + visual + wheel
    UF lvio110falseNative UF LiDAR + visual
    UF vio010falseNative UF standalone VIO (UFVIO)
    GF standalone vio010trueGround-Fusion standalone VIO baseline
    UF viwo011falseNative UF standalone visual + wheel
    UF wio001ignoredNative UF standalone wheel + IMU
    UF lio100ignoredLiDAR + IMU
    UF lwio101ignoredLiDAR + wheel + IMU

    Set depth: 1 only for RGB-D visual profiles that really provide the configured depth image; use depth: 0 for monocular RGB visual profiles. use_lidar_reproject only matters for LiDAR+visual profiles, so keep the copied profile's value unless you are intentionally evaluating that coupling. use_planar_wheel_factor selects the planar wheel factor model; keep the released profile's value unless you are intentionally comparing it with the legacy wheel-pose factor.

    Sensor topics for your drivers go in common:

    common:
      imu_topic: /camera/imu
      lid_topic: /livox/mid360/lidar
      wheel_topic: /odom
      image0_topic: /camera/color/image_raw/compressed
      image1_topic: /camera/aligned_depth_to_color/image_raw
    

    3.2 Camera intrinsics

    Point the profile at your camera calibration files. Intrinsics are not stored in the main UF YAML — the main YAML references camodocal/OpenCV calibration YAMLs:

    cam0_calib: "color.yaml"
    cam1_calib: "color.yaml"
    

    cam0_calib is the primary visual camera file. The runtime loads it as <directory-of-main-config>/<cam0_calib>, so keep the calibration file next to the copied main YAML or preserve the released config directory layout as in the copy example above. In the current runtime this field is treated as a path relative to the main config directory; an absolute path will still be prefixed by that directory.

    The released visual profiles use PINHOLE or KANNALA_BRANDT camera models:

    %YAML:1.0
    ---
    model_type: PINHOLE
    camera_name: camera
    image_width: 640
    image_height: 480
    distortion_parameters:
      k1: 0.0
      k2: 0.0
      p1: 0.0
      p2: 0.0
      k3: 0.0
    projection_parameters:
      fx: 607.79772949218
      fy: 607.83526613281
      cx: 328.79772949218
      cy: 245.53321838378
    

    For KANNALA_BRANDT, use projection_parameters fields mu, mv, u0, v0, k2, k3, k4, and k5, following the released fisheye-style calibration files. cam1_calib is only used when the runtime is configured for the two-camera path; for the current single-camera/RGB-D public profiles, keep it consistent with the released template. RGB-D depth input is controlled by depth: 1 and common.image1_topic, not by giving the depth image its own camera-intrinsic YAML.

    Multi-camera rigs use multi_camera.modules[].cam_calib instead of cam0_calib — see docs/visual_life_d360.md.

    3.3 GNSS fusion

    Enable GNSS only if your platform / bag provides the measurements. GNSS is independent of the LiDAR/visual/wheel mode switches. UF estimator paths can add raw GNSS pseudorange/Doppler factors and position-only sensor_msgs/NavSatFix factors when the bag provides the required topics. The GF standalone VIO backend receives raw GNSS only; position-only GNSS fixes are not consumed by that backend.

    Use caseMain fieldsNotes
    Disable GNSSgnss_enable: 0No GNSS subscribers are started
    Raw GNSSgnss_enable: 1, gnss_raw_enable: true, gnss_position_enable: falseRequires range measurements plus ephemeris/iono topics
    Position-only GNSSgnss_enable: 1, gnss_raw_enable: false, gnss_position_enable: trueUses sensor_msgs/NavSatFix in UF estimator paths
    Raw + position GNSSgnss_enable: 1, gnss_raw_enable: true, gnss_position_enable: trueUse only when both measurement types are available

    Typical GNSS topic and lever-arm fields:

    gnss_meas_topic: /ublox_driver/range_meas
    gnss_position_topic: /ublox_driver/receiver_lla
    gnss_ephem_topic: /ublox_driver/ephem
    gnss_glo_ephem_topic: /ublox_driver/glo_ephem
    gnss_iono_params_topic: /ublox_driver/iono_params
    
    gnss_use_antenna_extrinsic: false
    gnss_antenna_in_body: [0.0, 0.0, 0.0]
    

    If gnss_use_antenna_extrinsic is true, gnss_antenna_in_body is the antenna position in the estimator body/IMU frame. Do not enable raw GNSS without the matching ephemeris topics; use position-only GNSS in a UF estimator profile or leave GNSS off.

    3.4 Extrinsics

    Fill your body–sensor mounts under mapping. Ultra-Fusion uses T_A_B to mean "transform a point from frame B into frame A":

    p_A = R_A_B * p_B + t_A_B
    

    Rotation arrays are row-major 3x3 matrices, and translations are in meters.

    YAML fieldsTransformMeaning
    extrinsic_T, extrinsic_RT_I_LLiDAR frame L to IMU/body frame I
    extrinsic_TIC, extrinsic_RICT_I_CCamera frame C to IMU/body frame I
    extrinsic_TCL, extrinsic_RCLT_C_LLiDAR frame L to camera frame C
    extrinsic_TOL, extrinsic_ROLT_O_LLiDAR frame L to wheel/odometer frame O
    extrinsic_TIO, extrinsic_RIOT_I_OWheel/odometer frame O to IMU/body frame I

    Runtime priority:

    Runtime transformHow UF obtains it
    T_I_LAlways reads mapping.extrinsic_T/R
    T_I_CUses mapping.extrinsic_TIC/RIC if present; otherwise computes T_I_L * inverse(T_C_L) from extrinsic_TCL/RCL
    T_C_LIf T_I_C is present, UF also derives internal T_C_L = inverse(T_I_C) * T_I_L
    T_I_OUses explicit mapping.extrinsic_TIO/RIO if present; otherwise computes T_I_L * inverse(T_O_L) from extrinsic_TOL/ROL

    There is no public YAML flag named estimate_wheel_extrinsic. To change the wheel extrinsic, provide extrinsic_TIO/RIO directly or provide a correct extrinsic_TOL/ROL so UF can derive T_I_O.

    3.5 Calibration & delays

    Start with fixed calibration on a new device; turn on online estimation only after topics and extrinsics look sane. For fixed calibration, keep both visual online-calibration flags at zero:

    estimate_extrinsic: 0
    estimate_td: 0
    td: 0.0
    

    In the current runtime, estimate_extrinsic and estimate_td are treated as a joint online camera-IMU calibration request: any nonzero value starts the T_I_C + td calibration state machine after the visual feature and motion excitation gates pass. The state machine first commits T_I_C, then enters the visual delay (td) stage. Therefore estimate_td: 1 alone should not be read as an isolated delay-only mode. This state machine is driven in the UF LiDAR/visual processing path; pure UF standalone VIO/VIWO and GF standalone VIO keep their T_I_C and td parameter blocks fixed in the solver.

    FieldScopeCode behavior
    estimate_extrinsicCamera-IMU0 does not request online visual calibration by itself; nonzero requests the joint T_I_C + td state machine
    estimate_tdVisual timing0 does not request online visual calibration by itself; nonzero also requests the same T_I_C + td state machine
    tdVisual timingVisual state time uses image_timestamp + td
    common.img_time_offsetROS image stampAdded to the ROS image timestamp before visual buffering; this is separate from td
    wheel_initial_tdWheel timingWheel state time uses wheel_timestamp + wheel_initial_td
    TimeSync.initial_lidar_to_imu_dt_secLiDAR-IMU timingInitial LiDAR-to-IMU time offset
    TimeSync.enable_lidar_imu_online_dtLiDAR-IMU timingEnables online LiDAR-IMU time-offset estimation

    The current public configs use wheel_initial_td for wheel timing. Legacy fields such as estimate_td_wheel and td_wheel are not the public switch for wheel-delay calibration.

    LiDAR-IMU online extrinsic calibration is configured separately:

    lidar_imu_calib:
      enable: false
      enable_lock_result: true
      freeze_after_locked_result: true
      apply_locked_result_to_slam: false
    

    This LiDAR-IMU calibrator estimates the rotation part of T_I_L. Locked rotation results affect SLAM only when apply_locked_result_to_slam: true; the LiDAR-IMU translation used by SLAM remains the YAML translation unless you edit the config.

    When checking a new profile, inspect the startup log lines for Opti_TIC, Opti_TIO, td, wheel td, GNSS status, and LiDAR-IMU time sync. A smooth but biased trajectory is often a frame or time-offset error, not just solver tuning.

    3.6 Map PCD export

    ROS1 v0.1.2 and later, and ROS2 v0.2.2, can save LiDAR world-cloud keyframes and merge them into one map.pcd. The feature is opt-in; every released profile ships with enable: false so a normal run creates no map directory or service.

    map_pcd:
      enable: false
      output_directory: "/tmp/Ultrafusion"
      translation_threshold_m: 2.0
      rotation_threshold_deg: 30.0
      service_name: "/ultrafusion/generate_map_pcd"
    

    Set enable: true in a copied profile. The first keyframe is saved immediately; later keyframes are saved when translation reaches 2 m or rotation reaches 30 degrees with the defaults. Change both thresholds and the output directory in YAML if needed.

    Call the Trigger service before shutting down the node:

    # ROS1
    rosservice call /ultrafusion/generate_map_pcd
    
    # ROS2
    ros2 service call /ultrafusion/generate_map_pcd std_srvs/srv/Trigger '{}'
    

    Individual PCDs are written to <output_directory>/keyframes/keyframe_*.pcd; the service creates <output_directory>/map.pcd.


    4. Qualitative Results

    4.1 Robustness Under Degradation

    4.2 Cross-Platform Results

    For full-scene playback demos, see Expected output in §2.1 and §2.2.


    5. License & Acknowledgements

    This project is licensed under the MIT License. If you find this project useful, please cite:

    @article{tian2026ultra,
      title={Ultra-Fusion: A Resilient Tightly-Coupled Multi-Sensor Fusion SLAM Framework under Sensor Degradation and Spatiotemporal Perturbation for Intelligent Transportation Systems},
      author={Tian, Yihong and Zhang, Junjie and Li, Liuyang and Zhang, Deteng and Zuo, Yunfei and Yin, Jie},
      journal={arXiv preprint arXiv:2606.21223},
      year={2026}
    }
    

    Please also consider citing our previous works related to this project:

    
    @article{zhang2025towards,
      author={Zhang, Deteng and Zhang, Junjie and Sun, Yan and Li, Tao and Yin, Hao and Xie, Hongzhao and Yin, Jie},
      booktitle={2025 IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS)}, 
      title={Towards Robust Sensor-Fusion Ground SLAM: A Comprehensive Benchmark and A Resilient Framework}, 
      year={2025},
      volume={},
      number={},
      pages={8894-8901},
      doi={10.1109/IROS60139.2025.11247507}}
    
    
    @inproceedings{yin2024ground,
      title={Ground-fusion: A low-cost ground slam system robust to corner cases},
      author={Yin, Jie and Li, Ang and Xi, Wei and Yu, Wenxian and Zou, Danping},
      booktitle={2024 IEEE International Conference on Robotics and Automation (ICRA)},
      pages={8603--8609},
      year={2024},
      organization={IEEE}
    }
    @article{yin2021m2dgr,
      title={M2dgr: A multi-sensor and multi-scenario slam dataset for ground robots},
      author={Yin, Jie and Li, Ang and Li, Tao and Yu, Wenxian and Zou, Danping},
      journal={IEEE Robotics and Automation Letters},
      volume={7},
      number={2},
      pages={2266--2273},
      year={2021},
      publisher={IEEE}
    }
    

    This work is self-funded. Thanks to Tianbao Zhang for providing computation resources. For maintenance, collaboration, or business inquiries, contact [email protected] and [email protected].

    6.Star History