Calculate Plane Normal
SUMMARY
Calculate Plane Normal extracts the direction a plane faces, [a, b, c], from its equation coefficients [a, b, c, d] where ax + by + cz + d = 0.
It takes plane coefficients you already have — for example, from segment_point_cloud_using_plane — and returns just the normal direction as its own vector, ready to pass to a Skill that expects a plane defined by a point and a normal.
Use this Skill when you need to turn plane coefficients into a normal vector for filtering, projection, or orientation-based reasoning about a surface.
The Skill
from telekinesis import vitreous
plane_normal = vitreous.calculate_plane_normal(plane_coefficients=[a, b, c, d])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
Calculated Normal
The Code
"""
Demonstrates extracting the normal vector from plane coefficients.
"""
from loguru import logger
import rerun as rr
from telekinesis import vitreous, datatypes
def calculate_plane_normal_example():
"""
Extracts the normal vector from plane coefficients.
Extracts and normalizes the normal vector from plane equation coefficients
(ax + by + cz + d = 0).
"""
# ===================== Run Skill ==========================================
plane_coefficients = [0.0, 0.0, 1.0, 0.0]
normal_vector = vitreous.calculate_plane_normal(
plane_coefficients=plane_coefficients
)
# ===================== Log ================================================
logger.success(f"Calculated normal vector to {plane_coefficients}")
logger.success(f"Results: {normal_vector}")
logger.info(f"Normal vector as numpy array: {normal_vector.data}")
logger.info(f"Normal vector shape: {normal_vector.shape}")
logger.info(f"Normal vector ndim: {normal_vector.ndim}")
logger.info(f"Normal vector dtype: {normal_vector.dtype}")
# ===================== Visualization (Optional) ===========================
rr.init("calculate_plane_normal_example", spawn=True)
datatypes.visualize(normal_vector, entity_path="/normal_vector")
if __name__ == "__main__":
calculate_plane_normal_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/calculate_plane_normal.pyParameter Configuration
| Key | Type | Default | Description |
|---|---|---|---|
plane_coefficients | datatypes.Vector4D | np.ndarray | list[float] | required | The plane equation coefficients [a, b, c, d] where ax + by + cz + d = 0. Must have exactly 4 numeric elements. |
Returns
| Type | Description |
|---|---|
datatypes.Vector3D | The plane normal [a, b, c], taken directly from the input plane coefficients. Use .data for the raw (3,) array. |
Raises
| Exception | Condition |
|---|---|
TypeError | A parameter's value does not match its expected type (see the Parameter Configuration table above), or (for a list input) plane_coefficients contains a non-numeric element |
ValueError | plane_coefficients does not have exactly 4 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
calculate_plane_normal takes only plane_coefficients — there is nothing to tune. The result is fully determined by the first three coefficients of the input: whatever [a, b, c, d] you pass in, you get [a, b, c] back out.
The only thing that changes the result is where the coefficients themselves came from. If you don't have plane coefficients yet, get them from segment_point_cloud_using_plane, which fits a plane to a point cloud via RANSAC and returns its equation.
Where to Use the Skill
Common pipelines include:
- Surface alignment – extracting the normal of a plane found by
segment_point_cloud_using_planeto align a coordinate frame to a table, wall, or floor - Proximity filtering – passing the normal to
filter_point_cloud_using_plane_defined_by_point_normal_proximityto keep or remove points near a plane defined by a point and normal - Projection onto a plane – passing the normal to
project_point_cloud_to_plane_defined_by_point_normalto flatten points onto a known surface - Orientation-based reasoning – comparing normals across multiple detected planes to distinguish, e.g., a floor from a wall
Alternative Skills
There is no other Vitreous Skill for extracting a normal vector from plane coefficients — this is a single-purpose utility. If you already have the coefficients in a datatypes.Vector4D, np.ndarray, or list and don't need a typed datatypes.Vector3D result, the normal is literally the first three elements, plane_coefficients[:3].
When Not to Use the Skill
Do not use Calculate Plane Normal when:
- You don't have plane coefficients yet — segment a plane first with
segment_point_cloud_using_planeto obtain them. - Your coefficients don't represent a real plane — passing anything other than exactly 4 numeric values raises a
ValueErrorrather than returning a result. - You need the full plane equation, not just direction — this Skill only returns
[a, b, c]; keep the originalplane_coefficientsaround if you still need the offsetd.
TIP
The plane coefficients already contain the normal in [a, b, c]. Reach for this Skill when you need it as a typed datatypes.Vector3D for another Vitreous call (e.g. filter_point_cloud_using_plane_defined_by_point_normal_proximity); slice the coefficients yourself if you just need the raw numbers locally.

