Skip to content

Estimate Principal Axis Within Radius

SUMMARY

Estimate Principal Axis Within Radius computes the dominant direction of a local neighborhood in a point cloud using PCA.

This Skill is primarily used in industrial robotic manipulation to analyze local features of objects, such as edges, rods, or elongated components. By fitting a line to points within a specified radius, robots can align grippers or tools to local object geometry for precision tasks like picking, inserting, or assembly.

Use this Skill when you want to determine local orientation for pose estimation, grasp planning, or fine manipulation in dense or complex industrial scenes.

The Skill

python
from telekinesis import vitreous
import numpy as np

local_principal_axis = vitreous.estimate_principal_axis_within_radius(
    point_cloud=point_cloud,
    neighborhood_radius=1.0,
    reference_point=np.array([0.0, 0.0, 0.0]),
)

API Reference

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

Input Point Cloud

Estimated principal axis shown in red calculated for neighborhood of a reference point.
Parameters: reference_point = np.array([0., 0., -0.52], dtype=np.float32), neighborhood_radius = 0.25.

The Code

python
from telekinesis import vitreous
from datatypes import datatypes, io
import pathlib

# Optional for logging
from loguru import logger

DATA_DIR = pathlib.Path("path/to/telekinesis-data")

# Load point cloud
filepath = str(DATA_DIR / "point_clouds" / "can_vertical_3_downsampled.ply")
point_cloud = io.load_point_cloud(filepath=filepath)
logger.success(f"Loaded point cloud with {len(point_cloud.positions)} points")

neighborhood_radius = 50.0
reference_point = [90, 50, 600]

# Execute operation
local_principal_axis = vitreous.estimate_principal_axis_within_radius(
  point_cloud=point_cloud,
  neighborhood_radius=neighborhood_radius,
  reference_point=reference_point,
)
logger.success(
  f"Estimated principal axis within radius {neighborhood_radius} at {reference_point}"
)

The Explanation of the Code

We begin by importing the necessary modules: vitreous for point cloud operations, datatypes and io for handling data, pathlib for file path management, and loguru for optional logging.

python
from telekinesis import vitreous
from datatypes import datatypes, io
import pathlib

# Optional for logging
from loguru import logger

Next, the point cloud is loaded from a .ply file. This is the 3D data that will be analyzed, and logging is used to verify the number of points to ensure the data is correct.

python
# Load point cloud
filepath = str(DATA_DIR / "point_clouds" / "can_vertical_3_downsampled.ply")
point_cloud = io.load_point_cloud(filepath=filepath)
logger.success(f"Loaded point cloud with {len(point_cloud.positions)} points")

Finally, the estimate_principal_axis_within_radius Skill is applied. A local neighborhood is defined around a reference point with a given radius, and Principal Component Analysis (PCA) is used to determine the dominant axis of variation within that local region. This is particularly useful in industrial robotics pipelines, for example to identify the orientation of a handle, tube, or other cylindrical feature for pick-and-place tasks, alignment, or insertion operations. Logging confirms that the principal axis was successfully estimated.

python
# Execute operation
local_principal_axis = vitreous.estimate_principal_axis_within_radius(
  point_cloud=point_cloud,
  neighborhood_radius=neighborhood_radius,
  reference_point=reference_point,
)
logger.success(
  f"Estimated principal axis within radius {neighborhood_radius} at {reference_point}"
)

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:

bash
cd telekinesis-examples
python examples/vitreous_examples.py --example estimate_principal_axis_within_radius

How to Tune the Parameters

The estimate_principal_axis_within_radius Skill has two parameters that control the local neighborhood analysis:

neighborhood_radius (default: 1.0):

  • The radius of the spherical neighborhood around the reference point
  • Units: Uses the same units as your point cloud (e.g., if point cloud is in meters, radius is in meters; if in millimeters, radius is in millimeters)
  • Increase to consider more points, providing a more global principal axis but may include points from different regions
  • Decrease to use fewer points, giving a more local principal axis
  • Should be set based on the scale of features you want to analyze:
    • Millimeter-scale point clouds (e.g., Zivid where 1 unit = 1 mm): Typical values 10-1000 (representing 10-1000 mm radius)
    • Centimeter-scale point clouds (e.g., 1 unit = 1 cm): Typical values 1-100 (representing 1-100 cm radius)
    • Meter-scale point clouds (e.g., 1 unit = 1 m): Typical values 0.1-10.0 (representing 0.1-10.0 m radius)
  • Use smaller values for local features, larger values for regional or global analysis

reference_point (default: np.array([0.0, 0.0, 0.0])):

  • The 3D center point around which to analyze the neighborhood
  • Units: Uses the same units as your point cloud
  • Only points within neighborhood_radius of this point are used for principal axis estimation
  • Typically set to a point of interest or the center of a region to analyze
  • Default: [0.0, 0.0, 0.0] (origin)

TIP

Best practice: Set reference_point to the center of the feature you want to analyze (e.g., centroid of a cluster, center of an object). Adjust neighborhood_radius based on the size of the feature relative to your point cloud scale.

Where to Use the Skill in a Pipeline

Local principal axis estimation is commonly used in the following pipelines:

  • Local feature analysis and alignment
  • Grasp planning for elongated objects
  • Fine manipulation and insertion tasks
  • Edge and rod detection

A typical pipeline for local feature analysis looks as follows:

python
# Example pipeline using local principal axis estimation (parameters omitted).

from telekinesis import vitreous
import numpy as np

# 1. Load raw point cloud
point_cloud = vitreous.load_point_cloud(...)

# 2. Preprocess: remove outliers and downsample
filtered_cloud = vitreous.filter_point_cloud_using_statistical_outlier_removal(...)
downsampled_cloud = vitreous.filter_point_cloud_using_voxel_downsampling(...)

# 3. Cluster to separate objects
clusters = vitreous.cluster_point_cloud_using_dbscan(...)

# 4. For each cluster, analyze local features
for cluster in clusters:
    # Get centroid as reference point
    centroid = vitreous.calculate_point_cloud_centroid(point_cloud=cluster)
    
    # Estimate local principal axis around centroid
    local_axis = vitreous.estimate_principal_axis_within_radius(
        point_cloud=cluster,
        neighborhood_radius=50.0,  # Adjust based on point cloud scale
        reference_point=centroid,
    )
    # Use local axis for alignment or grasp planning

# 5. Optional: Use local axis for tool orientation

Related skills to build such a pipeline:

  • filter_point_cloud_using_statistical_outlier_removal: clean input before axis estimation
  • filter_point_cloud_using_voxel_downsampling: reduce point cloud density for faster processing
  • cluster_point_cloud_using_dbscan: separate objects before analyzing individual features
  • calculate_point_cloud_centroid: get reference point for local analysis
  • estimate_principal_axes: estimate global principal axes instead of local

Alternative Skills

Skillvs. Estimate Principal Axis Within Radius
estimate_principal_axesUse estimate_principal_axes when you need the principal axes of the entire point cloud. Use estimate_principal_axis_within_radius when you need the principal axis of a local neighborhood.
calculate_oriented_bounding_boxUse OBB when you need both orientation and size/extent information for the entire object. Use local principal axis when you need orientation of a specific local region.

When Not to Use the Skill

Do not use estimate principal axis within radius when:

  • You need global orientation (use estimate_principal_axes instead)
  • You need size or extent information (use calculate_oriented_bounding_box instead)
  • The neighborhood is too sparse (not enough points within the radius for reliable PCA)
  • You don't know where to place the reference point (use estimate_principal_axes for global analysis first)
  • The local region has no clear dominant direction (the principal axis may not be meaningful)

WARNING

This Skill requires sufficient points within the neighborhood_radius to compute a reliable principal axis. If the neighborhood is too sparse, the result may be unreliable. Consider preprocessing the point cloud or adjusting the radius.