00001
00002 import numpy as np, math
00003 from threading import RLock
00004 import sys, copy
00005 import matplotlib.pyplot as pp
00006
00007 import roslib; roslib.load_manifest('hrl_software_simulation_darpa_m3')
00008
00009 import rospy
00010 import PyKDL as kdl
00011
00012 from equilibrium_point_control.hrl_arm import HRLArm, HRLArmKinematics
00013
00014 import hrl_lib.geometry as hg
00015 import hrl_lib.kdl_utils as ku
00016 import hrl_lib.viz as hv
00017
00018 from hrl_msgs.msg import FloatArrayBare
00019 from visualization_msgs.msg import Marker
00020 from hrl_haptic_manipulation_in_clutter_msgs.msg import MechanicalImpedanceParams
00021
00022
00023 class ODESimArm(HRLArm):
00024 def __init__(self, d_robot):
00025 rospy.loginfo("Loading ODESimArm")
00026 kinematics = RobotSimulatorKDL(d_robot)
00027 HRLArm.__init__(self, kinematics)
00028
00029 self.jep_pub = rospy.Publisher('/sim_arm/command/jep', FloatArrayBare)
00030 self.cep_marker_pub = rospy.Publisher('/sim_arm/viz/cep', Marker)
00031
00032 self.impedance_pub = rospy.Publisher('/sim_arm/command/joint_impedance',
00033 MechanicalImpedanceParams)
00034
00035 rospy.Subscriber('/sim_arm/joint_angles', FloatArrayBare,
00036 self.joint_states_cb)
00037 rospy.Subscriber('/sim_arm/joint_angle_rates', FloatArrayBare,
00038 self.joint_rates_cb)
00039 rospy.Subscriber('/sim_arm/jep', FloatArrayBare, self.jep_cb)
00040 rospy.Subscriber('/sim_arm/joint_impedance', MechanicalImpedanceParams,
00041 self.impedance_params_cb)
00042 rospy.Subscriber ("/delta_jep_mpc_cvxgen", FloatArrayBare, self.set_delta_ep_ros)
00043
00044
00045 rospy.sleep(1.)
00046 rospy.loginfo("Finished loading SimpleArmManger")
00047
00048 def jep_cb(self, msg):
00049 with self.lock:
00050 self.ep = copy.copy(msg.data)
00051
00052 def joint_states_cb(self, data):
00053 with self.lock:
00054 self.q = copy.copy(data.data)
00055
00056 def joint_rates_cb(self, data):
00057 with self.lock:
00058 self.qdot = copy.copy(data.data)
00059
00060 def impedance_params_cb(self, data):
00061 with self.lock:
00062 self.kp = copy.copy(data.k_p.data)
00063 self.kd = copy.copy(data.k_d.data)
00064
00065 def get_joint_velocities(self):
00066 with self.lock:
00067 qdot = copy.copy(self.qdot)
00068 return qdot
00069
00070 def set_ep(self, jep, duration=0.15):
00071 f = FloatArrayBare(jep)
00072 self.jep_pub.publish(f)
00073 self.publish_rviz_markers()
00074
00075 def set_delta_ep_ros(self, msg):
00076 delta_jep = copy.copy(msg.data)
00077 if delta_jep is None or len(delta_jep) != 3:
00078 raise RuntimeError("set_jep value is " + str(delta_jep))
00079
00080 with self.lock:
00081 if self.ep == None:
00082 self.ep = self.get_joint_angles()
00083
00084 jep = (np.array(self.ep) + np.array(delta_jep)).tolist()
00085
00086 f = FloatArrayBare(jep)
00087 self.jep_pub.publish(f)
00088
00089 def publish_rviz_markers(self):
00090
00091 jep = self.get_ep()
00092 cep, r = self.kinematics.FK(jep)
00093 o = np.matrix([0.,0.,0.,1.]).T
00094 cep_marker = hv.single_marker(cep, o, 'sphere',
00095 '/torso_lift_link', color=(0., 0., 1., 1.),
00096 scale = (0.02, 0.02, 0.02), duration=0.)
00097
00098 cep_marker.header.stamp = rospy.Time.now()
00099 self.cep_marker_pub.publish(cep_marker)
00100
00101
00102 def set_joint_impedance(self, kp, kd):
00103 im = MechanicalImpedanceParams()
00104 im.k_p.data = kp
00105 im.k_d.data = kd
00106 self.impedance_pub.publish(im)
00107
00108
00109
00110
00111 class RobotSimulatorKDL(HRLArmKinematics):
00112 def __init__(self, d_robot):
00113 HRLArmKinematics.__init__(self, len(d_robot.b_jt_anchor))
00114 self.arm_type = "simulated"
00115 self.d_robot = d_robot
00116 self.right_chain = self.create_right_chain()
00117 fk, ik_v, ik_p, jac = self.create_solvers(self.right_chain)
00118
00119 self.right_fk = fk
00120 self.right_ik_v = ik_v
00121 self.right_ik_p = ik_p
00122 self.right_jac = jac
00123 self.right_tooltip = np.matrix([0.,0.,0.]).T
00124
00125
00126 self.min_jtlim_arr = d_robot.b_jt_limits_min
00127 self.max_jtlim_arr = d_robot.b_jt_limits_max
00128
00129
00130 def create_right_chain(self):
00131 height = 0.0
00132 linkage_offset_from_ground = np.matrix([0., 0., height]).T
00133 self.linkage_offset_from_ground = linkage_offset_from_ground
00134 self.n_jts = len(self.d_robot.b_jt_anchor)
00135 rospy.loginfo("number of joints is :"+str(self.n_jts))
00136
00137 ee_location = self.d_robot.ee_location
00138 b_jt_anchor = self.d_robot.b_jt_anchor
00139 b_jt_axis = self.d_robot.b_jt_axis
00140
00141 ch = kdl.Chain()
00142 prev_vec = np.copy(linkage_offset_from_ground.A1)
00143 n = len(self.d_robot.b_jt_anchor)
00144
00145 for i in xrange(n-1):
00146 if b_jt_axis[i][0] == 1 and b_jt_axis[i][1] == 0 and b_jt_axis[i][2] == 0:
00147 kdl_jt = kdl.Joint(kdl.Joint.RotX)
00148 elif b_jt_axis[i][0] == 0 and b_jt_axis[i][1] == 1 and b_jt_axis[i][2] == 0:
00149 kdl_jt = kdl.Joint(kdl.Joint.RotY)
00150 elif b_jt_axis[i][0] == 0 and b_jt_axis[i][1] == 0 and b_jt_axis[i][2] == 1:
00151 kdl_jt = kdl.Joint(kdl.Joint.RotZ)
00152 else:
00153 print "can't do off-axis joints yet!!!"
00154
00155 np_vec = np.array(b_jt_anchor[i+1])
00156 diff_vec = np_vec-prev_vec
00157 prev_vec = np_vec
00158 kdl_vec = kdl.Vector(diff_vec[0], diff_vec[1], diff_vec[2])
00159 ch.addSegment(kdl.Segment(kdl_jt, kdl.Frame(kdl_vec)))
00160
00161 np_vec = np.copy(ee_location.A1)
00162 diff_vec = np_vec-prev_vec
00163
00164 if b_jt_axis[n-1][0] == 1 and b_jt_axis[n-1][1] == 0 and b_jt_axis[n-1][2] == 0:
00165 kdl_jt = kdl.Joint(kdl.Joint.RotX)
00166 elif b_jt_axis[n-1][0] == 0 and b_jt_axis[n-1][1] == 1 and b_jt_axis[n-1][2] == 0:
00167 kdl_jt = kdl.Joint(kdl.Joint.RotY)
00168 elif b_jt_axis[n-1][0] == 0 and b_jt_axis[n-1][1] == 0 and b_jt_axis[n-1][2] == 1:
00169 kdl_jt = kdl.Joint(kdl.Joint.RotZ)
00170 else:
00171 print "can't do off-axis joints yet!!!"
00172
00173 kdl_vec = kdl.Vector(diff_vec[0], diff_vec[1], diff_vec[2])
00174 ch.addSegment(kdl.Segment(kdl_jt, kdl.Frame(kdl_vec)))
00175
00176 return ch
00177
00178 def create_solvers(self, ch):
00179 fk = kdl.ChainFkSolverPos_recursive(ch)
00180 ik_v = kdl.ChainIkSolverVel_pinv(ch)
00181 ik_p = kdl.ChainIkSolverPos_NR(ch, fk, ik_v)
00182 jac = kdl.ChainJntToJacSolver(ch)
00183 return fk, ik_v, ik_p, jac
00184
00185 def FK_kdl(self, q, link_number):
00186 fk = self.right_fk
00187 endeffec_frame = kdl.Frame()
00188 kinematics_status = fk.JntToCart(q, endeffec_frame,
00189 link_number)
00190 if kinematics_status >= 0:
00191 return endeffec_frame
00192 else:
00193 rospy.loginfo('Could not compute forward kinematics.')
00194 return None
00195
00196
00197 def FK_vanilla(self, q, link_number=None):
00198 if link_number == None:
00199 link_number = self.n_jts
00200 link_number = min(link_number, self.n_jts)
00201
00202 q = self.list_to_kdl(q)
00203 frame = self.FK_kdl(q, link_number)
00204 pos = frame.p
00205 pos = ku.kdl_vec_to_np(pos)
00206 pos = pos + self.linkage_offset_from_ground
00207 m = frame.M
00208 rot = ku.kdl_rot_to_np(m)
00209
00210 return pos, rot
00211
00212 def kdl_to_list(self, q):
00213 if q == None:
00214 return None
00215 n = self.n_jts
00216 q_list = [0] * n
00217 for i in xrange(n):
00218 q_list[i] = q[i]
00219 return q_list
00220
00221 def list_to_kdl(self, q):
00222 if q == None:
00223 return None
00224 n = len(q)
00225 q_kdl = kdl.JntArray(n)
00226 for i in xrange(n):
00227 q_kdl[i] = q[i]
00228 return q_kdl
00229
00230
00231
00232 def jacobian(self, q, pos=None):
00233 if pos == None:
00234 pos = self.FK(q)[0]
00235
00236 v_list = []
00237 w_list = []
00238
00239
00240
00241
00242 for i in xrange(self.n_jts):
00243 p, rot = self.FK_vanilla(q, i)
00244 r = pos - p
00245 z_idx = self.right_chain.getSegment(i).getJoint().getType() - 1
00246 z = rot[:, z_idx]
00247 v_list.append(np.matrix(np.cross(z.A1, r.A1)).T)
00248 w_list.append(z)
00249
00250 J = np.row_stack((np.column_stack(v_list), np.column_stack(w_list)))
00251 return J
00252
00253 def clamp_to_joint_limits(self, q):
00254 return np.clip(q, self.min_jtlim_arr, self.max_jtlim_arr)
00255
00256 def within_joint_limits(self, q, delta_list=None):
00257 if delta_list == None:
00258 delta_list = [0]*len(q)
00259
00260 min_arr = self.min_jtlim_arr
00261 max_arr = self.max_jtlim_arr
00262
00263 q_arr = np.array(q)
00264 d_arr = np.array(delta_list)
00265
00266 return np.all((q_arr <= max_arr+d_arr, q_arr >= min_arr+d_arr))
00267
00268 def get_joint_limits(self):
00269 return self.min_jtlim_arr, self.max_jtlim_arr
00270
00271
00272
00273
00274 def plot_arm(self, q, color, alpha, flip_xy, linewidth=2):
00275 pts = [[0.,0.,0.]]
00276 for i in range(len(q)):
00277 p,_ = self.FK(q, i+1)
00278 pts.append(p.A1.tolist())
00279
00280 pts_2d = np.array(pts)[:,0:2]
00281 direc_list = (pts_2d[1:] - pts_2d[:-1]).tolist()
00282
00283 for i, d in enumerate(direc_list):
00284 d_vec = np.matrix(d).T
00285 d_vec = d_vec / np.linalg.norm(d_vec)
00286 w = np.cross(d_vec.A1, np.array([0., 0., 1.])) * 0.03/2
00287 x1 = pts_2d[i,0]
00288 y1 = pts_2d[i,1]
00289 x2 = pts_2d[i+1,0]
00290 y2 = pts_2d[i+1,1]
00291
00292 x_data = np.array([x1+w[0], x1-w[0], x2-w[0], x2+w[0], x1+w[0]])
00293 y_data = np.array([y1+w[1], y1-w[1], y2-w[1], y2+w[1], y1+w[1]])
00294
00295 if flip_xy:
00296 tmp = y_data
00297 y_data = x_data
00298 x_data = -tmp
00299
00300 pp.plot(x_data, y_data, '-', alpha=alpha, color=color,
00301 linewidth=linewidth)
00302
00303
00304 if __name__ == '__main__':
00305 rospy.init_node('ode_arms_test')
00306 import hrl_common_code_darpa_m3.robot_config.six_link_planar as d_robot
00307 ode_arm = ODESimArm(d_robot)
00308
00309
00310 test_jep = np.radians(np.zeros(ode_arm.kinematics.n_jts))
00311
00312
00313 p, _ = ode_arm.kinematics.FK(test_jep, ode_arm.kinematics.n_jts)
00314 print 'p:', p.A1
00315
00316 ode_arm.set_ep(test_jep)
00317
00318
00319