35 #include <std_srvs/Empty.h> 43 #include <turtlebot_arm_object_manipulation/PickAndPlaceAction.h> 44 #include <turtlebot_arm_object_manipulation/MoveToTargetAction.h> 47 #include <moveit_msgs/Grasp.h> 48 #include <moveit_msgs/PlaceLocation.h> 62 turtlebot_arm_object_manipulation::PickAndPlaceFeedback
feedback_;
63 turtlebot_arm_object_manipulation::PickAndPlaceResult
result_;
64 turtlebot_arm_object_manipulation::PickAndPlaceGoalConstPtr
goal_;
91 as_(name, false), action_name_(name), arm_(
"arm"), gripper_(
"gripper")
96 nh.
param(
"grasp_attach_time", attach_time, 0.8);
97 nh.
param(
"grasp_detach_time", detach_time, 0.6);
98 nh.
param(
"vertical_backlash", z_backlash, 0.01);
99 nh.
param(
"/gripper_controller/max_opening", gripper_open, 0.045);
108 clear_octomap_srv_ = nh.
serviceClient<std_srvs::Empty>(
"/clear_octomap");
111 target_pose_pub_ = nh.
advertise<geometry_msgs::PoseStamped>(
"/target_pose", 1,
true);
121 ROS_INFO(
"[pick and place] Received goal!");
124 arm_link = goal_->frame;
137 pick_pose.header = goal_->header;
138 pick_pose.pose = goal_->pick_pose;
139 place_pose.header = goal_->header;
140 place_pose.pose = goal_->place_pose;
147 ROS_WARN(
"[pick and place] %s: Preempted", action_name_.c_str());
158 if (
pick(obj_name, pick_pose))
160 if (
place(obj_name, place_pose, pick_pose.pose.position.z))
177 bool pick(
const std::string&
obj_name, geometry_msgs::PoseStamped& pose)
180 std::map<std::string, moveit_msgs::CollisionObject> objects =
181 planning_scene_interface_.
getObjects(std::vector<std::string>(1, obj_name));
182 if (objects.size() == 0)
185 ROS_ERROR(
"[pick and place] Tabletop collision object '%s' not found", obj_name.c_str());
189 if (objects.size() > 1)
192 ROS_WARN(
"[pick and place] More than one (%d) tabletop collision objects with name '%s' found!",
193 objects.size(), obj_name.c_str());
197 Eigen::Vector3d tco_size;
198 geometry_msgs::PoseStamped tco_pose;
199 const moveit_msgs::CollisionObject& tco = objects[
obj_name];
201 tco_pose.header = tco.header;
204 if (tco.mesh_poses.size() > 0)
206 tco_pose.pose = tco.mesh_poses[0];
207 if (tco.meshes.size() > 0)
213 tco_pose.pose.position.z += tco_size[2]/2.0;
217 ROS_ERROR(
"[pick and place] Tabletop collision object '%s' has no meshes", obj_name.c_str());
221 else if (tco.primitive_poses.size() > 0)
223 tco_pose.pose = tco.primitive_poses[0];
224 if (tco.primitives.size() > 0)
230 ROS_ERROR(
"[pick and place] Tabletop collision object '%s' has no primitives", obj_name.c_str());
236 ROS_ERROR(
"[pick and place] Tabletop collision object '%s' has no mesh/primitive poses", obj_name.c_str());
240 ROS_INFO(
"[pick and place] Picking object '%s' with size [%.3f, %.3f, %.3f] at location [%s]...",
241 obj_name.c_str(), tco_size[0], tco_size[1], tco_size[2],
mtk::point2str2D(tco_pose.pose.position).c_str());
246 geometry_msgs::PoseStamped p = tco_pose;
254 moveit_msgs::Grasp g;
257 g.pre_grasp_approach.direction.vector.x = 0.5;
259 g.pre_grasp_approach.min_distance = 0.005;
260 g.pre_grasp_approach.desired_distance = 0.1;
263 g.post_grasp_retreat.direction.vector.x = -0.5;
264 g.post_grasp_retreat.min_distance = 0.005;
265 g.post_grasp_retreat.desired_distance = 0.1;
267 g.pre_grasp_posture.joint_names.push_back(
"gripper_joint");
268 g.pre_grasp_posture.points.resize(1);
269 g.pre_grasp_posture.points[0].positions.push_back(gripper_open);
273 g.grasp_posture.joint_names.push_back(
"gripper_joint");
274 g.grasp_posture.points.resize(1);
275 g.grasp_posture.points[0].positions.push_back(tco_size.minCoeff() - 0.002);
277 g.allowed_touch_objects.push_back(obj_name);
278 g.allowed_touch_objects.push_back(
"table");
282 std::vector<moveit_msgs::Grasp> grasps(1, g);
287 ROS_INFO(
"[pick and place] Pick successfully completed");
292 ROS_DEBUG(
"[pick and place] Pick attempt %d failed: %s", attempt,
mec2str(result));
295 clear_octomap_srv_.
call(empty_srv_);
298 ROS_ERROR(
"[pick and place] Pick failed after %d attempts", PICK_ATTEMPTS);
302 bool place(
const std::string&
obj_name,
const geometry_msgs::PoseStamped& pose,
double pick_position_z)
305 std::map<std::string, moveit_msgs::AttachedCollisionObject> objects =
308 if (objects.size() == 0)
311 ROS_ERROR(
"[pick and place] Attached collision object '%s' not found", obj_name.c_str());
315 if (objects.size() > 1)
318 ROS_WARN(
"[pick and place] More than one (%d) attached collision objects with name '%s' found!",
319 objects.size(), obj_name.c_str());
323 geometry_msgs::Pose aco_pose;
324 const moveit_msgs::AttachedCollisionObject& aco = objects[
obj_name];
326 if (aco.object.primitive_poses.size() > 0)
328 aco_pose = aco.object.primitive_poses[0];
330 else if (aco.object.mesh_poses.size() > 0)
332 aco_pose = aco.object.mesh_poses[0];
336 ROS_ERROR(
"[pick and place] Attached collision object '%s' has no pose!", obj_name.c_str());
340 ROS_INFO(
"[pick and place] Placing object '%s' at pose [%s]...", obj_name.c_str(),
mtk::pose2str3D(pose).c_str());
345 geometry_msgs::PoseStamped p = pose;
360 p.pose.position.z = pick_position_z;
362 ROS_DEBUG(
"Compensate place pose with the attached object pose [%s]. Results: [%s]",
367 moveit_msgs::PlaceLocation l;
370 l.pre_place_approach.direction.vector.x = 0.5;
372 l.pre_place_approach.min_distance = 0.005;
373 l.pre_place_approach.desired_distance = 0.1;
375 l.post_place_retreat.direction.vector.x = -0.5;
377 l.post_place_retreat.min_distance = 0.005;
378 l.post_place_retreat.desired_distance = 0.1;
380 l.post_place_posture.joint_names.push_back(
"gripper_joint");
381 l.post_place_posture.points.resize(1);
382 l.post_place_posture.points[0].positions.push_back(gripper_open);
384 l.allowed_touch_objects.push_back(obj_name);
385 l.allowed_touch_objects.push_back(
"table");
389 std::vector<moveit_msgs::PlaceLocation> locs(1, l);
394 ROS_INFO(
"[pick and place] Place successfully completed");
398 ROS_DEBUG(
"[pick and place] Place attempt %d failed: %s", attempt,
mec2str(result));
401 clear_octomap_srv_.
call(empty_srv_);
404 ROS_ERROR(
"[pick and place] Place failed after %d attempts", PLACE_ATTEMPTS);
418 bool validateTargetPose(geometry_msgs::PoseStamped& target,
bool compensate_backlash,
int attempt = 0)
421 if (target.header.frame_id != arm_link)
423 transformPose(target.header.frame_id, arm_link, target, target);
426 double x = target.pose.position.x;
427 double y = target.pose.position.y;
428 double z = target.pose.position.z;
429 double d = sqrt(x*x + y*y);
436 ROS_ERROR(
"[pick and place] Target pose out of reach [%f > %f]", d, 0.3);
444 double rp =
M_PI_2 - std::asin((d - 0.1)/0.22) + ((attempt%2)*2 - 1)*(std::ceil(attempt/2.0)*0.05);
445 double ry = std::atan2(y, x);
449 if (compensate_backlash)
453 double z_delta1 = std::abs(std::cos(rp))/50.0;
455 ROS_DEBUG(
"[pick and place] Z increase: %f + %f + %f", target.pose.position.z, z_delta1, z_delta2);
456 target.pose.position.z += z_delta1;
457 target.pose.position.z += z_delta2;
461 target_pose_pub_.
publish(target);
472 bool setGripper(
float opening,
bool wait_for_complete =
true)
474 ROS_DEBUG(
"[pick and place] Set gripper opening to %f", opening);
477 ROS_ERROR(
"[pick and place] Set gripper opening to %f failed", opening);
489 ROS_ERROR(
"[pick and place] Set gripper opening failed (error %d)", result.val);
496 return ((
float(rand()) /
float(RAND_MAX)) * (max - min)) + min;
503 case moveit::planning_interface::MoveItErrorCode::SUCCESS:
505 case moveit::planning_interface::MoveItErrorCode::FAILURE:
507 case moveit::planning_interface::MoveItErrorCode::PLANNING_FAILED:
508 return "planning failed";
509 case moveit::planning_interface::MoveItErrorCode::INVALID_MOTION_PLAN:
510 return "invalid motion plan";
511 case moveit::planning_interface::MoveItErrorCode::MOTION_PLAN_INVALIDATED_BY_ENVIRONMENT_CHANGE:
512 return "motion plan invalidated by environment change";
513 case moveit::planning_interface::MoveItErrorCode::CONTROL_FAILED:
514 return "control failed";
515 case moveit::planning_interface::MoveItErrorCode::UNABLE_TO_AQUIRE_SENSOR_DATA:
516 return "unable to acquire sensor data";
517 case moveit::planning_interface::MoveItErrorCode::TIMED_OUT:
519 case moveit::planning_interface::MoveItErrorCode::PREEMPTED:
521 case moveit::planning_interface::MoveItErrorCode::START_STATE_IN_COLLISION:
522 return "start state in collision";
523 case moveit::planning_interface::MoveItErrorCode::START_STATE_VIOLATES_PATH_CONSTRAINTS:
524 return "start state violates path constraints";
525 case moveit::planning_interface::MoveItErrorCode::GOAL_IN_COLLISION:
526 return "goal in collision";
527 case moveit::planning_interface::MoveItErrorCode::GOAL_VIOLATES_PATH_CONSTRAINTS:
528 return "goal violates path constraints";
529 case moveit::planning_interface::MoveItErrorCode::GOAL_CONSTRAINTS_VIOLATED:
530 return "goal constraints violated";
531 case moveit::planning_interface::MoveItErrorCode::INVALID_GROUP_NAME:
532 return "invalid group name";
533 case moveit::planning_interface::MoveItErrorCode::INVALID_GOAL_CONSTRAINTS:
534 return "invalid goal constraints";
535 case moveit::planning_interface::MoveItErrorCode::INVALID_ROBOT_STATE:
536 return "invalid robot state";
537 case moveit::planning_interface::MoveItErrorCode::INVALID_LINK_NAME:
538 return "invalid link name";
539 case moveit::planning_interface::MoveItErrorCode::INVALID_OBJECT_NAME:
540 return "invalid object name";
541 case moveit::planning_interface::MoveItErrorCode::FRAME_TRANSFORM_FAILURE:
542 return "frame transform failure";
543 case moveit::planning_interface::MoveItErrorCode::COLLISION_CHECKING_UNAVAILABLE:
544 return "collision checking unavailable";
545 case moveit::planning_interface::MoveItErrorCode::ROBOT_STATE_STALE:
546 return "robot state stale";
547 case moveit::planning_interface::MoveItErrorCode::SENSOR_INFO_STALE:
548 return "sensor info stale";
549 case moveit::planning_interface::MoveItErrorCode::NO_IK_SOLUTION:
550 return "no ik solution";
552 return "unrecognized error code";
557 bool transformPose(
const std::string& in_frame,
const std::string& out_frame,
558 const geometry_msgs::PoseStamped& in_pose, geometry_msgs::PoseStamped& out_pose)
569 ROS_ERROR(
"[pick and place] Transformed pose has invalid orientation: %s", e.what());
574 ROS_ERROR(
"[pick and place] Could not get sensor to arm transform: %s", e.what());
594 turtlebot_arm_object_manipulation::MoveToTargetFeedback
feedback_;
595 turtlebot_arm_object_manipulation::MoveToTargetResult
result_;
596 turtlebot_arm_object_manipulation::MoveToTargetGoalConstPtr
goal_;
606 as_(name, false), action_name_(name), arm_(
"arm"), gripper_(
"gripper")
615 target_pose_pub_ = nh.
advertise<geometry_msgs::PoseStamped>(
"/target_pose", 1,
true);
625 ROS_INFO(
"[move to target] Received goal!");
629 switch (goal_->target_type)
631 case turtlebot_arm_object_manipulation::MoveToTargetGoal::NAMED_TARGET:
632 result = moveArmTo(goal_->named_target);
634 case turtlebot_arm_object_manipulation::MoveToTargetGoal::JOINT_STATE:
635 case turtlebot_arm_object_manipulation::MoveToTargetGoal::POSE_TARGET:
637 ROS_ERROR(
"[move to target] Move to target of type %d not implemented", goal_->target_type);
653 ROS_INFO(
"[move to target] %s: Preempted", action_name_.c_str());
669 ROS_DEBUG(
"[move to target] Move arm to '%s' position", target.c_str());
672 ROS_ERROR(
"[move to target] Set named target '%s' failed", target.c_str());
677 if (
bool(result) ==
true)
679 ROS_INFO(
"[move to target] Move to target \"%s\" completed", target.c_str());
684 ROS_ERROR(
"[move to target] Move to target \"%s\" failed (error %d)", target.c_str(), result.val);
695 bool moveArmTo(
const geometry_msgs::PoseStamped& target)
698 ROS_DEBUG(
"[move to target] Move arm to [%.2f, %.2f, %.2f, %.2f]",
699 target.pose.position.x, target.pose.position.y, target.pose.position.z,
703 geometry_msgs::PoseStamped modiff_target = target;
705 double x = modiff_target.pose.position.x;
706 double y = modiff_target.pose.position.y;
707 double z = modiff_target.pose.position.z;
708 double d = sqrt(x*x + y*y);
712 ROS_ERROR(
"[move to target] Target pose out of reach [%f > %f]", d, 0.3);
718 double rp =
M_PI_2 - std::asin((d - 0.1)/0.205);
719 double ry = std::atan2(y, x);
722 attempts*
fRand(-0.05, +0.05) + rp,
723 attempts*
fRand(-0.05, +0.05) + ry);
727 ROS_DEBUG(
"[move to target] Z increase: %f + %f", modiff_target.pose.position.z, std::abs(std::cos(rp))/50.0);
728 modiff_target.pose.position.z += std::abs(std::cos(rp))/50.0;
730 ROS_DEBUG(
"[move to target] Set pose target [%.2f, %.2f, %.2f] [d: %.2f, p: %.2f, y: %.2f]", x, y, z, d, rp, ry);
731 target_pose_pub_.
publish(modiff_target);
735 ROS_ERROR(
"[move to target] Set pose target [%.2f, %.2f, %.2f, %.2f] failed",
736 modiff_target.pose.position.x, modiff_target.pose.position.y, modiff_target.pose.position.z,
742 if (
bool(result) ==
true)
744 ROS_INFO(
"[move to target] Move to target [%.2f, %.2f, %.2f, %.2f] completed",
745 modiff_target.pose.position.x, modiff_target.pose.position.y, modiff_target.pose.position.z,
751 ROS_ERROR(
"[move to target] Move to target failed (error %d) at attempt %d",
752 result.val, attempts + 1);
757 ROS_ERROR(
"[move to target] Move to target failed after %d attempts", attempts);
767 bool setGripper(
float opening,
bool wait_for_complete =
true)
769 ROS_DEBUG(
"[move to target] Set gripper opening to %f", opening);
772 ROS_ERROR(
"[move to target] Set gripper opening to %f failed", opening);
784 ROS_ERROR(
"[move to target] Set gripper opening failed (error %d)", result.val);
791 return ((
float(rand()) /
float(RAND_MAX)) * (max - min)) + min;
798 int main(
int argc,
char** argv)
800 ros::init(argc, argv,
"object_pick_and_place_action_server");
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
MoveItErrorCode asyncMove()
boost::shared_ptr< const Goal > acceptNewGoal()
static tf::Quaternion createQuaternionFromRPY(double roll, double pitch, double yaw)
static void poseMsgToTF(const geometry_msgs::Pose &msg, Pose &bt)
MoveToTargetServer(const std::string name)
bool detachObject(const std::string &name="")
bool validateTargetPose(geometry_msgs::PoseStamped &target, bool compensate_backlash, int attempt=0)
void publish(const boost::shared_ptr< M > &message) const
moveit::planning_interface::MoveGroupInterface arm_
moveit::planning_interface::MoveGroupInterface arm_
bool setJointValueTarget(const std::vector< double > &group_variable_values)
MoveItErrorCode pick(const std::string &object, bool plan_only=false)
turtlebot_arm_object_manipulation::PickAndPlaceFeedback feedback_
ros::Publisher target_pose_pub_
static double getYaw(const Quaternion &bt_q)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
ros::Publisher target_pose_pub_
bool call(MReq &req, MRes &res)
turtlebot_arm_object_manipulation::MoveToTargetFeedback feedback_
void setPoseReferenceFrame(const std::string &pose_reference_frame)
bool setGripper(float opening, bool wait_for_complete=true)
std::map< std::string, moveit_msgs::CollisionObject > getObjects(const std::vector< std::string > &object_ids=std::vector< std::string >())
bool moveArmTo(const geometry_msgs::PoseStamped &target)
bool setPoseTarget(const Eigen::Affine3d &end_effector_pose, const std::string &end_effector_link="")
bool place(const std::string &obj_name, const geometry_msgs::PoseStamped &pose, double pick_position_z)
std::string pose2str3D(const geometry_msgs::Pose &pose)
turtlebot_arm_object_manipulation::PickAndPlaceResult result_
bool pickAndPlace(const std::string &obj_name, geometry_msgs::PoseStamped &pick_pose, geometry_msgs::PoseStamped &place_pose)
float fRand(float min, float max)
void setGoalOrientationTolerance(double tolerance)
void setSucceeded(const Result &result=Result(), const std::string &text=std::string(""))
ros::ServiceClient clear_octomap_srv_
const std::string & getEndEffectorLink() const
void setGoalPositionTolerance(double tolerance)
moveit::planning_interface::MoveGroupInterface gripper_
float fRand(float min, float max)
void setPreempted(const Result &result=Result(), const std::string &text=std::string(""))
int main(int argc, char **argv)
PickAndPlaceServer(const std::string name)
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
const char * mec2str(const moveit::planning_interface::MoveItErrorCode &mec)
static void quaternionTFToMsg(const Quaternion &bt, geometry_msgs::Quaternion &msg)
bool transformPose(const std::string &in_frame, const std::string &out_frame, const geometry_msgs::PoseStamped &in_pose, geometry_msgs::PoseStamped &out_pose)
void registerPreemptCallback(boost::function< void()> cb)
bool pick(const std::string &obj_name, geometry_msgs::PoseStamped &pose)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
moveit::planning_interface::MoveGroupInterface gripper_
MoveItErrorCode place(const std::string &object, bool plan_only=false)
bool setGripper(float opening, bool wait_for_complete=true)
std_srvs::Empty empty_srv_
tf::TransformListener tf_listener_
void setAborted(const Result &result=Result(), const std::string &text=std::string(""))
actionlib::SimpleActionServer< turtlebot_arm_object_manipulation::MoveToTargetAction > as_
actionlib::SimpleActionServer< turtlebot_arm_object_manipulation::PickAndPlaceAction > as_
std::map< std::string, moveit_msgs::AttachedCollisionObject > getAttachedObjects(const std::vector< std::string > &object_ids=std::vector< std::string >())
static void poseTFToMsg(const Pose &bt, geometry_msgs::Pose &msg)
turtlebot_arm_object_manipulation::MoveToTargetResult result_
turtlebot_arm_object_manipulation::MoveToTargetGoalConstPtr goal_
void allowReplanning(bool flag)
static geometry_msgs::Quaternion createQuaternionMsgFromRollPitchYaw(double roll, double pitch, double yaw)
void setSupportSurfaceName(const std::string &name)
bool moveArmTo(const std::string &target)
turtlebot_arm_object_manipulation::PickAndPlaceGoalConstPtr goal_
void registerGoalCallback(boost::function< void()> cb)
Eigen::Vector3d computeShapeExtents(const ShapeMsg &shape_msg)
moveit::planning_interface::PlanningSceneInterface planning_scene_interface_
bool setNamedTarget(const std::string &name)
ROSCPP_DECL void waitForShutdown()
std::string point2str2D(const geometry_msgs::Point &point)