rgbd_play.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 # Copyright (c) 2016 PAL Robotics SL. All Rights Reserved
00004 #
00005 # Permission to use, copy, modify, and/or distribute this software for
00006 # any purpose with or without fee is hereby granted, provided that the
00007 # above copyright notice and this permission notice appear in all
00008 # copies.
00009 #
00010 # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00011 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00012 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
00013 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00014 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00015 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00016 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00017 #
00018 # Author:
00019 #   * Sammy Pfeiffer
00020 
00021 import rospy
00022 from sensor_msgs.msg import Image
00023 import struct
00024 
00025 # Depth image stuff from
00026 # http://answers.ros.org/question/90696/get-depth-from-kinect-sensor-in-gazebo-simulator/
00027 
00028 
00029 def get_pixels_depth(ini_x, ini_y, end_x, end_y, depth_image=None):
00030     rospy.loginfo(
00031         "Getting average depth at: " + str((ini_x, ini_y, end_x, end_y)))
00032     if depth_image is None:
00033         rospy.loginfo("Waiting for a depth image...")
00034         img = rospy.wait_for_message('/xtion/depth/image_raw',
00035                                      Image)
00036     else:
00037         img = depth_image
00038     rospy.loginfo("The image has size: " + str(img.width) +
00039                   " width, " + str(img.height) + " height")
00040     if ini_x < 0:
00041         rospy.logerr("Can't ask for a pixel depth out of image (ini_x < 0)")
00042         return None
00043     if ini_y < 0:
00044         rospy.logerr("Can't ask for a pixel depth out of image (ini_y < 0)")
00045         return None
00046     if end_x > img.width:
00047         rospy.logerr("Can't ask for a pixel depth out of image (end_x > img.width [%s])" % (
00048             str(img.width)))
00049         return None
00050     if end_y > img.height:
00051         rospy.logerr("Can't ask for a pixel depth out of image (end_x > img.height [%s])" % (
00052             str(img.height)))
00053         return None
00054 
00055     if (img.step / img.width) == 4:
00056         rospy.loginfo("Got a rectified depth image (4 byte floats)")
00057     else:
00058         rospy.loginfo("Got a raw depth image (2 byte integers)")
00059 
00060     # Compute the average of the area of interest
00061     sum_depth = 0
00062     pixel_count = 0
00063     nan_count = 0
00064     for x in range(ini_x, end_x):
00065         for y in range(ini_y, end_y):
00066             pixel = get_pixel_depth(x, y, img)
00067             # print "Curr pixel is: '" + str(pixel) + "' of type: " +
00068             # str(type(pixel))
00069             if pixel != pixel:  # check if nan
00070                 nan_count += 1
00071             else:
00072                 sum_depth += pixel
00073                 pixel_count += 1
00074 
00075     if pixel_count > 0:
00076         avg = sum_depth / float(pixel_count)
00077         rospy.loginfo("Average is: " + str(avg) + " (with " + str(pixel_count) +
00078                       " valid pixels, " + str(nan_count) + " NaNs)")
00079 
00080         return avg
00081     else:
00082         rospy.logwarn("No pixels that are not NaN, can't return an average")
00083         return None
00084 
00085 
00086 def get_pixel_depth(x, y, depth_image=None):
00087     if depth_image is None:
00088         rospy.loginfo("Waiting for a depth image...")
00089         img = rospy.wait_for_message('/xtion/depth/image_raw',
00090                                      Image)
00091     else:
00092         img = depth_image
00093 
00094     if x < 0:
00095         rospy.logerr("Can't ask for a pixel depth out of image (x < 0)")
00096         return None
00097     if y < 0:
00098         rospy.logerr("Can't ask for a pixel depth out of image (y < 0)")
00099         return None
00100     if x > img.width:
00101         rospy.logerr("Can't ask for a pixel depth out of image (x > img.width [%s])" % (
00102             str(img.width)))
00103         return None
00104     if y > img.height:
00105         rospy.logerr("Can't ask for a pixel depth out of image (x > img.height [%s])" % (
00106             str(img.height)))
00107         return None
00108 
00109     index = (y * img.step) + (x * (img.step / img.width))
00110 
00111     if (img.step / img.width) == 4:
00112         # rospy.loginfo("Got a rectified depth image (4 byte floats)")
00113         byte_data = ""
00114         for i in range(0, 4):
00115             byte_data += img.data[index + i]
00116 
00117         distance = struct.unpack('f', byte_data)[0]
00118         return distance
00119     else:  # NOT TESTED
00120         rospy.logwarn("Got a raw depth image (2 byte integers) (UNTESTED) it will probably fail.")
00121         # Encoding 16UC1, 
00122         if img.is_bigendian:
00123             distance = (img.data[index] << 8) + img.data[index + 1]
00124         else:
00125             distance = int(img.data[index]) + (int(img.data[index + 1]) << 8)
00126         return distance
00127 
00128 
00129 class RGBDPlay(object):
00130     def __init__(self):
00131         self.last_msg = None
00132         # To get the same kind of raw image in simulation or real robot
00133         if rospy.get_param('/use_sim_time', False):
00134             depth_32FC1_topic = '/xtion/depth/image_raw'
00135         else:
00136             depth_32FC1_topic = '/xtion/depth/image'
00137         self.rgbd_sub = rospy.Subscriber(depth_32FC1_topic,
00138                                          Image,
00139                                          self.depth_img_cb,
00140                                          queue_size=1)
00141         rospy.loginfo(
00142             "Subscribed to: '" + str(self.rgbd_sub.resolved_name) + "' topic.")
00143         self.run()
00144 
00145     def depth_img_cb(self, msg):
00146         """
00147         :type msg: Image
00148         """
00149         self.last_msg = msg
00150 
00151     def run(self):
00152         """Show information on what was found in the rgbD image"""
00153         rospy.loginfo("Waiting for first Image message...")
00154         while not rospy.is_shutdown() and self.last_msg is None:
00155             rospy.sleep(0.2)
00156 
00157         # Check at a 1Hz rate to not spam
00158         r = rospy.Rate(1)
00159         while not rospy.is_shutdown():
00160             self.do_stuff_with_last_msg()
00161             r.sleep()
00162 
00163     def do_stuff_with_last_msg(self):
00164         """Print funny sentences about what we can guess of our status thanks to the depth image"""
00165         avg_center_depth = self.get_center_image_depth()
00166         if avg_center_depth is None:
00167             rospy.loginfo(
00168                 "You are so close or so far I can't see you with my depth camera!")
00169         elif avg_center_depth > 1.5:
00170             rospy.loginfo("I see you, get closer to me!")
00171         else:
00172             rospy.loginfo("I see you, I like having people close to me :)")
00173 
00174     def get_center_image_depth(self):
00175         x1 = self.last_msg.width / 2 - 10
00176         x2 = self.last_msg.width / 2 + 10
00177         y1 = self.last_msg.height / 2 - 10
00178         y2 = self.last_msg.height / 2 + 10
00179 
00180         avg_depth = get_pixels_depth(x1, y1, x2, y2, self.last_msg)
00181         return avg_depth
00182 
00183 
00184 if __name__ == '__main__':
00185     rospy.init_node('rgbd_play')
00186     lp = RGBDPlay()
00187     rospy.spin()


play_with_sensors
Author(s):
autogenerated on Fri Aug 26 2016 13:20:19