Skip to content

Add Normal Distributions Transform (NDT) registration#7517

Open
Xiang-Zeng wants to merge 2 commits into
isl-org:mainfrom
Xiang-Zeng:feature/ndt-registration
Open

Add Normal Distributions Transform (NDT) registration#7517
Xiang-Zeng wants to merge 2 commits into
isl-org:mainfrom
Xiang-Zeng:feature/ndt-registration

Conversation

@Xiang-Zeng

@Xiang-Zeng Xiang-Zeng commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Type

  • Bug fix (non-breaking change which fixes an issue): Fixes #
  • New feature (non-breaking change which adds functionality). Resolves #
  • Breaking change (fix or feature that would cause existing functionality to not work as expected) Resolves #

Motivation and Context

Open3D provides ICP, Colored ICP, Generalized ICP, RANSAC, and FGR registration
pipelines, but does not currently expose a 3D Normal Distributions Transform
(NDT) registration method. NDT is a common LiDAR / point-cloud registration
method that optimizes a source-to-target rigid transform against voxelized
Gaussian target distributions instead of nearest-neighbor point
correspondences.

Upstream check:

  • Local source search under cpp, python, docs, and examples found no
    existing NDT registration implementation.
  • GitHub API search for active Open3D PRs matching NDT registration returned
    total_count: 0 on 2026-07-08.

Checklist:

  • I have run python util/check_style.py --apply to apply Open3D code style
    to my code.
  • This PR changes Open3D behavior or adds new functionality.
    • Both C++ (Doxygen) and Python (Sphinx / Google style) documentation is
      updated accordingly.
    • I have added or updated C++ and / or Python unit tests OR included test
      results
      (e.g. screenshots or numbers) here.
  • I will follow up and update the code if CI fails.
  • For fork PRs, I have selected Allow edits from maintainers.

Description

This PR adds a legacy CPU registration API:

  • NormalDistributionsTransformOption
  • RegistrationNDT
  • Python binding: open3d.pipelines.registration.registration_ndt

The implementation builds a target voxel Gaussian map once per registration
call, accepts either center-voxel or six-neighbor voxel residuals, regularizes
small covariance eigenvalues, rejects residuals by squared Mahalanobis distance,
and solves the rigid update using Open3D's existing Eigen SE(3) utilities.

The returned RegistrationResult includes fitness, Euclidean RMSE against the
accepted voxel means, the estimated transform, and representative target-point
indices for accepted voxel residuals.

This implementation is based on the Normal Distributions Transform (NDT) registration algorithm originally proposed by Biber and Straßer [1]. The concrete implementation follows the open‑source reference code by Gao [2], while being adapted to Open3D's registration API and coding style.

[1] P. Biber and W. Straßer, "The Normal Distributions Transform: A New Approach to Laser Scan Matching," Proceedings of the 2003 IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS 2003), vol. 3, pp. 2743–2748, IEEE, 2003.
[2] Xiang Gao, SLAM Technology in Autonomous Driving and Robotics: From Theory to Practice (in Chinese), Publishing House of Electronics Industry, 2023. Code available at: https://github.com/gaoxiang12/slam_in_autonomous_driving/blob/master/src/ch7/ndt_3d.cc

Added:

  • C++ tests for invalid option validation, synthetic known-transform recovery,
    and improvement over initial alignment.
  • Python tests for option binding, synthetic known-transform recovery, and
    invalid option validation.
  • Python example: examples/python/pipelines/ndt_registration.py
  • Tutorial page: docs/tutorial/pipelines/ndt_registration.rst

Local verification:

env -u https_proxy -u http_proxy -u HTTPS_PROXY -u HTTP_PROXY \
  /home/qi/.local/bin/cmake -S . -B build \
  -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
  -DBUILD_UNIT_TESTS=ON \
  -DBUILD_PYTHON_MODULE=ON \
  -DBUILD_CUDA_MODULE=OFF \
  -DBUILD_SYCL_MODULE=OFF \
  -DBUILD_ISPC_MODULE=OFF \
  -DBUILD_GUI=OFF \
  -DBUILD_WEBRTC=OFF \
  -DBUILD_EXAMPLES=OFF \
  -DBUILD_BENCHMARKS=OFF \
  -DBUILD_SHARED_LIBS=OFF

env -u https_proxy -u http_proxy -u HTTPS_PROXY -u HTTP_PROXY \
  /home/qi/.local/bin/cmake --build build --target tests pybind --parallel 2

./build/bin/tests --gtest_filter='*NormalDistributionsTransform*'
# [  PASSED  ] 3 tests.

PYTHONPATH=/home/qi/ws/ndt/Open3D/build/lib/python_package \
  python3 -m pytest python/test/pipelines/test_normal_distributions_transform.py -q
# 3 passed

python3 -m py_compile \
  python/test/pipelines/test_normal_distributions_transform.py \
  examples/python/pipelines/ndt_registration.py

Real-data validation: examples/python/pipelines/ndt_registration.py

The Python test was run against the local build package via PYTHONPATH; no
global Open3D package was installed or overwritten.

@Xiang-Zeng Xiang-Zeng changed the title Add Normal Distributions Transform registration Add Normal Distributions Transform (NDT) registration Jul 10, 2026
@Xiang-Zeng
Xiang-Zeng force-pushed the feature/ndt-registration branch 2 times, most recently from 5e0123d to cc0e43c Compare July 10, 2026 15:36
@ssheorey

Copy link
Copy Markdown
Member

Hi @Xiang-Zeng thanks for submitting this great new feature!
Please take a look at the failing CI checks (please ignore if they are due to unrelated changes - the main branch is in some major refactoring at the moment).
Also please provide the citation of the paper that is implemented here (add to docs and also here in the PR).

@ssheorey ssheorey added this to the v0.21 milestone Jul 11, 2026
@ssheorey ssheorey added the status / needs info Waiting for information from reporter / author label Jul 11, 2026
@Xiang-Zeng

Xiang-Zeng commented Jul 12, 2026

Copy link
Copy Markdown
Contributor Author

Hi @ssheorey ,
Thank you for the positive feedback! I will go through the failing CI checks and separate issues caused by this PR.
The Codacy/Cppcheck warnings about missing #include files (e.g., <Eigen/Core>, , ) seems to be false positives.
Some remaining failures appear to be related to GitHub attestation/OIDC permissions in forked PR workflows (Run actions/attest@v4 Error: missing "id-token" permission. Please add "permissions: id-token: write" to your workflow.).
I added the paper citation to the documentation and updated the PR description.

@Xiang-Zeng
Xiang-Zeng force-pushed the feature/ndt-registration branch from b9f2576 to 131ebe5 Compare July 13, 2026 04:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status / needs info Waiting for information from reporter / author

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants