00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
00257
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")