$search
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 }