_point_cloud.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 import roslib; roslib.load_manifest('projector_interface')
00004 
00005 import ctypes
00006 import math
00007 import struct
00008 import numpy as np
00009 from scipy.sparse import lil_matrix
00010 from pycloud import PyCloud
00011 
00012 from sensor_msgs.msg import PointCloud2, PointField
00013 
00014 _DATATYPES = {}
00015 _DATATYPES[PointField.INT8]        = ('b', 1)
00016 _DATATYPES[PointField.UINT8]   = ('B', 1)
00017 _DATATYPES[PointField.INT16]   = ('h', 2)
00018 _DATATYPES[PointField.UINT16]  = ('H', 2)
00019 _DATATYPES[PointField.INT32]   = ('i', 4)
00020 _DATATYPES[PointField.UINT32]  = ('I', 4)
00021 _DATATYPES[PointField.FLOAT32] = ('f', 4)
00022 _DATATYPES[PointField.FLOAT64] = ('d', 8)
00023 
00024 _NP_TYPES = {
00025         np.dtype('uint8')       :       (PointField.UINT8,      1),
00026         np.dtype('int8')        :       (PointField.INT8,       1),
00027         np.dtype('uint16')      :       (PointField.UINT16,     2),
00028         np.dtype('int16')       :       (PointField.INT16,      2),
00029         np.dtype('uint32')      :       (PointField.UINT32,     4),
00030         np.dtype('int32')       :       (PointField.INT32,      4),
00031         np.dtype('float32')     :       (PointField.FLOAT32,4),
00032         np.dtype('float64')     :       (PointField.FLOAT64,8)
00033 }
00034 
00035 import time
00036 
00037 def _float2rgb(x):
00038         rgb = struct.unpack('I', struct.pack('f', x))[0]
00039         b = (rgb >> 16) & 0x0000ff;
00040         g = (rgb >> 8)  & 0x0000ff;
00041         r = (rgb)               & 0x0000ff;
00042         return r,g,b
00043         
00044 def float2rgb(farr):
00045         assert farr.ndim == 2
00046         out = np.zeros(farr.shape + (3,))
00047         for u, col in enumerate(farr):
00048                 for v, val in enumerate(col):
00049                         out[u,v,:] = _float2rgb(val)
00050         return out
00051 
00052 def read_points_np(cloud, field_names=None, skip_nans=False, uvs=[], masked=True):
00053         reader = read_points(cloud, field_names=field_names, skip_nans=skip_nans, uvs=uvs)
00054         points = np.array(list(reader))
00055         reshaped = np.reshape(points, (cloud.height, cloud.width, len(cloud.fields)))
00056         if masked:
00057                 return np.ma.masked_array(reshaped, np.isnan(reshaped))         
00058         else:
00059                 return reshaped
00060 
00061 def read_points(cloud, field_names=None, skip_nans=False, uvs=[]):
00062         assert(cloud)
00063         fmt = _get_struct_fmt(cloud, field_names)
00064         width, height, point_step, row_step, data, isnan = cloud.width, cloud.height, cloud.point_step, cloud.row_step, cloud.data, math.isnan
00065         unpack_from = struct.Struct(fmt).unpack_from
00066 
00067         if skip_nans:
00068                 if uvs:
00069                         for u, v in uvs:
00070                                 p = unpack_from(data, (row_step * v) + (point_step * u))
00071                                 has_nan = False
00072                                 for pv in p:
00073                                         if isnan(pv):
00074                                                 has_nan = True
00075                                                 break
00076                                 if not has_nan:
00077                                         yield p
00078                 else:
00079                         for v in xrange(height):
00080                                 offset = row_step * v
00081                                 for u in xrange(width):
00082                                         p = unpack_from(data, offset)
00083                                         has_nan = False
00084                                         for pv in p:
00085                                                 if isnan(pv):
00086                                                         has_nan = True
00087                                                         break
00088                                         if not has_nan:
00089                                                 yield p
00090                                         offset += point_step
00091         else:
00092                 if uvs:
00093                         for u, v in uvs:
00094                                 yield unpack_from(data, (row_step * v) + (point_step * u))
00095                 else:
00096                         for v in xrange(height):
00097                                 offset = row_step * v
00098                                 for u in xrange(width):
00099                                         yield unpack_from(data, offset)
00100                                         offset += point_step
00101 
00102 def create_cloud_xyz32(header, points):
00103         fields = [PointField('x', 0, PointField.FLOAT32, 1),
00104                           PointField('y', 4, PointField.FLOAT32, 1),
00105                           PointField('z', 8, PointField.FLOAT32, 1)]
00106         return create_cloud(header, fields, points)
00107 
00108 def np_to_point_list(cloud, fields):
00109         if cloud.ndim > 2:
00110                 return cloud.reshape((np.prod(cloud.shape[:2]), len(fields)))
00111         else:
00112                 return cloud
00113 
00114 def create_cloud_np_xyz(points, header):
00115         dtype, width = _NP_TYPES[points.dtype]
00116         fields = [PointField('x', width*0, dtype, 1),
00117                           PointField('y', width*1, dtype, 1),
00118                           PointField('z', width*2, dtype, 1)]
00119         return create_cloud_np(header, fields, points)
00120         
00121 
00122 def create_cloud_np(header, fields, points):
00123         return create_cloud(header, fields, np_to_point_list(points, fields), points.shape)
00124 
00125 def create_cloud(header, fields, points, shape=None):
00126         cloud = PointCloud2()
00127         cloud.header       = header
00128         cloud.height       = 1
00129         cloud.width                = len(points)
00130         cloud.is_dense     = False
00131         cloud.is_bigendian = False
00132         cloud.fields       = fields
00133         fmt                                = _get_struct_fmt(cloud)
00134         cloud_struct       = struct.Struct(fmt)
00135         cloud.point_step   = cloud_struct.size
00136         cloud.row_step     = cloud_struct.size * cloud.width
00137 
00138         buffer = ctypes.create_string_buffer(cloud_struct.size * cloud.width)
00139 
00140         point_step, pack_into = cloud.point_step, cloud_struct.pack_into
00141         offset = 0
00142         for p in points:
00143                 if not np.ma.is_masked(p):
00144                         pack_into(buffer, offset, *p)
00145                         offset += point_step
00146 
00147         cloud.data = buffer.raw
00148 
00149         # if shape:
00150         #       cloud.height, cloud.width = shape[:2]
00151         return cloud
00152 
00153 def _create_point_field(cloud, field_names=None):
00154         nFields = cloud.shape[2]
00155         if not field_names:
00156                 if nFields == 3:
00157                         field_names = ['x','y','z']
00158                 elif nFields == 4:
00159                         field_names = ['x','y','z','index'] #ugh, this could also be intensity
00160                 elif nFields == 6:
00161                         field_names = ['x','y','z','r','g','b']
00162                 # field_names = ['x','y','z','r','g','b','a'][0:cloud.shape[2]]
00163         fields = []
00164         for field_name in field_names:
00165                 field = PointField()
00166 
00167 def _get_struct_fmt(cloud, field_names=None):
00168         fmt = '>' if cloud.is_bigendian else '<'
00169         offset = 0
00170         for field in (f for f in sorted(cloud.fields, key=lambda f: f.offset) if field_names is None or f.name in field_names):
00171                 if offset < field.offset:
00172                         fmt += 'x' * (field.offset - offset)
00173                         offset = field.offset
00174                 if field.datatype not in _DATATYPES:
00175                         print >> sys.stderr, 'Skipping unknown PointField datatype [%d]' % field.datatype
00176                 else:
00177                         datatype_fmt, datatype_length = _DATATYPES[field.datatype]
00178                         fmt        += field.count * datatype_fmt
00179                         offset += field.count * datatype_length
00180 
00181         return fmt


projector_interface
Author(s): Daniel Lazewatsky
autogenerated on Mon Oct 6 2014 10:12:36