hrl_arm_template.py
Go to the documentation of this file.
00001 #
00002 # Any robot that wants to use EPC should implement the functions
00003 # sketched out in the HRLArm and HRLArmKinematics
00004 #
00005 # Standards:
00006 #   pos is a 3x1 numpy matrix representing a position
00007 #   rot is a 3x3 numpy matrix represetning a rotation
00008 #   All values are computed in the arm's reference frame (frame 0)
00009 #
00010 
00011 import numpy as np, math
00012 import copy
00013 from threading import RLock
00014 
00015 ##
00016 # Abstract class which represents a basic structure for controlling
00017 # an arm.  An equilibrium point (ep) represents a commanded goal for the
00018 # arm which is passed to the underlying controller.  A basic assumption of
00019 # equilibrium point control is that the underlying controller doesn't necessarily
00020 # reach the arm commanded goal due to contact, gravity, low gains in the controller, etc.
00021 # Thus we employ another layer of control which relocates the equilibrium point
00022 # based on the task at hand.
00023 class HRLArm(object):
00024     def __init__(self, kinematics):
00025         # object of class derived from HRLArmKinematics
00026         self.kinematics = kinematics
00027         self.ep = None # equilibrium point
00028         self.q = None # angles
00029         self.qdot = None # angular velocity
00030         self.lock = RLock()
00031 
00032     #----------------- abstract functions ---------------------
00033     ##
00034     # Commands the arm to move to desired equilbrium point
00035     def set_ep(self, *args):
00036         raise RuntimeError('Unimplemented Function')
00037 
00038     # publish different viz markers.
00039     def publish_rviz_markers(self):
00040         raise RuntimeError('Unimplemented Function')
00041 
00042     ##
00043     # Resets the equilibrium point based on some estimate
00044     def reset_ep(self):
00045         raise RuntimeError('Unimplemented Function')
00046     #----------------------------------------------------------
00047 
00048     ##
00049     # Records the current joint angles.  This must be updated regularly
00050     # by the child class.
00051     # @param q array-like of joint angles
00052     def set_joint_angles(self, q):
00053         with self.lock:
00054             self.q = copy.copy(q)
00055 
00056     ##
00057     # Returns the current joint angles of the arm
00058     # @return array-like of joint angles
00059     def get_joint_angles(self):
00060         with self.lock:
00061             return copy.copy(self.q)
00062 
00063     ##
00064     # Returns the current equilibrium point
00065     # @return equilibrium point
00066     def get_ep(self):
00067         with self.lock:
00068             return copy.copy(self.ep)
00069 
00070     ##
00071     # Returns the current pose of the tooltip
00072     # @return (pos, rot)
00073     def get_end_effector_pose(self):
00074         q = self.get_joint_angles()
00075         if q is None:
00076             return None
00077         else:
00078             return self.kinematics.FK(q)
00079 
00080 
00081 ##
00082 # Abstract class containing kinematics interfaces for an arm
00083 class HRLArmKinematics(object):
00084     ##
00085     # @param n_jts Number of joints of the arm
00086     # @param tool_pos Postion offset of the tool from the last link in the kinematic chain
00087     # @param tool_rot Rotation offset of the tool from the last link in the kinematic chain
00088     def __init__(self, n_jts, arm_base_pos=np.matrix([0.]*3).T, arm_base_rot=np.matrix(np.eye(3)), 
00089                               tool_pos=np.matrix([0.]*3).T, tool_rot=np.matrix(np.eye(3))):
00090         self.n_jts = n_jts
00091         self.set_arm_base(arm_base_pos, arm_base_rot)
00092         self.set_tooltip(tool_pos, tool_rot)
00093 
00094     #----------------- abstract functions ---------------------
00095     ##
00096     # Returns FK for the last link in the kinematic chain.
00097     # Must be implemented by child class.
00098     # @param q Joint angles in radians
00099     # @param link_number Link in the kinematic chain to return FK for
00100     #                    0 represents the ground frame, 1 returns the first link's frame, ...
00101     #                    n_jts + 1 returns the tooltip's frame
00102     # @return pos (3x1) np matrix, rot (3x3) np matrix
00103     def FK_vanilla(self, q, link_number=None):
00104         raise RuntimeError('Unimplemented Function')
00105 
00106     ##
00107     # Computes IK for the last link in the kinematic chain.
00108     # Must be implemented by child class.
00109     # @param pos Desired link position (3x1 np matrix)
00110     # @param rot Desired link rotation (3x3 np matrix)
00111     # @param q_guess Estimate of the desired joint angles which seeds the IK solver
00112     def IK_vanilla(self, pos, rot, q_guess=None):
00113         raise RuntimeError('Unimplemented Function')
00114 
00115     ##
00116     # Computes Jacobian in the arm's frame given joint angles at the specified position.
00117     # Must be implemented by child class.
00118     # @param q Joint angles for Jacobian
00119     # @param pos Position at which the Jacobian is centered. If None, the tooltip
00120     #            location from FK is used.
00121     # @return Jacobian 6xN np matrix
00122     def jacobian_vanilla(self, q, pos=None):
00123         raise RuntimeError('Unimplemented Function')
00124     #----------------------------------------------------------
00125 
00126     ##
00127     # Returns FK for the last link in the kinematic chain.
00128     # Must be implemented by child class
00129     # @param q Joint angles in radians
00130     # @param link_number Link in the kinematic chain to return FK for
00131     #                    0 represents the ground frame, 1 returns the first link's frame, ...
00132     #                    n_jts + 1 (and None) returns the tooltip's frame
00133     # @return pos (3x1) np matrix, rot (3x3) np matrix
00134     def FK(self, q, link_number=None):
00135         if link_number == None or link_number > self.n_jts:
00136             use_end_affector = True
00137             link_number = None
00138         else:
00139             use_end_affector = False
00140             
00141         pos, rot = self.FK_vanilla(q, link_number)
00142 
00143         # offset arm base to FK end
00144         pos = self.arm_base_pos + self.arm_base_rot * pos
00145         rot = self.arm_base_rot * rot
00146 
00147         if use_end_affector:
00148             # offset end location to tooltip
00149             tooltip_baseframe = rot * self.tooltip_pos
00150             pos += tooltip_baseframe
00151             rot = rot * self.tooltip_rot
00152         return pos, rot
00153 
00154     ##
00155     # Computes IK for the tooltip.  The desired location is first transformed
00156     # back into the last link's frame and IK is performed on that location.
00157     # @param pos Desired link position (3x1 np matrix)
00158     # @param rot Desired link rotation (3x3 np matrix)
00159     # @param q_guess Estimate of the desired joint angles which seeds the IK solver
00160     def IK(self, pos, rot, q_guess=None):
00161         base_pos = self.arm_base_rot.T * pos - self.arm_base_rot.T * self.arm_base_pos
00162         base_rot = self.arm_base_rot.T * rot
00163         last_link_pos = base_pos - base_rot * self.tooltip_rot.T * self.tooltip_pos
00164         last_link_rot = base_rot * self.tooltip_rot.T
00165         return self.IK_vanilla(last_link_pos, last_link_rot, q_guess)
00166 
00167     ##
00168     # Computes Jacobian in the arm's frame given joint angles at the specified position.
00169     # @param q Joint angles for Jacobian
00170     # @param pos Position at which the Jacobian is centered. If None, the tooltip
00171     #            location from FK is used.
00172     # @return Jacobian 6xN np matrix
00173     def jacobian(self, q, pos=None):
00174         if pos is None:
00175             pos = self.FK(q)
00176         return self.jacobian_vanilla(q, pos)
00177 
00178     ##
00179     # Sets the offset of the first link in the kinematic chain
00180     # @param arm_base_pos Postion offset of the first link in the kinematic chain
00181     # @param arm_base_rot Rotation offset of the first link in the kinematic chain
00182     def set_arm_base(self, arm_base_pos, arm_base_rot=np.matrix(np.eye(3))):
00183         self.arm_base_pos = arm_base_pos
00184         self.arm_base_rot = arm_base_rot
00185 
00186     ##
00187     # Sets the offset of the tool from the last link in the kinematic chain
00188     # @param tool_pos Postion offset of the tool from the last link in the kinematic chain
00189     # @param tool_rot Rotation offset of the tool from the last link in the kinematic chain
00190     def set_tooltip(self, tool_pos, tool_rot=np.matrix(np.eye(3))):
00191         self.tooltip_pos = tool_pos
00192         self.tooltip_rot = tool_rot
00193 


hrl_generic_arms
Author(s): Kelsey Hawkins
autogenerated on Wed Nov 27 2013 11:53:37