Register Point Clouds Using Cuboid Translation Sampler ICP
SUMMARY
Register Point Clouds Using Cuboid Translation Sampler ICP finds the best alignment between two point clouds by trying many candidate translations on a 3D grid, refining each one with point-to-point ICP.
It samples translations on a regular grid within [x_min, x_max] x [y_min, y_max] x [z_min, z_max] (relative to initial_transformation_matrix), runs ICP starting from each sampled translation, and keeps whichever run converged to the best fitness score. This is useful when source_point_cloud and target_point_cloud are already roughly rotationally aligned but the translation between them isn't known precisely enough for plain ICP to converge on its own. Compare with register_point_clouds_using_rotation_sampler_icp, which instead searches over rotations. The function returns the 4x4 transform that produced the best result, not an already-moved point cloud — apply it with apply_transform_to_point_cloud.
Use this Skill when you want to register two point clouds whose relative translation is uncertain but whose relative rotation is already roughly known.
The Skill
from telekinesis import vitreous
import numpy as np
transformation_matrix = vitreous.register_point_clouds_using_cuboid_translation_sampler_icp(
source_point_cloud=source_point_cloud,
target_point_cloud=target_point_cloud,
initial_transformation_matrix=np.eye(4),
step_size=2,
x_min=-20,
x_max=20,
y_min=-20,
y_max=20,
z_min=-20,
z_max=20,
early_stop_fitness_score=0.3,
min_fitness_score=0.48,
max_iterations=50,
max_correspondence_distance=2,
estimate_scaling=False,
)
aligned_point_cloud = vitreous.apply_transform_to_point_cloud(
point_cloud=source_point_cloud,
transformation_matrix=transformation_matrix,
modify_inplace=False,
)Data Transfer Notice
There is no longer a fixed limit of 1 million points per request. However, very large datasets may result in slower data transfer and processing times. We are continuously optimizing performance as part of our beta program, with ongoing improvements to enhance speed and reliability.
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 cuboid translation sampler ICP with 3D grid translation search
The Code
"""
Demonstrates finding the best alignment by sampling translations in a 3D grid (cuboid) with ICP.
"""
import numpy as np
from loguru import logger
import rerun as rr
from telekinesis import vitreous, datatypes
def register_point_clouds_using_cuboid_translation_sampler_icp_example():
"""
Finds best alignment by sampling translations in a 3D grid (cuboid) with ICP.
Tries translations on a regular 3D grid within specified x/y/z ranges, runs ICP
for each, and keeps best result.
"""
# ===================== Load Data ==========================================
source_point_cloud_url = "https://assets.telekinesis.ai/examples/v1/point_clouds/weld_clamp_model_shifted.ply"
target_point_cloud_url = "https://assets.telekinesis.ai/examples/v1/point_clouds/weld_clamp_cluster_0_centroid_registered.ply"
source_point_cloud = datatypes.PointCloud.from_url(
url=source_point_cloud_url, use_cache=True
)
target_point_cloud = datatypes.PointCloud.from_url(
url=target_point_cloud_url, use_cache=True
)
# ===================== Run Skill ==========================================
transformation_matrix = (
vitreous.register_point_clouds_using_cuboid_translation_sampler_icp(
step_size=2,
x_min=-20,
x_max=20,
y_min=-20,
y_max=20,
z_min=-20,
z_max=20,
early_stop_fitness_score=0.3,
min_fitness_score=0.48,
max_iterations=50,
max_correspondence_distance=2,
estimate_scaling=False,
source_point_cloud=source_point_cloud,
target_point_cloud=target_point_cloud,
initial_transformation_matrix=np.eye(4),
)
)
# ===================== Log ================================================
logger.success(
f"Registered {source_point_cloud} to {target_point_cloud} using cuboid translation sampler ICP"
)
logger.success(f"Results: {transformation_matrix}")
logger.info(f"Transformation matrix data: {transformation_matrix.data}")
logger.info(f"Transformation matrix shape: {transformation_matrix.shape}")
logger.info(f"Transformation matrix ndim: {transformation_matrix.ndim}")
logger.info(f"Transformation matrix dtype: {transformation_matrix.dtype}")
# ===================== Visualization (Optional) ===========================
aligned_source_point_cloud = vitreous.apply_transform_to_point_cloud(
point_cloud=source_point_cloud,
transformation_matrix=transformation_matrix,
modify_inplace=False,
)
rr.init(
"register_point_clouds_using_cuboid_translation_sampler_icp_example", spawn=True
)
datatypes.visualize(source_point_cloud, entity_path="/1-before_registration_source")
datatypes.visualize(target_point_cloud, entity_path="/2-before_registration_target")
datatypes.visualize(
aligned_source_point_cloud, entity_path="/3-after_registration_source_aligned"
)
if __name__ == "__main__":
register_point_clouds_using_cuboid_translation_sampler_icp_example()Runnable examples are available in the Telekinesis examples repository.
Follow the README in that repository to set up the environment, run this specific example with:
cd telekinesis-examples
python examples/point_cloud/register_point_clouds_using_cuboid_translation_sampler_icp.pyParameter Configuration
| Key | Type | Default | Description |
|---|---|---|---|
source_point_cloud | datatypes.PointCloud | required | The point cloud to align |
target_point_cloud | datatypes.PointCloud | required | The point cloud to align to |
initial_transformation_matrix | datatypes.Mat4x4 | np.ndarray | list[list[float]] | np.eye(4) | A 4x4 transform applied to source_point_cloud before the search — the translation search happens relative to this initial alignment |
step_size | datatypes.Float | float | int | 0.001 | Spacing, in meters, between sampled translations on the search grid |
x_min | datatypes.Float | float | int | -0.01 | Lower bound, in meters, of the translation search along x (relative to initial_transformation_matrix) |
x_max | datatypes.Float | float | int | 0.01 | Upper bound, in meters, of the translation search along x |
y_min | datatypes.Float | float | int | -0.01 | Lower bound, in meters, of the translation search along y |
y_max | datatypes.Float | float | int | 0.01 | Upper bound, in meters, of the translation search along y |
z_min | datatypes.Float | float | int | -0.01 | Lower bound, in meters, of the translation search along z |
z_max | datatypes.Float | float | int | 0.01 | Upper bound, in meters, of the translation search along z |
early_stop_fitness_score | datatypes.Float | float | int | 0.5 | A fitness score in [0, 1] at which the grid search stops early instead of trying every remaining sample |
min_fitness_score | datatypes.Float | float | int | 0.9 | Minimum fitness score in [0, 1] the best result must reach to be accepted at all |
max_iterations | datatypes.Int | int | 50 | Maximum number of ICP iterations run for each sampled translation |
max_correspondence_distance | datatypes.Float | float | int | 0.02 | Maximum distance, in meters, at which two points from the source/target clouds are considered a match during ICP |
estimate_scaling | datatypes.Bool | bool | False | Whether to also estimate and apply a uniform scale factor between the two point clouds, instead of assuming they're at the same scale |
Returns
| Type | Description |
|---|---|
datatypes.Mat4x4 | The best-scoring 4x4 transform found by the grid search — this is the transform itself, not an already-transformed point cloud. Pass it to apply_transform_to_point_cloud (as transformation_matrix) to actually move source_point_cloud's points. Use .data for the raw (4, 4) array. |
Raises
| Exception | Condition |
|---|---|
TypeError | A parameter's value does not match its expected type (see the Parameter Configuration table above) |
ValueError | initial_transformation_matrix is not shape (4, 4) (or, for a list input, doesn't contain only numeric elements) |
ConfigurationError | The TELEKINESIS_API_KEY environment variable is not set |
SerializationError | The request input failed to serialize, or the response failed to deserialize |
RequestTimeoutError | The request to the Vitreous service timed out |
TransportError | A network failure occurred before a response was received |
ClientError | The Vitreous service rejected the request due to invalid input, invalid data, or another unexpected 4xx response |
AuthenticationError | The API key was rejected as invalid or expired |
AuthenticationServiceError | The authentication service was unavailable |
ServerError | The Vitreous service returned a 5xx or otherwise unexpected error response |
How to Tune the Parameters
The register_point_clouds_using_cuboid_translation_sampler_icp Skill exposes thirteen tunable parameters that define the translation search grid and control the ICP refinement run at each grid point.
initial_transformation_matrix
- Controls: The seed transform the translation grid is centered on — every sampled translation is relative to this.
- Default:
np.eye(4)(identity — no pre-alignment) - Provide a rough rotation-only alignment here if
source_point_cloudandtarget_point_cloudaren't already close in orientation; this Skill only searches over translation, not rotation.
step_size
- Controls: Spacing, in meters, between sampled translations on the search grid.
- Units: Meters
- Default:
0.001 - Increase → coarser grid — fewer samples, faster, but may miss the optimal alignment
- Decrease → finer grid — more samples, slower, more thorough
- Set to roughly 0.5-2x the alignment accuracy you need
- Typical range: 0.0005-0.01 meters — use 0.0005-0.001 for a precise search, 0.001-0.005 for balanced, 0.005-0.01 for coarse
x_min / x_max, y_min / y_max, z_min / z_max
- Controls: The bounds, in meters, of the translation search cuboid along each axis, relative to
initial_transformation_matrix. - Units: Meters
- Default:
-0.01/0.01on all three axes - The
_minbound should be negative and the_maxbound positive (and greater than_min) if the true translation could lie in either direction along that axis - Typical range: -0.1 to 0.1 meters per bound
early_stop_fitness_score
- Controls: A fitness score in
[0, 1]at which the grid search stops early instead of trying every remaining sample. - Units: Dimensionless (fitness score)
- Default:
0.5 - Increase → accepts stopping sooner (faster), but may settle for a suboptimal alignment
- Decrease → requires a better fit before stopping early
- Typical range: 0.3-0.7 — use 0.3-0.5 for a fast search, 0.5-0.7 for higher quality
min_fitness_score
- Controls: The minimum fitness score in
[0, 1]the best result must reach to be accepted at all. - Units: Dimensionless (fitness score)
- Default:
0.9 - Increase → requires higher-quality alignment
- Decrease → accepts lower quality
- Typical range: 0.7-0.99 — use 0.7-0.85 for lenient, 0.85-0.95 for balanced, 0.95-0.99 for strict
max_iterations
- Controls: The maximum number of ICP iterations run for each sampled translation.
- Units: Iterations (integer)
- Default:
50 - Increase → more refinement per sample, but slower overall
- Decrease → faster
- Typical range: 10-200 — use 10-30 for fast, 30-50 for balanced, 50-200 for high precision
max_correspondence_distance
- Controls: The maximum distance, in meters, at which two points from the source/target clouds are considered a match during ICP.
- Units: Meters
- Default:
0.02 - Increase → allows matching more distant points, risking incorrect matches
- Decrease → requires closer matches
- Set to roughly 2-5x the point spacing
- Typical range: 0.01-0.1 meters
estimate_scaling
- Controls: Whether to also estimate and apply a uniform scale factor between the two point clouds, instead of assuming they're at the same scale.
- Default:
False - Set to
Trueonly if the clouds might genuinely be at different scales.
TIP
Pick x_min/x_max/y_min/y_max/z_min/z_max to bracket your expected translation uncertainty first, then set step_size to roughly 0.5-2x the precision you need within that range. If the clouds aren't already roughly rotationally aligned, resolve that separately (e.g. with register_point_clouds_using_rotation_sampler_icp or a known fixed rotation) — this Skill only searches over translation.
Where to Use the Skill
Common pipelines include:
- 6D pose estimation with uncertain translation – aligning a reference/CAD model to a sensor scan when the object's position, but not its orientation, on a fixture or conveyor is unknown
- Multi-view point cloud registration – merging scans captured from positions that are only approximately known
- Robotic pick-and-place setup – locating a known part whose position varies from scan to scan while its orientation stays consistent
- Refining a coarse translation guess – following up the SDK's
register_point_clouds_using_centroid_translationwhen a single centroid match isn't precise enough
Alternative Skills
| Skill | vs. Register Point Clouds Using Cuboid Translation Sampler ICP |
|---|---|
| register_point_clouds_using_rotation_sampler_icp | Searches over rotations instead of translations. Use it when the clouds are already close in position but the relative rotation is unknown; use this Skill when it's the other way around. |
| register_point_clouds_using_point_to_point_icp | Plain point-to-point ICP from a single initial guess, with no sampling. Use it once you already have a translation estimate good enough for direct convergence; use this Skill first if you don't. |
| register_point_clouds_using_fast_global_registration | Feature-based global registration that doesn't require any rough pre-alignment at all. A good alternative starting point when neither the translation nor the rotation between the clouds is known. |
The SDK's register_point_clouds_using_centroid_translation is a fast, translation-only coarse-alignment step commonly run before this Skill (it has no doc page yet, but its docstring — and this Skill's — reference each other directly).
When Not to Use the Skill
Do not use Register Point Clouds Using Cuboid Translation Sampler ICP when:
- The clouds are already roughly aligned in translation – plain
register_point_clouds_using_point_to_point_icp(orregister_point_clouds_using_point_to_plane_icp) converges directly, without the extra grid search - The rotation between the clouds is unknown, not the translation – use
register_point_clouds_using_rotation_sampler_icpinstead, which searches rotations - You have no rough alignment at all, in rotation or translation – use
register_point_clouds_using_fast_global_registrationfirst, since it tolerates large initial misalignment - You need a fast result – this Skill runs a full ICP pass for every sampled translation, so it is slower than a single ICP call
- The translation uncertainty spans a very large volume – the grid may need too many samples at a workable
step_sizeto search effectively - The point clouds may be at different scales – set
estimate_scaling=True, or pre-scale the clouds; otherwise the search assumes matching scale
TIP
Keep the search cuboid (x_min/x_max/y_min/y_max/z_min/z_max) as tight as your actual translation uncertainty allows — a smaller cuboid at a given step_size means fewer ICP runs and a faster search.

