00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 import numpy as np
00033
00034 import roslib
00035 roslib.load_manifest('hrl_pr2_force_ctrl')
00036
00037 import rospy
00038 from pr2_manipulation_controllers.msg import JTTaskControllerState
00039 from geometry_msgs.msg import WrenchStamped
00040 from std_msgs.msg import Float64MultiArray, Header, Bool
00041
00042 from ep_arm_base import EPArmBase, create_ep_arm
00043 from pr2_arm_cart_base import PR2ArmCartPostureBase, extract_twist
00044 from hrl_geom.pose_converter import PoseConv
00045
00046 from hrl_pr2_arms.pr2_arm import PR2ArmCartesianPostureBase, extract_twist
00047 from msg import HybridCartesianGains, HybridForceState
00048
00049
00050
00051
00052
00053 class PR2ArmHybridForce(PR2ArmCartPostureBase):
00054 def __init__(self, arm_side, urdf, base_link='torso_lift_link', end_link='%s_gripper_tool_frame',
00055 controller_name='/%s_cart', kdl_tree=None, timeout=1.):
00056 super(PR2ArmJTranspose, self).__init__(arm_side, urdf, base_link, end_link,
00057 controller_name, kdl_tree, timeout)
00058 self.auto_update = False
00059 self.command_gains_pub = rospy.Publisher(controller_name + '/gains', HybridCartesianGains)
00060 self.command_force_pub = rospy.Publisher(controller_name + '/command_force', WrenchStamped)
00061 self.command_force_max_pub = rospy.Publisher(controller_name + '/command_max_force',
00062 WrenchStamped)
00063 self.command_zero_pub = rospy.Publisher(controller_name + '/ft_zero', Bool)
00064 self.ft_wrench_sub = rospy.Subscriber(controller_name + '/ft_wrench', WrenchStamped,
00065 self._ft_wrench_cb)
00066 self.ft_wrench = np.mat(6 * [0]).T
00067 self.tip_frame = rospy.get_param(controller_name + '/tip_name')
00068 self.force_selector = 6 * [0]
00069
00070 self.trans_p_motion_gains = 3 * [rospy.get_param(controller_name + '/cart_gains/trans/p')]
00071 self.trans_d_motion_gains = 3 * [rospy.get_param(controller_name + '/cart_gains/trans/d')]
00072
00073 self.rot_p_motion_gains = 3 * [rospy.get_param(controller_name + '/cart_gains/rot/p')]
00074 self.rot_d_motion_gains = 3 * [rospy.get_param(controller_name + '/cart_gains/rot/d')]
00075
00076 self.trans_p_force_gains = 3 * [rospy.get_param(controller_name + '/force_gains/trans/p')]
00077 self.trans_i_force_gains = 3 * [rospy.get_param(controller_name + '/force_gains/trans/i')]
00078 self.trans_i_max_force_gains = 3 * [rospy.get_param(controller_name +
00079 '/force_gains/trans/i_max')]
00080
00081 self.rot_p_force_gains = 3 * [rospy.get_param(controller_name + '/force_gains/rot/p')]
00082 self.rot_i_force_gains = 3 * [rospy.get_param(controller_name + '/force_gains/rot/i')]
00083 self.rot_i_max_force_gains = 3 * [rospy.get_param(controller_name + '/force_gains/rot/i_max')]
00084
00085 self.ctrl_state_dict = {}
00086 rospy.Subscriber(self.controller_name + '/state', JTTaskControllerState,
00087 self._ctrl_state_cb)
00088 if self.wait_for_joint_angles(0):
00089 if not self.wait_for_ep(timeout):
00090 rospy.logwarn("[pr2_arm_hybrid] Timed out waiting for EP.")
00091
00092 def _ctrl_state_cb(self, ctrl_state):
00093 with self.ep_lock:
00094 self.ep = PoseConv.to_homo_mat(ctrl_state.x_desi_filtered)
00095 with self.ctrl_state_lock:
00096 self.ctrl_state_dict["frame"] = ctrl_state.header.frame_id
00097 self.ctrl_state_dict["x_desi"] = PoseConverter.to_pos_rot(ctrl_state.x_desi)
00098 self.ctrl_state_dict["xd_desi"] = extract_twist(ctrl_state.xd_desi)
00099 self.ctrl_state_dict["x_act"] = PoseConverter.to_pos_rot(ctrl_state.x)
00100 self.ctrl_state_dict["xd_act"] = extract_twist(ctrl_state.xd)
00101 self.ctrl_state_dict["x_desi_filt"] = PoseConverter.to_pos_rot(
00102 ctrl_state.x_desi_filtered)
00103 self.ctrl_state_dict["x_err"] = extract_twist(ctrl_state.x_err)
00104 self.ctrl_state_dict["tau_pose"] = np.array(ctrl_state.tau_pose)
00105 self.ctrl_state_dict["tau_posture"] = np.array(ctrl_state.tau_posture)
00106 self.ctrl_state_dict["tau"] = np.array(ctrl_state.tau)
00107 self.ctrl_state_dict["F"] = np.array([ctrl_state.F.force.x,
00108 ctrl_state.F.force.y,
00109 ctrl_state.F.force.z,
00110 ctrl_state.F.torque.x,
00111 ctrl_state.F.torque.y,
00112 ctrl_state.F.torque.z])
00113
00114 def _ft_wrench_cb(self, ws):
00115 self.ft_wrench = np.mat([ws.wrench.force.x, ws.wrench.force.y, ws.wrench.force.z,
00116 ws.wrench.torque.x, ws.wrench.torque.y, ws.wrench.torque.z]).T
00117
00118 def get_ft_wrench(self):
00119 return self.ft_wrench
00120
00121 def set_motion_gains(self, p_trans=None, p_rot=None, d_trans=None, d_rot=None):
00122 local_names = ['trans_p_motion_gains', 'rot_p_motion_gains',
00123 'trans_d_motion_gains', 'rot_d_motion_gains']
00124 vals = [p_trans, p_rot, d_trans, d_rot]
00125 for local_name, val in zip(local_names, vals):
00126 self._set_gain(local_name, val)
00127 if self.auto_update:
00128 self.update_gains()
00129
00130 def set_force_gains(self, p_trans=None, p_rot=None, i_trans=None, i_rot=None,
00131 i_max_trans=None, i_max_rot=None):
00132 local_names = ['trans_p_force_gains', 'rot_p_force_gains',
00133 'trans_i_force_gains','rot_i_force_gains',
00134 'trans_i_max_force_gains','rot_i_max_force_gains']
00135 vals = [p_trans, p_rot, i_trans, i_rot, i_max_trans, i_max_rot]
00136 for local_name, val in zip(local_names, vals):
00137 self._set_gain(local_name, val)
00138 if self.auto_update:
00139 self.update_gains()
00140
00141 def _set_gain(self, local_name, val):
00142 if val is not None:
00143 try:
00144 if len(val) == 3:
00145 self.__dict__[local_name] = list(val)
00146 else:
00147 raise Exception()
00148 except Exception as e:
00149 if type(val) in [int, float]:
00150 self.__dict__[local_name] = 3 * [float(val)]
00151 else:
00152 rospy.logerr("Bad gain parameter (must be single value or array-like of 3)")
00153
00154 def set_tip_frame(self, tip_frame):
00155 self.tip_frame = tip_frame
00156 if self.auto_update:
00157 self.update_gains()
00158
00159 def set_force_directions(self, directions):
00160 if len(directions) == 6 and all([direction in [0, 1] for direction in directions]):
00161 self.force_selector = list(directions)
00162 return
00163 self.force_selector = 6 * [0]
00164 names = ['x', 'y', 'z', 'rx', 'ry', 'rz']
00165 for direction in directions:
00166 if direction in names:
00167 self.force_selector[names.index(direction)] = 1
00168 if self.auto_update:
00169 self.update_gains()
00170
00171 def set_mass_params(self, mass, center_of_mass=None):
00172 params_msg = Float64MultiArray()
00173 params_msg.data = [mass]
00174 if center_of_mass is not None:
00175 params_msg.data += list(center_of_mass)
00176
00177 def update_gains(self):
00178 p_gains = self.trans_p_motion_gains + self.rot_p_motion_gains
00179 d_gains = self.trans_d_motion_gains + self.rot_d_motion_gains
00180 fp_gains = self.trans_p_force_gains + self.rot_p_force_gains
00181 fi_gains = self.trans_i_force_gains + self.rot_i_force_gains
00182 fi_max_gains = self.trans_i_max_force_gains + self.rot_i_max_force_gains
00183 gains_msg = HybridCartesianGains(Header(0, rospy.Time.now(), self.tip_frame),
00184 p_gains, d_gains,
00185 fp_gains, fi_gains, fi_max_gains, self.force_selector)
00186 self.command_gains_pub.publish(gains_msg)
00187
00188 def set_force(self, f, frame=None):
00189 if frame is None:
00190 frame = self.tip_frame
00191 f_msg = WrenchStamped()
00192 f_msg.header.stamp = rospy.Time.now()
00193 f_msg.header.frame_id = frame
00194 f_msg.wrench.force.x, f_msg.wrench.force.y, f_msg.wrench.force.z = f[0], f[1], f[2]
00195 f_msg.wrench.torque.x, f_msg.wrench.torque.y, f_msg.wrench.torque.z = f[3], f[4], f[5]
00196 self.command_force_pub.publish(f_msg)
00197
00198 def set_force_max(self, f):
00199 f_msg = WrenchStamped()
00200 f_msg.header.stamp = rospy.Time.now()
00201 f_msg.wrench.force.x, f_msg.wrench.force.y, f_msg.wrench.force.z = f[0], f[1], f[2]
00202 f_msg.wrench.torque.x, f_msg.wrench.torque.y, f_msg.wrench.torque.z = f[3], f[4], f[5]
00203 self.command_force_max_pub.publish(f_msg)
00204
00205 def zero_sensor(self):
00206 bool_msg = Bool()
00207 self.command_zero_pub.publish(bool_msg)
00208
00209 def use_auto_update(self, use_auto_update):
00210 self.auto_update = use_auto_update