4242import math
4343import struct
4444import sys
45+ import numpy as np
4546
4647from sensor_msgs .msg import PointCloud2 , PointField
4748
@@ -144,40 +145,6 @@ def read_points_list(cloud, field_names=None, skip_nans=False, uvs=[]):
144145 skip_nans , uvs )]
145146
146147
147- def create_cloud (header , fields , points ):
148- """
149- Create a sensor_msgs.msg.PointCloud2 message.
150-
151- :param header: The point cloud header. (Type: std_msgs.msg.Header)
152- :param fields: The point cloud fields.
153- (Type: iterable of sensor_msgs.msg.PointField)
154- :param points: The point cloud points. List of iterables, i.e. one iterable
155- for each point, with the elements of each iterable being the
156- values of the fields for that point (in the same order as
157- the fields parameter)
158- :return: The point cloud as sensor_msgs.msg.PointCloud2
159- """
160- cloud_struct = struct .Struct (_get_struct_fmt (False , fields ))
161-
162- buff = ctypes .create_string_buffer (cloud_struct .size * len (points ))
163-
164- point_step , pack_into = cloud_struct .size , cloud_struct .pack_into
165- offset = 0
166- for p in points :
167- pack_into (buff , offset , * p )
168- offset += point_step
169-
170- return PointCloud2 (header = header ,
171- height = 1 ,
172- width = len (points ),
173- is_dense = False ,
174- is_bigendian = False ,
175- fields = fields ,
176- point_step = cloud_struct .size ,
177- row_step = cloud_struct .size * len (points ),
178- data = buff .raw )
179-
180-
181148def create_cloud_xyz32 (header , points ):
182149 """
183150 Create a sensor_msgs.msg.PointCloud2 message with (x, y, z) fields.
@@ -186,13 +153,39 @@ def create_cloud_xyz32(header, points):
186153 :param points: The point cloud points. (Type: Iterable)
187154 :return: The point cloud as sensor_msgs.msg.PointCloud2.
188155 """
189- fields = [PointField (name = 'x' , offset = 0 ,
190- datatype = PointField .FLOAT32 , count = 1 ),
191- PointField (name = 'y' , offset = 4 ,
192- datatype = PointField .FLOAT32 , count = 1 ),
193- PointField (name = 'z' , offset = 8 ,
194- datatype = PointField .FLOAT32 , count = 1 )]
195- return create_cloud (header , fields , points )
156+ # Convert to numpy if it isn't already
157+ points = np .asarray (points )
158+ # Convert data to f32, flatten it and cat it to a byte string
159+ data = points .astype (np .float32 ).reshape (- 1 ).tobytes ()
160+ # Define offsets
161+ point_value_bits = 32 # float32
162+ point_num_values = 3 # 3 values are a point
163+ point_value_bytes = point_value_bits // 8 # Number of bytes used for one value
164+ point_bytes = (point_num_values * point_value_bits ) // 8 # Bytes used by one point
165+
166+ # This function generates a point field describing the stored raw data for one dimension
167+ def make_point_field (element ):
168+ i = element [0 ]
169+ name = element [1 ]
170+ return PointField (
171+ name = name ,
172+ offset = i * point_value_bytes ,
173+ datatype = PointField .FLOAT32 ,
174+ count = 1 )
175+
176+ # Make a point field for each of the major axis
177+ fields = list (map (make_point_field , enumerate (['x' , 'y' , 'z' ])))
178+ # Put everything together
179+ return PointCloud2 (
180+ header = header ,
181+ height = 1 ,
182+ width = len (points ),
183+ is_dense = False ,
184+ is_bigendian = False ,
185+ fields = fields ,
186+ point_step = point_bytes ,
187+ row_step = point_bytes * len (points ),
188+ data = data )
196189
197190
198191def _get_struct_fmt (is_bigendian , fields , field_names = None ):
0 commit comments