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 import math
00032 import numpy as np
00033 import copy
00034 import sys, time, os
00035 
00036 import PyKDL as kdl
00037 import create_IK_guess_dict as cgd
00038 
00039 import roslib; roslib.load_manifest('hrl_cody_arms')
00040 
00041 import hrl_lib.transforms as tr
00042 import hrl_lib.util as ut
00043 import hrl_lib.kdl_utils as ku
00044 
00045 
00046 def link_tf_name(arm, link_number):
00047     if arm == 'right_arm':
00048         nm = 'r_arm'
00049     else:
00050         nm = 'l_arm'
00051 
00052     if link_number == 0:
00053         nm = 'torso_link'
00054     elif link_number == 7:
00055         nm = nm + '_ee'
00056     else:
00057         nm = nm + '_' + str(link_number)
00058     return nm
00059 
00060 
00061 class M3HrlRobot():
00062     def __init__(self, end_effector_length):
00063         
00064         self.joint_lim_dict = {}
00065         self.joint_lim_dict['right_arm'] = {'max': np.radians([ 120.00, 122.15, 77.5, 144., 122.,  45.,  45.]),
00066                                             'min': np.radians([ -47.61,  -20., -77.5,   0., -80., -45., -45.])}
00067 
00068         self.joint_lim_dict['left_arm'] = {'max': np.radians([ 120.00,   20.,  77.5, 144.,   80.,  45.,  45.]),
00069                                            'min': np.radians([ -47.61, -122.15, -77.5,   0., -122., -45., -45.])}
00070 
00071         end_effector_length += 0.0135 + 0.04318 
00072         self.setup_kdl_mekabot(end_effector_length)
00073         q_guess_pkl_l = os.environ['HOME']+'/svn/gt-ros-pkg/hrl/hrl_arm_control/hrl_cody_arms/src/hrl_cody_arms/q_guess_left_dict.pkl'
00074         q_guess_pkl_r = os.environ['HOME']+'/svn/gt-ros-pkg/hrl/hrl_arm_control/hrl_cody_arms/src/hrl_cody_arms/q_guess_right_dict.pkl'
00075 
00076         self.q_guess_dict_left = ut.load_pickle(q_guess_pkl_l)
00077         self.q_guess_dict_right = ut.load_pickle(q_guess_pkl_r)
00078 
00079     
00080     
00081     def kdl_angles_to_meka(self, arm, q_jnt_arr):
00082         if q_jnt_arr == None:
00083             return None
00084 
00085         q_rad = [0. for i in range(7)]
00086         q_rad[0] = -q_jnt_arr[0]
00087         q_rad[1] = -q_jnt_arr[1]
00088         q_rad[2] = -q_jnt_arr[2]
00089         q_rad[3] = -q_jnt_arr[3]
00090         q_rad[4] = -q_jnt_arr[4]
00091         q_rad[5] = -q_jnt_arr[5]
00092         q_rad[6] = -q_jnt_arr[6]
00093         return q_rad
00094 
00095     
00096     
00097     def meka_angles_to_kdl(self,arm,q_list):
00098         if q_list == None:
00099             return None
00100 
00101         n_joints = len(q_list)
00102         q = kdl.JntArray(n_joints)
00103         q[0] = -q_list[0]
00104         q[1] = -q_list[1]
00105         q[2] = -q_list[2]
00106         if n_joints > 3:
00107             q[3] = -q_list[3]
00108         if n_joints == 7:
00109             q[4] = -q_list[4]
00110             q[5] = -q_list[5]
00111             q[6] = -q_list[6]
00112         return q
00113 
00114     def create_right_chain(self, end_effector_length):
00115         ch = kdl.Chain()
00116         ch.addSegment(kdl.Segment(kdl.Joint(kdl.Joint.RotY),kdl.Frame(kdl.Vector(0.,-0.18493,0.))))
00117         ch.addSegment(kdl.Segment(kdl.Joint(kdl.Joint.RotX),kdl.Frame(kdl.Vector(0.,-0.03175,0.))))
00118         ch.addSegment(kdl.Segment(kdl.Joint(kdl.Joint.RotZ),kdl.Frame(kdl.Vector(0.00635,0.,-0.27795))))
00119         ch.addSegment(kdl.Segment(kdl.Joint(kdl.Joint.RotY),kdl.Frame(kdl.Vector(0.,0.,-0.27853))))
00120         ch.addSegment(kdl.Segment(kdl.Joint(kdl.Joint.RotZ),kdl.Frame(kdl.Vector(0.,0.,0.))))
00121         ch.addSegment(kdl.Segment(kdl.Joint(kdl.Joint.RotY),kdl.Frame(kdl.Vector(0.,0.,0.))))
00122         ch.addSegment(kdl.Segment(kdl.Joint(kdl.Joint.RotX),kdl.Frame(kdl.Vector(0.,0.,-end_effector_length))))
00123         return ch
00124 
00125     def create_left_chain(self, end_effector_length):
00126         ch = kdl.Chain()
00127         ch.addSegment(kdl.Segment(kdl.Joint(kdl.Joint.RotY),kdl.Frame(kdl.Vector(0.,0.18493,0.))))
00128         ch.addSegment(kdl.Segment(kdl.Joint(kdl.Joint.RotX),kdl.Frame(kdl.Vector(0.,0.03175,0.))))
00129         ch.addSegment(kdl.Segment(kdl.Joint(kdl.Joint.RotZ),kdl.Frame(kdl.Vector(0.00635,0.,-0.27795))))
00130         ch.addSegment(kdl.Segment(kdl.Joint(kdl.Joint.RotY),kdl.Frame(kdl.Vector(0.,0.,-0.27853))))
00131         ch.addSegment(kdl.Segment(kdl.Joint(kdl.Joint.RotZ),kdl.Frame(kdl.Vector(0.,0.,0.))))
00132         ch.addSegment(kdl.Segment(kdl.Joint(kdl.Joint.RotY),kdl.Frame(kdl.Vector(0.,0.,0.))))
00133         ch.addSegment(kdl.Segment(kdl.Joint(kdl.Joint.RotX),kdl.Frame(kdl.Vector(0.,0.,-end_effector_length))))
00134         return ch
00135 
00136     def create_solvers(self, ch):
00137          fk = kdl.ChainFkSolverPos_recursive(ch)
00138          ik_v = kdl.ChainIkSolverVel_pinv(ch)
00139          ik_p = kdl.ChainIkSolverPos_NR(ch, fk, ik_v)
00140          jac = kdl.ChainJntToJacSolver(ch)
00141          return fk, ik_v, ik_p, jac
00142 
00143     def setup_kdl_mekabot(self, end_effector_length):
00144         
00145         ch = self.create_right_chain(end_effector_length)
00146         fk, ik_v, ik_p, jac = self.create_solvers(ch)
00147 
00148         kdl_rightarm = {}
00149         kdl_rightarm['chain'] = ch
00150         kdl_rightarm['nJnts'] = ch.getNrOfJoints()
00151         kdl_rightarm['fk_p'] = fk
00152         kdl_rightarm['ik_v'] = ik_v
00153         kdl_rightarm['ik_p'] = ik_p
00154         kdl_rightarm['jacobian_solver'] = jac
00155 
00156         
00157         kdl_leftarm = {}
00158         ch = self.create_left_chain(end_effector_length)
00159         fk, ik_v, ik_p, jac = self.create_solvers(ch)
00160 
00161         kdl_leftarm['chain'] = ch
00162         kdl_leftarm['nJnts'] = ch.getNrOfJoints()
00163         kdl_leftarm['fk_p'] = fk
00164         kdl_leftarm['ik_v'] = ik_v
00165         kdl_leftarm['ik_p'] = ik_p
00166         kdl_leftarm['jacobian_solver'] = jac
00167 
00168         
00169         self.cody_kdl = {'right_arm':kdl_rightarm,'left_arm':kdl_leftarm}
00170 
00171     def FK_kdl(self, arm, q, link_number):
00172         fk_solver = self.cody_kdl[arm]['fk_p']
00173         endeffec_frame = kdl.Frame()
00174         kinematics_status = fk_solver.JntToCart(q, endeffec_frame,
00175                                                 link_number)
00176         if kinematics_status >= 0:
00177 
00178             return endeffec_frame
00179         else:
00180             print 'Could not compute forward kinematics.'
00181             return None
00182 
00183     def Jac_kdl(self,arm,q):
00184         ''' returns the Jacobian, given the joint angles
00185         '''
00186         J_kdl = kdl.Jacobian(7)
00187         self.cody_kdl[arm]['jacobian_solver'].JntToJac(q,J_kdl)
00188 
00189         kdl_jac =  np.matrix([
00190             [J_kdl[0,0],J_kdl[0,1],J_kdl[0,2],J_kdl[0,3],J_kdl[0,4],J_kdl[0,5],J_kdl[0,6]],
00191             [J_kdl[1,0],J_kdl[1,1],J_kdl[1,2],J_kdl[1,3],J_kdl[1,4],J_kdl[1,5],J_kdl[1,6]],
00192             [J_kdl[2,0],J_kdl[2,1],J_kdl[2,2],J_kdl[2,3],J_kdl[2,4],J_kdl[2,5],J_kdl[2,6]],
00193             [J_kdl[3,0],J_kdl[3,1],J_kdl[3,2],J_kdl[3,3],J_kdl[3,4],J_kdl[3,5],J_kdl[3,6]],
00194             [J_kdl[4,0],J_kdl[4,1],J_kdl[4,2],J_kdl[4,3],J_kdl[4,4],J_kdl[4,5],J_kdl[4,6]],
00195             [J_kdl[5,0],J_kdl[5,1],J_kdl[5,2],J_kdl[5,3],J_kdl[5,4],J_kdl[5,5],J_kdl[5,6]],
00196             ])
00197         return kdl_jac
00198         
00199     def IK_kdl(self,arm,frame, q_init):
00200         ''' IK, returns jointArray (None if impossible)
00201             frame - desired frame of the end effector
00202             q_init - initial guess for the joint angles. (JntArray)
00203         '''
00204         nJnts = self.cody_kdl[arm]['nJnts']
00205         ik_solver = self.cody_kdl[arm]['ik_p']
00206         q = kdl.JntArray(nJnts)
00207         if ik_solver.CartToJnt(q_init,frame,q)>=0:
00208             for i in range(nJnts):
00209                 q[i] = tr.angle_within_mod180(q[i])
00210             return q
00211         else:
00212             if arm == 'right_arm':
00213                 ik_solver = self.cody_kdl[arm]['ik_p_nolim']
00214                 if ik_solver.CartToJnt(q_init,frame,q)>=0:
00215                     for i in range(nJnts):
00216                         q[i] = tr.angle_within_mod180(q[i])
00217                     return q
00218             print 'Error: could not calculate inverse kinematics'
00219             return None
00220 
00221     def FK_rot(self, arm, q, link_number = 7):
00222         pos, rot = self.FK_all(arm, q, link_number)
00223         return rot
00224 
00225     
00226     
00227     
00228     
00229     def FK(self, arm, q, link_number = 7):
00230         pos, rot = self.FK_all(arm, q, link_number)
00231         return pos
00232 
00233     def FK_all(self, arm, q, link_number = 7):
00234         q = self.meka_angles_to_kdl(arm, q)
00235         frame = self.FK_kdl(arm, q, link_number)
00236         pos = frame.p
00237         pos = ku.kdl_vec_to_np(pos)
00238         m = frame.M
00239         rot = ku.kdl_rot_to_np(m)
00240         return pos, rot
00241 
00242     def Jac(self,arm,q):
00243         ''' q - list of 7 joint angles (meka axes) in RADIANS.
00244             arm - 'right_arm' or 'left_arm'
00245             returns 6x7 numpy matrix.
00246         '''
00247         jntarr = self.meka_angles_to_kdl(arm,q)
00248         kdl_jac = self.Jac_kdl(arm,jntarr)
00249         meka_jac = -kdl_jac  
00250         return meka_jac
00251 
00252     
00253     
00254     def Jacobian(self, arm, q, pos):
00255         chain = self.cody_kdl[arm]['chain']
00256         v_list = []
00257         w_list = []
00258         for i in range(self.n_joints):
00259             p, rot = self.FK_all(arm, q, i)
00260             r = pos - p
00261             z_idx = chain.getSegment(i).getJoint().getType() - 1
00262             z = rot[:, z_idx]
00263             v_list.append(np.matrix(np.cross(z.A1, r.A1)).T)
00264             w_list.append(z)
00265 
00266         J = np.row_stack((np.column_stack(v_list), np.column_stack(w_list)))
00267         
00268         J = self.Jac(arm, q)
00269         return J
00270 
00271     
00272     
00273     
00274     
00275     
00276     
00277     
00278     def IK(self,arm,p,rot,q_guess=None):
00279         p_kdl = ku.np_vec_to_kdl(p)
00280         rot_kdl = ku.np_rot_to_kdl(rot)
00281         fr = kdl.Frame(rot_kdl,p_kdl)
00282 
00283         if q_guess == None:
00284             if arm == 'left_arm':
00285                 q_guess = cgd.find_good_config(p,self.q_guess_dict_left)
00286             elif arm == 'right_arm':    
00287                 q_guess = cgd.find_good_config(p,self.q_guess_dict_right)
00288 
00289         q_guess = self.meka_angles_to_kdl(arm,q_guess)
00290 
00291         q_res = self.IK_kdl(arm,fr,q_guess)
00292         q_res = self.kdl_angles_to_meka(arm,q_res)
00293 
00294         if self.within_joint_limits(arm,q_res):
00295             if arm == 'right_arm':  
00296                 if q_res[1]<0.:
00297                     q_res[1] = math.radians(10.)
00298                     qg = self.meka_angles_to_kdl(arm,q_res)
00299                     q_res = self.IK_kdl(arm,fr,qg)
00300                     q_res = self.kdl_angles_to_meka(arm,q_res)
00301                 if self.within_joint_limits(arm,q_res):
00302                     return q_res
00303                 else:
00304                     return None
00305             else:
00306                 return q_res
00307         else:
00308             return None
00309 
00310     
00311     
00312     
00313     
00314     def clamp_to_joint_limits(self, arm, q, delta_list=[0.,0.,0.,0.,0.,0.,0.]):
00315         d = self.joint_lim_dict[arm]
00316         max_arr = d['max']
00317         min_arr = d['min']
00318         q_arr = np.array(q)
00319         d_arr = np.array(delta_list)
00320         return np.clip(q_arr, min_arr-d_arr, max_arr+d_arr)
00321 
00322     def within_joint_limits(self, arm, q, delta_list=[0.,0.,0.,0.,0.,0.,0.]):
00323         d = self.joint_lim_dict[arm]
00324         max_arr = d['max']
00325         min_arr = d['min']
00326         q_arr = np.array(q)
00327         d_arr = np.array(delta_list)
00328         return np.all((q_arr <= max_arr+d_arr, q_arr >= min_arr-d_arr))
00329 
00330 
00331 
00332 
00333 if __name__ == '__main__':
00334     import roslib; roslib.load_manifest('hrl_cody_arms')
00335     import hrl_cody_arms.cody_arm_kinematics as cak
00336 
00337     h = M3HrlRobot(0.16)
00338     k = cak.CodyArmKinematics('r')
00339     p = np.matrix([0., 0., -0.16]).T
00340     k.set_tooltip(p)
00341 
00342     J_old = h.Jacobian
00343 
00344 
00345 
00346 
00347 
00348