Skip to content

feat(nuscenes/lidar-model): add nuScenes V4 converter and lidar-model estimation lib / evaluation tool#128

Merged
janickm merged 3 commits into
NVIDIA:mainfrom
janickm:issue-123-jammy-quokka
Jun 5, 2026
Merged

feat(nuscenes/lidar-model): add nuScenes V4 converter and lidar-model estimation lib / evaluation tool#128
janickm merged 3 commits into
NVIDIA:mainfrom
janickm:issue-123-jammy-quokka

Conversation

@janickm

@janickm janickm commented May 21, 2026

Copy link
Copy Markdown
Collaborator

Summary

Add a nuScenes dataset converter for NCore V4 format, a generic structured lidar model extraction library, and a lidar model evaluation tool.

image

Closes #123

Architecture

The work is split into three self-contained commits:

1. feat(data_converter): add structured lidar model extraction library

tools/data_converter/structured_lidar_model.py -- a generic, reusable library for deriving structured spinning lidar models from motion-compensated point cloud data. Designed for datasets that lack raw sensor timestamps.

Key features:

  • Composable steps: extract_column_azimuths, compute_column_alignment, assign_model_columns, compute_frame_timestamps, decompensate_frame
  • Resolution upsampling (upsample_model): interpolate column azimuths to 2x/4x for sub-column alignment precision
  • Multi-frame optimization (optimize_model): median-based correction across many frames
  • Pre-computed timestamps support: align_frame(timestamps_us=...) for sensors with known per-point timestamps
  • HDL-32E presets: spec elevations, analytical firing offsets, nominal model factory
  • 18 unit tests (no external data dependency)

2. feat(tools): add lidar model evaluation tool

tools/ncore_evaluate_lidar_model.py -- CLI tool that evaluates model quality by comparing model-predicted vs stored native directions. Works on any V4 sequence.

Outputs:

  • Numerical metrics: angular error (mean/median/p95), per-row and per-frame breakdowns, pixel-equivalent error
  • Overlay images: native (cyan) + model (red) points on camera
  • Error heatmap images: points colored by angular error magnitude
000070_overlay

3. feat(nuscenes): add nuScenes to NCore V4 converter

Full converter handling 6 cameras, 1 lidar (HDL-32E), 5 radars, 3D cuboid annotations. Uses the generic library directly (no local lidar model code).

Lidar Model Quality

Dataset Mean error (far) Pixel equiv Notes
Waymo (ground truth) 0.010 deg 0.35 px Theoretical floor
PAI (extraction) 0.028 deg ~0.5 px Factory-quality
nuScenes (4x nominal + opt) 0.029 deg 0.7 px This PR
nuScenes (1x empirical + opt) 0.083 deg 1.8 px Without resolution upsampling

Recommended config: --lidar-model-source nominal --lidar-model-resolution 4 --lidar-model-optimization-passes 1

Key Design Decisions

  1. Resolution upsampling is the dominant improvement (0.10 -> 0.03 deg). Column alignment quantization was the bottleneck.
  2. Nominal model from spec avoids circular dependency (need timestamps to decompensate, need model to derive timestamps).
  3. Analytical firing offsets (from HDL-32E timing) replace unreliable empirical measurements for ground-hitting beams.
  4. timestamps_us parameter on align_frame supports sensors with known per-point timestamps (e.g., raw PCAP data).
  5. Library lives at tools/data_converter/ level (not inside nuscenes/) for reuse by other converters.

Testing

# Unit tests (no external data)
bazel test //tools/data_converter:pytest_structured_lidar_model_3_11

# Integration test (requires nuScenes mini)
bazel test //tools/data_converter/nuscenes:pytest_converter_3_11 \
    --test_env=NUSCENES_DIR=/path/to/nuscenes/mini/v1.0-mini \
    --test_env=NUSCENES_VERSION=v1.0-mini

@copy-pr-bot

copy-pr-bot Bot commented May 21, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@janickm janickm self-assigned this May 21, 2026
@janickm janickm force-pushed the issue-123-jammy-quokka branch 19 times, most recently from f05c1db to f8deb39 Compare May 29, 2026 12:05
@janickm janickm force-pushed the issue-123-jammy-quokka branch 9 times, most recently from 988e4da to 9d2d19c Compare May 29, 2026 14:47
@janickm janickm force-pushed the issue-123-jammy-quokka branch 13 times, most recently from a08ab36 to 713b3d1 Compare June 3, 2026 15:03
Comment thread docs/conversions/nuscenes/nuscenes.rst
Comment thread docs/conversions/nuscenes/nuscenes.rst
Comment thread docs/conversions/nuscenes/nuscenes.rst
Comment thread tools/data_converter/nuscenes/converter.py
Comment thread tools/data_converter/nuscenes/converter.py
Comment thread tools/data_converter/structured_lidar_model.py Outdated
Comment thread tools/data_converter/structured_lidar_model.py Outdated
Comment thread tools/data_converter/structured_lidar_model.py Outdated
Comment thread tools/data_converter/structured_lidar_model.py Outdated
Comment thread tools/data_converter/structured_lidar_model.py
@janickm janickm force-pushed the issue-123-jammy-quokka branch 2 times, most recently from 76c9c5b to 1fc7199 Compare June 5, 2026 07:08
@janickm janickm changed the title feat(nuscenes): add nuScenes to NCore V4 converter feat(nuscenes/lidar-model): add nuScenes V4 converter and lidar-model estimation lib / evaluation tool Jun 5, 2026
@janickm janickm force-pushed the issue-123-jammy-quokka branch 3 times, most recently from 8303933 to a202ad7 Compare June 5, 2026 07:51
Comment thread tools/ncore_evaluate_lidar_model.py Outdated
Add tools/data_converter/structured_lidar_model.py -- a generic,
sensor-agnostic library for deriving structured spinning lidar models
from motion-compensated point cloud data.

Composable low-level steps:
- extract_column_azimuths: per-column median azimuth from far-range points
- compute_column_alignment: brute-force integer shift search
- assign_model_columns: 1:1 or sub-column fine-grained mapping
- compute_frame_timestamps: linear interpolation from column position
  (fencepost: col/N, not col/(N-1), next frame starts at frame_end_us)
- upsample_model: interpolate column azimuths to higher resolution to
  compensate for per-revolution azimuth drift in mechanical spinning
- optimize_model: multi-frame median correction of azimuths and offsets
- compute_model_consistency: angular error metrics
- compute_intra_column_firing_offsets: generic intra-column timing model
- derive_model_from_decompensated: empirical model from decompensated frame

High-level convenience: align_frame() orchestrates the full pipeline.
When timestamps_us is provided, uses them directly (skips column-index
approximation -- for sensors with known per-point timestamps).

HDL-32E presets included as a reference implementation.

Includes 18 unit tests (no external data dependency).
@janickm janickm force-pushed the issue-123-jammy-quokka branch 2 times, most recently from 426c6e9 to 4133f44 Compare June 5, 2026 08:50
@janickm

janickm commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator Author

/ok to test d123655

janickm added 2 commits June 5, 2026 11:18
Add ncore_evaluate_lidar_model -- a CLI tool that evaluates structured
lidar model quality by comparing model-predicted ray directions against
native directions derived from stored sensor-frame points (via compat
API: get_frame_point_cloud with motion_compensation=False).

Follows the standard tool CLI pattern: CLIBaseParams frozen dataclass,
cli() group packs into ctx.obj, v4() constructs SequenceLoaderV4 then
delegates to run(params: CLIBaseParams, loader: SequenceLoaderProtocol).

Uses StructuredLidarModel.maybe_from_parameters() + elements_to_sensor_rays()
(torch) for model direction computation.

Metrics:
- Combined angular error (mean/median/p95/max), all points and far-range
- Signed azimuth error and signed elevation error (far-range)
- Per-row and per-frame breakdowns for systematic issue detection
- Pixel-equivalent error when --camera-id is provided

Warning threshold: --warn-threshold-deg (default 0.05 deg) issues a
WARNING if mean far-range error or systematic azimuth/elevation error
exceeds the bound.

Image output (when --camera-id + --output-dir provided):
- overlay: native points (cyan) + model points (red) on camera image
- error: points colored by angular error magnitude (turbo colormap)

Sphinx docs added at docs/tools/lidar_model_eval.rst.
Add a nuScenes dataset converter (CLI: nuscenes-v4) that produces NCore
V4 format sequences. Uses the generic structured lidar model library
(tools/data_converter/structured_lidar_model.py) for all model
derivation, alignment, and optimization.

Handles:
- 6 cameras (global shutter, undistorted)
- 1 lidar (HDL-32E, motion-decompensated, structured model)
- 5 radars (Continental ARS 408, radial velocity + RCS)
- 3D cuboid annotations (world_global frame)

Lidar model pipeline (CLI flags):
- --lidar-model-source nominal|empirical (default: nominal)
- --lidar-model-resolution 1|2|4 (default: 4, sub-column alignment)
- --lidar-model-optimization-passes N (default: 1, multi-frame opt)

Nominal + 4x + 1 opt pass achieves 0.029 deg far-range angular error,
matching PAI extraction quality.

Closes NVIDIA#123
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

nuScenes and Argoverse 2 support

1 participant