pick_place_interface.py
Go to the documentation of this file.
1 # Copyright 2015, Fetch Robotics Inc
2 # Copyright 2011-2014, Michael Ferguson
3 # All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
7 # are met:
8 #
9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following
13 # disclaimer in the documentation and/or other materials provided
14 # with the distribution.
15 #
16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 # POSSIBILITY OF SUCH DAMAGE.
28 
29 import rospy
30 import actionlib
31 from moveit_msgs.msg import MoveItErrorCodes
32 from moveit_msgs.msg import PickupAction, PickupGoal, PlaceAction, PlaceGoal
33 
34 ## @brief Simple interface to pick and place actions
35 class PickPlaceInterface(object):
36 
37  ## @brief Create a grasp manager, connect actions
38  ## @param group Name of arm planning group
39  ## @param ee_group Name of end effector planning group
40  ## @param plan_only Should we only plan, but not execute?
41  def __init__(self,
42  group="arm",
43  ee_group="gripper",
44  plan_only=False,
45  verbose=False):
46  self._verbose = verbose
47  self._group = group
48  self._effector = ee_group
49  if self._verbose:
50  rospy.loginfo("Connecting to pickup action...")
52  PickupAction)
53  self._pick_action.wait_for_server()
54  if self._verbose:
55  rospy.loginfo("...connected")
56  rospy.loginfo("Connecting to place action...")
58  PlaceAction)
59  self._place_action.wait_for_server()
60  if self._verbose:
61  rospy.loginfo("...connected")
62  self._plan_only = plan_only
63  self.planner_id = None
65 
66  def get_pick_action(self):
67  return self._pick_action
68 
69  def get_place_action(self):
70  return self._place_action
71 
72  ## @brief Plan and grasp something
73  ## @param name Name of the object to grasp
74  ## @param grasps Grasps to try (moveit_msgs/Grasp)
75  ## @param support_name Name of the support surface
76  ## @returns moveit_msgs/PickupResult
77  def pickup(self, name, grasps, wait=True, **kwargs):
78  # Check arguments
79  supported_args = ("allow_gripper_support_collision",
80  "allowed_touch_objects",
81  "plan_only",
82  "planner_id",
83  "planning_scene_diff",
84  "planning_time",
85  "support_name")
86  for arg in kwargs.keys():
87  if not arg in supported_args:
88  rospy.loginfo("pickup: unsupported argument: %s", arg)
89 
90  # Create goal
91  g = PickupGoal()
92 
93  # 1. Fill in target name
94  g.target_name = name
95 
96  # 2. Fill in group name
97  g.group_name = self._group
98 
99  # 3. Fill in end effector
100  g.end_effector = self._effector
101 
102  # 4. List of grasps
103  g.possible_grasps = grasps
104 
105  # 5. Fill in support surface
106  try:
107  g.support_surface_name = kwargs["support_name"]
108  except KeyError:
109  g.support_surface_name = ""
110 
111  # 6. Can gripper contact the support surface (named above)
112  try:
113  g.allow_gripper_support_collision = kwargs["allow_gripper_support_collision"]
114  except KeyError:
115  g.allow_gripper_support_collision = True
116 
117  # 7. What links are part of the "gripper" (and can contact the object/surface)
118  try:
119  g.attached_object_touch_links = kwargs["attached_object_touch_links"]
120  except KeyError:
121  g.attached_object_touch_links = list() # empty list = use all links of end-effector
122 
123  # 8. Fill in minimize_object_distance
124 
125  # 9. Fill in path_constraints
126 
127  # 10. Fill in planner id
128  try:
129  g.planner_id = kwargs["planner_id"]
130  except KeyError:
131  if self.planner_id:
132  g.planner_id = self.planner_id
133 
134  # 11. List of obstacles that we are allowed to touch
135  try:
136  g.allowed_touch_objects = kwargs["allowed_touch_objects"]
137  except KeyError:
138  g.allowed_touch_objects = list()
139 
140  # 12. Planning time
141  try:
142  g.allowed_planning_time = kwargs["planning_time"]
143  except KeyError:
144  g.allowed_planning_time = self.allowed_planning_time
145 
146  # 13. Planning options
147  try:
148  g.planning_options.planning_scene_diff = kwargs["planning_scene_diff"]
149  except KeyError:
150  g.planning_options.planning_scene_diff.is_diff = True
151  g.planning_options.planning_scene_diff.robot_state.is_diff = True
152  g.planning_options.plan_only = self._plan_only
153 
154  self._pick_action.send_goal(g)
155  if wait:
156  self._pick_action.wait_for_result()
157  return self._pick_action.get_result()
158  else:
159  return None
160 
161  ## @brief Plan and grasp something
162  ## @param name Name of the object to grasp
163  ## @param grasps Grasps to try (moveit_msgs/Grasp)
164  ## @param support_name Name of the support surface
165  ## @param goal_is_eef Set to true if the place goal is for the
166  ## end effector frame, default is object frame.
167  ## @returns moveit_msgs/PlaceResult
168  def place(self, name, locations, wait=True, **kwargs):
169  # Check arguments
170  supported_args = ("allow_gripper_support_collision",
171  "allowed_touch_objects",
172  "goal_is_eef",
173  "plan_only",
174  "planner_id",
175  "planning_scene_diff",
176  "planning_time",
177  "support_name")
178  for arg in kwargs.keys():
179  if not arg in supported_args:
180  rospy.loginfo("place: unsupported argument: %s", arg)
181 
182  # Create goal
183  g = PlaceGoal()
184 
185  # 1. Name of ARM planning group
186  g.group_name = self._group
187 
188  # 2. Name of attached object to place
189  g.attached_object_name = name
190 
191  # 3. Possible locations to place
192  g.place_locations = locations
193 
194  # 4. If true, using eef pose (same as pick)
195  try:
196  g.place_eef = kwargs["goal_is_eef"]
197  except KeyError:
198  g.place_eef = False
199 
200  # 5. Fill in support surface
201  try:
202  g.support_surface_name = kwargs["support_name"]
203  except KeyError:
204  g.support_surface_name = ""
205 
206  # 6. Can gripper contact the support surface (named above)
207  try:
208  g.allow_gripper_support_collision = kwargs["allow_gripper_support_collision"]
209  except KeyError:
210  g.allow_gripper_support_collision = True
211 
212  # 8. Fill in path_constraints
213 
214  # 9. Fill in planner id
215  try:
216  g.planner_id = kwargs["planner_id"]
217  except KeyError:
218  if self.planner_id:
219  g.planner_id = self.planner_id
220 
221  # 10. List of obstacles that we are allowed to touch
222  try:
223  g.allowed_touch_objects = kwargs["allowed_touch_objects"]
224  except KeyError:
225  g.allowed_touch_objects = list()
226 
227  # 11. Planning time
228  try:
229  g.allowed_planning_time = kwargs["planning_time"]
230  except KeyError:
231  g.allowed_planning_time = self.allowed_planning_time
232 
233  # 12. Planning options
234  try:
235  g.planning_options.planning_scene_diff = kwargs["planning_scene_diff"]
236  except KeyError:
237  g.planning_options.planning_scene_diff.is_diff = True
238  g.planning_options.planning_scene_diff.robot_state.is_diff = True
239  g.planning_options.plan_only = self._plan_only
240 
241  self._place_action.send_goal(g)
242  if wait:
243  self._place_action.wait_for_result()
244  return self._place_action.get_result()
245  else:
246  return None
247 
248  ## Common usage pattern
249  ## TODO document
250  def pick_with_retry(self, name, grasps, retries=5, scene=None, **kwargs):
251  if self._verbose:
252  rospy.loginfo("Beginning to pick.")
253  while retries > 0:
254  retries += -1
255  pick_result = self.pickup(name, grasps, **kwargs)
256  if pick_result.error_code.val == MoveItErrorCodes.SUCCESS:
257  rospy.loginfo("Pick succeeded")
258  return [True, pick_result]
259  elif pick_result.error_code.val == MoveItErrorCodes.PLANNING_FAILED:
260  rospy.logerr("Pick failed in the planning stage, try again...")
261  rospy.sleep(0.5) # short sleep to try and let state settle a bit?
262  continue
263  elif scene and \
264  pick_result.error_code.val == MoveItErrorCodes.CONTROL_FAILED or \
265  pick_result.error_code.val == MoveItErrorCodes.MOTION_PLAN_INVALIDATED_BY_ENVIRONMENT_CHANGE or \
266  pick_result.error_code.val == MoveItErrorCodes.TIMED_OUT:
267  rospy.logerr("Pick failed during execution, attempting to cleanup.")
268  if name in scene.getKnownAttachedObjects():
269  rospy.loginfo("Pick managed to grab object, retreat must have failed, continuing anyways")
270  return [True, pick_result]
271  else:
272  rospy.loginfo("Pick did not grab object, try again...")
273  continue
274  else:
275  rospy.logerr("Pick failed with error code: %d. Will retry...",
276  pick_result.error_code.val)
277  continue
278  rospy.logerr("Pick failed, and all retries are used")
279  return [False, pick_result]
280 
281  ## Common usage pattern
282  ## TODO document
283  def place_with_retry(self,
284  name,
285  locations,
286  retries=5,
287  scene=None,
288  **kwargs):
289  if self._verbose:
290  rospy.loginfo("Beginning to place.")
291  while retries > 0:
292  retries += -1
293  place_result = self.place(name, locations, **kwargs)
294  if place_result.error_code.val == MoveItErrorCodes.SUCCESS:
295  rospy.loginfo("Place succeeded")
296  return [True, place_result]
297  elif place_result.error_code.val == MoveItErrorCodes.PLANNING_FAILED:
298  rospy.logerr("Place failed in planning stage, try again...")
299  rospy.sleep(0.5) # short sleep to let state settle a bit?
300  continue
301  elif scene and \
302  place_result.error_code.val == MoveItErrorCodes.CONTROL_FAILED or \
303  place_result.error_code.val == MoveItErrorCodes.MOTION_PLAN_INVALIDATED_BY_ENVIRONMENT_CHANGE or \
304  place_result.error_code.val == MoveItErrorCodes.TIMED_OUT:
305  rospy.logerr("Place failed during execution, attempting to cleanup.")
306  if name in scene.getKnownAttachedObjects():
307  rospy.loginfo("Place did not place object, approach must have failed, will retry...")
308  continue
309  else:
310  rospy.loginfo("Object no longer in gripper, must be placed, continuing...")
311  return [True, place_result]
312  else:
313  rospy.logerr("Place failed with error code: %d. Will retry...",
314  place_result.error_code.val)
315  continue
316  rospy.logerr("Place failed, and all retries are used")
317  return [False, place_result]
def pickup(self, name, grasps, wait=True, kwargs)
Plan and grasp something.
def place_with_retry(self, name, locations, retries=5, scene=None, kwargs)
Common usage pattern TODO document.
def pick_with_retry(self, name, grasps, retries=5, scene=None, kwargs)
Common usage pattern TODO document.
def place(self, name, locations, wait=True, kwargs)
Plan and grasp something.
def __init__(self, group="arm", ee_group="gripper", plan_only=False, verbose=False)
Create a grasp manager, connect actions.
Simple interface to pick and place actions.


moveit_python
Author(s): Michael Ferguson
autogenerated on Wed Jun 5 2019 21:51:17