joint_state_group.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 * Software License Agreement (BSD License)
00003 *
00004 *  Copyright (c) 2008, Willow Garage, Inc.
00005 *  All rights reserved.
00006 *
00007 *  Redistribution and use in source and binary forms, with or without
00008 *  modification, are permitted provided that the following conditions
00009 *  are met:
00010 *
00011 *   * Redistributions of source code must retain the above copyright
00012 *     notice, this list of conditions and the following disclaimer.
00013 *   * Redistributions in binary form must reproduce the above
00014 *     copyright notice, this list of conditions and the following
00015 *     disclaimer in the documentation and/or other materials provided
00016 *     with the distribution.
00017 *   * Neither the name of the Willow Garage nor the names of its
00018 *     contributors may be used to endorse or promote products derived
00019 *     from this software without specific prior written permission.
00020 *
00021 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 *  POSSIBILITY OF SUCH DAMAGE.
00033 *********************************************************************/
00034 
00035 /* Author: Ioan Sucan, E. Gil Jones, Sachin Chitta */
00036 
00037 #include <moveit/robot_state/robot_state.h>
00038 #include <eigen_conversions/eigen_msg.h>
00039 #include <boost/bind.hpp>
00040 #include <boost/math/constants/constants.hpp>
00041 #include <algorithm>
00042 #include <Eigen/SVD>
00043 
00044 robot_state::JointStateGroup::JointStateGroup(RobotState *state,
00045                                               const robot_model::JointModelGroup *jmg) :
00046   kinematic_state_(state), joint_model_group_(jmg)
00047 {
00048   const std::vector<const robot_model::JointModel*>& joint_model_vector = jmg->getJointModels();
00049   for (std::size_t i = 0; i < joint_model_vector.size() ; ++i)
00050   {
00051     assert(kinematic_state_->hasJointState(joint_model_vector[i]->getName()));
00052     JointState* js = kinematic_state_->getJointState(joint_model_vector[i]->getName());
00053     joint_state_vector_.push_back(js);
00054     joint_state_map_[joint_model_vector[i]->getName()] = js;
00055   }
00056   const std::vector<const robot_model::LinkModel*>& link_model_vector = jmg->getUpdatedLinkModels();
00057   for (unsigned int i = 0; i < link_model_vector.size(); i++)
00058   {
00059     assert(kinematic_state_->hasLinkState(link_model_vector[i]->getName()));
00060     LinkState* ls = kinematic_state_->getLinkState(link_model_vector[i]->getName());
00061     updated_links_.push_back(ls);
00062   }
00063 
00064   const std::vector<const robot_model::JointModel*>& joint_root_vector = jmg->getJointRoots();
00065   for (std::size_t i = 0; i < joint_root_vector.size(); ++i)
00066   {
00067     JointState* js = kinematic_state_->getJointState(joint_root_vector[i]->getName());
00068     if (js)
00069       joint_roots_.push_back(js);
00070   }
00071 }
00072 
00073 robot_state::JointStateGroup::~JointStateGroup()
00074 {
00075 }
00076 
00077 random_numbers::RandomNumberGenerator& robot_state::JointStateGroup::getRandomNumberGenerator()
00078 {
00079   if (!rng_)
00080     rng_.reset(new random_numbers::RandomNumberGenerator());
00081   return *rng_;
00082 }
00083 
00084 bool robot_state::JointStateGroup::hasJointState(const std::string &joint) const
00085 {
00086   return joint_state_map_.find(joint) != joint_state_map_.end();
00087 }
00088 
00089 bool robot_state::JointStateGroup::setVariableValues(const std::vector<double> &joint_state_values)
00090 {
00091   if (joint_state_values.size() != getVariableCount())
00092   {
00093     logError("JointStateGroup: Incorrect variable count specified for array of joint values. Expected %u but got %u values in group '%s'",
00094              getVariableCount(), (int)joint_state_values.size(), joint_model_group_->getName().c_str() );
00095     return false;
00096   }
00097 
00098   unsigned int value_counter = 0;
00099   for(unsigned int i = 0; i < joint_state_vector_.size(); i++)
00100   {
00101     unsigned int dim = joint_state_vector_[i]->getVariableCount();
00102     if (dim != 0)
00103     {
00104       joint_state_vector_[i]->setVariableValues(&joint_state_values[value_counter]);
00105       value_counter += dim;
00106     }
00107   }
00108   updateLinkTransforms();
00109   return true;
00110 }
00111 
00112 bool robot_state::JointStateGroup::setVariableValues(const Eigen::VectorXd &joint_state_values)
00113 {
00114   std::vector<double> values(joint_state_values.rows());
00115   for (std::size_t i = 0; i < joint_state_values.rows(); i++)
00116     values[i] =  joint_state_values(i);
00117   setVariableValues(values);
00118 }
00119 
00120 void robot_state::JointStateGroup::setVariableValues(const std::map<std::string, double>& joint_state_map)
00121 {
00122   for(unsigned int i = 0; i < joint_state_vector_.size(); ++i)
00123     joint_state_vector_[i]->setVariableValues(joint_state_map);
00124   updateLinkTransforms();
00125 }
00126 
00127 void robot_state::JointStateGroup::setVariableValues(const sensor_msgs::JointState& js)
00128 {
00129   std::map<std::string, double> v;
00130   for (std::size_t i = 0 ; i < js.name.size() ; ++i)
00131     v[js.name[i]] = js.position[i];
00132   setVariableValues(v);
00133 }
00134 
00135 void robot_state::JointStateGroup::updateLinkTransforms()
00136 {
00137   for(unsigned int i = 0; i < updated_links_.size(); ++i)
00138     updated_links_[i]->computeTransform();
00139 }
00140 
00141 robot_state::JointStateGroup& robot_state::JointStateGroup::operator=(const JointStateGroup &other)
00142 {
00143   if (this != &other)
00144     copyFrom(other);
00145   return *this;
00146 }
00147 
00148 void robot_state::JointStateGroup::copyFrom(const JointStateGroup &other_jsg)
00149 {
00150   const std::vector<JointState*> &ojsv = other_jsg.getJointStateVector();
00151   for (std::size_t i = 0 ; i < ojsv.size() ; ++i)
00152     joint_state_vector_[i]->setVariableValues(ojsv[i]->getVariableValues());
00153   updateLinkTransforms();
00154 }
00155 
00156 void robot_state::JointStateGroup::setToDefaultValues()
00157 {
00158   std::map<std::string, double> default_joint_values;
00159   for (std::size_t i = 0  ; i < joint_state_vector_.size() ; ++i)
00160     joint_state_vector_[i]->getJointModel()->getVariableDefaultValues(default_joint_values);
00161   setVariableValues(default_joint_values);
00162 }
00163 
00164 bool robot_state::JointStateGroup::setToDefaultState(const std::string &name)
00165 {
00166   std::map<std::string, double> default_joint_values;
00167   if (!joint_model_group_->getVariableDefaultValues(name, default_joint_values))
00168     return false;
00169   setVariableValues(default_joint_values);
00170   return true;
00171 }
00172 
00173 void robot_state::JointStateGroup::setToRandomValues()
00174 {
00175   random_numbers::RandomNumberGenerator &rng = getRandomNumberGenerator();
00176   std::vector<double> random_joint_states;
00177   joint_model_group_->getVariableRandomValues(rng, random_joint_states);
00178   setVariableValues(random_joint_states);
00179 }
00180 
00181 void robot_state::JointStateGroup::setToRandomValuesNearBy(const std::vector<double> &near,
00182                                                            const std::map<robot_model::JointModel::JointType, double> &distance_map)
00183 {
00184   random_numbers::RandomNumberGenerator &rng = getRandomNumberGenerator();
00185   std::vector<double> variable_values;
00186   joint_model_group_->getVariableRandomValuesNearBy(rng, variable_values, near, distance_map);
00187   setVariableValues(variable_values);
00188 }
00189 
00190 void robot_state::JointStateGroup::setToRandomValuesNearBy(const std::vector<double> &near,
00191                                                            const std::vector<double> &distances)
00192 {
00193   random_numbers::RandomNumberGenerator &rng = getRandomNumberGenerator();
00194   std::vector<double> variable_values;
00195   joint_model_group_->getVariableRandomValuesNearBy(rng, variable_values, near, distances);
00196   setVariableValues(variable_values);
00197 }
00198 
00199 void robot_state::JointStateGroup::getVariableValues(std::vector<double>& joint_state_values) const
00200 {
00201   joint_state_values.clear();
00202   for(unsigned int i = 0; i < joint_state_vector_.size(); i++)
00203   {
00204     const std::vector<double> &jv = joint_state_vector_[i]->getVariableValues();
00205     joint_state_values.insert(joint_state_values.end(), jv.begin(), jv.end());
00206   }
00207 }
00208 
00209 void robot_state::JointStateGroup::getVariableValues(Eigen::VectorXd& joint_state_values) const
00210 {
00211   joint_state_values.resize(getVariableCount());
00212   unsigned int count = 0;
00213   for(unsigned int i = 0; i < joint_state_vector_.size(); i++)
00214   {
00215     const std::vector<double> &jv = joint_state_vector_[i]->getVariableValues();
00216     for (std::size_t j = 0; j < jv.size() ; ++j)
00217       joint_state_values(count++) = jv[j];
00218   }
00219 }
00220 
00221 bool robot_state::JointStateGroup::satisfiesBounds(double margin) const
00222 {
00223   for (std::size_t i = 0 ; i < joint_state_vector_.size() ; ++i)
00224     if (!joint_state_vector_[i]->satisfiesBounds(margin))
00225       return false;
00226   return true;
00227 }
00228 
00229 void robot_state::JointStateGroup::enforceBounds()
00230 {
00231   for (std::size_t i = 0 ; i < joint_state_vector_.size() ; ++i)
00232     joint_state_vector_[i]->enforceBounds();
00233   updateLinkTransforms();
00234 }
00235 
00236 double robot_state::JointStateGroup::infinityNormDistance(const JointStateGroup *other) const
00237 {
00238   if (joint_state_vector_.empty())
00239     return 0.0;
00240   double max_d = joint_state_vector_[0]->distance(other->joint_state_vector_[0]);
00241   for (std::size_t i = 1 ; i < joint_state_vector_.size() ; ++i)
00242   {
00243     double d = joint_state_vector_[i]->distance(other->joint_state_vector_[i]);
00244     if (d > max_d)
00245       max_d = d;
00246   }
00247   return max_d;
00248 }
00249 
00250 double robot_state::JointStateGroup::distance(const JointStateGroup *other) const
00251 {
00252   double d = 0.0;
00253   for (std::size_t i = 0 ; i < joint_state_vector_.size() ; ++i)
00254     d += joint_state_vector_[i]->distance(other->joint_state_vector_[i]) * joint_state_vector_[i]->getJointModel()->getDistanceFactor();
00255   return d;
00256 }
00257 
00258 void robot_state::JointStateGroup::interpolate(const JointStateGroup *to, const double t, JointStateGroup *dest) const
00259 {
00260   for (std::size_t i = 0 ; i < joint_state_vector_.size() ; ++i)
00261     joint_state_vector_[i]->interpolate(to->joint_state_vector_[i], t, dest->joint_state_vector_[i]);
00262   dest->updateLinkTransforms();
00263 }
00264 
00265 void robot_state::JointStateGroup::getVariableValues(std::map<std::string, double>& joint_state_values) const
00266 {
00267   joint_state_values.clear();
00268   for (std::size_t i = 0; i < joint_state_vector_.size(); ++i)
00269   {
00270     const std::vector<double> &jsv = joint_state_vector_[i]->getVariableValues();
00271     const std::vector<std::string> &jsn = joint_state_vector_[i]->getVariableNames();
00272     for (std::size_t j = 0 ; j < jsv.size(); ++j)
00273       joint_state_values[jsn[j]] = jsv[j];
00274   }
00275 }
00276 
00277 robot_state::JointState* robot_state::JointStateGroup::getJointState(const std::string &name) const
00278 {
00279   std::map<std::string, JointState*>::const_iterator it = joint_state_map_.find(name);
00280   if (it == joint_state_map_.end())
00281   {
00282     logError("Joint '%s' not found", name.c_str());
00283     return NULL;
00284   }
00285   else
00286     return it->second;
00287 }
00288 
00289 bool robot_state::JointStateGroup::setFromIK(const geometry_msgs::Pose &pose, unsigned int attempts, double timeout, const StateValidityCallbackFn &constraint, const kinematics::KinematicsQueryOptions &options)
00290 {
00291   const kinematics::KinematicsBaseConstPtr& solver = joint_model_group_->getSolverInstance();
00292   if (!solver)
00293   {
00294     logError("No kinematics solver instantiated for this group");
00295     return false;
00296   }
00297   return setFromIK(pose, solver->getTipFrame(), attempts, timeout, constraint, options);
00298 }
00299 
00300 bool robot_state::JointStateGroup::setFromIK(const geometry_msgs::Pose &pose, unsigned int attempts, double timeout, const kinematics::KinematicsQueryOptions &options)
00301 {
00302   const kinematics::KinematicsBaseConstPtr& solver = joint_model_group_->getSolverInstance();
00303   if (!solver)
00304   {
00305     logError("No kinematics solver instantiated for this group");
00306     return false;
00307   }
00308   static StateValidityCallbackFn constraint = StateValidityCallbackFn();
00309   return setFromIK(pose, solver->getTipFrame(), attempts, timeout, constraint, options);
00310 }
00311 
00312 bool robot_state::JointStateGroup::setFromIK(const geometry_msgs::Pose &pose, const std::string &tip, unsigned int attempts, double timeout, const StateValidityCallbackFn &constraint, const kinematics::KinematicsQueryOptions &options)
00313 {
00314   Eigen::Affine3d mat;
00315   tf::poseMsgToEigen(pose, mat);
00316   return setFromIK(mat, tip,  attempts, timeout, constraint, options);
00317 }
00318 
00319 bool robot_state::JointStateGroup::setFromIK(const Eigen::Affine3d &pose, unsigned int attempts, double timeout, const StateValidityCallbackFn &constraint, const kinematics::KinematicsQueryOptions &options)
00320 {
00321   const kinematics::KinematicsBaseConstPtr& solver = joint_model_group_->getSolverInstance();
00322   if (!solver)
00323   {
00324     logError("No kinematics solver instantiated for this group");
00325     return false;
00326   }
00327   static std::vector<double> consistency_limits;
00328   return setFromIK(pose, solver->getTipFrame(), consistency_limits, attempts, timeout, constraint, options);
00329 }
00330 
00331 bool robot_state::JointStateGroup::setFromIK(const Eigen::Affine3d &pose_in, const std::string &tip_in, unsigned int attempts, double timeout, const StateValidityCallbackFn &constraint, const kinematics::KinematicsQueryOptions &options)
00332 {
00333   static std::vector<double> consistency_limits;
00334   return setFromIK(pose_in, tip_in, consistency_limits, attempts, timeout, constraint, options);
00335 }
00336 
00337 bool robot_state::JointStateGroup::setFromIK(const Eigen::Affine3d &pose_in, const std::string &tip_in, unsigned int attempts, double timeout, const kinematics::KinematicsQueryOptions &options)
00338 {
00339   static std::vector<double> consistency_limits;
00340   static StateValidityCallbackFn constraint = StateValidityCallbackFn();
00341   return setFromIK(pose_in, tip_in, consistency_limits, attempts, timeout, constraint, options);
00342 }
00343 
00344 bool robot_state::JointStateGroup::setFromIK(const Eigen::Affine3d &pose_in, unsigned int attempts, double timeout, const kinematics::KinematicsQueryOptions &options)
00345 {
00346   static std::vector<double> consistency_limits;
00347   static StateValidityCallbackFn constraint = StateValidityCallbackFn();
00348   const kinematics::KinematicsBaseConstPtr& solver = joint_model_group_->getSolverInstance();
00349   if (!solver)
00350   {
00351     logError("No kinematics solver instantiated for this group");
00352     return false;
00353   }
00354   return setFromIK(pose_in, solver->getTipFrame(), consistency_limits, attempts, timeout, constraint, options);
00355 }
00356 
00357 bool robot_state::JointStateGroup::setFromIK(const Eigen::Affine3d &pose_in, const std::string &tip_in, const std::vector<double> &consistency_limits, unsigned int attempts, double timeout, const StateValidityCallbackFn &constraint, const kinematics::KinematicsQueryOptions &options)
00358 {
00359   const kinematics::KinematicsBaseConstPtr& solver = joint_model_group_->getSolverInstance();
00360   if (!solver)
00361   {
00362     logError("No kinematics solver instantiated for this group");
00363     return false;
00364   }
00365 
00366   Eigen::Affine3d pose = pose_in;
00367   std::string tip = tip_in;
00368 
00369   // bring the pose to the frame of the IK solver
00370   const std::string &ik_frame = solver->getBaseFrame();
00371   if (ik_frame != joint_model_group_->getParentModel()->getModelFrame())
00372   {
00373     const LinkState *ls = kinematic_state_->getLinkState(ik_frame);
00374     if (!ls)
00375       return false;
00376     pose = ls->getGlobalLinkTransform().inverse() * pose;
00377   }
00378 
00379   // see if the tip frame can be transformed via fixed transforms to the frame known to the IK solver
00380   const std::string &tip_frame = solver->getTipFrame();
00381   if (tip != tip_frame)
00382   {
00383     if (kinematic_state_->hasAttachedBody(tip))
00384     {
00385       const AttachedBody *ab = kinematic_state_->getAttachedBody(tip);
00386       const EigenSTL::vector_Affine3d &ab_trans = ab->getFixedTransforms();
00387       if (ab_trans.size() != 1)
00388       {
00389         logError("Cannot use an attached body with multiple geometries as a reference frame.");
00390         return false;
00391       }
00392       tip = ab->getAttachedLinkName();
00393       pose = pose * ab_trans[0].inverse();
00394     }
00395     if (tip != tip_frame)
00396     {
00397       const robot_model::LinkModel *lm = joint_model_group_->getParentModel()->getLinkModel(tip);
00398       if (!lm)
00399         return false;
00400       const robot_model::LinkModel::AssociatedFixedTransformMap &fixed_links = lm->getAssociatedFixedTransforms();
00401       for (std::map<const robot_model::LinkModel*, Eigen::Affine3d>::const_iterator it = fixed_links.begin() ; it != fixed_links.end() ; ++it)
00402         if (it->first->getName() == tip_frame)
00403         {
00404           tip = tip_frame;
00405           pose = pose * it->second;
00406           break;
00407         }
00408     }
00409   }
00410 
00411   if (tip != tip_frame)
00412   {
00413     logError("Cannot compute IK for tip reference frame '%s'", tip.c_str());
00414     return false;
00415   }
00416 
00417   // if no timeout has been specified, use the default one
00418   if (timeout < std::numeric_limits<double>::epsilon())
00419     timeout = joint_model_group_->getDefaultIKTimeout();
00420 
00421   if (attempts == 0)
00422     attempts = joint_model_group_->getDefaultIKAttempts();
00423 
00424   const std::vector<unsigned int> &bij = joint_model_group_->getKinematicsSolverJointBijection();
00425   Eigen::Quaterniond quat(pose.rotation());
00426   Eigen::Vector3d point(pose.translation());
00427   geometry_msgs::Pose ik_query;
00428   ik_query.position.x = point.x();
00429   ik_query.position.y = point.y();
00430   ik_query.position.z = point.z();
00431   ik_query.orientation.x = quat.x();
00432   ik_query.orientation.y = quat.y();
00433   ik_query.orientation.z = quat.z();
00434   ik_query.orientation.w = quat.w();
00435 
00436   kinematics::KinematicsBase::IKCallbackFn ik_callback_fn;
00437   if (constraint)
00438     ik_callback_fn = boost::bind(&JointStateGroup::ikCallbackFnAdapter, this, constraint, _1, _2, _3);
00439 
00440   bool first_seed = true;
00441   std::vector<double> initial_values;
00442   getVariableValues(initial_values);
00443   for (unsigned int st = 0 ; st < attempts ; ++st)
00444   {
00445     std::vector<double> seed(bij.size());
00446 
00447     // the first seed is the initial state
00448     if (first_seed)
00449     {
00450       first_seed = false;
00451       for (std::size_t i = 0 ; i < bij.size() ; ++i)
00452         seed[bij[i]] = initial_values[i];
00453     }
00454     else
00455     {
00456       // sample a random seed
00457       random_numbers::RandomNumberGenerator &rng = getRandomNumberGenerator();
00458       std::vector<double> random_values;
00459       joint_model_group_->getVariableRandomValues(rng, random_values);
00460       for (std::size_t i = 0 ; i < bij.size() ; ++i)
00461         seed[bij[i]] = random_values[i];
00462 
00463       if (options.lock_redundant_joints)
00464       {
00465         std::vector<unsigned int> red_joints;
00466         solver->getRedundantJoints(red_joints);
00467         if (!red_joints.empty())
00468         {
00469           for(std::size_t i = 0 ; i < red_joints.size(); ++i)
00470           {
00471             seed[bij[red_joints[i]]] = initial_values[red_joints[i]];
00472           }
00473         }
00474       }
00475     }
00476 
00477     // compute the IK solution
00478     std::vector<double> ik_sol;
00479     moveit_msgs::MoveItErrorCodes error;
00480     if (ik_callback_fn ?
00481         solver->searchPositionIK(ik_query, seed, timeout, consistency_limits, ik_sol, ik_callback_fn, error, options) :
00482         solver->searchPositionIK(ik_query, seed, timeout, consistency_limits, ik_sol, error, options))
00483     {
00484       std::vector<double> solution(bij.size());
00485       for (std::size_t i = 0 ; i < bij.size() ; ++i)
00486         solution[i] = ik_sol[bij[i]];
00487       setVariableValues(solution);
00488       return true;
00489     }
00490   }
00491   return false;
00492 }
00493 
00494 bool robot_state::JointStateGroup::setFromIK(const EigenSTL::vector_Affine3d &poses_in,
00495                                              const std::vector<std::string> &tips_in,
00496                                              unsigned int attempts,
00497                                              double timeout,
00498                                              const StateValidityCallbackFn &constraint,
00499                                              const kinematics::KinematicsQueryOptions &options)
00500 {
00501   static const std::vector<std::vector<double> > consistency_limits;
00502   return setFromIK(poses_in, tips_in, consistency_limits, attempts, timeout, constraint, options);
00503 }
00504 
00505 bool robot_state::JointStateGroup::setFromIK(const EigenSTL::vector_Affine3d &poses_in,
00506                                              const std::vector<std::string> &tips_in,
00507                                              const std::vector<std::vector<double> > &consistency_limits,
00508                                              unsigned int attempts,
00509                                              double timeout,
00510                                              const StateValidityCallbackFn &constraint,
00511                                              const kinematics::KinematicsQueryOptions &options)
00512 {
00513   if (poses_in.size() == 1 && tips_in.size() == 1 && consistency_limits.size() <= 1)
00514   {
00515     if (consistency_limits.empty())
00516       return setFromIK(poses_in[0], tips_in[0], attempts, timeout, constraint, options);
00517     else
00518       return setFromIK(poses_in[0], tips_in[0], consistency_limits[0], attempts, timeout, constraint, options);
00519   }
00520 
00521   const std::vector<std::string>& sub_group_names = joint_model_group_->getSubgroupNames();
00522 
00523   if (poses_in.size() != sub_group_names.size())
00524   {
00525     logError("Number of poses must be the same as number of sub-groups");
00526     return false;
00527   }
00528 
00529   if (tips_in.size() != sub_group_names.size())
00530   {
00531     logError("Number of tip names must be the same as number of sub-groups");
00532     return false;
00533   }
00534 
00535   if (!consistency_limits.empty() && consistency_limits.size() != sub_group_names.size())
00536   {
00537     logError("Number of consistency limit vectors must be the same as number of sub-groups");
00538     return false;
00539   }
00540 
00541   if (!consistency_limits.empty())
00542   {
00543     for (std::size_t i = 0 ; i < consistency_limits.size() ; ++i)
00544     {
00545       if (consistency_limits[i].size() != joint_model_group_->getParentModel()->getJointModelGroup(sub_group_names[i])->getVariableCount())
00546       {
00547         logError("Number of joints in consistency_limits is %u but it should be should be %u", (unsigned int)i,
00548                  joint_model_group_->getParentModel()->getJointModelGroup(sub_group_names[i])->getVariableCount());
00549         return false;
00550       }
00551     }
00552   }
00553 
00554   std::vector<kinematics::KinematicsBaseConstPtr> solvers;
00555   for(std::size_t i = 0; i < poses_in.size() ; ++i)
00556   {
00557     kinematics::KinematicsBaseConstPtr solver = joint_model_group_->getParentModel()->getJointModelGroup(sub_group_names[i])->getSolverInstance();
00558     if (!solver)
00559     {
00560       logError("Could not find solver for %s", sub_group_names[i].c_str());
00561       return false;
00562     }
00563     solvers.push_back(solver);
00564   }
00565 
00566   EigenSTL::vector_Affine3d transformed_poses = poses_in;
00567   std::vector<std::string> tip_names = tips_in;
00568 
00569   for(std::size_t i = 0 ; i < poses_in.size() ; ++i)
00570   {
00571     Eigen::Affine3d pose = poses_in[i];
00572     std::string tip = tips_in[i];
00573 
00574     // bring the pose to the frame of the IK solver
00575     const std::string &ik_frame = solvers[i]->getBaseFrame();
00576     if (ik_frame != joint_model_group_->getParentModel()->getModelFrame())
00577     {
00578       const LinkState *ls = kinematic_state_->getLinkState(ik_frame);
00579       if (!ls)
00580         return false;
00581       pose = ls->getGlobalLinkTransform().inverse() * pose;
00582     }
00583 
00584     // see if the tip frame can be transformed via fixed transforms to the frame known to the IK solver
00585     const std::string &tip_frame = solvers[i]->getTipFrame();
00586     if (tip != tip_frame)
00587     {
00588       if (kinematic_state_->hasAttachedBody(tip))
00589       {
00590         const AttachedBody *ab = kinematic_state_->getAttachedBody(tip);
00591         const EigenSTL::vector_Affine3d &ab_trans = ab->getFixedTransforms();
00592         if (ab_trans.size() != 1)
00593         {
00594           logError("Cannot use an attached body with multiple geometries as a reference frame.");
00595           return false;
00596         }
00597         tip = ab->getAttachedLinkName();
00598         pose = pose * ab_trans[0].inverse();
00599       }
00600       if (tip != tip_frame)
00601       {
00602         const robot_model::LinkModel *lm = joint_model_group_->getParentModel()->getLinkModel(tip);
00603         if (!lm)
00604           return false;
00605         const robot_model::LinkModel::AssociatedFixedTransformMap &fixed_links = lm->getAssociatedFixedTransforms();
00606         for (std::map<const robot_model::LinkModel*, Eigen::Affine3d>::const_iterator it = fixed_links.begin() ; it != fixed_links.end() ; ++it)
00607           if (it->first->getName() == tip_frame)
00608           {
00609             tip = tip_frame;
00610             pose = pose * it->second;
00611             break;
00612           }
00613       }
00614     }
00615 
00616     if (tip != tip_frame)
00617     {
00618       logError("Cannot compute IK for tip reference frame '%s'", tip.c_str());
00619       return false;
00620     }
00621     transformed_poses[i] = pose;
00622     tip_names[i] = tip;
00623   }
00624 
00625   std::vector<geometry_msgs::Pose> ik_queries(poses_in.size());
00626   kinematics::KinematicsBase::IKCallbackFn ik_callback_fn;
00627   if (constraint)
00628     ik_callback_fn = boost::bind(&JointStateGroup::ikCallbackFnAdapter, this, constraint, _1, _2, _3);
00629 
00630   for(std::size_t i = 0; i < transformed_poses.size(); ++i)
00631   {
00632     Eigen::Quaterniond quat(transformed_poses[i].rotation());
00633     Eigen::Vector3d point(transformed_poses[i].translation());
00634     ik_queries[i].position.x = point.x();
00635     ik_queries[i].position.y = point.y();
00636     ik_queries[i].position.z = point.z();
00637     ik_queries[i].orientation.x = quat.x();
00638     ik_queries[i].orientation.y = quat.y();
00639     ik_queries[i].orientation.z = quat.z();
00640     ik_queries[i].orientation.w = quat.w();
00641   }
00642 
00643   if (attempts == 0)
00644     attempts = joint_model_group_->getDefaultIKAttempts();
00645 
00646   bool first_seed = true;
00647   for (unsigned int st = 0 ; st < attempts ; ++st)
00648   {
00649     bool found_solution = true;
00650     for(std::size_t sg = 0; sg < sub_group_names.size(); ++sg)
00651     {
00652       robot_state::JointStateGroup* joint_state_group = getRobotState()->getJointStateGroup(sub_group_names[sg]);
00653       const std::vector<unsigned int>& bij = joint_state_group->getJointModelGroup()->getKinematicsSolverJointBijection();
00654       std::vector<double> seed(bij.size());
00655        // the first seed is the initial state
00656       if (first_seed)
00657       {
00658         if(sg == sub_group_names.size()-1)
00659           first_seed = false;
00660         std::vector<double> initial_values;
00661         joint_state_group->getVariableValues(initial_values);
00662         for (std::size_t i = 0 ; i < bij.size() ; ++i)
00663           seed[bij[i]] = initial_values[i];
00664       }
00665       else
00666       {
00667         // sample a random seed
00668         random_numbers::RandomNumberGenerator &rng = getRandomNumberGenerator();
00669         std::vector<double> random_values;
00670         joint_state_group->getJointModelGroup()->getVariableRandomValues(rng, random_values);
00671         for (std::size_t i = 0 ; i < bij.size() ; ++i)
00672           seed[bij[i]] = random_values[i];
00673       }
00674 
00675       // compute the IK solution
00676       std::vector<double> ik_sol;
00677       moveit_msgs::MoveItErrorCodes error;
00678       if (!consistency_limits.empty() ?
00679          solvers[sg]->searchPositionIK(ik_queries[sg], seed, timeout < std::numeric_limits<double>::epsilon() ? joint_state_group->getDefaultIKTimeout() : timeout,
00680                                        consistency_limits[sg], ik_sol, error) :
00681          solvers[sg]->searchPositionIK(ik_queries[sg], seed,  timeout < std::numeric_limits<double>::epsilon() ? joint_state_group->getDefaultIKTimeout() : timeout,
00682                                        ik_sol, error))
00683       {
00684         std::vector<double> solution(bij.size());
00685         for (std::size_t i = 0 ; i < bij.size() ; ++i)
00686           solution[i] = ik_sol[bij[i]];
00687         joint_state_group->setVariableValues(solution);
00688       }
00689       else
00690       {
00691         found_solution = false;
00692         break;
00693       }
00694       if(found_solution && sg == (sub_group_names.size() - 1))
00695       {
00696         std::vector<double> full_solution;
00697         getVariableValues(full_solution);
00698         if(constraint ? constraint(this, full_solution) : true)
00699         {
00700           logDebug("Found IK solution");
00701           return true;
00702         }
00703       }
00704       logDebug("IK attempt: %d of %d", st, attempts);
00705     }
00706   }
00707   return false;
00708 }
00709 
00710 void robot_state::JointStateGroup::computeJointVelocity(Eigen::VectorXd &qdot, const Eigen::VectorXd &twist, const std::string &tip, const SecondaryTaskFn &st) const
00711 {
00712   //Get the Jacobian of the group at the current configuration
00713   Eigen::MatrixXd J(6, getVariableCount());
00714   Eigen::Vector3d reference_point(0.0, 0.0, 0.0);
00715   getJacobian(tip, reference_point, J);
00716 
00717   //Rotate the jacobian to the end-effector frame
00718   Eigen::Affine3d eMb = getRobotState()->getLinkState(tip)->getGlobalLinkTransform().inverse();
00719   Eigen::MatrixXd eWb = Eigen::ArrayXXd::Zero(6, 6);
00720   eWb.block(0, 0, 3, 3) = eMb.matrix().block(0, 0, 3, 3);
00721   eWb.block(3, 3, 3, 3) = eMb.matrix().block(0, 0, 3, 3);
00722   J = eWb * J;
00723 
00724   //Do the Jacobian moore-penrose pseudo-inverse
00725   Eigen::JacobiSVD<Eigen::MatrixXd> svdOfJ(J, Eigen::ComputeThinU | Eigen::ComputeThinV);
00726   const Eigen::MatrixXd U = svdOfJ.matrixU();
00727   const Eigen::MatrixXd V = svdOfJ.matrixV();
00728   const Eigen::VectorXd S = svdOfJ.singularValues();
00729 
00730   Eigen::VectorXd Sinv = S;
00731   static const double pinvtoler = std::numeric_limits<float>::epsilon();
00732   double maxsv = 0.0 ;
00733   for (std::size_t i = 0; i < S.rows(); ++i)
00734     if (fabs(S(i)) > maxsv) maxsv = fabs(S(i));
00735   for (std::size_t i = 0; i < S.rows(); ++i)
00736   {
00737     //Those singular values smaller than a percentage of the maximum singular value are removed
00738     if ( fabs(S(i)) > maxsv * pinvtoler )
00739       Sinv(i) = 1.0 / S(i);
00740     else Sinv(i) = 0.0;
00741   }
00742   Eigen::MatrixXd Jinv = ( V * Sinv.asDiagonal() * U.transpose() );
00743 
00744   //Compute joint velocity
00745   qdot = Jinv * twist;
00746 
00747   //Project the secondary task
00748   if (st)
00749   {
00750     Eigen::VectorXd cost_vector = Eigen::VectorXd::Zero(qdot.rows());
00751     st(this, cost_vector);
00752     qdot += (Eigen::MatrixXd::Identity(qdot.rows(), qdot.rows()) - Jinv * J) * cost_vector;
00753   }
00754 }
00755 
00756 bool robot_state::JointStateGroup::setFromDiffIK(const Eigen::VectorXd &twist, const std::string &tip, double dt, const StateValidityCallbackFn &constraint, const SecondaryTaskFn &st)
00757 {
00758   Eigen::VectorXd qdot;
00759   computeJointVelocity(qdot, twist, tip, st);
00760   return integrateJointVelocity(qdot, dt, constraint);
00761 }
00762 
00763 bool robot_state::JointStateGroup::setFromDiffIK(const geometry_msgs::Twist &twist, const std::string &tip, double dt, const StateValidityCallbackFn &constraint, const SecondaryTaskFn &st)
00764 {
00765   Eigen::Matrix<double, 6, 1> t;
00766   tf::twistMsgToEigen(twist, t);
00767   return setFromDiffIK(t, tip, dt, constraint, st);
00768 }
00769 
00770 bool robot_state::JointStateGroup::integrateJointVelocity(const Eigen::VectorXd &qdot, double dt, const StateValidityCallbackFn &constraint)
00771 {
00772   Eigen::VectorXd q(getVariableCount());
00773   getVariableValues(q);
00774   q = q + dt * qdot;
00775   setVariableValues(q);
00776   enforceBounds();
00777 
00778   if (constraint)
00779   {
00780     std::vector<double> values;
00781     getVariableValues(values);
00782     return constraint(this, values);
00783   }
00784   else
00785     return true;
00786 }
00787 
00788 bool robot_state::JointStateGroup::avoidJointLimitsSecondaryTask(const robot_state::JointStateGroup *joint_state_group, Eigen::VectorXd &stvector,
00789                                                                  double activation_threshold, double gain) const
00790 {
00791   //Get current joint values (q)
00792   Eigen::VectorXd q;
00793   joint_state_group->getVariableValues(q);
00794 
00795   //Get joint lower and upper limits (qmin and qmax)
00796   const std::vector<moveit_msgs::JointLimits> &qlimits = joint_state_group->getJointModelGroup()->getVariableLimits();
00797   Eigen::VectorXd qmin(qlimits.size());
00798   Eigen::VectorXd qmax(qlimits.size());
00799   Eigen::VectorXd qrange(qlimits.size());
00800   stvector.resize(qlimits.size());
00801   stvector = Eigen::ArrayXd::Zero(qlimits.size());
00802 
00803   for (std::size_t i = 0; i < qlimits.size(); ++i)
00804   {
00805     qmin(i) = qlimits[i].min_position;
00806     qmax(i) = qlimits[i].max_position;
00807     qrange(i) = qmax(i) - qmin(i);
00808 
00809     //Fill in stvector with the gradient of a joint limit avoidance cost function
00810     const std::vector<const robot_model::JointModel*> joint_models = joint_state_group->getJointModelGroup()->getJointModels();
00811     if (qrange(i) == 0)
00812     {
00813       //If the joint range is zero do not compute the cost
00814       stvector(i) = 0;
00815     }
00816     else if (joint_models[i]->getType() == robot_model::JointModel::REVOLUTE)
00817     {
00818       //If the joint is continuous do not compute the cost
00819       const robot_model::RevoluteJointModel *rjoint = static_cast<const robot_model::RevoluteJointModel*>(joint_models[i]);
00820       if (rjoint->isContinuous())
00821         stvector(i) = 0;
00822     }
00823     else
00824     {
00825       if (q(i) > (qmax(i) - qrange(i) * activation_threshold))
00826       {
00827         stvector(i) = -gain * (q(i) - (qmax(i) - qrange(i) * activation_threshold)) / qrange(i);
00828       }
00829       else if (q(i) < (qmin(i) + qrange(i) * activation_threshold))
00830       {
00831         stvector(i) = -gain * (q(i) - (qmin(i) + qrange(i) * activation_threshold)) / qrange(i);
00832       }
00833     }
00834   }
00835 
00836   return true;
00837 }
00838 
00839 double robot_state::JointStateGroup::computeCartesianPath(std::vector<RobotStatePtr> &traj, const std::string &link_name, const Eigen::Vector3d &direction, bool global_reference_frame,
00840                                                           double distance, double max_step, double jump_threshold, const StateValidityCallbackFn &validCallback, const kinematics::KinematicsQueryOptions &options)
00841 {
00842   const LinkState *link_state = kinematic_state_->getLinkState(link_name);
00843   if (!link_state)
00844     return 0.0;
00845 
00846   //this is the Cartesian pose we start from, and have to move in the direction indicated
00847   const Eigen::Affine3d &start_pose = link_state->getGlobalLinkTransform();
00848 
00849   //the direction can be in the local reference frame (in which case we rotate it)
00850   const Eigen::Vector3d &rotated_direction = global_reference_frame ? direction : start_pose.rotation() * direction;
00851 
00852   //The target pose is built by applying a translation to the start pose for the desired direction and distance
00853   Eigen::Affine3d target_pose = start_pose;
00854   target_pose.translation() += rotated_direction * distance;
00855 
00856   //call computeCartesianPath for the computed target pose in the global reference frame
00857   return (distance * computeCartesianPath(traj, link_name, target_pose, true, max_step, jump_threshold, validCallback, options));
00858 }
00859 
00860 double robot_state::JointStateGroup::computeCartesianPath(std::vector<RobotStatePtr> &traj, const std::string &link_name, const Eigen::Affine3d &target, bool global_reference_frame,
00861                                                           double max_step, double jump_threshold, const StateValidityCallbackFn &validCallback, const kinematics::KinematicsQueryOptions &options)
00862 {
00863   const LinkState *link_state = kinematic_state_->getLinkState(link_name);
00864   if (!link_state)
00865     return 0.0;
00866 
00867   const std::vector<const robot_model::JointModel*> &jnt = joint_model_group_->getJointModels();
00868 
00869   // make sure that continuous joints wrap, but remember how much we wrapped them
00870   std::map<std::string, double> upd_continuous_joints;
00871   for (std::size_t i = 0 ; i < jnt.size() ; ++i)
00872     if (jnt[i]->getType() == robot_model::JointModel::REVOLUTE)
00873     {
00874       if (static_cast<const robot_model::RevoluteJointModel*>(jnt[i])->isContinuous())
00875       {
00876         double initial = joint_state_vector_[i]->getVariableValues()[0];
00877         joint_state_vector_[i]->enforceBounds();
00878         double after = joint_state_vector_[i]->getVariableValues()[0];
00879         if (fabs(initial - after) > std::numeric_limits<double>::epsilon())
00880           upd_continuous_joints[joint_state_vector_[i]->getName()] = initial - after;
00881       }
00882     }
00883 
00884   // this is the Cartesian pose we start from, and we move in the direction indicated
00885   Eigen::Affine3d start_pose = link_state->getGlobalLinkTransform();
00886 
00887   // the target can be in the local reference frame (in which case we rotate it)
00888   Eigen::Affine3d rotated_target = global_reference_frame ? target : start_pose * target;
00889 
00890   bool test_joint_space_jump = jump_threshold > 0.0;
00891 
00892   // decide how many steps we will need for this trajectory
00893   double distance = (rotated_target.translation() - start_pose.translation()).norm();
00894   unsigned int steps = (test_joint_space_jump ? 5 : 1) + (unsigned int)floor(distance / max_step);
00895 
00896   traj.clear();
00897   traj.push_back(RobotStatePtr(new RobotState(*kinematic_state_)));
00898 
00899   std::vector<std::vector<double> > previous_values(joint_state_vector_.size());
00900   std::vector<double> dist_vector;
00901   double total_dist = 0.0;
00902 
00903   if (test_joint_space_jump) // the joint values we start with
00904     for (std::size_t k = 0 ; k < joint_state_vector_.size() ; ++k)
00905       previous_values[k] = joint_state_vector_[k]->getVariableValues();
00906 
00907   double last_valid_percentage = 0.0;
00908   Eigen::Quaterniond start_quaternion(start_pose.rotation());
00909   Eigen::Quaterniond target_quaternion(rotated_target.rotation());
00910   for (unsigned int i = 1; i <= steps ; ++i)
00911   {
00912     double percentage = (double)i / (double)steps;
00913 
00914     Eigen::Affine3d pose(start_quaternion.slerp(percentage, target_quaternion));
00915     pose.translation() = percentage * rotated_target.translation() + (1 - percentage) * start_pose.translation();
00916 
00917     if (setFromIK(pose, link_name, 1, 0.0, validCallback, options))
00918     {
00919       traj.push_back(RobotStatePtr(new RobotState(*kinematic_state_)));
00920 
00921       // compute the distance to the previous point (infinity norm)
00922       if (test_joint_space_jump)
00923       {
00924         double dist_prev_point = 0.0;
00925         for (std::size_t k = 0 ; k < joint_state_vector_.size() ; ++k)
00926         {
00927           double d_k = jnt[k]->distance(joint_state_vector_[k]->getVariableValues(), previous_values[k]);
00928           if (dist_prev_point < 0.0 || dist_prev_point < d_k)
00929             dist_prev_point = d_k;
00930           previous_values[k] = joint_state_vector_[k]->getVariableValues();
00931         }
00932         dist_vector.push_back(dist_prev_point);
00933         total_dist += dist_prev_point;
00934       }
00935     }
00936     else
00937       break;
00938     last_valid_percentage = percentage;
00939   }
00940 
00941   if (test_joint_space_jump)
00942   {
00943     // compute the average distance between the states we looked at
00944     double thres = jump_threshold * (total_dist / (double)dist_vector.size());
00945     for (std::size_t i = 0 ; i < dist_vector.size() ; ++i)
00946       if (dist_vector[i] > thres)
00947       {
00948         logDebug("Truncating Cartesian path due to detected jump in joint-space distance");
00949         last_valid_percentage = (double)i / (double)steps;
00950         traj.resize(i);
00951         break;
00952       }
00953   }
00954 
00955   return last_valid_percentage;
00956 }
00957 
00958 double robot_state::JointStateGroup::computeCartesianPath(std::vector<RobotStatePtr> &traj, const std::string &link_name, const EigenSTL::vector_Affine3d &waypoints,
00959                                                           bool global_reference_frame, double max_step, double jump_threshold, const StateValidityCallbackFn &validCallback, const kinematics::KinematicsQueryOptions &options)
00960 {
00961   double percentage_solved = 0.0;
00962   for (std::size_t i = 0; i < waypoints.size(); ++i)
00963   {
00964     std::vector<RobotStatePtr> waypoint_traj;
00965     double wp_percentage_solved = computeCartesianPath(waypoint_traj, link_name, waypoints[i], global_reference_frame, max_step, jump_threshold, validCallback);
00966     if (fabs(wp_percentage_solved - 1.0) < std::numeric_limits<double>::epsilon())
00967     {
00968       percentage_solved = (double)(i + 1) / (double)waypoints.size();
00969       traj.insert(traj.end(), waypoint_traj.begin(), waypoint_traj.end());
00970     }
00971     else
00972     {
00973       percentage_solved += wp_percentage_solved / (double)waypoints.size();
00974       traj.insert(traj.end(), waypoint_traj.begin(), waypoint_traj.end());
00975       break;
00976     }
00977   }
00978 
00979   return percentage_solved;
00980 }
00981 
00982 void robot_state::JointStateGroup::ikCallbackFnAdapter(const StateValidityCallbackFn &constraint,
00983                                                        const geometry_msgs::Pose &, const std::vector<double> &ik_sol, moveit_msgs::MoveItErrorCodes &error_code)
00984 {
00985   const std::vector<unsigned int> &bij = joint_model_group_->getKinematicsSolverJointBijection();
00986   std::vector<double> solution(bij.size());
00987   for (std::size_t i = 0 ; i < bij.size() ; ++i)
00988     solution[i] = ik_sol[bij[i]];
00989   if (constraint(this, solution))
00990     error_code.val = moveit_msgs::MoveItErrorCodes::SUCCESS;
00991   else
00992     error_code.val = moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION;
00993 }
00994 
00995 bool robot_state::JointStateGroup::getJacobian(const std::string &link_name,
00996                                                const Eigen::Vector3d &reference_point_position,
00997                                                Eigen::MatrixXd& jacobian,
00998                                                bool use_quaternion_representation) const
00999 {
01000   if (!joint_model_group_->isChain())
01001   {
01002     logError("The group '%s' is not a chain. Cannot compute Jacobian", joint_model_group_->getName().c_str());
01003     return false;
01004   }
01005   if (!joint_model_group_->isLinkUpdated(link_name))
01006   {
01007     logError("Link name '%s' does not exist in the chain '%s' or is not a child for this chain", link_name.c_str(), joint_model_group_->getName().c_str());
01008     return false;
01009   }
01010 
01011   const robot_model::JointModel* root_joint_model = (joint_model_group_->getJointRoots())[0];
01012   const robot_state::LinkState *root_link_state = kinematic_state_->getLinkState(root_joint_model->getParentLinkModel()->getName());
01013   Eigen::Affine3d reference_transform = root_link_state ? root_link_state->getGlobalLinkTransform() : kinematic_state_->getRootTransform();
01014   reference_transform = reference_transform.inverse();
01015   int rows = use_quaternion_representation ? 7 : 6;
01016   int columns = joint_model_group_->getVariableCount();
01017   jacobian = Eigen::MatrixXd::Zero(rows, columns);
01018 
01019   const robot_state::LinkState *link_state = kinematic_state_->getLinkState(link_name);
01020   Eigen::Affine3d link_transform = reference_transform*link_state->getGlobalLinkTransform();
01021   Eigen::Vector3d point_transform = link_transform*reference_point_position;
01022 
01023   logDebug("Point from reference origin expressed in world coordinates: %f %f %f",
01024            point_transform.x(),
01025            point_transform.y(),
01026            point_transform.z());
01027 
01028   Eigen::Vector3d joint_axis;
01029   Eigen::Affine3d joint_transform;
01030 
01031   while (link_state)
01032   {
01033     /*
01034     logDebug("Link: %s, %f %f %f",link_state->getName().c_str(),
01035              link_state->getGlobalLinkTransform().translation().x(),
01036              link_state->getGlobalLinkTransform().translation().y(),
01037              link_state->getGlobalLinkTransform().translation().z());
01038     logDebug("Joint: %s",link_state->getParentJointState()->getName().c_str());
01039     */
01040 
01041     if (joint_model_group_->isActiveDOF(link_state->getParentJointState()->getJointModel()->getName()))
01042     {
01043         unsigned int joint_index = joint_model_group_->getJointVariablesIndexMap().find(link_state->getParentJointState()->getJointModel()->getName())->second;
01044         double multiplier = 1.0; // to account for mimic joints
01045         if (link_state->getParentJointState()->getJointModel()->getMimic())
01046         {
01047           joint_index = joint_model_group_->getJointVariablesIndexMap().find(link_state->getParentJointState()->getJointModel()->getMimic()->getName())->second;
01048           multiplier = link_state->getParentJointState()->getJointModel()->getMimicFactor();
01049         }
01050       if (link_state->getParentJointState()->getJointModel()->getType() == robot_model::JointModel::REVOLUTE)
01051       {
01052         joint_transform = reference_transform*link_state->getGlobalLinkTransform();
01053         joint_axis = joint_transform.rotation()*(static_cast<const robot_model::RevoluteJointModel*>(link_state->getParentJointState()->getJointModel()))->getAxis();
01054         jacobian.block<3,1>(0,joint_index) = jacobian.block<3,1>(0,joint_index) + multiplier * joint_axis.cross(point_transform - joint_transform.translation());
01055         jacobian.block<3,1>(3,joint_index) = jacobian.block<3,1>(3,joint_index) + multiplier * joint_axis;
01056       }
01057       if (link_state->getParentJointState()->getJointModel()->getType() == robot_model::JointModel::PRISMATIC)
01058       {
01059         joint_transform = reference_transform*link_state->getGlobalLinkTransform();
01060         joint_axis = joint_transform*(static_cast<const robot_model::PrismaticJointModel*>(link_state->getParentJointState()->getJointModel()))->getAxis();
01061         jacobian.block<3,1>(0,joint_index) = jacobian.block<3,1>(0,joint_index) + multiplier * joint_axis;
01062       }
01063       if (link_state->getParentJointState()->getJointModel()->getType() == robot_model::JointModel::PLANAR)
01064       {
01065         joint_transform = reference_transform*link_state->getGlobalLinkTransform();
01066         joint_axis = joint_transform*Eigen::Vector3d(1.0,0.0,0.0);
01067         jacobian.block<3,1>(0,joint_index) = jacobian.block<3,1>(0,joint_index) + multiplier * joint_axis;
01068         joint_axis = joint_transform*Eigen::Vector3d(0.0,1.0,0.0);
01069         jacobian.block<3,1>(0,joint_index+1) = jacobian.block<3,1>(0,joint_index+1) + multiplier * joint_axis;
01070         joint_axis = joint_transform*Eigen::Vector3d(0.0,0.0,1.0);
01071         jacobian.block<3,1>(0,joint_index+2) = jacobian.block<3,1>(0,joint_index+2) + multiplier * joint_axis.cross(point_transform - joint_transform.translation());
01072         jacobian.block<3,1>(3,joint_index+2) = jacobian.block<3,1>(3,joint_index+2) + multiplier * joint_axis;
01073       }
01074     }
01075     if (link_state->getParentJointState()->getJointModel() == root_joint_model)
01076       break;
01077     link_state = link_state->getParentLinkState();
01078   }
01079   if (use_quaternion_representation) { // Quaternion representation
01080     // From "Advanced Dynamics and Motion Simulation" by Paul Mitiguy
01081     // d/dt ( [w] ) = 1/2 * [ -x -y -z ]  * [ omega_1 ]
01082     //        [x]           [  w -z  y ]    [ omega_2 ]
01083     //        [y]           [  z  w -x ]    [ omega_3 ]
01084     //        [z]           [ -y  x  w ]
01085     Eigen::Quaterniond q(link_transform.rotation());
01086     double w = q.w(), x = q.x(), y = q.y(), z = q.z();
01087     Eigen::MatrixXd quaternion_update_matrix(4,3);
01088     quaternion_update_matrix << -x, -y, -z,
01089                                  w, -z,  y,
01090                                  z,  w, -x,
01091                                 -y,  x,  w;
01092     jacobian.block(3,0,4,columns) = 0.5*quaternion_update_matrix*jacobian.block(3,0, 3, columns);
01093   }
01094   return true;
01095 }
01096 
01097 std::pair<double,int> robot_state::JointStateGroup::getMinDistanceToBounds() const
01098 {
01099   double distance = std::numeric_limits<double>::max();
01100   int index = -1;
01101   for(std::size_t i=0; i < joint_state_vector_.size(); ++i)
01102   {
01103     if(joint_state_vector_[i]->getType() == robot_model::JointModel::REVOLUTE)
01104     {
01105       const robot_model::RevoluteJointModel* revolute_model = dynamic_cast<const robot_model::RevoluteJointModel*> (joint_state_vector_[i]->getJointModel());
01106       if(revolute_model->isContinuous())
01107         continue;
01108     }
01109     if(joint_state_vector_[i]->getType() == robot_model::JointModel::PLANAR)
01110     {
01111       const std::vector<std::pair<double, double> >& planar_bounds = joint_state_vector_[i]->getVariableBounds();
01112       if(planar_bounds[0].first == -std::numeric_limits<double>::max() || planar_bounds[0].second == std::numeric_limits<double>::max() ||
01113          planar_bounds[1].first == -std::numeric_limits<double>::max() || planar_bounds[1].second == std::numeric_limits<double>::max() ||
01114          planar_bounds[2].first == -boost::math::constants::pi<double>() || planar_bounds[2].second == boost::math::constants::pi<double>())
01115         continue;
01116     }
01117     if(joint_state_vector_[i]->getType() == robot_model::JointModel::FLOATING)
01118     {
01119       //Joint limits are not well-defined for floating joints
01120       continue;
01121     }
01122 
01123     const std::vector<double>& joint_values = joint_state_vector_[i]->getVariableValues();
01124     const std::vector<std::pair<double, double> >& bounds = joint_state_vector_[i]->getVariableBounds();
01125     std::vector<double> lower_bounds, upper_bounds;
01126     for(std::size_t j=0; j < bounds.size(); ++j)
01127     {
01128       lower_bounds.push_back(bounds[j].first);
01129       upper_bounds.push_back(bounds[j].second);
01130     }
01131     double new_distance = joint_state_vector_[i]->getJointModel()->distance(joint_values, lower_bounds);
01132     if(new_distance < distance)
01133     {
01134       index = i;
01135       distance = new_distance;
01136     }
01137     new_distance = joint_state_vector_[i]->getJointModel()->distance(joint_values, upper_bounds);
01138     if(new_distance < distance)
01139     {
01140       index = i;
01141       distance = new_distance;
01142     }
01143   }
01144   return std::pair<double,int>(distance,index);
01145 }


moveit_core
Author(s): Ioan Sucan , Sachin Chitta , Acorn Pooley
autogenerated on Mon Oct 6 2014 02:24:47