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
00034
00035 from geometry_msgs.msg import Pose, PoseStamped
00036 from sensor_msgs.msg import JointState
00037 import rospy
00038 import tf
00039 from moveit_ros_planning_interface import _moveit_move_group_interface
00040 from exception import MoveItCommanderException
00041 import conversions
00042
00043 class MoveGroupCommander(object):
00044 """
00045 Execution of simple commands for a particular group
00046 """
00047
00048 def __init__(self, name):
00049 """ Specify the group name for which to construct this commander instance. Throws an exception if there is an initialization error. """
00050 self._g = _moveit_move_group_interface.MoveGroup(name, "robot_description")
00051
00052 def get_name(self):
00053 """ Get the name of the group this instance was initialized for """
00054 return self._g.get_name()
00055
00056 def stop(self):
00057 """ Stop the current execution, if any """
00058 self._g.stop()
00059
00060 def get_joints(self):
00061 """ Get the joints of this group """
00062 return self._g.get_joints()
00063
00064 def get_variable_count(self):
00065 """ Return the number of variables used to parameterize a state in this group (larger or equal to number of DOF)"""
00066 return self._g.get_variable_count()
00067
00068 def has_end_effector_link(self):
00069 """ Check if this group has a link that is considered to be an end effector """
00070 return len(self._g.get_end_effector_link()) > 0
00071
00072 def get_end_effector_link(self):
00073 """ Get the name of the link that is considered to be an end-effector. Return an empty string if there is no end-effector. """
00074 return self._g.get_end_effector_link()
00075
00076 def set_end_effector_link(self, link_name):
00077 """ Set the name of the link to be considered as an end effector """
00078 if not self._g.set_end_effector_link(link_name):
00079 raise MoveItCommanderException("Unable to set end efector link")
00080
00081 def get_pose_reference_frame(self):
00082 """ Get the reference frame assumed for poses of end-effectors """
00083 return self._g.get_pose_reference_frame()
00084
00085 def set_pose_reference_frame(self, reference_frame):
00086 """ Set the reference frame to assume for poses of end-effectors """
00087 self._g.set_pose_reference_frame(reference_frame)
00088
00089 def get_planning_frame(self):
00090 """ Get the name of the frame where all planning is performed """
00091 return self._g.get_planning_frame()
00092
00093 def get_current_joint_values(self):
00094 """ Get the current configuration of the group (as published on JointState) """
00095 return self._g.get_current_joint_values()
00096
00097 def get_current_pose(self, end_effector_link = ""):
00098 """ Get the current pose of the end-effector of the group. Throws an exception if there is not end-effector. """
00099 if len(end_effector_link) > 0 or self.has_end_effector_link():
00100 return conversions.list_to_pose_stamped(self._g.get_current_pose(end_effector_link), self.get_planning_frame())
00101 else:
00102 raise MoveItCommanderException("There is no end effector to get the pose of")
00103
00104 def get_current_rpy(self, end_effector_link = ""):
00105 """ Get a list of 3 elements defining the [roll, pitch, yaw] of the end-effector. Throws an exception if there is not end-effector. """
00106 if len(end_effector_link) > 0 or self.has_end_effector_link():
00107 return self._g.get_current_rpy(end_effector_link)
00108 else:
00109 raise MoveItCommanderException("There is no end effector to get the rpy of")
00110
00111 def get_random_joint_values(self):
00112 return self._g.get_random_joint_values()
00113
00114 def get_random_pose(self, end_effector_link = ""):
00115 if len(end_effector_link) > 0 or self.has_end_effector_link():
00116 return conversions.list_to_pose_stamped(self._g.get_random_pose(end_effector_link), self.get_planning_frame())
00117 else:
00118 raise MoveItCommanderException("There is no end effector to get the pose of")
00119
00120 def set_joint_value_target(self, name, value = None):
00121 """ Specify a target joint configuration for the group."""
00122 if value == None:
00123 value = name
00124 if not self._g.set_joint_value_target(value):
00125 raise MoveItCommanderException("Error setting joint target. Is the target within bounds?")
00126 else:
00127 if not self._g.set_joint_value_target(name, value):
00128 raise MoveItCommanderException("Error setting joint target. Is the target within bounds?")
00129
00130 def set_rpy_target(self, rpy, end_effector_link = ""):
00131 """ Specify a target orientation for the end-effector. Any position of the end-effector is acceptable."""
00132 if len(end_effector_link) > 0 or self.has_end_effector_link():
00133 if len(rpy) == 3:
00134 if not self._g.set_rpy_target(rpy[0], rpy[1], rpy[2], end_effector_link):
00135 raise MoveItCommanderException("Unable to set orientation target")
00136 else:
00137 raise MoveItCommanderException("Expected [roll, pitch, yaw]")
00138 else:
00139 raise MoveItCommanderException("There is no end effector to set the pose for")
00140
00141 def set_orientation_target(self, q, end_effector_link = ""):
00142 """ Specify a target orientation for the end-effector. Any position of the end-effector is acceptable."""
00143 if len(end_effector_link) > 0 or self.has_end_effector_link():
00144 if len(q) == 4:
00145 if not self._g.set_orientation_target(q[0], q[1], q[2], q[3], end_effector_link):
00146 raise MoveItCommanderException("Unable to set orientation target")
00147 else:
00148 raise MoveItCommanderException("Expected [qx, qy, qz, qw]")
00149 else:
00150 raise MoveItCommanderException("There is no end effector to set the pose for")
00151
00152 def set_position_target(self, xyz, end_effector_link = ""):
00153 """ Specify a target position for the end-effector. Any orientation of the end-effector is acceptable."""
00154 if len(end_effector_link) > 0 or self.has_end_effector_link():
00155 if not self._g.set_position_target(xyz[0], xyz[1], xyz[2], end_effector_link):
00156 raise MoveItCommanderException("Unable to set position target")
00157 else:
00158 raise MoveItCommanderException("There is no end effector to set the pose for")
00159
00160 def set_pose_target(self, pose, end_effector_link = ""):
00161 """ Set the pose of the end-effector, if one is available. The expected input is a Pose message, a PoseStamped message or a list of 6 floats:"""
00162 """ [x, y, z, rot_x, rot_y, rot_z] or a list of 7 floats [x, y, z, qx, qy, qz, qw] """
00163 if len(end_effector_link) > 0 or self.has_end_effector_link():
00164 ok = False
00165 if type(pose) is PoseStamped:
00166 old = self.get_pose_reference_frame()
00167 self.set_pose_reference_frame(pose.header.frame_id)
00168 ok = self._g.set_pose_target(conversions.pose_to_list(pose.pose), end_effector_link)
00169 self.set_pose_reference_frame(old)
00170 elif type(pose) is Pose:
00171 ok = self._g.set_pose_target(conversions.pose_to_list(pose), end_effector_link)
00172 else:
00173 ok = self._g.set_pose_target(pose, end_effector_link)
00174 if not ok:
00175 raise MoveItCommanderException("Unable to set target pose")
00176 else:
00177 raise MoveItCommanderException("There is no end effector to set the pose for")
00178
00179 def set_pose_targets(self, poses, end_effector_link = ""):
00180 """ Set the pose of the end-effector, if one is available. The expected input is a list of poses. Each pose can be a Pose message, a list of 6 floats: [x, y, z, rot_x, rot_y, rot_z] or a list of 7 floats [x, y, z, qx, qy, qz, qw] """
00181 if len(end_effector_link) > 0 or self.has_end_effector_link():
00182 if not self._g.set_pose_targets([conversions.pose_to_list(p) if type(p) is Pose else p for p in poses], end_effector_link):
00183 raise MoveItCommanderException("Unable to set target poses")
00184 else:
00185 raise MoveItCommanderException("There is no end effector to set poses for")
00186
00187 def shift_pose_target(self, axis, value, end_effector_link = ""):
00188 """ Get the current pose of the end effector, add value to the corresponding axis (0..5: X, Y, Z, R, P, Y) and set the new pose as the pose target """
00189 if len(end_effector_link) > 0 or self.has_end_effector_link():
00190 pose = self._g.get_current_pose(end_effector_link)
00191
00192
00193 if axis > 2:
00194 (r, p, y) = tf.transformations.euler_from_quaternion(pose[3:])
00195 pose = [pose[0], pose[1], pose[2], r, p, y]
00196 if axis >= 0 and axis < 6:
00197 pose[axis] = pose[axis] + value
00198 self.set_pose_target(pose, end_effector_link)
00199 else:
00200 raise MoveItCommanderException("An axis value between 0 and 5 expected")
00201 else:
00202 raise MoveItCommanderException("There is no end effector to set poses for")
00203
00204 def clear_pose_target(self, end_effector_link):
00205 """ Clear the pose target for a particular end-effector """
00206 self._g.clear_pose_target(end_effector_link)
00207
00208 def clear_pose_targets(self):
00209 """ Clear all known pose targets """
00210 self._g.clear_pose_targets()
00211
00212 def set_random_target(self):
00213 """ Set a random joint configuration target """
00214 self._g.set_random_target()
00215
00216 def set_named_target(self, name):
00217 """ Set a joint configuration by name. The name can be a name previlusy remembered with remember_joint_values() or a configuration specified in the SRDF. """
00218 if not self._g.set_named_target(name):
00219 raise MoveItCommanderException("Unable to set target %s. Is the target within bounds?" % name)
00220
00221 def remember_joint_values(self, name, values = None):
00222 """ Record the specified joint configuration of the group under the specified name. If no values are specified, the current state of the group is recorded. """
00223 if values == None:
00224 values = self.get_current_joint_values()
00225 self._g.remember_joint_values(name, values)
00226
00227 def get_remembered_joint_values(self):
00228 """ Get a dictionary that maps names to joint configurations for the group """
00229 return self._g.get_remembered_joint_values()
00230
00231 def forget_joint_values(self, name):
00232 """ Forget a stored joint configuration """
00233 self._g.forget_joint_values(name)
00234
00235 def get_goal_tolerance(self):
00236 """ Return a tuple of goal tolerances: joint, position and orientation. """
00237 return (self.get_goal_joint_tolerance(), self.get_goal_position_tolerance(), self.get_goal_orientation_tolerance())
00238
00239 def get_goal_joint_tolerance(self):
00240 """ Get the tolerance for achieving a joint goal (distance for each joint variable) """
00241 return self._g.get_goal_joint_tolerance()
00242
00243 def get_goal_position_tolerance(self):
00244 """ When moving to a position goal or to a pose goal, the tolerance for the goal position is specified as the radius a sphere around the target origin of the end-effector """
00245 return self._g.get_goal_position_tolerance()
00246
00247 def get_goal_orientation_tolerance(self):
00248 """ When moving to an orientation goal or to a pose goal, the tolerance for the goal orientation is specified as the distance (roll, pitch, yaw) to the target origin of the end-effector """
00249 return self._g.get_goal_orientation_tolerance()
00250
00251 def set_goal_tolerance(self, value):
00252 """ Set the joint, position and orientation goal tolerances simultaneously """
00253 self._g.set_goal_tolerance(value)
00254
00255 def set_goal_joint_tolerance(self, value):
00256 """ Set the tolerance for a target joint configuration """
00257 self._g.set_goal_joint_tolerance(value)
00258
00259 def set_goal_position_tolerance(self, value):
00260 """ Set the tolerance for a target end-effector position """
00261 self._g.set_goal_position_tolerance(value)
00262
00263 def set_goal_orientation_tolerance(self, value):
00264 """ Set the tolerance for a target end-effector orientation """
00265 self._g.set_goal_orientation_tolerance(value)
00266
00267 def allow_looking(self, value):
00268 """ Enable/disable looking around for motion planning """
00269 self._g.allow_looking(value)
00270
00271 def allow_replanning(self, value):
00272 """ Enable/disable replanning """
00273 self._g.allow_replanning(value)
00274
00275 def get_known_constraints(self):
00276 """ Get a list of names for the constraints specific for this group, as read from the warehouse """
00277 return self._g.get_known_constraints()
00278
00279 def set_path_constraints(self, value):
00280 """ Specify the path constraints to be used (as read from the database) """
00281 if value == None:
00282 self.clear_path_constraints()
00283 else:
00284 if not self._g.set_path_constraints(value):
00285 raise MoveItCommanderException("Unable to set path constraints " + value)
00286
00287 def clear_path_constraints(self):
00288 """ Specify that no path constraints are to be used during motion planning """
00289 self._g.clear_path_constraints()
00290
00291 def set_constraints_database(self, host, port):
00292 """ Specify which database to connect to for loading possible path constraints """
00293 self._g.set_constraints_database(host, port)
00294
00295 def set_planning_time(self, seconds):
00296 """ Specify the amount of time to be used for motion planning. """
00297 self._g.set_planning_time(seconds)
00298
00299 def get_planning_time(self):
00300 """ Specify the amount of time to be used for motion planning. """
00301 return self._g.get_planning_time()
00302
00303 def set_planner_id(self, planner_id):
00304 """ Specify which planner to use when motion planning """
00305 self._g.set_planner_id(planner_id)
00306
00307 def set_workspace(self, ws):
00308 """ Set the workspace for the robot as either [], [minX, minY, maxX, maxY] or [minX, minY, minZ, maxX, maxY, maxZ] """
00309 if len(ws) == 0:
00310 self._g.set_workspace(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
00311 else:
00312 if len(ws) == 4:
00313 self._g.set_workspace(ws[0], ws[1], 0.0, ws[2], ws[3], 0.0)
00314 else:
00315 if len(ws) == 6:
00316 self._g.set_workspace(ws[0], ws[1], ws[2], ws[3], ws[4], ws[5])
00317 else:
00318 raise MoveItCommanderException("Expected 0, 4 or 6 values in list specifying workspace")
00319
00320 def go(self, joints = None, wait = True):
00321 """ Set the target of the group and then move the group to the specified target """
00322 if type(joints) is bool:
00323 wait = joints
00324 joints = None
00325
00326 elif type(joints) is JointState:
00327 self.set_joint_value_target(joints.position)
00328
00329 elif type(joints) is Pose:
00330 self.set_pose_target(joints)
00331
00332 elif not joints == None:
00333 try:
00334 self.set_joint_value_target(self.get_remembered_joint_values()[joints])
00335 except:
00336 self.set_joint_value_target(joints)
00337 if wait:
00338 return self._g.move()
00339 else:
00340 return self._g.async_move()
00341
00342 def plan(self, joints = None):
00343 """ Return a motion plan (a RobotTrajectory) to the set goal state (or specified by the joints argument) """
00344 if type(joints) is JointState:
00345 self.set_joint_value_target(joints.position)
00346
00347 elif type(joints) is Pose:
00348 self.set_pose_target(joints)
00349
00350 elif not joints == None:
00351 try:
00352 self.set_joint_value_target(self.get_remembered_joint_values()[joints])
00353 except:
00354 self.set_joint_value_target(joints)
00355 plan = self._g.compute_plan()
00356 return conversions.dict_to_trajectory(plan)
00357
00358 def compute_cartesian_path(self, waypoints, eef_step, jump_threshold, avoid_collisions = True):
00359 """ Compute a sequence of waypoints that make the end-effector move in straight line segments that follow the poses specified as waypoints. Configurations are computed for every eef_step meters; The jump_threshold specifies the maximum distance in configuration space between consecutive points in the resultingpath. The return value is a tuple: a fraction of how much of the path was followed, the actual RobotTrajectory. """
00360 (dpath, fraction) = self._g.compute_cartesian_path([conversions.pose_to_list(p) for p in waypoints], eef_step, jump_threshold, avoid_collisions)
00361 return (conversions.dict_to_trajectory(dpath), fraction)
00362
00363 def execute(self, plan_msg):
00364 """Execute a previously planned path"""
00365 return self._g.execute(conversions.trajectory_to_dict(plan_msg))
00366
00367 def pick(self, object_name):
00368 """Pick the named object"""
00369 return self._g.pick(object_name)
00370
00371 def place(self, object_name, pose):
00372 """Place the named object at a particular location in the environment"""
00373 result = False
00374 if type(pose) is PoseStamped:
00375 old = self.get_pose_reference_frame()
00376 self.set_pose_reference_frame(pose.header.frame_id)
00377 result = self._g.place(object_name, conversions.pose_to_list(pose.pose))
00378 self.set_pose_reference_frame(old)
00379 else:
00380 result = self._g.place(object_name, conversions.pose_to_list(pose))
00381 return result