Skip to content

Add Symmetric ICP Implementation #7276

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 21 commits into
base: main
Choose a base branch
from

Conversation

eclipse0922
Copy link
Contributor

@eclipse0922 eclipse0922 commented Jun 15, 2025

Add Symmetric ICP Implementation for Improved Point Cloud Registration

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

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 --apply to 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:

  1. TransformationEstimationSymmetric class extending TransformationEstimation
  2. RegistrationSymmetricICP function following Open3D's registration API patterns
  3. Comprehensive test suite with 9 unit tests covering edge cases
  4. Python bindings for seamless integration with existing workflows

Files Added/Modified:

  • cpp/open3d/pipelines/registration/SymmetricICP.h - Header with class declaration
  • cpp/open3d/pipelines/registration/SymmetricICP.cpp - Core implementation
  • cpp/tests/pipelines/registration/SymmetricICP.cpp - Comprehensive C++ tests
  • python/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.

Copy link

update-docs bot commented Jun 15, 2025

Thanks for submitting this pull request! The maintainers of this repository would appreciate if you could update the CHANGELOG.md based on your changes.

@eclipse0922 eclipse0922 marked this pull request as draft June 15, 2025 15:31
@eclipse0922 eclipse0922 marked this pull request as ready for review June 15, 2025 15:53
@eclipse0922 eclipse0922 changed the title Add Symmetric ICP Implementation for Improved Point Cloud Registration Add Symmetric ICP Implementation Jun 15, 2025
@eclipse0922 eclipse0922 force-pushed the zyu8e9-codex/implement-symmetric-icp-with-objective-function branch from d441e69 to e75b3f7 Compare June 15, 2025 16:56
@eclipse0922
Copy link
Contributor Author

eclipse0922 commented Jun 16, 2025

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?

@eclipse0922 eclipse0922 force-pushed the zyu8e9-codex/implement-symmetric-icp-with-objective-function branch from 7c1247f to c45b03a Compare June 16, 2025 09:30
Copilot

This comment was marked as outdated.

@eclipse0922 eclipse0922 force-pushed the zyu8e9-codex/implement-symmetric-icp-with-objective-function branch from ebb0809 to 67b735e Compare July 3, 2025 02:16
eclipse0922 and others added 15 commits July 3, 2025 11:32
Implements the Symmetric Iterative Closest Point (ICP) algorithm for point cloud registration.

This change introduces a new method for aligning point clouds that considers the symmetry between source and target, leading to potentially more accurate and robust registration results, especially when dealing with noisy or incomplete data.

Includes C++ and Python implementations with corresponding tests.
Introduces a new class for estimating transformations
based on symmetric point-to-plane distance, enhancing
registration pipelines.

Includes corresponding unit tests to ensure correct
functionality and robustness.
Adds more comprehensive tests for the Symmetric ICP registration pipeline,
covering various scenarios such as empty correspondence sets, missing
normals, and convergence behavior. These improvements enhance the
reliability and robustness of the algorithm.
This commit refactors the SymmetricICP class for improved
readability and maintainability. It also fixes a potential issue
where the kernel_ member was not properly initialized.

Changes include:
- Ensures proper initialization of the robust kernel.
- Improves error logging for clarity.
- Modifies the order of methods in the header file for better organization.
Refactors the Symmetric ICP implementation for better readability
and consistency. Addresses minor issues in the symmetric
transformation estimation and improves code formatting.
Improves the Symmetric ICP estimation by making minor adjustments to variable declarations for better code clarity.

The change also includes a cleanup in the header file by removing a redundant public access modifier.
The Eigen/Geometry header was included but not used. Removes the unnecessary include to reduce compilation time and dependencies.
Removes unnecessary includes from SymmetricICP.h and SymmetricICP.cpp, cleaning up the code and reducing compile times.
Adds CUDA implementation for the Symmetric ICP registration algorithm, enabling it to run on GPUs.

This improves performance for point cloud registration tasks by leveraging parallel processing capabilities.

Includes device consistency tests between CPU and GPU, and supports different robust kernels.
Removes the CLAUDE.md file, as the information it contained is no longer relevant or has been migrated to other documentation.
Fixes an error in the test suite by updating the attribute name
used to access correspondence set length. It changes
`correspondence_set_` to `correspondence_set`.
Adds normal estimation for both source and target point clouds
to ensure compatibility with symmetric ICP. Symmetric ICP requires
normals to properly function.
Removes trailing whitespace to improve code consistency
and adhere to style guidelines.
Refactors Jacobian calculation for clarity and efficiency.

Adds checks for valid correspondences to prevent errors when no valid pairs are available.
@eclipse0922 eclipse0922 force-pushed the zyu8e9-codex/implement-symmetric-icp-with-objective-function branch from 67b735e to 456f14c Compare July 3, 2025 02:34
@eclipse0922 eclipse0922 requested a review from Copilot July 3, 2025 04:12
Copilot

This comment was marked as outdated.

@eclipse0922 eclipse0922 requested a review from Copilot July 3, 2025 04:28
Copilot

This comment was marked as outdated.

Removes an unnecessary device assertion
@eclipse0922 eclipse0922 requested a review from Copilot July 3, 2025 04:50
Copilot

This comment was marked as outdated.

@eclipse0922 eclipse0922 requested a review from Copilot July 3, 2025 05:43
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Adds a new symmetric ICP algorithm to improve point‐cloud registration by minimizing bidirectional point‐to‐plane errors.

  • Introduces TransformationEstimationSymmetric and RegistrationSymmetricICP in both legacy (open3d::pipelines) and tensor (open3d::t::pipelines) pipelines.
  • Implements CPU and CUDA kernels (ComputePoseSymmetricCPU/ComputePoseSymmetricCUDA) and integrates them via ComputePoseSymmetric.
  • Adds comprehensive C++ and Python unit tests and updates Python bindings for both pipelines.

Reviewed Changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
python/test/test_symmetric_icp.py New Python tests for legacy pipeline symmetric ICP
python/test/t/registration/test_registration.py New Python tests for tensor‐based symmetric ICP
cpp/open3d/pipelines/registration/SymmetricICP.h/.cpp Legacy pipeline symmetric ICP declaration & implementation
cpp/open3d/t/pipelines/registration/TransformationEstimation.h/.cpp Declares and implements tensor pipeline symmetric estimation
cpp/open3d/t/pipelines/kernel/RegistrationImpl.h Declares symmetric ICP CPU/CUDA kernels
cpp/open3d/t/pipelines/kernel/RegistrationCPU.cpp Implements symmetric ICP CPU kernel
cpp/open3d/t/pipelines/kernel/RegistrationCUDA.cu Implements symmetric ICP CUDA kernel
cpp/pybind/pipelines/registration/registration.cpp Binds legacy symmetric ICP to Python
cpp/pybind/t/pipelines/registration/registration.cpp Binds tensor symmetric ICP to Python
cpp/tests/pipelines/registration/SymmetricICP.cpp C++ tests for legacy pipeline symmetric ICP
cpp/tests/t/pipelines/registration/TransformationEstimation.cpp C++ tests for tensor pipeline symmetric estimation
cpp/tests/t/pipelines/registration/... Additional tensor‐pipeline C++ tests (device consistency, robust kernels)
cpp/open3d/pipelines/CMakeLists.txt Added legacy SymmetricICP sources
cpp/tests/pipelines/CMakeLists.txt Added legacy SymmetricICP tests
cpp/open3d/Open3D.h.in Exposed SymmetricICP header in main include
Comments suppressed due to low confidence (1)

python/test/t/registration/test_registration.py:205

  • [nitpick] Consider adding a test case to verify that registration_symmetric_icp raises an error when the source or target lacks normals in the tensor pipeline, mirroring the legacy behavior enforced in TransformationEstimationSymmetric.
@pytest.mark.parametrize("device", list_devices())

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.

1 participant