rs2_listener.py
Go to the documentation of this file.
00001 import sys
00002 import time
00003 import rospy
00004 from sensor_msgs.msg import Image as msg_Image
00005 from sensor_msgs.msg import PointCloud2 as msg_PointCloud2
00006 import sensor_msgs.point_cloud2 as pc2
00007 from sensor_msgs.msg import Imu as msg_Imu
00008 import numpy as np
00009 from cv_bridge import CvBridge, CvBridgeError
00010 import inspect
00011 import ctypes
00012 import struct
00013 import tf
00014 
00015 
00016 def pc2_to_xyzrgb(point):
00017         # Thanks to Panos for his code used in this function.
00018     x, y, z = point[:3]
00019     rgb = point[3]
00020 
00021     # cast float32 to int so that bitwise operations are possible
00022     s = struct.pack('>f', rgb)
00023     i = struct.unpack('>l', s)[0]
00024     # you can get back the float value by the inverse operations
00025     pack = ctypes.c_uint32(i).value
00026     r = (pack & 0x00FF0000) >> 16
00027     g = (pack & 0x0000FF00) >> 8
00028     b = (pack & 0x000000FF)
00029     return x, y, z, r, g, b
00030 
00031 
00032 class CWaitForMessage:
00033     def __init__(self, params={}):
00034         self.result = None
00035 
00036         self.break_timeout = False
00037         self.timeout = params.get('timeout_secs', -1)
00038         self.seq = params.get('seq', -1)
00039         self.time = params.get('time', None)
00040         self.node_name = params.get('node_name', 'rs2_listener')
00041         self.bridge = CvBridge()
00042         self.listener = None
00043 
00044         self.themes = {'depthStream': {'topic': '/camera/depth/image_rect_raw', 'callback': self.imageColorCallback, 'msg_type': msg_Image},
00045                        'colorStream': {'topic': '/camera/color/image_raw', 'callback': self.imageColorCallback, 'msg_type': msg_Image},
00046                        'pointscloud': {'topic': '/camera/depth/color/points', 'callback': self.pointscloudCallback, 'msg_type': msg_PointCloud2},
00047                        'alignedDepthInfra1': {'topic': '/camera/aligned_depth_to_infra1/image_raw', 'callback': self.imageColorCallback, 'msg_type': msg_Image},
00048                        'alignedDepthColor': {'topic': '/camera/aligned_depth_to_color/image_raw', 'callback': self.imageColorCallback, 'msg_type': msg_Image},
00049                        'static_tf': {'topic': '/camera/color/image_raw', 'callback': self.imageColorCallback, 'msg_type': msg_Image},
00050                        'accelStream': {'topic': '/camera/accel/sample', 'callback': self.imuCallback, 'msg_type': msg_Imu},
00051                        }
00052 
00053         self.func_data = dict()
00054 
00055     def imuCallback(self, theme_name):
00056         def _imuCallback(data):
00057             if self.listener is None:
00058                 self.listener = tf.TransformListener()
00059             self.prev_time = time.time()
00060             self.func_data[theme_name].setdefault('value', [])
00061             self.func_data[theme_name].setdefault('ros_value', [])
00062             try:
00063                 frame_id = data.header.frame_id
00064                 value = data.linear_acceleration
00065 
00066                 (trans,rot) = self.listener.lookupTransform('/camera_link', frame_id, rospy.Time(0))
00067                 quat = tf.transformations.quaternion_matrix(rot)
00068                 point = np.matrix([value.x, value.y, value.z, 1], dtype='float32')
00069                 point.resize((4, 1))
00070                 rotated = quat*point
00071                 rotated.resize(1,4)
00072                 rotated = np.array(rotated)[0][:3]
00073             except Exception as e:
00074                 print(e)
00075                 return
00076             self.func_data[theme_name]['value'].append(value)
00077             self.func_data[theme_name]['ros_value'].append(rotated)
00078         return _imuCallback            
00079 
00080     def imageColorCallback(self, theme_name):
00081         def _imageColorCallback(data):
00082             self.prev_time = time.time()
00083             self.func_data[theme_name].setdefault('avg', [])
00084             self.func_data[theme_name].setdefault('ok_percent', [])
00085             self.func_data[theme_name].setdefault('num_channels', [])
00086             self.func_data[theme_name].setdefault('shape', [])
00087             self.func_data[theme_name].setdefault('reported_size', [])
00088 
00089             try:
00090                 cv_image = self.bridge.imgmsg_to_cv2(data, data.encoding)
00091             except CvBridgeError as e:
00092                 print(e)
00093                 return
00094             channels = cv_image.shape[2] if len(cv_image.shape) > 2 else 1
00095             pyimg = np.asarray(cv_image)
00096 
00097             ok_number = (pyimg != 0).sum()
00098 
00099             self.func_data[theme_name]['avg'].append(pyimg.sum() / ok_number)
00100             self.func_data[theme_name]['ok_percent'].append(float(ok_number) / (pyimg.shape[0] * pyimg.shape[1]) / channels)
00101             self.func_data[theme_name]['num_channels'].append(channels)
00102             self.func_data[theme_name]['shape'].append(cv_image.shape)
00103             self.func_data[theme_name]['reported_size'].append((data.width, data.height, data.step))
00104         return _imageColorCallback
00105 
00106     def imageDepthCallback(self, data):
00107         pass
00108 
00109     def pointscloudCallback(self, theme_name):
00110         def _pointscloudCallback(data):
00111             self.prev_time = time.time()
00112             print 'Got pointcloud: %d, %d' % (data.width, data.height)
00113 
00114             self.func_data[theme_name].setdefault('frame_counter', 0)
00115             self.func_data[theme_name].setdefault('avg', [])
00116             self.func_data[theme_name].setdefault('size', [])
00117             self.func_data[theme_name].setdefault('width', [])
00118             self.func_data[theme_name].setdefault('height', [])
00119             # until parsing pointcloud is done in real time, I'll use only the first frame.
00120             self.func_data[theme_name]['frame_counter'] += 1
00121 
00122             if self.func_data[theme_name]['frame_counter'] == 1:
00123                 # Known issue - 1st pointcloud published has invalid texture. Skip 1st frame.
00124                 return
00125 
00126             try:
00127                 points = np.array([pc2_to_xyzrgb(pp) for pp in pc2.read_points(data, skip_nans=True, field_names=("x", "y", "z", "rgb")) if pp[0] > 0])
00128             except Exception as e:
00129                 print(e)
00130                 return
00131             self.func_data[theme_name]['avg'].append(points.mean(0))
00132             self.func_data[theme_name]['size'].append(len(points))
00133             self.func_data[theme_name]['width'].append(data.width)
00134             self.func_data[theme_name]['height'].append(data.height)
00135         return _pointscloudCallback
00136 
00137     def wait_for_message(self, params):
00138         topic = params['topic']
00139         print 'connect to ROS with name: %s' % self.node_name
00140         rospy.init_node(self.node_name, anonymous=True)
00141 
00142         rospy.loginfo('Subscribing on topic: %s' % topic)
00143         self.sub = rospy.Subscriber(topic, msg_Image, self.callback)
00144 
00145         self.prev_time = time.time()
00146         break_timeout = False
00147         while not any([rospy.core.is_shutdown(), break_timeout, self.result]):
00148             rospy.rostime.wallsleep(0.5)
00149             if self.timeout > 0 and time.time() - self.prev_time > self.timeout:
00150                 break_timeout = True
00151                 self.sub.unregister()
00152 
00153         return self.result
00154 
00155     @staticmethod
00156     def unregister_all(registers):
00157         for test_name in registers:
00158             rospy.loginfo('Un-Subscribing test %s' % test_name)
00159             registers[test_name]['sub'].unregister()
00160 
00161     def wait_for_messages(self, themes):
00162         # tests_params = {<name>: {'callback', 'topic', 'msg_type', 'internal_params'}}
00163         self.func_data = dict([[theme_name, {}] for theme_name in themes])
00164 
00165         print 'connect to ROS with name: %s' % self.node_name
00166         rospy.init_node(self.node_name, anonymous=True)
00167         for theme_name in themes:
00168             theme = self.themes[theme_name]
00169             rospy.loginfo('Subscribing %s on topic: %s' % (theme_name, theme['topic']))
00170             self.func_data[theme_name]['sub'] = rospy.Subscriber(theme['topic'], theme['msg_type'], theme['callback'](theme_name))
00171 
00172         self.prev_time = time.time()
00173         break_timeout = False
00174         while not any([rospy.core.is_shutdown(), break_timeout]):
00175             rospy.rostime.wallsleep(0.5)
00176             if self.timeout > 0 and time.time() - self.prev_time > self.timeout:
00177                 break_timeout = True
00178                 self.unregister_all(self.func_data)
00179 
00180         return self.func_data
00181 
00182     def callback(self, data):
00183         rospy.loginfo('Got message. Seq %d, secs: %d, nsecs: %d' % (data.header.seq, data.header.stamp.secs, data.header.stamp.nsecs))
00184 
00185         self.prev_time = time.time()
00186         if any([self.seq > 0 and data.header.seq >= self.seq,
00187                 self.time and data.header.stamp.secs == self.time['secs'] and data.header.stamp.nsecs == self.time['nsecs']]):
00188             self.result = data
00189             self.sub.unregister()
00190 
00191 
00192 
00193 def main():
00194     if len(sys.argv) < 2 or '--help' in sys.argv or '/?' in sys.argv:
00195         print 'USAGE:'
00196         print '------'
00197         print 'rs2_listener.py <topic | theme> [Options]'
00198         print 'example: rs2_listener.py /camera/color/image_raw --time 1532423022.044515610 --timeout 3'
00199         print 'example: rs2_listener.py pointscloud'
00200         print ''
00201         print 'Application subscribes on <topic>, wait for the first message matching [Options].'
00202         print 'When found, prints the timestamp.'
00203         print
00204         print '[Options:]'
00205         print '-s <sequential number>'
00206         print '--time <secs.nsecs>'
00207         print '--timeout <secs>'
00208         exit(-1)
00209 
00210     # wanted_topic = '/device_0/sensor_0/Depth_0/image/data'
00211     # wanted_seq = 58250
00212 
00213     wanted_topic = sys.argv[1]
00214     msg_params = {}
00215     for idx in range(2, len(sys.argv)):
00216         if sys.argv[idx] == '-s':
00217             msg_params['seq'] = int(sys.argv[idx + 1])
00218         if sys.argv[idx] == '--time':
00219             msg_params['time'] = dict(zip(['secs', 'nsecs'], [int(part) for part in sys.argv[idx + 1].split('.')]))
00220         if sys.argv[idx] == '--timeout':
00221             msg_params['timeout_secs'] = int(sys.argv[idx + 1])
00222 
00223     msg_retriever = CWaitForMessage(msg_params)
00224     if '/' in wanted_topic:
00225         msg_params = {'topic': wanted_topic}
00226         res = msg_retriever.wait_for_message(msg_params)
00227         rospy.loginfo('Got message: %s' % res.header)
00228     else:
00229         themes = [wanted_topic]
00230         res = msg_retriever.wait_for_messages(themes)
00231         print res
00232 
00233 
00234 if __name__ == '__main__':
00235     main()
00236 


realsense2_camera
Author(s): Sergey Dorodnicov , Doron Hirshberg
autogenerated on Sat Jul 6 2019 03:30:09