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
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]),
)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
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.
from telekinesis import vitreous
from datatypes import datatypes, io
import pathlib
# Optional for logging
from loguru import loggerNext, 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.
# 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.
# 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:
cd telekinesis-examples
python examples/vitreous_examples.py --example estimate_principal_axis_within_radiusHow 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_radiusof 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:
# 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 orientationRelated skills to build such a pipeline:
filter_point_cloud_using_statistical_outlier_removal: clean input before axis estimationfilter_point_cloud_using_voxel_downsampling: reduce point cloud density for faster processingcluster_point_cloud_using_dbscan: separate objects before analyzing individual featurescalculate_point_cloud_centroid: get reference point for local analysisestimate_principal_axes: estimate global principal axes instead of local
Alternative Skills
| Skill | vs. Estimate Principal Axis Within Radius |
|---|---|
| estimate_principal_axes | Use 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_box | Use 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_axesinstead) - You need size or extent information (use
calculate_oriented_bounding_boxinstead) - 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_axesfor 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.

