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