00001
00002 #include "ros/ros.h"
00003 #include <kinematics_base/kinematics_base.h>
00004 #include <kdl/tree.hpp>
00005 #include <urdf/model.h>
00006 #include <kdl_parser/kdl_parser.hpp>
00007 #include <kdl/chainfksolverpos_recursive.hpp>
00008 #include <tf/tf.h>
00009 #include <tf_conversions/tf_kdl.h>
00010 #include <map>
00011 #include <iostream>
00012 #define IKFAST_NO_MAIN
00013 #ifdef IKFAST_REAL
00014 typedef IKFAST_REAL IKReal;
00015 #else
00016 typedef double IKReal;
00017 #endif
00018
00019
00020 namespace cob3_arm_kinematics
00021 {
00022
00023 class ik_solver_base{
00024 public:
00025 virtual int solve(KDL::Frame &pose_frame, const std::vector<double> &ik_seed_state) = 0;
00026 virtual void getSolution(int i, std::vector<double> &solution) = 0;
00027 virtual void getClosestSolution(const std::vector<double> &ik_seed_state, std::vector<double> &solution) = 0;
00028 };
00029
00030 template <class T> class ikfast_solver: public ik_solver_base{
00031 public:
00032 typedef bool (*ik_type)(const IKReal* eetrans, const IKReal* eerot, const IKReal* pfree, std::vector<T>& vsolutions);
00033 ikfast_solver(ik_type ik,int numJoints):ik(ik),numJoints(numJoints) {}
00034 virtual int solve(KDL::Frame &pose_frame, const std::vector<double> &vfree){
00035
00036 solutions.clear();
00037 ik(pose_frame.p.data, pose_frame.M.data, vfree.size() > 0 ? &vfree[0] : NULL, solutions);
00038
00039 return solutions.size();
00040 }
00041 virtual void getSolution(int i, std::vector<double> &solution){
00042 solution.clear();
00043 std::vector<IKReal> vsolfree(solutions[i].GetFree().size());
00044 solution.clear();
00045 solution.resize(numJoints);
00046 solutions[i].GetSolution(&solution[0],vsolfree.size()>0?&vsolfree[0]:NULL);
00047 std::cout << "solution " << i << ":" ;
00048 for(int j=0;j<numJoints; ++j)
00049 std::cout << " " << solution[j];
00050 std::cout << std::endl;
00051
00052
00053 }
00054 virtual void getClosestSolution(const std::vector<double> &ik_seed_state, std::vector<double> &solution){
00055 double mindist = 0;
00056 int minindex = -1;
00057 std::vector<double> sol;
00058 for(size_t i=0;i<solutions.size();++i){
00059 getSolution(i,sol);
00060 double dist = 0;
00061 for(int j=0;j< numJoints;++j){
00062 double diff = ik_seed_state[j] - sol[j];
00063 dist += diff*diff;
00064 }
00065 if(minindex == -1 || dist<mindist){
00066 minindex = i;
00067 mindist = dist;
00068 }
00069 }
00070 if(minindex >= 0) getSolution(minindex,solution);
00071 }
00072
00073
00074
00075 private:
00076 ik_type ik;
00077 std::vector<T> solutions;
00078 int numJoints;
00079 };
00080
00081
00082 namespace cob3_2{
00083 #include "ikfast_cob3_2.cpp"
00084 }
00085
00086 class IKFastKinematicsPlugin : public kinematics::KinematicsBase
00087 {
00088 std::vector<std::string> joints;
00089 std::vector<double> jointMin;
00090 std::vector<double> jointMax;
00091 std::vector<std::string> links;
00092 std::map<std::string,size_t> link2index;
00093 std::string tip_name, root_name;
00094 KDL::Chain kdl_chain;
00095 boost::shared_ptr<KDL::ChainFkSolverPos_recursive> jnt_to_pose_solver;
00096 ik_solver_base* ik_solver;
00097 size_t numJoints;
00098 std::vector<int> freeParams;
00099
00100 public:
00101
00102 IKFastKinematicsPlugin():ik_solver(0) {}
00103 ~IKFastKinematicsPlugin(){ if(ik_solver) delete ik_solver;}
00104
00105 void fillFreeParams(int count, int *array) { freeParams.clear(); for(int i=0; i<count;++i) freeParams.push_back(array[i]); }
00106
00107 bool initialize(std::string name) {
00108
00109 ros::NodeHandle node_handle("~/"+name);
00110
00111 std::string robot;
00112 node_handle.param("robot",robot,std::string());
00113
00114 if(robot == "cob3-2"){
00115 fillFreeParams(cob3_2::getNumFreeParameters(),cob3_2::getFreeParameters());
00116 numJoints = cob3_2::getNumJoints();
00117 ik_solver = new ikfast_solver<cob3_2::IKSolution>(cob3_2::ik, numJoints);
00118 }else{
00119 ROS_FATAL("Robot '%s' unknown!",robot.c_str());
00120 return false;
00121 }
00122
00123 if(freeParams.size()>1){
00124 ROS_FATAL("Only one free joint paramter supported!");
00125 return false;
00126 }
00127
00128
00129 urdf::Model robot_model;
00130 std::string xml_string;
00131
00132 std::string urdf_xml,full_urdf_xml;
00133 node_handle.param("urdf_xml",urdf_xml,std::string("robot_description"));
00134 node_handle.searchParam(urdf_xml,full_urdf_xml);
00135
00136 ROS_DEBUG("Reading xml file from parameter server\n");
00137 if (!node_handle.getParam(full_urdf_xml, xml_string))
00138 {
00139 ROS_FATAL("Could not load the xml from parameter server: %s\n", urdf_xml.c_str());
00140 return false;
00141 }
00142
00143 if (!node_handle.getParam("root_name", root_name)){
00144 ROS_FATAL("PR2IK: No root name found on parameter server");
00145 return false;
00146 }
00147 if (!node_handle.getParam("tip_name", tip_name)){
00148 ROS_FATAL("PR2IK: No tip name found on parameter server");
00149 return false;
00150 }
00151
00152 KDL::Tree tree;
00153 if (!kdl_parser::treeFromString(xml_string, tree))
00154 {
00155 ROS_ERROR("Could not initialize tree object");
00156 return false;
00157 }
00158
00159
00160
00161
00162
00163
00164 if (!tree.getChain(root_name, tip_name, kdl_chain))
00165 {
00166 ROS_ERROR("Could not initialize kdl_chain object");
00167 return false;
00168 }
00169
00170 int i=0;
00171 while(i < (int)kdl_chain.getNrOfSegments())
00172 {
00173 link2index.insert(std::make_pair(kdl_chain.getSegment(i).getName(),i));
00174 links.push_back(kdl_chain.getSegment(i).getName());
00175 if(links.size()>1){
00176 joints.push_back(kdl_chain.getSegment(i).getJoint().getName());
00177 ROS_ERROR("Joint %s",joints.back().c_str());
00178
00179 }
00180 i++;
00181 }
00182 if(joints.size() != numJoints){
00183 ROS_ERROR("Joints count mismatch");
00184 return false;
00185 }
00186
00187 jnt_to_pose_solver.reset(new KDL::ChainFkSolverPos_recursive(kdl_chain));
00188
00189
00190 return true;
00191 }
00192
00193 bool getPositionIK(const geometry_msgs::Pose &ik_pose,
00194 const std::vector<double> &ik_seed_state,
00195 std::vector<double> &solution,
00196 int &error_code) {
00197 ROS_ERROR("getPositionIK");
00198
00199 std::vector<double> vfree(freeParams.size());
00200 for(std::size_t i = 0; i < freeParams.size(); ++i){
00201 int p = freeParams[i];
00202
00203 vfree[i] = ik_seed_state[p];
00204 }
00205
00206 KDL::Frame frame;
00207 tf::PoseMsgToKDL(ik_pose,frame);
00208
00209 int numsol = ik_solver->solve(frame,vfree);
00210
00211
00212 if(numsol){
00213 ik_solver->getClosestSolution(ik_seed_state,solution);
00214 ROS_ERROR("Solved!");
00215 error_code = kinematics::SUCCESS;
00216 return true;
00217 }
00218
00219 error_code = kinematics::NO_IK_SOLUTION;
00220 return false;
00221 }
00222 bool searchPositionIK(const geometry_msgs::Pose &ik_pose,
00223 const std::vector<double> &ik_seed_state,
00224 const double &timeout,
00225 std::vector<double> &solution,
00226 int &error_code) {
00227
00228 ROS_ERROR("searchPositionIK1");
00229 if(freeParams.size()==0){
00230 return getPositionIK(ik_pose, ik_seed_state,solution, error_code);
00231 }
00232
00233 KDL::Frame frame;
00234 tf::PoseMsgToKDL(ik_pose,frame);
00235
00236 std::vector<double> vfree(freeParams.size());
00237
00238 ros::Time maxTime = ros::Time::now() + ros::Duration(timeout);
00239 const double increment = 0.01;
00240 int counter = 0;
00241
00242 while (ros::Time::now() < maxTime){
00243 vfree[0] = ik_seed_state[freeParams[0]] + increment*counter;
00244
00245 int numsol = ik_solver->solve(frame,vfree);
00246
00247 if(numsol > 0){
00248 ik_solver->getClosestSolution(ik_seed_state,solution);
00249 ROS_ERROR("Solved!");
00250 error_code = kinematics::SUCCESS;
00251 return true;
00252 }
00253 int i = 0;
00254 do{
00255 if( i >= 2){
00256 error_code = kinematics::NO_IK_SOLUTION;
00257 return false;
00258 }
00259 counter = counter > 0? - counter: counter + 1;
00260 ++i;
00261 }while( counter * increment < jointMin[freeParams[0]] || counter * increment > jointMax[freeParams[0]] );
00262
00263 }
00264 error_code = kinematics::NO_IK_SOLUTION;
00265 return false;
00266 }
00267 bool searchPositionIK(const geometry_msgs::Pose &ik_pose,
00268 const std::vector<double> &ik_seed_state,
00269 const double &timeout,
00270 std::vector<double> &solution,
00271 const boost::function<void(const geometry_msgs::Pose &ik_pose,const std::vector<double> &ik_solution,int &error_code)> &desired_pose_callback,
00272 const boost::function<void(const geometry_msgs::Pose &ik_pose,const std::vector<double> &ik_solution,int &error_code)> &solution_callback,
00273 int &error_code){
00274
00275 ROS_ERROR("searchPositionIK2");
00276 if(freeParams.size()==0){
00277 return getPositionIK(ik_pose, ik_seed_state,solution, error_code);
00278 }
00279
00280 if(!desired_pose_callback.empty())
00281 desired_pose_callback(ik_pose,ik_seed_state,error_code);
00282 if(error_code < 0)
00283 {
00284 ROS_ERROR("Could not find inverse kinematics for desired end-effector pose since the pose may be in collision");
00285 return false;
00286 }
00287
00288 KDL::Frame frame;
00289 tf::PoseMsgToKDL(ik_pose,frame);
00290
00291 std::vector<double> vfree(freeParams.size());
00292
00293 ros::Time maxTime = ros::Time::now() + ros::Duration(timeout);
00294 const double increment = 0.01;
00295 int counter = 0;
00296
00297 std::vector<double> sol;
00298 while (ros::Time::now() < maxTime){
00299 if(freeParams.size())
00300 vfree[0] = ik_seed_state[freeParams[0]] + increment*counter;
00301
00302 int numsol = ik_solver->solve(frame,vfree);
00303
00304 if(numsol > 0){
00305 if(solution_callback.empty()){
00306 ik_solver->getClosestSolution(ik_seed_state,solution);
00307 error_code = kinematics::SUCCESS;
00308 return true;
00309 }
00310
00311 for (int s = 0; s < numsol; ++s){
00312 ik_solver->getSolution(s,sol);
00313 solution_callback(ik_pose,sol,error_code);
00314
00315 if(error_code == kinematics::SUCCESS){
00316 solution = sol;
00317 ROS_ERROR("Solved!");
00318 return true;
00319 }
00320 }
00321 }
00322 int i = 0;
00323 do{
00324 if( i >= 2 || freeParams.size()==0){
00325 error_code = kinematics::NO_IK_SOLUTION;
00326 return false;
00327 }
00328 counter = counter > 0? - counter: counter + 1 ;
00329 ++i;
00330 }while( counter * increment < jointMin[freeParams[0]] || counter * increment > jointMax[freeParams[0]] );
00331
00332 }
00333 error_code = kinematics::NO_IK_SOLUTION;
00334 return false;
00335 }
00336 bool getPositionFK(const std::vector<std::string> &link_names,
00337 const std::vector<double> &joint_angles,
00338 std::vector<geometry_msgs::Pose> &poses){
00339 KDL::Frame p_out;
00340 KDL::JntArray jnt_pos_in;
00341 geometry_msgs::PoseStamped pose;
00342 tf::Stamped<tf::Pose> tf_pose;
00343
00344 jnt_pos_in.resize(joints.size());
00345 for(size_t i=0; i < joints.size(); i++)
00346 {
00347 jnt_pos_in(i) = joint_angles[i];
00348 }
00349
00350 poses.resize(link_names.size());
00351
00352 bool valid = true;
00353 for(unsigned int i=0; i < poses.size(); i++)
00354 {
00355 if(jnt_to_pose_solver->JntToCart(jnt_pos_in,p_out,link2index[link_names[i]]) >=0)
00356 {
00357 tf::PoseKDLToMsg(p_out,poses[i]);
00358 }
00359 else
00360 {
00361 ROS_ERROR("Could not compute FK for %s",link_names[i].c_str());
00362 valid = false;
00363 }
00364 }
00365 ROS_ERROR("getPositionFK %s",valid?"succeded":"failed");
00366
00367 return valid;
00368 }
00369 std::string getBaseFrame() { ROS_ERROR("getBaseFrame");
00370 return root_name; }
00371 std::string getToolFrame() { ROS_ERROR("getToolFrame");
00372 return tip_name; }
00373 std::vector<std::string> getJointNames() { ROS_ERROR("getJointNames");
00374 return joints; }
00375 std::vector<std::string> getLinkNames() { ROS_ERROR("getLinkNames");
00376 return links; }
00377 };
00378 }
00379
00380 #include <pluginlib/class_list_macros.h>
00381 PLUGINLIB_DECLARE_CLASS(cob3_arm_kinematics,IKFastKinematicsPlugin, cob3_arm_kinematics::IKFastKinematicsPlugin, kinematics::KinematicsBase)