00001
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
00030
00031 self.state = 'ready'
00032 self.lock = RLock()
00033 self.lock.acquire()
00034 self.message = None
00035 self.STATES = {'ready':'ready',
00036 'head_turn': 'head_turn',
00037
00038 'driving': 'driving'}
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
00049 self.base_client = actionlib.SimpleActionClient('move_base', MoveBaseAction)
00050
00051
00052 self.move_pub = rospy.Publisher('look_at_point_goal', PoseStamped)
00053
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
00067
00068
00069
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
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
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
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
00132
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
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