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,
)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,
)
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
| Parameter | 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 the point clouds' coordinate units, used to estimate each point's surface normal. Must be > 0 |
normal_max_neighbors | datatypes.Int | int | 20 | Maximum number of neighbors used for normal estimation. Must be > 0 |
feature_radius | datatypes.Float | float | int | 0.05 | Search radius, in the point clouds' coordinate units, used to compute each point's FPFH feature descriptor. Must be > 0 |
feature_max_neighbors | datatypes.Int | int | 30 | Maximum number of neighbors used when computing each FPFH feature. Must be > 0 |
min_fitness_score | datatypes.Float | float | int | 0.3 | The minimum fitness score the result must reach to be accepted (see the Returns section below for what happens if it never is) |
max_correspondence_distance | datatypes.Float | float | int | 0.015 | Maximum feature-space distance, in the point clouds' coordinate units, for two points to be considered a matching correspondence. Must be > 0 |
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. If the alignment's fitness falls below min_fitness_score — including when either point cloud has fewer than 3 points, or FPFH feature computation yields no usable features — this silently returns the identity transform instead of raising. |
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, the response was not returned as an Arrow stream, 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 or malformed input (HTTP 400/422), an unrecognized endpoint (HTTP 404), or another unexpected 4xx response |
AuthenticationError | The API key was rejected as invalid or expired (HTTP 401) |
AuthenticationServiceError | The authentication service returned an invalid response, was temporarily unavailable, or timed out (HTTP 502/503/504) |
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 seven 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 the point clouds' coordinate units, used to estimate each point's surface normal.
- Units: The point clouds' coordinate units (e.g. meters or millimeters, whatever unit the input data uses)
- Default:
0.02 - Must be
> 0 - 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 (in coordinate units matching a meter-scale point cloud) — 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 - Must be
> 0 - 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 the point clouds' coordinate units, used to compute each point's FPFH feature descriptor.
- Units: The point clouds' coordinate units
- Default:
0.05 - Must be
> 0 - 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 (in coordinate units matching a meter-scale point cloud) — 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 - Must be
> 0 - 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
min_fitness_score
- Controls: The minimum fitness score the result must reach to be accepted.
- Default:
0.3 - If the alignment's fitness falls below this threshold — including when either point cloud has fewer than 3 points, or FPFH feature computation yields no usable features — the function silently returns the identity transform instead of raising (see the Returns section above)
- Increase → requires higher-quality alignment before accepting the result
- Decrease → accepts a lower-quality alignment
max_correspondence_distance
- Controls: The maximum feature-space distance, in the point clouds' coordinate units, for two points to be considered a matching correspondence.
- Units: The point clouds' coordinate units
- Default:
0.015 - Must be
> 0 - 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 (in coordinate units matching a meter-scale point cloud)
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. |
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.