grasp_executor_with_approach.cpp
Go to the documentation of this file.
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


object_manipulator
Author(s): Matei Ciocarlie and Kaijen Hsiao
autogenerated on Thu Jan 2 2014 11:39:04