$search
00001 /********************************************************************* 00002 * 00003 * Copyright (c) 2009, Willow Garage, Inc. 00004 * All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 00010 * * Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * * Redistributions in binary form must reproduce the above 00013 * copyright notice, this list of conditions and the following 00014 * disclaimer in the documentation and/or other materials provided 00015 * with the distribution. 00016 * * Neither the name of the Willow Garage nor the names of its 00017 * contributors may be used to endorse or promote products derived 00018 * from this software without specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00021 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00022 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00023 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00024 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00025 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00026 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00027 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00028 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00029 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00030 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00031 * POSSIBILITY OF SUCH DAMAGE. 00032 *********************************************************************/ 00033 00034 #include "object_manipulator/grasp_execution/approach_lift_grasp.h" 00035 00036 #include "object_manipulator/tools/mechanism_interface.h" 00037 #include "object_manipulator/tools/exceptions.h" 00038 #include "object_manipulator/tools/hand_description.h" 00039 #include "object_manipulator/tools/vector_tools.h" 00040 00041 using object_manipulation_msgs::GraspResult; 00042 using arm_navigation_msgs::ArmNavigationErrorCodes; 00043 00044 namespace object_manipulator { 00045 00047 float GraspTesterWithApproach::EPS = 1.0e-6; 00048 00049 // ---------------------------- Definitions --------------------------------- 00050 00051 void GraspTester::testGrasps(const object_manipulation_msgs::PickupGoal &goal, 00052 const std::vector<object_manipulation_msgs::Grasp> &grasps, 00053 std::vector<GraspExecutionInfo> &execution_info, 00054 bool return_on_first_hit) 00055 { 00056 execution_info.clear(); 00057 for (size_t i=0; i<grasps.size(); i++) 00058 { 00059 GraspExecutionInfo info; 00060 ROS_DEBUG_NAMED("manipulation","Grasp tester: testing grasp %zd out of batch of %zd", i, grasps.size()); 00061 if (feedback_function_) feedback_function_(i); 00062 if (interrupt_function_ && interrupt_function_()) throw InterruptRequestedException(); 00063 if (marker_publisher_) 00064 { 00065 geometry_msgs::PoseStamped marker_pose; 00066 marker_pose.pose = grasps[i].grasp_pose; 00067 marker_pose.header.frame_id = goal.target.reference_frame_id; 00068 marker_pose.header.stamp = ros::Time::now(); 00069 info.marker_id_ = marker_publisher_->addGraspMarker(marker_pose); 00070 } 00071 testGrasp(goal, grasps[i], info); 00072 execution_info.push_back(info); 00073 if (info.result_.result_code == info.result_.SUCCESS && return_on_first_hit) return; 00074 } 00075 } 00076 00077 void GraspPerformer::performGrasps(const object_manipulation_msgs::PickupGoal &goal, 00078 const std::vector<object_manipulation_msgs::Grasp> &grasps, 00079 std::vector<GraspExecutionInfo> &execution_info) 00080 { 00081 for (size_t i=0; i<grasps.size(); i++) 00082 { 00083 if (feedback_function_) feedback_function_(i); 00084 if (interrupt_function_ && interrupt_function_()) throw InterruptRequestedException(); 00085 if (i>= execution_info.size()) throw GraspException("Grasp Performer: not enough execution info provided"); 00086 if (execution_info[i].result_.result_code != GraspResult::SUCCESS) continue; 00087 ROS_DEBUG_NAMED("manipulation","Grasp performer: trying grasp %zd out of batch of %zd", i, grasps.size()); 00088 performGrasp(goal, grasps[i], execution_info[i]); 00089 if (execution_info[i].result_.result_code == execution_info[i].result_.SUCCESS || 00090 !execution_info[i].result_.continuation_possible) return; 00091 } 00092 } 00093 00094 // ------------------------------ Grasp Testers ---------------------------------- 00095 00099 arm_navigation_msgs::OrderedCollisionOperations 00100 GraspTesterWithApproach::collisionOperationsForLift(const object_manipulation_msgs::PickupGoal &pickup_goal, 00101 const object_manipulation_msgs::Grasp &grasp) 00102 { 00103 arm_navigation_msgs::OrderedCollisionOperations ord; 00104 arm_navigation_msgs::CollisionOperation coll; 00105 coll.object1 = handDescription().gripperCollisionName(pickup_goal.arm_name); 00106 coll.operation = arm_navigation_msgs::CollisionOperation::DISABLE; 00107 if (!pickup_goal.collision_object_name.empty()) 00108 { 00109 coll.object2 = pickup_goal.collision_object_name; 00110 ord.collision_operations.push_back(coll); 00111 } 00112 if (pickup_goal.allow_gripper_support_collision) 00113 { 00114 coll.object2 = pickup_goal.collision_support_surface_name; 00115 ord.collision_operations.push_back(coll); 00116 } 00117 00118 for (unsigned int i = 0; i < grasp.moved_obstacles.size(); i++) 00119 { 00120 ROS_DEBUG_NAMED("manipulation"," Disabling all collisions for lift against moved obstacle %s", 00121 grasp.moved_obstacles[i].collision_name.c_str()); 00122 coll.object1 = grasp.moved_obstacles[i].collision_name; 00123 //This disables all collisions with the object. Ignore possible collisions of the robot with the object 00124 //during the push-grasp. We need all the capture region to be able to do this safely. Or we can disable 00125 //collisions just with the forearm, which should work almost always but still theoretically is not the right 00126 //thing to do. 00127 coll.object2 = arm_navigation_msgs::CollisionOperation::COLLISION_SET_ALL; 00128 ord.collision_operations.push_back(coll); 00129 } 00130 00131 ord.collision_operations = concat(ord.collision_operations, 00132 pickup_goal.additional_collision_operations.collision_operations); 00133 return ord; 00134 } 00135 00137 std::vector<arm_navigation_msgs::LinkPadding> 00138 GraspTesterWithApproach::linkPaddingForLift(const object_manipulation_msgs::PickupGoal &pickup_goal, 00139 const object_manipulation_msgs::Grasp&) 00140 { 00141 return concat(MechanismInterface::gripperPadding(pickup_goal.arm_name, 0.0), 00142 pickup_goal.additional_link_padding); 00143 } 00144 00145 GraspResult 00146 GraspTesterWithApproach::getInterpolatedIKForLift(const object_manipulation_msgs::PickupGoal &pickup_goal, 00147 const object_manipulation_msgs::Grasp &grasp, 00148 const std::vector<double> &grasp_joint_angles, 00149 GraspExecutionInfo &execution_info) 00150 { 00151 geometry_msgs::PoseStamped grasp_pose; 00152 grasp_pose.pose = grasp.grasp_pose; 00153 grasp_pose.header.frame_id = pickup_goal.target.reference_frame_id; 00154 grasp_pose.header.stamp = ros::Time(0); 00155 00156 float actual_lift_distance; 00157 int error_code = 00158 mechInterface().getInterpolatedIK(pickup_goal.arm_name, 00159 grasp_pose, 00160 pickup_goal.lift.direction, pickup_goal.lift.desired_distance, 00161 grasp_joint_angles, 00162 grasp.grasp_posture, 00163 collisionOperationsForLift(pickup_goal, grasp), 00164 linkPaddingForLift(pickup_goal, grasp), 00165 false, execution_info.lift_trajectory_, actual_lift_distance); 00166 ROS_DEBUG_NAMED("manipulation"," Lift distance: actual %f, min %f and desired %f", 00167 actual_lift_distance, pickup_goal.lift.min_distance, pickup_goal.lift.desired_distance); 00168 00169 if (actual_lift_distance < pickup_goal.lift.min_distance - EPS) 00170 { 00171 ROS_DEBUG_NAMED("manipulation"," Lift trajectory below min. threshold"); 00172 if (marker_publisher_) marker_publisher_->colorGraspMarker(execution_info.marker_id_, 0.0, 0.0, 1.0); 00173 if (execution_info.lift_trajectory_.points.empty()) 00174 { 00175 ROS_DEBUG_NAMED("manipulation"," Lift trajectory empty; problem is with grasp location"); 00176 if (error_code == ArmNavigationErrorCodes::COLLISION_CONSTRAINTS_VIOLATED) 00177 return Result(GraspResult::GRASP_IN_COLLISION, true); 00178 else if (error_code == ArmNavigationErrorCodes::JOINT_LIMITS_VIOLATED) 00179 return Result(GraspResult::GRASP_OUT_OF_REACH, true); 00180 else return Result(GraspResult::GRASP_UNFEASIBLE, true); 00181 } 00182 if (error_code == ArmNavigationErrorCodes::COLLISION_CONSTRAINTS_VIOLATED) 00183 return Result(GraspResult::LIFT_IN_COLLISION, true); 00184 else if (error_code == ArmNavigationErrorCodes::JOINT_LIMITS_VIOLATED) 00185 return Result(GraspResult::LIFT_OUT_OF_REACH, true); 00186 else return Result(GraspResult::LIFT_UNFEASIBLE, true); 00187 } 00188 00189 return Result(GraspResult::SUCCESS, true); 00190 } 00191 00195 arm_navigation_msgs::OrderedCollisionOperations 00196 GraspTesterWithApproach::collisionOperationsForGrasp(const object_manipulation_msgs::PickupGoal &pickup_goal, 00197 const object_manipulation_msgs::Grasp &grasp) 00198 { 00199 arm_navigation_msgs::OrderedCollisionOperations ord; 00200 arm_navigation_msgs::CollisionOperation coll; 00201 coll.object1 = handDescription().gripperCollisionName(pickup_goal.arm_name); 00202 coll.operation = arm_navigation_msgs::CollisionOperation::DISABLE; 00203 if (!pickup_goal.collision_object_name.empty()) 00204 { 00205 coll.object2 = pickup_goal.collision_object_name; 00206 ord.collision_operations.push_back(coll); 00207 } 00208 if (pickup_goal.allow_gripper_support_collision) 00209 { 00210 coll.object2 = pickup_goal.collision_support_surface_name; 00211 ord.collision_operations.push_back(coll); 00212 } 00213 00214 coll.object1 = pickup_goal.collision_object_name; 00215 //This disables all collisions with the object. Ignore possible collisions of the robot with the object 00216 //during the push-grasp. We need all the capture region to be able to do this safely. Or we can disable 00217 //collisions just with the forearm, which should work almost always but still theoretially is not the right 00218 //thing to do. 00219 coll.object2 = arm_navigation_msgs::CollisionOperation::COLLISION_SET_ALL; 00220 ord.collision_operations.push_back(coll); 00221 00222 for (unsigned int i = 0; i < grasp.moved_obstacles.size(); i++) 00223 { 00224 ROS_DEBUG_NAMED("manipulation"," Disabling all collisions for grasp against moved obstacle %s", 00225 grasp.moved_obstacles[i].collision_name.c_str()); 00226 coll.object1 = grasp.moved_obstacles[i].collision_name; 00227 //This disables all collisions with the object. Ignore possible collisions of the robot with the object 00228 //during the push-grasp. We need all the capture region to be able to do this safely. Or we can disable 00229 //collisions just with the forearm, which should work almost always but still theoretially is not the right 00230 //thing to do. 00231 coll.object2 = arm_navigation_msgs::CollisionOperation::COLLISION_SET_ALL; 00232 ord.collision_operations.push_back(coll); 00233 } 00234 00235 ord.collision_operations = concat(ord.collision_operations, 00236 pickup_goal.additional_collision_operations.collision_operations); 00237 return ord; 00238 } 00239 00241 std::vector<arm_navigation_msgs::LinkPadding> 00242 GraspTesterWithApproach::linkPaddingForGrasp(const object_manipulation_msgs::PickupGoal &pickup_goal, 00243 const object_manipulation_msgs::Grasp&) 00244 { 00245 return concat(MechanismInterface::gripperPadding(pickup_goal.arm_name, 0.0), 00246 pickup_goal.additional_link_padding); 00247 } 00248 00249 GraspResult 00250 GraspTesterWithApproach::getInterpolatedIKForGrasp(const object_manipulation_msgs::PickupGoal &pickup_goal, 00251 const object_manipulation_msgs::Grasp &grasp, 00252 GraspExecutionInfo &execution_info) 00253 { 00254 //get the grasp pose in the right frame 00255 geometry_msgs::PoseStamped grasp_pose_stamped; 00256 grasp_pose_stamped.pose = grasp.grasp_pose; 00257 grasp_pose_stamped.header.frame_id = pickup_goal.target.reference_frame_id; 00258 grasp_pose_stamped.header.stamp = ros::Time(0); 00259 00260 //use the opposite of the approach direction as we are going backwards, from grasp to pre-grasp 00261 geometry_msgs::Vector3Stamped direction; 00262 direction.header.stamp = ros::Time::now(); 00263 direction.header.frame_id = handDescription().gripperFrame(pickup_goal.arm_name); 00264 direction.vector = mechInterface().negate( handDescription().approachDirection(pickup_goal.arm_name) ); 00265 00266 std::vector<double> empty; 00267 //remember to pass that we want to flip the trajectory 00268 float actual_approach_distance; 00269 int error_code = mechInterface().getInterpolatedIK(pickup_goal.arm_name, 00270 grasp_pose_stamped, 00271 direction, grasp.desired_approach_distance, 00272 empty, 00273 grasp.pre_grasp_posture, 00274 collisionOperationsForGrasp(pickup_goal, grasp), 00275 linkPaddingForGrasp(pickup_goal, grasp), 00276 true, execution_info.approach_trajectory_, 00277 actual_approach_distance); 00278 ROS_DEBUG_NAMED("manipulation"," Grasp executor approach distance: actual (%f), min(%f) and desired (%f)", 00279 actual_approach_distance, grasp.min_approach_distance, grasp.desired_approach_distance); 00280 00281 if ( actual_approach_distance < grasp.min_approach_distance - EPS) 00282 { 00283 ROS_DEBUG_NAMED("manipulation"," Grasp executor: interpolated IK for grasp below min threshold"); 00284 if (execution_info.approach_trajectory_.points.empty()) 00285 { 00286 ROS_DEBUG_NAMED("manipulation"," Grasp executor: interpolated IK empty, problem is with grasp location"); 00287 if (marker_publisher_) marker_publisher_->colorGraspMarker(execution_info.marker_id_, 1.0, 1.0, 0.0); //yellow 00288 if (error_code == ArmNavigationErrorCodes::COLLISION_CONSTRAINTS_VIOLATED) 00289 return Result(GraspResult::GRASP_IN_COLLISION, true); 00290 else if (error_code == ArmNavigationErrorCodes::JOINT_LIMITS_VIOLATED) 00291 return Result(GraspResult::GRASP_OUT_OF_REACH, true); 00292 else return Result(GraspResult::GRASP_UNFEASIBLE, true); 00293 } 00294 if (marker_publisher_) marker_publisher_->colorGraspMarker(execution_info.marker_id_, 0.0, 1.0, 1.0); //cyan 00295 if (error_code == ArmNavigationErrorCodes::COLLISION_CONSTRAINTS_VIOLATED) 00296 return Result(GraspResult::PREGRASP_IN_COLLISION, true); 00297 else if (error_code == ArmNavigationErrorCodes::JOINT_LIMITS_VIOLATED) 00298 return Result(GraspResult::PREGRASP_OUT_OF_REACH, true); 00299 else return Result(GraspResult::PREGRASP_UNFEASIBLE, true); 00300 } 00301 00302 return Result(GraspResult::SUCCESS, true); 00303 } 00304 00305 void GraspTesterWithApproach::testGrasp(const object_manipulation_msgs::PickupGoal &pickup_goal, 00306 const object_manipulation_msgs::Grasp &grasp, 00307 GraspExecutionInfo &execution_info) 00308 { 00309 if (marker_publisher_) marker_publisher_->colorGraspMarker(execution_info.marker_id_, 1.0, 0.0, 0.0); //red 00310 00311 execution_info.result_ = getInterpolatedIKForGrasp(pickup_goal, grasp, execution_info); 00312 if ( execution_info.result_.result_code != GraspResult::SUCCESS ) 00313 { 00314 ROS_DEBUG_NAMED("manipulation"," Grasp executor: failed to generate approach trajectory"); 00315 return; 00316 } 00317 00318 //check for lift trajectory starting from grasp solution 00319 std::vector<double> grasp_joint_angles = execution_info.approach_trajectory_.points.back().positions; 00320 execution_info.result_ = getInterpolatedIKForLift(pickup_goal, grasp, grasp_joint_angles, execution_info); 00321 if (execution_info.result_.result_code != GraspResult::SUCCESS) 00322 { 00323 ROS_DEBUG_NAMED("manipulation"," Grasp executor: failed to generate lift trajectory"); 00324 return; 00325 } 00326 00327 //check if the first pose in grasp trajectory is valid 00328 //when we check from pre-grasp to grasp we use custom link padding, so we need to check here 00329 //if the initial pose is feasible with default padding; otherwise, move_arm might refuse to 00330 //take us there 00331 if ( !mechInterface().checkStateValidity(pickup_goal.arm_name, 00332 execution_info.approach_trajectory_.points.front().positions, 00333 pickup_goal.additional_collision_operations, 00334 pickup_goal.additional_link_padding) ) 00335 { 00336 ROS_DEBUG_NAMED("manipulation"," Grasp executor: initial pose in grasp trajectory is unfeasible " 00337 "with default padding"); 00338 execution_info.result_ = Result(GraspResult::PREGRASP_UNFEASIBLE, true); 00339 return; 00340 } 00341 ROS_DEBUG_NAMED("manipulation"," Grasp executor: goal pose for move arm passed validity test"); 00342 00343 //check if the last pose in lift trajectory is valid 00344 //when we check for lift we use custom link padding, so we need to check here if the last pose 00345 //is feasible with default padding; otherwise, move_arm might refuse to take us out of there 00346 if ( pickup_goal.lift.min_distance != 0 && 00347 !mechInterface().checkStateValidity(pickup_goal.arm_name, 00348 execution_info.lift_trajectory_.points.back().positions, 00349 collisionOperationsForLift(pickup_goal, grasp), 00350 pickup_goal.additional_link_padding) ) 00351 { 00352 ROS_DEBUG_NAMED("manipulation"," Grasp executor: last pose in lift trajectory is unfeasible with default padding"); 00353 execution_info.result_ = Result(GraspResult::LIFT_UNFEASIBLE, true); 00354 return; 00355 } 00356 ROS_DEBUG_NAMED("manipulation"," Grasp executor: final lift pose passed validity test"); 00357 } 00358 00360 arm_navigation_msgs::OrderedCollisionOperations 00361 UnsafeGraspTester::collisionOperationsForGrasp(const object_manipulation_msgs::PickupGoal &pickup_goal, 00362 const object_manipulation_msgs::Grasp&) 00363 { 00364 arm_navigation_msgs::OrderedCollisionOperations ord; 00365 arm_navigation_msgs::CollisionOperation coll; 00366 coll.object1 = arm_navigation_msgs::CollisionOperation::COLLISION_SET_ALL; 00367 coll.object2 = arm_navigation_msgs::CollisionOperation::COLLISION_SET_ALL; 00368 coll.operation = arm_navigation_msgs::CollisionOperation::DISABLE; 00369 ord.collision_operations.push_back(coll); 00370 ord.collision_operations = concat(ord.collision_operations, 00371 pickup_goal.additional_collision_operations.collision_operations); 00372 return ord; 00373 } 00374 00376 arm_navigation_msgs::OrderedCollisionOperations 00377 UnsafeGraspTester::collisionOperationsForLift(const object_manipulation_msgs::PickupGoal &pickup_goal, 00378 const object_manipulation_msgs::Grasp&) 00379 { 00380 arm_navigation_msgs::OrderedCollisionOperations ord; 00381 arm_navigation_msgs::CollisionOperation coll; 00382 coll.object1 = arm_navigation_msgs::CollisionOperation::COLLISION_SET_ALL; 00383 coll.object2 = arm_navigation_msgs::CollisionOperation::COLLISION_SET_ALL; 00384 coll.operation = arm_navigation_msgs::CollisionOperation::DISABLE; 00385 ord.collision_operations.push_back(coll); 00386 ord.collision_operations = concat(ord.collision_operations, 00387 pickup_goal.additional_collision_operations.collision_operations); 00388 return ord; 00389 } 00390 00391 00392 // ---------------------------- Grasp Performers --------------------------------- 00393 00394 void StandardGraspPerformer::performGrasp(const object_manipulation_msgs::PickupGoal &pickup_goal, 00395 const object_manipulation_msgs::Grasp &grasp, 00396 GraspExecutionInfo &execution_info) 00397 { 00398 execution_info.result_ = approachAndGrasp(pickup_goal, grasp, execution_info); 00399 if (execution_info.result_.result_code != GraspResult::SUCCESS) return; 00400 00401 //check if there is anything in gripper; if not, open gripper and retreat 00402 if (!mechInterface().graspPostureQuery(pickup_goal.arm_name, grasp)) 00403 { 00404 ROS_DEBUG_NAMED("manipulation","Hand reports that grasp was not successfully executed; " 00405 "releasing object and retreating"); 00406 mechInterface().handPostureGraspAction(pickup_goal.arm_name, grasp, 00407 object_manipulation_msgs::GraspHandPostureExecutionGoal::RELEASE, -1); 00408 retreat(pickup_goal, grasp, execution_info); 00409 execution_info.result_ = Result(GraspResult::GRASP_FAILED, false); 00410 return; 00411 } 00412 00413 //attach object to gripper 00414 if (!pickup_goal.collision_object_name.empty()) 00415 { 00416 mechInterface().attachObjectToGripper(pickup_goal.arm_name, pickup_goal.collision_object_name); 00417 } 00418 00419 execution_info.result_ = lift(pickup_goal, grasp, execution_info); 00420 } 00421 00422 00423 object_manipulation_msgs::GraspResult 00424 StandardGraspPerformer::approachAndGrasp(const object_manipulation_msgs::PickupGoal &pickup_goal, 00425 const object_manipulation_msgs::Grasp &grasp, 00426 GraspExecutionInfo &execution_info) 00427 { 00428 ROS_INFO("Additional collision operations:"); 00429 for (unsigned int i = 0; i < pickup_goal.additional_collision_operations.collision_operations.size(); i++) 00430 { 00431 ROS_INFO_STREAM("\t for objects " << pickup_goal.additional_collision_operations.collision_operations[i].object1 << " and " << pickup_goal.additional_collision_operations.collision_operations[i].object2 ); 00432 } 00433 if ( !mechInterface().attemptMoveArmToGoal(pickup_goal.arm_name, 00434 execution_info.approach_trajectory_.points.front().positions, 00435 pickup_goal.additional_collision_operations, 00436 pickup_goal.additional_link_padding) ) 00437 { 00438 ROS_DEBUG_NAMED("manipulation"," Grasp executor: move_arm to pre-grasp reports failure"); 00439 if (marker_publisher_) marker_publisher_->colorGraspMarker(execution_info.marker_id_, 1.0, 0.5, 0.0); //orange-ish 00440 return Result(GraspResult::MOVE_ARM_FAILED, true); 00441 } 00442 00443 mechInterface().handPostureGraspAction(pickup_goal.arm_name, grasp, 00444 object_manipulation_msgs::GraspHandPostureExecutionGoal::PRE_GRASP, -1); 00445 00446 mechInterface().attemptTrajectory(pickup_goal.arm_name, execution_info.approach_trajectory_, true); 00447 00448 mechInterface().handPostureGraspAction(pickup_goal.arm_name, grasp, 00449 object_manipulation_msgs::GraspHandPostureExecutionGoal::GRASP, pickup_goal.max_contact_force); 00450 00451 if (marker_publisher_) marker_publisher_->colorGraspMarker(execution_info.marker_id_, 0.0, 1.0, 0.0); //green 00452 return Result(GraspResult::SUCCESS, true); 00453 } 00454 00455 object_manipulation_msgs::GraspResult 00456 StandardGraspPerformer::lift(const object_manipulation_msgs::PickupGoal &pickup_goal, 00457 const object_manipulation_msgs::Grasp &grasp, 00458 GraspExecutionInfo &execution_info) 00459 { 00460 if (execution_info.lift_trajectory_.points.empty()) 00461 { 00462 ROS_ERROR(" Grasp executor: lift trajectory not set"); 00463 return Result(GraspResult::LIFT_FAILED, false); 00464 } 00465 mechInterface().attemptTrajectory(pickup_goal.arm_name, execution_info.lift_trajectory_, true); 00466 return Result(GraspResult::SUCCESS, true); 00467 00468 } 00469 00470 object_manipulation_msgs::GraspResult 00471 StandardGraspPerformer::retreat(const object_manipulation_msgs::PickupGoal &pickup_goal, 00472 const object_manipulation_msgs::Grasp &grasp, 00473 GraspExecutionInfo &execution_info) 00474 { 00475 arm_navigation_msgs::OrderedCollisionOperations ord; 00476 arm_navigation_msgs::CollisionOperation coll; 00477 //disable collision between gripper and object 00478 coll.object1 = handDescription().gripperCollisionName(pickup_goal.arm_name); 00479 coll.object2 = pickup_goal.collision_object_name; 00480 coll.operation = arm_navigation_msgs::CollisionOperation::DISABLE; 00481 ord.collision_operations.push_back(coll); 00482 //disable collision between gripper and table 00483 coll.object2 = pickup_goal.collision_support_surface_name; 00484 ord.collision_operations.push_back(coll); 00485 ord.collision_operations = concat(ord.collision_operations, 00486 pickup_goal.additional_collision_operations.collision_operations); 00487 00488 geometry_msgs::Vector3Stamped direction; 00489 direction.header.stamp = ros::Time::now(); 00490 direction.header.frame_id = handDescription().gripperFrame(pickup_goal.arm_name); 00491 direction.vector = mechInterface().negate( handDescription().approachDirection(pickup_goal.arm_name) ); 00492 00493 //even if the complete retreat trajectory is not possible, execute as many 00494 //steps as we can (pass min_distance = 0) 00495 float retreat_distance = grasp.min_approach_distance; 00496 float actual_distance; 00497 if (!mechInterface().translateGripper(pickup_goal.arm_name, direction, 00498 ord, pickup_goal.additional_link_padding, 00499 retreat_distance, 0, actual_distance)) 00500 { 00501 ROS_ERROR(" Grasp executor: failed to retreat gripper at all"); 00502 return Result(GraspResult::RETREAT_FAILED, false); 00503 } 00504 if (actual_distance < retreat_distance) 00505 { 00506 ROS_WARN(" Grasp executor: only partial retreat (%f) succeeeded", actual_distance); 00507 return Result(GraspResult::RETREAT_FAILED, false); 00508 } 00509 return Result(GraspResult::SUCCESS, true); 00510 } 00511 00512 object_manipulation_msgs::GraspResult 00513 ReactiveGraspPerformer::nonReactiveLift(const object_manipulation_msgs::PickupGoal &pickup_goal, 00514 const object_manipulation_msgs::Grasp &grasp, 00515 GraspExecutionInfo &execution_info) 00516 { 00517 arm_navigation_msgs::OrderedCollisionOperations ord; 00518 arm_navigation_msgs::CollisionOperation coll; 00519 coll.object1 = handDescription().gripperCollisionName(pickup_goal.arm_name); 00520 coll.operation = arm_navigation_msgs::CollisionOperation::DISABLE; 00521 //disable collisions between end-effector and table 00522 if (!pickup_goal.collision_support_surface_name.empty()) 00523 { 00524 coll.object2 = pickup_goal.collision_support_surface_name; 00525 ord.collision_operations.push_back(coll); 00526 } 00527 //disable collisions between attached object and table 00528 if (!pickup_goal.collision_support_surface_name.empty() && !pickup_goal.collision_object_name.empty()) 00529 { 00530 coll.object1 = pickup_goal.collision_object_name; 00531 coll.object2 = pickup_goal.collision_support_surface_name; 00532 ord.collision_operations.push_back(coll); 00533 } 00534 ord.collision_operations = concat(ord.collision_operations, 00535 pickup_goal.additional_collision_operations.collision_operations); 00536 00537 float actual_distance; 00538 if (!mechInterface().translateGripper(pickup_goal.arm_name, 00539 pickup_goal.lift.direction, 00540 ord, pickup_goal.additional_link_padding, 00541 pickup_goal.lift.desired_distance, 0.0, actual_distance)) 00542 { 00543 ROS_DEBUG_NAMED("manipulation"," Reactive grasp executor: lift performed no steps"); 00544 return Result(GraspResult::LIFT_FAILED, false); 00545 } 00546 if (actual_distance < pickup_goal.lift.min_distance) 00547 { 00548 ROS_DEBUG_NAMED("manipulation"," Reactive grasp executor: lift distance below min threshold "); 00549 return Result(GraspResult::LIFT_FAILED, false); 00550 } 00551 if (actual_distance < pickup_goal.lift.desired_distance) 00552 { 00553 ROS_DEBUG_NAMED("manipulation"," Reactive grasp executor: lift distance below desired, but above min threshold"); 00554 } 00555 else 00556 { 00557 ROS_DEBUG_NAMED("manipulation"," Reactive grasp executor: desired lift distance executed"); 00558 } 00559 return Result(GraspResult::SUCCESS, true); 00560 } 00561 00562 object_manipulation_msgs::GraspResult 00563 ReactiveGraspPerformer::reactiveLift(const object_manipulation_msgs::PickupGoal &pickup_goal, 00564 const object_manipulation_msgs::Grasp &grasp, 00565 GraspExecutionInfo &execution_info) 00566 { 00567 object_manipulation_msgs::ReactiveLiftGoal reactive_lift_goal; 00568 reactive_lift_goal.lift = pickup_goal.lift; 00569 reactive_lift_goal.arm_name = pickup_goal.arm_name; 00570 reactive_lift_goal.target = pickup_goal.target; 00571 reactive_lift_goal.trajectory = execution_info.lift_trajectory_; 00572 reactive_lift_goal.collision_support_surface_name = pickup_goal.collision_support_surface_name; 00573 00574 //give the reactive lift 1 minute to do its thing 00575 ros::Duration timeout = ros::Duration(60.0); 00576 mechInterface().reactive_lift_action_client_.client(pickup_goal.arm_name).sendGoal(reactive_lift_goal); 00577 if ( !mechInterface().reactive_lift_action_client_.client(pickup_goal.arm_name).waitForResult(timeout) ) 00578 { 00579 ROS_ERROR(" Reactive lift timed out"); 00580 return Result(GraspResult::LIFT_FAILED, false); 00581 } 00582 object_manipulation_msgs::ReactiveLiftResult reactive_lift_result = 00583 *mechInterface().reactive_lift_action_client_.client(pickup_goal.arm_name).getResult(); 00584 if (reactive_lift_result.manipulation_result.value != reactive_lift_result.manipulation_result.SUCCESS) 00585 { 00586 ROS_ERROR("Reactive lift failed with error code %d", reactive_lift_result.manipulation_result.value); 00587 return Result(GraspResult::LIFT_FAILED, false); 00588 } 00589 return Result(GraspResult::SUCCESS, true); 00590 } 00591 00592 object_manipulation_msgs::GraspResult 00593 ReactiveGraspPerformer::lift(const object_manipulation_msgs::PickupGoal &pickup_goal, 00594 const object_manipulation_msgs::Grasp &grasp, 00595 GraspExecutionInfo &execution_info) 00596 { 00597 if (pickup_goal.use_reactive_lift) 00598 { 00599 return reactiveLift(pickup_goal, grasp, execution_info); 00600 } 00601 else 00602 { 00603 return nonReactiveLift(pickup_goal, grasp, execution_info); 00604 } 00605 } 00606 00607 object_manipulation_msgs::GraspResult 00608 ReactiveGraspPerformer::approachAndGrasp(const object_manipulation_msgs::PickupGoal &pickup_goal, 00609 const object_manipulation_msgs::Grasp &grasp, 00610 GraspExecutionInfo &execution_info) 00611 { 00612 if ( !mechInterface().attemptMoveArmToGoal(pickup_goal.arm_name, 00613 execution_info.approach_trajectory_.points.front().positions, 00614 pickup_goal.additional_collision_operations, 00615 pickup_goal.additional_link_padding) ) 00616 { 00617 ROS_DEBUG_NAMED("manipulation"," Grasp executor: move_arm to pre-grasp reports failure"); 00618 if (marker_publisher_) marker_publisher_->colorGraspMarker(execution_info.marker_id_, 1.0, 0.5, 0.0); //orange-ish 00619 return Result(GraspResult::MOVE_ARM_FAILED, true); 00620 } 00621 00622 mechInterface().handPostureGraspAction(pickup_goal.arm_name, grasp, 00623 object_manipulation_msgs::GraspHandPostureExecutionGoal::PRE_GRASP, -1); 00624 00625 geometry_msgs::PoseStamped final_grasp_pose_stamped; 00626 final_grasp_pose_stamped.pose = grasp.grasp_pose; 00627 final_grasp_pose_stamped.header.frame_id = pickup_goal.target.reference_frame_id; 00628 final_grasp_pose_stamped.header.stamp = ros::Time(0); 00629 00630 object_manipulation_msgs::ReactiveGraspGoal reactive_grasp_goal; 00631 reactive_grasp_goal.arm_name = pickup_goal.arm_name; 00632 reactive_grasp_goal.target = pickup_goal.target; 00633 reactive_grasp_goal.final_grasp_pose = final_grasp_pose_stamped; 00634 reactive_grasp_goal.trajectory = execution_info.approach_trajectory_; 00635 reactive_grasp_goal.collision_support_surface_name = pickup_goal.collision_support_surface_name; 00636 reactive_grasp_goal.pre_grasp_posture = grasp.pre_grasp_posture; 00637 reactive_grasp_goal.grasp_posture = grasp.grasp_posture; 00638 00639 //give the reactive grasp 3 minutes to do its thing 00640 ros::Duration timeout = ros::Duration(180.0); 00641 mechInterface().reactive_grasp_action_client_.client(pickup_goal.arm_name).sendGoal(reactive_grasp_goal); 00642 if ( !mechInterface().reactive_grasp_action_client_.client(pickup_goal.arm_name).waitForResult(timeout) ) 00643 { 00644 ROS_ERROR(" Reactive grasp timed out"); 00645 return Result(GraspResult::GRASP_FAILED, false); 00646 } 00647 object_manipulation_msgs::ReactiveGraspResult reactive_grasp_result = 00648 *mechInterface().reactive_grasp_action_client_.client(pickup_goal.arm_name).getResult(); 00649 if (reactive_grasp_result.manipulation_result.value != reactive_grasp_result.manipulation_result.SUCCESS) 00650 { 00651 ROS_ERROR("Reactive grasp failed with error code %d", reactive_grasp_result.manipulation_result.value); 00652 return Result(GraspResult::GRASP_FAILED, false); 00653 } 00654 if (marker_publisher_) marker_publisher_->colorGraspMarker(execution_info.marker_id_, 0.0, 1.0, 0.0); //green 00655 return Result(GraspResult::SUCCESS, true); 00656 } 00657 00658 object_manipulation_msgs::GraspResult 00659 UnsafeGraspPerformer::approachAndGrasp(const object_manipulation_msgs::PickupGoal &pickup_goal, 00660 const object_manipulation_msgs::Grasp &grasp, 00661 GraspExecutionInfo &execution_info) 00662 { 00663 ROS_DEBUG_NAMED("manipulation", "executing unsafe grasp"); 00664 00665 //compute the pre-grasp pose 00666 //get the grasp pose in the right frame 00667 geometry_msgs::PoseStamped grasp_pose_stamped; 00668 grasp_pose_stamped.pose = grasp.grasp_pose; 00669 grasp_pose_stamped.header.frame_id = pickup_goal.target.reference_frame_id; 00670 grasp_pose_stamped.header.stamp = ros::Time(0); 00671 00672 //use the opposite of the approach direction as we are going backwards, from grasp to pre-grasp 00673 geometry_msgs::Vector3Stamped direction; 00674 direction.header.stamp = ros::Time::now(); 00675 direction.header.frame_id = handDescription().gripperFrame(pickup_goal.arm_name); 00676 direction.vector = mechInterface().negate( handDescription().approachDirection(pickup_goal.arm_name) ); 00677 00678 //make sure the input is normalized 00679 geometry_msgs::Vector3Stamped direction_norm = direction; 00680 direction_norm.vector = mechInterface().normalize(direction.vector); 00681 00682 //multiply the approach direction by the desired length and translate the grasp pose back along it 00683 double desired_trajectory_length = fabs(grasp.desired_approach_distance); 00684 direction_norm.vector.x *= desired_trajectory_length; 00685 direction_norm.vector.y *= desired_trajectory_length; 00686 direction_norm.vector.z *= desired_trajectory_length; 00687 geometry_msgs::PoseStamped pregrasp_pose = mechInterface().translateGripperPose(direction_norm, grasp_pose_stamped, 00688 pickup_goal.arm_name); 00689 00690 //move to the pre-grasp using the Cartesian controller 00691 mechInterface().moveArmToPoseCartesian(pickup_goal.arm_name, pregrasp_pose, ros::Duration(15.0), 00692 .0015, .01, 0.02, 0.16, 0.005, 0.087, 0.1, 00693 execution_info.approach_trajectory_.points.front().positions); 00694 00695 //move to the pre-grasp hand posture 00696 mechInterface().handPostureGraspAction(pickup_goal.arm_name, grasp, 00697 object_manipulation_msgs::GraspHandPostureExecutionGoal::PRE_GRASP, -1); 00698 00699 //if not using reactive grasping, execute the unnormalized interpolated trajectory from pre-grasp to grasp 00700 if(!pickup_goal.use_reactive_execution) 00701 { 00702 mechInterface().attemptTrajectory(pickup_goal.arm_name, execution_info.approach_trajectory_, true); 00703 mechInterface().handPostureGraspAction(pickup_goal.arm_name, grasp, 00704 object_manipulation_msgs::GraspHandPostureExecutionGoal::GRASP, pickup_goal.max_contact_force); 00705 } 00706 00707 //otherwise, call reactive grasping 00708 else 00709 { 00710 geometry_msgs::PoseStamped final_grasp_pose_stamped; 00711 final_grasp_pose_stamped.pose = grasp.grasp_pose; 00712 final_grasp_pose_stamped.header.frame_id = pickup_goal.target.reference_frame_id; 00713 final_grasp_pose_stamped.header.stamp = ros::Time(0); 00714 00715 object_manipulation_msgs::ReactiveGraspGoal reactive_grasp_goal; 00716 reactive_grasp_goal.arm_name = pickup_goal.arm_name; 00717 reactive_grasp_goal.target = pickup_goal.target; 00718 reactive_grasp_goal.final_grasp_pose = final_grasp_pose_stamped; 00719 reactive_grasp_goal.trajectory = execution_info.approach_trajectory_; 00720 reactive_grasp_goal.collision_support_surface_name = pickup_goal.collision_support_surface_name; 00721 reactive_grasp_goal.pre_grasp_posture = grasp.pre_grasp_posture; 00722 reactive_grasp_goal.grasp_posture = grasp.grasp_posture; 00723 00724 //give the reactive grasp 3 minutes to do its thing 00725 ros::Duration timeout = ros::Duration(180.0); 00726 mechInterface().reactive_grasp_action_client_.client(pickup_goal.arm_name).sendGoal(reactive_grasp_goal); 00727 if ( !mechInterface().reactive_grasp_action_client_.client(pickup_goal.arm_name).waitForResult(timeout) ) 00728 { 00729 ROS_ERROR(" Reactive grasp timed out"); 00730 return Result(GraspResult::GRASP_FAILED, false); 00731 } 00732 object_manipulation_msgs::ReactiveGraspResult reactive_grasp_result = 00733 *mechInterface().reactive_grasp_action_client_.client(pickup_goal.arm_name).getResult(); 00734 if (reactive_grasp_result.manipulation_result.value != reactive_grasp_result.manipulation_result.SUCCESS) 00735 { 00736 ROS_ERROR("Reactive grasp failed with error code %d", reactive_grasp_result.manipulation_result.value); 00737 return Result(GraspResult::GRASP_FAILED, false); 00738 } 00739 } 00740 if (marker_publisher_) marker_publisher_->colorGraspMarker(execution_info.marker_id_, 0.0, 1.0, 0.0); //green 00741 return Result(GraspResult::SUCCESS, true); 00742 } 00743 00744 }