arm_cmder.py
Go to the documentation of this file.
00001 #! /usr/bin/env python
00002 #
00003 # Copyright (c) 2010, Willow Garage, Inc.
00004 # All rights reserved.
00005 #
00006 # Redistribution and use in source and binary forms, with or without
00007 # modification, are permitted provided that the following conditions are met:
00008 #
00009 #     * Redistributions of source code must retain the above copyright
00010 #       notice, this list of conditions and the following disclaimer.
00011 #     * Redistributions in binary form must reproduce the above copyright
00012 #       notice, this list of conditions and the following disclaimer in the
00013 #       documentation and/or other materials provided with the distribution.
00014 #     * Neither the name of the Willow Garage, Inc. nor the names of its
00015 #       contributors may be used to endorse or promote products derived from
00016 #       this software without specific prior written permission.
00017 #
00018 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00022 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028 # POSSIBILITY OF SUCH DAMAGE.
00029 
00030 ##\author Kevin Watts
00031 ##\brief Sends goals to arms in collision free way.
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 ##\brief Moves arms to 0 position using unsafe trajectory
00047 ##
00048 ##\param recovery { str : float } : Recover positions for arms
00049 ##\return JointTrajectoryGoal for arm 
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     ##\return GoalStatus
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     ## Unit testing only
00097     ##\return GoalStatus
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     ## Send random commands to arm.
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 


life_test
Author(s): Kevin Watts
autogenerated on Sat Dec 28 2013 17:56:37