#### NOTE
This is a **Hugging Face dataset**. For large datasets, ensure `huggingface_hub>=1.1.3` to avoid rate limits. Learn more in the <a href="https://docs.voxel51.com/integrations/huggingface.html#loading-datasets-from-the-hub" target="_blank">Hugging Face integration docs</a>.

<a href="https://huggingface.co/datasets/Voxel51/Hilti-SLAM-Challenge-2022" target="_blank">![Hugging Face](https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-Dataset-yellow)</a>

# Hilti SLAM Challenge 2022 → FiftyOne (Native Multimodal MCAP)

![preview](https://huggingface.co/datasets/Voxel51/Hilti-SLAM-Challenge-2022/resolve/main/hilti_slam.gif)

The [Hilti SLAM Challenge 2022](https://hilti-challenge.com/dataset-2022)
recordings, converted from ROS 1 bags to native multimodal MCAP episodes.

The recordings were made with a handheld rig called Phasma, which carries
five synchronized global-shutter cameras, a Hesai PandarXT-32 LiDAR and a
Bosch BMI085 IMU. Seven runs were walked through an active construction site
in Schaan, Liechtenstein, and nine through the Sheldonian Theatre in Oxford,
over five days in March and April 2022. Between them the runs cover
construction floors, staircases, long corridors, galleries, basements, an
attic, a cupola and the ground outside, and most of them pass through the
same place more than once.

A surveyor measured reference positions along every run, and three runs also
carry a continuous reference trajectory.

## Installation

```bash
pip install fiftyone
```

## Usage

```python
import fiftyone as fo
import fiftyone.utils.huggingface as fouh

dataset = fouh.load_from_hub(
    "Voxel51/Hilti-SLAM-Challenge-2022",
    name="Hilti-SLAM-Challenge-2022",
    persistent=True,
)
fo.launch_app(dataset)
```

The runs that carry a continuous reference trajectory:

```python
view = dataset.match({"has_dense_ground_truth": True})
```

## What you get

Sixteen runs arrive as 18 episodes and 70.7 minutes of recording. Each
episode carries:

- `/cam0` through `/cam4`, the five cameras at 720x540, as
  `foxglove.CompressedImage`
- `/cam0-calibration` through `/cam4-calibration`, the intrinsics for each
  camera, as `foxglove.CameraCalibration`
- `/lidar-points`, the LiDAR at its native 10 Hz, as
  `foxglove.PointCloud` with `x`, `y`, `z`, `intensity`, `ring` and
  `time_offset`
- `/imu.plot`, three-axis acceleration and angular rate at 400 Hz
- `/ground-truth.plot`, the reference position at each instant the release
  measured one, whether that is a surveyed mark or a pose of a continuous
  trajectory
- `/ground-truth-control-points`, the surveyed reference positions drawn
  together, as `foxglove.SceneUpdate`, labelled with the surveyor’s marker
  names
- `/ground-truth-pose`, the continuous reference trajectory, as
  `foxglove.PoseInFrame`, on the three runs that have one
- `/tf`, the rig’s frame tree, as `foxglove.FrameTransform`
- `/sequence`, naming the run

Across the whole set that comes to 212,065 camera frames, 42,408 LiDAR
sweeps holding 2.55 billion points, 1,692,948 inertial samples and 159
surveyed reference positions.

Episodes carry the fields `sequence`, `part`, `site`, `recorded`, `scene`,
`cameras`, `num_camera_frames`, `num_lidar_scans`, `num_lidar_points`,
`num_imu_samples`, `has_dense_ground_truth`, `num_ground_truth_poses`,
`num_control_points`, `num_control_points_observed`, `control_point_names`
and `duration`.

## Notes on the conversion

Camera frames are published at 10 Hz. The bags record them at 40 Hz. All
sixteen runs and all five cameras are present.

Camera frames are JPEG at quality 92. The source frames are uncompressed
8-bit greyscale.

The LiDAR’s per-point time is published as `time_offset`, in seconds
relative to the sweep. The source records it as an absolute float64
timestamp, and the point cloud format packs fields as 32-bit floats, which
quantize a value near 1.65e9 into steps of about two minutes.

The cameras are fisheye. Their four distortion coefficients are published
under the `equidistant` model name they were calibrated with.

`exp23_the_sheldonian_slam` is one continuous run stored as three bags. It
is published as three episodes that share a `sequence` value and differ in
`part`. Its surveyed positions are divided between the three by time.

Marker names come from the announcements in the recordings and are matched
to surveyed positions by time. 158 of the 159 positions carry a name. One
announced marker in `exp10_cupola_2` has no surveyed position, and one
position in `exp23_the_sheldonian_slam` part 2 was measured after the
cameras stopped.

The surveyed positions are timed, not just placed: each one is a position
at a recorded instant during the run, which is what an estimated trajectory
is scored against. They are carried on `/ground-truth.plot` at those
instants as well as drawn together in one scene. A run that passes a mark
twice records it twice, so the plot holds more observations than the scene
holds distinct points.

Reference data is expressed in the IMU frame, and sits in its own
`ground-truth` frame rather than hanging off the rig tree, since the
surveying instrument has no measured relation to the rig.

Every sensor publishes in its own frame, so each episode carries the rig’s
whole frame tree on `/tf`: the five cameras and the LiDAR against the
inertial frame, the inertial frame against the rig’s base, and the
surveying tip the marks were measured with. It is built from the release’s
own calibration, whose camera chains are inverted to hang the cameras off
the inertial frame rather than the other way round.

The `laser_scans` and `CAD` directories of the source release, and the
calibration reports beside the files `/tf` is built from, are not
reproduced here. The camera intrinsics are published with each episode.

## License & attribution

The source dataset is released under
[CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/), and
this conversion is distributed under the same license. Use is limited to
non-commercial purposes, attribution is required, and adaptations must be
distributed under the same or a compatible license.

Changes from the source: conversion from ROS 1 bags to the FiftyOne MCAP
flavor, JPEG encoding of the camera frames, camera frame rate reduced to
10 Hz, the LiDAR per-point timestamp rebased to a per-sweep offset, and the
reference positions and the calibrated frame tree carried as streams
alongside the episodes.

## Citation

```bibtex
@article{zhang2023hilti,
  author  = {Lintong Zhang and Michael Helmberger and Lanke Frank Tarimo Fu and David Wisth and Marco Camurri and Davide Scaramuzza and Maurice Fallon},
  title   = {Hilti-Oxford Dataset: A Millimeter-Accurate Benchmark for Simultaneous Localization and Mapping},
  journal = {IEEE Robotics and Automation Letters},
  volume  = {8},
  number  = {1},
  pages   = {408--415},
  year    = {2023},
  doi     = {10.1109/LRA.2022.3226077}
}
```
