This is the official PyTorch implementation of the following publication:
OPAL: Visibility-aware LiDAR-to-OpenStreetMap Place Recognition via Adaptive Radial Fusion
Shuhao Kang*, Youqi Liao*, Yan Xia†, Olaf Wysocki, Boris Jutzi, Daniel Cremers
CoRL 2025
Paper | Arxiv | Project-page
TL;DR: OPAL is a framework for point cloud localization in OpenStreetMap.
Abstract: LiDAR place recognition is a critical capability for autonomous navigation and cross-modal localization in large-scale outdoor environments. Existing approaches predominantly depend on pre-built 3D dense maps or aerial imagery, which impose significant storage overhead and lack real-time adaptability. In this paper, we propose OPAL, a novel framework for LiDAR place recognition that leverages OpenStreetMap (OSM) as a lightweight and up-to-date prior. Our key innovation lies in bridging the domain disparity between sparse LiDAR scans and structured OSM data through two carefully designed components. First, a cross-modal visibility mask that identifies observable regions from both modalities to guide feature alignment. Second, an adaptive radial fusion module that dynamically consolidates radial features into discriminative global descriptors. Extensive experiments on KITTI and KITTI-360 datasets demonstrate OPAL’s superiority, achieving 15.98% higher recall at 1 m threshold for top-1 retrieved matches, along with 12× faster inference speed compared to the state-of-the-art approach.
pip install -r requirements.txtPlease download the semantic labels for KITTI and KITTI-360, which are generated using Cylinder3D, as well as the pretrained checkpoint file and karlsruhe.osm from Google Drive.
Note: We have already prepared the processed OSM tiles in the data/ directory, so downloading the original OSM data of Karlsruhe is not required. However, if needed, you may re-generate them during training or testing.
After downloading, place the checkpoint file into the directory:
checkpoints/
Download KITTI Odometry point cloud data from KITTI website.
After extracting point clouds and labels, your layout should look like:
data_odometry_velodyne/dataset/sequences
│
├── 00
│ ├── pred_labels
│ └── velodyne
├── 01
│
├── ...
│
└── 10
Note: The KITTI raw dataset provides odometry data with GPS information. Since sequence 03 lacks GPS data, it is excluded from both training and evaluation.
Download KITTI-360 point cloud data from KITTI-360 website
After extracting:
KITTI360/data_3d_raw
│
├── 2013_05_28_drive_0000_sync
│ └── velodyne_points
│ └── data
│ └── *.bin
├── 2013_05_28_drive_0000_sync_pred
│ └── *.label
├── 2013_05_28_drive_0005_sync
├── ...
├── 2013_05_28_drive_0009_sync
└── 2013_05_28_drive_0009_sync_pred
Evaluate on KITTI dataset
python test_kitti.py --seq "00"Evaluate on KITTI-360 dataset
python test_kitti360.py --seq "2013_05_28_drive_0000_sync"python train.pyIf you find this repo helpful, please give us a star~.Please consider citing OPAL if this program benefits your project.
@article{kang2025opal,
title={Opal: Visibility-aware lidar-to-openstreetmap place recognition via adaptive radial fusion},
author={Kang, Shuhao and Liao, Martin Y and Xia, Yan and Wysocki, Olaf and Jutzi, Boris and Cremers, Daniel},
journal={arXiv preprint arXiv:2504.19258},
year={2025}
}
We thank OrienterNet, PolarNet, BoQ for their code implementation.
