pr2_arm_kinematics_plugin.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 /*
00031  * Author: Sachin Chitta
00032  */
00033 
00034 #include <pr2_arm_kinematics/pr2_arm_kinematics_plugin.h>
00035 #include <geometry_msgs/PoseStamped.h>
00036 #include <kdl_parser/kdl_parser.hpp>
00037 #include <tf_conversions/tf_kdl.h>
00038 #include "ros/ros.h"
00039 #include <algorithm>
00040 #include <numeric>
00041 
00042 #include <pluginlib/class_list_macros.h>
00043 
00044 using namespace KDL;
00045 using namespace tf;
00046 using namespace std;
00047 using namespace ros;
00048 
00049 //register PR2ArmKinematics as a KinematicsBase implementation
00050 PLUGINLIB_DECLARE_CLASS(pr2_arm_kinematics,PR2ArmKinematicsPlugin, pr2_arm_kinematics::PR2ArmKinematicsPlugin, kinematics::KinematicsBase)
00051 
00052 namespace pr2_arm_kinematics {
00053 
00054 PR2ArmKinematicsPlugin::PR2ArmKinematicsPlugin():active_(false){}
00055 
00056 bool PR2ArmKinematicsPlugin::isActive()
00057 {
00058   if(active_)
00059     return true;
00060   return false;
00061 }
00062 
00063 bool PR2ArmKinematicsPlugin::initialize(const std::string& group_name,
00064                                         const std::string& base_name,
00065                                         const std::string& tip_name,
00066                                         const double& search_discretization)
00067 {
00068   setValues(group_name, base_name, tip_name,search_discretization);
00069   urdf::Model robot_model;
00070   std::string xml_string;
00071   ros::NodeHandle private_handle("~/"+group_name);
00072   dimension_ = 7;
00073   while(!loadRobotModel(private_handle,robot_model,xml_string) && private_handle.ok())
00074   {
00075     ROS_ERROR("Could not load robot model. Are you sure the robot model is on the parameter server?");
00076     ros::Duration(0.5).sleep();
00077   }
00078 
00079   ROS_DEBUG("Loading KDL Tree");
00080   if(!getKDLChain(xml_string,base_name_,tip_name_,kdl_chain_))
00081   {
00082     active_ = false;
00083     ROS_ERROR("Could not load kdl tree");
00084   }
00085   ROS_DEBUG("Advertising services");
00086   jnt_to_pose_solver_.reset(new KDL::ChainFkSolverPos_recursive(kdl_chain_));
00087   private_handle.param<int>("free_angle",free_angle_,2);
00088 
00089   pr2_arm_ik_solver_.reset(new pr2_arm_kinematics::PR2ArmIKSolver(robot_model, base_name_,tip_name_, search_discretization_,free_angle_));
00090   if(!pr2_arm_ik_solver_->active_)
00091   {
00092     ROS_ERROR("Could not load ik");
00093     active_ = false;
00094   }
00095   else
00096   {
00097 
00098     pr2_arm_ik_solver_->getSolverInfo(ik_solver_info_);
00099     pr2_arm_kinematics::getKDLChainInfo(kdl_chain_,fk_solver_info_);
00100     fk_solver_info_.joint_names = ik_solver_info_.joint_names;
00101 
00102     for(unsigned int i=0; i < ik_solver_info_.joint_names.size(); i++)
00103     {
00104       ROS_DEBUG("PR2Kinematics:: joint name: %s",ik_solver_info_.joint_names[i].c_str());
00105     }
00106     for(unsigned int i=0; i < ik_solver_info_.link_names.size(); i++)
00107     {
00108       ROS_DEBUG("PR2Kinematics can solve IK for %s",ik_solver_info_.link_names[i].c_str());
00109     }
00110     for(unsigned int i=0; i < fk_solver_info_.link_names.size(); i++)
00111     {
00112       ROS_DEBUG("PR2Kinematics can solve FK for %s",fk_solver_info_.link_names[i].c_str());
00113     }
00114     ROS_DEBUG("PR2KinematicsPlugin::active for %s",group_name.c_str());
00115     active_ = true;
00116   }    
00117   return active_;
00118 }
00119 
00120 bool PR2ArmKinematicsPlugin::getPositionIK(const geometry_msgs::Pose &ik_pose,
00121                                            const std::vector<double> &ik_seed_state,
00122                                            std::vector<double> &solution,
00123                                            int &error_code)
00124 {
00125   if(!active_)
00126   {
00127     ROS_ERROR("kinematics not active");
00128     error_code = kinematics::NO_IK_SOLUTION; 
00129     return false;
00130   }
00131     
00132   KDL::Frame pose_desired;
00133   tf::poseMsgToKDL(ik_pose, pose_desired);
00134 
00135   //Do the IK
00136   KDL::JntArray jnt_pos_in;
00137   KDL::JntArray jnt_pos_out;
00138   jnt_pos_in.resize(dimension_);
00139   for(int i=0; i < dimension_; i++)
00140   {
00141     jnt_pos_in(i) = ik_seed_state[i];
00142   }
00143 
00144   int ik_valid = pr2_arm_ik_solver_->CartToJnt(jnt_pos_in,
00145                                                pose_desired,
00146                                                jnt_pos_out);
00147   if(ik_valid == pr2_arm_kinematics::NO_IK_SOLUTION)
00148   {
00149     error_code = kinematics::NO_IK_SOLUTION; 
00150     return false;
00151   }
00152 
00153   if(ik_valid >= 0)
00154   {
00155     solution.resize(dimension_);
00156     for(int i=0; i < dimension_; i++)
00157     {
00158       solution[i] = jnt_pos_out(i);
00159     }
00160     error_code = kinematics::SUCCESS;
00161     return true;
00162   }
00163   else
00164   {
00165     ROS_DEBUG("An IK solution could not be found");   
00166     error_code = kinematics::NO_IK_SOLUTION; 
00167     return false;
00168   }
00169 }
00170 
00171 bool PR2ArmKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose &ik_pose,
00172                                               const std::vector<double> &ik_seed_state,
00173                                               const double &timeout,
00174                                               std::vector<double> &solution,
00175                                               int &error_code)
00176 {
00177   if(!active_)
00178   {
00179     ROS_ERROR("kinematics not active");
00180     error_code = kinematics::INACTIVE; 
00181     return false;
00182   }
00183   KDL::Frame pose_desired;
00184   tf::poseMsgToKDL(ik_pose, pose_desired);
00185   //Do the IK
00186   KDL::JntArray jnt_pos_in;
00187   KDL::JntArray jnt_pos_out;
00188   jnt_pos_in.resize(dimension_);
00189   for(int i=0; i < dimension_; i++)
00190   {
00191     jnt_pos_in(i) = ik_seed_state[i];
00192   }
00193 
00194   int ik_valid = pr2_arm_ik_solver_->CartToJntSearch(jnt_pos_in,
00195                                                      pose_desired,
00196                                                      jnt_pos_out,
00197                                                      timeout);
00198   if(ik_valid == pr2_arm_kinematics::NO_IK_SOLUTION) {
00199     error_code = kinematics::NO_IK_SOLUTION; 
00200     return false;
00201   }
00202 
00203   if(ik_valid >= 0)
00204   {
00205     solution.resize(dimension_);
00206     for(int i=0; i < dimension_; i++)
00207     {
00208       solution[i] = jnt_pos_out(i);
00209     }
00210     error_code = kinematics::SUCCESS;
00211     return true;
00212   }
00213   else
00214   {
00215     ROS_DEBUG("An IK solution could not be found");   
00216     error_code = kinematics::NO_IK_SOLUTION; 
00217     return false;
00218   }
00219 }
00220 
00221 bool PR2ArmKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose &ik_pose,
00222                                               const std::vector<double> &ik_seed_state,
00223                                               const double &timeout,
00224                                               const unsigned int& redundancy,
00225                                               const double &consistency_limit,
00226                                               std::vector<double> &solution,
00227                                               int &error_code)
00228 {
00229   if(!active_)
00230   {
00231     ROS_ERROR("kinematics not active");
00232     error_code = kinematics::INACTIVE; 
00233     return false;
00234   }
00235   KDL::Frame pose_desired;
00236   tf::poseMsgToKDL(ik_pose, pose_desired);
00237 
00238   //Do the IK
00239   KDL::JntArray jnt_pos_in;
00240   KDL::JntArray jnt_pos_out;
00241   jnt_pos_in.resize(dimension_);
00242   for(int i=0; i < dimension_; i++)
00243   {
00244     jnt_pos_in(i) = ik_seed_state[i];
00245   }
00246 
00247   unsigned int old_free_angle = pr2_arm_ik_solver_->getFreeAngle();
00248   pr2_arm_ik_solver_->setFreeAngle(redundancy);
00249   int ik_valid = pr2_arm_ik_solver_->CartToJntSearch(jnt_pos_in,
00250                                                      pose_desired,
00251                                                      consistency_limit,
00252                                                      jnt_pos_out,
00253                                                      timeout);
00254   pr2_arm_ik_solver_->setFreeAngle(old_free_angle);
00255 
00256   if(ik_valid == pr2_arm_kinematics::NO_IK_SOLUTION)
00257   {
00258     error_code = kinematics::NO_IK_SOLUTION; 
00259     return false;
00260   }
00261 
00262   if(ik_valid >= 0)
00263   {
00264     solution.resize(dimension_);
00265     for(int i=0; i < dimension_; i++)
00266     {
00267       solution[i] = jnt_pos_out(i);
00268     }
00269     error_code = kinematics::SUCCESS;
00270     return true;
00271   }
00272   else
00273   {
00274     ROS_DEBUG("An IK solution could not be found");   
00275     error_code = kinematics::NO_IK_SOLUTION; 
00276     return false;
00277   }
00278 }
00279 
00280 
00281 void PR2ArmKinematicsPlugin::desiredPoseCallback(const KDL::JntArray& jnt_array, 
00282                                                  const KDL::Frame& ik_pose,
00283                                                  arm_navigation_msgs::ArmNavigationErrorCodes& error_code)
00284 {
00285   std::vector<double> ik_seed_state;
00286   ik_seed_state.resize(dimension_);
00287   int int_error_code;
00288   for(int i=0; i < dimension_; i++)
00289     ik_seed_state[i] = jnt_array(i);
00290 
00291   geometry_msgs::Pose ik_pose_msg;
00292   tf::poseKDLToMsg(ik_pose,ik_pose_msg);
00293 
00294   desiredPoseCallback_(ik_pose_msg,ik_seed_state,int_error_code);
00295   if(int_error_code)
00296     error_code.val = arm_navigation_msgs::ArmNavigationErrorCodes::SUCCESS;
00297   else
00298     error_code.val = arm_navigation_msgs::ArmNavigationErrorCodes::NO_IK_SOLUTION;     
00299 }
00300 
00301 
00302 void PR2ArmKinematicsPlugin::jointSolutionCallback(const KDL::JntArray& jnt_array, 
00303                                                    const KDL::Frame& ik_pose,
00304                                                    arm_navigation_msgs::ArmNavigationErrorCodes& error_code)
00305 {
00306   std::vector<double> ik_seed_state;
00307   ik_seed_state.resize(dimension_);
00308   int int_error_code;
00309   for(int i=0; i < dimension_; i++)
00310     ik_seed_state[i] = jnt_array(i);
00311 
00312   geometry_msgs::Pose ik_pose_msg;
00313   tf::poseKDLToMsg(ik_pose,ik_pose_msg);
00314 
00315   solutionCallback_(ik_pose_msg,ik_seed_state,int_error_code);
00316   if(int_error_code > 0)
00317     error_code.val = arm_navigation_msgs::ArmNavigationErrorCodes::SUCCESS;
00318   else
00319     error_code.val = arm_navigation_msgs::ArmNavigationErrorCodes::NO_IK_SOLUTION;     
00320 }
00321 
00322 bool PR2ArmKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose &ik_pose,
00323                                               const std::vector<double> &ik_seed_state,
00324                                               const double &timeout,
00325                                               std::vector<double> &solution,
00326                                               const boost::function<void(const geometry_msgs::Pose &ik_pose,const std::vector<double> &ik_solution,int &error_code)> &desired_pose_callback,
00327                                               const boost::function<void(const geometry_msgs::Pose &ik_pose,const std::vector<double> &ik_solution,int &error_code)> &solution_callback,
00328                                               int &error_code_int)  
00329 {
00330   if(!active_)
00331   {
00332     ROS_ERROR("kinematics not active");
00333     error_code_int = kinematics::INACTIVE;
00334     return false;
00335   }
00336   KDL::Frame pose_desired;
00337   tf::poseMsgToKDL(ik_pose, pose_desired);
00338 
00339   desiredPoseCallback_ = desired_pose_callback;
00340   solutionCallback_    = solution_callback;
00341 
00342   //Do the IK
00343   KDL::JntArray jnt_pos_in;
00344   KDL::JntArray jnt_pos_out;
00345   jnt_pos_in.resize(dimension_);
00346   for(int i=0; i < dimension_; i++)
00347   {
00348     jnt_pos_in(i) = ik_seed_state[i];
00349   }
00350 
00351   arm_navigation_msgs::ArmNavigationErrorCodes error_code;
00352   int ik_valid = pr2_arm_ik_solver_->CartToJntSearch(jnt_pos_in,
00353                                                      pose_desired,
00354                                                      jnt_pos_out,
00355                                                      timeout,
00356                                                      error_code,
00357                                                      boost::bind(&PR2ArmKinematicsPlugin::desiredPoseCallback, this, _1, _2, _3),
00358                                                      boost::bind(&PR2ArmKinematicsPlugin::jointSolutionCallback, this, _1, _2, _3));
00359   if(ik_valid == pr2_arm_kinematics::NO_IK_SOLUTION)
00360     return false;
00361 
00362   if(ik_valid >= 0)
00363   {
00364     solution.resize(dimension_);
00365     for(int i=0; i < dimension_; i++)
00366     {
00367       solution[i] = jnt_pos_out(i);
00368     }
00369     error_code_int = kinematics::SUCCESS;
00370     return true;
00371   }
00372   else
00373   {
00374     ROS_DEBUG("An IK solution could not be found");   
00375     error_code_int = error_code.val;
00376     return false;
00377   }
00378 }
00379 
00380 bool PR2ArmKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose &ik_pose,
00381                                               const std::vector<double> &ik_seed_state,
00382                                               const double &timeout,
00383                                               const unsigned int& redundancy,
00384                                               const double &consistency_limit,
00385                                               std::vector<double> &solution,
00386                                               const boost::function<void(const geometry_msgs::Pose &ik_pose,const std::vector<double> &ik_solution,int &error_code)> &desired_pose_callback,
00387                                               const boost::function<void(const geometry_msgs::Pose &ik_pose,const std::vector<double> &ik_solution,int &error_code)> &solution_callback,
00388                                               int &error_code_int)  
00389 {
00390   if(!active_)
00391   {
00392     ROS_ERROR("kinematics not active");
00393     error_code_int = kinematics::INACTIVE;
00394     return false;
00395   }
00396   KDL::Frame pose_desired;
00397   tf::poseMsgToKDL(ik_pose, pose_desired);
00398 
00399   desiredPoseCallback_ = desired_pose_callback;
00400   solutionCallback_    = solution_callback;
00401 
00402   //Do the IK
00403   KDL::JntArray jnt_pos_in;
00404   KDL::JntArray jnt_pos_out;
00405   jnt_pos_in.resize(dimension_);
00406   for(int i=0; i < dimension_; i++)
00407   {
00408     jnt_pos_in(i) = ik_seed_state[i];
00409   }
00410 
00411   arm_navigation_msgs::ArmNavigationErrorCodes error_code;
00412   unsigned int old_free_angle = pr2_arm_ik_solver_->getFreeAngle();
00413   pr2_arm_ik_solver_->setFreeAngle(redundancy);
00414   int ik_valid = pr2_arm_ik_solver_->CartToJntSearch(jnt_pos_in,
00415                                                      pose_desired,
00416                                                      jnt_pos_out,
00417                                                      consistency_limit,
00418                                                      timeout,
00419                                                      error_code,
00420                                                      boost::bind(&PR2ArmKinematicsPlugin::desiredPoseCallback, this, _1, _2, _3),
00421                                                      boost::bind(&PR2ArmKinematicsPlugin::jointSolutionCallback, this, _1, _2, _3));
00422   pr2_arm_ik_solver_->setFreeAngle(old_free_angle);
00423   if(ik_valid == pr2_arm_kinematics::NO_IK_SOLUTION)
00424     return false;
00425 
00426   if(ik_valid >= 0)
00427   {
00428     solution.resize(dimension_);
00429     for(int i=0; i < dimension_; i++)
00430     {
00431       solution[i] = jnt_pos_out(i);
00432     }
00433     error_code_int = kinematics::SUCCESS;
00434     return true;
00435   }
00436   else
00437   {
00438     ROS_DEBUG("An IK solution could not be found");   
00439     error_code_int = error_code.val;
00440     return false;
00441   }
00442 }
00443 
00444 bool PR2ArmKinematicsPlugin::getPositionFK(const std::vector<std::string> &link_names,
00445                                            const std::vector<double> &joint_angles,
00446                                            std::vector<geometry_msgs::Pose> &poses)
00447 {
00448   if(!active_)
00449   {
00450     ROS_ERROR("kinematics not active");
00451     return false;
00452   }
00453 
00454   KDL::Frame p_out;
00455   KDL::JntArray jnt_pos_in;
00456   geometry_msgs::PoseStamped pose;
00457   tf::Stamped<tf::Pose> tf_pose;
00458 
00459   jnt_pos_in.resize(dimension_);
00460   for(int i=0; i < dimension_; i++)
00461   {
00462     jnt_pos_in(i) = joint_angles[i];
00463   }
00464 
00465   poses.resize(link_names.size());
00466 
00467   bool valid = true;
00468   for(unsigned int i=0; i < poses.size(); i++)
00469   {
00470     ROS_DEBUG("End effector index: %d",pr2_arm_kinematics::getKDLSegmentIndex(kdl_chain_,link_names[i]));
00471     if(jnt_to_pose_solver_->JntToCart(jnt_pos_in,p_out,pr2_arm_kinematics::getKDLSegmentIndex(kdl_chain_,link_names[i])) >=0)
00472     {
00473       tf::poseKDLToMsg(p_out,poses[i]);
00474     }
00475     else
00476     {
00477       ROS_ERROR("Could not compute FK for %s",link_names[i].c_str());
00478       valid = false;
00479     }
00480   }
00481   return valid;
00482 }
00483 
00484 const std::vector<std::string>& PR2ArmKinematicsPlugin::getJointNames() const
00485 {
00486   if(!active_)
00487   {
00488     ROS_ERROR("kinematics not active");
00489   }
00490   return ik_solver_info_.joint_names;
00491 }
00492 
00493 const std::vector<std::string>& PR2ArmKinematicsPlugin::getLinkNames() const
00494 {
00495   if(!active_)
00496   {
00497     ROS_ERROR("kinematics not active");
00498   }
00499   return fk_solver_info_.link_names;
00500 }
00501 
00502 } // namespace


pr2_arm_kinematics
Author(s): Sachin Chitta
autogenerated on Tue Apr 22 2014 19:33:02