Skip to content

Commit 9bebbd8

Browse files
Xiang-Zengssheorey
andauthored
Add Normal Distributions Transform (NDT) registration (#7517)
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. 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 over the returned representative target-point correspondences, 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 Eigen based implementation, parallelized with TBB. Fix main CI failures: SYCL Python version & Windows RPC port --------- Co-authored-by: Sameer Sheorey <sameer.sheorey@intel.com>
1 parent cf67052 commit 9bebbd8

19 files changed

Lines changed: 1411 additions & 27 deletions

File tree

.github/workflows/ubuntu-sycl.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,13 @@ jobs:
171171
# We execute docker buildscript with python version argument.
172172
docker/docker_build.sh sycl-shared py${{ matrix.python_version }}
173173
174+
# Wheel produced by the Docker build matches the matrix Python version
175+
# via -DPython3_EXECUTABLE in Dockerfile.ci. Keep only that wheel.
176+
PYTHON_ABI="cp${PYTHON_VERSION/./}"
177+
find . -maxdepth 1 -name 'open3d*.whl' \
178+
! -name "*${PYTHON_ABI}-${PYTHON_ABI}-*.whl" -delete
179+
compgen -G "open3d*${PYTHON_ABI}-${PYTHON_ABI}-*.whl" > /dev/null
180+
174181
- name: Docker test (Python)
175182
run: docker/docker_test.sh sycl-shared python
176183

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
- Fix macOS arm64 builds, add CI runner for macOS arm64 (PR #6695)
5858
- Fix KDTreeFlann possibly using a dangling pointer instead of internal storage and simplified its members (PR #6734)
5959
- Fix RANSAC early stop if no inliers in a specific iteration (PR #6789)
60+
- Add 3D Normal Distributions Transform registration with C++ and Python APIs (PR #7517).
6061
- Fix segmentation fault (infinite recursion) of DetectPlanarPatches if multiple points have same coordinates (PR #6794)
6162
- `TriangleMesh`'s `+=` operator appends UVs regardless of the presence of existing features (PR #6728)
6263
- Fix build with fmt v10.2.0 (#6783)

cpp/open3d/Open3D.h.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
#include "open3d/pipelines/registration/Feature.h"
6464
#include "open3d/pipelines/registration/GeneralizedICP.h"
6565
#include "open3d/pipelines/registration/GlobalOptimization.h"
66+
#include "open3d/pipelines/registration/NormalDistributionsTransform.h"
6667
#include "open3d/pipelines/registration/Registration.h"
6768
#include "open3d/pipelines/registration/SymmetricICP.h"
6869
#include "open3d/pipelines/registration/TransformationEstimation.h"

cpp/open3d/io/rpc/DummyReceiver.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ namespace rpc {
1919
class DummyReceiver : public ZMQReceiver {
2020
public:
2121
DummyReceiver(const std::string& address, int timeout);
22+
using ZMQReceiver::GetLastEndpoint;
2223
};
2324

2425
} // namespace rpc

cpp/open3d/io/rpc/ZMQReceiver.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ std::runtime_error ZMQReceiver::GetLastError() {
9292
return result;
9393
}
9494

95+
std::string ZMQReceiver::GetLastEndpoint() const {
96+
if (!socket_) return "";
97+
return socket_->get(zmq::sockopt::last_endpoint);
98+
}
99+
95100
void ZMQReceiver::Mainloop() {
96101
context_ = GetZMQContext();
97102
socket_ = std::unique_ptr<zmq::socket_t>(

cpp/open3d/io/rpc/ZMQReceiver.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ class ZMQReceiver {
6060
/// Returns the last error from the mainloop thread.
6161
std::runtime_error GetLastError();
6262

63+
/// Returns the endpoint the OS actually bound to (e.g. when address_ is
64+
/// tcp://localhost:0). Must be called after Start() succeeds.
65+
std::string GetLastEndpoint() const;
66+
6367
/// Sets the message processor object which will process incoming messages.
6468
void SetMessageProcessor(std::shared_ptr<MessageProcessorBase> processor);
6569

cpp/open3d/pipelines/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ target_sources(pipelines PRIVATE
2525
registration/GeneralizedICP.cpp
2626
registration/SymmetricICP.cpp
2727
registration/GlobalOptimization.cpp
28+
registration/NormalDistributionsTransform.cpp
2829
registration/PoseGraph.cpp
2930
registration/Registration.cpp
3031
registration/RobustKernel.cpp

0 commit comments

Comments
 (0)