Register Point Clouds Using Rotation Sampler ICP
SUMMARY
Register Point Clouds Using Rotation Sampler ICP aligns two point clouds by trying multiple initial orientations sampled uniformly on a sphere and running ICP from each orientation to find the best alignment.
This Skill is useful in industrial, mobile, and humanoid robotics pipelines for 6D pose estimation when the object’s initial rotation is unknown. For instance, it can align parts in manufacturing when their orientation on a conveyor is arbitrary, register LIDAR scans with uncertain initial rotation for mobile robots, or orient objects correctly for humanoid robot manipulation. Sampling multiple rotations increases robustness to poor initial guesses.
Use this Skill when you want to perform ICP registration robust to unknown initial rotations for precise alignment.
The Skill
from telekinesis import vitreous
import numpy as np
registered_point_cloud = vitreous.register_point_clouds_using_rotation_sampler_icp(
source_point_cloud=source_point_cloud,
target_point_cloud=target_point_cloud,
initial_transformation_matrix=np.eye(4),
x_step_size_deg=20,
y_step_size_deg=20,
z_step_size_deg=20,
x_min_deg=0,
x_max_deg=180,
y_min_deg=0,
y_max_deg=180,
z_min_deg=0,
z_max_deg=180,
early_stop_fitness_score=0.5,
min_fitness_score=0.9,
max_iterations=50,
max_correspondence_distance=0.02,
estimate_scaling=False,
)Performance Note
Current Data Limits: The system currently supports up to 1 million points per request (approximately 16MB of data). We're actively optimizing data transfer performance as part of our beta program, with improvements rolling out regularly to enhance processing speed.
Example
Source and Target Point Clouds
Raw sensor input i.e. target point cloud in green and object model in red
Registered Point Clouds
Registered source point cloud (red) aligned to target point cloud (green) using rotation sampler ICP with multiple orientation initializations
The Code
from telekinesis import vitreous
from datatypes import datatypes, io
import pathlib
import numpy as np
# Optional for logging
from loguru import logger
DATA_DIR = pathlib.Path("path/to/telekinesis-data")
# Load point clouds
source_filepath = str(DATA_DIR / "point_clouds" / "zivid_bottle_segmented.ply")
target_filepath = str(DATA_DIR / "point_clouds" / "zivid_bottle_cylinder_centered.ply")
source_point_cloud = io.load_point_cloud(filepath=source_filepath)
target_point_cloud = io.load_point_cloud(filepath=target_filepath)
logger.success(f"Loaded source point cloud with {len(source_point_cloud.positions)} points")
logger.success(f"Loaded target point cloud with {len(target_point_cloud.positions)} points")
# Execute operation
registered_point_cloud = vitreous.register_point_clouds_using_rotation_sampler_icp(
source_point_cloud=source_point_cloud,
target_point_cloud=target_point_cloud,
initial_transformation_matrix=np.eye(4),
x_step_size_deg=20,
y_step_size_deg=20,
z_step_size_deg=20,
x_min_deg=0,
x_max_deg=180,
y_min_deg=0,
y_max_deg=180,
z_min_deg=0,
z_max_deg=180,
early_stop_fitness_score=0.5,
min_fitness_score=0.9,
max_iterations=50,
max_correspondence_distance=0.02,
estimate_scaling=False,
)
logger.success("Registered point clouds using rotation sampler ICP")Running the Example
Runnable examples are available in the Telekinesis examples repository. Follow the README in that repository to set up the environment. Once set up, you can run this specific example with:
cd telekinesis-examples
python examples/vitreous_examples.py --example register_point_clouds_using_rotation_sampler_icpThe Explanation of the Code
The script starts by importing the necessary modules for point cloud processing (vitreous), data management (datatypes, io), file handling (pathlib), numerical computations (numpy), and optional logging (loguru).
from telekinesis import vitreous
from datatypes import datatypes, io
import pathlib
import numpy as np
# Optional for logging
from loguru import loggerNext, the source and target point clouds are loaded from disk. Logging statements confirm successful loading and display the number of points in each cloud, providing insight into the data size and density before registration.
DATA_DIR = pathlib.Path("path/to/telekinesis-data")
# Load point clouds
source_filepath = str(DATA_DIR / "point_clouds" / "zivid_bottle_segmented.ply")
target_filepath = str(DATA_DIR / "point_clouds" / "zivid_bottle_cylinder_centered.ply")
source_point_cloud = io.load_point_cloud(filepath=source_filepath)
target_point_cloud = io.load_point_cloud(filepath=target_filepath)
logger.success(f"Loaded source point cloud with {len(source_point_cloud.positions)} points")
logger.success(f"Loaded target point cloud with {len(target_point_cloud.positions)} points")The main operation applies the register_point_clouds_using_rotation_sampler_icp Skill. This method performs ICP registration with multiple initial orientations sampled on a rotation grid, iterating over various Euler angle rotations along the X, Y, and Z axes to find the best initial alignment. Key parameters include:
x_step_size_deg,y_step_size_deg,z_step_size_deg: define the angular increments for rotation sampling along each axis. Smaller values yield finer sampling but increase computation time.x_min_deg,x_max_deg,y_min_deg,y_max_deg,z_min_deg,z_max_deg: define the rotation range along each axis, allowing control over the orientation search space.early_stop_fitness_scoreandmin_fitness_score: thresholds to determine when to stop sampling early or consider a registration successful.max_iterationsandmax_correspondence_distance: control the ICP refinement process.estimate_scaling: whether to allow scaling during alignment.initial_transformation_matrix: starting transformation for ICP.
# Execute operation
registered_point_cloud = vitreous.register_point_clouds_using_rotation_sampler_icp(
source_point_cloud=source_point_cloud,
target_point_cloud=target_point_cloud,
initial_transformation_matrix=np.eye(4),
x_step_size_deg=20,
y_step_size_deg=20,
z_step_size_deg=20,
x_min_deg=0,
x_max_deg=180,
y_min_deg=0,
y_max_deg=180,
z_min_deg=0,
z_max_deg=180,
early_stop_fitness_score=0.5,
min_fitness_score=0.9,
max_iterations=50,
max_correspondence_distance=0.02,
estimate_scaling=False,
)
logger.success("Registered point clouds using rotation sampler ICP")This Skill is useful in industrial robotics and perception pipelines where objects may be arbitrarily oriented. By sampling multiple rotations, it increases the likelihood of finding the correct initial alignment, which can then be refined with standard ICP.
How to Tune the Parameters
The register_point_clouds_using_rotation_sampler_icp Skill has many parameters that control the rotation search and ICP refinement:
x_step_size_deg, y_step_size_deg, z_step_size_deg (default: 20):
- Step size for rotation sampling along each axis in degrees
- Increase (20-45) to create a coarser search (fewer samples, faster) but may miss optimal rotation
- Decrease (5-10) to create finer search (more samples, slower)
- Typical range: 5-45 degrees
- Use 5-10 for fine search, 10-20 for balanced, 20-45 for coarse
x_min_deg, x_max_deg, y_min_deg, y_max_deg, z_min_deg, z_max_deg (defaults: 0 to 180):
- Define the rotation range along each axis in degrees
- Increase range (0-360) to search over full rotation space
- Decrease range (0-180) to focus search in a smaller region (faster)
- Typical range: 0-360 degrees
- Use 0-180 for half-sphere, 0-360 for full rotation
early_stop_fitness_score (default: 0.5):
- Fitness score threshold (0-1) for early stopping during search
- Increase (0.5-0.7) to require better alignments before stopping (slower but potentially better results)
- Decrease (0.3-0.5) to stop earlier (faster) but may accept suboptimal alignments
- Should be set higher than
min_fitness_scoreto ensure early-stopped results are acceptable - Typical range: 0.3-0.7
min_fitness_score (default: 0.9):
- Minimum fitness score (0-1) required to accept the final result
- Increase (0.95-0.99) to require better alignment quality
- Decrease (0.7-0.85) to accept lower quality alignments
- Typical range: 0.7-0.99
max_iterations (default: 50):
- The maximum number of ICP iterations per rotation sample
- Increase (50-200) to allow more refinement but is slower
- Decrease (10-30) for faster computation
- Typical range: 10-200
max_correspondence_distance (default: 0.02):
- The maximum distance to consider points as correspondences
- Units: Uses the same units as your point cloud
- Increase to allow matching more distant points but may include incorrect matches
- Decrease to require closer matches
- Should be 2-5x point spacing
- Typical range: 0.01-0.1 in point cloud units
estimate_scaling (default: False):
- Whether to estimate and apply uniform scaling between point clouds
True: Allows the algorithm to find scale differencesFalse: Assumes same scale- Set to
Trueif point clouds may have different scales,Falsefor same-scale alignment
TIP
Best practice: Start with default values and adjust the rotation ranges based on your expected rotation uncertainty. Adjust step sizes based on the precision you need. Use register_point_clouds_using_centroid_translation first for coarse translation alignment, then use this for rotation search.
Where to Use the Skill in a Pipeline
Rotation sampler ICP is commonly used in the following pipelines:
- 6D pose estimation with uncertain rotation
- Object alignment with unknown orientation
- Part inspection and quality control
- Multi-view registration
A typical pipeline for pose estimation with unknown rotation looks as follows:
# Example pipeline using rotation sampler ICP (parameters omitted).
from telekinesis import vitreous
import numpy as np
# 1. Load point clouds
source_point_cloud = vitreous.load_point_cloud(...) # Object model
target_point_cloud = vitreous.load_point_cloud(...) # Scene scan
# 2. Preprocess both point clouds
filtered_source = vitreous.filter_point_cloud_using_statistical_outlier_removal(...)
filtered_target = vitreous.filter_point_cloud_using_statistical_outlier_removal(...)
downsampled_source = vitreous.filter_point_cloud_using_voxel_downsampling(...)
downsampled_target = vitreous.filter_point_cloud_using_voxel_downsampling(...)
# 3. Optional: Coarse alignment using centroid translation
coarse_aligned = vitreous.register_point_clouds_using_centroid_translation(
source_point_cloud=downsampled_source,
target_point_cloud=downsampled_target,
)
# 4. Fine alignment using rotation sampler ICP
registered_cloud = vitreous.register_point_clouds_using_rotation_sampler_icp(
source_point_cloud=downsampled_source,
target_point_cloud=downsampled_target,
initial_transformation_matrix=np.eye(4),
x_step_size_deg=20,
y_step_size_deg=20,
z_step_size_deg=20,
x_min_deg=0,
x_max_deg=180,
y_min_deg=0,
y_max_deg=180,
z_min_deg=0,
z_max_deg=180,
early_stop_fitness_score=0.5,
min_fitness_score=0.9,
max_iterations=50,
max_correspondence_distance=0.02,
estimate_scaling=False,
)
# 5. Use registered point cloud for pose estimation or analysisRelated skills to build such a pipeline:
register_point_clouds_using_centroid_translation: coarse translation alignment before rotation searchregister_point_clouds_using_cuboid_translation_sampler_icp: alternative for translation uncertaintyregister_point_clouds_using_point_to_point_icp: simpler ICP without rotation samplingfilter_point_cloud_using_statistical_outlier_removal: clean input before registrationfilter_point_cloud_using_voxel_downsampling: reduce point cloud density for faster processing
Alternative Skills
| Skill | vs. Rotation Sampler ICP |
|---|---|
| register_point_clouds_using_point_to_point_icp | Use point-to-point ICP when initial rotation is known. Use rotation sampler ICP when rotation is uncertain. |
| register_point_clouds_using_cuboid_translation_sampler_icp | Use cuboid translation sampler when translation is uncertain. Use rotation sampler when rotation is uncertain. |
| register_point_clouds_using_fast_global_registration | Use FGR for feature-based initial alignment. Use rotation sampler ICP for rotation search with ICP refinement. |
When Not to Use the Skill
Do not use rotation sampler ICP when:
- Initial rotation is already known (use
register_point_clouds_using_point_to_point_icpinstead) - Only translation is uncertain (use
register_point_clouds_using_cuboid_translation_sampler_icpinstead) - You need fast registration (this method is slower due to multiple ICP runs)
- Rotation uncertainty is very large (the search space may be too large to sample effectively)
- Point clouds are very different in scale (set
estimate_scaling=Trueor pre-scale the clouds)

