reem_arm_kinematics_plugin.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (Modified BSD License)
00003  *
00004  *  Copyright (c) 2012, PAL Robotics, S.L.
00005  *  Copyright (c) 2008, Willow Garage, Inc.
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/or other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of PAL Robotics, S.L. nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
00034  */
00035 
00040 #include <reem_kinematics_constraint_aware/reem_arm_kinematics_plugin.h>
00041 #include <pluginlib/class_list_macros.h>
00042 
00043 using namespace KDL;
00044 using namespace tf;
00045 using namespace std;
00046 using namespace ros;
00047  
00048 const double BOUNDS_EPSILON = .00001;
00049  
00050 //register ReemKinematics as a KinematicsBase implementation
00051 PLUGINLIB_DECLARE_CLASS(reem_kinematics_constraint_aware,ReemKinematicsPlugin, reem_kinematics_constraint_aware::ReemKinematicsPlugin, kinematics::KinematicsBase)
00052 
00053 namespace reem_kinematics_constraint_aware {
00054 
00055 ReemKinematicsPlugin::ReemKinematicsPlugin():active_(false)
00056 {
00057   srand ( time(NULL) );
00058 }
00059 
00060 bool ReemKinematicsPlugin::isActive()
00061 {
00062   if(active_)
00063     return true;
00064   return false;
00065 }
00066 
00067 double ReemKinematicsPlugin::genRandomNumber(const double &min, const double &max)
00068 {
00069   int rand_num = rand()%100+1;
00070   double result = min + (double)((max-min)*rand_num)/101.0;
00071   return result;
00072 }
00073 
00074 KDL::JntArray ReemKinematicsPlugin::getRandomConfiguration()
00075 {
00076   KDL::JntArray jnt_array;
00077   jnt_array.resize(dimension_);
00078   for(unsigned int i=0; i < dimension_; ++i)
00079     jnt_array(i) = genRandomNumber(joint_min_(i),joint_max_(i));
00080   return jnt_array;
00081 }
00082 
00083 KDL::JntArray ReemKinematicsPlugin::getRandomConfiguration(const KDL::JntArray& seed_state,
00084                                                            const unsigned int& redundancy,
00085                                                            const double& consistency_limit)
00086 {
00087   KDL::JntArray jnt_array;
00088   jnt_array.resize(dimension_);
00089   for(unsigned int i=0; i < dimension_; i++) {
00090     if(i != redundancy) {
00091       jnt_array(i) = genRandomNumber(joint_min_(i),joint_max_(i));
00092     } else {
00093       double jmin = fmin(joint_min_(i), seed_state(i)-consistency_limit);
00094       double jmax = fmax(joint_max_(i), seed_state(i)+consistency_limit);
00095       jnt_array(i) = genRandomNumber(jmin, jmax);
00096     }
00097   }
00098   return jnt_array;
00099 }
00100 
00101 bool ReemKinematicsPlugin::checkConsistency(const KDL::JntArray& seed_state,
00102                                             const unsigned int& redundancy,
00103                                             const double& consistency_limit,
00104                                             const KDL::JntArray& solution) const
00105 {
00106   KDL::JntArray jnt_array;
00107   jnt_array.resize(dimension_);
00108   for(unsigned int i=0; i < dimension_; i++) {
00109     if(i == redundancy) {
00110       double jmin = fmin(joint_min_(i), seed_state(i)-consistency_limit);
00111       double jmax = fmax(joint_max_(i), seed_state(i)+consistency_limit);
00112       if(solution(i) < jmin || solution(i) > jmax) {
00113         return false;
00114       }
00115     }
00116   }
00117   return true;
00118 }
00119 
00120 bool ReemKinematicsPlugin::initialize(const std::string& group_name,
00121                                       const std::string& base_name,
00122                                       const std::string& tip_name,
00123                                       const double& search_discretization)
00124 {
00125   setValues(group_name, base_name, tip_name, search_discretization);
00126   // Get URDF XML
00127   std::string urdf_xml, full_urdf_xml;
00128   ros::NodeHandle node_handle;
00129   ros::NodeHandle private_handle("~"+group_name);
00130   ROS_INFO_STREAM("Private handle registered under " << private_handle.getNamespace());
00131   node_handle.param("urdf_xml",urdf_xml,std::string("robot_description"));
00132   node_handle.searchParam(urdf_xml,full_urdf_xml);
00133   ROS_DEBUG("Reading xml file from parameter server");
00134   std::string result;
00135   if (!node_handle.getParam(full_urdf_xml, result)) {
00136     ROS_FATAL("Could not load the xml from parameter server: %s", urdf_xml.c_str());
00137     return false;
00138   }
00139 
00140   // Load and Read Models
00141   if (!loadModel(result)) {
00142     ROS_FATAL("Could not load models!");
00143     return false;
00144   }
00145 
00146   // Populate map from joint names to KDL tree indices
00147   std::map<std::string, int> joint_name_to_idx;
00148   for (size_t i = 0; i < kdl_chain_.getNrOfSegments(); ++i)
00149   {
00150     const KDL::Joint& joint = kdl_chain_.getSegment(i).getJoint();
00151     if (joint.getType() != KDL::Joint::None)
00152     {
00153       joint_name_to_idx[joint.getName()] = i;
00154     }
00155   }
00156 
00157   // Space diensions
00158   const int q_dim = kdl_chain_.getNrOfJoints();
00159   const int x_dim = 6;
00160 
00161   // Get Solver Parameters
00162   int max_iterations;
00163   double epsilon;
00164   double max_delta_x;
00165   double max_delta_q;
00166   double velik_gain;
00167 
00168   private_handle.param("max_solver_iterations", max_iterations, 500);
00169   private_handle.param("max_search_iterations", max_search_iterations_, 3);
00170   private_handle.param("epsilon", epsilon, 1e-5);
00171   private_handle.param("max_delta_x", max_delta_x, 0.006);
00172   private_handle.param("max_delta_q", max_delta_q, 0.03);
00173   private_handle.param("velik_gain", velik_gain,   1.0);
00174 
00175   // Joint space weights diagonal matrix inverse and default posture
00176   Eigen::VectorXd Wqinv = Eigen::VectorXd::Ones(q_dim);
00177   default_posture_.resize(q_dim);
00178   for (size_t i = 0; i < kdl_chain_.getNrOfSegments(); ++i)
00179   {
00180     const KDL::Joint& joint = kdl_chain_.getSegment(i).getJoint();
00181     if (joint.getType() != KDL::Joint::None)
00182     {
00183       private_handle.param("joint_weights/"   + joint.getName(), Wqinv(joint_name_to_idx[joint.getName()]),            1.0);
00184       private_handle.param("default_posture/" + joint.getName(), default_posture_[joint_name_to_idx[joint.getName()]], 0.0);
00185     }
00186   }
00187 
00188   // Task space weights diagonal matrix
00189   Eigen::VectorXd Wxinv = Eigen::VectorXd::Ones(x_dim);
00190   private_handle.param("task_weights/position/x", Wxinv(0), 1.0);
00191   private_handle.param("task_weights/position/y", Wxinv(1), 1.0);
00192   private_handle.param("task_weights/position/z", Wxinv(2), 1.0);
00193   private_handle.param("task_weights/orientation/x", Wxinv(3), 1.0);
00194   private_handle.param("task_weights/orientation/y", Wxinv(4), 1.0);
00195   private_handle.param("task_weights/orientation/z", Wxinv(5), 1.0);
00196 
00197   // Build Solvers
00198   fk_solver_.reset(new KDL::ChainFkSolverPos_recursive(kdl_chain_));
00199   ik_solver_.reset(new IkSolver(kdl_chain_));
00200   ik_solver_->setJointPositionLimits(joint_min_.data, joint_max_.data);
00201   ik_solver_->setEpsilon(epsilon);
00202   ik_solver_->setMaxIterations(max_iterations);
00203   ik_solver_->setMaxDeltaPosTask(max_delta_x);
00204   ik_solver_->setMaxDeltaPosJoint(max_delta_q);
00205   ik_solver_->setVelocityIkGain(velik_gain);
00206   ik_solver_->setJointSpaceWeights(Wqinv);
00207   ik_solver_->setTaskSpaceWeights(Wxinv);
00208   active_ = true;
00209   return true;
00210 }
00211 
00212 bool ReemKinematicsPlugin::loadModel(const std::string xml)
00213 {
00214   urdf::Model robot_model;
00215   KDL::Tree tree;
00216 
00217   if (!robot_model.initString(xml)) {
00218     ROS_FATAL("Could not initialize robot model");
00219     return -1;
00220   }
00221   if (!kdl_parser::treeFromString(xml, tree)) {
00222     ROS_ERROR("Could not initialize tree object");
00223     return false;
00224   }
00225   if (!tree.getChain(base_name_, tip_name_, kdl_chain_)) {
00226     ROS_ERROR("Could not initialize chain object");
00227     return false;
00228   }
00229   if (!readJoints(robot_model)) {
00230     ROS_FATAL("Could not read information about the joints");
00231     return false;
00232   }
00233   return true;
00234 }
00235 
00236 bool ReemKinematicsPlugin::readJoints(urdf::Model &robot_model)
00237 {
00238   dimension_ = 0;
00239   // get joint maxs and mins
00240   boost::shared_ptr<const urdf::Link> link = robot_model.getLink(tip_name_);
00241   boost::shared_ptr<const urdf::Joint> joint;
00242   while (link && link->name != base_name_) {
00243     joint = robot_model.getJoint(link->parent_joint->name);
00244     if (!joint) {
00245       ROS_ERROR("Could not find joint: %s",link->parent_joint->name.c_str());
00246       return false;
00247     }
00248     if (joint->type != urdf::Joint::UNKNOWN && joint->type != urdf::Joint::FIXED) {
00249       ROS_INFO( "adding joint: [%s]", joint->name.c_str() );
00250       dimension_++;
00251     }
00252     link = robot_model.getLink(link->getParent()->name);
00253   }
00254   joint_min_.resize(dimension_);
00255   joint_max_.resize(dimension_);
00256   chain_info_.joint_names.resize(dimension_);
00257   chain_info_.limits.resize(dimension_);
00258   link = robot_model.getLink(tip_name_);
00259   if(link)
00260     chain_info_.link_names.push_back(tip_name_);
00261 
00262   unsigned int i = 0;
00263   while (link && i < dimension_) {
00264     joint = robot_model.getJoint(link->parent_joint->name);
00265     if (joint->type != urdf::Joint::UNKNOWN && joint->type != urdf::Joint::FIXED) {
00266       ROS_INFO( "getting bounds for joint: [%s]", joint->name.c_str() );
00267 
00268       float lower, upper;
00269       int hasLimits;
00270       if ( joint->type != urdf::Joint::CONTINUOUS ) {
00271         if(joint->safety) {
00272           lower = joint->safety->soft_lower_limit+BOUNDS_EPSILON; 
00273           upper = joint->safety->soft_upper_limit-BOUNDS_EPSILON;
00274         } else {
00275           lower = joint->limits->lower+BOUNDS_EPSILON;
00276           upper = joint->limits->upper-BOUNDS_EPSILON;
00277         }
00278         hasLimits = 1;
00279       } else {
00280         lower = -M_PI;
00281         upper = M_PI;
00282         hasLimits = 0;
00283       }
00284       int index = dimension_ - i -1;
00285 
00286       joint_min_.data[index] = lower;
00287       joint_max_.data[index] = upper;
00288       chain_info_.joint_names[index] = joint->name;
00289       chain_info_.limits[index].joint_name = joint->name;
00290       chain_info_.limits[index].has_position_limits = hasLimits;
00291       chain_info_.limits[index].min_position = lower;
00292       chain_info_.limits[index].max_position = upper;
00293       ++i;
00294     }
00295     link = robot_model.getLink(link->getParent()->name);
00296   }
00297   return true;
00298 }
00299 
00300 int ReemKinematicsPlugin::getJointIndex(const std::string &name)
00301 {
00302   for (unsigned int i=0; i < chain_info_.joint_names.size(); ++i) {
00303     if (chain_info_.joint_names[i] == name)
00304       return i;
00305   }
00306   return -1;
00307 }
00308 
00309 int ReemKinematicsPlugin::getKDLSegmentIndex(const std::string &name)
00310 {
00311   int i=0; 
00312   while (i < (int)kdl_chain_.getNrOfSegments()) {
00313     if (kdl_chain_.getSegment(i).getName() == name) {
00314       return i+1;
00315     }
00316     ++i;
00317   }
00318   return -1;
00319 }
00320 
00321 bool ReemKinematicsPlugin::getPositionIK(const geometry_msgs::Pose &ik_pose,
00322                                          const std::vector<double> &ik_seed_state,
00323                                          const std::vector<double> &posture,
00324                                          std::vector<double> &solution,
00325                                          int &error_code)
00326 {
00327   ros::WallTime n1 = ros::WallTime::now();
00328   if(!active_)
00329   {
00330     ROS_ERROR("kinematics not active");
00331     return false;
00332   }
00333 
00334   ROS_DEBUG_STREAM("getPositionIK1:Position request pose is " <<
00335                    ik_pose.position.x << " " <<
00336                    ik_pose.position.y << " " <<
00337                    ik_pose.position.z << " " <<
00338                    ik_pose.orientation.x << " " <<
00339                    ik_pose.orientation.y << " " <<
00340                    ik_pose.orientation.z << " " <<
00341                    ik_pose.orientation.w);
00342 
00343   KDL::Frame pose_desired;
00344   tf::PoseMsgToKDL(ik_pose, pose_desired);
00345   //Do the inverse kinematics
00346   KDL::JntArray jnt_pos_in(dimension_);
00347   KDL::JntArray jnt_pos_out(dimension_);
00348   KDL::JntArray jnt_posture(dimension_);
00349   for(unsigned int i=0; i < dimension_; ++i)
00350   {
00351     jnt_pos_in(i)  = ik_seed_state[i];
00352     jnt_posture(i) = posture[i];
00353   }
00354   ik_solver_->setPosture(jnt_posture);
00355   bool ik_valid = ik_solver_->solve(jnt_pos_in, pose_desired, jnt_pos_out);
00356   ROS_DEBUG_STREAM("IK success " << ik_valid << " time " << (ros::WallTime::now()-n1).toSec());
00357   solution.resize(dimension_);
00358   // NOTE: In the original implementation, the solution is not reported if IK failed. We do populate the best estimate
00359   for(unsigned int i=0; i < dimension_; ++i)
00360   {
00361     solution[i] = jnt_pos_out(i);
00362   }
00363   if(ik_valid)
00364   {
00365     error_code = kinematics::SUCCESS;
00366     return true;
00367   }
00368   else
00369   {
00370     ROS_DEBUG("An IK solution could not be found");
00371     error_code = kinematics::NO_IK_SOLUTION;
00372     return false;
00373   }
00374 }
00375 
00376 bool ReemKinematicsPlugin::getPositionIK(const geometry_msgs::Pose &ik_pose,
00377                                          const std::vector<double> &ik_seed_state,
00378                                          std::vector<double> &solution,
00379                                          int &error_code)
00380 {
00381   return getPositionIK(ik_pose,
00382                        ik_seed_state,
00383                        default_posture_,
00384                        solution,
00385                        error_code);
00386 }
00387 
00388 bool ReemKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose &ik_pose,
00389                                               const std::vector<double> &ik_seed_state,
00390                                               const double &timeout,
00391                                               std::vector<double> &solution,
00392                                               int &error_code)
00393 {
00394   ros::WallTime n1 = ros::WallTime::now();
00395   if(!active_)
00396   {
00397     ROS_ERROR("kinematics not active");
00398     error_code = kinematics::INACTIVE;
00399     return false;
00400   }
00401   KDL::Frame pose_desired;
00402   tf::PoseMsgToKDL(ik_pose, pose_desired);
00403 
00404   ROS_DEBUG_STREAM("searchPositionIK1:Position request pose is " <<
00405                    ik_pose.position.x << " " <<
00406                    ik_pose.position.y << " " <<
00407                    ik_pose.position.z << " " <<
00408                    ik_pose.orientation.x << " " << 
00409                    ik_pose.orientation.y << " " << 
00410                    ik_pose.orientation.z << " " << 
00411                    ik_pose.orientation.w);
00412 
00413   //Do the IK
00414   KDL::JntArray jnt_pos_in;
00415   KDL::JntArray jnt_pos_out;
00416   jnt_pos_in.resize(dimension_);
00417   KDL::JntArray posture(dimension_);
00418   for(unsigned int i=0; i < dimension_; ++i)
00419   {
00420     jnt_pos_in(i) = ik_seed_state[i];
00421     posture(i)    = default_posture_[i];
00422   }
00423   for(int i=0; i < max_search_iterations_; ++i)
00424   {
00425     for(unsigned int j=0; j < dimension_; ++j)
00426     { 
00427       ROS_DEBUG_STREAM("seed state " << j << " " << jnt_pos_in(j));
00428     }
00429     ik_solver_->setPosture(posture);
00430     bool ik_valid = ik_solver_->solve(jnt_pos_in, pose_desired, jnt_pos_out);
00431     ROS_DEBUG_STREAM("IK success " << ik_valid << " time " << (ros::WallTime::now()-n1).toSec());
00432     if(ik_valid) {
00433       solution.resize(dimension_);
00434       for(unsigned int j=0; j < dimension_; ++j) {
00435         solution[j] = jnt_pos_out(j);
00436       }
00437       error_code = kinematics::SUCCESS;
00438       ROS_DEBUG_STREAM("Solved after " << i+1 << " iterations");
00439       return true;
00440     }      
00441     jnt_pos_in = getRandomConfiguration();
00442   }
00443   ROS_DEBUG("An IK solution could not be found");   
00444   error_code = kinematics::NO_IK_SOLUTION;
00445   return false;
00446 }
00447 
00448 bool ReemKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose &ik_pose,
00449                                             const std::vector<double> &ik_seed_state,
00450                                             const double &timeout,
00451                                             const unsigned int& redundancy,
00452                                             const double &consistency_limit,
00453                                             std::vector<double> &solution,
00454                                             int &error_code)
00455 {
00456   ros::WallTime n1 = ros::WallTime::now();
00457   if(!active_)
00458   {
00459     ROS_ERROR("kinematics not active");
00460     error_code = kinematics::INACTIVE;
00461     return false;
00462   }
00463   KDL::Frame pose_desired;
00464   tf::PoseMsgToKDL(ik_pose, pose_desired);
00465 
00466   ROS_DEBUG_STREAM("searchPositionIK1:Position request pose is " <<
00467                    ik_pose.position.x << " " <<
00468                    ik_pose.position.y << " " <<
00469                    ik_pose.position.z << " " <<
00470                    ik_pose.orientation.x << " " <<
00471                    ik_pose.orientation.y << " " <<
00472                    ik_pose.orientation.z << " " <<
00473                    ik_pose.orientation.w);
00474 
00475   //Do the IK
00476   KDL::JntArray jnt_pos_in;
00477   KDL::JntArray jnt_pos_out;
00478   KDL::JntArray jnt_seed_state;
00479   jnt_pos_in.resize(dimension_);
00480   KDL::JntArray posture(dimension_);
00481   for(unsigned int i=0; i < dimension_; ++i)
00482   {
00483     jnt_seed_state(i) = ik_seed_state[i];
00484     posture(i)        = default_posture_[i];
00485   }
00486   jnt_pos_in = jnt_seed_state;
00487   for(int i=0; i < max_search_iterations_; ++i)
00488   {
00489     for(unsigned int j=0; j < dimension_; ++j)
00490     {
00491       ROS_DEBUG_STREAM("seed state " << j << " " << jnt_pos_in(j));
00492     }
00493     ik_solver_->setPosture(posture);
00494     int ik_valid = ik_solver_->solve(jnt_pos_in, pose_desired, jnt_pos_out);
00495     ROS_DEBUG_STREAM("IK success " << ik_valid << " time " << (ros::WallTime::now()-n1).toSec());
00496     if(ik_valid >= 0 && checkConsistency(jnt_seed_state, redundancy, consistency_limit, jnt_pos_out)) {
00497       solution.resize(dimension_);
00498       for(unsigned int j=0; j < dimension_; j++) {
00499         solution[j] = jnt_pos_out(j);
00500       }
00501       error_code = kinematics::SUCCESS;
00502       ROS_DEBUG_STREAM("Solved after " << i+1 << " iterations");
00503       return true;
00504     }
00505     jnt_pos_in = getRandomConfiguration(jnt_seed_state, redundancy, consistency_limit);
00506   }
00507   ROS_DEBUG("An IK solution could not be found");
00508   error_code = kinematics::NO_IK_SOLUTION;
00509   return false;
00510 }
00511 
00512 bool ReemKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose &ik_pose,
00513                                               const std::vector<double> &ik_seed_state,
00514                                               const double &timeout,
00515                                               std::vector<double> &solution,
00516                                               const boost::function<void(const geometry_msgs::Pose &ik_pose,const std::vector<double> &ik_solution,int &error_code)> &desired_pose_callback,
00517                                               const boost::function<void(const geometry_msgs::Pose &ik_pose,const std::vector<double> &ik_solution,int &error_code)> &solution_callback,
00518                                               int &error_code)  
00519 {
00520   if(!active_)
00521   {
00522     ROS_ERROR("kinematics not active");
00523     error_code = kinematics::INACTIVE;
00524     return false;
00525   }
00526   KDL::Frame pose_desired;
00527   tf::PoseMsgToKDL(ik_pose, pose_desired);
00528 
00529   ROS_DEBUG_STREAM("searchPositionIK2: Position request pose is " <<
00530                    ik_pose.position.x << " " <<
00531                    ik_pose.position.y << " " <<
00532                    ik_pose.position.z << " " <<
00533                    ik_pose.orientation.x << " " << 
00534                    ik_pose.orientation.y << " " << 
00535                    ik_pose.orientation.z << " " << 
00536                    ik_pose.orientation.w);
00537 
00538   //Do the IK
00539   KDL::JntArray jnt_pos_in;
00540   KDL::JntArray jnt_pos_out;
00541   jnt_pos_in.resize(dimension_);
00542   KDL::JntArray posture(dimension_);
00543   for(unsigned int i=0; i < dimension_; ++i)
00544   {
00545     jnt_pos_in(i) = ik_seed_state[i];
00546     posture(i)    = default_posture_[i];
00547   }
00548 
00549   if(!desired_pose_callback.empty())
00550     desired_pose_callback(ik_pose,ik_seed_state,error_code);
00551 
00552   if(error_code < 0)
00553   {
00554     ROS_DEBUG("Could not find inverse kinematics for desired end-effector pose since the pose may be in collision");
00555     return false;
00556   }
00557   for(int i=0; i < max_search_iterations_; ++i)
00558   {
00559     ik_solver_->setPosture(posture);
00560     bool ik_valid = ik_solver_->solve(jnt_pos_in, pose_desired, jnt_pos_out);
00561     jnt_pos_in = getRandomConfiguration();
00562     if(!ik_valid)
00563       continue;
00564     std::vector<double> solution_local;
00565     solution_local.resize(dimension_);
00566     for(unsigned int j=0; j < dimension_; ++j)
00567       solution_local[j] = jnt_pos_out(j);
00568     solution_callback(ik_pose,solution_local,error_code);
00569     if(error_code == kinematics::SUCCESS)
00570     {
00571       solution = solution_local;
00572       ROS_DEBUG_STREAM("Solved after " << i+1 << " iterations");
00573       return true;
00574     }
00575   }
00576   ROS_DEBUG("An IK that satisifes the constraints and is collision free could not be found");   
00577   error_code = kinematics::NO_IK_SOLUTION;
00578   return false;
00579 }
00580 
00581 bool ReemKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose &ik_pose,
00582                                             const std::vector<double> &ik_seed_state,
00583                                             const double &timeout,
00584                                             const unsigned int& redundancy,
00585                                             const double& consistency_limit,
00586                                             std::vector<double> &solution,
00587                                             const boost::function<void(const geometry_msgs::Pose &ik_pose,const std::vector<double> &ik_solution,int &error_code)> &desired_pose_callback,
00588                                             const boost::function<void(const geometry_msgs::Pose &ik_pose,const std::vector<double> &ik_solution,int &error_code)> &solution_callback,
00589                                             int &error_code)
00590 {
00591   if(!active_)
00592   {
00593     ROS_ERROR("kinematics not active");
00594     error_code = kinematics::INACTIVE;
00595     return false;
00596   }
00597   KDL::Frame pose_desired;
00598   tf::PoseMsgToKDL(ik_pose, pose_desired);
00599 
00600   ROS_DEBUG_STREAM("searchPositionIK2: Position request pose is " <<
00601                    ik_pose.position.x << " " <<
00602                    ik_pose.position.y << " " <<
00603                    ik_pose.position.z << " " <<
00604                    ik_pose.orientation.x << " " <<
00605                    ik_pose.orientation.y << " " <<
00606                    ik_pose.orientation.z << " " <<
00607                    ik_pose.orientation.w);
00608 
00609   //Do the IK
00610   //Do the IK
00611   KDL::JntArray jnt_pos_in;
00612   KDL::JntArray jnt_pos_out;
00613   KDL::JntArray jnt_seed_state;
00614   jnt_pos_in.resize(dimension_);
00615   KDL::JntArray posture(dimension_);
00616   for(unsigned int i=0; i < dimension_; ++i)
00617   {
00618     jnt_seed_state(i) = ik_seed_state[i];
00619     posture(i)        = default_posture_[i];
00620   }
00621   jnt_pos_in = jnt_seed_state;
00622 
00623   if(!desired_pose_callback.empty())
00624     desired_pose_callback(ik_pose,ik_seed_state,error_code);
00625 
00626   if(error_code < 0)
00627   {
00628     ROS_DEBUG("Could not find inverse kinematics for desired end-effector pose since the pose may be in collision");
00629     return false;
00630   }
00631   for(int i=0; i < max_search_iterations_; ++i)
00632   {
00633     ik_solver_->setPosture(posture);
00634     int ik_valid = ik_solver_->solve(jnt_pos_in,pose_desired,jnt_pos_out);
00635     jnt_pos_in = getRandomConfiguration(jnt_seed_state, redundancy, consistency_limit);
00636     if(ik_valid < 0 || !checkConsistency(jnt_seed_state, redundancy, consistency_limit, jnt_pos_out))
00637       continue;
00638     std::vector<double> solution_local;
00639     solution_local.resize(dimension_);
00640     for(unsigned int j=0; j < dimension_; j++)
00641       solution_local[j] = jnt_pos_out(j);
00642     solution_callback(ik_pose,solution_local,error_code);
00643     if(error_code == kinematics::SUCCESS)
00644     {
00645       solution = solution_local;
00646       ROS_DEBUG_STREAM("Solved after " << i+1 << " iterations");
00647       return true;
00648     }
00649   }
00650   ROS_DEBUG("An IK that satisifes the constraints and is collision free could not be found");
00651   error_code = kinematics::NO_IK_SOLUTION;
00652   return false;
00653 }
00654 
00655 bool ReemKinematicsPlugin::getPositionFK(const std::vector<std::string> &link_names,
00656                                            const std::vector<double> &joint_angles,
00657                                            std::vector<geometry_msgs::Pose> &poses)
00658 {
00659   if(!active_)
00660   {
00661     ROS_ERROR("kinematics not active");
00662     return false;
00663   }
00664   
00665   KDL::Frame p_out;
00666   KDL::JntArray jnt_pos_in;
00667   geometry_msgs::PoseStamped pose;
00668   tf::Stamped<tf::Pose> tf_pose;
00669   
00670   jnt_pos_in.resize(dimension_);
00671   for(unsigned int i=0; i < dimension_; ++i)
00672   {
00673     jnt_pos_in(i) = joint_angles[i];
00674   }
00675   
00676   poses.resize(link_names.size());
00677   
00678   bool valid = true;
00679   for(unsigned int i=0; i < poses.size(); ++i)
00680   {
00681     if(fk_solver_->JntToCart(jnt_pos_in,p_out,getKDLSegmentIndex(link_names[i])) >=0)
00682     {
00683       tf::PoseKDLToMsg(p_out,poses[i]);
00684     }
00685     else
00686     {
00687       ROS_ERROR("Could not compute FK for %s",link_names[i].c_str());
00688       valid = false;
00689     }
00690   }
00691   return valid;
00692 }
00693 
00694 std::string ReemKinematicsPlugin::getBaseFrame()
00695 {
00696   if(!active_)
00697   {
00698     ROS_ERROR("kinematics not active");
00699     return std::string("");
00700   }
00701   return base_name_;
00702 }
00703 
00704 std::string ReemKinematicsPlugin::getToolFrame()
00705 {
00706   if(!active_ || chain_info_.link_names.empty())
00707   {
00708     ROS_ERROR("kinematics not active");
00709     return std::string("");
00710   }
00711   return chain_info_.link_names[0];
00712 }
00713 
00714 const std::vector<std::string>& ReemKinematicsPlugin::getJointNames() const
00715 {
00716   if(!active_)
00717   {
00718     ROS_ERROR("kinematics not active");
00719   }
00720   return chain_info_.joint_names;
00721 }
00722 
00723 const std::vector<std::string>& ReemKinematicsPlugin::getLinkNames() const
00724 {
00725   if(!active_)
00726   {
00727     ROS_ERROR("kinematics not active");
00728   }
00729   return chain_info_.link_names;
00730 }
00731 
00732 } // namespace


reem_kinematics_constraint_aware
Author(s): Adolfo Rodriguez Tsouroukdissian, Hilario Tome.
autogenerated on Thu Jan 2 2014 11:42:41