You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rviz中可视化PC2转换点云并解决HDBSCAN聚类报错

问题解决与实现方案

报错原因

你触发报错的核心问题是numpy_msg()的入参要求是ROS消息类,但你传入了pcl点云对象p,类属性不匹配触发了AttributeError。
另外你定义的自定义msg也不合理:cluster.msg仅定义了单个float32字段,无法存储点云的x/y/z三维坐标信息,也不能直接在RViz中可视化。

最优实现方案

不需要自定义msg,直接发布 sensor_msgs/PointCloud2类型的带色点云即可,RViz原生支持该类型的可视化,还可以给不同聚类分配不同颜色,直观验证聚类效果。

修改后可运行代码

import hdbscan
import rospy
from sensor_msgs.msg import PointCloud2
import numpy as np
import ros_numpy
import time

rospy.init_node('hdbscan')
# 提前初始化发布者,不要放在回调里重复创建
pub_clusters = rospy.Publisher('cluster_pointcloud', PointCloud2, queue_size=1)

def callback(data):
    tstart = time.time()
    # 把输入的PointCloud2转numpy数组
    pc = ros_numpy.numpify(data)
    points = np.zeros((pc.shape[0], 3))
    points[:, 0] = pc['x']
    points[:, 1] = pc['y']
    points[:, 2] = pc['z']
    
    # HDBSCAN聚类
    clusterer = hdbscan.HDBSCAN(min_cluster_size=15, min_samples=1, alpha=1.3).fit(points)
    cluster_labels = clusterer.fit_predict(points)
    
    # 构建带RGB的点云数组
    # 随机生成不同聚类的颜色,噪声点(label=-1)设为灰色
    n_clusters = cluster_labels.max() + 1
    colors = np.random.randint(0, 255, size=(n_clusters, 3))
    rgba = np.zeros((points.shape[0], 4), dtype=np.uint8)
    for i, label in enumerate(cluster_labels):
        if label == -1:
            rgba[i] = [128, 128, 128, 255] # 噪声点灰色
        else:
            rgba[i, :3] = colors[label]
            rgba[i, 3] = 255
    
    # 构造符合ros_numpy要求的结构化数组
    cloud_arr = np.zeros(points.shape[0], dtype=[
        ('x', np.float32),
        ('y', np.float32),
        ('z', np.float32),
        ('rgb', np.uint32)
    ])
    cloud_arr['x'] = points[:, 0]
    cloud_arr['y'] = points[:, 1]
    cloud_arr['z'] = points[:, 2]
    # 把rgba转成uint32格式
    cloud_arr['rgb'] = rgba.view(np.uint32)
    
    # 转成PointCloud2消息发布
    ros_msg = ros_numpy.msgify(PointCloud2, cloud_arr, frame_id=data.header.frame_id)
    pub_clusters.publish(ros_msg)
    
    tstop = time.time()
    rospy.loginfo(f"聚类耗时: {tstop - tstart:.4f}s, 聚类数: {n_clusters}")

def listener():
    rospy.Subscriber('/wamv/sensors/lidars/lidar_wamv/points', PointCloud2, callback)
    rospy.spin()

if __name__ == '__main__':
    listener()

RViz可视化操作步骤

  • 运行你的ROS节点和rosbag
  • 启动RViz,在左侧面板点击Add,选择PointCloud2
  • 把PointCloud2插件的Topic选为/cluster_pointcloud
  • 把Color Transformer选为RGB8,即可看到不同颜色区分的聚类结果,噪声点为灰色。

内容的提问来源于stack exchange,提问作者Drizzy23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 23:36:00