simple_arm_tasks.py
Go to the documentation of this file.
00001 #! /usr/bin/env python
00002 
00003 import roslib; roslib.load_manifest('tidyup_arm_services')
00004 import rospy
00005 import actionlib
00006 
00007 import sys, traceback, math, copy
00008 import std_srvs
00009 from tidyup_msgs import msg
00010 from tidyup_msgs import srv
00011 from pr2_tasks.arm_tasks import ArmTasks
00012 from arm_navigation_msgs.msg import ArmNavigationErrorCodes
00013 from geometry_msgs.msg import PoseStamped, Quaternion, Point, Pose
00014 from arm_navigation_msgs.msg import CollisionObject, AttachedCollisionObject, CollisionOperation
00015 from pr2_python import exceptions
00016 import pr2_python.geometry_tools as gt
00017 from pr2_python.hand_description import HandDescription
00018 from tidyup_arm_services.find_free_space import free_spots_on_table
00019 from pr2_python.exceptions import ManipulationError, AllYourBasePosesAreBelongToUs, ActionFailedError
00020 from pr2_python.planning_scene_interface import PlanningSceneInterface, get_planning_scene_interface
00021 from pr2_python.arm_planner import ArmPlanner
00022 from pr2_tasks.pickplace import PickPlace, get_wrist_pose_from_grasp, PickupResult
00023 from pr2_tasks.pickplace_definitions import PlaceGoal, PickupGoal
00024 from pr2_tasks.tableware_detection import TablewareDetection, TablewareDetectionResult
00025 from pr2_tasks.exceptions import DetectionError
00026 from tidyup_arm_services.planning_scene_sync import PlanningSceneSync
00027 from pr2_python import trajectory_tools as tt
00028 from pr2_python import visualization_tools as vt
00029 from pr2_python import head
00030 from visualization_msgs.msg import Marker, MarkerArray
00031 from pr2_python.world_interface import WorldInterface
00032 from hardcoded_facts.geometry_pose_loader import read_table_file
00033 import tf
00034 import numpy as np
00035 import object_manipulation_msgs
00036 import tabletop_object_detector
00037 
00038 DEFAULT_CARRY_JOINT_TRAJECTORY = {'left_arm': [[0.968, 0.129, 0.554, -1.891, 1.786, -1.127, 0.501], 
00039                                               [2.135, -0.02, 1.64, -2.07, 1.64, -1.68, 1.398],
00040                                               [2.110, 1.230, 2.06, -1.69, -0.3, -1.32, 1.57]],
00041                                  'right_arm': [[-0.968, 0.129, -0.554, -1.891, -1.786, -1.127, 0.501],
00042                                                [-2.135, -0.02, -1.64, -2.07, -1.64, -1.68, 1.398],
00043                                                [-2.110, 1.230, -2.06, -1.69, 0.3, -1.32, 1.57]]}
00044 
00045 class SimpleArmTasks():
00046   def __init__(self):
00047     self._detector = TablewareDetection()
00048     self._tasks = ArmTasks()
00049     self._psi = get_planning_scene_interface()
00050     self._wi = self._detector._wi
00051     # reset world interface
00052     self._reset_world_interface()
00053 
00054     self._pick_place = PickPlace()
00055     self._known_objects = dict()
00056     self._known_wipe_goals = dict()
00057     self._head = head.Head()
00058 
00059     # to side
00060     self._side_joint_trajectory = self._tasks.side_joint_trajectory
00061     self._toSideActionServer = actionlib.SimpleActionServer('/tidyup/side_position_action', msg.ArmToSideAction, self._to_side_execute, False)
00062     self._toSideActionServer.start() 
00063     # to carry 
00064     self._carry_joint_trajectory = DEFAULT_CARRY_JOINT_TRAJECTORY
00065 #    for arm in ['left_arm', 'right_arm']:
00066 #      self._carry_joint_trajectory[arm] = rospy.get_param('/arm_configurations/side_carry/trajectory/'+arm, DEFAULT_CARRY_JOINT_TRAJECTORY[arm])
00067     self._toCarryActionServer = actionlib.SimpleActionServer('/tidyup/post_grasp_position_action', msg.PostGraspPositionAction, self._to_carry_execute, False)
00068     self._toCarryActionServer.start()
00069     # detect objects 
00070     self._detectGraspableObjectsService = rospy.Service('/tidyup/detect_objects', srv.DetectGraspableObjects, self._detect_objects_callback)
00071     # graspability
00072     self._requestObjectGraspabilityService = rospy.Service('/tidyup/request_graspability', srv.RequestObjectsGraspability, self._request_graspability_callback)
00073     # pickup
00074     self._pickUpActionServer = actionlib.SimpleActionServer('/tidyup/grasping_action', msg.GraspObjectAction, self._pick_up_execute, False)
00075     self._pickUpActionServer.start() 
00076     # compute putdown pose
00077     self._find_putdown_pose_service = rospy.Service('/tidyup/request_putdown_pose', srv.GetPutdownPose, self._find_putdown_pose_callback)
00078     # putdown 
00079     self._putDownActionServer = actionlib.SimpleActionServer('/tidyup/placing_action', msg.PlaceObjectAction, self._put_down_execute, False)
00080     self._putDownActionServer.start()
00081     # Reset world interface
00082     self._resetWorldInterface = rospy.Service('/tidyup/reset_world_interface', std_srvs.srv.Empty, self._reset_world_interface)
00083     self._attachSponge = rospy.Service('/tidyup/attach_sponge', std_srvs.srv.Empty, self._add_sponge_to_right_gripper)
00084     self._detachSponge = rospy.Service('/tidyup/detach_sponge', std_srvs.srv.Empty, self._add_sponge_to_base)
00085     # debug visualization
00086     self._visualization_publisher = rospy.Publisher('/tidyup/visualization', MarkerArray)
00087     #self._planning_scene_sync = PlanningSceneSync()
00088     rospy.loginfo('tidyup_arm_services: initialized.')
00089  
00090 
00091   def _to_carry_execute(self, goal):
00092     self._psi.reset()
00093     arm_name = 'no_arm'
00094     if goal.right_arm:
00095       arm_name = 'right_arm'
00096     elif goal.left_arm:
00097       arm_name = 'left_arm'
00098     rospy.loginfo('executing: move {0} to carry.'.format(arm_name))
00099     self._tasks.side_joint_trajectory = self._carry_joint_trajectory
00100     self._tasks.move_arm_to_side(arm_name)
00101     self._psi.reset()
00102     self._toCarryActionServer.set_succeeded()
00103 
00104   def _to_side_execute(self, goal):
00105     self._psi.reset()
00106     arm_name = 'no_arm'
00107     if goal.right_arm:
00108       arm_name = 'right_arm'
00109     elif goal.left_arm:
00110       arm_name = 'left_arm'
00111     rospy.loginfo('executing: move {0} to side.'.format(arm_name))
00112     self._tasks.side_joint_trajectory = self._side_joint_trajectory
00113     self._tasks.move_arm_to_side(arm_name)
00114     self._psi.reset()
00115     self._toSideActionServer.set_succeeded()
00116 
00117   def _reset_world_interface(self, request=None):
00118     rospy.loginfo("Resetting world interface")
00119     self._wi.reset(True)
00120     self._known_objects = dict()
00121     self._known_wipe_goals = dict()
00122     self._add_tables_to_wi()
00123     self._add_sponge_to_base()
00124     self._psi.reset()
00125     return {}
00126 
00127   def _pose_to_str(self, pose):
00128       if pose is None:
00129           return "None pose"
00130       (_, _, yaw) = tf.transformations.euler_from_quaternion([pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w])
00131       ps = "position: (%.2f, %.2f, %.2f) - quat: (%.2f, %.2f, %.2f, %.2f) - yaw: %.2f deg" % \
00132       (pose.position.x, pose.position.y, pose.position.z, \
00133           pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w, 180.0/math.pi*yaw)
00134       return ps
00135 
00136   def _point_to_str(self, pt):
00137       ps = "position: (%.2f, %.2f, %.2f)" % \
00138         (pt.x, pt.y, pt.z)
00139       return ps
00140 
00141   def _dump_planning_scene_objects(self, planning_scene=None):
00142       """ Output a condensed printable form of the planning scene.
00143           If the planning_scene is None, the current world scene is retrieved
00144           from the world interface."""
00145       if planning_scene is None:
00146           planning_scene = self._wi.get_planning_scene().planning_scene
00147 
00148       s = "Collision Objects:"
00149       if not planning_scene.collision_objects:
00150           s += "\nNone"
00151       for co in planning_scene.collision_objects:
00152           s += "\nid: %s op: %d frame: %s pose: %s" % (co.id, co.operation.operation, co.header.frame_id, \
00153               self._pose_to_str(co.poses[0]))
00154       s += "\nAttached Collision Objects:"
00155       if not planning_scene.attached_collision_objects:
00156           s += "\nNone"
00157       for aco in planning_scene.attached_collision_objects:
00158           s += "\nid: %s attach_link: %s op: %d frame: %s pose: %s" % (aco.object.id, aco.link_name, \
00159                aco.object.operation.operation, \
00160                aco.object.header.frame_id, self._pose_to_str(aco.object.poses[0]))
00161       rospy.loginfo("Planning Scene Objects:\n%s" % s)
00162 
00163   def _pickup_goal_to_str(self, pg):
00164       if pg is None:
00165           return "Pickup Goal is None"
00166       s = "Pickup Goal for %s (collision_object) on collision_support %s using arm \"%s\".\n" % \
00167           (pg.collision_object_name, pg.collision_support_surface_name, pg.arm_name)
00168       s += "label: %s graspable_object collision name: %s object pose: %s %s\n" % \
00169           (pg.label, pg.target.collision_name, pg.object_pose_stamped.header.frame_id, self._pose_to_str(pg.object_pose_stamped.pose))
00170       if hasattr(pg, 'collision_object_header') and hasattr(pg, 'collision_object_poses'):
00171           s += "collision_object_pose: %s %s" % (pg.collision_object_header.frame_id, self._pose_to_str(pg.collision_object_poses[0]))
00172       else:
00173           s += "no collision_object_pose"
00174       #s += "%d desired grasps" % len(pg.desired_grasps)
00175       return s
00176 
00177   def _place_goal_to_str(self, pg, print_locations=True):
00178       if pg is None:
00179           return "Place Goal is None"
00180       s = "Place Goal for %s (collision_object) on collision_support %s using arm \"%s\"." % \
00181               (pg.collision_object_name, pg.collision_support_surface_name, pg.arm_name)
00182       if print_locations:
00183           s += "\nPlace Locations:"
00184           for loc in pg.place_locations:
00185               s += "\nframe: %s pose: %s" % (loc.header.frame_id, self._pose_to_str(loc.pose))
00186       return s
00187 
00188   def _dump_known_objects(self):
00189       s = ""
00190       if not self._known_objects:
00191           s += " None"
00192       for so, known in self._known_objects.iteritems():
00193           s += "\nOn Static Object %s:" % so
00194           for pg in known.pickup_goals:
00195               s += "\n" + self._pickup_goal_to_str(pg)
00196       rospy.loginfo("Known Objects:%s" % s)
00197 
00198   def _wipe_goal_to_str(self, wg, valid):
00199       if wg is None:
00200           return "Wipe Goal is None"
00201       validity = "validity unknown"
00202       if valid is not None:
00203           if valid:
00204               validity = "valid"
00205           else:
00206               validity = "invalid"
00207       s = "Wipe Goal %s (box_size %s) at %s, %s (%s)." % \
00208               (wg.name, wg.box_size, wg.spot.header.frame_id, self._point_to_str(wg.spot.point), validity)
00209       return s
00210 
00211   def _dump_known_wipe_goals(self):
00212       s = ""
00213       if not self._known_wipe_goals:
00214           s += " None"
00215       for so, wgs in self._known_wipe_goals.iteritems():
00216           s += "\nOn Static Object %s:" % so
00217           for (wg, valid) in wgs:
00218               s += "\n" + self._wipe_goal_to_str(wg, valid)
00219       rospy.loginfo("Known Wipe Goals:%s" % s)
00220 
00221   def _remove_known_objects(self, known):
00222     """ Remove known objects from the world."""
00223     if known:
00224       for pg in known.pickup_goals:
00225         self._wi.remove_collision_object(pg.collision_object_name)
00226 
00227   def _remove_objects_in_fov(self, cur_collision_objects):
00228     """ Remove objects from the world that are in the FOV.
00229         The cur_collision_objects contain the collision objects as they were in
00230         the world right before calling this function."""
00231 
00232     rospy.loginfo("Removing collision objects in FOV for re-detection")
00233     # Also remove all objects that are in the FOV of the robot
00234     # for now, we'll just assume FOV is all objects in a within a radius in front of the robot
00235     fov_point = PoseStamped()
00236     fov_point.header.frame_id = "base_link"
00237     fov_point.header.stamp = rospy.Time.now()
00238     fov_point.pose.position.x = 0.7
00239     fov_point.pose.position.y = 0.0
00240     fov_point.pose.position.z = 0.7
00241     fov_point.pose.orientation.x = 0.0
00242     fov_point.pose.orientation.y = 0.0
00243     fov_point.pose.orientation.z = 0.0
00244     fov_point.pose.orientation.w = 1.0
00245     map_fov_point = self._psi.transform_pose_stamped("map", fov_point)
00246     clearing_radius = 1.0
00247     for co in cur_collision_objects:
00248         if co.id.startswith("table"):
00249             continue
00250         distance = gt.euclidean_distance(map_fov_point.pose.position, co.poses[0].position)
00251         if distance < clearing_radius:
00252             self._wi.remove_collision_object(co.id)
00253 
00254   def _compute_redetected_objects(self, known, det, cur_collision_objects):
00255     """ Compute which objects have been redetected, which are newly detected, and
00256         which known objects have not been redetected.
00257         known and det are detection results of the previsouly known objects (known)
00258         and the current detection (det).
00259         The cur_collision_objects contain the collision objects as they were in
00260         the world right before calling this function.
00261         Returns a tuple (known_not_redetected, newly_detected, redetected) that
00262         contains sets of the respective pickup goals. Redetected contains a set
00263         of tuples (known_pg, detected_pg) that are redetected matches."""
00264 
00265     rospy.loginfo("Updating/merging world interface/known objects.")
00266     # First only determine the merging before applying anything
00267     known_not_redetected = set()    # should be here, but aren't any more
00268     redetected = set()              # did know this, detection redetected it here (known, detected)
00269     if known:
00270         for known_pg in known.pickup_goals:
00271           # for each known object find corresponding detected object
00272           min_distance = 0.1 # max distance variance 10cm
00273           closest_new_pg = None
00274           for det_pg in det.pickup_goals:
00275             det_co = None
00276             for co in cur_collision_objects:
00277                 if co.id == det_pg.collision_object_name:
00278                     det_co = co
00279                     break
00280             if det_co is None:
00281                 rospy.error("Could not find collision object for pickup goal %s" % det_pg.collision_object_name)
00282             assert det_co.header.frame_id == known_pg.collision_object_header.frame_id
00283             distance = gt.euclidean_distance(known_pg.collision_object_poses[0].position, det_co.poses[0].position)
00284             if distance < min_distance:
00285               min_distance = distance
00286               closest_new_pg = det_pg
00287           if closest_new_pg is None:
00288             known_not_redetected.add(known_pg)
00289           else:
00290             # Assumption: name is 'cup_1', 'bottle_3' and the stuff before '_' is the type
00291             # warn if the type changes
00292             known_type = known_pg.collision_object_name.split("_")[0]
00293             new_detected_type = closest_new_pg.collision_object_name.split("_")[0]
00294             if known_type != new_detected_type:
00295                 rospy.logwarn('Possible type redetection mismatch: known: %s new_detected: %s' % \
00296                     (self._pickup_goal_to_str(known_pg), self._pickup_goal_to_str(closest_new_pg)))
00297                 rospy.logwarn('Treating as non-match/new detection')
00298                 known_not_redetected.add(known_pg)
00299             else:
00300                 redetected.add((known_pg, closest_new_pg))
00301 
00302     # The newly detected ones are those that are not redetected
00303     newly_detected = set()          # didn't know about this before, detection just found it
00304     redetected_only_new = [new_pg for (known_pg, new_pg) in redetected]
00305     # As a (common) corner case: If known was empty, redetected is empty, thus none of the
00306     # det_pg in det.pickup_goals will be in redetected_only_new and all are newly_detected.
00307     for det_pg in det.pickup_goals:
00308         if det_pg not in redetected_only_new:
00309             newly_detected.add(det_pg)
00310 
00311     # output merges
00312     for pg in known_not_redetected:
00313         rospy.logwarn('not able to re-detect known object {0}.'.format(self._pickup_goal_to_str(pg)))
00314     for pg in newly_detected:
00315         rospy.loginfo('Newly detected object: %s' % self._pickup_goal_to_str(pg))
00316     for (known_pg, detected_pg) in redetected:
00317         rospy.loginfo('known object {0} re-detected as {1}.'.format(
00318             self._pickup_goal_to_str(known_pg), self._pickup_goal_to_str(detected_pg)))
00319 
00320     return (known_not_redetected, newly_detected, redetected)
00321 
00322   def _compute_detection_name_mappings(self, det_names, world_names, newly_detected, redetected):
00323     """ Determine name mappings in the form newly_detected_name -> old/known_name.
00324         The name mappings should include a mapping for every detected object and
00325         thus might include trivial ones like: cup_1 -> cup_1.
00326         Args:
00327             det_names - set of names in the new detection
00328             world_names - set of names that exist in the world (from cur_collision_objects)
00329             newly_detected - pickup goals for objects that have been newly detected
00330             redetected - set of pickup goal tuples of redetected objects: (known_pg, redetected_pg)
00331         """
00332     # First extract name mappings and check for possible conflicts
00333     name_mappings = dict()  # det_name -> known_name (need to rename det_name to known_name)
00334     new_names = set()       # every name we will assign to
00335 
00336     for (known_pg, detected_pg) in redetected:
00337         name_mappings[detected_pg.collision_object_name] = known_pg.collision_object_name
00338         if detected_pg.collision_object_name != known_pg.collision_object_name:
00339             new_names.add(known_pg.collision_object_name)
00340 
00341     # conflicts arise when we want to assign a new name that already exists in the world
00342     # if it is somewhere else in the world that is very bad and shouldn't happen as
00343     # our new names are chosen from the known objects that were at this location before
00344     # and thus before this detection run also were in the world.
00345     # Nobody should have been able to insert an object with that name somewhere else
00346     world_other = world_names - det_names
00347     world_conflicts = world_other & new_names
00348     for wc_name in world_conflicts:
00349         rospy.logerror('Naming conflict: Found %s in world, but should be reassigned from known' % wc_name)
00350     # if it is in our det set that is OK as we'll just change that
00351     # all redetected ones get their old name in name_mappings, but some newly detected ones
00352     # might block that, so we'll just change their name as they are new
00353     for new_pg in newly_detected:
00354         if new_pg.collision_object_name in new_names:
00355             # bad, already assigned this name to some other thing, we are new, so just invent a new name
00356             type_name_parts = new_pg.collision_object_name.split("_")
00357             type_name = type_name_parts[0]
00358             if(len(type_name_parts) > 1):
00359                 type_name = '_'.join(type_name_parts[:-1])
00360             # cup, cup_1, cup_c_1 -> cup, cup, cup_c
00361             cand = ""
00362             for cand_id in range(1, 100000):
00363                 cand = type_name + "_" + str(cand_id)
00364                 if cand not in world_other and cand not in new_names:
00365                     break 
00366             if not cand:
00367                 rospy.logerror('Could not find new name for %s - this is bad.' % new_pg.collision_object_name)
00368             else:
00369                 name_mappings[new_pg.collision_object_name] = cand
00370                 new_names.add(cand)
00371         else:
00372             name_mappings[new_pg.collision_object_name] = new_pg.collision_object_name
00373             new_names.add(new_pg.collision_object_name)
00374 
00375     rospy.loginfo("Determined the following renamings: %s" % str(name_mappings))
00376     return name_mappings
00377 
00378   def _remove_objects_for_renaming(self, name_mappings):
00379     """ Remove all objects from the world that should be renamed. """
00380 
00381     rospy.loginfo('Removing old objects for renaming')
00382     for old_name, new_name in name_mappings.iteritems():
00383         if old_name != new_name:
00384             self._wi.remove_collision_object(old_name)
00385 
00386   def _readd_objects_for_renaming(self, name_mappings, cur_collision_objects):
00387     """ Readd all objects from the world (with a new name) that were 
00388         previously removed for renaming.
00389         The cur_collision_objects are the object as they were in the world
00390         before _remove_objects_for_renaming was called!"""
00391 
00392     rospy.loginfo('Add new objects for renaming')
00393     for old_name, new_name in name_mappings.iteritems():
00394         if old_name != new_name:
00395             match_co = None
00396             for co in cur_collision_objects:
00397                 if co.id == old_name:
00398                     match_co = co
00399                     break
00400             if match_co is None:
00401                 rospy.logerror('_readd_objects_for_renaming: Could not find collision object for %s in current collision objects.' % old_name)
00402             else:
00403                 match_co.id = new_name
00404                 self._wi.add_object(match_co)
00405 
00406   def _rename_and_update_pickup_goals(self, name_mappings, cur_collision_objects, pickup_goals):
00407     """ Rename the pickup goals according to name mappings and also update/assign a
00408         collision_object_header/collision_object_poses to them.
00409         The cur_collision_objects contain the collision objects as they were in
00410         the world right before calling this function."""
00411 
00412     rospy.loginfo('Renaming known pickup goals')
00413     for pg in pickup_goals:
00414         pg.target.collision_name = name_mappings[pg.collision_object_name]
00415         pg.collision_object_name = name_mappings[pg.collision_object_name]  # do this last as it changes the name!
00416 
00417     rospy.loginfo("Adding collision_object_poses to pickup goals")
00418     for pg in pickup_goals:
00419         match_co = None
00420         for co in cur_collision_objects:
00421             if co.id == pg.collision_object_name:
00422                 match_co = co
00423                 break
00424         if match_co is None:
00425             rospy.logerror('_rename_and_update_pickup_goals: Could not find collision object for %s in current collision objects.' % pg.collision_object_name)
00426         else:
00427             pg.collision_object_header = match_co.header
00428             pg.collision_object_poses = match_co.poses
00429             assert pg.collision_object_poses
00430 
00431   def _compute_new_wipe_goals(self, pickup_goals):
00432     """ Compute tentative wiping goals from pickup_goals (using their obj locations)
00433         pickup_goals is a list of PickupGoal with collision_object_poses + names
00434         Returns: list of (msg.WipeGoal, valid) - Here valid is None = unknown."""
00435     wgs = []
00436     for pg in pickup_goals:
00437         wg = msg.WipeGoal()
00438         wg.name = "wipe_goal_" + pg.collision_object_name
00439         wg.box_size = 0.3
00440         wg.spot.header = pg.collision_object_header
00441         wg.spot.point = pg.collision_object_poses[0].position
00442         wgs.append((wg, None))
00443     return wgs
00444 
00445   def _filter_wipe_goals(self, new_wgs, known_wgs):
00446     """ Filter wiping goals for this location.
00447         new_wg is a list of wiping goals computed for this location.
00448         known_wgs is a list of the known wiping goals already at this location.
00449         Returns a filtered list of WipeGoals where all new and known wipe goals
00450         are contained, unless a new WipeGoal is too close to an already known WipeGoal."""
00451     # We never want to create a WipeGoal for an object we placed ourselves.
00452     # So, we only remember WipeGoals the first time we detect an object.
00453     # From then on the WipeGoal is remembered, but only a valid WipeGoal,
00454     # if it is not too close to a known one.
00455     def wg_distance(wg1, wg2):
00456         return gt.euclidean_distance(wg1.spot.point, wg2.spot.point)
00457 
00458     # we should only have one wg per object once it is first detected
00459     # maybe add valid flag?
00460     all_known_wipe_goal_names = set()
00461     for so, wgs in self._known_wipe_goals.iteritems():
00462         for (wg, valid) in wgs:
00463             all_known_wipe_goal_names.add(wg.name)
00464     # problem here: if we reject one because it is too close, it is not known at all,
00465     # thus we'll readd it after putdown + detect
00466 
00467     filtered_wgs = []
00468     # Initialize the known ones, we always keep the old ones
00469     if known_wgs:
00470         for (wg, valid) in known_wgs:
00471             filtered_wgs.append((wg, valid))
00472     # TODO: Self filter the new detection, some in there might be too close
00473     for (wg, _) in new_wgs:
00474         # we already have this one somewhere, do not readd
00475         if wg.name in all_known_wipe_goal_names:
00476             continue
00477         # This is an unknown one! We will definitely remember this one,
00478         # but it is only valid if it is not too near to another valid one
00479         valid = True
00480         if known_wgs:
00481             for (known_wg, known_wg_valid) in known_wgs:
00482                 if not known_wg_valid:
00483                     continue
00484                 if wg_distance(wg, known_wg) <= 0.1:
00485                     valid = False
00486                     break
00487         filtered_wgs.append((wg, valid))
00488     return filtered_wgs
00489 
00490   def _create_detected_visible_objects(self, pickup_goals):
00491     """ Create a reply of visible_objects for an object detection request from the pickup_goals. """
00492 
00493     self._psi.reset()   # for _check_trajectory_to_pickup_goal
00494 
00495     # convert objects to tidyup_objects and return results
00496     visible_objects = list()
00497     for pg in pickup_goals:
00498       object = msg.GraspableObject()
00499       object.name = pg.collision_object_name
00500       object.pose = pg.object_pose_stamped
00501       # if we have a global pose from collision object, use this one instead of the
00502       # pickup goal pose, which is usually in base_link
00503       if hasattr(pg, 'collision_object_header') and hasattr(pg, 'collision_object_poses'):
00504         object.pose = PoseStamped()
00505         object.pose.header = pg.collision_object_header
00506         object.pose.pose = pg.collision_object_poses[0]
00507       else:
00508         rospy.logwarn("Pickup goal for %s did not have collision_object_header/poses" % pg.collision_object_name)
00509       object.reachable_right_arm = True
00510       object.reachable_left_arm = True
00511       #pg.only_perform_feasibility_test = True
00512 #      pg.arm_name = 'left_arm'
00513 #      if self._check_trajectory_to_pickup_goal(pg):
00514 #        object.reachable_left_arm = True
00515 #      else:
00516 #        object.reachable_left_arm = False
00517 #      pg.arm_name = 'right_arm'
00518 #      if self._check_trajectory_to_pickup_goal(pg):
00519 #        object.reachable_right_arm = True
00520 #      else:
00521 #        object.reachable_right_arm = False
00522       visible_objects.append(object)
00523 
00524     return visible_objects
00525 
00526   def _detect_objects_callback(self, request):
00527     """ Call the object detection and based on that:
00528         update the world interface so the newly detected objects are now in the world and
00529         already known objects are updated. The set of objects that we know to be on this
00530         static_object should be exaclty the set of detected objects, i.e. not re-detected objects are removed,
00531         new ones added, re-detected ones updated.
00532         Objects in the world not on this static_object should never be touched.
00533 
00534         In addition update our known_objects on this static_object with this information.
00535         We will also forget about any other known_objects on this location
00536         and the planner state should do the same.
00537         Any picked up object should also be removed."""
00538 
00539     rospy.loginfo('request: detect objects at %s.' % request.static_object)
00540     self._psi.reset()
00541 
00542     self._head.look_at_relative_point(0.8, 0.0, 0.7)
00543 
00544     self._dump_planning_scene_objects()
00545     self._dump_known_objects()
00546 
00547     rospy.loginfo("Removing known objects at %s from world interface for re-detection." % request.static_object)
00548 
00549     cur_collision_objects = self._wi.collision_objects()
00550     # remove known objects from this position in the world map
00551     known = self._known_objects.get(request.static_object)
00552     self._remove_known_objects(known)
00553 
00554     self._dump_planning_scene_objects()
00555 
00556     self._remove_objects_in_fov(cur_collision_objects)
00557 
00558     self._dump_planning_scene_objects()
00559     self._dump_known_objects()
00560 
00561     rospy.loginfo("Calling object detection.")
00562 
00563     try:
00564       # det is a tableware_detection.TablewareDetectionResult
00565       det = self._detector.detect_objects(add_objects_to_map='recognized', add_table_to_map=False, reset_collision_objects=False, table_name=request.static_object)
00566     except DetectionError, last_ex:
00567       rospy.logerr('object detection FAILED')
00568       return False #{ 'objects': list()}
00569 
00570     self._dump_planning_scene_objects()
00571     self._dump_known_objects()
00572 
00573     # filter unrecognized and compute grasps
00574     recognized_pgs = list()
00575     for pg in det.pickup_goals:
00576       if pg.label != 'graspable':
00577         recognized_pgs.append(pg)
00578     det.pickup_goals = recognized_pgs
00579     rospy.loginfo("Recognized pickup goals from detection:")
00580     for pg in det.pickup_goals:
00581         rospy.loginfo(self._pickup_goal_to_str(pg))
00582 
00583     cur_collision_objects = self._wi.collision_objects()
00584     (known_not_redetected, newly_detected, redetected) = self._compute_redetected_objects(known, det, cur_collision_objects)
00585 
00586     # Initialize the new known with det to get an updated table
00587     # pickup goals will be updated now
00588     new_known = det
00589     # we will keep all the objects in det, but might rename the matched ones in the new det
00590     # so they will have the 'old' known name
00591 
00592     # those should be the new names in the detection at static_object
00593     det_names = set([pg.collision_object_name for pg in det.pickup_goals])   # every name we just got from det
00594     world_names = set([co.id for co in cur_collision_objects])   # every name in wi right now
00595 
00596     name_mappings = self._compute_detection_name_mappings(det_names, world_names, newly_detected, redetected)
00597 
00598     # As we might have cyclic conflicts (e.g. cup_1 -> cup_2, cup_2 -> cup_1), we'll do this the easy way:
00599     # Remove all objects and reinsert them
00600     self._dump_planning_scene_objects()
00601     self._remove_objects_for_renaming(name_mappings)
00602     self._dump_planning_scene_objects()
00603     self._readd_objects_for_renaming(name_mappings, cur_collision_objects)
00604     self._dump_planning_scene_objects()
00605 
00606     # Reget from wi as we renamed stuff above
00607     cur_collision_objects = self._wi.collision_objects()
00608     self._rename_and_update_pickup_goals(name_mappings, cur_collision_objects, new_known.pickup_goals)
00609 
00610     self._known_objects[request.static_object] = new_known
00611 
00612     rospy.loginfo("Final world scene/known objects")
00613     self._dump_planning_scene_objects()
00614     self._dump_known_objects()
00615 
00616     rospy.loginfo("Update/Merge done.")
00617 
00618     rospy.loginfo("Computing Wipe Goals")
00619     self._dump_known_wipe_goals()
00620 
00621     # Compute tentative wiping goals (all obj locations at static_object (in /map))
00622     new_wgs = self._compute_new_wipe_goals(self._known_objects[request.static_object].pickup_goals)
00623     rospy.loginfo("Tentative new wipe goals at %s" % request.static_object)
00624     for (wg, valid) in new_wgs:
00625         rospy.loginfo(self._wipe_goal_to_str(wg, valid))
00626     # Remove extra wiping goals (knowing the old ones)
00627     filtered_wgs = self._filter_wipe_goals(new_wgs, self._known_wipe_goals.get(request.static_object))
00628     rospy.loginfo("Filtered wipe goals at %s" % request.static_object)
00629     for (wg, valid) in filtered_wgs:
00630         rospy.loginfo(self._wipe_goal_to_str(wg, valid))
00631 
00632     self._known_wipe_goals[request.static_object] = filtered_wgs
00633 
00634     self._dump_known_wipe_goals()
00635 
00636     # Prepare the response
00637     visible_objects = self._create_detected_visible_objects(self._known_objects[request.static_object].pickup_goals)
00638     valid_wipe_goals = [wg for (wg, valid) in filtered_wgs if valid]
00639 
00640     obj_names = ", ".join([obj.name for obj in visible_objects])
00641     wg_names = ", ".join([wg.name for wg in valid_wipe_goals])
00642     rospy.loginfo('detect objects finished. sending {0} objects ({1})'.format(len(visible_objects), obj_names))
00643     rospy.loginfo('determined %d wipe goals (%s)' % (len(valid_wipe_goals), wg_names))
00644     return { 'objects': visible_objects, 'wipe_goals': valid_wipe_goals}
00645 
00646   def _request_graspability_callback(self, request):
00647     rospy.loginfo('DEPRECATED: request object graspability.')
00648     return { 'objects': request.objects}
00649 
00650   def _pick_up_execute(self, goal):
00651     rospy.loginfo('pick up execute: pickup {0} on {1} with {2}'.format(goal.pickup_object, goal.static_object, goal.arm))
00652     self._psi.reset()
00653     action_result = msg.GraspObjectResult()
00654     action_result.grasp.pose.orientation.w = 1 
00655 
00656     self._dump_known_objects()
00657 
00658     # find pickup_goal by id
00659     known = self._known_objects.get(goal.static_object)
00660     if not known:
00661       rospy.logerr('pickup_execute: FAILED: detection data not available for this static_object {0}'.format(goal.static_object))
00662       action_result.error_code.val = action_result.error_code.SENSOR_INFO_STALE
00663       self._pickUpActionServer.set_aborted(result=action_result, text='execution failed: detection data not available for this static_object {0}'.format(goal.static_object))
00664       return
00665     pickup_goal = None
00666     for pg in known.pickup_goals:
00667       if pg.collision_object_name == goal.pickup_object:
00668         pickup_goal = pg
00669         break
00670     if pickup_goal == None:
00671       rospy.logerr('pickup_execute: FAILED: detection data not available for this pickup_object {0}'.format(goal.pickup_object))
00672       action_result.error_code.val = action_result.error_code.SENSOR_INFO_STALE
00673       self._pickUpActionServer.set_aborted(result=action_result, text='execution failed: detection data not available for this pickup_object {0}'.format(goal.pickup_object))
00674       return
00675 
00676     # compute grasps
00677     #pickup_goal = PickupGoal()
00678     pickup_goal.arm_name = goal.arm
00679     #pickup_result = PickupResult()
00680     try:
00681       pickup_result = self._pick_place.pickup(pickup_goal)
00682     except ManipulationError, last_ex:
00683       rospy.logerr('pickup_execute: FAILED: {0}'.format(last_ex))
00684       #action_result.error_code.val = last_ex.arm_navigation_error_code.val
00685       self._pickUpActionServer.set_aborted(result=action_result, text='execution failed: {0}'.format(last_ex))
00686       return
00687 
00688     # Success: Remove this pickup goal from known as
00689     # we can't pick this up any more
00690     known.pickup_goals.remove(pickup_goal)
00691 
00692     self._dump_known_objects()
00693 
00694     action_result.error_code.val = action_result.error_code.SUCCESS
00695     #action_result.grasp.pose = pickup_result.frame_free_grasp
00696     # TODO: frame_id for grasp pose correct?! no, fill this correct
00697     rospy.loginfo('pickup_execute: succeded')
00698     action_result.grasp.header.frame_id = self._tasks._arm_planners[goal.arm].hand.attach_link
00699     self._pickUpActionServer.set_succeeded(result=action_result, text='pickup successful')
00700 
00701   def _find_putdown_pose_callback(self, request):
00702     rospy.loginfo('find putdown pose request: place {0} held in {2} on {1}'.format(request.putdown_object, request.static_object, request.arm))
00703     psi = self._psi
00704     psi.current_diff.planning_scene_diff = request.planning_scene
00705     psi.send_diff()
00706     #self._planning_scene_sync.update_planning_scene(psi)
00707     #scene = psi.send_diff().planning_scene
00708     place_goal, grasp = self._create_place_goal(request)
00709     response = srv.GetPutdownPoseResponse()
00710     if not place_goal:
00711       rospy.logerr('find putdown pose FAILED: no object attached to gripper.')
00712       response.error_code.val = ArmNavigationErrorCodes.INCOMPLETE_ROBOT_STATE
00713       return response
00714     place_pose = self._check_trajectory_to_place_goal(place_goal)
00715     if not place_pose:
00716       rospy.logerr('find putdown pose FAILED: no valid pose found.')
00717       response.error_code.val = ArmNavigationErrorCodes.PLANNING_FAILED
00718       return response
00719     response.error_code.val = ArmNavigationErrorCodes.SUCCESS
00720     response.putdown_pose = place_pose
00721     rospy.loginfo('found putdown pose: {0}'.format(response.putdown_pose))
00722     return response
00723 
00724   def _put_down_execute(self, goal):
00725     rospy.loginfo('find putdown pose request: place {0} held in {2} on {1}'.format(goal.putdown_object, goal.static_object, goal.arm))
00726     self._psi.reset()
00727 
00728     place_goal, grasp = self._create_place_goal(goal)
00729     rospy.loginfo(self._place_goal_to_str(place_goal))
00730 
00731     self._pick_place._place_client.send_goal_and_wait(place_goal)
00732     result = self._pick_place._place_client.get_result()
00733     if result.manipulation_result.value == result.manipulation_result.SUCCESS:
00734       rospy.loginfo('planner selected pose: {0}'.format(result.place_location))
00735 
00736       self._dump_known_objects()
00737 
00738       rospy.loginfo('Inserting new pickup goal for %s at %s' % (goal.putdown_object, goal.static_object))
00739       # Insert this placed object into known, so it can be
00740       # matched by object detection in the next step, instead of getting a new name
00741       # All data should come from object det anyways, so we only need to make
00742       # sure it can be matched
00743       known = self._known_objects.get(goal.static_object)
00744       putdown_pg = None
00745       # First make sure that known is a valid TablewareDetectionResult in self._known_objects
00746       # which we can use to add our new pickup goal for the placed object to
00747       if known:
00748           for pg in known.pickup_goals:
00749               if pg.collision_object_name == goal.putdown_object:
00750                   putdown_pg = pg
00751                   rospy.logwarn('Found old pickup goal (%s) for putdown object already at this location' % _pickup_goal_to_str(putdown_pg))
00752                   break
00753       else:
00754           table = tabletop_object_detector.msg.Table()
00755           known = TablewareDetectionResult([], table, goal.static_object)
00756           self._known_objects[goal.static_object] = known
00757 
00758       # PoseStamped of the actual object pose, not the place wrist pose
00759       place_object_location = self.get_object_pose_from_grasp(result.place_location, grasp)
00760 
00761       # create or update the pickup goal for the placed object
00762       if putdown_pg is None:
00763           grasp_target = object_manipulation_msgs.msg.GraspableObject()
00764           grasp_target.collision_name = goal.putdown_object
00765           # FIXME: place_location is in map frame, this should still be OK for object_pose_stamped
00766           putdown_pg = PickupGoal("", grasp_target, object_pose_stamped=place_object_location, collision_object_name=goal.putdown_object)
00767           known.pickup_goals.append(putdown_pg) # This is new, so add it.
00768       else:
00769           putdown_pg.target.collision_name = goal.putdown_object
00770           putdown_pg.object_pose_stamped = place_object_location
00771 
00772       putdown_pg.collision_object_header = place_object_location.header
00773       putdown_pg.collision_object_poses = [place_object_location.pose]
00774       putdown_pg.collision_support_surface_name = goal.static_object
00775 
00776       self._dump_known_objects()
00777 
00778       # send result
00779       self._psi.reset()
00780       action_result = msg.PlaceObjectResult()
00781       action_result.putdown_pose = place_object_location
00782       action_result.error_code.val = result.manipulation_result.value
00783       self._putDownActionServer.set_succeeded(text='putdown successful', result=action_result)
00784       rospy.loginfo("putdown successful")
00785     else:
00786       rospy.logerr('pickplace.place pose FAILED: error code: {0}'.format(result.manipulation_result.value))
00787       rospy.logerr('Attempted Locations:')
00788       for ps in result.attempted_locations:
00789           rospy.logerr("frame: %s pose: %s" % (ps.header.frame_id, self._pose_to_str(ps.pose)))
00790       rospy.logerr('PlaceLocationResults:')
00791       for plr in result.attempted_location_results:
00792           rospy.logerr("Result Code: %d" % plr.result_code)
00793       self._putDownActionServer.set_aborted(text='find putdown pose FAILED: no valid pose.')
00794     #self._psi.reset()
00795 
00796   def get_object_pose_from_grasp(self, wrist_pose_stamped, frame_free_grasp_pose):
00797     '''
00798     Function for finding the end effector pose given a grasp and a desired place for the object.
00799 
00800     **Args:**
00801 
00802         **wrist_pose_stamped (geometry_msgs.msg.PoseStamped):** The pose as a geometry_msgs.msg.PoseStamped
00803             of the end effector to place the object at place_pose_stamped.
00804             For the PR2 this is the wrist pose.
00805 
00806         **frame_free_grasp (pickplace_definitions.FrameFreeGrasp):** Grasp with which the object is held
00807 
00808     **Returns:**
00809         place_pose_stamped (geometry_msgs.msg.PoseStamped): The Place for an object
00810     '''
00811 
00812     origin = Pose()
00813     origin.orientation.w = 1.0
00814     pose_stamped = PoseStamped()
00815     pose_stamped.header.frame_id = wrist_pose_stamped.header.frame_id
00816     pose_stamped.header.stamp = wrist_pose_stamped.header.stamp
00817     pose_stamped.pose = gt.transform_pose(gt.transform_pose(origin, frame_free_grasp_pose), 
00818                                           wrist_pose_stamped.pose)
00819     return pose_stamped
00820 
00821   def _create_place_goal(self, request):
00822     rospy.loginfo('create_place_goal')
00823     #scene = self._planning_scene_sync._latest_planning_scene
00824     psi = self._psi
00825     scene = psi.current_planning_scene()
00826 
00827     # check object id and arm
00828     putdown_object = None
00829     for attached in scene.attached_collision_objects:
00830       if attached.object.id == request.putdown_object and attached.link_name[0] == request.arm[0]:
00831         putdown_object = attached
00832 #    putdown_object = psi.attached_collision_object(request.putdown_object)
00833     if not putdown_object:
00834       rospy.logerr('no attached object.')
00835       return None, None
00836     rospy.loginfo('attached object: {0}'.format(putdown_object.object.id))
00837 
00838     # table / shelf
00839     table = None
00840     for co in scene.collision_objects:
00841         if co.id == request.static_object:
00842             table = co
00843     #table = psi.collision_object(request.static_object)
00844     collision_objects = []
00845     for object in scene.collision_objects:
00846       if object.id != request.static_object and object.id != request.putdown_object:
00847         collision_objects.append(object)
00848 
00849     # find possible poses
00850     orientation = scene.robot_state.multi_dof_joint_state.poses[0].orientation
00851     object_poses = free_spots_on_table(table, putdown_object.object, orientation, collision_objects, orientation_count=8)
00852     rospy.loginfo('finished: free_spots_on_table ({1}). first pose: {0}'.format(object_poses[0], len(object_poses)))
00853 
00854     # prioritize putdown poses
00855     preferred_putdown_point = Point()
00856     preferred_putdown_point.x = 0.7
00857     preferred_putdown_point.y = 0.0
00858     preferred_putdown_point.z = 0
00859     if request.arm == 'right_arm':
00860       preferred_putdown_point.y *= -1;
00861     preferred_putdown_point = psi.transform_point('/map', '/torso_lift_link', preferred_putdown_point)
00862     object_poses.sort(key=lambda object_pose: math.sqrt((preferred_putdown_point.x - object_pose.pose.position.x)**2 + (preferred_putdown_point.y - object_pose.pose.position.y)**2))
00863     shoulder_point = Point()
00864     shoulder_point.x = 0
00865     shoulder_point.y = 0.3
00866     shoulder_point.z = 0
00867     if request.arm == 'right_arm':
00868       shoulder_point.y *= -1;
00869     shoulder_point = psi.transform_point('/map', '/torso_lift_link', shoulder_point)
00870     rospy.loginfo('should point at: {0}'.format(shoulder_point))
00871     object_poses = filter(lambda object_pose: math.sqrt((shoulder_point.x - object_pose.pose.position.x)**2 + (shoulder_point.y - object_pose.pose.position.y)**2) <= 1.0, object_poses)
00872     if object_poses:
00873         rospy.loginfo('finished: prioritizing/filtering ({1}). first pose: {0}'.format(object_poses[0], len(object_poses)))
00874     else:
00875         rospy.logwarn('finished: prioritizing/filtering: 0 poses.')
00876 
00877     # compute grasp
00878 #    rospy.loginfo('robot state: {0}'.format(psi.get_robot_state()))
00879 #    pose_markers = MarkerArray()
00880     grasp = psi.transform_pose(\
00881       psi.hands[request.arm].hand_frame, \
00882       putdown_object.object.header.frame_id, \
00883       putdown_object.object.poses[0])
00884     rospy.loginfo('grasp: {0}'.format(grasp))
00885 
00886     # compute wrist poses
00887     wrist_poses = []
00888     for object_pose in object_poses:
00889       wrist_poses.append(get_wrist_pose_from_grasp(object_pose, grasp))
00890 #      pose_markers.markers.append(vt.marker_at(wrist_poses[-1], mid=len(wrist_poses), ns='putdown_wrist_poses'))
00891  #   self._visualization_publisher.publish(pose_markers)
00892     if object_poses:
00893         rospy.loginfo('finished creating place goal. firts pose: {0}'.format(wrist_poses[0]))
00894     else:
00895         rospy.logwarn('place goal does not have any poses')
00896     return PlaceGoal(request.arm, wrist_poses, collision_object_name=putdown_object.object.id, collision_support_surface_name=table.id), grasp
00897 
00898   def _check_trajectory_to_place_goal(self, place_goal):
00899     rospy.loginfo('check putdown for {0} with {1}'.format(place_goal.collision_object_name, place_goal.arm_name))
00900 #    arm_planner = self._tasks._arm_planners[place_goal.arm_name]
00901     # disable collisions between putdown object and anything else
00902     collision = CollisionOperation()
00903     collision.object1 = place_goal.collision_object_name
00904     collision.object2 = collision.COLLISION_SET_ALL # arm_planner.joint_names[6]
00905     collision.operation = collision.DISABLE
00906     place_goal.additional_collision_operations.collision_operations.append(collision)
00907     self._psi.add_ordered_collisions(place_goal.additional_collision_operations)
00908     marker_ns = place_goal.collision_object_name+"_"+place_goal.arm_name+'_putdown'
00909     result = self._check_trajectory_to_wrist_poses_list(place_goal.place_locations, place_goal.arm_name, marker_ns=marker_ns)
00910     self._psi.remove_ordered_collisions(place_goal.additional_collision_operations)
00911     # request failed. visualize situation
00912     #robot_marker = vt.robot_marker(robot_state=self._psi.get_robot_state(), ns=marker_ns+'_failed', r=0.9, g=0.0, b=0.0, a=0.5)
00913     #self._visualization_publisher.publish(robot_marker)
00914     return result
00915 
00916   def _check_trajectory_to_pickup_goal(self, pickup_goal):
00917     rospy.loginfo('check pickup for {0} with {1}'.format(pickup_goal.collision_object_name, pickup_goal.arm_name))
00918     #arm_planner = self._tasks._arm_planners[pickup_goal.arm_name]
00919     grasps = self._pick_place.get_grasps(pickup_goal)
00920 
00921     # disable collisions between putdown object and anything else
00922     collision = CollisionOperation()
00923     collision.object1 = pickup_goal.collision_object_name
00924     collision.object2 = collision.COLLISION_SET_ALL # arm_planner.joint_names[6]
00925     collision.operation = collision.DISABLE
00926     pickup_goal.additional_collision_operations.collision_operations.append(collision)
00927     self._psi.add_ordered_collisions(pickup_goal.additional_collision_operations)
00928     grasp_markers = MarkerArray()
00929     marker_ns = pickup_goal.collision_object_name+"_"+pickup_goal.arm_name+"_pickup"
00930     #rospy.loginfo('potential models: \n{0}'.format(pickup_goal.target.potential_models))
00931     rospy.loginfo('checking grasps: {0}'.format(len(grasps)))
00932     wrist_poses = list()
00933     for grasp in grasps:
00934       #rospy.loginfo('grasp: \n{0}'.format(grasp))
00935       gripper_pose = PoseStamped() 
00936       gripper_pose.pose = grasp.grasp_pose
00937       gripper_pose.header.frame_id = '/base_link'
00938       wrist_poses.append(self._psi.transform_pose_stamped('/map', gripper_pose))
00939     result = self._check_trajectory_to_wrist_poses_list(wrist_poses, pickup_goal.arm_name, marker_ns)
00940     self._psi.remove_ordered_collisions(pickup_goal.additional_collision_operations)
00941     pickup_goal.additional_collision_operations.collision_operations.remove(collision)
00942     return result
00943     
00944   def _check_trajectory_to_wrist_poses_list(self, wrist_poses, arm_name, marker_ns=None):
00945     if not marker_ns: 
00946       marker_ns='wrist_'+arm_name
00947     rospy.loginfo('check to wrist poses {0} for {1}'.format(len(wrist_poses), arm_name))
00948     # disable collisions between putdown object and anything else
00949     arm_planner = self._tasks._arm_planners[arm_name]
00950     robot_state = self._psi.get_robot_state()
00951     wrist_markers = MarkerArray()
00952     found_trajectory = False
00953     trajectory_pose = None
00954     for wrist_pose in wrist_poses:
00955       # HACK: plan to 0.1m above the table surface to avoid colisions
00956       # this is somewhat correct, since the pickplace planner first moves to approach pose, 
00957       # before moving to the "real" wrist pose
00958       wrist_pose.pose.position.z += 0.1
00959       # 1) check collision-aware ik
00960 #      rospy.loginfo('checking ik for wrist pose: {0} {1}'.format(wrist_pose.header.frame_id, self._pose_to_str(wrist_pose.pose)))
00961 #      relative_pose = self._psi.transform_pose_stamped('base_link', wrist_pose)
00962 #      rospy.loginfo('       relative wrist pose: {0} {1}'.format(relative_pose.header.frame_id, self._pose_to_str(relative_pose.pose)))
00963       ik_result = arm_planner.get_ik(wrist_pose, starting_state=robot_state, handle_collision_operations=False)
00964       if ik_result.error_code.val == ik_result.error_code.SUCCESS:
00965         wrist_markers.markers.append(vt.marker_at(pose_stamped=wrist_pose, ns=marker_ns+'_'+str(ik_result.error_code.val), mid=len(wrist_markers.markers), mtype=Marker.ARROW, r=0.1, g=0.3, b=0.8, a=1.0))
00966         if not found_trajectory:
00967           rospy.loginfo('found ik solution, checking trajectory')
00968           try:
00969             # 2) check full trajectory
00970             trajectory = arm_planner.plan_collision_free(wrist_pose, starting_state=robot_state)
00971             found_trajectory = True
00972             trajectory_pose = wrist_pose
00973           except exceptions.ArmNavError, e:
00974             wrist_markers.markers.append(vt.marker_at(pose_stamped=wrist_pose, ns=marker_ns+'_'+str(ik_result.error_code.val), mid=len(wrist_markers.markers), mtype=Marker.ARROW, r=0.1, g=0.8, b=0.8, a=1.0))
00975       else:
00976         wrist_markers.markers.append(vt.marker_at(pose_stamped=wrist_pose, ns=marker_ns+'_'+str(ik_result.error_code.val), mid=len(wrist_markers.markers), mtype=Marker.ARROW, r=0.8, g=0.3, b=0.1, a=1.0))
00977     if found_trajectory:
00978       # visualize result
00979       final_arm_state = tt.last_state_on_joint_trajectory(trajectory)
00980       final_robot_state = tt.set_joint_state_in_robot_state(final_arm_state, copy.deepcopy(robot_state))
00981       robot_marker = vt.robot_marker(robot_state=final_robot_state, ns=marker_ns+'_succeeded', r=0.2, g=0.5, b=0.9, a=0.5)
00982       self._visualization_publisher.publish(robot_marker)
00983       self._visualization_publisher.publish(wrist_markers)
00984       rospy.loginfo('trajectory ok, wrist pose reachable')
00985       return wrist_pose
00986     else:
00987       # request failed. visualize situation
00988       robot_marker = vt.robot_marker(robot_state=robot_state, ns=marker_ns+'_failed', r=0.8, g=0.3, b=0.1, a=0.5)
00989       self._visualization_publisher.publish(robot_marker)
00990       self._visualization_publisher.publish(wrist_markers)
00991       rospy.loginfo('trajectory check FAILED')
00992       return None
00993 
00994   def _add_tables_to_wi(self):
00995     table_file = rospy.get_param('~tables')
00996     tables = read_table_file(table_file)
00997     for table in tables:
00998       self._wi.add_collision_box(table[0], table[1], table[2])
00999 
01000   def _add_sponge_to_base(self, req=None):
01001     link_name = 'base_link'
01002     object_name = 'sponge'
01003     touch_links = ['base_link']
01004     stamped = PoseStamped()
01005     pose = Pose()
01006     pose.position.x = 0.25
01007     pose.position.y = 0.0
01008     pose.position.z = 0.33
01009     pose.orientation.x = 0
01010     pose.orientation.y = 0
01011     pose.orientation.z = 0
01012     pose.orientation.w = 1
01013     stamped.pose = pose
01014     stamped.header.frame_id = link_name
01015     self._attach_object(object_name, link_name, touch_links, stamped)
01016     return {}
01017     
01018   def _add_sponge_to_right_gripper(self, req=None):
01019     wi = self._wi
01020     hand = arm_planner = self._tasks._arm_planners['right_arm'].hand
01021     link_name = hand.attach_link
01022     object_name = 'sponge'
01023     touch_links = hand.touch_links
01024     stamped = PoseStamped()
01025     pose = Pose()
01026     pose.position.x = 0.025
01027     pose.position.y = 0.025
01028     pose.position.z = 0
01029     quat_list = tf.transformations.quaternion_from_euler(np.pi/2.0, 0, -np.pi/2.0)
01030     pose.orientation.x = quat_list[0]
01031     pose.orientation.y = quat_list[1]
01032     pose.orientation.z = quat_list[2]
01033     pose.orientation.w = quat_list[3]
01034     stamped.pose = pose
01035     stamped.header.frame_id = hand.attach_link
01036     self._attach_object(object_name, link_name, touch_links, stamped)
01037     return {}
01038 
01039   def _attach_object(self, object_name, link_name, touch_links, stamped):
01040     wi = self._wi
01041     # detach, if attached
01042     attached = wi.attached_collision_object(object_name)
01043     if attached:
01044       attached.object.operation.operation = attached.object.operation.DETACH_AND_ADD_AS_OBJECT
01045       wi._publish(attached, wi._attached_object_pub)
01046     
01047     object = wi.collision_object(object_name)
01048     # create object, if does not exist 
01049     if not object:
01050       rospy.loginfo('creating sponge')
01051       wi.add_collision_box(stamped, [0.10, 0.15, 0.05], object_name)
01052       object = wi.collision_object(object_name)
01053     
01054     # update object pose
01055     object.header.frame_id = stamped.header.frame_id
01056     object.poses[0] = stamped.pose
01057     object.operation.operation = object.operation.ADD
01058     wi.add_object(object)
01059     
01060     # attach to new link
01061     attached = AttachedCollisionObject()
01062     attached.object = wi.collision_object(object_name)
01063     attached.link_name = link_name
01064     attached.touch_links = touch_links
01065     attached.object.operation.operation = attached.object.operation.ATTACH_AND_REMOVE_AS_OBJECT
01066     wi._publish(attached, wi._attached_object_pub)
01067     
01068     self._psi.reset()
01069 
01070 
01071 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends


tidyup_arm_services
Author(s): Andreas Hertle, Christian Dornhege
autogenerated on Wed Dec 26 2012 15:48:37