ep_control.py
Go to the documentation of this file.
00001 
00002 import numpy as np, math
00003 import copy
00004 import roslib; roslib.load_manifest('equilibrium_point_control')
00005 import rospy
00006 from std_msgs.msg import Bool
00007 
00008 ##
00009 # Abstract class to be implemented when using equilibrium point control.
00010 # If generate_ep produces equilibrium points which are used by control_ep
00011 # to move the arm, this object can be passed into EPC.epc_motion to control
00012 # the arm.  Equilibrium points can be of any type so long as generate_ep,
00013 # control_ep, and clamp_ep are all written with this type in mind.
00014 class EPGenerator(object):
00015     #----------------- abstract functions ---------------------
00016     ##
00017     # Generates a new equilibrium point.
00018     # @return (stop, ep)
00019     #         stop: EPStopConditions.CONTINUE or non-empty string to terminate
00020     #         ep: equilibrium point to be sent to control_function
00021     def generate_ep(self):
00022         raise RuntimeError('Unimplemented Function')
00023 
00024     ##
00025     # Commands the arm to move towards the specified equilibrium point.
00026     # @param ep equilibrium point to command the arm towards
00027     def control_ep(self, ep):
00028         raise RuntimeError('Unimplemented Function')
00029 
00030     ##
00031     # Takes an equilibrium point and clamps it to reasonable control values.
00032     # To be overwritten if needed by the child class.
00033     # @param ep equilibrium point to clamp
00034     # @return clamped equilibrium point
00035     def clamp_ep(self, ep):
00036         return ep
00037 
00038     ##
00039     # Termination check for collision or goal reaching.
00040     # To be overwritten if needed by the child class.
00041     # @return EPStopConditions.CONTINUE or non-empty string to terminate
00042     def terminate_check(self):
00043         return EPStopConditions.CONTINUE
00044     #----------------------------------------------------------
00045 
00046 ##
00047 # Enumerated constants for EPC termination conditions
00048 class EPStopConditions:
00049     CONTINUE = ''
00050     ROSPY_SHUTDOWN = 'rospy shutdown'
00051     ROS_STOP = 'stop_command_over_ROS'
00052     TIMEOUT = 'timed out'
00053     RESET_TIMING = 'reset timing'
00054     SUCCESSFUL = 'epc motion successful'
00055     COLLISION = 'collision detected'
00056 
00057 ##
00058 # Simple class containing the core EPC function: a control loop paradigm.
00059 class EPC(object):
00060 
00061     ##
00062     # Initializes variables and subscribers
00063     def __init__(self, epc_name = 'epc'):
00064         self.epc_name = epc_name
00065         self.stop_epc = False
00066         self.pause_epc = False
00067         rospy.Subscriber('/'+epc_name+'/stop', Bool, self._stop_cb)
00068         rospy.Subscriber('/'+epc_name+'/pause', Bool, self._pause_cb)
00069 
00070     ##
00071     # Subscriber callback for stopping the arm's motion
00072     def _stop_cb(self, msg):
00073         self.stop_epc = msg.data
00074         self.pause_epc = False # stop/start overrides pause.
00075 
00076     ##
00077     # Subscriber callback for pausing the arm's motion
00078     def _pause_cb(self, msg):
00079         self.pause_epc = msg.data
00080 
00081     ##
00082     # Control loop for equilibrium point control.  For each time step, ep_gen
00083     # provides 4 functions, a termination check, an ep generation step, 
00084     # a clamping step, and an ep control step.  These functions are called in this
00085     # order along with helper functionality for stopping and pausing control.
00086     # @param ep_gen - Object of type EPGenerator.
00087     # @param time_step: Time between successive calls to equi_pt_generator
00088     # @param timeout - time after which the epc motion will stop.
00089     # @return stop (the string which has the reason why the epc
00090     # motion stopped.), ea (last commanded equilibrium angles)
00091     def epc_motion(self, ep_gen, time_step, timeout=np.inf):
00092         rospy.loginfo("[epc] epc_motion started")
00093         timeout_at = rospy.get_time() + timeout
00094         stop = EPStopConditions.CONTINUE
00095         ea = None
00096         while True:
00097             # basic rospy shutdown termination
00098             if rospy.is_shutdown():
00099                 stop = EPStopConditions.ROSPY_SHUTDOWN
00100                 break
00101 
00102             # check to see if we should stop (stop_epc changed from another thread)
00103             if self.stop_epc:
00104                 stop = EPStopConditions.ROS_STOP
00105                 break
00106 
00107             # check to see if the generator thinks we should stop
00108             stop = ep_gen.terminate_check()
00109             if stop != EPStopConditions.CONTINUE:
00110                 break
00111             
00112             # check to see if we're paused
00113             if self.pause_epc:
00114                 rospy.sleep(0.1)
00115                 timeout_at += 0.101 # approximate.
00116                 continue
00117 
00118             # timeout check
00119             if timeout_at < rospy.get_time():
00120                 stop = EPStopConditions.TIMEOUT
00121                 break
00122 
00123             # create a new ep
00124             stop, ep = ep_gen.generate_ep() 
00125             if stop != EPStopConditions.CONTINUE:
00126                 break
00127 
00128             # if a post-processing function exits, use it to process the ep
00129             ep = ep_gen.clamp_ep(ep)
00130 
00131             # command the arm to move to the ep
00132             ep_gen.control_ep(ep)
00133 
00134             rospy.sleep(time_step)
00135 
00136         rospy.loginfo("[epc] epc_motion stopped with termination condition: %s" % stop)
00137         return stop, ea
00138 
00139 


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