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
from telekinesis import vitreous
filtered_mesh = vitreous.filter_mesh_using_cylinder_base_removal(
mesh=mesh,
distance_threshold=0.01,
compute_vertex_normals=True,
)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
"""
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:
cd telekinesis-examples
python examples/point_cloud/filter_mesh_using_cylinder_base_removal.pyParameter 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.
| Key | Type | Default | Description |
|---|---|---|---|
mesh | datatypes.Mesh3D | required | The 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_threshold | datatypes.Float | float | int | 0.01 | Maximum distance, in the mesh's coordinate units, from the detected base plane within which vertices are removed. Must be >= 0 |
compute_vertex_normals | datatypes.Bool | bool | True | Whether to recompute per-vertex normals for the resulting mesh (the original normals no longer match after vertices/faces are removed) |
Returns
| Type | Description |
|---|---|
datatypes.Mesh3D | A 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
| Exception | Condition |
|---|---|
TypeError | A parameter's value does not match its expected type (see the Parameter Configuration table above) |
ValueError | distance_threshold is negative (must be >= 0) |
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
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 aValueError - 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_cloudso 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

