[Python] Reading Pointcloud from .pcd to ROS PointCloud2

Discussão em 'Python' iniciado por Stack, Dezembro 20, 2024.

  1. Stack

    Stack Membro Participativo

    I want to create a simple python script to read some .pcd files and create a sensor_msgs::pointCloud2 for each in a rosbag.

    I tried using the python-pcl library, but I'm probably doing something wrong when adding the points to the data field, because when playing the rosbag and checking with RViz and echoing the topic I get no points.

    This is the part where I set the PointCloud2 msg.

    pcl_data = pcl.load(metadata_dir + "/" + pcd_path)

    # get data
    pcl_msg = sensor_msgs.msg.PointCloud2()
    pcl_msg.data = np.ndarray.tobytes(pcl_data.to_array())
    pcl_msg.header.stamp = rospy.Time(t_us/10000000.0)
    pcl_msg.header.frame_id = "robot_1/navcam_sensor"

    # Pusblish Pointcloud2 msg
    outbag.write("/robot_1/pcl_navcam", pcl_msg, rospy.Time(t_us/10000000.0))


    I also tried pypc without any luck as well.

    How would you do it? Maybe there is a ToROSMsg method somewhere like in the cpp version of pcl?

    Is there a python equivalent for what is very easily available in cpp: pcl::toROSMsg ?

    Thank you

    Here is the full code of the python script:

    #! /usr/bin/env python3

    import rospy
    import rosbag
    import tf2_msgs.msg
    import geometry_msgs.msg
    import sensor_msgs.msg
    import sys
    import os
    import json
    import numpy as np
    import tf.transformations as tf_transformations
    import pcl
    import json
    import math
    import pypcd
    import sensor_msgs.point_cloud2 as pc2
    import tf2_msgs.msg._TFMessage


    def main():
    output_bag_path = dataset_path + "rosbag.bag"
    with rosbag.Bag(output_bag_path, 'w') as outbag:

    # iterate metadata files with tfs
    metadata_dir = dataset_path + "Pointcloud/metadata"
    t_first_flag = False

    # for filename in os.listdir(metadata_dir):
    list_of_files = sorted( filter( lambda x: os.path.isfile(os.path.join(metadata_dir, x)),
    os.listdir(metadata_dir) ) )
    for filename in list_of_files:

    # open json file
    json_path = os.path.join(metadata_dir, filename)
    json_file = open(json_path)
    json_data = json.load(json_file)

    # get timestamp
    t_us = json_data \
    ["metadata"] \
    ["Timestamps"] \
    ["microsec"]
    t_ns, t_s = math.modf(t_us/1000000)

    # get camera tf
    pos = geometry_msgs.msg.Vector3( \
    json_data["metadata"] \
    ["pose_robotFrame_sensorFrame"] \
    ["data"] \
    ["translation"][0], \
    json_data["metadata"] \
    ["pose_robotFrame_sensorFrame"] \
    ["data"] \
    ["translation"][1], \
    json_data["metadata"] \
    ["pose_robotFrame_sensorFrame"] \
    ["data"] \
    ["translation"][2])
    quat = geometry_msgs.msg.Quaternion( \
    json_data["metadata"] \
    ["pose_robotFrame_sensorFrame"] \
    ["data"] \
    ["orientation"] \
    ["x"], \
    json_data["metadata"] \
    ["pose_robotFrame_sensorFrame"] \
    ["data"] \
    ["orientation"] \
    ["y"], \
    json_data["metadata"] \
    ["pose_robotFrame_sensorFrame"] \
    ["data"] \
    ["orientation"] \
    ["z"], \
    json_data["metadata"] \
    ["pose_robotFrame_sensorFrame"] \
    ["data"] \
    ["orientation"] \
    ["w"], )
    navcam_sensor_tf = geometry_msgs.msg.TransformStamped()
    navcam_sensor_tf.header.frame_id = "reu_1/base_link"
    navcam_sensor_tf.child_frame_id = "reu_1/navcam_sensor"
    navcam_sensor_tf.header.stamp = rospy.Time(t_us/1000000.0)
    navcam_sensor_tf.transform.translation = pos
    navcam_sensor_tf.transform.rotation = quat

    # get base_link tf
    pos = geometry_msgs.msg.Vector3( \
    json_data["metadata"] \
    ["pose_fixedFrame_robotFrame"] \
    ["data"] \
    ["translation"][0], \
    json_data["metadata"] \
    ["pose_fixedFrame_robotFrame"] \
    ["data"] \
    ["translation"][1], \
    json_data["metadata"] \
    ["pose_fixedFrame_robotFrame"] \
    ["data"] \
    ["translation"][2])
    quat = geometry_msgs.msg.Quaternion( \
    json_data["metadata"] \
    ["pose_fixedFrame_robotFrame"] \
    ["data"] \
    ["orientation"] \
    ["x"], \
    json_data["metadata"] \
    ["pose_fixedFrame_robotFrame"] \
    ["data"] \
    ["orientation"] \
    ["y"], \
    json_data["metadata"] \
    ["pose_fixedFrame_robotFrame"] \
    ["data"] \
    ["orientation"] \
    ["z"], \
    json_data["metadata"] \
    ["pose_fixedFrame_robotFrame"] \
    ["data"] \
    ["orientation"] \
    ["w"], )
    base_link_tf = geometry_msgs.msg.TransformStamped()
    base_link_tf.header.frame_id = "map"
    base_link_tf.child_frame_id = "reu_1/base_link"
    base_link_tf.header.stamp = rospy.Time(t_us/1000000.0)
    base_link_tf.transform.translation = pos
    base_link_tf.transform.rotation = quat

    # publish TFs
    tf_msg = tf2_msgs.msg.TFMessage()
    tf_msg.transforms = []
    tf_msg.transforms.append(base_link_tf)
    outbag.write("/tf", tf_msg, rospy.Time(t_us/1000000.0))
    tf_msg = tf2_msgs.msg.TFMessage()
    tf_msg.transforms = []
    tf_msg.transforms.append(navcam_sensor_tf)
    outbag.write("/tf", tf_msg, rospy.Time(t_us/1000000.0))

    # open corresponding .pcd file
    pcd_path = json_data["data"]["path"]
    pcl_data = pcl.load(metadata_dir + "/" + pcd_path)
    # pcl_data = pypcd.(metadata_dir + "/" + pcd_path)

    # get data
    pcl_msg = sensor_msgs.msg.PointCloud2()
    pcl_msg.data = np.ndarray.tobytes(pcl_data.to_array())
    pcl_msg.header.stamp = rospy.Time(t_us/1000000.0)# t_s, t_ns)
    pcl_msg.header.frame_id = "reu_1/navcam_sensor"

    # Pusblish Pointcloud2 msg
    outbag.write("/reu_1/pcl_navcam", pcl_msg, rospy.Time(t_us/1000000.0))

    pass



    if __name__ == "__main__":

    dataset_path = "/home/---/Documents/datasets/---/"

    main()


    The base_link and camera tfs come from a json file that also stores a string to associate the .pcd file.

    Continue reading...

Compartilhe esta Página