1
'''Author: Nick Hillier'''
2
# Various utils for interacting with ROS
8
import mrol_mapping.poseutil as poseutil
9
import mrol_mapping.depth_image as depth_image
11
from cv_bridge import CvBridge, CvBridgeError
13
def makePose3D(transform):
15
R = tf.transformations.quaternion_matrix(transform[1])
20
M[0:3,3:4] = np.asarray(T).reshape(3,1)
24
from sensor_msgs.msg import PointCloud2
25
from sensor_msgs.msg import PointField
26
def xyzs2pc2(xyzs,stamp,seq,frame_id):
27
#import pydb;pydb.set_trace()
28
pc2Data = PointCloud2()
30
if type(xyzs[0][0]) == np.float64:
31
xyzs = np.array(xyzs,dtype=np.float32)
32
assert (xyzs.shape[1] != 3) or (xyzs.shape[1] != 6),\
33
"Shape: {0}".format(xyzs.shape)
34
if xyzs.shape[1] == 3:
38
float32LE = np.dtype(np.float32,align='<')
39
pc2Data.is_dense = False
40
pc2Data.is_bigendian = False
42
pc2Data.width = len(xyzs)
43
pc2Data.header.frame_id = frame_id
44
pc2Data.header.seq = seq
45
pc2Data.header.stamp = stamp;
46
for i in range(numfields):
47
pc2Field = PointField()
57
pc2Field.name = 'unknown'
59
#if type(xyzs[0][0]) == np.float64:
60
# pc2Field.datatype = 8 # FLOAT64
61
# dataLen = 8 # FLOAT64
62
if type(xyzs[0][0]) == float32LE:
63
pc2Field.datatype = 7 # FLOAT32
66
assert False, "unknown datatype"
68
pc2Field.offset = i*dataLen
69
pc2Data.fields.append(pc2Field)
70
pc2Data.point_step = i*dataLen + dataLen;
71
pc2Data.row_step = pc2Data.point_step * pc2Data.width;
72
if xyzs.shape[1] == 3:
73
data_buf = xyzs.flatten().tostring()
75
#import pydb;pydb.set_trace()
76
rgb = np.hstack([np.uint8(xyzs[:,6:2:-1]),
77
np.zeros([xyzs.shape[0],1],dtype=np.uint8)]
79
rgb = rgb.view(dtype=float32LE)
80
data = np.hstack([xyzs[:,0:3],rgb])
81
data_buf = data.flatten().tostring()
82
if (xyzs.shape[1] == 3):
83
assert len(data_buf)/float(dataLen)/3.0 == len(xyzs), "len(data_buf)/4.0/3.0 = "+np.str(len(data_buf)/4.0/3.0)+" but len(xyzs) = "+np.str(len(xyzs))
85
assert len(data_buf)/float(dataLen)/4.0 == len(xyzs), "len(data_buf)/4.0/4.0 = "+np.str(len(data_buf)/4.0/4.0)+" but len(xyzs) = "+np.str(len(xyzs))
86
pc2Data.data = data_buf
89
def pc22xyzs(msg, max_range=100.):
90
#import pydb;pydb.set_trace()
91
assert msg.is_bigendian == False, "Big Endian support is not yet implemented"
92
num_fields = len(msg.fields)
93
assert num_fields >=3, "Message must contain at least 3 dimensions (x,y,z)"
94
# TODO: checks on fields content for type etc
95
float32LE = np.dtype(np.float32,align='<')
96
#data = np.frombuffer(msg.data, dtype=float32LE)
97
#data_arr = data.reshape((-1,num_fields*2))
98
data = np.frombuffer(msg.data, dtype=np.uint8)
99
data_arr = data.reshape((-1,msg.point_step))
100
# TODO: WARNING! The copying below assumes msg.fields is x,y,z(,rgb).
101
#xyzsD = data_arr[:,0:3].copy()
102
data_arrF = data_arr.view(dtype=float32LE)
103
xyzsD = data_arrF[:,0:3]
104
inds = np.logical_not(np.isnan(xyzsD[:,1]))
105
xyzsD = xyzsD[inds,:]
106
ranges = (xyzsD[:,0]*xyzsD[:,0] + xyzsD[:,1]*xyzsD[:,1]) + xyzsD[:,2]*xyzsD[:,2]
107
indsD = np.logical_and(ranges < max_range**2, ranges > 0)
108
xyzsD = xyzsD[indsD,:]
111
# TODO: This indexing ONLY WORKS FOR KINECT!!!
112
#import pydb;pydb.set_trace()
113
#xyzsRGB = data_arrF[:,4]
114
xyzsRGB = data_arr[:,18:15:-1] # RGB is backwards!
115
xyzsRGB = xyzsRGB[inds,:]
116
xyzsRGB = xyzsRGB[indsD,:]
117
#xyzsRGB = xyzsRGB.view(np.uint8)
118
#xyzsRGB = xyzsRGB.reshape((-1,4))
120
xyzs = np.hstack([xyzsD,xyzsRGB])
126
def imgmsg_to_cv(imgmsg):
127
return CvBridge().imgmsg_to_cv(imgmsg)
131
cv.IPL_DEPTH_8U: 'uint8',
132
cv.IPL_DEPTH_8S: 'int8',
133
cv.IPL_DEPTH_16U: 'uint16',
134
cv.IPL_DEPTH_16S: 'int16',
135
cv.IPL_DEPTH_32S: 'int32',
136
cv.IPL_DEPTH_32F: 'float32',
137
cv.IPL_DEPTH_64F: 'float64',
143
dtype=depth2dtype[im.depth],
144
count=im.width*im.height*im.nChannels)
145
a.shape = (im.height,im.width,im.nChannels)
148
def imgmsg2array(imgmsg):
149
img_or_mat = imgmsg_to_cv(imgmsg)
150
if isinstance(img_or_mat, cv.cvmat):
151
return np.asarray(img_or_mat)
153
return cv2array(img_or_mat)
155
def imgmsg2xyz(imgmsg, **kwargs):
156
arr = imgmsg2array(imgmsg)
157
# image_raw topic is encoded as 16-bit integer where each pixel depth is
159
# http://ros.org/reps/rep-0118.html
161
# Convert it into SI units.
162
arr = np.asarray(arr, dtype=np.float32)
165
return depth_image.image_to_points(arr, **kwargs)