Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 import rospy
00019 import threading
00020
00021 from sr_robot_msgs.msg import sendupdate, joint
00022 from sr_hand.shadowhand_ros import ShadowHand_ROS
00023 from sr_hand.grasps_interpoler import GraspInterpoler
00024 from sr_hand.Grasp import Grasp
00025
00026 """
00027 Module to provide a quick and easy way to script the Shadow Hand.
00028 This is done via creating a short script with a Commander object then calling
00029 methods on the commander to script the motion.
00030
00031 Basic script will look like:
00032
00033 #!/usr/bin/python
00034 import rospy
00035 from sr_hand.shadowhand_commander import Commander
00036
00037 rospy.init_node('basic_example')
00038 c = Commander()
00039
00040 c.move_hand({
00041 "THJ1": 0, "THJ2": 6, "THJ3": 10, "THJ4": 37, "THJ5": 9,
00042 "FFJ0": 21, "FFJ3": 26, "FFJ4": 0,
00043 "MFJ0": 18, "MFJ3": 24, "MFJ4": 0,
00044 "RFJ0": 30, "RFJ3": 16, "RFJ4": 0,
00045 "LFJ0": 30, "LFJ3": 0, "LFJ4": -10, "LFJ5": 10
00046 })
00047 rospy.sleep(3.0)
00048
00049
00050 See the examples directory in the package sr_examples.
00051 """
00052
00053 class Commander(object):
00054 def __init__(self):
00055
00056 self.mutex = threading.Lock()
00057
00058
00059 self.grasp_interpolators = {}
00060
00061
00062 self.hand = ShadowHand_ROS()
00063
00064
00065
00066 self.hand_interpolation_period = 0.01
00067 if self.hand.check_hand_type() == "gazebo":
00068
00069 self.hand_interpolation_period = 0.1
00070
00071
00072 def move_hand(self, command):
00073 """
00074 Move the Shadow Hand.
00075
00076 This call is non blocking. It will return before the motion has finished.
00077
00078 If called with interpolation time of 0.0 the joints will move to the target position
00079 at maximum velocity (i.e. the max. vel. allowed by the position controller for that joint)
00080
00081 If called with interpolation time greater than self.hand_interpolation_period,
00082 a separate thread will deal with the interpolation time and will keep
00083 sending targets to the hand until the last target is sent.
00084
00085 If move_hand() is called again before the previous movements have finished,
00086 the new call will override only the conciding joints. The others will keep moving
00087 to their previous targets at their previous velocity.
00088
00089 @param command - Dictionary of joint names in the keys and angles in
00090 degrees in the values. The key interpolation_time gives the time in seconds that
00091 the movement will last.
00092 """
00093
00094
00095 joints = dict(command)
00096
00097 interpolation_time = 0.0
00098 if 'interpolation_time' in joints:
00099 interpolation_time = joints['interpolation_time']
00100 del joints['interpolation_time']
00101
00102 if interpolation_time == 0.0:
00103 self.mutex.acquire()
00104 self._prune_interpolators(joints)
00105 self.mutex.release()
00106 self.hand.sendupdate_from_dict(joints)
00107 else:
00108 threading.Thread(target=self._move_hand_interpolation,
00109 args=(joints, interpolation_time)).start()
00110
00111
00112 def _move_hand_interpolation(self, joints, interpolation_time=1.0):
00113 """
00114 Remove the coinciding joints from the currently running interpolators.
00115 It actually removes the joints from the 'grasp_to' list of the interpolator.
00116
00117 @param joints - Dictionary of joint names in the keys and angles in
00118 degrees in the values.
00119 @param interpolation_time - A float. Interpolation time in seconds.
00120 """
00121
00122 rospy.logdebug("call interpolation")
00123 thread_name = threading.current_thread().name
00124 try:
00125 self.mutex.acquire()
00126 self._prune_interpolators(joints)
00127 self.mutex.release()
00128
00129 rospy.logdebug("start interpolation")
00130 current_grasp = Grasp()
00131 current_grasp.joints_and_positions = self.hand.read_all_current_positions()
00132 target_grasp = Grasp()
00133 target_grasp.joints_and_positions = joints
00134
00135 interpolator = GraspInterpoler(current_grasp, target_grasp)
00136 self.grasp_interpolators[thread_name] = interpolator
00137
00138 r = rospy.Rate(1.0 / self.hand_interpolation_period)
00139
00140 for interpolation in range (1, int(interpolation_time / self.hand_interpolation_period) + 1):
00141 self.mutex.acquire()
00142 targets_to_send = interpolator.interpolate(100.0 * interpolation * self.hand_interpolation_period / interpolation_time)
00143 self.mutex.release()
00144 self.hand.sendupdate_from_dict(targets_to_send)
00145
00146 r.sleep()
00147 finally:
00148 self.mutex.acquire()
00149 self.grasp_interpolators.pop(thread_name, None)
00150 self.mutex.release()
00151 rospy.logdebug("end interpolation")
00152
00153
00154 def _prune_interpolators(self, joints):
00155 """
00156 Remove the coinciding joints from the currently running interpolators.
00157 It actually removes the joints from the 'grasp_to' list of the interpolator.
00158
00159 @param joints - Dictionary of joint names in the keys and angles in
00160 degrees in the values.
00161 """
00162 rospy.logdebug("Call prune from thread %s", threading.current_thread().name )
00163 for thread_id in self.grasp_interpolators.keys():
00164 for joint_name in joints.keys():
00165 self.grasp_interpolators[thread_id].grasp_to.joints_and_positions.pop(joint_name, None)
00166 rospy.logdebug("Prune joint %s thread %s", joint_name, thread_id )
00167
00168
00169 def get_hand_position(self):
00170 """
00171 Returns a dictionary with the position of each joint in degrees.
00172 """
00173 return dict(self.hand.read_all_current_positions())
00174
00175 def get_hand_velocity(self):
00176 """
00177 Returns a dictionary with the velocity of each joint in degrees/s.
00178 """
00179 return dict(self.hand.read_all_current_velocities())
00180
00181 def get_hand_effort(self):
00182 """
00183 Returns a dictionary with the effort of each joint. Currently in ADC units, as no calibration is performed on the strain gauges.
00184 """
00185 return dict(self.hand.read_all_current_efforts())
00186
00187 def get_tactile_type(self):
00188 """
00189 Returns a string indicating the type of tactile sensors present. Possible values are: PST, biotac, UBI0 .
00190 """
00191 return self.hand.get_tactile_type()
00192
00193 def get_tactile_state(self):
00194 """
00195 Returns an object containing tactile data. The structure of the data is different for every tactile_type .
00196 """
00197 return self.hand.get_tactile_state()
00198
00199