ep_arm_base.py
Go to the documentation of this file.
00001 #! /usr/bin/python
00002 #
00003 # Base class for interacting with a realtime controller using an equilibrium point control
00004 # framework.
00005 #
00006 # Copyright (c) 2012, Georgia Tech Research Corporation
00007 # All rights reserved.
00008 # 
00009 # Redistribution and use in source and binary forms, with or without
00010 # modification, are permitted provided that the following conditions are met:
00011 #     * Redistributions of source code must retain the above copyright
00012 #       notice, this list of conditions and the following disclaimer.
00013 #     * Redistributions in binary form must reproduce the above copyright
00014 #       notice, this list of conditions and the following disclaimer in the
00015 #       documentation and/or other materials provided with the distribution.
00016 #     * Neither the name of the Georgia Tech Research Corporation nor the
00017 #       names of its contributors may be used to endorse or promote products
00018 #       derived from this software without specific prior written permission.
00019 # 
00020 # THIS SOFTWARE IS PROVIDED BY GEORGIA TECH RESEARCH CORPORATION ''AS IS'' AND
00021 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00022 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00023 # DISCLAIMED. IN NO EVENT SHALL GEORGIA TECH BE LIABLE FOR ANY DIRECT, INDIRECT,
00024 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00025 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00026 # OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00027 # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
00028 # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00029 # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 #
00031 # Author: Kelsey Hawkins
00032 
00033 from threading import Lock
00034 import numpy as np
00035 import copy
00036 
00037 import roslib
00038 roslib.load_manifest('hrl_pr2_arms')
00039 
00040 import rospy
00041 
00042 from urdf_parser_py.urdf import URDF
00043 from pykdl_utils.joint_kinematics import JointKinematics
00044 
00045 
00046 ##
00047 # Base class for interacting with a realtime controller using an equilibrium point control
00048 # frame work.  An equilibrium point is a set of parameters representing the state of the
00049 # controller at which no torques would be applied. For a PID controller, this represents
00050 # the joint angles where the error would be zero.
00051 class EPArmBase(JointKinematics):
00052     ##
00053     # Constructor
00054     # @param arm_side Used to signify side of robot for similar arms 
00055     #                 (e.g. 'r' for right, 'l' for left)
00056     # @param urdf URDF object of robot.
00057     # @param base_link Name of the root link of the kinematic chain. 
00058     #                  Will fill in arm_side if %s is in string.
00059     # @param end_link Name of the end link of the kinematic chain.
00060     #                 Will fill in arm_side if %s is in string.
00061     # @param controller_name Optional name of the controller which will be subscribed to
00062     #                        to obtain controller information
00063     # @param kdl_tree Optional KDL.Tree object to use. If None, one will be generated
00064     #                          from the URDF.
00065     # @param timeout Time in seconds to wait for the /joint_states topic.
00066     def __init__(self, arm_side, urdf, base_link, end_link, controller_name=None, 
00067                  kdl_tree=None, timeout=1.):
00068         if "%s" in base_link:
00069             base_link = base_link % arm_side
00070         if "%s" in end_link:
00071             end_link = end_link % arm_side
00072         if controller_name is not None and "%s" in controller_name:
00073             controller_name = controller_name % arm_side
00074         super(EPArmBase, self).__init__(urdf, base_link, end_link, kdl_tree, timeout)
00075         self.arm_side = arm_side
00076         self.controller_name = controller_name
00077         self.ep = None # equilibrium point
00078         self.ep_time = None # time ep was last recorded
00079         self.ep_lock = Lock()
00080         self.ctrl_state_lock = Lock()
00081         self.ctrl_state_dict = {} # stores information from the realtime controller
00082 
00083     ##
00084     # Returns the current pose of the tooltip
00085     # @return 4x4 np.mat homogeneous matrix
00086     def get_end_effector_pose(self):
00087         return self.forward()
00088 
00089     ##
00090     # Returns the current equilibrium point as read from the controller
00091     # @return equilibrium point
00092     def get_ep(self):
00093         with self.ep_lock:
00094             if self.ep is None:
00095                 rospy.logwarn("[ep_arm_base] Equilibrium point not read yet.")
00096             return copy.copy(self.ep)
00097 
00098     ##
00099     # Commands the arm to move to desired equilbrium point
00100     def set_ep(self, *args):
00101         raise RuntimeError('Unimplemented Function')
00102 
00103     ##
00104     # Wait until we have the ep from the controller
00105     # @param timeout Time in seconds at which we break if we haven't recieved the EP.
00106     def wait_for_ep(self, timeout=1.):
00107         start_time = rospy.get_time()
00108         r = rospy.Rate(100)
00109         while not rospy.is_shutdown() and rospy.get_time() - start_time < timeout:
00110             with self.ep_lock:
00111                 if self.ep is not None:
00112                     return True
00113             r.sleep()
00114         return False
00115             
00116     ##
00117     # Returns the current state of the realtime controller. The state is filled in
00118     # by the subclasses.
00119     # @return dict with realtime controller information.
00120     def get_controller_state(self):
00121         with self.ctrl_state_lock:
00122             if self.controller_name is None:
00123                 rospy.logerror("[ep_arm_base] get_controller_state NOT IMPLEMENTED!")
00124                 return None
00125             elif len(self.ctrl_state_dict) == 0:
00126                 rospy.logwarn("[ep_arm_base] Controller state not yet published.")
00127                 return None
00128             return self.ctrl_state_dict
00129 
00130     ##
00131     # Returns whether the equilibrium point has been recorded for some time.
00132     # @param stale_time Time in seconds to pass to consider the EP stale.
00133     # @return True if the EP is stale.
00134     def is_ep_stale(self, stale_time=1.):
00135         with self.ep_lock:
00136             if self.ep is None:
00137                 rospy.logwarn("[ep_arm_base] Equilibrium point not read yet.")
00138                 return True
00139             return rospy.get_time() - self.ep_time > stale_time
00140 
00141     ##
00142     # Method to be implemented by subclasses to record the equilibrium point.
00143     def _save_ep(self, ep):
00144         with self.ep_lock:
00145             self.ep_time = rospy.get_time()
00146             self.ep = ep
00147 
00148 def create_ep_arm(arm_side, arm_type=EPArmBase, urdf_filename=None, **args):
00149     if urdf_filename is None:
00150         robot = URDF.load_from_parameter_server(verbose=False)
00151     else:
00152         robot = URDF.load_xml_file(urdf_filename, verbose=False)
00153     return arm_type(arm_side, robot, **args)


hrl_pr2_arms
Author(s): Kelsey Hawkins, Advisor: Prof. Charlie Kemp, Lab: Healthcare Robotics Lab
autogenerated on Wed Nov 27 2013 11:41:30