Open3D
Open3D copied to clipboard
Add Symmetric ICP Implementation
Add Symmetric ICP Implementation for Improved Point Cloud Registration
Type
- [ ] Bug fix (non-breaking change which fixes an issue): Fixes #
- [x ] 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
This PR introduces a Symmetric ICP (Iterative Closest Point) algorithm implementation.
Key Benefits:
- Improved accuracy: Bidirectional error minimization reduces registration bias
- Better convergence: More stable optimization through symmetric error terms
- Noise robustness: Less sensitive to outliers and measurement noise
- Partial overlap handling: Better performance when point clouds have limited overlap
This implementation follows the symmetric point-to-plane error formulation where the objective function minimizes:
E = Σ [(p_s - p_t) · n_t]² + [(p_s - p_t) · n_s]²
where p_s, p_t are corresponding points and n_s, n_t are their respective normals.
Checklist:
- [x ] I have run
python util/check_style.py --applyto apply Open3D code style to my code. - [ x] This PR changes Open3D behavior or adds new functionality.
- [ x] Both C++ (Doxygen) and Python (Sphinx / Google style) documentation is updated accordingly.
- [ x] I have added or updated C++ and / or Python unit tests OR included test results (e.g. screenshots or numbers) here.
- [x ] I will follow up and update the code if CI fails.
- [x ] For fork PRs, I have selected Allow edits from maintainers.
Description
Implementation Details
Core Components:
TransformationEstimationSymmetricclass extendingTransformationEstimationRegistrationSymmetricICPfunction following Open3D's registration API patterns- Comprehensive test suite with 9 unit tests covering edge cases
- Python bindings for seamless integration with existing workflows
Files Added/Modified:
cpp/open3d/pipelines/registration/SymmetricICP.h- Header with class declarationcpp/open3d/pipelines/registration/SymmetricICP.cpp- Core implementationcpp/tests/pipelines/registration/SymmetricICP.cpp- Comprehensive C++ testspython/test/test_symmetric_icp.py- Python test suite
API Usage
C++ API:
#include "open3d/pipelines/registration/SymmetricICP.h"
auto estimation = registration::TransformationEstimationSymmetric();
auto result = registration::RegistrationSymmetricICP(
source, target, max_distance, init_transform, estimation, criteria);
Python API:
import open3d as o3d
estimation = o3d.pipelines.registration.TransformationEstimationSymmetric()
result = o3d.pipelines.registration.registration_symmetric_icp(
source, target, max_distance, init_transform, estimation, criteria)
Test Results
C++ Tests (9/9 passing): [==========] Running 9 tests from 1 test suite. [----------] 9 tests from SymmetricICP [ RUN ] SymmetricICP.TransformationEstimationSymmetricConstructor [ OK ] SymmetricICP.TransformationEstimationSymmetricConstructor (0 ms) [ RUN ] SymmetricICP.TransformationEstimationSymmetricComputeRMSE [ OK ] SymmetricICP.TransformationEstimationSymmetricComputeRMSE (0 ms) [ RUN ] SymmetricICP.TransformationEstimationSymmetricComputeRMSEEmptyCorres [ OK ] SymmetricICP.TransformationEstimationSymmetricComputeRMSEEmptyCorres (0 ms) [ RUN ] SymmetricICP.TransformationEstimationSymmetricComputeRMSENoNormals [ OK ] SymmetricICP.TransformationEstimationSymmetricComputeRMSENoNormals (0 ms) [ RUN ] SymmetricICP.TransformationEstimationSymmetricComputeTransformation [ OK ] SymmetricICP.TransformationEstimationSymmetricComputeTransformation (0 ms) [ RUN ] SymmetricICP.TransformationEstimationSymmetricComputeTransformationEmptyCorres [ OK ] SymmetricICP.TransformationEstimationSymmetricComputeTransformationEmptyCorres (0 ms) [ RUN ] SymmetricICP.TransformationEstimationSymmetricComputeTransformationNoNormals [ OK ] SymmetricICP.TransformationEstimationSymmetricComputeTransformationNoNormals (0 ms) [ RUN ] SymmetricICP.RegistrationSymmetricICP [ OK ] SymmetricICP.RegistrationSymmetricICP (36 ms) [ RUN ] SymmetricICP.RegistrationSymmetricICPConvergence [ OK ] SymmetricICP.RegistrationSymmetricICPConvergence (4 ms) [----------] 9 tests from SymmetricICP (41 ms total) [ PASSED ] 9 tests.
Test Coverage:
- ✅ Constructor and basic functionality
- ✅ RMSE computation with various input conditions
- ✅ Transformation estimation with perfect and noisy correspondences
- ✅ Edge cases: empty correspondences, missing normals
- ✅ End-to-end registration with convergence validation
- ✅ Robust handling of large-scale point clouds (50+ points)
Code Quality
Style Compliance:
- ✅ All files pass check_style.py validation
- ✅ 80-character line limit compliance
- ✅ Consistent indentation and formatting
- ✅ Proper Doxygen documentation
- ✅ Memory-safe smart pointer usage
Design Patterns:
- Follows existing Open3D registration framework patterns
- Consistent with ColoredICP and standard ICP implementations
- Supports robust kernels through the same interface
- Maintains backward compatibility
Integration
This implementation integrates seamlessly with Open3D's existing registration pipeline:
- Reuses existing RegistrationICP infrastructure
- Compatible with current convergence criteria
- Supports all robust kernel types
- Maintains consistent error handling patterns
The Symmetric ICP method provides users with an additional tool for challenging registration scenarios while maintaining the familiar Open3D API design.
Thanks for submitting this pull request! The maintainers of this repository would appreciate if you could update the CHANGELOG.md based on your changes.
I've noticed some failing test cases, but they don't appear to be connected to my recent modifications. Am I responsible for addressing them?
Check out this pull request on ![]()
See visual diffs & provide feedback on Jupyter Notebooks.
Powered by ReviewNB