polar_to_cartesian_pointcloud_ros1.py
Go to the documentation of this file.
1 # Receive polar pointcloud messages (fields: "i", "range", "azimuth", "elevation")
2 # and convert to cartesian pointcloud messages (fields: "x", "y", "z", "i")
3 
4 import argparse
5 import math
6 import numpy as np
7 
8 import rospy
9 from sensor_msgs.msg import PointCloud2, PointField
10 class Node:
11  pass
12 
13 # Convert a polar pointcloud to ros cartesian pointcloud
14 def convertPolarToCartesianPointCloud(polar_pointcloud):
15  # Copy pointcloud header
16  ros_pointcloud = PointCloud2()
17  ros_pointcloud.header = polar_pointcloud.header
18  ros_pointcloud.width = polar_pointcloud.width
19  ros_pointcloud.height = polar_pointcloud.height
20  ros_pointcloud.is_bigendian = polar_pointcloud.is_bigendian
21  ros_pointcloud.is_dense = polar_pointcloud.is_dense
22  # Create pointcloud fields
23  field_offset_range = -1
24  field_offset_azimuth = -1
25  field_offset_elevation = -1
26  field_offset_intensity = -1
27  for polar_field in polar_pointcloud.fields:
28  if polar_field.name == "range" and polar_field.datatype == PointField.FLOAT32:
29  field_offset_range = polar_field.offset
30  elif polar_field.name == "azimuth" and polar_field.datatype == PointField.FLOAT32:
31  field_offset_azimuth = polar_field.offset
32  elif polar_field.name == "elevation" and polar_field.datatype == PointField.FLOAT32:
33  field_offset_elevation = polar_field.offset
34  elif (polar_field.name == "intensity" or polar_field.name == "i") and polar_field.datatype == PointField.FLOAT32:
35  field_offset_intensity = polar_field.offset
36  ros_pointcloud.fields = [ PointField("x", 0, PointField.FLOAT32, 1), PointField("y", 4, PointField.FLOAT32, 1), PointField("z", 8, PointField.FLOAT32, 1), PointField("intensity", 12, PointField.FLOAT32, 1) ]
37  ros_pointcloud.point_step = 16
38  ros_pointcloud.row_step = ros_pointcloud.point_step * ros_pointcloud.width
39  # Convert pointcloud data
40  cartesian_point_cloud_buffer = np.zeros(4 * ros_pointcloud.width * ros_pointcloud.height, dtype = np.float32)
41  cartesian_point_cloud_offset = 0
42  for row_idx in range(polar_pointcloud.height):
43  for col_idx in range(polar_pointcloud.width):
44  # Get scan point in polar coordinates (range, azimuth and elevation)
45  polar_point_offset = row_idx * polar_pointcloud.row_step + col_idx * polar_pointcloud.point_step
46  point_range = np.frombuffer(polar_pointcloud.data, dtype = np.float32, count = 1, offset = polar_point_offset + field_offset_range)[0]
47  point_azimuth = np.frombuffer(polar_pointcloud.data, dtype = np.float32, count = 1, offset = polar_point_offset + field_offset_azimuth)[0]
48  point_elevation = np.frombuffer(polar_pointcloud.data, dtype = np.float32, count = 1, offset = polar_point_offset + field_offset_elevation)[0]
49  point_intensity = 0
50  if field_offset_intensity >= 0:
51  point_intensity = np.frombuffer(polar_pointcloud.data, dtype = np.float32, count = 1, offset = polar_point_offset + field_offset_intensity)[0]
52  # Convert from polar to cartesian coordinates
53  point_x = point_range * math.cos(point_elevation) * math.cos(point_azimuth)
54  point_y = point_range * math.cos(point_elevation) * math.sin(point_azimuth)
55  point_z = point_range * math.sin(point_elevation)
56  cartesian_point_cloud_buffer[cartesian_point_cloud_offset + 0] = point_x
57  cartesian_point_cloud_buffer[cartesian_point_cloud_offset + 1] = point_y
58  cartesian_point_cloud_buffer[cartesian_point_cloud_offset + 2] = point_z
59  cartesian_point_cloud_buffer[cartesian_point_cloud_offset + 3] = point_intensity
60  cartesian_point_cloud_offset = cartesian_point_cloud_offset + 4
61  ros_pointcloud.data = cartesian_point_cloud_buffer.tostring()
62  return ros_pointcloud
63 
65  def __init__(self, subscriber_topic, publisher_topic):
66  self.cloud_subscriber = rospy.Subscriber(subscriber_topic, PointCloud2, self.listener_callback, queue_size=16*12*3) # multiScan: 16 layer, 12 segments, 3 echos
67  self.cloud_publisher = rospy.Publisher(publisher_topic, PointCloud2, queue_size=16*12*3)
68  def listener_callback(self, msg):
69  ros_pointcloud = convertPolarToCartesianPointCloud(msg)
70  self.cloud_publisher.publish(ros_pointcloud)
71 
72 if __name__ == '__main__':
73  subscriber_topic = "/cloud_polar_unstructured_fullframe"
74  publisher_topic = "/cloud_polar_to_cartesian"
75  arg_parser = argparse.ArgumentParser()
76  arg_parser.add_argument("--polar_topic", help="ros topic of polar pointcloud (subscriber)", default=subscriber_topic, type=str)
77  arg_parser.add_argument("--cartesian_topic", help="ros topic of cartesian pointcloud (publisher)", default=publisher_topic, type=str)
78  cli_args = arg_parser.parse_args()
79  subscriber_topic = cli_args.polar_topic
80  publisher_topic = cli_args.cartesian_topic
81  node = rospy.init_node("polar_to_cartesian_pointcloud")
82  subscriber = PointCloudSubscriber(subscriber_topic, publisher_topic)
83  # rospy.spin()
84  while not rospy.is_shutdown():
85  rospy.sleep(0.1)
sensor_msgs::PointCloud2
::sensor_msgs::PointCloud2_< std::allocator< void > > PointCloud2
Definition: PointCloud2.h:90
polar_to_cartesian_pointcloud_ros1.Node
Definition: polar_to_cartesian_pointcloud_ros1.py:10
polar_to_cartesian_pointcloud_ros1.PointCloudSubscriber.listener_callback
def listener_callback(self, msg)
Definition: polar_to_cartesian_pointcloud_ros1.py:68
polar_to_cartesian_pointcloud_ros1.PointCloudSubscriber.cloud_publisher
cloud_publisher
Definition: polar_to_cartesian_pointcloud_ros1.py:67
polar_to_cartesian_pointcloud_ros1.convertPolarToCartesianPointCloud
def convertPolarToCartesianPointCloud(polar_pointcloud)
Definition: polar_to_cartesian_pointcloud_ros1.py:14
polar_to_cartesian_pointcloud_ros1.PointCloudSubscriber.__init__
def __init__(self, subscriber_topic, publisher_topic)
Definition: polar_to_cartesian_pointcloud_ros1.py:65
polar_to_cartesian_pointcloud_ros1.PointCloudSubscriber
Definition: polar_to_cartesian_pointcloud_ros1.py:64
polar_to_cartesian_pointcloud_ros1.PointCloudSubscriber.cloud_subscriber
cloud_subscriber
Definition: polar_to_cartesian_pointcloud_ros1.py:66


sick_scan_xd
Author(s): Michael Lehning , Jochen Sprickerhof , Martin Günther
autogenerated on Fri Oct 25 2024 02:47:09