multiscan_laserscan_msg_to_pointcloud.py
Go to the documentation of this file.
1 # Receive LaserScan messages and convert to pointcloud
2 
3 import math
4 import numpy as np
5 import os
6 import sys
7 import threading
8 import time
9 
10 # set __ROS_VERSION to 1 (ROS-1), or 2 (ROS-2)
11 __ROS_VERSION = os.getenv("ROS_VERSION")
12 if __ROS_VERSION is not None:
13  __ROS_VERSION = int(__ROS_VERSION)
14 if __ROS_VERSION == 2:
15  import rclpy
16  from rclpy.node import Node
17  from rclpy.qos import QoSProfile
18  from rclpy.qos import QoSReliabilityPolicy
19  from sensor_msgs.msg import LaserScan
20  from sensor_msgs.msg import PointCloud2, PointField
21 else:
22  import rospy
23  from sensor_msgs.msg import LaserScan
24  from sensor_msgs.msg import PointCloud2, PointField
25  class Node:
26  pass
27 
29 
30  def __init__(self, __ROS_VERSION, num_messages_decay):
31  self.__ROS_VERSION = __ROS_VERSION
32  if self.__ROS_VERSION == 2: # ROS-2
33  super().__init__("multiscan_laserscan_msg_to_pointcloud")
34  self.num_messages_decay = num_messages_decay
35  self.scan_msg_array = []
36  if self.__ROS_VERSION == 2: # ROS-2
37  self.scan_subscription = self.create_subscription(LaserScan, "/sick_scansegment_xd/scan_segment", self.listener_callback, 10) # QoSProfile(depth=16*12*3,reliability=QoSReliabilityPolicy.RELIABLE))
38  self.cloud_publisher = self.create_publisher(PointCloud2, "/laserscan_msg_cloud", 10)
39  else: # ROS-1
40  self.scan_subscription = rospy.Subscriber("/sick_scansegment_xd/scan_segment", LaserScan, self.listener_callback, queue_size=16*12*3) # multiScan: 16 layer, 12 segments, 3 echos
41  self.cloud_publisher = rospy.Publisher("/laserscan_msg_cloud", PointCloud2, queue_size=10)
42  self.frame_id_elevation_table = { # Elevation table for Multiscan 136 (16 layer):
43  "world_0": -22.71 * math.pi / 180, # layer:0 elevation: -22.71 deg
44  "world_1": -17.56 * math.pi / 180, # layer:1 elevation: -17.56 deg
45  "world_2": -12.48 * math.pi / 180, # layer:2 elevation: -12.48 deg
46  "world_3": -7.51 * math.pi / 180, # layer:3 elevation: -7.51 deg
47  "world_4": -2.49 * math.pi / 180, # layer:4 elevation: -2.49 deg
48  "world_5": -0.07 * math.pi / 180, # layer:5 elevation: -0.07 deg
49  "world_6": +2.43 * math.pi / 180, # layer:6 elevation: +2.43 deg
50  "world_7": +7.29 * math.pi / 180, # layer:7 elevation: +7.29 deg
51  "world_8": +12.79 * math.pi / 180, # layer:8 elevation: +12.79 deg
52  "world_9": +17.28 * math.pi / 180, # layer:9 elevation: +17.28 deg
53  "world_10": +21.94 * math.pi / 180, # layer:10 elevation: +21.94 deg
54  "world_11": +26.73 * math.pi / 180, # layer:11 elevation: +26.73 deg
55  "world_12": +31.86 * math.pi / 180, # layer:12 elevation: +31.86 deg
56  "world_13": +33.42 * math.pi / 180, # layer:13 elevation: +33.42 deg
57  "world_14": +37.18 * math.pi / 180, # layer:14 elevation: +37.18 deg
58  "world_15": +42.79 * math.pi / 180 # layer:15 elevation: +42.79 deg
59  }
60 
61  def listener_callback(self, msg):
62  # print("subscriber: {}".format(msg))
63  # print("subscriber: {}".format(msg.header.frame_id))
64  self.scan_msg_array.append(msg)
65  if len(self.scan_msg_array) >= self.num_messages_decay:
66  # Create pointcloud header and field description
67  ros_pointcloud = PointCloud2()
68  ros_pointcloud.header.seq = msg.header.seq
69  ros_pointcloud.header.stamp = msg.header.stamp
70  ros_pointcloud.header.frame_id = "world"
71  ros_pointcloud.width = 0
72  for scan_msg in self.scan_msg_array:
73  ros_pointcloud.width = ros_pointcloud.width + len(scan_msg.ranges)
74  ros_pointcloud.height = 1
75  ros_pointcloud.is_bigendian = False
76  ros_pointcloud.is_dense = True
77  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) ]
78  ros_pointcloud.point_step = 16
79  ros_pointcloud.row_step = ros_pointcloud.point_step * ros_pointcloud.width
80  # Convert laserscan message to pointcloud
81  cloud_data = np.zeros(4 * ros_pointcloud.width * ros_pointcloud.height, dtype=np.float32)
82  cloud_point_idx = 0
83  for scan_msg in self.scan_msg_array:
84  azimuth = scan_msg.angle_min
85  azimuth_inc = scan_msg.angle_increment
86  elevation = self.frame_id_elevation_table[scan_msg.header.frame_id]
87  elevation_cos = math.cos(elevation)
88  elevation_sin = math.sin(elevation)
89  for point_idx, range in enumerate(scan_msg.ranges):
90  cloud_data[4 * cloud_point_idx + 0] = range * elevation_cos * math.cos(azimuth) # x
91  cloud_data[4 * cloud_point_idx + 1] = range * elevation_cos * math.sin(azimuth) # y
92  cloud_data[4 * cloud_point_idx + 2] = range * elevation_sin # z
93  cloud_data[4 * cloud_point_idx + 3] = scan_msg.intensities[point_idx] # intensity
94  cloud_point_idx = cloud_point_idx + 1
95  azimuth = azimuth + azimuth_inc
96  ros_pointcloud.data = cloud_data.tostring()
97  self.cloud_publisher.publish(ros_pointcloud)
98  self.scan_msg_array = []
99 
100 def main(args=None):
101  global __ROS_VERSION
102  num_messages_decay = 3 * 12 * 16 # decay over one complete fullscan, multiScan: 16 layer, 12 segments, 3 echos
103  if __ROS_VERSION == 2: # ROS-2
104  rclpy.init()
105  subscriber = LaserScanSubscriber(__ROS_VERSION, num_messages_decay)
106  rclpy.spin(subscriber)
107  rclpy.shutdown()
108 
109  else: # ROS-1
110  node = rospy.init_node("multiscan_laserscan_msg_to_pointcloud")
111  subscriber = LaserScanSubscriber(__ROS_VERSION, num_messages_decay)
112  # rospy.spin()
113  while not rospy.is_shutdown():
114  rospy.sleep(0.1)
115 
116 if __name__ == '__main__':
117  main()
multiscan_laserscan_msg_to_pointcloud.LaserScanSubscriber.cloud_publisher
cloud_publisher
Definition: multiscan_laserscan_msg_to_pointcloud.py:38
multiscan_laserscan_msg_to_pointcloud.Node
Definition: multiscan_laserscan_msg_to_pointcloud.py:25
multiscan_laserscan_msg_to_pointcloud.LaserScanSubscriber.__ROS_VERSION
__ROS_VERSION
Definition: multiscan_laserscan_msg_to_pointcloud.py:31
multiscan_laserscan_msg_to_pointcloud.LaserScanSubscriber.scan_subscription
scan_subscription
Definition: multiscan_laserscan_msg_to_pointcloud.py:37
multiscan_laserscan_msg_to_pointcloud.LaserScanSubscriber.num_messages_decay
num_messages_decay
Definition: multiscan_laserscan_msg_to_pointcloud.py:34
sensor_msgs::PointCloud2
::sensor_msgs::PointCloud2_< std::allocator< void > > PointCloud2
Definition: PointCloud2.h:90
multiscan_laserscan_msg_to_pointcloud.main
def main(args=None)
Definition: multiscan_laserscan_msg_to_pointcloud.py:100
multiscan_laserscan_msg_to_pointcloud.LaserScanSubscriber.__init__
def __init__(self, __ROS_VERSION, num_messages_decay)
Definition: multiscan_laserscan_msg_to_pointcloud.py:30
multiscan_laserscan_msg_to_pointcloud.LaserScanSubscriber
Definition: multiscan_laserscan_msg_to_pointcloud.py:28
PointField
ros_sensor_msgs::PointField PointField
Definition: include/sick_scansegment_xd/common.h:127
multiscan_laserscan_msg_to_pointcloud.LaserScanSubscriber.listener_callback
def listener_callback(self, msg)
Definition: multiscan_laserscan_msg_to_pointcloud.py:61
roswrap::names::append
ROSCPP_DECL std::string append(const std::string &left, const std::string &right)
Append one name to another.
multiscan_laserscan_msg_to_pointcloud.LaserScanSubscriber.scan_msg_array
scan_msg_array
Definition: multiscan_laserscan_msg_to_pointcloud.py:35
multiscan_laserscan_msg_to_pointcloud.LaserScanSubscriber.frame_id_elevation_table
frame_id_elevation_table
Definition: multiscan_laserscan_msg_to_pointcloud.py:42


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