hrl_arm.py
Go to the documentation of this file.
00001 
00002 #
00003 # Any robot that wants to use EPC should implement the functions
00004 # sketched out in the HRLArm and HRLArmKinematics
00005 #
00006 
00007 import numpy as np, math
00008 import copy
00009 from threading import RLock
00010 
00011 import roslib; roslib.load_manifest('equilibrium_point_control')
00012 
00013 try:
00014     import hrl_lib.geometry as hg
00015 except ImportError, e:
00016     print '<hrl_arm.py> WARNING:', e
00017 
00018 
00019 class HRLArm():
00020     def __init__(self, kinematics):
00021         # object of class derived from HRLArmKinematics
00022         self.kinematics = kinematics
00023         self.ep = None # equilibrium point
00024         self.kp = None # joint stiffness
00025         self.kd = None # joint damping
00026         self.q = None # angles
00027         self.qdot = None # angular velocity
00028         self.joint_names_list = None # joint names
00029         self.lock = RLock()
00030 
00031     def get_joint_velocities(self):
00032         with self.lock:
00033             return copy.copy(self.qdot)
00034 
00035     def get_joint_angles(self):
00036         with self.lock:
00037             return copy.copy(self.q)
00038 
00039     def set_ep(self, *args):
00040         raise RuntimeError('Unimplemented Function')
00041 
00042     # publish different viz markers.
00043     def publish_rviz_markers(self):
00044         raise RuntimeError('Unimplemented Function')
00045 
00046     def get_ep(self):
00047         with self.lock:
00048             return copy.copy(self.ep)
00049 
00050     # returns kp, kd
00051     # np arrays of stiffness and damping of the virtual springs.      
00052     def get_joint_impedance(self): 
00053         with self.lock:
00054             return copy.copy(self.kp), copy.copy(self.kd)
00055     
00056     def get_joint_names(self):
00057       with self.lock:
00058         return copy.copy(self.joint_names_list)
00059 
00060     # do we really need this function?
00061     def freeze(self):
00062         self.set_ep(self.ep)
00063 
00064     def get_end_effector_pose(self):
00065         return self.kinematics.FK(self.get_joint_angles())
00066 
00067 
00068 class HRLArmKinematics():
00069     def __init__(self, n_jts):
00070         self.tooltip_pos = np.matrix([0.,0.,0.]).T
00071         self.tooltip_rot = np.matrix(np.eye(3))
00072         self.n_jts = n_jts
00073 
00074     # FK without the tooltip
00075     def FK_vanilla(self, q, link_number=None):
00076         raise RuntimeError('Unimplemented Function')
00077 
00078     # @param q - array-like (RADIANs)
00079     # @param link_number - perform FK up to this link. (0-n_jts)
00080     # @return pos (3X1) np matrix, rot (3X3) np matrix
00081     def FK(self, q, link_number=None):
00082         if link_number == None:
00083             link_number = self.n_jts
00084         if link_number > self.n_jts:
00085             raise RuntimeError('Link Number is greater than n_jts: %d'%link_number)
00086         pos, rot = self.FK_vanilla(q, link_number)
00087 
00088         if link_number == self.n_jts:
00089             tooltip_baseframe = rot * self.tooltip_pos
00090             pos += tooltip_baseframe
00091             rot = rot * self.tooltip_rot
00092         return pos, rot
00093 
00094     ##
00095     # Computes IK for the tooltip.  The desired location is first transformed
00096     # back into the last link's frame and IK is performed on that location.
00097     # @param pos Desired link position (3x1 np matrix)
00098     # @param rot Desired link rotation (3x3 np matrix)
00099     # @param q_guess Estimate of the desired joint angles which seeds the IK solver
00100     def IK(self, pos, rot, q_guess=None):
00101         last_link_pos = pos - rot * self.tooltip_rot.T * self.tooltip_pos
00102         last_link_rot = rot * self.tooltip_rot.T
00103         return self.IK_vanilla(last_link_pos, last_link_rot, q_guess)
00104 
00105     # IK without the  tooltip.
00106     def IK_vanilla(self, p, rot, q_guess=None):
00107         raise RuntimeError('Unimplemented Function')
00108 
00109     # @param p - 3x1 np matrix
00110     # @param rot - orientation of end effector frame wrt base of the arm.
00111     def IK(self, p, rot, q_guess=None):
00112         # this code should be common to everyone.
00113         pass
00114 
00115     ## compute Jacobian at point pos.
00116     def Jacobian(self, q, pos=None):
00117         raise RuntimeError('Unimplemented Function')
00118 
00119     ## compute Jacobian at point pos.
00120     def jacobian(self, q, pos=None):
00121         raise RuntimeError('Unimplemented Function')
00122 
00123     ## return min_array, max_array
00124     def get_joint_limits(self):
00125         raise RuntimeError('Unimplemented Function')
00126 
00127     ## define tooltip as a 3x1 np matrix in the wrist coord frame.
00128     def set_tooltip(self, p, rot=np.matrix(np.eye(3))):
00129         self.tooltip_pos = copy.copy(p)
00130         self.tooltip_rot = copy.copy(rot)
00131 
00132     #----- 2D functions ----------
00133 
00134     # return list of 2D points corresponding to the locations of the
00135     # joint axes for a planar arm. Something funky for a spatial arm
00136     # that Advait does not want to put into words.
00137     def arm_config_to_points_list(self, q):
00138         return [self.FK(q, i)[0].A1[0:2] for i in range(len(q)+1)]
00139 
00140     # project point onto the arm skeleton in 2D and compute distance
00141     # along it to the end effector.
00142     def distance_from_ee_along_arm(self, q, pt):
00143         p_l = self.arm_config_to_points_list(q)
00144         ee = self.FK(q)[0]
00145         d_ee = hg.distance_along_curve(ee, p_l)
00146         d_pt = hg.distance_along_curve(pt, p_l)
00147         assert(d_ee >= d_pt)
00148         return d_ee - d_pt
00149     
00150     # distance of a point from the arm
00151     def distance_from_arm(self, q, pt):
00152         p_l = self.arm_config_to_points_list(q)
00153         return hg.distance_from_curve(pt, p_l)
00154 
00155     # is pt at the joint?
00156     # pt - 2x1 or 3x1 np matrix
00157     # return True if distance between a joint and the point projected
00158     # onto the skeleton is <= dist_threshold.
00159     #
00160     # tested only for planar arms. (see test_contact_at_joints.py in
00161     # sandbox_advait_darpa_m3/src/sandbox_advait_darpa_m3/software_simulation)
00162     def is_contact_at_joint(self, pt, q, dist_threshold):
00163         pts_list = [self.FK(q, i)[0].A1 for i in range(len(q)+1)]
00164         proj_pt = hg.project_point_on_curve(pt, pts_list)
00165 
00166         # ignore end effector (it is not a joint)
00167         for jt in pts_list[:-1]:
00168             dist = np.linalg.norm(np.matrix(jt).T-proj_pt)
00169             if dist <= dist_threshold:
00170                 return True
00171         return False
00172 
00173 
00174 
00175 
00176 
00177 
00178 
00179 
00180 


equilibrium_point_control
Author(s): Advait Jain, Kelsey Hawkins. Advisor: Prof. Charlie Kemp (Healthcare Robotics Lab)
autogenerated on Wed Nov 27 2013 11:34:55