【问题标题】:how to effeciently convert ROS PointCloud2 to pcl point cloud and visualize it in python如何有效地将 ROS PointCloud2 转换为 pcl 点云并在 python 中可视化
【发布时间】:2017-02-07 21:42:50
【问题描述】:

我正在尝试从 ROS 中的 kinect 对点云进行一些分割。截至目前,我有这个:

import rospy
import pcl
from sensor_msgs.msg import PointCloud2
import sensor_msgs.point_cloud2 as pc2
def on_new_point_cloud(data):
    pc = pc2.read_points(data, skip_nans=True, field_names=("x", "y", "z"))
    pc_list = []
    for p in pc:
        pc_list.append( [p[0],p[1],p[2]] )

    p = pcl.PointCloud()
    p.from_list(pc_list)
    seg = p.make_segmenter()
    seg.set_model_type(pcl.SACMODEL_PLANE)
    seg.set_method_type(pcl.SAC_RANSAC)
    indices, model = seg.segment()

rospy.init_node('listener', anonymous=True)
rospy.Subscriber("/kinect2/hd/points", PointCloud2, on_new_point_cloud)
rospy.spin()

这似乎可行,但由于 for 循环而非常慢。 我的问题是:

1) 我如何有效地将 PointCloud2 消息转换为 pcl 点云

2) 我如何可视化云。

【问题讨论】:

    标签: python kinect ros point-clouds


    【解决方案1】:

    在带有 Python3 的 Ubuntu 20.04 上,我使用以下内容:

    import numpy as np
    import pcl  # pip3 install python-pcl
    import ros_numpy  # apt install ros-noetic-ros-numpy
    import rosbag
    import sensor_msgs
    
    def convert_pc_msg_to_np(pc_msg):
        # Fix rosbag issues, see: https://github.com/eric-wieser/ros_numpy/issues/23
        pc_msg.__class__ = sensor_msgs.msg._PointCloud2.PointCloud2
        offset_sorted = {f.offset: f for f in pc_msg.fields}
        pc_msg.fields = [f for (_, f) in sorted(offset_sorted.items())]
    
        # Conversion from PointCloud2 msg to np array.
        pc_np = ros_numpy.point_cloud2.pointcloud2_to_xyz_array(pc_msg, remove_nans=True)
        pc_pcl = pcl.PointCloud(np.array(pc_np, dtype=np.float32))
        return pc_np, pc_pcl  # point cloud in numpy and pcl format
    
    # Use a ros subscriber as you already suggested or is shown in the other
    # answers to run it online :)
    
    # To run it offline on a rosbag use:
    for topic, msg, t in rosbag.Bag('/my/rosbag.bag').read_messages():
        if topic == "/my/cloud":
            pc_np, pc_pcl = convert_pc_msg_to_np(msg)
    
    
    

    【讨论】:

      【解决方案2】:

      这对我有用。我只是调整点云的大小,因为我的是一台订购的电脑(512x x 512px)。我的代码改编自 @Abdulbaki Aybakan - 谢谢!

      我的代码:

      pc = ros_numpy.numpify(pointcloud)
      height = pc.shape[0]
      width = pc.shape[1]
      np_points = np.zeros((height * width, 3), dtype=np.float32)
      np_points[:, 0] = np.resize(pc['x'], height * width)
      np_points[:, 1] = np.resize(pc['y'], height * width)
      np_points[:, 2] = np.resize(pc['z'], height * width)
      

      要使用 ros_numpy,必须克隆 repo:http://wiki.ros.org/ros_numpy

      【讨论】:

      • 如果pointcloud 有漏洞,这是否有效?这些会成为np_points中的NaN吗?
      • 不确定这是否适用于有序的 pointcloud2,但如果您将每个洞的每个点的每个值都设置为 NaN,它可能会起作用。然后应将“is_dense”标志设置为 False,请参阅:docs.ros.org/melodic/api/sensor_msgs/html/msg/PointCloud2.html
      【解决方案3】:
      import rospy
      import pcl
      from sensor_msgs.msg import PointCloud2
      import sensor_msgs.point_cloud2 as pc2
      import ros_numpy
      
      def callback(data):
          pc = ros_numpy.numpify(data)
          points=np.zeros((pc.shape[0],3))
          points[:,0]=pc['x']
          points[:,1]=pc['y']
          points[:,2]=pc['z']
          p = pcl.PointCloud(np.array(points, dtype=np.float32))
      
      rospy.init_node('listener', anonymous=True)
      rospy.Subscriber("/velodyne_points", PointCloud2, callback)
      rospy.spin()
      

      我更喜欢使用 ros_numpy 模块首先转换为 numpy 数组并从该数组初始化点云。

      【讨论】:

      • 这不适用于 ROS melodic,因为它没有 ros_numpy。我们能否以某种方式使用其他东西来解释变量data?或者这是唯一的方法?
      • 模块 pcl 在哪里
      猜你喜欢
      • 2018-10-06
      • 2012-04-23
      • 2021-11-14
      • 1970-01-01
      • 2022-07-31
      • 1970-01-01
      • 2021-04-06
      • 1970-01-01
      • 2019-02-24
      相关资源
      最近更新 更多