label_based_euclidean_cluster#
Purpose#
label_based_euclidean_cluster converts object-compatible semantic pointcloud labels into DetectedObjects.
It groups points by semantic class, clusters each label bucket independently, and estimates a shape for every resulting cluster.
Non-object semantic labels are published as segment pointclouds.
This node is intended for segmented pointcloud inputs published as autoware::point_types::PointXYZCPE, which carry the semantic label as class_id and the per-point confidence as probability.
Inputs / Outputs#
Input#
| Name | Type | Description |
|---|---|---|
~/input/pointcloud |
sensor_msgs::msg::PointCloud2 |
segmented autoware::point_types::PointXYZCPE cloud |
The input point type is assumed to be autoware::point_types::PointXYZCPE, that is a densely packed
24-byte point with the following fields. Clouds with any other layout are rejected and reported with
a throttled warning.
x,y,z(float32): point position.class_id(uint8):PointCloudClassificationvalue for each point.probability(float32): semantic confidence for each point.entropy(float32): normalized prediction entropy,NaNwhen it is unavailable. Not used by this node, but preserved in the segment output.
Output#
| Name | Type | Description |
|---|---|---|
~/output/objects |
autoware_perception_msgs::msg::DetectedObjects |
detected objects estimated per cluster |
~/output/pointcloud |
sensor_msgs::msg::PointCloud2 |
non-object semantic points with original fields |
Processing Flow#
- Validate that the incoming pointcloud is a densely packed
autoware::point_types::PointXYZCPEcloud. - Interpret
class_idvalues asPointCloudClassification. - Send object-compatible classifications through clustering and copy non-object or unknown classifications to
output_segments. - Drop points with
probability < min_probability. - Split object-compatible points into buckets keyed by the Autoware object label.
- Run
VoxelGridBasedEuclideanClusterindependently for each label bucket, using the per-label parameter overrides fromlabel_cluster_params.*where configured and the global defaults otherwise. - Merge over-segmented clusters across labels that belong to the same confusable label group (
confusable_label_groups.*). - Compute the average semantic probability for each output cluster from the points that ended up in that cluster. This uses the source-point indices returned by the clustering backend for the per-label filtered cloud, rather than rematching points by coordinate.
- Estimate a shape and pose for each cluster with
ShapeEstimator. - If shape estimation does not produce a usable shape, fall back to an axis-aligned bounding shape computed from the clustered points.
Shape Estimation Behavior#
After clustering, the node converts each cluster into a DetectedObject.
- The output classification label is the mapped object label for that bucket.
- The output existence probability is the average of the clustered point probabilities for that object instance.
- Shape estimation is delegated to
autoware::shape_estimation::ShapeEstimator. shape_policy=0(ALL_POLYGON) estimates whole shapes as polygon.shape_policy=1(LABEL_DEPEND) estimates shapes with the mapped object label.
If the estimator does not return a usable shape:
pedestrianfalls back toCYLINDER- all other labels fall back to
BOUNDING_BOX
The fallback shape uses the cluster axis-aligned min/max extents, with each dimension clamped to at least 0.1 m.
Parameters#
Parameters are loaded from config/label_based_euclidean_cluster.param.yaml.
| Name | Type | Description | Default | Range |
|---|---|---|---|---|
| use_height | boolean | Use point.z for clustering. | 0 | N/A |
| tolerance_m | float | The spatial cluster tolerance as a measure in the L2 Euclidean space. | 0.7 | N/A |
| min_points_per_cluster | integer | The minimum number of points that a cluster needs to contain in order to be considered valid. | 10 | N/A |
| voxel_leaf_size_m | float | The voxel leaf size of x and y. | 0.2 | N/A |
| min_points_per_voxel | integer | The minimum number of points required per voxel. | 1 | N/A |
| large_cluster_voxel_count_threshold | integer | The minimum voxel cluster size for a cluster to be checked for being a large cluster. | 10 | N/A |
| large_cluster_max_points_per_voxel | integer | The maximum points per voxel allowed in large clusters. | 100 | N/A |
| max_voxels_per_cluster | integer | Maximum number of voxels in a cluster when outputted. | 1000 | ≥1 |
| min_probability | float | Minimum semantic probability required for a point to be used. | 0.3 | N/A |
| use_shape_estimation_corrector | boolean | Enable the shape estimation corrector. | 0 | N/A |
| use_shape_estimation_filter | boolean | Enable the shape estimation filter. | 0 | N/A |
| use_boost_bbox_optimizer | boolean | Enable the boost bounding-box optimizer. | 0 | N/A |
| shape_policy | integer | Shape estimation policy. 0: ALL_POLYGON, 1: LABEL_DEPEND. | 0 | [0, 1] |
Per-Label Clustering Parameter Overrides#
The clustering parameters at the top level (use_height, tolerance_m, voxel_leaf_size_m,
min_points_per_voxel, min_points_per_cluster, large_cluster_voxel_count_threshold,
large_cluster_max_points_per_voxel, max_voxels_per_cluster) define a single global
VoxelGridBasedEuclideanCluster that is used for every label bucket by default.
label_cluster_params.<label> lets each label run with its own tuned clustering instance instead.
This is useful because the spatial density and size of objects differ by class: pedestrians and
hazards need a tighter tolerance and finer voxels than cars or trucks.
<label>must be one of the supported Autoware object labels (unknown,car,bus,truck,trailer,motorcycle,bicycle,pedestrian,animal,hazard).- Each override block accepts the same keys as the global clustering parameters.
- Any key omitted inside an override block falls back to the corresponding global value, so a block only needs to list the parameters that differ.
- A label with no override block (or an empty one) keeps using the global default cluster.
- When a label-specific cluster is created, the node logs
Using custom cluster params for label '<label>'at startup.
Example: give pedestrians a tighter tolerance and finer voxels while leaving everything else on the global defaults.
tolerance_m: 0.65
voxel_leaf_size_m: 0.2
# ... other global defaults ...
label_cluster_params:
pedestrian:
tolerance_m: 0.3
voxel_leaf_size_m: 0.1
min_points_per_voxel: 1
min_points_per_cluster: 3
large_cluster_voxel_count_threshold: 5
large_cluster_max_points_per_voxel: 30
max_voxels_per_cluster: 200
Confusable-Label Merge#
Because each label bucket is clustered independently, a single physical object whose points carry two
semantically confusable labels (for example a truck and its trailer, where the segmentation model
splits one vehicle across the truck and trailer classes) is split into separate clusters.
confusable_label_groups.* performs an optional post-clustering merge that stitches such pieces back
together.
Each entry under confusable_label_groups is a user-named group:
labels: the list of labels (two or more) that may be merged with each other. Only clusters of different labels within the same group are considered for merging; clusters that share a label are never merged here.cross_label_tolerance_m: the maximum point-to-point XY gap between two clusters for them to be joined. The gap is the true minimum distance between the closest points of the two clusters (measured in the XY plane, height is ignored).max_merged_size_m(default25.0): an upper bound on the diameter of a merged component. A union that would produce a bounding circle larger than this is refused, so a chain of nearby clusters cannot collapse a dense scene into one oversized blob.
Notes:
- A label may appear in at most one group. If it is listed in several, the first group wins and a warning is logged.
- Labels not listed in any group are passed through unchanged.
Example: merge truck and trailer fragments that are within 0.5 m of each other, capping the
merged object at a 25 m diameter.
confusable_label_groups:
truck_trailer:
labels: ["truck", "trailer"]
cross_label_tolerance_m: 0.5
max_merged_size_m: 25.0
Default Configuration Notes#
The default parameter file keeps shared clustering and shape-estimation parameters only.
Object selection is derived from PointCloudClassification compatibility.
Assumptions / Known Limits#
- The node assumes the incoming pointcloud already represents semantically segmented points and uses the
autoware::point_types::PointXYZCPElayout. class_idvalues are interpreted asPointCloudClassificationvalues.- Non-object or unknown
PointCloudClassificationvalues are copied tooutput/pointcloudwith the original point fields preserved. - Inputs whose layout differs from
autoware::point_types::PointXYZCPEare rejected instead of being clustered with default values. - Clustering is spatial only; there is no temporal association or tracking.
Intended Usage#
Use this node when a segmentation model already separates obstacle classes in the pointcloud and the next step is to produce object-level DetectedObjects without mixing points from different semantic classes into the same cluster.
Future Extensions / Follow-up Works#
The following items came up during PR review as acceptable short-term trade-offs, but they remain good candidates for follow-up work.
- Load semantic label order from the segmentation model artifact, such as
label.txt, and keep the ROS parameter file focused on label selection and Autoware label remapping instead of treating YAML declaration order as the source of truth. - Improve uncertainty-aware clustering so point-level probabilities can be propagated with richer statistics than a simple per-cluster average, such as entropy-aware aggregation or quantile-based gating.
- Improve large-cluster downsampling in the internal voxel-grid-based cluster with deterministic voxel-wise, spatially uniform, or edge-preserving sampling so shape estimation keeps outline points more reliably.