Skip to main content
Commerge: Communication-Efficient Map Merging
CI Claude Code ready Codex ready
pip install commerge
Commerge on KITTI 00 split into two robots: the affinity of their SOLiD descriptors goes through step (A) sequential matching, step (B) balanced minimum vertex cover and step (C) maximum edge-weighted clique; the most consistent region's scans (magenta) are the only ones exchanged, and the transform registered from them merges the two maps.

[IJRR 2026] Commerge: Communication-Efficient, Robust, and Fast LiDAR Map Merging Framework
for Multi-Robot Coordination in Resource-Constrained Scenarios


Robots that map on their own must exchange scans to merge their maps, and over a weak link that exchange is the bottleneck. Commerge picks the few scans that carry the overlap and sends only those, in three steps:

  • 🤖 Before the steps, each robot runs its own SLAM with SOLiD: keyframe scans, poses and SOLiD descriptors, saved as a session.
  • 🔗 Step (A) Sequential matching: regions of the inter-robot affinity matrix where both robots saw the same places in sequence.
  • ⚖️ Step (B) Balanced minimum vertex cover: the fewest keyframes that still touch every candidate match, shared fairly between the robots.
  • 💎 Step (C) Maximum edge-weighted clique: among those, only the pairs that agree with each other geometrically.
  • 🤝 Exchange and merge: the robots exchange the scans of the most consistent region only; their submaps are registered (KISS-Matcher + GICP) and the transform merges the whole maps.
  • 📦 MB, not GB: up to 99.98 % less data exchanged (7,000 MB → 1.3 MB on HeLiPR) with comparable alignment, also on a Jetson Nano.

Data exchanged after each step on HeLiPR: 7,000 MB for the whole map, 60 MB after step (A), 26 MB after step (B) and 1.3 MB after step (C)


📦 Prerequisites

  • Python 3.9+. pip install commerge brings NumPy, SciPy, Matplotlib and the registration (KISS-Matcher, wheels for Python 3.9-3.12, and small_gicp).
  • Solver: Gurobi, free for academic use, as in the paper (pip install gurobipy, then grbgetkey <key>). No license? HiGHS ships with SciPy and returns the same selection, only slower on the largest regions (--solver highs; auto, the default, picks Gurobi when it is licensed).
  • One session per robot from SOLiD (thirdparty/SOLiD): keyframe scans, poses and SOLiD descriptors.

🛠️ Installation

pip install commerge          # + "commerge[gurobi]" for gurobipy, "commerge[compare]" for the AutoMerge comparison
# or from a clone, with SOLiD and KISS-Matcher as submodules:
git clone --recursive https://github.com/sparolab/Commerge.git && cd Commerge && pip install .
# KISS-Matcher from the submodule instead of the wheel: pip install thirdparty/KISS-Matcher/python
commerge --version

Ubuntu and macOS (no ROS needed for Commerge itself).

C++

The same pipeline in C++17 (cpp/): a library (commerge::commerge), the commerge_cpp command with the same options and outputs (except --plot), and Python bindings. HiGHS is built in; Gurobi and the registration (KISS-Matcher + small_gicp) are used when found.

sudo apt install libeigen3-dev libflann-dev liblz4-dev    # macOS: brew install eigen flann lz4 libomp; export OpenMP_ROOT=$(brew --prefix libomp)
cmake -S cpp -B cpp/build && cmake --build cpp/build -j    # from the clone (submodules: KISS-Matcher)
cpp/build/commerge_cpp $HOME/robot_a $HOME/robot_b --threshold 0.96 --min-area 2000 --out merged/
pip install commerge-cpp                                  # bindings (selection, HiGHS); from the clone: pip install ./cpp
import commerge_cpp as cc
sel = cc.select(affinity, pos_a, pos_b, threshold=0.96, min_area=2000)   # same selection as commerge.select
sel.keyframes_a, sel.keyframes_b, sel.pairs

Docker

docker pull ghcr.io/sparolab/commerge     # or: docker build -f docker/Dockerfile -t ghcr.io/sparolab/commerge .
docker run --rm -v $HOME/robot_a:/a -v $HOME/robot_b:/b -v $PWD/merged:/out ghcr.io/sparolab/commerge \
    commerge /a /b --threshold 0.96 --min-area 2000 --out /out --plot
# Gurobi: add -v $HOME/gurobi.lic:/opt/gurobi/gurobi.lic (otherwise HiGHS)

🚀 Run

1. One session per robot with SOLiD, with any odometry it supports (FAST-LIO, KISS-ICP, GeoRIO, …) or without ROS:

cd thirdparty/SOLiD
roslaunch solid_ros run.launch odometry:=fast_lio save_dir:=$HOME/robot_a     # ROS 1, while the bag of robot A plays
ros2 launch solid_ros run.launch.py odometry:=kiss_icp save_dir:=$HOME/robot_b  # ROS 2
python slam/common/mac/solid_loops.py --kitti <sequence> --config slam/config/kitti.yaml --out $HOME/robot_a  # no ROS

2. Select the scans to exchange, register them and merge:

commerge $HOME/robot_a $HOME/robot_b --threshold 0.96 --min-area 2000 --out merged/ --plot [--gt-a gt_a.txt --gt-b gt_b.txt]
[commerge] kitti00_a: 1011 keyframes | kitti00_b: 1701 keyframes
[commerge] steps (A)+(B)+(C), solver gurobi: (A) 4 region(s) (threshold 0.96, min area 2000) in 0.021 s
[commerge] region 2: A 250-381 x B 899-1027: (A) 1077 candidate pairs -> (B) 66+66 keyframes -> (C) 24 pairs = 14 A + 17 B scans, (B) 0.34 s, (C) 0.13 s
...
[commerge] registered B to A: 540 KISS-Matcher inliers, GICP in 1.3 s; vs ground truth: 0.35 m, 0.06 deg (B keyframes 0.15 m off on average)
[commerge] exchanged 14 A + 17 B scans (1.1 % of 2712, 4.6 MB) from region(s) [2] of 4 -> merged/

All outputs, options and the Python API: docs/GUIDE.md.

📊 Compare

commerge-compare runs Commerge, its ablations and AutoMerge on the same sessions. On KITTI 00 split into two robots, Commerge sends 31 of 2,712 scans (4.6 MB) and merges the maps within 0.35 m; AutoMerge's region sends 156 scans and merges within 1.05 m. Details and the ablations: docs/GUIDE.md.


🤖 Run with your agent

Open Claude Code or Codex in an empty folder and paste:

Clone https://github.com/sparolab/Commerge, read its AGENTS.md, and follow it to install Commerge and merge KITTI 00 split into two robots on this machine. Ask me what you need along the way.

The agent follows AGENTS.md: it installs Commerge with Gurobi or HiGHS, makes one SOLiD session per robot, selects and exchanges the scans, merges the maps, and checks the result.


💡 Tips: any sensor, any descriptor

Commerge never looks at the sensor. It needs, per robot, keyframe poses and one place descriptor per keyframe; the two robots' descriptors give an affinity (--affinity, any (N_A, N_B) .npy, higher = more similar), and steps (A), (B), (C) run on it unchanged. Without point clouds, --registration pairs merges the maps from the selected pairs alone: they are the same places, so B's keyframe positions are fitted onto A's (yaw and translation). So if your sensor has a place-recognition descriptor, Commerge merges its maps: thermal across day and night, radar through rain and fog, sonar under water, a camera...

import numpy as np
desc_a, desc_b = ..., ...                      # one descriptor per keyframe, any place-recognition method
np.save("affinity.npy", desc_a @ desc_b.T)     # cosine similarity for normalized vectors; or 1 - distance / max
commerge robot_a robot_b --affinity affinity.npy --threshold T --min-area N --registration pairs --policy all \
    --out merged/                              # robot_*: odom_poses.txt (KITTI format), one row per keyframe

Five demos split real data into two robots, move robot B into its own frame and let Commerge find it back, with maps drawn from each sensor's own points (no LiDAR). Results, how to pick --threshold / --min-area, and the commands: tools/demo.

Commerge on five sensors in turn: 4D radar (SOLiD, SNAIL-Radar), spinning radar (RadLoc, MulRan), imaging sonar (Sonar Context, Aracati 2017), thermal camera (AnyThermal, ViViD++ day vs night) and camera (MegaLoc, KITTI 00); each map is drawn from that sensor's own points, and the robots exchange a few keyframes and merge

Each sensor on its own, with its GIF, commands and result: 4D radar · radar · sonar · thermal · camera.


⚠️ Limitation: heterogeneous LiDARs

Commerge selects scans from the affinity of the two robots' descriptors. With the same LiDAR on both robots, SOLiD gives an affinity whose overlapping regions stand out. With different LiDARs (a spinning Ouster and a Livox Avia with a 70° field of view, for instance), SOLiD describes the same place differently and step (A) finds hundreds of regions with no structure. A descriptor made for heterogeneous LiDARs, such as HeLiOS or InLiER, passed with --affinity (and --enhance), brings the right region back; registering the few scans exchanged across such different fields of view is still unreliable (--registration grid is experimental). Contributions are welcome.


Citation

If you use Commerge in your research, please cite our paper.

See bibtex
@article{kim2026commerge,
  author  = {Kim, Hogyun and Choi, Jiwon and Kim, Juwon and Yang, Geonmo and Jeong, Seokhwan and Lim, Hyungtae and Cho, Younggun},
  title   = {Commerge: Communication-Efficient, Robust, and Fast LiDAR Map Merging Framework for Multi-Robot Coordination in Resource-Constrained Scenarios},
  journal = {International Journal of Robotics Research (IJRR)},
  year    = {2026}
}

Contributing

Issues and pull requests are welcome.

Acknowledgements

Commerge uses SOLiD for inter-robot place recognition. The comparison re-implements the region selection of AutoMerge, which builds on SeqSLAM. Related research: KISS-Matcher, SKiD-SLAM.

Special Thanks

We thank Minwoo Jung for the HeLiPR dataset, and Nikolaos Stathoulopoulos for InLiER, learning-free heterogeneous LiDAR place recognition.

Metadata

Release files for commerge 2.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for commerge 2.1.0
File Size Uploaded Provenance Actions
commerge-2.1.0.tar.gz 36.6 kB With provenance Details for commerge-2.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for commerge 2.1.0
File Interpreter ABI Platform Actions
commerge-2.1.0-py3-none-any.whl Python 3 none any Details for commerge-2.1.0-py3-none-any.whl

Total release size: 71.5 kB

Release files / commerge-2.1.0.tar.gz

Download URL commerge-2.1.0.tar.gz
Size 36.6 kB
Tags Source
SHA-256 checksum
How to use checksums
448812b90977a8bda3bf9bc05b54301cf00921d3f6f38f28e542865ae5ba1941
BLAKE2b-256 checksum
How to use checksums
c7532396449ea2d0e7274688385d1a646f2dca9ead5652d879d0b091b22ac048
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 11, 2026.

Transparency log

Release files / commerge-2.1.0-py3-none-any.whl

Download URL commerge-2.1.0-py3-none-any.whl
Size 34.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
79a963bf477273fe3a2572821ca33bbb0f197dfa55a31318c1bbf443dd786837
BLAKE2b-256 checksum
How to use checksums
2b5453be6dd6d9b2373954d0aa9ed21112980fc153050619cf55d258dfcab138
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 11, 2026.

Transparency log

Security for commerge 2.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for commerge-2.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 11, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

2.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page