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 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 PKG = 'life_test'
00034 import roslib; roslib.load_manifest(PKG)
00035 import rospy
00036 import actionlib
00037 import random
00038 random.seed()
00039 
00040 from pr2_controllers_msgs.msg import JointTrajectoryGoal, JointTrajectoryAction
00041 from trajectory_msgs.msg import JointTrajectoryPoint
00042 from actionlib_msgs.msg import GoalStatus
00043 
00044 FAILED_OUT = 5
00045 
00046 
00047 
00048 
00049 
00050 def _get_recovery_goal(recovery):
00051     point = JointTrajectoryPoint()
00052     point.time_from_start = rospy.Duration.from_sec(5)    
00053     
00054     goal = JointTrajectoryGoal()
00055     goal.trajectory.points.append(point)
00056     goal.trajectory.header.stamp = rospy.get_rostime()
00057 
00058     for joint, pos in recovery.iteritems():
00059         goal.trajectory.joint_names.append(joint)
00060         goal.trajectory.points[0].positions.append(pos)
00061         goal.trajectory.points[0].velocities.append(0.0)
00062 
00063     return goal
00064 
00065 class ArmCmder(object):
00066     """
00067     This class sends commands random to an arm using a JointTrajectoryAction. 
00068     It sends "safe" commands by default. If the arm fails to move after a few tries, 
00069     it sends an unsafe, predefined recovery command.
00070     """
00071     def __init__(self, arm_client, ranges, recovery_client, recovery_positions):
00072         """
00073         \param arm_client SimpleActionClient : Client to collision free arm commands
00074         \param ranges { str : (float, float) } : Position ranges for each joint.
00075         \param recovery_client SimpleActionClient : Client to unsafe arm controller
00076         \param recovery_positions { str : float } : Recovery positions for each joint
00077         """
00078         self._arm_client = arm_client
00079         self._ranges = ranges
00080         self._recovery_client = recovery_client
00081         self._recovery_positions = recovery_positions
00082 
00083         self._fail_count = 0
00084         
00085         
00086     
00087     def command_goal(self, goal, duration = 15):
00088         self._arm_client.send_goal(goal)
00089         self._arm_client.wait_for_result(rospy.Duration.from_sec(duration))
00090 
00091         rv = self._arm_client.get_state()
00092         self._arm_client.cancel_goal()
00093 
00094         return rv
00095 
00096     
00097     
00098     def command_recovery(self):
00099         recovery_goal = _get_recovery_goal(self._recovery_positions)
00100         self._recovery_client.cancel_all_goals()
00101         self._recovery_client.send_goal(recovery_goal)
00102         rospy.loginfo('Sent recovery goal')
00103         self._recovery_client.wait_for_result(rospy.Duration.from_sec(10))
00104 
00105         rv = self._recovery_client.get_state()
00106         rospy.loginfo('Got recovery result: %d' % rv)
00107 
00108         self._recovery_client.cancel_goal()
00109 
00110         return rv
00111 
00112     def _get_random_goal(self):
00113         goal = JointTrajectoryGoal()
00114         point = JointTrajectoryPoint()
00115         point.time_from_start = rospy.Duration.from_sec(1)
00116 
00117         goal.trajectory.points.append(point)
00118 
00119         for joint, rng in self._ranges.iteritems():
00120             goal.trajectory.joint_names.append(joint)
00121                         
00122             goal.trajectory.points[0].positions.append(random.uniform(rng[0], rng[1]))
00123 
00124         return goal
00125 
00126     
00127     def send_cmd(self):
00128         goal = self._get_random_goal()
00129         my_result = self.command_goal(goal)
00130 
00131         if my_result == GoalStatus.SUCCEEDED:
00132             self._fail_count = 0
00133         else:
00134             self._fail_count += 1
00135 
00136         if self._fail_count > FAILED_OUT:
00137             rospy.logwarn('Arm may be stuck. Sending recovery goal to free it')
00138             self._fail_count = 0
00139             self._arm_client.cancel_goal()
00140             self.command_recovery()
00141