pr2_arm_hybrid.py
Go to the documentation of this file.
00001 #! /usr/bin/python
00002 #
00003 # Class for interacting with the hybrid force realtime controller.
00004 #
00005 # Copyright (c) 2012, Georgia Tech Research Corporation
00006 # All rights reserved.
00007 # 
00008 # Redistribution and use in source and binary forms, with or without
00009 # modification, are permitted provided that the following conditions are met:
00010 #     * Redistributions of source code must retain the above copyright
00011 #       notice, this list of conditions and the following disclaimer.
00012 #     * Redistributions in binary form must reproduce the above copyright
00013 #       notice, this list of conditions and the following disclaimer in the
00014 #       documentation and/or other materials provided with the distribution.
00015 #     * Neither the name of the Georgia Tech Research Corporation nor the
00016 #       names of its contributors may be used to endorse or promote products
00017 #       derived from this software without specific prior written permission.
00018 # 
00019 # THIS SOFTWARE IS PROVIDED BY GEORGIA TECH RESEARCH CORPORATION ''AS IS'' AND
00020 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022 # DISCLAIMED. IN NO EVENT SHALL GEORGIA TECH BE LIABLE FOR ANY DIRECT, INDIRECT,
00023 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00024 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00025 # OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00026 # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
00027 # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00028 # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 #
00030 # Author: Kelsey Hawkins
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 # Class for interacting with the Cartesian controllers on the PR2.
00051 # Controller type: hrl_pr2_force_ctrl/HybridForce
00052 # The equilibrium points are pose-like objects.
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


hrl_pr2_force_ctrl
Author(s): Kelsey Hawkins
autogenerated on Wed Nov 27 2013 11:42:28