Register Point Clouds Using Fast Global Registration
SUMMARY
Register Point Clouds Using Fast Global Registration aligns two point clouds using Fast Global Registration (FGR), a feature-based global registration method.
It estimates surface normals, computes FPFH (Fast Point Feature Histogram) descriptors around each point, matches points by feature similarity rather than raw proximity, and optimizes the alignment via graduated non-convexity. Unlike the ICP-based registration Skills in Vitreous, FGR doesn't need the clouds to already be roughly aligned — it can handle larger initial misalignments — which makes it the right choice when you don't have a good initial_transformation_matrix to start from. The function returns the 4x4 transform it found, not an already-moved point cloud — apply it with apply_transform_to_point_cloud.
Use this Skill when you want to compute an initial alignment between two point clouds without needing them to already be roughly positioned relative to each other.
The Skill
from telekinesis import vitreous
import numpy as np
transformation_matrix = vitreous.register_point_clouds_using_fast_global_registration(
source_point_cloud=source_point_cloud,
target_point_cloud=target_point_cloud,
initial_transformation_matrix=np.eye(4),
normal_radius=3.7,
normal_max_neighbors=30,
feature_radius=11.1,
feature_max_neighbors=100,
max_correspondence_distance=7.4,
)
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 Fast Global Registration (FGR) with FPFH features
The Code
"""
Demonstrates aligning point clouds using Fast Global Registration (FGR).
"""
import numpy as np
from loguru import logger
import rerun as rr
from telekinesis import vitreous, datatypes
def register_point_clouds_using_fast_global_registration_example():
"""
Aligns point clouds using Fast Global Registration (FGR).
Feature-based registration that's faster than RANSAC. Uses graduated
non-convexity optimization.
"""
# ===================== Load Data ==========================================
source_point_cloud_url = "https://assets.telekinesis.ai/examples/v1/point_clouds/gusset_model_voxelized.ply"
target_point_cloud_url = "https://assets.telekinesis.ai/examples/v1/point_clouds/gusset_0_preprocessed_voxelized.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_fast_global_registration(
normal_radius=3.7,
normal_max_neighbors=30,
feature_radius=11.1,
feature_max_neighbors=100,
max_correspondence_distance=7.4,
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 fast global registration"
)
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_fast_global_registration_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_fast_global_registration_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_fast_global_registration.pyParameter Configuration
| Key | Type | Default | Description |
|---|---|---|---|
source_point_cloud | datatypes.PointCloud | required | The point cloud to align. Normals are estimated automatically if not already present |
target_point_cloud | datatypes.PointCloud | required | The point cloud to align to. Normals are estimated automatically if not already present |
initial_transformation_matrix | datatypes.Mat4x4 | np.ndarray | list[list[float]] | np.eye(4) | A 4x4 transform applied to source_point_cloud before registration. FGR tolerates larger initial misalignments than ICP, but a rough initial alignment still helps |
normal_radius | datatypes.Float | float | int | 0.02 | Search radius, in meters, used to estimate each point's surface normal |
normal_max_neighbors | datatypes.Int | int | 20 | Maximum number of neighbors used for normal estimation |
feature_radius | datatypes.Float | float | int | 0.05 | Search radius, in meters, used to compute each point's FPFH feature descriptor |
feature_max_neighbors | datatypes.Int | int | 30 | Maximum number of neighbors used when computing each FPFH feature |
max_correspondence_distance | datatypes.Float | float | int | 0.015 | Maximum feature-space distance, in meters, for two points to be considered a matching correspondence |
Returns
| Type | Description |
|---|---|
datatypes.Mat4x4 | The 4x4 transform found by FGR — 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_fast_global_registration Skill exposes six tunable parameters that control normal estimation, FPFH feature computation, and feature matching.
initial_transformation_matrix
- Controls: An optional seed transform applied to
source_point_cloudbefore registration. - Default:
np.eye(4)(identity) - FGR tolerates a larger initial misalignment than the ICP-based Skills, so this can usually be left at the identity; a rough alignment still helps if you happen to have one.
normal_radius
- Controls: The search radius, in meters, used to estimate each point's surface normal.
- Units: Meters
- Default:
0.02 - Increase → considers more neighbors — smoother, more stable normals, but slower
- Decrease → fewer neighbors — faster, but noisier
- Set to roughly 2-5x the point spacing
- Typical range: 0.01-0.1 meters — use 0.01-0.02 for dense clouds, 0.02-0.05 for medium, 0.05-0.1 for sparse
normal_max_neighbors
- Controls: The maximum number of neighbors used for normal estimation.
- Units: Points (integer count)
- Default:
20 - Increase → more stable normals, slower
- Decrease → faster, noisier
- Typical range: 10-50 — use 10-20 for fast, 20-30 for balanced, 30-50 for quality
feature_radius
- Controls: The search radius, in meters, used to compute each point's FPFH feature descriptor.
- Units: Meters
- Default:
0.05 - Increase → captures larger-scale surface features, but slower
- Decrease → captures finer features
- Set to roughly 5-10x the point spacing
- Typical range: 0.02-0.2 meters — use 0.02-0.05 for fine features, 0.05-0.1 for balanced, 0.1-0.2 for coarse
feature_max_neighbors
- Controls: The maximum number of neighbors used when computing each FPFH feature.
- Units: Points (integer count)
- Default:
30 - Increase → captures more surrounding context, slower
- Decrease → faster
- Typical range: 20-100 — use 20-30 for fast, 30-50 for balanced, 50-100 for detailed
max_correspondence_distance
- Controls: The maximum feature-space distance, in meters, for two points to be considered a matching correspondence.
- Units: Meters
- Default:
0.015 - Increase → allows matching more dissimilar features, risking incorrect matches
- Decrease → requires closer matches
- Set to roughly 2-5x
feature_radius - Typical range: 0.01-0.1 meters
TIP
Set normal_radius and feature_radius relative to your point cloud's density (a few times the typical point spacing) before touching the other parameters — feature quality depends more on these radii matching the data than on the neighbor-count limits. Follow up with register_point_clouds_using_point_to_point_icp or register_point_clouds_using_point_to_plane_icp for a higher-accuracy refinement once FGR has produced a rough alignment.
Where to Use the Skill
Common pipelines include:
- Initial coarse alignment with no prior pose estimate – bootstrapping registration when neither the translation nor the rotation between two clouds is known
- Feature-based multi-view registration – merging scans from viewpoints that weren't tracked precisely enough for a direct ICP start
- Object pose estimation from scratch – finding a first alignment of a reference model to a scene scan before refining with ICP
- Recovering from a failed or missing coarse alignment – as a fallback when
register_point_clouds_using_centroid_translationor a sampler-based ICP Skill isn't applicable because the misalignment is too large
Alternative Skills
| Skill | vs. Register Point Clouds Using Fast Global Registration |
|---|---|
| register_point_clouds_using_point_to_point_icp | Matches by raw point-to-point distance and requires the clouds to already be roughly aligned within max_correspondence_distance. Use it to refine the alignment FGR produces, or directly if you already have a good starting alignment. |
| register_point_clouds_using_point_to_plane_icp | Matches by distance to the target's tangent plane using normals; also requires rough pre-alignment. A more accurate refinement step to run after FGR when normals are reliable. |
| register_point_clouds_using_cuboid_translation_sampler_icp | Searches over translations with repeated ICP runs; still requires the clouds to be roughly rotationally aligned first, unlike FGR. |
| register_point_clouds_using_rotation_sampler_icp | Searches over rotations with repeated ICP runs; still requires the clouds to be roughly positioned first, unlike FGR. |
The SDK's register_point_clouds_using_centroid_translation is a much cheaper coarse-alignment alternative when you already know the clouds share the same orientation and only need a translation estimate — FGR is the better choice when you don't even have that.
When Not to Use the Skill
Do not use Register Point Clouds Using Fast Global Registration when:
- The point clouds are already well-aligned – use
register_point_clouds_using_point_to_point_icporregister_point_clouds_using_point_to_plane_icpdirectly for refinement instead - You need very high final accuracy – FGR produces a coarse-to-medium alignment; follow it with an ICP-based Skill for a precise final result
- The point clouds have very different geometries – FPFH feature matching relies on comparable surface structure and may fail otherwise
- The point clouds are very sparse – normals and FPFH descriptors become unreliable with too few neighboring points
- You already have a good rough alignment and only need refinement speed – the ICP-based Skills are cheaper once a good
initial_transformation_matrixis available
TIP
Because FGR estimates normals and FPFH features from scratch, voxel-downsampling both clouds to a consistent density before calling this Skill (e.g. with filter_point_cloud_using_voxel_downsampling) makes normal_radius and feature_radius easier to tune and keeps the feature computation fast.

