Skip to content

Filter Mesh Using Cylinder Base Removal

SUMMARY

Filter Mesh Using Cylinder Base Removal removes the base (bottom cap) of a roughly cylindrical mesh.

It detects the base of a cylindrical datatypes.Mesh3D — for example a scanned rod, pipe, or bottle — and removes the vertices and faces within distance_threshold of it, cutting the base off before further processing such as convert_mesh_to_point_cloud. This Skill operates on a datatypes.Mesh3D, not a datatypes.PointCloud — pass it a mesh, not a point cloud.

Use this Skill when you want to cut the flat mounting base off a scanned cylindrical mesh before pose estimation, alignment, or further mesh processing.

The Skill

python
from telekinesis import vitreous

filtered_mesh = vitreous.filter_mesh_using_cylinder_base_removal(
    mesh=mesh,
    distance_threshold=0.01,
    compute_vertex_normals=True,
)
API Reference
Full parameter and return type documentation for filter_mesh_using_cylinder_base_removal.
View Reference →

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

Raw Sensor Input

Unprocessed point cloud captured directly from the sensor.

Filtered Point Cloud

Input point cloud overlayed with the plane for extraction.

The Code

python
"""
Demonstrates removing the base faces from a cylindrical mesh, leaving only the curved side surface.
"""

from loguru import logger
import rerun as rr

from telekinesis import vitreous, datatypes


def filter_mesh_using_cylinder_base_removal_example():
    """
    Removes the base faces from a cylindrical mesh.

    Identifies and removes triangles that form the flat base(s) of a cylinder,
    leaving only the curved side surface.
    """
    # ===================== Load Data ==========================================
    mesh_url = "https://assets.telekinesis.ai/examples/v1/meshes/beer_can.glb"
    mesh = datatypes.Mesh3D.from_url(url=mesh_url, use_cache=True)

    # ===================== Run Skill ==========================================
    filtered_mesh = vitreous.filter_mesh_using_cylinder_base_removal(
        mesh=mesh,
        compute_vertex_normals=True,
        distance_threshold=0.005,
    )

    # ===================== Log ================================================
    logger.success(f"Filtered {mesh} using cylinder base removal")
    logger.success(f"Results: {filtered_mesh}")
    logger.info(
        f"Filtered mesh has {len(filtered_mesh.vertex_positions)} vertices "
        f"and {len(filtered_mesh.triangle_indices)} triangles"
    )
    logger.info(
        f"Filtered mesh has vertex normals: {filtered_mesh.has_vertex_normals}, "
        f"vertex colors: {filtered_mesh.has_vertex_colors}"
    )

    # ===================== Visualization  (Optional) ===========================
    rr.init("filter_mesh_using_cylinder_base_removal_example", spawn=True)
    datatypes.visualize(mesh, entity_path="/1-original_mesh")
    datatypes.visualize(filtered_mesh, entity_path="/2-filtered_mesh")


if __name__ == "__main__":
    filter_mesh_using_cylinder_base_removal_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:

bash
cd telekinesis-examples
python examples/point_cloud/filter_mesh_using_cylinder_base_removal.py

Parameter Configuration

mesh must be a datatypes.Mesh3D, not a datatypes.PointCloud — this is the one Skill in this group whose primary input is a mesh rather than a point cloud.

KeyTypeDefaultDescription
meshdatatypes.Mesh3DrequiredThe mesh to filter. Should represent a roughly cylindrical object (a rod, pipe, or bottle) for base detection to work well. Not a datatypes.PointCloud
distance_thresholddatatypes.Float | float | int0.01Maximum distance, in the mesh's coordinate units, from the detected base plane within which vertices are removed. Must be >= 0
compute_vertex_normalsdatatypes.Bool | boolTrueWhether to recompute per-vertex normals for the resulting mesh (the original normals no longer match after vertices/faces are removed)

Returns

TypeDescription
datatypes.Mesh3DA mesh with the base region removed. Use len(mesh) (or len(mesh.vertex_positions)) for the remaining vertex count and len(mesh.triangle_indices) for the remaining triangle count.

Raises

ExceptionCondition
TypeErrorA parameter's value does not match its expected type (see the Parameter Configuration table above)
ValueErrordistance_threshold is negative (must be >= 0)
ConfigurationErrorThe TELEKINESIS_API_KEY environment variable is not set
SerializationErrorThe request input failed to serialize, or the response failed to deserialize
RequestTimeoutErrorThe request to the Vitreous service timed out
TransportErrorA network failure occurred before a response was received
ClientErrorThe Vitreous service rejected the request due to invalid input, invalid data, or another unexpected 4xx response
AuthenticationErrorThe API key was rejected as invalid or expired
AuthenticationServiceErrorThe authentication service was unavailable
ServerErrorThe Vitreous service returned a 5xx or otherwise unexpected error response

How to Tune the Parameters

filter_mesh_using_cylinder_base_removal exposes two parameters.

distance_threshold

  • Controls: How far from the detected base plane a vertex can be and still be removed — a thicker or thinner "cut."
  • Units: The mesh's own coordinate units (not necessarily meters)
  • Default: 0.01
  • Must be >= 0 — a negative value raises a ValueError
  • Increase → removes more of the base region (a thicker cut)
  • Decrease → removes less (a thinner cut)
  • Scale it to the cylinder's size and how much you want removed
  • Typical range: 0.001–0.1 — use 0.001–0.01 for a precise, shallow cut, 0.01–0.05 for moderate, 0.05–0.1 for aggressive

compute_vertex_normals

  • Controls: Whether per-vertex normals are recomputed for the filtered mesh.
  • Default: True
  • True – recomputes normals so they stay correct after vertices/faces are removed (needed for lighting/rendering or any downstream skill that reads normals)
  • False – skips recomputation, saving time when normals aren't needed

TIP

Best practice: Check the mesh's approximate dimensions (e.g. from its vertex position range) before picking distance_threshold, rather than reusing a value tuned for a differently-scaled mesh — the same numeric threshold that's a shallow cut on a large pipe can remove most of a small bottle.

Where to Use the Skill

Common pipelines include:

  • Cylindrical part preprocessing – Removing a scanned rod, pipe, or bottle's flat base before pose estimation or grasp planning
  • Mounting-base cleanup – Cutting away a flat mounting base introduced by the scanning rig itself
  • Pre-conversion cleanup – Removing the base before convert_mesh_to_point_cloud so the resulting point cloud doesn't include base points
  • Object alignment – Isolating the curved side surface for downstream registration against a cylindrical CAD model

Alternative Skills

There is no direct alternative to this Skill in this group — it is specifically designed to remove the base of a roughly cylindrical mesh, and no other Vitreous Skill performs the equivalent operation on a mesh's base geometry.

When Not to Use the Skill

Do not use Filter Mesh Using Cylinder Base Removal when:

  • The input is a point cloud, not a mesh – this Skill requires a datatypes.Mesh3D; reconstruct a mesh first, or use a point-cloud-native filtering Skill instead
  • The mesh isn't roughly cylindrical – base detection is designed around a cylinder's geometry and won't behave predictably on other shapes
  • You need to preserve the base – this Skill only removes base regions; it has no option to keep them
  • The cylinder is very short relative to distance_threshold – an aggressive cut can remove most or all of the object along with the base