grasp_planner.cpp
Go to the documentation of this file.
00001 /*
00002  * UOS-ROS packages - Robot Operating System code by the University of Osnabrück
00003  * Copyright (C) 2012 University of Osnabrück
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018  *
00019  * grasp_planner.cpp
00020  *
00021  *  Created on: 17.11.2012
00022  *      Author: Martin Günther <mguenthe@uos.de>
00023  */
00024 
00025 #include <katana_simple_grasp_planner/grasp_planner.h>
00026 #include <math.h>
00027 
00028 namespace katana_simple_grasp_planner
00029 {
00030 
00031 GraspPlanner::GraspPlanner() :
00032     kinematics_loader_("kinematics_base", "kinematics::KinematicsBase"),
00033     as_(nh_, "/plan_point_cluster_grasp", boost::bind(&GraspPlanner::execute_cb, this, _1), false)
00034 {
00035   as_.start();
00036 
00037   // this is usually configured via pr2_gripper_grasp_planner_cluster/config
00038   pre_grasp_joint_state_.name.push_back("katana_l_finger_joint");
00039   pre_grasp_joint_state_.name.push_back("katana_r_finger_joint");
00040   pre_grasp_joint_state_.position.push_back(0.30);
00041   pre_grasp_joint_state_.position.push_back(0.30);
00042   pre_grasp_joint_state_.effort.push_back(100.0);
00043   pre_grasp_joint_state_.effort.push_back(100.0);
00044 
00045   grasp_joint_state_.name = pre_grasp_joint_state_.name;
00046   grasp_joint_state_.position.push_back(-0.44);
00047   grasp_joint_state_.position.push_back(-0.44);
00048   grasp_joint_state_.effort.push_back(50.0);
00049   grasp_joint_state_.effort.push_back(50.0);
00050 
00051   // see arm_kinematics_constraint_aware/src/arm_kinematics_solver_constraint_aware.cpp
00052   try
00053   {
00054       kinematics_solver_ = kinematics_loader_.createInstance("arm_kinematics_constraint_aware/KDLArmKinematicsPlugin");
00055   }
00056   catch(pluginlib::PluginlibException& ex)
00057   {
00058       ROS_ERROR("The plugin failed to load. Error1: %s", ex.what());    //handle the class failing to load
00059       return;
00060   }
00061 
00062   std::string group_name = "arm";
00063   std::string base_name = "katana_base_link";
00064   std::string tip_name = "katana_motor5_wrist_roll_link";
00065 
00066   if(kinematics_solver_->initialize(group_name,
00067                                     base_name,
00068                                     tip_name,
00069                                     .025)) {
00070   } else {
00071     ROS_ERROR_STREAM("Initialize is failing for " << group_name);
00072     return;
00073   }
00074 
00075   ROS_INFO("katana_simple_grasp_planner initialized.");
00076 }
00077 
00078 GraspPlanner::~GraspPlanner()
00079 {
00080 }
00081 
00085 std::vector<tf::Transform> GraspPlanner::generate_grasps(double x, double y, double z)
00086 {
00087   static const double ANGLE_INC = M_PI / 16;
00088   static const double STRAIGHT_ANGLE_MIN = 0.0 + ANGLE_INC;  // + ANGLE_INC, because 0 is already covered by side grasps
00089   static const double ANGLE_MAX = M_PI / 2;
00090 
00091   // how far from the grasp center should the wrist be?
00092   static const double STANDOFF = -0.12;
00093 
00094   std::vector<tf::Transform> grasps;
00095 
00096   tf::Transform transform;
00097 
00098   tf::Transform standoff_trans;
00099   standoff_trans.setOrigin(tf::Vector3(STANDOFF, 0.0, 0.0));
00100   standoff_trans.setRotation(tf::createIdentityQuaternion());
00101 
00102 
00103   // ----- side grasps
00104   //
00105   //  1. side grasp (xy-planes of `katana_motor5_wrist_roll_link` and of `katana_base_link` are parallel):
00106   //     - standard: `rpy = (0, 0, *)` (orientation of `katana_motor5_wrist_roll_link` in `katana_base_link` frame)
00107   //     - overhead: `rpy = (pi, 0, *)`
00108   transform.setOrigin(tf::Vector3(x, y, z));
00109 
00110   for (double roll = 0.0; roll <= M_PI; roll += M_PI)
00111   {
00112     double pitch = 0.0;
00113 
00114     // add yaw = 0 first, then +ANGLE_INC, -ANGLE_INC, 2*ANGLE_INC, ...
00115     // reason: grasps with yaw near 0 mean that the approach is from the
00116     // direction of the arm; it is usually easier to place the object back like
00117     // this
00118     for (double yaw = ANGLE_INC; yaw <= ANGLE_MAX; yaw += ANGLE_INC)
00119     {
00120       // + atan2 to center the grasps around the vector from arm to object
00121       transform.setRotation(tf::createQuaternionFromRPY(roll, pitch, yaw + atan2(y, x)));
00122       grasps.push_back(transform * standoff_trans);
00123 
00124       if (yaw != 0.0)
00125       {
00126         transform.setRotation(tf::createQuaternionFromRPY(roll, pitch, -yaw + atan2(y, x)));
00127         grasps.push_back(transform * standoff_trans);
00128       }
00129     }
00130   }
00131 
00132   // ----- straight grasps
00133   //
00134   //  2. straight grasp (xz-plane of `katana_motor5_wrist_roll_link` contains z axis of `katana_base_link`)
00135   //     - standard: `rpy = (0, *, atan2(y_w, x_w))`   (x_w, y_w = position of `katana_motor5_wrist_roll_link` in `katana_base_link` frame)
00136   //     - overhead: `rpy = (pi, *, atan2(y_w, x_w))`
00137   for (double roll = 0.0; roll <= M_PI; roll += M_PI)
00138   {
00139     for (double pitch = STRAIGHT_ANGLE_MIN; pitch <= ANGLE_MAX; pitch += ANGLE_INC)
00140     {
00141       double yaw = atan2(y, x);
00142       transform.setOrigin(tf::Vector3(x, y, z));
00143       transform.setRotation(tf::createQuaternionFromRPY(roll, pitch, yaw));
00144 
00145       grasps.push_back(transform * standoff_trans);
00146     }
00147   }
00148 
00149   return grasps;
00150 }
00151 
00152 std::vector<double> GraspPlanner::get_ik(tf::Transform grasp_tf)
00153 {
00154   geometry_msgs::Pose ik_pose;
00155   tf::poseTFToMsg(grasp_tf, ik_pose);
00156 
00157   std::vector<double> ik_seed_state;
00158   ik_seed_state.resize(5, 0.0);
00159 
00160   std::vector<double> solution;
00161   int error_code;   // see arm_navigation_msgs/msg/ArmNavigationErrorCodes.msg
00162 
00163   kinematics_solver_->getPositionIK(ik_pose, ik_seed_state, solution, error_code);
00164 
00165   if (error_code == 1)
00166     ROS_DEBUG("IK solution: %f %f %f %f %f", solution[0], solution[1], solution[2], solution[3], solution[4]);
00167   else
00168     ROS_INFO("no IK found (error %d)", error_code);
00169 
00170   return solution;
00171 }
00172 
00173 void GraspPlanner::execute_cb(const object_manipulation_msgs::GraspPlanningGoalConstPtr &goal)
00174 {
00175   object_manipulation_msgs::GraspPlanningFeedback feedback;
00176   object_manipulation_msgs::GraspPlanningResult result;
00177 
00178 
00179   // ----- compute the center point of the object
00180   // just calculate the average
00181   sensor_msgs::PointCloud cloud = goal->target.cluster;
00182   float x = 0.0, y = 0.0, z = 0.0;
00183   for (size_t i = 0; i < cloud.points.size(); ++i)
00184   {
00185     x += cloud.points[i].x;
00186     y += cloud.points[i].y;
00187     z += cloud.points[i].z;
00188   }
00189   x /= cloud.points.size();
00190   y /= cloud.points.size();
00191   z /= cloud.points.size();
00192 
00193   std::vector<tf::Transform> grasp_tfs = generate_grasps(x, y, z);
00194 
00195   for (std::vector<tf::Transform>::iterator it = grasp_tfs.begin(); it != grasp_tfs.end(); ++it)
00196   {
00197     // skip grasps without IK solution
00198     if (get_ik(*it).size() == 0)
00199       continue;
00200 
00201     object_manipulation_msgs::Grasp grasp;
00202 
00203     //# The internal posture of the hand for the pre-grasp
00204     //# only positions are used
00205     //sensor_msgs/JointState pre_grasp_posture
00206     grasp.pre_grasp_posture = pre_grasp_joint_state_;
00207 
00208     //# The internal posture of the hand for the grasp
00209     //# positions and efforts are used
00210     //sensor_msgs/JointState grasp_posture
00211     grasp.grasp_posture = grasp_joint_state_;
00212 
00213     //# The position of the end-effector for the grasp relative to a reference frame
00214     //# (that is always specified elsewhere, not in this message)
00215     //geometry_msgs/Pose grasp_pose
00216     tf::poseTFToMsg(*it, grasp.grasp_pose);
00217 
00218     //# The estimated probability of success for this grasp
00219     //float64 success_probability
00220     grasp.success_probability = 0.5;
00221 
00222     //# Debug flag to indicate that this grasp would be the best in its cluster
00223     //bool cluster_rep
00224     //
00225     //# how far the pre-grasp should ideally be away from the grasp
00226     //float32 desired_approach_distance
00227     grasp.desired_approach_distance = 0.10;
00228 
00229     //# how much distance between pre-grasp and grasp must actually be feasible
00230     //# for the grasp not to be rejected
00231     //float32 min_approach_distance
00232     grasp.min_approach_distance = 0.05;
00233 
00234     // tf_broadcaster_.sendTransform(tf::StampedTransform(*it, ros::Time::now(), "katana_base_link", "wrist_link"));
00235     // ros::Duration(2.0).sleep();
00236 
00237 
00238     feedback.grasps.push_back(grasp);
00239 
00240     // don't publish feedback for now
00241     // as_->publishFeedback(feedback);
00242   }
00243 
00244   result.grasps = feedback.grasps;
00245   if (result.grasps.size() == 0)
00246     result.error_code.value = result.error_code.OTHER_ERROR;
00247   else
00248     result.error_code.value = result.error_code.SUCCESS;
00249 
00250   ROS_INFO("Returning %zu grasps.", result.grasps.size());
00251 
00252   as_.setSucceeded(result);
00253 }
00254 
00255 
00256 
00257 void GraspPlanner::main_loop() {
00258   ros::Rate loop_rate(0.5);
00259 
00260   std::vector<tf::Transform> grasps = generate_grasps(0.30, 0.20, 0.0);
00261 
00262   // publish TFs
00263   for (std::vector<tf::Transform>::iterator it = grasps.begin(); it != grasps.end(); ++it)
00264   {
00265     std::vector<double> ik_sol = get_ik(*it);
00266 
00267     if (ik_sol.size() > 0)
00268       tf_broadcaster_.sendTransform(tf::StampedTransform(*it, ros::Time::now(), "katana_base_link", "wrist_link"));
00269 
00270     if (!ros::ok())
00271       break;
00272 
00273     ros::spinOnce();
00274     loop_rate.sleep();
00275   }
00276 }
00277 
00278 } /* namespace katana_simple_grasp_planner */
00279 
00280 
00281 int main(int argc, char** argv)
00282 {
00283   ros::init(argc, argv, "katana_simple_grasp_planner");
00284   katana_simple_grasp_planner::GraspPlanner grasp_planner_node;
00285 
00286   //grasp_planner_node.main_loop();
00287   ros::spin();
00288   return 0;
00289 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends


katana_simple_grasp_planner
Author(s): Martin Günther
autogenerated on Tue May 28 2013 15:16:51