00001
00002 import roslib; roslib.load_manifest('pr2_doors_executive')
00003 import rospy
00004
00005 import math
00006
00007 from geometry_msgs.msg import *
00008 from door_msgs.msg import *
00009
00010 import tf
00011 import tf.transformations as transformations
00012 import conversions
00013
00014 import PyKDL as kdl
00015
00016 eps_angle = 5.0*math.pi/180.0
00017 gripper_height = 0.8
00018
00019 def point2kdl(point):
00020 return kdl.Vector(point.x, point.y, point.z)
00021
00022 def kdl2point(vector):
00023 return Point(vector.x, vector.y, vector.z)
00024
00025 def get_door_angle(door):
00026 frame_vec = kdl.Vector(
00027 door.frame_p1.x-door.frame_p2.x,
00028 door.frame_p1.y-door.frame_p2.y,
00029 door.frame_p1.z-door.frame_p2.z)
00030 door_vec = kdl.Vector(
00031 door.door_p1.x-door.door_p2.x,
00032 door.door_p1.y-door.door_p2.y,
00033 door.door_p1.z-door.door_p2.z)
00034
00035 angle = get_yaw_angle(frame_vec, door_vec)
00036
00037 if door.rot_dir == Door.ROT_DIR_CLOCKWISE and angle > eps_angle:
00038 rospy.logdebug("Door angle is positive, but door message specifies it turns clockwise")
00039
00040 if door.rot_dir == Door.ROT_DIR_COUNTERCLOCKWISE and angle < -eps_angle:
00041 rospy.logdebug("Door angle is negative, but door message specifies it turns counter-clockwise")
00042
00043 return angle
00044
00045 def get_door_normal(door):
00046 frame_normal = get_frame_normal(door)
00047 rot_frame_door = kdl.Rotation.RotZ(get_door_angle(door))
00048 return rot_frame_door * frame_normal
00049
00050 def get_frame_normal(door):
00051 """Get the normal of the door frame.
00052 @type door: door_msgs.msg.Door
00053 @rtype: kdl.Vector
00054 """
00055
00056 p12 = kdl.Vector(
00057 door.frame_p1.x - door.frame_p2.x,
00058 door.frame_p1.y - door.frame_p2.y,
00059 door.frame_p1.z - door.frame_p2.z)
00060
00061 p12.Normalize()
00062 z_axis = kdl.Vector(0,0,1)
00063 normal = p12 * z_axis
00064
00065
00066 direction = kdl.Vector(
00067 door.travel_dir.x,
00068 door.travel_dir.y,
00069 door.travel_dir.z)
00070
00071 if kdl.dot(direction, normal) < 0:
00072 normal = normal * -1.0
00073
00074 return normal
00075
00076 def get_Frame_angle(door):
00077 if door.hinge == door.HINGE_P1:
00078 return math.atan2(door.frame_p2.y - door.frame_p1.y, door.frame_p2.x - door.frame_p1.x)
00079 else:
00080 return math.atan2(door.frame_p1.y - door.frame_p2.y, door.frame_p1.x - door.frame_p2.x)
00081
00082 def get_door_dir(door):
00083
00084 if door.hinge == Door.HINGE_P1:
00085 frame_vec = point2kdl(door.frame_p2) - point2kdl(door.frame_p1)
00086 elif door.hinge == Door.HINGE_P2:
00087 frame_vec = point2kdl(door.frame_p1) - point2kdl(door.frame_p2)
00088 else:
00089 rospy.logerr("Hinge side is not defined")
00090
00091
00092 if door.rot_dir == Door.ROT_DIR_CLOCKWISE:
00093 frame_vec = kdl.Rotation.RotZ(-math.pi/2) * frame_vec
00094 elif door.rot_dir == Door.ROT_DIR_COUNTERCLOCKWISE:
00095 frame_vec = kdl.Rotation.RotZ(math.pi/2) * frame_vec
00096 else:
00097 rospy.logerr("Rot dir is not defined")
00098
00099 if kdl.dot(frame_vec, get_frame_normal(door)) < 0:
00100 return -1.0
00101 else:
00102 return 1.0
00103
00104 def get_handle_dir(door):
00105 frame_normal = get_frame_normal(door)
00106
00107 if door.hinge == Door.HINGE_P1:
00108 frame_vec = point2kdl(door.frame_p2) - point2kdl(door.frame_p1)
00109 elif door.hinge == Door.HINGE_P2:
00110 frame_vec = point2kdl(door.frame_p1) - point2kdl(door.frame_p2)
00111 else:
00112 rospy.logerr("Hinge side is not defined")
00113
00114 rot_vec = frame_vec * frame_normal
00115 if rot_vec[2] > 0:
00116 return -1.0
00117 else:
00118 return 1.0
00119
00120 def get_yaw_angle(v1, v2):
00121 """Get the angle between the projections of v1 and v2 onto the XY plane.
00122 @type v1: kdl.Vector
00123 @type v2: kdl.Vector
00124 @rtype: double
00125 """
00126 vec1 = v1
00127 vec2 = v2
00128 vec1.Normalize()
00129 vec2.Normalize()
00130 dot = vec2[0] * vec1[0] + vec2[1] * vec1[1]
00131 perp_dot = vec2[1] * vec1[0] - vec2[0] * vec1[1]
00132 return math.atan2(perp_dot, dot)
00133
00134 def get_robot_pose(door, dist):
00135 """Get a robot pose some distance from the door.
00136 @type door: door_msgs.msg.Door
00137 @rtype: geometry_msgs.msg.PoseStamped
00138 """
00139 x_axis = kdl.Vector(1,0,0)
00140
00141 frame_1 = kdl.Vector(door.frame_p1.x, door.frame_p1.y, door.frame_p1.z)
00142 frame_2 = kdl.Vector(door.frame_p2.x, door.frame_p2.y, door.frame_p2.z)
00143 frame_center = (frame_1+frame_2)/2.0
00144
00145 frame_normal = get_frame_normal(door)
00146 robot_pos = frame_center + (frame_normal * dist)
00147
00148 robot_pose = kdl.Frame(
00149 kdl.Rotation.RPY(0,0,get_yaw_angle(x_axis, frame_normal)),
00150 robot_pos)
00151
00152 robot_pose_msg = PoseStamped()
00153 robot_pose_msg.header.frame_id = door.header.frame_id
00154 robot_pose_msg.header.stamp = door.header.stamp
00155 robot_pose_msg.pose = conversions.toMsg(robot_pose)
00156
00157 return robot_pose_msg
00158
00159 def get_gripper_pose(door, angle, dist, side):
00160 x_axis = kdl.Vector(1,0,0)
00161
00162
00163 hinge = kdl.Vector()
00164 frame_vec = kdl.Vector()
00165
00166 if door.hinge == Door.HINGE_P1:
00167 hinge = kdl.Vector(door.door_p1.x, door.door_p1.y, door.door_p1.z)
00168 frame_vec = kdl.Vector(
00169 door.frame_p2.x - door.frame_p1.x,
00170 door.frame_p2.y - door.frame_p1.y,
00171 door.frame_p2.z - door.frame_p1.z)
00172 elif door.hinge == Door.HINGE_P2:
00173 hinge = kdl.Vector(door.door_p2.x, door.door_p2.y, door.door_p2.z)
00174 frame_vec = kdl.Vector(
00175 door.frame_p1.x - door.frame_p2.x,
00176 door.frame_p1.y - door.frame_p2.y,
00177 door.frame_p1.z - door.frame_p2.z)
00178
00179
00180 frame_vec.Normalize()
00181 frame_vec = frame_vec * dist
00182 rot_angle = kdl.Rotation.RotZ(angle)
00183 gripper_pos = hinge + (rot_angle * frame_vec)
00184
00185 frame_normal = get_frame_normal(door)
00186
00187 if side == DoorCmd.PULL:
00188 axis_sign = -1.0
00189 else:
00190 axis_sign = 1.0
00191
00192 gripper_pose = kdl.Frame(
00193 kdl.Rotation.RPY(0,0,get_yaw_angle(axis_sign*x_axis, frame_normal)+angle),
00194 gripper_pos)
00195
00196 gripper_pose_msg = PoseStamped()
00197 gripper_pose_msg.header.frame_id = door.header.frame_id
00198 gripper_pose_msg.header.stamp = door.header.stamp
00199 gripper_pose_msg.pose = gripper_pose
00200
00201 return gripper_pose_msg
00202
00203 def get_handle_pose(door, side):
00204 x_axis = kdl.Vector(1,0,0)
00205
00206 dist = math.sqrt(
00207 math.pow(door.frame_p1.x - door.handle.x,2)
00208 +math.pow(door.frame_p1.y - door.handle.y,2))
00209
00210 if door.hinge == Door.HINGE_P2:
00211 dist = math.sqrt(math.pow(door.frame_p2.x - door.handle.x,2)+math.pow(door.frame_p2.y - door.handle.y,2))
00212
00213 angle = get_door_angle(door)
00214
00215
00216
00217 if door.hinge == Door.HINGE_P1:
00218 hinge = point2kdl(door.door_p1)
00219 frame_vec = point2kdl(door.frame_p2) - point2kdl(door.frame_p1)
00220 else:
00221 hinge = point2kdl(door.door_p2)
00222 frame_vec = point2kdl(door.frame_p1) - point2kdl(door.frame_p2)
00223
00224
00225 frame_vec.Normalize()
00226 frame_vec = frame_vec * dist
00227 rot_angle = kdl.Rotation.RotZ(angle)
00228 handle_pos = hinge + (rot_angle * frame_vec)
00229
00230
00231 frame_normal = get_frame_normal(door)
00232 if side == -1:
00233 frame_normal = -frame_normal
00234
00235 handle_pose = kdl.Frame(
00236 kdl.Rotation.RPY(0,0,get_yaw_angle(x_axis, frame_normal)),
00237 handle_pos)
00238
00239 gripper_rotate = kdl.Frame(
00240 kdl.Rotation.RPY(math.pi/2,0.0,0.0),
00241 kdl.Vector(0,0,0))
00242
00243 handle_pose = handle_pose * gripper_rotate
00244
00245 handle_pose_msg = PoseStamped()
00246 handle_pose_msg.header.frame_id = door.header.frame_id
00247 handle_pose_msg.header.stamp = door.header.stamp
00248 handle_pose_msg.pose = conversions.toMsg(handle_pose)
00249
00250 return handle_pose_msg