00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <object_manipulator/place_execution/descend_retreat_place.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 arm_navigation_msgs::ArmNavigationErrorCodes;
00042 using object_manipulation_msgs::PlaceLocationResult;
00043
00044 namespace object_manipulator {
00045
00047 float StandardPlaceTester::EPS = 1.0e-6;
00048
00049
00050
00051 void PlaceTester::testPlaces(const object_manipulation_msgs::PlaceGoal &goal,
00052 const std::vector<geometry_msgs::PoseStamped> &place_locations,
00053 std::vector<PlaceExecutionInfo> &execution_info,
00054 bool return_on_first_hit)
00055 {
00056 execution_info.clear();
00057 for (size_t i=0; i<place_locations.size(); i++)
00058 {
00059 ROS_DEBUG_NAMED("manipulation","Place tester: testing place %zd out of batch of %zd", i, place_locations.size());
00060 if (feedback_function_) feedback_function_(i);
00061 if (interrupt_function_ && interrupt_function_()) throw InterruptRequestedException();
00062 PlaceExecutionInfo info;
00063
00064
00065 info.gripper_place_pose_ = computeGripperPose(place_locations[i], goal.grasp.grasp_pose,
00066 handDescription().robotFrame(goal.arm_name));
00067 if (marker_publisher_)
00068 {
00069 info.marker_id_ = marker_publisher_->addGraspMarker(info.gripper_place_pose_);
00070 marker_publisher_->colorGraspMarker(info.marker_id_, 1.0, 0.0, 1.0);
00071 }
00072 testPlace(goal, place_locations[i], info);
00073 execution_info.push_back(info);
00074 if (info.result_.result_code == info.result_.SUCCESS && return_on_first_hit) return;
00075 }
00076 }
00077
00078 geometry_msgs::PoseStamped
00079 PlaceTester::computeGripperPose(geometry_msgs::PoseStamped place_location,
00080 geometry_msgs::Pose grasp_pose,
00081 std::string frame_id)
00082 {
00083
00084 tf::Transform place_trans;
00085 tf::poseMsgToTF(place_location.pose, place_trans);
00086 tf::Transform grasp_trans;
00087 tf::poseMsgToTF(grasp_pose, grasp_trans);
00088 grasp_trans = place_trans * grasp_trans;
00089
00090
00091 tf::Stamped<tf::Pose> grasp_trans_stamped;
00092 grasp_trans_stamped.setData(grasp_trans);
00093 grasp_trans_stamped.frame_id_ = place_location.header.frame_id;
00094 grasp_trans_stamped.stamp_ = ros::Time::now();
00095 if (!listener_.waitForTransform(frame_id, place_location.header.frame_id, ros::Time::now(), ros::Duration(1.0)))
00096 {
00097 ROS_ERROR("Object place: tf does not have transform from %s to %s",
00098 place_location.header.frame_id.c_str(),
00099 frame_id.c_str());
00100 throw MechanismException( std::string("Object place: tf does not have transform from ") +
00101 place_location.header.frame_id.c_str() + std::string(" to ") +
00102 frame_id);
00103 }
00104 tf::Stamped<tf::Pose> grasp_trans_base;
00105 try
00106 {
00107 listener_.transformPose( frame_id, grasp_trans_stamped, grasp_trans_base);
00108 }
00109 catch (tf::TransformException ex)
00110 {
00111 ROS_ERROR("Object place: tf failed to transform gripper pose into frame %s; exception: %s",
00112 frame_id.c_str(), ex.what());
00113 throw MechanismException( std::string("tf failed to transform gripper pose into frame ") +
00114 frame_id + std::string("; tf exception: ") +
00115 std::string(ex.what()) );
00116 }
00117
00118 geometry_msgs::PoseStamped gripper_pose;
00119 tf::poseTFToMsg(grasp_trans_base, gripper_pose.pose);
00120 gripper_pose.header.frame_id = frame_id;
00121 gripper_pose.header.stamp = ros::Time::now();
00122 return gripper_pose;
00123 }
00124
00125
00126 void PlacePerformer::performPlaces(const object_manipulation_msgs::PlaceGoal &goal,
00127 const std::vector<geometry_msgs::PoseStamped> &place_locations,
00128 std::vector<PlaceExecutionInfo> &execution_info)
00129 {
00130 for (size_t i=0; i<place_locations.size(); i++)
00131 {
00132 if (feedback_function_) feedback_function_(i);
00133 if (interrupt_function_ && interrupt_function_()) throw InterruptRequestedException();
00134 if (i>= execution_info.size()) throw GraspException("Place Performer: not enough execution info provided");
00135 if (execution_info[i].result_.result_code != PlaceLocationResult::SUCCESS) continue;
00136 ROS_DEBUG_NAMED("manipulation","Place performer: trying place %zd out of batch of %zd", i, place_locations.size());
00137 performPlace(goal, place_locations[i], execution_info[i]);
00138 if (execution_info[i].result_.result_code == execution_info[i].result_.SUCCESS ||
00139 !execution_info[i].result_.continuation_possible) return;
00140 }
00141 }
00142
00143
00144
00145 void StandardPlaceTester::testPlace(const object_manipulation_msgs::PlaceGoal &place_goal,
00146 const geometry_msgs::PoseStamped &place_location,
00147 PlaceExecutionInfo &execution_info)
00148 {
00149
00150 arm_navigation_msgs::OrderedCollisionOperations ord;
00151 arm_navigation_msgs::CollisionOperation coll;
00152 coll.operation = arm_navigation_msgs::CollisionOperation::DISABLE;
00153 if (!place_goal.collision_object_name.empty() && !place_goal.collision_support_surface_name.empty())
00154 {
00155 coll.object1 = place_goal.collision_object_name;
00156 coll.object2 = place_goal.collision_support_surface_name;
00157 ord.collision_operations.push_back(coll);
00158 }
00159 if (place_goal.allow_gripper_support_collision)
00160 {
00161 coll.object1 = handDescription().gripperCollisionName(place_goal.arm_name);
00162 coll.object2 = place_goal.collision_support_surface_name;
00163 ord.collision_operations.push_back(coll);
00164 }
00165 ord.collision_operations = concat(ord.collision_operations,
00166 place_goal.additional_collision_operations.collision_operations);
00167
00168
00169
00170
00171 std::vector<arm_navigation_msgs::LinkPadding> link_padding =
00172 MechanismInterface::gripperPadding(place_goal.arm_name, 0.0);
00173
00174
00175 arm_navigation_msgs::LinkPadding padding;
00176 padding.link_name = handDescription().attachedName(place_goal.arm_name);
00177 padding.padding = place_goal.place_padding;
00178 link_padding.push_back(padding);
00179 link_padding = concat(link_padding, place_goal.additional_link_padding);
00180
00181 geometry_msgs::Vector3Stamped place_direction;
00182 place_direction.header.frame_id = place_goal.approach.direction.header.frame_id;
00183 place_direction.header.stamp = ros::Time::now();
00184 place_direction.vector = mechInterface().negate(place_goal.approach.direction.vector);
00185
00186
00187 std::vector<double> empty;
00188 float actual_distance;
00189 int error_code = mechInterface().getInterpolatedIK(place_goal.arm_name,
00190 execution_info.gripper_place_pose_, place_direction,
00191 place_goal.approach.desired_distance,
00192 empty,
00193 place_goal.grasp.grasp_posture,
00194 ord, link_padding,
00195 true, execution_info.descend_trajectory_, actual_distance);
00196 ROS_DEBUG_NAMED("manipulation"," Place trajectory: actual(%f), min(%f), desired (%f)",
00197 actual_distance, place_goal.approach.min_distance, place_goal.approach.desired_distance);
00198
00199 if (actual_distance < place_goal.approach.min_distance - EPS)
00200 {
00201 ROS_DEBUG_NAMED("manipulation","Place trajectory below min. threshold");
00202 if (execution_info.descend_trajectory_.points.empty())
00203 {
00204 ROS_DEBUG_NAMED("manipulation","Place trajectory empty; problem is with place location");
00205 if (error_code == ArmNavigationErrorCodes::COLLISION_CONSTRAINTS_VIOLATED) {
00206 execution_info.result_ = Result(PlaceLocationResult::PLACE_IN_COLLISION, true);
00207 return;
00208 }
00209 else if (error_code == ArmNavigationErrorCodes::JOINT_LIMITS_VIOLATED) {
00210 execution_info.result_ = Result(PlaceLocationResult::PLACE_OUT_OF_REACH, true);
00211 return;
00212 }
00213 else {
00214 execution_info.result_ = Result(PlaceLocationResult::PLACE_UNFEASIBLE, true);
00215 return;
00216 }
00217 }
00218 if (error_code == ArmNavigationErrorCodes::COLLISION_CONSTRAINTS_VIOLATED) {
00219 execution_info.result_ = Result(PlaceLocationResult::PREPLACE_IN_COLLISION, true);
00220 return;
00221 }
00222 else if (error_code == ArmNavigationErrorCodes::JOINT_LIMITS_VIOLATED) {
00223 execution_info.result_ = Result(PlaceLocationResult::PREPLACE_OUT_OF_REACH, true);
00224 return;
00225 }
00226 else {
00227 execution_info.result_ = Result(PlaceLocationResult::PREPLACE_UNFEASIBLE, true);
00228 return;
00229 }
00230 }
00231
00232
00233
00234 if ( !mechInterface().checkStateValidity(place_goal.arm_name,
00235 execution_info.descend_trajectory_.points.front().positions,
00236 place_goal.additional_collision_operations,
00237 place_goal.additional_link_padding) )
00238 {
00239 ROS_DEBUG_NAMED("manipulation","First pose in place trajectory is unfeasible with default padding");
00240 execution_info.result_ = Result(PlaceLocationResult::PREPLACE_UNFEASIBLE, true);
00241 return;
00242 }
00243
00244
00245 ord.collision_operations.clear();
00246 coll.operation = arm_navigation_msgs::CollisionOperation::DISABLE;
00247
00248 if (!place_goal.collision_object_name.empty())
00249 {
00250 coll.object1 = place_goal.collision_object_name;
00251 coll.object2 = coll.COLLISION_SET_ALL;
00252 ord.collision_operations.push_back(coll);
00253 }
00254 if (place_goal.allow_gripper_support_collision)
00255 {
00256 coll.object1 = handDescription().gripperCollisionName(place_goal.arm_name);
00257 coll.object2 = place_goal.collision_support_surface_name;
00258 ord.collision_operations.push_back(coll);
00259 }
00260 ord.collision_operations = concat(ord.collision_operations,
00261 place_goal.additional_collision_operations.collision_operations);
00262
00263 geometry_msgs::Vector3Stamped retreat_direction;
00264 retreat_direction.header.stamp = ros::Time::now();
00265 retreat_direction.header.frame_id = handDescription().gripperFrame(place_goal.arm_name);
00266 retreat_direction.vector = mechInterface().negate( handDescription().approachDirection(place_goal.arm_name) );
00267
00268
00269 std::vector<double> place_joint_angles = execution_info.descend_trajectory_.points.back().positions;
00270 mechInterface().getInterpolatedIK(place_goal.arm_name,
00271 execution_info.gripper_place_pose_, retreat_direction,
00272 place_goal.desired_retreat_distance,
00273 place_joint_angles,
00274 place_goal.grasp.pre_grasp_posture,
00275 ord, link_padding,
00276 false, execution_info.retreat_trajectory_, actual_distance);
00277 ROS_DEBUG_NAMED("manipulation","Retreat trajectory: actual (%f), min (%f) and desired (%f)", actual_distance,
00278 place_goal.min_retreat_distance, place_goal.desired_retreat_distance);
00279
00280 if (actual_distance < place_goal.min_retreat_distance - EPS)
00281 {
00282 ROS_DEBUG_NAMED("manipulation","Retreat trajectory below min. threshold");
00283 if (execution_info.retreat_trajectory_.points.empty())
00284 {
00285 ROS_DEBUG_NAMED("manipulation","Retreat trajectory empty; problem is with place location");
00286 if (error_code == ArmNavigationErrorCodes::COLLISION_CONSTRAINTS_VIOLATED) {
00287 execution_info.result_ = Result(PlaceLocationResult::PLACE_IN_COLLISION, true);
00288 return;
00289 }
00290 else if (error_code == ArmNavigationErrorCodes::JOINT_LIMITS_VIOLATED) {
00291 execution_info.result_ = Result(PlaceLocationResult::PLACE_OUT_OF_REACH, true);
00292 return;
00293 }
00294 else {
00295 execution_info.result_ = Result(PlaceLocationResult::PLACE_UNFEASIBLE, true);
00296 return;
00297 }
00298 }
00299 if (error_code == ArmNavigationErrorCodes::COLLISION_CONSTRAINTS_VIOLATED) {
00300 execution_info.result_ = Result(PlaceLocationResult::RETREAT_IN_COLLISION, true);
00301 return;
00302 }
00303 else if (error_code == ArmNavigationErrorCodes::JOINT_LIMITS_VIOLATED) {
00304 execution_info.result_ = Result(PlaceLocationResult::RETREAT_OUT_OF_REACH, true);
00305 return;
00306 }
00307 else {
00308 execution_info.result_ = Result(PlaceLocationResult::RETREAT_UNFEASIBLE, true);
00309 return;
00310 }
00311 }
00312 execution_info.result_ = Result(PlaceLocationResult::SUCCESS, true);
00313 }
00314
00315
00316
00331 PlaceLocationResult StandardPlacePerformer::retreat(const object_manipulation_msgs::PlaceGoal &place_goal)
00332 {
00333 arm_navigation_msgs::OrderedCollisionOperations ord;
00334 arm_navigation_msgs::CollisionOperation coll;
00335 coll.object1 = handDescription().gripperCollisionName(place_goal.arm_name);
00336 coll.operation = arm_navigation_msgs::CollisionOperation::DISABLE;
00337
00338 if (!place_goal.collision_object_name.empty())
00339 {
00340 coll.object2 = place_goal.collision_object_name;
00341 ord.collision_operations.push_back(coll);
00342 }
00343
00344 if (!place_goal.collision_support_surface_name.empty())
00345 {
00346 coll.object2 = place_goal.collision_support_surface_name;
00347 ord.collision_operations.push_back(coll);
00348 }
00349 ord.collision_operations = concat(ord.collision_operations,
00350 place_goal.additional_collision_operations.collision_operations);
00351
00352
00353 std::vector<arm_navigation_msgs::LinkPadding> link_padding
00354 = concat(MechanismInterface::gripperPadding(place_goal.arm_name, 0.0),
00355 place_goal.additional_link_padding);
00356
00357 geometry_msgs::Vector3Stamped direction;
00358 direction.header.stamp = ros::Time::now();
00359 direction.header.frame_id = handDescription().gripperFrame(place_goal.arm_name);
00360 direction.vector = mechInterface().negate( handDescription().approachDirection(place_goal.arm_name) );
00361
00362 float actual_distance;
00363 mechInterface().translateGripper(place_goal.arm_name,
00364 direction,
00365 ord, link_padding,
00366 place_goal.desired_retreat_distance, 0, actual_distance);
00367 if (actual_distance < place_goal.min_retreat_distance)
00368 {
00369 ROS_DEBUG_NAMED("manipulation","Object place: retreat incomplete (%f executed and %f desired)",
00370 actual_distance, place_goal.min_retreat_distance);
00371 return Result(PlaceLocationResult::RETREAT_FAILED, false);
00372 }
00373
00374 return Result(PlaceLocationResult::SUCCESS, true);
00375 }
00376
00380 PlaceLocationResult
00381 StandardPlacePerformer::placeApproach(const object_manipulation_msgs::PlaceGoal &place_goal,
00382 const PlaceExecutionInfo &execution_info)
00383 {
00384 mechInterface().attemptTrajectory(place_goal.arm_name, execution_info.descend_trajectory_, true);
00385 return Result(PlaceLocationResult::SUCCESS, true);
00386 }
00387
00388
00389 void StandardPlacePerformer::performPlace(const object_manipulation_msgs::PlaceGoal &place_goal,
00390 const geometry_msgs::PoseStamped &place_location,
00391 PlaceExecutionInfo &execution_info)
00392 {
00393
00394 bool use_constraints = true;
00395
00396 if(!constraintsUnderstandable(place_goal.path_constraints))
00397 {
00398 ROS_WARN("Constraints passed to place executor are of types not yet handled. Ignoring them.");
00399 use_constraints = false;
00400 }
00401 if (place_goal.path_constraints.orientation_constraints.empty())
00402 {
00403 use_constraints = false;
00404 }
00405 if(use_constraints)
00406 {
00407
00408 geometry_msgs::PoseStamped place_pose;
00409 place_pose.header.frame_id = place_location.header.frame_id;
00410 place_pose.header.stamp = ros::Time(0.0);
00411
00412 if(!mechInterface().getFK(place_goal.arm_name, execution_info.descend_trajectory_.points.front().positions,
00413 place_pose))
00414 {
00415 ROS_ERROR("Could not re-compute pre-place pose based on trajectory");
00416 throw MechanismException("Could not re-compute pre-place pose based on trajectory");
00417 }
00418 ROS_DEBUG_NAMED("manipulation","Attempting move arm to pre-place with constraints");
00419 if (!mechInterface().moveArmConstrained(place_goal.arm_name, place_pose,
00420 place_goal.additional_collision_operations,
00421 place_goal.additional_link_padding,
00422 place_goal.path_constraints,
00423 execution_info.descend_trajectory_.points.front().positions[2],
00424 false))
00425 {
00426
00427
00428 ROS_WARN("Object place: move_arm to pre-place with constraints failed. Trying again without constraints.");
00429 use_constraints = false;
00430 }
00431 }
00432
00433 if(!use_constraints)
00434 {
00435 ROS_DEBUG_NAMED("manipulation","Attempting move arm to pre-place without constraints");
00436 if ( !mechInterface().attemptMoveArmToGoal(place_goal.arm_name,
00437 execution_info.descend_trajectory_.points.front().positions,
00438 place_goal.additional_collision_operations,
00439 place_goal.additional_link_padding) )
00440 {
00441 ROS_DEBUG_NAMED("manipulation","Object place: move_arm (without constraints) to pre-place reports failure");
00442 execution_info.result_ = Result(PlaceLocationResult::MOVE_ARM_FAILED, true);
00443 return;
00444 }
00445 }
00446 ROS_DEBUG_NAMED("manipulation"," Arm moved to pre-place");
00447
00448 execution_info.result_ = placeApproach(place_goal, execution_info);
00449 if ( execution_info.result_.result_code != PlaceLocationResult::SUCCESS)
00450 {
00451 ROS_DEBUG_NAMED("manipulation"," Pre-place to place approach failed");
00452 execution_info.result_ = Result(PlaceLocationResult::PLACE_FAILED, false);
00453 return;
00454 }
00455 ROS_DEBUG_NAMED("manipulation"," Place trajectory done");
00456
00457 mechInterface().detachAndAddBackObjectsAttachedToGripper(place_goal.arm_name, place_goal.collision_object_name);
00458 ROS_DEBUG_NAMED("manipulation"," Object detached");
00459
00460 mechInterface().handPostureGraspAction(place_goal.arm_name, place_goal.grasp,
00461 object_manipulation_msgs::GraspHandPostureExecutionGoal::RELEASE, -1);
00462 ROS_DEBUG_NAMED("manipulation"," Object released");
00463
00464 execution_info.result_ = retreat(place_goal);
00465 if (execution_info.result_.result_code != PlaceLocationResult::SUCCESS)
00466 {
00467 execution_info.result_ = Result(PlaceLocationResult::RETREAT_FAILED, false);
00468 return;
00469 }
00470 execution_info.result_ = Result(PlaceLocationResult::SUCCESS, true);
00471 }
00472
00476 bool StandardPlacePerformer::constraintsUnderstandable(const arm_navigation_msgs::Constraints &constraints)
00477 {
00478 if(constraints.position_constraints.empty() && constraints.orientation_constraints.empty() &&
00479 constraints.joint_constraints.empty() && constraints.visibility_constraints.empty())
00480 return true;
00481 if(constraints.orientation_constraints.size() == 1 && constraints.position_constraints.empty()
00482 && constraints.joint_constraints.empty() && constraints.visibility_constraints.empty())
00483 return true;
00484 return false;
00485 }
00486
00487 PlaceLocationResult
00488 ReactivePlacePerformer::placeApproach(const object_manipulation_msgs::PlaceGoal &place_goal,
00489 const PlaceExecutionInfo &execution_info)
00490 {
00491
00492 object_manipulation_msgs::ReactivePlaceGoal reactive_place_goal;
00493 reactive_place_goal.arm_name = place_goal.arm_name;
00494 reactive_place_goal.collision_object_name = place_goal.collision_object_name;
00495 reactive_place_goal.collision_support_surface_name = place_goal.collision_support_surface_name;
00496 reactive_place_goal.trajectory = execution_info.descend_trajectory_;
00497 reactive_place_goal.final_place_pose = execution_info.gripper_place_pose_;
00498
00499
00500 ros::Duration timeout = ros::Duration(60.0);
00501 ROS_DEBUG_NAMED("manipulation"," Calling the reactive place action");
00502 mechInterface().reactive_place_action_client_.client(place_goal.arm_name).sendGoal(reactive_place_goal);
00503 if ( !mechInterface().reactive_place_action_client_.client(place_goal.arm_name).waitForResult(timeout) )
00504 {
00505 ROS_ERROR(" Reactive place timed out");
00506 return Result(PlaceLocationResult::PLACE_FAILED, false);
00507 }
00508 object_manipulation_msgs::ReactivePlaceResult reactive_place_result =
00509 *mechInterface().reactive_place_action_client_.client(place_goal.arm_name).getResult();
00510 if (reactive_place_result.manipulation_result.value != reactive_place_result.manipulation_result.SUCCESS)
00511 {
00512 ROS_ERROR(" Reactive place failed with error code %d", reactive_place_result.manipulation_result.value);
00513 return Result(PlaceLocationResult::PLACE_FAILED, false);
00514 }
00515 ROS_DEBUG_NAMED("manipulation"," Reactive place action succeeded");
00516 return Result(PlaceLocationResult::SUCCESS, true);
00517 }
00518
00519 }