sr_robot_commander.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 # Copyright 2015 Shadow Robot Company Ltd.
00004 #
00005 # This program is free software: you can redistribute it and/or modify it
00006 # under the terms of the GNU General Public License as published by the Free
00007 # Software Foundation, either version 2 of the License, or (at your option)
00008 # any later version.
00009 #
00010 # This program is distributed in the hope that it will be useful, but WITHOUT
00011 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
00013 # more details.
00014 #
00015 # You should have received a copy of the GNU General Public License along
00016 # with this program.  If not, see <http://www.gnu.org/licenses/>.
00017 
00018 import threading
00019 
00020 import rospy
00021 from actionlib import SimpleActionClient
00022 from control_msgs.msg import FollowJointTrajectoryAction, \
00023     FollowJointTrajectoryGoal
00024 from moveit_commander import MoveGroupCommander, RobotCommander, \
00025     PlanningSceneInterface
00026 from moveit_msgs.msg import RobotTrajectory
00027 from sensor_msgs.msg import JointState
00028 from sr_robot_msgs.srv import RobotTeachMode, RobotTeachModeRequest, \
00029     RobotTeachModeResponse
00030 from trajectory_msgs.msg import JointTrajectoryPoint
00031 from math import radians
00032 
00033 
00034 class SrRobotCommander(object):
00035     """
00036     Base class for hand and arm commanders
00037     """
00038     __group_prefixes = {"right_arm": "ra_",
00039                         "left_arm": "la_",
00040                         "right_hand": "rh_",
00041                         "left_hand": "lh_"}
00042 
00043     def __init__(self, name):
00044         """
00045         Initialize MoveGroupCommander object
00046         @param name - name of the MoveIt group
00047         """
00048         self._name = name
00049         self._move_group_commander = MoveGroupCommander(name)
00050         self._robot_commander = RobotCommander()
00051         self._planning_scene = PlanningSceneInterface()
00052 
00053         self._move_group_commander.set_planner_id("ESTkConfigDefault")
00054 
00055         self._joint_states_lock = threading.Lock()
00056         self._joint_states_listener = \
00057             rospy.Subscriber("joint_states", JointState,
00058                              self._joint_states_callback, queue_size=1)
00059         self._joints_position = {}
00060         self._joints_velocity = {}
00061         self._joints_effort = {}
00062         self.__plan = None
00063 
00064         # prefix of the trajectory controller
00065         self._prefix = self.__group_prefixes[name]
00066 
00067         self._set_up_action_client()
00068 
00069         threading.Thread(None, rospy.spin)
00070 
00071     def execute(self):
00072         """
00073         Executes the last plan made.
00074         """
00075         if self.__plan is not None:
00076             self._move_group_commander.execute(self.__plan)
00077             self.__plan = None
00078         else:
00079             rospy.logwarn("No plans where made, not executing anything.")
00080 
00081     def move_to_joint_value_target(self, joint_states, wait=True,
00082                                    angle_degrees=False):
00083         """
00084         Set target of the robot's links and moves to it.
00085         @param joint_states - dictionary with joint name and value. It can
00086         contain only joints values of which need to be changed.
00087         @param wait - should method wait for movement end or not
00088         @param angle_degrees - are joint_states in degrees or not
00089         """
00090         if angle_degrees:
00091             joint_states.update((joint, radians(i))
00092                                 for joint, i in joint_states.items())
00093         self._move_group_commander.set_start_state_to_current_state()
00094         self._move_group_commander.set_joint_value_target(joint_states)
00095         self._move_group_commander.go(wait=wait)
00096 
00097     def plan_to_joint_value_target(self, joint_states, angle_degrees=False):
00098         """
00099         Set target of the robot's links and plans.
00100         @param joint_states - dictionary with joint name and value. It can
00101         contain only joints values of which need to be changed.
00102         @param angle_degrees - are joint_states in degrees or not
00103         This is a blocking method.
00104         """
00105         if angle_degrees:
00106             joint_states.update((joint, radians(i))
00107                                 for joint, i in joint_states.items())
00108         self._move_group_commander.set_start_state_to_current_state()
00109         self._move_group_commander.set_joint_value_target(joint_states)
00110         self.__plan = self._move_group_commander.plan()
00111 
00112     def move_to_named_target(self, name, wait=True):
00113         """
00114         Set target of the robot's links and moves to it
00115         @param name - name of the target pose defined in SRDF
00116         @param wait - should method wait for movement end or not
00117         """
00118         self._move_group_commander.set_start_state_to_current_state()
00119         self._move_group_commander.set_named_target(name)
00120         self._move_group_commander.go(wait=wait)
00121 
00122     def plan_to_named_target(self, name):
00123         """
00124         Set target of the robot's links and plans
00125         This is a blocking method.
00126         @param name - name of the target pose defined in SRDF
00127         """
00128         self._move_group_commander.set_start_state_to_current_state()
00129         self._move_group_commander.set_named_target(name)
00130         self.__plan = self._move_group_commander.plan()
00131 
00132     def get_joints_position(self):
00133         """
00134         Returns joints position
00135         @return - dictionary with joints positions
00136         """
00137         with self._joint_states_lock:
00138             return self._joints_position
00139 
00140     def get_joints_velocity(self):
00141         """
00142         Returns joints velocities
00143         @return - dictionary with joints velocities
00144         """
00145         with self._joint_states_lock:
00146             return self._joints_velocity
00147 
00148     def _get_joints_effort(self):
00149         """
00150         Returns joints effort
00151         @return - dictionary with joints efforts
00152         """
00153         with self._joint_states_lock:
00154             return self._joints_effort
00155 
00156     def run_joint_trajectory(self, joint_trajectory):
00157         """
00158         Moves robot through all joint states with specified timeouts
00159         @param joint_trajectory - JointTrajectory class object. Represents
00160         trajectory of the joints which would be executed.
00161         """
00162         plan = RobotTrajectory()
00163         plan.joint_trajectory = joint_trajectory
00164         self._move_group_commander.execute(plan)
00165 
00166     def _move_to_position_target(self, xyz, end_effector_link="", wait=True):
00167         """
00168         Specify a target position for the end-effector and moves to it
00169         @param xyz - new position of end-effector
00170         @param end_effector_link - name of the end effector link
00171         @param wait - should method wait for movement end or not
00172         """
00173         self._move_group_commander.set_start_state_to_current_state()
00174         self._move_group_commander.set_position_target(xyz, end_effector_link)
00175         self._move_group_commander.go(wait=wait)
00176 
00177     def _plan_to_position_target(self, xyz, end_effector_link=""):
00178         """
00179         Specify a target position for the end-effector and plans.
00180         This is a blocking method.
00181         @param xyz - new position of end-effector
00182         @param end_effector_link - name of the end effector link
00183         """
00184         self._move_group_commander.set_start_state_to_current_state()
00185         self._move_group_commander.set_position_target(xyz, end_effector_link)
00186         self.__plan = self._move_group_commander.plan()
00187 
00188     def _move_to_pose_target(self, pose, end_effector_link="", wait=True):
00189         """
00190         Specify a target pose for the end-effector and moves to it
00191         @param pose - new pose of end-effector: a Pose message, a PoseStamped
00192         message or a list of 6 floats: [x, y, z, rot_x, rot_y, rot_z] or a list
00193         of 7 floats [x, y, z, qx, qy, qz, qw]
00194         @param end_effector_link - name of the end effector link
00195         @param wait - should method wait for movement end or not
00196         """
00197         self._move_group_commander.set_start_state_to_current_state()
00198         self._move_group_commander.set_pose_target(pose, end_effector_link)
00199         self._move_group_commander.go(wait=wait)
00200 
00201     def _plan_to_pose_target(self, pose, end_effector_link=""):
00202         """
00203         Specify a target pose for the end-effector and plans.
00204         This is a blocking method.
00205         @param pose - new pose of end-effector: a Pose message, a PoseStamped
00206         message or a list of 6 floats: [x, y, z, rot_x, rot_y, rot_z] or a list
00207         of 7 floats [x, y, z, qx, qy, qz, qw]
00208         @param end_effector_link - name of the end effector link
00209         """
00210         self._move_group_commander.set_start_state_to_current_state()
00211         self._move_group_commander.set_pose_target(pose, end_effector_link)
00212         self.__plan = self._move_group_commander.plan()
00213 
00214     def _joint_states_callback(self, joint_state):
00215         """
00216         The callback function for the topic joint_states.
00217         It will store the received joint position, velocity and efforts
00218         information into dictionaries
00219         @param joint_state - the message containing the joints data.
00220         """
00221         with self._joint_states_lock:
00222             self._joints_position = {n: p for n, p in
00223                                      zip(joint_state.name,
00224                                          joint_state.position)}
00225             self._joints_velocity = {n: v for n, v in
00226                                      zip(joint_state.name,
00227                                          joint_state.velocity)}
00228             self._joints_effort = {n: v for n, v in
00229                                    zip(joint_state.name, joint_state.effort)}
00230 
00231     def _set_up_action_client(self):
00232         """
00233         Sets up an action client to communicate with the trajectory controller
00234         """
00235         self._client = SimpleActionClient(
00236             self._prefix + "trajectory_controller/follow_joint_trajectory",
00237             FollowJointTrajectoryAction
00238         )
00239 
00240         if self._client.wait_for_server(timeout=rospy.Duration(4)) is False:
00241             rospy.logfatal("Failed to connect to action server in 4 sec")
00242             raise
00243 
00244     def move_to_joint_value_target_unsafe(self, joint_states, time=0.002,
00245                                           wait=True, angle_degrees=False):
00246         """
00247         Set target of the robot's links and moves to it.
00248         @param joint_states - dictionary with joint name and value. It can
00249         contain only joints values of which need to be changed.
00250         @param time - time in s (counting from now) for the robot to reach the
00251         target (it needs to be greater than 0.0 for it not to be rejected by
00252         the trajectory controller)
00253         @param wait - should method wait for movement end or not
00254         @param angle_degrees - are joint_states in degrees or not
00255         """
00256         # self._update_default_trajectory()
00257         # self._set_targets_to_default_trajectory(joint_states)
00258         if angle_degrees:
00259             joint_states.update((joint, radians(i))
00260                                 for joint, i in joint_states.items())
00261         goal = FollowJointTrajectoryGoal()
00262         goal.trajectory.joint_names = list(joint_states.keys())
00263         point = JointTrajectoryPoint()
00264         point.time_from_start = rospy.Duration.from_sec(time)
00265         for key in goal.trajectory.joint_names:
00266             point.positions.append(joint_states[key])
00267 
00268         goal.trajectory.points = []
00269         goal.trajectory.points.append(point)
00270 
00271         self._client.send_goal(goal)
00272 
00273         if not wait:
00274             return
00275 
00276         if not self._client.wait_for_result():
00277             rospy.loginfo("Trajectory not completed")
00278 
00279     def run_joint_trajectory_unsafe(self, joint_trajectory, wait=True):
00280         """
00281         Moves robot through all joint states with specified timeouts
00282         @param joint_trajectory - JointTrajectory class object. Represents
00283         trajectory of the joints which would be executed.
00284         @param wait - should method wait for movement end or not
00285         """
00286         goal = FollowJointTrajectoryGoal()
00287         goal.trajectory = joint_trajectory
00288         self._client.send_goal(goal)
00289 
00290         if not wait:
00291             return
00292 
00293         if not self._client.wait_for_result():
00294             rospy.loginfo("Trajectory not completed")
00295 
00296     def set_teach_mode(self, teach):
00297         """
00298         Activates/deactivates the teach mode for the robot.
00299         Activation: stops the the trajectory controllers for the robot, and
00300         sets it to teach mode.
00301         Deactivation: stops the teach mode and starts trajectory controllers
00302         for the robot.
00303         Currently this method blocks for a few seconds when called on a hand,
00304         while the hand parameters are reloaded.
00305         @param teach - bool to activate or deactivate teach mode
00306         """
00307 
00308         if teach:
00309             mode = RobotTeachModeRequest.TEACH_MODE
00310         else:
00311             mode = RobotTeachModeRequest.TRAJECTORY_MODE
00312         self.change_teach_mode(mode, self._name)
00313 
00314     @staticmethod
00315     def change_teach_mode(mode, robot):
00316         teach_mode_client = rospy.ServiceProxy('/teach_mode', RobotTeachMode)
00317 
00318         req = RobotTeachModeRequest()
00319         req.teach_mode = mode
00320         req.robot = robot
00321         try:
00322             resp = teach_mode_client(req)
00323             if resp.result == RobotTeachModeResponse.ERROR:
00324                 rospy.logerr("Failed to change robot %s to mode %d", robot,
00325                              mode)
00326             else:
00327                 rospy.loginfo("Changed robot %s to mode %d Result = %d", robot,
00328                               mode, resp.result)
00329         except rospy.ServiceException:
00330             rospy.logerr("Failed to call service teach_mode")


sr_robot_commander
Author(s): Andriy Petlovanyy
autogenerated on Fri Aug 21 2015 12:26:35