look_at_point_behavior.py
Go to the documentation of this file.
00001 #!/usr/bin/python
00002 import roslib
00003 roslib.load_manifest("pr2_laser_follow_behavior")
00004 import rospy
00005 
00006 import numpy as np
00007 import math
00008 
00009 from actionlib_msgs.msg import *
00010 from pr2_controllers_msgs.msg import *
00011 from geometry_msgs.msg import *
00012 from std_msgs.msg import String
00013 from move_base_msgs.msg import *
00014 
00015 import actionlib
00016 import tf
00017 import laser_interface.camera as cam
00018 import hrl_lib.tf_utils as tfu
00019 from threading import RLock
00020 
00021 
00022 def in_bounds(p2d, xlim, ylim):
00023     return (xlim[0] <= p2d[0,0]) and (p2d[0,0] <= xlim[1]) \
00024             and (ylim[0] <= p2d[1,0]) and (p2d[1,0] <= ylim[1])
00025 
00026 class LookAtBehavior:
00027 
00028     def __init__(self, camera_root_topic):
00029         #self.wait = False
00030         #self.point3d = None
00031         self.state = 'ready'
00032         self.lock = RLock()
00033         self.lock.acquire()
00034         self.message = None 
00035         self.STATES = {'ready':'ready',                      # none
00036                        'head_turn': 'head_turn',             # something
00037                        #'head_turn_drive': 'head_turn_drive', # something
00038                        'driving': 'driving'}                 # something
00039 
00040         rospy.init_node('look_at_point_behavior', anonymous=True)
00041         rospy.Subscriber('cursor3d', PointStamped, self.laser_point_handler)
00042         self.point_pub = rospy.Publisher('cursor3dcentered', PointStamped)
00043         self.double_click = rospy.Subscriber('mouse_left_double_click', String, self.move_base_double_click)
00044         self.double_click2 = rospy.Subscriber('mouse_left_double_click', String, self.cancel_move_base_double_click)
00045         self.camera_model = cam.ROSStereoCalibration('/' + camera_root_topic + '/left/camera_info' , 
00046                                                      '/' + camera_root_topic + '/right/camera_info')
00047         self.head_client = actionlib.SimpleActionClient('head_traj_controller/point_head_action', PointHeadAction)
00048         #self.head_client.wait_for_server()
00049         self.base_client = actionlib.SimpleActionClient('move_base', MoveBaseAction)
00050         #self.base_client.wait_for_server()
00051         #self.move_pub = rospy.Publisher('move_base_simple/goal', PoseStamped)
00052         self.move_pub = rospy.Publisher('look_at_point_goal', PoseStamped)
00053         #self.move_pub2 = rospy.Publisher('hai_constant', PoseStamped)
00054         self.tflistener = tf.TransformListener()
00055         self.lock.release()
00056         print 'running'
00057 
00058 
00059     def move_base_double_click(self, a_str):
00060         if self.message == None:
00061             rospy.logwarn('Unable to go, no message heard.')
00062             return
00063         else:
00064             self.lock.acquire()
00065             self.state = self.STATES['driving']
00066             #Looking at the point last clicked on... (maybe keep doing this as we drive?)
00067             #self.look_at(self.message)
00068 
00069             #Move base
00070             self.move_base(self.message)
00071             self.message = None
00072             self.state = self.STATES['ready']
00073             self.lock.release()
00074 
00075     def transform_point(self, point_stamped):
00076         point_head = point_stamped.point
00077 
00078         #Tranform into base link
00079         target_link = '/base_link'
00080         base_T_head = tfu.transform(target_link, point_stamped.header.frame_id, self.tflistener)
00081         point_mat_head = tfu.translation_matrix([point_head.x, point_head.y, point_head.z])
00082         point_mat_base = base_T_head * point_mat_head
00083         t_base, o_base = tfu.matrix_as_tf(point_mat_base)
00084 
00085         #Calculate angle robot should face
00086         angle = math.atan2(t_base[1], t_base[0])
00087         q = tf.transformations.quaternion_from_euler(0, 0, angle)
00088         return (t_base, q, target_link)
00089 
00090         
00091     def move_base(self, point, wait=False):
00092         t_base, q, target_link = point
00093         ps = PoseStamped()
00094         ps.header.frame_id  = target_link
00095         ps.pose.position    = geometry_msgs.msg.Point(t_base[0], t_base[1], 0)
00096         ps.pose.orientation = geometry_msgs.msg.Quaternion(*q)
00097         self.move_pub.publish(ps)
00098 
00099         #Uncomment to actually move
00100         goal = MoveBaseGoal()
00101         goal.target_pose.header.frame_id = target_link
00102         goal.target_pose.pose.position = geometry_msgs.msg.Point(t_base[0], t_base[1], 0)
00103         goal.target_pose.pose.orientation = geometry_msgs.msg.Quaternion(*q)
00104         self.base_client.send_goal(goal)
00105         print 'Sent GOAL'
00106         if wait:
00107             self.base_client.wait_for_result()
00108         if self.base_client.get_state() == GoalStatus.SUCCEEDED:
00109             return True
00110         else:
00111             return False
00112 
00113     def laser_point_handler(self, point_stamped):
00114         p = np.matrix([point_stamped.point.x, point_stamped.point.y, point_stamped.point.z, 1.]).T
00115         p2d = self.camera_model.left.P * p
00116         p2d = p2d / p2d[2,0]
00117         bx = ((self.camera_model.left.w/2.) * .9)
00118         by = ((self.camera_model.left.h/2.) * .9)
00119         xlim = [bx, self.camera_model.left.w - bx]
00120         ylim = [by, self.camera_model.left.h - by]
00121 
00122         if (self.state == self.STATES['driving']):
00123             return
00124         self.message = self.transform_point(point_stamped)
00125 
00126         if not in_bounds(p2d, xlim, ylim):
00127             if self.state != self.STATES['head_turn']:
00128                 self.lock.acquire()
00129                 self.state = self.STATES['head_turn']
00130                 self.lock.release()
00131         #else if we are in bounds, we do nothing 
00132         #always update laser's location
00133 
00134     def run(self):
00135         r = rospy.Rate(50)
00136         while not rospy.is_shutdown():
00137             r.sleep()
00138             if self.state == self.STATES['head_turn']:
00139                 self.lock.acquire()
00140                 result = self.look_at(self.message, False)
00141                 self.state = self.STATES['ready']
00142                 self.lock.release()
00143 
00144     def look_at(self, message, wait=True):
00145         g = PointHeadGoal()
00146         g.target.header.frame_id = message[2]
00147         g.target.point = geometry_msgs.msg.Point(*message[0])
00148         g.min_duration = rospy.Duration(1.0)
00149         g.max_velocity = 10.
00150 
00151         self.head_client.send_goal(g)
00152         #rospy.loginfo('Sent look at goal ' + str(g))
00153         if wait:
00154             self.head_client.wait_for_result()
00155 
00156         if self.head_client.get_state() == GoalStatus.SUCCEEDED:
00157             return True
00158         else:
00159             return False
00160 
00161 if __name__ == '__main__':
00162     lab = LookAtBehavior('wide_stereo')
00163     lab.run()
00164 
00165 
00166 
00167     


pr2_laser_follow_behavior
Author(s): Hai Nguyen, Advisor: Prof. Charlie Kemp, Lab: Healthcare Robotics Lab at Georgia Tech
autogenerated on Wed Nov 27 2013 12:17:18