object_manipulation.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # Copyright (c) 2013, Oregon State University
00003 # All rights reserved.
00004 #
00005 # Redistribution and use in source and binary forms, with or without
00006 # modification, are permitted provided that the following conditions are met:
00007 #     * Redistributions of source code must retain the above copyright
00008 #       notice, this list of conditions and the following disclaimer.
00009 #     * Redistributions in binary form must reproduce the above copyright
00010 #       notice, this list of conditions and the following disclaimer in the
00011 #       documentation and/or other materials provided with the distribution.
00012 #     * Neither the name of the Oregon State University nor the
00013 #       names of its contributors may be used to endorse or promote products
00014 #       derived from this software without specific prior written permission.
00015 #
00016 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00017 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 # DISCLAIMED. IN NO EVENT SHALL OREGON STATE UNIVERSITY BE LIABLE FOR ANY
00020 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00022 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00023 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00024 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00025 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 #
00027 # Author Dan Lazewatsky/lazewatd@engr.orst.edu
00028 
00029 import roslib; roslib.load_manifest('projector_interface')
00030 from pr2_pick_and_place_demos.pick_and_place_manager import PickAndPlaceManager
00031 from geometry_msgs.msg import PointStamped, PoseStamped, PolygonStamped, Point
00032 from sensor_msgs.msg import PointCloud2
00033 from projector_interface.srv import GetCursorStats, DrawPolygon, CircleInhibit
00034 from std_msgs.msg import Empty
00035 from threading import RLock
00036 import rospy
00037 from matplotlib.nxutils import pnpoly
00038 from pr2_python.geometry_tools import euler_to_quaternion
00039 from object_manipulation_msgs.msg import ManipulationResult
00040 from copy import deepcopy
00041 import numpy as np
00042 from projector_interface._point_cloud import read_points_np
00043 
00044 
00045 NOTGRASPING = 0
00046 GRASPING    = 1
00047 
00048 x =  0.14744849503040314 - 0.03
00049 y = -0.49022838473320007 + 0.005
00050 w = 0.15
00051 h = 0.21
00052 p = 0.02
00053 RECYCLING = PolygonStamped()
00054 TRASH     = PolygonStamped()
00055 RECYCLING.header.frame_id = 'table'
00056 TRASH.header.frame_id     = 'table'
00057 
00058 RECYCLING.polygon.points.append(Point(x    , y    ,  0.))
00059 RECYCLING.polygon.points.append(Point(x - h, y    ,  0.))
00060 RECYCLING.polygon.points.append(Point(x - h, y + w,  0.))
00061 RECYCLING.polygon.points.append(Point(x    , y + w,  0.))
00062 
00063 TRASH.polygon.points.append(    Point(x -   (h+p), y,      0.))
00064 TRASH.polygon.points.append(    Point(x - (2*h+p), y,      0.))
00065 TRASH.polygon.points.append(    Point(x - (2*h+p), y + w,  0.))
00066 TRASH.polygon.points.append(    Point(x -   (h+p), y + w,  0.))
00067 
00068 class Manipulator(object):
00069     state = NOTGRASPING
00070     point = None
00071     grasp_arm = -1
00072     INPROGRESS = False
00073     click_lock = RLock()
00074     def __init__(self):
00075         self.place_viz_pub = rospy.Publisher('place_pose', PoseStamped)
00076         self.manager = PickAndPlaceManager()
00077         self.cursor_proxy = rospy.ServiceProxy('get_cursor_stats', GetCursorStats)
00078         #~ self.cursor_proxy.wait_for_service()
00079         rospy.loginfo("Waiting for polygon service")
00080         self.polygon_proxy = rospy.ServiceProxy('draw_polygon', DrawPolygon)
00081         self.polygon_proxy.wait_for_service()
00082         rospy.loginfo("Waiting for circle inhibit service")
00083         self.circle_inhibit_proxy = rospy.ServiceProxy('circle_inhibit', CircleInhibit)
00084         self.circle_inhibit_proxy.wait_for_service()
00085         
00086         rospy.loginfo("Drawing trash/recycling")
00087         self.polygon_proxy('Recycling', True, RECYCLING)
00088         self.polygon_proxy('Garbage', True, TRASH)
00089         
00090     
00091     def click(self, msg):
00092         if self.click_lock.acquire(blocking=False):
00093             #~ self.circle_inhibit_proxy(True)
00094             rospy.logwarn('Calling tabletop detection')
00095             self.manager.call_tabletop_detection()
00096             # self.point = self.cursor_proxy().click_pos
00097             print 'STATE = ',self.state
00098             if self.state == NOTGRASPING:
00099                 rospy.logwarn('About to grasp')
00100                 self.grasp()
00101             elif self.state == GRASPING:
00102                 rospy.logwarn('About to drop')
00103                 self.drop()
00104             self.click_lock.release()
00105             #~ self.circle_inhibit_proxy(False)
00106 
00107     def point_cb(self, msg):
00108         #self.point = msg
00109         cloud = read_points_np(msg)
00110         point = PointStamped()
00111         point.header = msg.header
00112         if cloud.shape[1] == 0: return
00113         point.point.x, point.point.y, point.point.z = cloud[0][0]
00114         self.point = point
00115     
00116 
00117     def transformAtLatestCommonTime(self, target_frame, point):
00118         lct = self.manager.tf_listener.getLatestCommonTime(point.header.frame_id, target_frame)
00119         point_lct = deepcopy(point)
00120         point_lct.header.stamp = lct
00121         return self.manager.tf_listener.transformPoint(target_frame, point_lct)
00122 
00123     #TODO need to make sure we can't trigger grasp/drop multiple times concurrently
00124     def grasp(self):
00125         print self.state, self.point
00126         if (self.state == NOTGRASPING) and (self.point is not None):
00127             rospy.loginfo('===grasping')
00128             self.manager.move_arm_to_side(0)
00129             ptt = self.transformAtLatestCommonTime('base_link', self.point)
00130             status = self.manager.pick_up_object_near_point(ptt, 0)
00131             self.grasp_arm = 0
00132             # if not success:
00133             #     self.manager.move_arm_to_side(1)
00134             #     success = self.manager.pick_up_object_near_point(self.point, 1)
00135             #     self.grasp_arm = 1
00136             if status == ManipulationResult.SUCCESS:
00137                 self.state = GRASPING
00138                 rospy.logerr('SUCCESSFUL GRASP')
00139             else:
00140                 rospy.logerr('FAILED TO GRASP')
00141         
00142     def drop(self):
00143         if self.state == GRASPING:
00144             #success = self.manager.put_down_object(self.grasp_arm, max_place_tries=25, use_place_override=1)
00145             place_pose = PoseStamped()
00146             ptt = self.transformAtLatestCommonTime('table', self.point)
00147             place_pose.header = ptt.header 
00148             place_pose.pose.position = ptt.point
00149             place_pose.pose.orientation = euler_to_quaternion(0,0,0)
00150             place_pose.pose.position.z = 0.03
00151             # see if it's in one of our predefined boxes
00152             
00153             pw,ph = 0.1,0.1
00154        
00155             #boxes = [('TRASH', TRASH), ('RECYCLING', RECYCLING)]
00156             boxes = []
00157             for name, polygon in boxes:
00158                 pts_arr = np.array([[(p.x,p.y) for p in polygon.polygon.points]])
00159                 print pts_arr
00160                 if pnpoly(ptt.point.x, ptt.point.y, pts_arr.squeeze()):
00161                     # we're doing this from the top right corner (don't ask)
00162                     # place_pose.pose.position = polygon.polygon.points[0]
00163                     poly_center = pts_arr.squeeze().mean(0)
00164                     place_pose.pose.position.x = poly_center[0]
00165                     place_pose.pose.position.y = poly_center[1]
00166                     pw,ph = w,h
00167                     rospy.loginfo('Placing in box: %s' % name)
00168                     
00169             rospy.loginfo('Placing at %s' % place_pose)
00170             self.place_viz_pub.publish(place_pose)
00171             
00172             #import pdb; pdb.set_trace()
00173 
00174             self.manager.set_place_area(place_pose, (pw,ph))
00175             # status = self.manager.place_object(self.grasp_arm, place_pose, padding=0) 
00176             status = self.manager.put_down_object(self.grasp_arm, max_place_tries=25, use_place_override=1)
00177             if status == ManipulationResult.SUCCESS:
00178                 self.state = NOTGRASPING
00179                 self.grasp_arm = -1
00180 
00181 if __name__ == '__main__':
00182     rospy.init_node('manipulator')
00183     manipulator = Manipulator()
00184     rospy.Subscriber('click', Empty, manipulator.click, queue_size=1)
00185     rospy.Subscriber('intersected_points', PointCloud2, manipulator.point_cb)
00186     rospy.loginfo('READY')
00187     rospy.spin()


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