Filter Point Cloud Using Pass Through Filter
SUMMARY
Filter Point Cloud Using Pass Through Filter keeps only the points that fall inside an axis-aligned min/max box.
A point survives only if x_min <= x <= x_max, y_min <= y <= y_max, and z_min <= z <= z_max hold independently, all at once — the simplest way to crop a point cloud to a known region of interest, such as a robot's workspace, using six scalar bounds. Compare with filter_point_cloud_using_bounding_box, which takes a datatypes.Box3D object instead of six separate scalars, and filter_point_cloud_using_oriented_bounding_box, for a box that can also rotate.
Use this Skill when you want to crop a point cloud to a known axis-aligned region using simple min/max coordinate bounds.
The Skill
from telekinesis import vitreous
filtered_point_cloud = vitreous.filter_point_cloud_using_pass_through_filter(
point_cloud=point_cloud,
x_min=-100.0,
x_max=100.0,
y_min=-100.0,
y_max=100.0,
z_min=-100.0,
z_max=100.0,
)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.
Passthrough Filter
Passthrough filter in red overlayed with the unprocessed point cloud. The corners of the box correspond to the min/max bounds for each axis.
Filtered Points
Only the points that fall within the specified 3D box defined by min/max coordinates along each axis are kept.
The Code
"""
Demonstrates filtering points within axis-aligned min/max ranges.
"""
from loguru import logger
import rerun as rr
from telekinesis import vitreous, datatypes
def filter_point_cloud_using_pass_through_filter_example():
"""
Filters points within axis-aligned min/max ranges.
Keeps only points where each coordinate (x, y, z) falls within specified
min/max bounds.
"""
# ===================== Load Data ==========================================
point_cloud_url = (
"https://assets.telekinesis.ai/examples/v1/point_clouds/mounts_3_raw.ply"
)
point_cloud = datatypes.PointCloud.from_url(url=point_cloud_url, use_cache=True)
# ===================== Run Skill ==========================================
filtered_point_cloud = vitreous.filter_point_cloud_using_pass_through_filter(
x_min=-185.0,
x_max=230.0,
y_min=-164.0,
y_max=164.0,
z_min=450.0,
z_max=548.0,
point_cloud=point_cloud,
)
# ===================== Log ================================================
logger.success(f"Filtered {point_cloud} using axis-aligned range")
logger.success(f"Results: {filtered_point_cloud}")
logger.info(
f"Filtered point cloud positions shape: {filtered_point_cloud.positions.shape}"
)
logger.info(
f"Filtered point cloud has normals shape: "
f"{filtered_point_cloud.normals.shape if filtered_point_cloud.has_normals else None}"
)
logger.info(
f"Filtered point cloud has colors shape: "
f"{filtered_point_cloud.colors.shape if filtered_point_cloud.has_colors else None}"
)
# ===================== Visualization (Optional) ===========================
rr.init("filter_point_cloud_using_pass_through_filter_example", spawn=True)
datatypes.visualize(point_cloud, entity_path="/1-input_point_cloud")
datatypes.visualize(filtered_point_cloud, entity_path="/2-filtered_point_cloud")
if __name__ == "__main__":
filter_point_cloud_using_pass_through_filter_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_point_cloud_using_pass_through_filter.pyParameter Configuration
These six scalar bounds define the axis-aligned box; a point is kept only if it falls within all three ranges at once.
| Parameter | Type | Default | Description |
|---|---|---|---|
point_cloud | datatypes.PointCloud | required | The point cloud to filter. Must contain at least one point |
x_min | datatypes.Float | float | int | -100.0 | Minimum x coordinate, in the point cloud's coordinate units, to keep. Points with x < x_min are removed; must be less than x_max |
x_max | datatypes.Float | float | int | 100.0 | Maximum x coordinate, in the point cloud's coordinate units, to keep. Points with x > x_max are removed; must be greater than x_min |
y_min | datatypes.Float | float | int | -100.0 | Minimum y coordinate, in the point cloud's coordinate units, to keep. Same behavior as x_min along the y-axis |
y_max | datatypes.Float | float | int | 100.0 | Maximum y coordinate, in the point cloud's coordinate units, to keep. Same behavior as x_max along the y-axis |
z_min | datatypes.Float | float | int | -100.0 | Minimum z coordinate, in the point cloud's coordinate units, to keep. Same behavior as x_min along the z-axis |
z_max | datatypes.Float | float | int | 100.0 | Maximum z coordinate, in the point cloud's coordinate units, to keep. Same behavior as x_max along the z-axis |
Returns
| Type | Description |
|---|---|
datatypes.PointCloud | A point cloud containing only the points that fell inside the box; returns an empty datatypes.PointCloud if none did. Use .positions for the surviving (N, 3) position array and len(...) for the point count. |
Raises
| Exception | Condition |
|---|---|
TypeError | A parameter's value does not match its expected type (see the Parameter Configuration table above) |
ValueError | x_min is not less than x_max, y_min is not less than y_max, or z_min is not less than z_max |
ConfigurationError | The TELEKINESIS_API_KEY environment variable is not set |
SerializationError | The request input failed to serialize, the response was not returned as an Arrow stream, 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 or malformed input (HTTP 400/422), an unrecognized endpoint (HTTP 404), or another unexpected 4xx response |
AuthenticationError | The API key was rejected as invalid or expired (HTTP 401) |
AuthenticationServiceError | The authentication service returned an invalid response, was temporarily unavailable, or timed out (HTTP 502/503/504) |
ServerError | The Vitreous service returned a 5xx or otherwise unexpected error response |
How to Tune the Parameters
The filter_point_cloud_using_pass_through_filter skill exposes six scalar bounds — a min/max pair for each axis — that together define the axis-aligned crop box.
In general, tightening any pair shrinks the box and keeps fewer points; loosening a pair grows the box and keeps more. If a _min bound isn't strictly less than its _max counterpart on any axis, the Skill raises a ValueError rather than silently returning an empty or unintended result.
x_min / x_max
- Controls: The minimum and maximum x coordinate a point may have and still be kept.
- Units: The point cloud's coordinate units (see the tip below)
- Default:
-100.0/100.0 - Narrow the range to crop tightly around a known x-extent, such as a workspace or conveyor width;
x_minmust stay less thanx_max - Typical range: -100.0 to 100.0, depending on scene scale
y_min / y_max
- Controls: The minimum and maximum y coordinate a point may have and still be kept.
- Units: The point cloud's coordinate units
- Default:
-100.0/100.0 - Same behavior as
x_min/x_max, applied along the y-axis - Typical range: -100.0 to 100.0, depending on scene scale
z_min / z_max
- Controls: The minimum and maximum z coordinate a point may have and still be kept.
- Units: The point cloud's coordinate units
- Default:
-100.0/100.0 - Same behavior as
x_min/x_max, applied along the z-axis — often the first axis to narrow when isolating a specific height or depth band, such as a shelf or table - Typical range: -100.0 to 100.0, depending on scene scale
TIP
Because the box is axis-aligned and defined by six independent scalars, it's straightforward to compute programmatically — for example, derive the six bounds from an existing datatypes.Box3D (such as one returned by calculate_axis_aligned_bounding_box) instead of hand-picking them.
Where to Use the Skill
Common pipelines include:
- Workspace region extraction – Cropping sensor data to a robot's reachable workspace before detection or grasp planning
- Conveyor or bin isolation – Removing points outside a known conveyor belt or bin footprint
- Background removal – Discarding points far outside the scene of interest along one or more axes
- Depth-range gating – Keeping only points within a known height or depth band, such as above a table or below a ceiling
Alternative Skills
| Skill | vs. Filter Point Cloud Using Pass Through Filter |
|---|---|
| filter_point_cloud_using_bounding_box | Takes the box as a single datatypes.Box3D object instead of six separate scalars — convenient when the box already exists, e.g. from calculate_axis_aligned_bounding_box, rather than being hand-picked. |
| filter_point_cloud_using_oriented_bounding_box | Uses a box that can rotate away from the world's X/Y/Z axes. Use it when the region of interest isn't axis-aligned; use this Skill when it is. |
When Not to Use the Skill
Do not use Filter Point Cloud Using Pass Through Filter when:
- The region of interest is rotated relative to the world axes – an axis-aligned box will either clip the region or include extra space; use
filter_point_cloud_using_oriented_bounding_boxinstead - You already have the region as a
datatypes.Box3Dobject – pass it directly tofilter_point_cloud_using_bounding_boxinstead of decomposing it back into six scalars - You need to filter by distance from a plane rather than a box – use
filter_point_cloud_using_plane_proximityorfilter_point_cloud_using_plane_defined_by_point_normal_proximityinstead - A
_minbound isn't strictly less than its_maxcounterpart on any axis – this raises aValueErrorrather than filtering; fix the bound instead of relying on the Skill to handle it
TIP
The six bounds are expressed in whatever length unit your point cloud already uses, not necessarily meters — the example above filters a point cloud whose coordinates run into the hundreds, consistent with millimeters rather than meters. Check point_cloud.positions's actual scale before picking bounds if you're unsure.