18 Changes from version 4.0:
19 1- Fixed Mode respected by functions:
20 set_target(), larm_endeffector_position(), rarm_endeffector_position()
22 2- Function name changes:
23 larm_endeffector_position(): larm_end_position()
24 rarm_endeffector_position(): rarm_end_position()
25 larm_endeffector_orientation(): larm_end_orientation()
26 rarm_endeffector_orientation(): rarm_end_orientation()
30 import copy, math, sys, numpy
as np
31 import general_python
as pygen
32 import pr2_arm_kinematics
34 from interval
import interval, inf, imath
35 from math_tools
import general_math
as gen
36 from math_tools.geometry import rotation
as rotlib, trigonometry
as trig, trajectory
as trajlib
43 default_ql = drc*np.array([-130.0, 69.0 , -180.0, - 131.0, -180.0, -130.0, -180.0, 0.8/drc, -1000.0, -1000.0, -180.0, -40.0, 60.0, - 44.0, -131.0, -180.0, -130.0, -180.0])
44 default_qh = drc*np.array([ 30.0, 170.0, 44.0, - 8.5, 180.0, 0.00, 180.0, 1.14/drc, 1000.0, 1000.0, 180.0, 130.0, 170.0, 180.0, - 8.5, 180.0, 0.00, 180.0])
45 all_control_modes = [
'Fixed-Base',
'Free-Base']
66 def __init__(self, a0 = 0.1, b0 = 0.05, d2 = 0.4, d4 = 0.321, d7 = 0.168, l0 = 0.188, ql = default_ql, qh = default_qh, run_magiks = False):
68 assert (len(ql) == 18)
and (len(qh) == 18),
"Error from " + __name__ +
" Constructor" +
": ql and qh must be numpy vectors of size 18"
106 self.
W = np.zeros(11)
107 for i
in [0, 1, 2, 3, 5, 7]:
108 self.
W[i] = 1.0/((qh[i] - ql[i])**2)
150 return self.rarm.config.joint_in_range(i, qi)
151 elif i
in range(11, 18):
152 return self.larm.config.joint_in_range(i - 11, qi)
155 qi = trig.angle_standard_range(qi)
157 if abs(qi - self.
ql[i]) < gen.epsilon:
159 if abs(qi - self.
qh[i]) < gen.epsilon:
162 return ((qi <= self.
qh[i])
and (qi >= self.
ql[i]))
172 flag = self.rarm.config.all_joints_in_range(qd[0:7])
173 flag = flag
and self.larm.config.all_joints_in_range(qd[11:18])
175 for i
in range(7, 11):
185 def full_config(self, q_partial, q_full = None , is_left_arm = False):
188 permit = type(q_full)
in [np.ndarray, tuple, list]
189 permit = permit
and (len(q_full) == 18)
190 assert permit, pygen.err_str(__name__, self.__class__.__name__,sys._getframe().f_code.co_name,
'q_full must be a tuple, numpy vector or array of size 18')
192 if q_partial ==
None:
195 permit = type(q_partial)
in [np.ndarray, tuple, list]
197 permit = permit
and (nqp
in [7,11])
198 assert permit, pygen.err_str(__name__, self.__class__.__name__,sys._getframe().f_code.co_name,
'q_partial must be a tuple, numpy vector or array of size 7 or 11')
200 qf = copy.copy(q_full)
203 qf[11:18] = q_partial
208 qf[7:11] = q_partial[7:11]
209 qf[11:18] = q_partial[0:7]
217 if (new_ofuncode > 2)
or (new_ofuncode < 0):
218 print "set_ofuncode_error: The given objective function code is not supported"
241 if not len(qd) == 18:
242 print "set_config error: Number of input elements must be 18 in dual arm mode"
245 if self.
all_joints_in_range(qd)
and self.rarm.set_config(qd[0:7])
and self.larm.set_config(qd[11:18]):
246 self.
q[0:7] = trig.angles_standard_range(qd[0:7])
247 self.
q[7:10] = qd[7:10]
248 self.
q[10:18] = trig.angles_standard_range(qd[10:18])
250 self.
C = math.cos(self.
q[10])
251 self.
S = math.sin(self.
q[10])
253 self.
p_BO = np.array([qd[8] , qd[9],0.0])
257 self.
R_B = np.array([[ self.
C, - self.
S, 0.0 ],
258 [ self.
S, self.
C, 0.0 ],
276 print "Error from PR2().set_config(): Given joints are not in their feasible range"
278 if qd[i] > self.
qh[i]:
279 print "Joint No. ", i ,
" is ", qd[i],
" greater than maximum: ", self.
qh[i]
280 if qd[i] < self.
ql[i]:
281 print "Joint No. ", i ,
" is ", qd[i],
" lower than minimum: ", self.
ql[i]
293 sets the endeffector target to the given position and orientation
294 variables self.xd and self.Rd should not be manipulated by the user. Always use this function
296 self.
xd = np.copy(target_position)
297 self.
Rd = np.copy(target_orientation)
299 arm = self.reference_arm()
309 print "in ST: p_BR_BO = ", self.p_BR_BO
311 print "rel_ef_pos[2] = ", -self.p_BR_BO[2] + target_position[2] - target_orientation[2,2]*self.d7
313 relative_endeffector_position = - self.p_BR_BO + np.dot(self.R_B.T,target_position - self.p_BO - np.dot(target_orientation,self.p_EFR_WR))
314 print "rel_ef_pos[2] = ", relative_endeffector_position[2]
316 assert self.
control_mode in all_control_modes, pygen.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name, self.
control_mode +
" is an invalid value for control mode")
318 rel_end_position = - p0 + target_position - np.dot(target_orientation, pe)
319 rel_end_orientation = target_orientation
321 rel_end_position = - p0 + np.dot(self.R_B.T,target_position - self.
p_BO - np.dot(target_orientation, pe))
322 rel_end_orientation = np.dot(self.R_B.T, target_orientation)
325 arm.set_target(rel_end_position, rel_end_orientation)
328 if posture ==
'praying':
329 qr = np.array([ -6.85916588e-06, 1.59104071e+00, 1.04472774e-03, -2.49505670e-01, -3.26593628e-03, -3.35053472e-01, -1.65636744e-03])
330 ql = np.array([ -3.57102700e-04, 1.59100714e+00, -5.27852219e-04, -2.48833571e-01, 3.85286996e-03, -3.36172240e-01, 1.43031683e-03])
335 elif posture ==
'writing':
336 qd = np.array([ -1.26299826e-01, 1.77046412e+00, -1.02862191e+00, -1.36864905e+00, -2.31195189e+00, -1.29253137e+00,
337 1.71195615e-01, 8.02176174e-01, -2.12167293e-03, 2.32811863e-04, 7.05358701e-03, 4.01010384e-01,
338 2.44565260e+00, 7.10476515e-01, -1.30808585e+00, 1.15357810e+00, -4.49485156e-01, -2.46943329e+00])
340 elif posture ==
'catch_the_board_with_right_hand':
341 qr = np.array([ 0.08842831, 2.34773988, 0.07718497, -1.32087472, -0.71994221, -1.02121596, -1.56155048])
346 assert False,
"Error from PR2.set_posture(): Unknown Posture"
383 print "Error from "+__name__+func_name+
": The first given redundant parameter (phi[0]) is out of feasible range"
387 print "Error from "+__name__+func_name+
": The fifth given redundant parameter (phi[4], tau or trunc rotation angle) is out of feasible range"
393 save_arm_target_position = copy.copy(arm.xd)
394 save_arm_target_orientation = copy.copy(arm.Rd)
407 p_W_B = np.array([px, py, pz])
411 R_B = rotlib.rot_z(tau)
414 R_W_B = np.dot(R_B.T, R_W)
418 arm.set_target(p_W_B, R_W_B)
422 arm_solution_set = arm.all_IK_solutions(phi[0])
424 if len(arm_solution_set) == 0:
425 print "IK Error: No solution for the arm for given phi"
430 h_ts = - pz + self.
xd[2] - self.
Rd[2,2]*self.
d7
434 p_B_BO = np.array([self.
b0 , l0, h_ts])
436 p_BO = p_EF - np.dot(R_B,(p_B_BO + p_W_B)) - np.dot(R_W, p_EF_W)
438 assert gen.equal(p_BO[2], 0.0)
442 for arm_solution
in arm_solution_set:
443 solution = np.zeros(11)
444 solution[0:7] = arm_solution
446 solution[8] = p_BO[0]
447 solution[9] = p_BO[1]
449 solution_set.append(solution)
453 arm.set_target(save_arm_target_position, save_arm_target_orientation)
471 qc = np.append(self.
q[11:18] , self.
q[7:11])
472 qm = np.append(self.
qm[11:18], self.
qm[7:11])
475 delta = trig.angles_standard_range(q - qc)
476 ofun = np.dot(delta.T, self.
W*delta)
478 delta = trig.angles_standard_range(q - qm)
479 ofun = np.dot(delta.T, self.
W*delta)
481 assert False,
"Error from "+__name__ + func_name +
": Value "+str(self.
ofuncode)+
" for argument ofuncode is not supported"
496 assert type(phi)
is float, pygen.err_str(__name__, self.__class__.__name__,sys._getframe().f_code.co_name,
'given redundant parameter must be a float in Fixed-Base mode')
497 arm = self.reference_arm()
498 q_arm = arm.IK_config(phi = phi)
501 permit = type(phi)
in [np.ndarray, float, list]
503 permit = permit
and len(phi) == 5
504 assert permit, pygen.err_str(__name__, self.__class__.__name__,sys._getframe().f_code.co_name,
'given redundant parameter must be an array of size 5 in Free-Base mode')
506 if len(solution_set) == 0:
507 print "IK_config error: No solution found within the feasible joint ranges for the given redundant parameters"
510 ofun_min = float(
"inf")
511 for i
in range(0, len(solution_set)):
512 solution = solution_set[i]
525 R_WR_B = self.rarm.wrist_orientation()
526 p_WR_BR = self.rarm.wrist_position()
527 p_EFR_BR = p_WR_BR + np.dot(R_WR_B, self.
p_EFR_WR)
535 R_WL_B = self.larm.wrist_orientation()
536 p_WL_BL = self.larm.wrist_position()
537 p_EFL_BL = p_WL_BL + np.dot(R_WL_B, self.
p_EFL_WL)
548 p_EFL_BO = self.
p_BL_BO + p_EFL_BL
559 p_EFR_BO = self.
p_BR_BO + p_EFR_BR
567 return(self.
p_BO + p_EFR_BO)
574 return(self.
p_BO + p_EFL_BO)
581 assert self.
control_mode in all_control_modes, pygen.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name, self.
control_mode +
" is an invalid value for control mode")
582 relative = pygen.check_type(relative, [bool], __name__, self.__class__.__name__, sys._getframe().f_code.co_name,
'relative', default = self.
control_mode ==
'Fixed-Base')
587 if self.
p_EFR ==
None:
591 return copy.copy(self.
p_EFR)
598 pygen.check_valid(self.
control_mode, all_control_modes, __name__, self.__class__.__name__, sys._getframe().f_code.co_name,
'control_mode')
599 relative = pygen.check_type(relative, [bool], __name__, self.__class__.__name__, sys._getframe().f_code.co_name,
'relative', default = self.
control_mode ==
'Fixed-Base')
604 if self.
p_EFL ==
None:
608 return copy.copy(self.
p_EFL)
621 pygen.check_valid(self.
control_mode, all_control_modes, __name__, self.__class__.__name__, sys._getframe().f_code.co_name,
'control_mode')
622 relative = pygen.check_type(relative, [bool], __name__, self.__class__.__name__, sys._getframe().f_code.co_name,
'relative', default = self.
control_mode ==
'Fixed-Base')
624 Returns the cartesian coordiantes of the right arm gripper as the endeffector frame.
628 return self.rarm.wrist_orientation()
630 if self.
R_WR ==
None:
631 self.
R_WR_B = self.rarm.wrist_orientation()
633 return copy.copy(self.
R_WR)
636 pygen.check_valid(self.
control_mode, all_control_modes, __name__, self.__class__.__name__, sys._getframe().f_code.co_name,
'control_mode')
637 relative = pygen.check_type(relative, [bool], __name__, self.__class__.__name__, sys._getframe().f_code.co_name,
'relative', default = self.
control_mode ==
'Fixed-Base')
639 Returns the cartesian coordiantes of the left arm gripper as the endeffector frame.
642 return self.larm.wrist_orientation()
644 if self.
R_WL ==
None:
645 self.
R_WL_B = self.larm.wrist_orientation()
647 return copy.copy(self.
R_WL)
657 Returns the divergence of the vector of kinematic constraints "e" in respect with the joints
659 e_ij = rond e_i / rond q_j (for i,j = 0,..,8)
670 self.
E = np.zeros((9,9))
671 self.
F = np.zeros((9,5))
675 [s0, s1, s2, s3, s4, s5, s6] = arm.config.s
676 [c0, c1, c2, c3, c4, c5, c6] = arm.config.c
682 [s10] = arm.config.s1_mult1
683 [s20,s21, s22, s210] = arm.config.s2_mult1
684 [s30, s31, s32, s310, s320, s321, s322, s33,s3210] = arm.config.s3_mult1
685 [c0s0,c0s1,c0s2,c0s10,c0s20,c0s21,c0s30,c0s31,c0s32,c0s321] = arm.config.c0_mult
686 [c10, c1s0, c1s1, c1s2, c1s3, c1s10, c1s20,c1s30,c1s32,c1s320] = arm.config.c1_mult
687 [c20,c21,c22,c210,c2s0,c2s1,c2s2,c2s3,c2s10,c2s20,c2s30,c2s31,c2s310,c21s30,c20s31] = arm.config.c2_mult
688 [c30,c31,c32,c33,c3s0,c3s1,c3s2,c3s3,c3s10,c3s20,c3s21,c3s30,c310,c320,c321,c3210,c32s0,c32s10] = arm.config.c3_mult
689 [c21s0,c31s0,c321s0] = arm.config.s0_mult
690 [c10s1,c20s1,c30s1, c32s1,c320s1] = arm.config.s1_mult2
691 [c10s2,c20s2,c30s2, c32s2,c310s2] = arm.config.s2_mult2
692 [c10s3, c20s3, c30s3, c21s3, c210s3,s332] = arm.config.s3_mult2
693 [c10s32, c31s20, s54] = arm.config.cs_mult
694 [c54, c5s4, c5s5] = arm.config.c5_mult
695 [s64, s65, c4s6, c5s6, c54s6, s654] = arm.config.s6_mult
696 [c64, c65, c6s4, c6s5, c654, C6s54] = arm.config.c6_mult
703 [Q, Q2, d42, d44, a00, d22_plus_d44, foura00d44, alpha] = arm.additional_dims
706 rho2 = r2 + phi[2]**2
716 ax_c5_m_ay_s5 = a[0]*C5 - a[1]*S5
717 ax_s5_p_ay_c5 = a[0]*S5 + a[1]*C5
719 nx_c5_m_ny_s5 = n[0]*C5 - n[1]*S5
720 nx_s5_p_ny_c5 = n[0]*S5 + n[1]*C5
722 C14 = math.cos(phi[0] + phi[3])
723 S14 = math.sin(phi[0] + phi[3])
724 C45 = math.cos(phi[4] + phi[3])
725 S45 = math.sin(phi[4] + phi[3])
727 self.
E[0,2] = - 2*d42*s3
728 self.
E[2,1] = arm.d4*s321
738 self.
E[1,1] = 2*a00*d44*s33*c2s2
739 self.
E[1,2] = 2*a0*d42*s3*phi[1]*S14 + (a0**2)*(d4**2)*(s2**2)*(2*c3*s3)
745 self.
E[2,0] = - arm.d2*s1 - arm.d4*(c3s1 + c21s3)
746 self.
E[2,2] = - arm.d4*(c1s3 + c32s1)
747 self.
E[3,0] = ax_c5_m_ay_s5*(c20s31 - c310) + ax_s5_p_ay_c5*(c2s310 - c31s0) + a[2]*(c3s1 + c21s3)
748 self.
E[3,1] = ax_c5_m_ay_s5*(c2s30 + c10s32) - ax_s5_p_ay_c5*(c20s3 - c1s320) - a[2]*s321
749 self.
E[3,2] = ax_c5_m_ay_s5*(c3s20 - c3210 + c0s31) - ax_s5_p_ay_c5*(c30s2 + c321s0 - s310) + a[2]*(c1s3 + c32s1)
750 self.
E[4,0] = - ax_c5_m_ay_s5*c0s21 - ax_s5_p_ay_c5*s210 - a[2]*c1s2
751 self.
E[4,1] = ax_c5_m_ay_s5*(c210 -s20) + ax_s5_p_ay_c5*(c0s2 + c21s0) - a[2]*c2s1
753 self.
E[5,0] = nx_c5_m_ny_s5*(- c20s31 + c310) + nx_s5_p_ny_c5*(- c2s310 + c31s0) - n[2]*(c3s1 + c21s3)
754 self.
E[5,1] = - nx_c5_m_ny_s5*(c2s30 + c10s32) + nx_s5_p_ny_c5*(c20s3 - c1s320) + n[2]*s321
755 self.
E[5,2] = nx_c5_m_ny_s5*(- c3s20 + c3210 - c0s31) + nx_s5_p_ny_c5*(c30s2 + c321s0 - s310) - n[2]*(c1s3 + c32s1)
759 self.
F[0,2] = -2*phi[2]
764 self.
F[0,0] = 2*arm.a0*phi[1]*C14
765 self.
F[0,1] = 2*arm.a0*S14 - 2*phi[1]
766 self.
F[0,3] = 2*arm.a0*phi[1]*C14
768 self.
F[1,1] = 2*phi[1]*arm.a0*(phi[1]*S14 - arm.a0)
769 self.
F[1,2] = 2*phi[1]*arm.a0*S14*phi[2]
771 self.
F[3,0] = ax_c5_m_ay_s5 *(c0s32 + c21s30 + c3s10) + ax_s5_p_ay_c5*(s320 - c210s3 - c30s1)
772 self.
F[3,4] = - ax_s5_p_ay_c5*(s320 - c210*s3 - c30*s1) - ax_c5_m_ay_s5*(c0*s32 + c21*s30 + c3s10)
773 self.
F[4,0] = ax_c5_m_ay_s5*(c20 - c1s20) + ax_s5_p_ay_c5*(c2s0 + c10s2)
774 self.
F[4,4] = - ax_c5_m_ay_s5*(c20 - c1s20) - ax_s5_p_ay_c5*(c2s0 + c10s2)
775 self.
F[5,0] = - nx_c5_m_ny_s5*(c0s32 + c21s30 + c3s10) + nx_s5_p_ny_c5*(-s320 + c210s3 + c30s1)
776 self.
F[5,4] = + nx_c5_m_ny_s5*(c0s32 + c21s30 + c3s10) - nx_s5_p_ny_c5*(-s320 + c210s3 + c30s1)
777 self.
F[7,4] = phi[1]*C45 + C5*l0
778 self.
F[8,4] = - phi[1]*S45 - S5*l0
779 self.
F[7,3] = phi[1]*C45
780 self.
F[8,3] = - phi[1]*S45
784 return copy.copy(self.
E)
789 @return A numpy vector of 5 elements containing the redundant parameters phi according to the parametrization specified in <provide link>
791 phi[0] = The first arm joint angle (Shoulder Pan joint)
792 phi[1] = The "r" coordinate of the relative wrist position(in cylinderical coordinates) phi[1]^2 = px^2 + py^2
793 phi[2] = The "z" coordinate of the relative wrist position(
in cylinderical coordinates) phi[2] = pz
794 phi[3] = The
"psi" coordinate of the relative wrist position(
in cylinderical coordinates) phi[3] = arctan(x/y)
795 phi[4] = The rotation of the base. Same
as "tau" or the 10th joint angle (phi[4] = q[10] = tau)
797 if self.larm_reference:
802 if not self.redundant_parameters_updated:
803 p = arm.wrist_position()
804 r2 = p[0]**2 + p[1]**2
805 self.phi = np.zeros(5)
806 self.phi[0] = arm.config.q[0]
807 self.phi[1] = math.sqrt(r2)
809 self.phi[3] = math.atan2(p[0],p[1])
810 self.phi[4] = self.q[10]
811 self.redundant_parameters_updated = True
812 return copy.copy(self.phi)
814 def div_phi_err(self):
816 Returns the divergence of the vector of kinematic constraints
"e" in respect with the redundant parameters
"phi"
818 f_ij = rond e_i / rond phi_j (
for i = 0,..,8 & j = 0,..,4)
819 the value of
"self.F" is computed
in function
"div_theta_e" to avoid repeated calculations
821 if not self.div_theta_err_updated:
823 return copy.copy(self.F)
825 def redundancy_jacobian(self):
827 Returns the redundancy jacobian
828 Redundancy Jacobian
is the partial derivative of the joints
in respect with redundant parameters
829 RJ
is a 9*5 matrix because the first
and the last joints (q[0]
and q[10]) are themselves selected
as the redundant parameters
831 if self.larm_reference:
836 if not self.redun_jacob_updated:
840 [s0, s1, s2, s3, s4, s5, s6] = arm.config.s
841 [c0, c1, c2, c3, c4, c5, c6] = arm.config.c
848 p = self.end_position()
850 r2 = p[0]**2 + p[1]**2
855 C4 = math.cos(self.q[10])
856 S4 = math.sin(self.q[10])
860 E = self.div_theta_err()
861 F = self.div_phi_err()
864 RJ[2,0] = F[0,0]/(2*d42*s3)
865 RJ[2,1] = F[0,1]/(2*d42*s3)
866 RJ[2,2] = -p2/(d42*s3)
867 RJ[2,3] = F[0,3]/(2*d42*s3)
875 RJ[ 7 , 1 ] = -F[7,1]
876 RJ[ 7 , 3 ] = -F[7,3]
877 RJ[ 7 , 4 ] = -F[7,4]
879 RJ[7,0] = -RJ[8,0]*E[7,8]/E[7,7]
880 RJ[7,1] = (2*p1 - RJ[8,1]*E[7,8])/E[7,7]
881 RJ[7,2] = -RJ[8,2]*E[7,8]/E[7,7]
882 RJ[7,3] = -RJ[8,3]*E[7,8]/E[7,7]
883 RJ[7,4] = -(F[7,4] + RJ[8,4]*E[7,8])/E[7,7]
885 RJ[1,0] = -RJ[2,0]*E[1,2]/E[1,1]
886 RJ[1,1] = -(F[1,1] + RJ[2,1]*E[1,2])/E[1,1]
887 RJ[1,2] = -(F[1,2] + RJ[2,2]*E[1,2])/E[1,1]
888 RJ[1,3] = -RJ[2,3]*E[1,2]/E[1,1]
889 RJ[1,4] = -RJ[2,4]*E[1,2]/E[1,1]
891 RJ[0,0] = -(RJ[6,0] + RJ[2,0]*E[2,2] + RJ[1,0]*arm.d4*s321)/E[2,0]
892 RJ[0,1] = -(RJ[6,1] + RJ[2,1]*E[2,2] + RJ[1,1]*arm.d4*s321)/E[2,0]
893 RJ[0,2] = -(RJ[6,2] + RJ[2,2]*E[2,2] + RJ[1,2]*arm.d4*s321)/E[2,0]
894 RJ[0,3] = -(RJ[6,3] + RJ[2,3]*E[2,2] + RJ[1,3]*arm.d4*s321)/E[2,0]
895 RJ[0,4] = -(RJ[6,4] + RJ[2,4]*E[2,2] + RJ[1,4]*arm.d4*s321)/E[2,0]
897 RJ[4,0] = (F[3,0] + RJ[0,0]*E[3,0] + RJ[1,0]*E[3,1] + RJ[2,0]*E[3,2])/s5
898 RJ[4,1] = (RJ[0,1]*E[3,0] + RJ[1,1]*E[3,1] + RJ[2,1]*E[3,2])/s5
899 RJ[4,2] = (RJ[0,2]*E[3,0] + RJ[1,2]*E[3,1] + RJ[2,2]*E[3,2])/s5
900 RJ[4,3] = (RJ[0,3]*E[3,0] + RJ[1,3]*E[3,1] + RJ[2,3]*E[3,2])/s5
901 RJ[4,4] = (- F[3,0] + RJ[0,4]*E[3,0] + RJ[1,4]*E[3,1] + RJ[2,4]*E[3,2])/s5
903 RJ[3,0] = -(F[4,0] + RJ[0,0]*E[4,0] + RJ[1,0]*E[4,1] + RJ[4,0]*c5*s4)/(c4*s5)
904 RJ[3,1] = -(RJ[0,1]*E[4,0] + RJ[1,1]*E[4,1] + RJ[4,1]*c5*s4)/(c4*s5)
905 RJ[3,2] = -(RJ[0,2]*E[4,0] + RJ[1,2]*E[4,1] + RJ[4,2]*c5*s4)/(c4*s5)
906 RJ[3,3] = -(RJ[0,3]*E[4,0] + RJ[1,3]*E[4,1] + RJ[4,3]*c5*s4)/(c4*s5)
907 RJ[3,4] = -(F[4,4] + RJ[0,4]*E[4,0] + RJ[1,4]*E[4,1] + RJ[4,4]*c5*s4)/(c4*s5)
909 RJ[5,0] = (F[5,0] + RJ[0,0]*E[5,0] + RJ[1,0]*E[5,1] + RJ[2,0]*E[5,2] + RJ[4,0]*c65)/s65
910 RJ[5,1] = (RJ[0,1]*E[5,0] + RJ[1,1]*E[5,1] + RJ[2,1]*E[5,2] + RJ[4,1]*c65)/s65
911 RJ[5,2] = (RJ[0,2]*E[5,0] + RJ[1,2]*E[5,1] + RJ[2,2]*E[5,2] + RJ[4,2]*c65)/s65
912 RJ[5,3] = (RJ[0,3]*E[5,0] + RJ[1,3]*E[5,1] + RJ[2,3]*E[5,2] + RJ[4,3]*c65)/s65
913 RJ[5,4] = (- F[5,0] + RJ[0,4]*E[5,0] + RJ[1,4]*E[5,1] + RJ[2,4]*E[5,2] + RJ[4,4]*c65)/s65
916 self.redun_jacob_updated = True
917 return copy.copy(self.RJ)
919 def redundancy_jacobian_extended(self):
921 returns the extended redundancy jacobian which
is "11 x 5" matrix.
922 It
is the redundancy jacobian with two rows inserted At its first
and last rows.
923 These rows are corresponding to the first
and last joints (shoulder pan joint
and base rotation angle).
925 if not self.redun_jacob_ext_updated:
926 self.ERJ = np.zeros((11,5))
927 RJ = self.redundancy_jacobian()
929 self.ERJ[i+1,:] = RJ[i,:]
932 self.redun_jacob_ext_updated = True
933 return copy.copy(self.ERJ)
935 def div_theta_ofun(self):
937 Returns the divergence of the objective function
in respect with the joint angles
938 argument
"ofun" specifies the code of the objective function which
is set to 0 by default
940 if not self.div_theta_ofun_updated:
941 self.DTG = np.zeros(11)
943 self.DTG[i] = 2*self.W[i]*(self.q[i] - self.qm[i])
944 self.div_theta_ofun_updated = True
945 return copy.copy(self.DTG)
947 def div_phi_ofun(self):
949 Returns the divergence of the objective function
in respect with the redundant parameters
"phi"
950 argument
"ofun" specifies the code of the objective function which
is set to 0 by default.
951 The code legend
is like function
"div_theta_ofun"
953 if not self.div_phi_ofun_updated:
954 J = self.redundancy_jacobian_extended()
955 self.DFG = np.dot(J.T, self.div_theta_ofun())
956 self.div_phi_ofun_updated = True
957 return copy.copy(self.DFG)
959 def joint_stepsize_interval(self, direction):
961 Returns an interval
for the step size by which the joints are allowed to move
in the given
"direction"
962 "direction" is a
"n X 1" vector
and specifies the direction of motion
in the jointspace.
965 stepsize_interval = interval([-inf, inf])
966 for i in range(11): # for each joint
967 if self.W[i] != 0: # if the joint is limited
968 joint_correction_interval = interval([self.ql[i], self.qh[i]]) - interval(self.q[i]) # find the interval for joint correction
970 joint_correction_interval = interval([-inf, inf])
972 stepsize_interval = stepsize_interval & joint_correction_interval/direction[i]
975 print "direction : = ", direction[i]
976 print "stepsize_interval: = ", stepsize_interval
980 return stepsize_interval
982 def optimum_joint_stepsize(self, direction, safety_factor = 0.99):
984 returns the optimum feasible step size that minimizes the objective function
985 if the joints are constrained to move
in the given
"direction".
986 The
"safety_factor" specifies how much we can approach to the borders of joint limits
988 if not self.larm_reference:
992 qc = np.append(self.q[11:18] , self.q[7:11])
993 qm = np.append(self.qm[11:18], self.qm[7:11])
995 den = np.dot(direction.T, self.W * direction)
996 num = np.dot(direction.T, self.W * (qc - qm))
998 if not gen.equal(num, 0.0):
1001 print "Error from PR2.optim_joint_stepsize(): Moving in the given direction does not influence the objective function"
1004 interval_eta = self.joint_stepsize_interval(direction)
1006 (eta_l, eta_h) = interval_eta[0]
1009 return safety_factor*eta_l
1013 return safety_factor*eta_h
1015 def steepest_descent_redundancy_correction(self):
1017 Finds the steepest descent direction of the objective function
for redundancy vector
"phi"
1019 steepest_descent_redundancy_direction = - self.div_phi_ofun()
1020 steepest_descent_joint_direction = np.dot(self.redundancy_jacobian_extended(), steepest_descent_redundancy_direction)
1022 eta = self.optimum_joint_stepsize(steepest_descent_joint_direction)
1025 return eta*steepest_descent_redundancy_direction
1027 def endeffector_in_target(self):
1029 Returns true
is endeffector
is in target
1031 self.in_target = vecmat.equal(self.xd, self.end_position()) and vecmat.equal(self.Rd, self.end_orientation())
1032 return self.in_target
1034 def optimize_config(self, silent = True):
1036 Assuming the endeffector
is in target,
1037 this function changes the robot configuration without changing the endeffector pose
1038 until the minimum possible value of objective function
is achieved
1040 This function
is a procedure
and does
not return any thing. Running this function, changes the robot configuration.
1041 If the current tip pose
is not in target, this function fails with an error
1043 if (self.xd == None) or (self.Rd == None):
1044 self.set_target(self.end_position(), self.end_orientation())
1046 assert self.endeffector_in_target(), "optimize_config Error: Endeffector is not in target pose"
1048 ofun_old = self.objective_function()
1052 phi = self.redundant_parameters()
1053 # Find the steepest descent correction for redundancy:
1054 delta_phi = self.steepest_descent_redundancy_correction()
1055 # Correct the redundancy
1056 phi = phi + k*delta_phi
1057 # Run IK to find the joints with the corrected redundancy:
1058 solution = self.IK_config(phi)
1059 if solution == None:
1062 # Solution exists: Compute the value of the objective function for the new configuration
1063 ofun_new = self.objective_function_for(solution)
1064 pygen.show("Objective Function Value: ", ofun_new, silent)
1065 if ofun_new > ofun_old - gen.epsilon:
1068 # Objective Function Reduced: Try to set the solution config
1069 qd = np.copy(self.q)
1071 if not self.set_config(qd):
1074 # Solution is feasible :-)
1082 def extended_config(self, q):
1083 qq = np.copy(self.q)
1084 if not self.larm_reference:
1091 def goto_target(self):
1093 Finds the inverse kinematic solution closest to the current configuration
1094 The new joint angles will be set
if all the kinematic equations are satisfied.
1095 All kinematic parameters will be updated.
1096 THIS FUNCTION IS NOT COMPLETE AND i NEED TO WORK ON IT MORE ...
1098 arm = self.reference_arm()
1100 if self.control_mode == "Fixed-Base":
1101 if not arm.goto_target(optimize = True):
1102 print "Error from goto_target: No soluton for the arm in fixed mode"
1105 if not self.larm_reference:
1106 self.q[0:7] = arm.config.q
1108 self.q[11:18] = arm.config.q
1110 self.set_config(self.q)
1112 elif self.control_mode == "Free-Base":
1113 print "Error from PR2().goto_target: Free-Base mode is not supported yet."
1116 print "Error from PR2().goto_target: Unknown control mode"
1119 def project_to_js(self, pos_traj, ori_traj = None, phi_start = 0.0, phi_end = None, delta_phi = 0.1, relative = True):
1121 projects the given taskspace pose trajectory into the jointspace
1122 The phase starts
from phi_start
and added by delta_phi
in each step.
1123 at any time,
if a solution
is not found, the process stops
1126 phi_end = pos_traj.phi_end
1128 if phi_end > pos_traj.phi_end:
1129 phi_end = pos_traj.phi_end
1131 if ori_traj == None:
1132 ori_traj = trajlib.Orientation_Trajectory()
1133 ori_traj.current_orientation = self.end_orientation()
1135 jt = trajlib.Polynomial_Trajectory(dimension = 18)
1137 jt.add_point(phi = 0.0, pos = np.copy(self.q), vel = np.zeros(18))
1140 pos_traj.set_phi(phi)
1141 ori_traj.set_phi(phi)
1143 p0 = self.end_position() - pos_traj.current_position
1144 R0 = np.dot(self.end_orientation(), ori_traj.current_orientation.T)
1149 phi = phi + delta_phi
1152 while (phi <= phi_end) and stay:
1155 pos_traj.set_phi(phi)
1156 ori_traj.set_phi(phi)
1157 p = p0 + pos_traj.current_position
1158 R = np.dot(R0, ori_traj.current_orientation)
1159 self.set_target(p, R)
1160 if self.goto_target():
1161 jt.add_point(phi = phi - phi_start, pos = np.copy(self.q))
1162 phi = phi + delta_phi
1172 def project_to_ts(self, js_traj, phi_start = 0.0, phi_end = None, delta_phi = 0.1):
1174 projects the given jointspace trajectory into the taskspace
1175 The phase starts
from phi_start
and added by delta_phi
in each step.
1176 if at any time the joint values are
not feasible, the process
is stopped.
1179 phi_end = js_traj.phi_end
1181 ori_traj = trajlib.Orientation_Trajectory_Segment()
1182 ori_traj.capacity = 200
1183 pos_traj = trajlib.Polynomial_Trajectory()
1184 if phi_end > js_traj.phi_end:
1185 phi_end = js_traj.phi_end
1188 js_traj.set_phi(phi)
1190 while (phi < phi_end) and (self.set_config(js_traj.current_position)):
1191 pos_traj.add_point(phi - phi_start, self.end_position())
1192 # print self.end_position()
1193 ori_traj.add_point(phi - phi_start, self.end_orientation())
1194 phi = phi + delta_phi
1197 js_traj.set_phi(phi)
1199 pos_traj.add_point(phi - phi_start, self.end_position())
1200 ori_traj.add_point(phi - phi_start, self.end_orientation())
1201 return (pos_traj, ori_traj)
def full_config
Dumps the given partial joint values in the given full set of PR2 joints and returns the modified ful...
Rd
A rotation matrix specifying the desired endeffector orientation for the IK problem.
def objective_function_for
Use this function to get the value of the objective function for a given configuration q Why has this...
def larm_end_position
Returns the current position of the endeffector or gripper end for the left arm.
def objective_function
Use this function to find the current value of the objective function.
xd
A numpy vector of size 3 representing the desired position of the Endeffector.
def all_joints_in_range
Use this function to check if all values of the given joint vector are in their feasibility range...
larm_reference
A boolean specifying the reference arm for the endeffector.
def end_position
Returns the current position of the endeffector or gripper end for the reference arm.
def pos_rarm_grip_wrt_tor_shpan
Use this function to get the current position of the right gripper (Arm Endeffector) w...
def set_ofuncode
protected
def set_target
Sets the endeffector target to a desired position and orientation.
Contains properties and methods managing the kinematics of the PR2 robot.
def all_IK_solutions
Finds all the feasible solutions of the Inverse Kinematic problem for given redundant parameter vecto...
def redundant_parameters
Use this function to get the current values of the five redundant parameters of the PR2 robot in free...
def set_config
Sets the robot configuration to the desired given joint values.
def pos_larm_grip_wrt_tor_shpan
Use this function to get the current position of the left gripper (Arm Endeffector) w...
def joint_in_range
Use this function to check if a given value for specific joint is in its feasibility range...
rarm
An instance of class packages.nima.robotics.kinematics.special_geometries.pr2.pr2_arm_kinematics.PR2_ARM() containing the kinematic properties and methods of the right arm.
Contains properties and methods managing the kinematics of the PR2 robot arm.
q
A numpy vector of size 18 containing the current values of the joints.
def pos_larm_grip
Use this function to get the current global position of the left gripper (Arm Endeffector).
qh
A numpy vector of size 7 containing the upper bounds of the arm joints.
ofuncode
Specifies the objective function for redundancy optimization.
def IK_config
Finds the solution of the Inverse Kinematic problem for given redundant parameter vector in free-bas...
def pos_larm_grip_wrt_tor
Use this function to get the current position of the left gripper (Arm Endeffector) w...
redundant_parameters_updated
def __init__
The Class Constructor:
larm
An instance of class packages.nima.robotics.kinematics.special_geometries.pr2.pr2_arm_kinematics.PR2_ARM() containing the kinematic properties and methods of the left arm.
def pos_rarm_grip_wrt_tor
Use this function to get the current position of the right gripper (Arm Endeffector) w...
qm
A numpy vector of size 18 containing a set of reference values for the joints.
def pos_rarm_grip
Use this function to get the current global position of the right gripper (Arm Endeffector).
def rarm_end_position
Returns the current position of the endeffector or gripper end for the right arm. ...
ql
A numpy vector of size 7 containing the lower bounds of the arm joints.