$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 // Author(s): Matei Ciocarlie 00035 00036 #include "object_manipulator/grasp_execution/grasp_executor_with_approach.h" 00037 00038 #include "object_manipulator/tools/hand_description.h" 00039 #include "object_manipulator/tools/vector_tools.h" 00040 00041 //#include <demo_synchronizer/synchronizer_client.h> 00042 00043 using object_manipulation_msgs::GraspResult; 00044 using arm_navigation_msgs::ArmNavigationErrorCodes; 00045 00046 namespace object_manipulator { 00047 00049 arm_navigation_msgs::OrderedCollisionOperations 00050 GraspExecutorWithApproach::collisionOperationsForGrasp(const object_manipulation_msgs::PickupGoal &pickup_goal) 00051 { 00052 arm_navigation_msgs::OrderedCollisionOperations ord; 00053 arm_navigation_msgs::CollisionOperation coll; 00054 coll.object1 = handDescription().gripperCollisionName(pickup_goal.arm_name); 00055 coll.operation = arm_navigation_msgs::CollisionOperation::DISABLE; 00056 if (!pickup_goal.collision_object_name.empty()) 00057 { 00058 coll.object2 = pickup_goal.collision_object_name; 00059 ord.collision_operations.push_back(coll); 00060 } 00061 if (pickup_goal.allow_gripper_support_collision) 00062 { 00063 coll.object2 = pickup_goal.collision_support_surface_name; 00064 ord.collision_operations.push_back(coll); 00065 } 00066 /* 00067 // not sure we need this anymore 00068 ROS_DEBUG_NAMED("manipulation","Disabling collisions between fingertips and table for grasp"); 00069 for (size_t i=0; i<handDescription().fingertipLinks(pickup_goal.arm_name).size(); i++) 00070 { 00071 coll.object1 = pickup_goal.collision_support_surface_name; 00072 coll.object2 = handDescription().fingertipLinks(pickup_goal.arm_name).at(i); 00073 ord.collision_operations.push_back(coll); 00074 } 00075 */ 00076 ord.collision_operations = concat(ord.collision_operations, 00077 pickup_goal.additional_collision_operations.collision_operations); 00078 return ord; 00079 } 00080 00082 std::vector<arm_navigation_msgs::LinkPadding> 00083 GraspExecutorWithApproach::linkPaddingForGrasp(const object_manipulation_msgs::PickupGoal &pickup_goal) 00084 { 00085 //return concat(MechanismInterface::fingertipPadding(pickup_goal.arm_name, 0.0), 00086 // pickup_goal.additional_link_padding); 00087 return concat(MechanismInterface::gripperPadding(pickup_goal.arm_name, 0.0), 00088 pickup_goal.additional_link_padding); 00089 } 00090 00091 GraspResult 00092 GraspExecutorWithApproach::getInterpolatedIKForGrasp(const object_manipulation_msgs::PickupGoal &pickup_goal, 00093 const object_manipulation_msgs::Grasp &grasp, 00094 trajectory_msgs::JointTrajectory &grasp_trajectory) 00095 { 00096 //get the grasp pose in the right frame 00097 geometry_msgs::PoseStamped grasp_pose_stamped; 00098 grasp_pose_stamped.pose = grasp.grasp_pose; 00099 grasp_pose_stamped.header.frame_id = pickup_goal.target.reference_frame_id; 00100 grasp_pose_stamped.header.stamp = ros::Time(0); 00101 00102 //use the opposite of the approach direction as we are going backwards, from grasp to pre-grasp 00103 geometry_msgs::Vector3Stamped direction; 00104 direction.header.stamp = ros::Time::now(); 00105 direction.header.frame_id = handDescription().gripperFrame(pickup_goal.arm_name); 00106 direction.vector = mechInterface().negate( handDescription().approachDirection(pickup_goal.arm_name) ); 00107 00108 std::vector<double> empty; 00109 //remember to pass that we want to flip the trajectory 00110 float actual_approach_distance; 00111 int error_code = mechInterface().getInterpolatedIK(pickup_goal.arm_name, 00112 grasp_pose_stamped, 00113 direction, grasp.desired_approach_distance, 00114 empty, 00115 grasp.pre_grasp_posture, 00116 collisionOperationsForGrasp(pickup_goal), 00117 linkPaddingForGrasp(pickup_goal), 00118 true, grasp_trajectory, actual_approach_distance); 00119 ROS_DEBUG_NAMED("manipulation"," Grasp executor approach distance: actual (%f), min(%f) and desired (%f)", 00120 actual_approach_distance, grasp.min_approach_distance, grasp.desired_approach_distance); 00121 00122 if ( actual_approach_distance < grasp.min_approach_distance) 00123 { 00124 ROS_DEBUG_NAMED("manipulation"," Grasp executor: interpolated IK for grasp below min threshold"); 00125 if (grasp_trajectory.points.empty()) 00126 { 00127 ROS_DEBUG_NAMED("manipulation"," Grasp executor: interpolated IK empty, problem is with grasp location"); 00128 if (marker_publisher_) marker_publisher_->colorGraspMarker(marker_id_, 1.0, 1.0, 0.0); //yellow 00129 if (error_code == ArmNavigationErrorCodes::COLLISION_CONSTRAINTS_VIOLATED) 00130 return Result(GraspResult::GRASP_IN_COLLISION, true); 00131 else if (error_code == ArmNavigationErrorCodes::JOINT_LIMITS_VIOLATED) 00132 return Result(GraspResult::GRASP_OUT_OF_REACH, true); 00133 else return Result(GraspResult::GRASP_UNFEASIBLE, true); 00134 } 00135 if (marker_publisher_) marker_publisher_->colorGraspMarker(marker_id_, 0.0, 1.0, 1.0); //cyan 00136 if (error_code == ArmNavigationErrorCodes::COLLISION_CONSTRAINTS_VIOLATED) 00137 return Result(GraspResult::PREGRASP_IN_COLLISION, true); 00138 else if (error_code == ArmNavigationErrorCodes::JOINT_LIMITS_VIOLATED) 00139 return Result(GraspResult::PREGRASP_OUT_OF_REACH, true); 00140 else return Result(GraspResult::PREGRASP_UNFEASIBLE, true); 00141 } 00142 00143 // note: here we used to check if the first state is valid with default padding and collision. That 00144 // check has been moved to prepareGrasp() so that it can be grouped together with other checks that 00145 // use similar planning scenes. 00146 00147 return Result(GraspResult::SUCCESS, true); 00148 } 00149 00150 00151 GraspResult GraspExecutorWithApproach::prepareGrasp(const object_manipulation_msgs::PickupGoal &pickup_goal, 00152 const object_manipulation_msgs::Grasp &grasp) 00153 { 00154 if (marker_publisher_) marker_publisher_->colorGraspMarker(marker_id_, 1.0, 0.0, 0.0); //red 00155 00156 //demo_synchronizer::getClient().sync(3, "Computing interpolated IK path from pre-grasp to grasp to lift"); 00157 //demo_synchronizer::getClient().rviz(3, "Collision models;Interpolated IK;IK contacts;Grasp execution"); 00158 00159 GraspResult result = getInterpolatedIKForGrasp(pickup_goal, grasp, interpolated_grasp_trajectory_); 00160 if ( result.result_code != GraspResult::SUCCESS ) 00161 { 00162 ROS_DEBUG_NAMED("manipulation"," Grasp executor: failed to generate grasp trajectory"); 00163 return result; 00164 } 00165 00166 //check for lift trajectory starting from grasp solution 00167 std::vector<double> grasp_joint_angles = interpolated_grasp_trajectory_.points.back().positions; 00168 result = getInterpolatedIKForLift(pickup_goal, grasp, grasp_joint_angles, interpolated_lift_trajectory_); 00169 if (result.result_code != GraspResult::SUCCESS) 00170 { 00171 ROS_DEBUG_NAMED("manipulation"," Grasp executor: failed to generate lift trajectory"); 00172 return result; 00173 } 00174 00175 //check if the first pose in grasp trajectory is valid 00176 //when we check from pre-grasp to grasp we use custom link padding, so we need to check here 00177 //if the initial pose is feasible with default padding; otherwise, move_arm might refuse to 00178 //take us there 00179 if ( !mechInterface().checkStateValidity(pickup_goal.arm_name, 00180 interpolated_grasp_trajectory_.points.front().positions, 00181 pickup_goal.additional_collision_operations, 00182 pickup_goal.additional_link_padding) ) 00183 { 00184 ROS_DEBUG_NAMED("manipulation"," Grasp executor: initial pose in grasp trajectory is unfeasible with default padding"); 00185 return Result(GraspResult::PREGRASP_UNFEASIBLE, true); 00186 } 00187 ROS_DEBUG_NAMED("manipulation"," Grasp executor: goal pose for move arm passed validity test"); 00188 00189 //check if the last pose in lift trajectory is valid 00190 //when we check for lift we use custom link padding, so we need to check here if the last pose 00191 //is feasible with default padding; otherwise, move_arm might refuse to take us out of there 00192 if ( pickup_goal.lift.min_distance != 0 && 00193 !mechInterface().checkStateValidity(pickup_goal.arm_name, interpolated_lift_trajectory_.points.back().positions, 00194 collisionOperationsForLift(pickup_goal), 00195 pickup_goal.additional_link_padding) ) 00196 { 00197 ROS_DEBUG_NAMED("manipulation"," Grasp executor: last pose in lift trajectory is unfeasible with default padding"); 00198 return Result(GraspResult::LIFT_UNFEASIBLE, true); 00199 } 00200 00201 return Result(GraspResult::SUCCESS, true); 00202 } 00203 00204 GraspResult 00205 GraspExecutorWithApproach::executeGrasp(const object_manipulation_msgs::PickupGoal &pickup_goal, 00206 const object_manipulation_msgs::Grasp &grasp) 00207 { 00208 //demo_synchronizer::getClient().sync(2, "Using motion planner to move arm to pre-grasp position"); 00209 //demo_synchronizer::getClient().rviz(1, "Collision models;Planning goal;Environment contacts;Collision map"); 00210 00211 if ( !mechInterface().attemptMoveArmToGoal(pickup_goal.arm_name, 00212 interpolated_grasp_trajectory_.points.front().positions, 00213 pickup_goal.additional_collision_operations, 00214 pickup_goal.additional_link_padding) ) 00215 { 00216 ROS_DEBUG_NAMED("manipulation"," Grasp executor: move_arm to pre-grasp reports failure"); 00217 if (marker_publisher_) marker_publisher_->colorGraspMarker(marker_id_, 1.0, 0.5, 0.0); //orange-ish 00218 return Result(GraspResult::MOVE_ARM_FAILED, true); 00219 } 00220 00221 mechInterface().handPostureGraspAction(pickup_goal.arm_name, grasp, 00222 object_manipulation_msgs::GraspHandPostureExecutionGoal::PRE_GRASP, -1); 00223 00224 //demo_synchronizer::getClient().sync(2, "Executing interpolated IK path from pre-grasp to grasp"); 00225 //demo_synchronizer::getClient().rviz(1, "Collision models"); 00226 00227 //execute the unnormalized interpolated trajectory from pre-grasp to grasp 00228 mechInterface().attemptTrajectory(pickup_goal.arm_name, interpolated_grasp_trajectory_, true); 00229 00230 mechInterface().handPostureGraspAction(pickup_goal.arm_name, grasp, 00231 object_manipulation_msgs::GraspHandPostureExecutionGoal::GRASP, pickup_goal.max_contact_force); 00232 00233 if (marker_publisher_) marker_publisher_->colorGraspMarker(marker_id_, 0.0, 1.0, 0.0); //green 00234 return Result(GraspResult::SUCCESS, true); 00235 } 00236 00241 GraspResult GraspExecutorWithApproach::retreat(const object_manipulation_msgs::PickupGoal &pickup_goal, 00242 const object_manipulation_msgs::Grasp &grasp) 00243 { 00244 arm_navigation_msgs::OrderedCollisionOperations ord; 00245 arm_navigation_msgs::CollisionOperation coll; 00246 //disable collision between gripper and object 00247 coll.object1 = handDescription().gripperCollisionName(pickup_goal.arm_name); 00248 coll.object2 = pickup_goal.collision_object_name; 00249 coll.operation = arm_navigation_msgs::CollisionOperation::DISABLE; 00250 ord.collision_operations.push_back(coll); 00251 //disable collision between gripper and table 00252 coll.object2 = pickup_goal.collision_support_surface_name; 00253 ord.collision_operations.push_back(coll); 00254 ord.collision_operations = concat(ord.collision_operations, 00255 pickup_goal.additional_collision_operations.collision_operations); 00256 00257 geometry_msgs::Vector3Stamped direction; 00258 direction.header.stamp = ros::Time::now(); 00259 direction.header.frame_id = handDescription().gripperFrame(pickup_goal.arm_name); 00260 direction.vector = mechInterface().negate( handDescription().approachDirection(pickup_goal.arm_name) ); 00261 00262 //even if the complete retreat trajectory is not possible, execute as many 00263 //steps as we can (pass min_distance = 0) 00264 float retreat_distance = grasp.min_approach_distance; 00265 float actual_distance; 00266 if (!mechInterface().translateGripper(pickup_goal.arm_name, direction, 00267 ord, pickup_goal.additional_link_padding, 00268 retreat_distance, 0, actual_distance)) 00269 { 00270 ROS_ERROR(" Grasp executor: failed to retreat gripper at all"); 00271 return Result(GraspResult::RETREAT_FAILED, false); 00272 } 00273 if (actual_distance < retreat_distance) 00274 { 00275 ROS_WARN(" Grasp executor: only partial retreat (%f) succeeeded", actual_distance); 00276 return Result(GraspResult::RETREAT_FAILED, false); 00277 } 00278 return Result(GraspResult::SUCCESS, true); 00279 } 00280 00281 } //namespace object_manipulator