joint_model_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 */
00036 
00037 #include <moveit/robot_model/joint_model_group.h>
00038 #include <moveit/robot_model/robot_model.h>
00039 #include <algorithm>
00040 
00041 namespace robot_model
00042 {
00043 namespace
00044 {
00045 
00046 bool orderLinksByIndex(const LinkModel *a, const LinkModel *b)
00047 {
00048   return a->getTreeIndex() < b->getTreeIndex();
00049 }
00050 
00051 bool orderJointsByIndex(const JointModel *a, const JointModel *b)
00052 {
00053   return a->getTreeIndex() < b->getTreeIndex();
00054 }
00055 
00056 bool includesParent(const JointModel *joint, const JointModelGroup *group)
00057 {
00058   bool found = false;
00059   // if we find that an ancestor is also in the group, then the joint is not a root
00060   while (joint->getParentLinkModel() != NULL)
00061   {
00062     joint = joint->getParentLinkModel()->getParentJointModel();
00063     if (group->hasJointModel(joint->getName()) && joint->getVariableCount() > 0 && joint->getMimic() == NULL)
00064     {
00065       found = true;
00066       break;
00067     }
00068     else
00069       if (joint->getMimic() != NULL)
00070       {
00071         const JointModel *mjoint = joint->getMimic();
00072         if (group->hasJointModel(mjoint->getName()) && mjoint->getVariableCount() > 0 && mjoint->getMimic() == NULL)
00073           found = true;
00074         else
00075           if (includesParent(mjoint, group))
00076             found = true;
00077         if (found)
00078           break;
00079       }
00080   }
00081   return found;
00082 }
00083 
00084 }
00085 }
00086 
00087 robot_model::JointModelGroup::JointModelGroup(const std::string& group_name,
00088                           const std::vector<const JointModel*> &unsorted_group_joints,
00089                           const RobotModel* parent_model) :
00090   parent_model_(parent_model), name_(group_name),
00091   variable_count_(0), is_end_effector_(false), is_chain_(false),
00092   default_ik_timeout_(0.5), default_ik_attempts_(2)
00093 {
00094   // sort joints in Depth-First order
00095   std::vector<const JointModel*> group_joints = unsorted_group_joints;
00096   std::sort(group_joints.begin(), group_joints.end(), &orderJointsByIndex);
00097 
00098   for (std::size_t i = 0 ; i < group_joints.size() ; ++i)
00099   {
00100     joint_model_map_[group_joints[i]->getName()] = group_joints[i];
00101     unsigned int vc = group_joints[i]->getVariableCount();
00102     if (vc > 0)
00103     {
00104       if (group_joints[i]->getMimic() == NULL)
00105       {
00106         joint_model_vector_.push_back(group_joints[i]);
00107         variable_count_ += vc;
00108       }
00109       else
00110         mimic_joints_.push_back(group_joints[i]);
00111 
00112       if (group_joints[i]->getType() == JointModel::REVOLUTE && static_cast<const RevoluteJointModel*>(group_joints[i])->isContinuous())
00113         continuous_joint_model_vector_const_.push_back(group_joints[i]);
00114     }
00115     else
00116       fixed_joints_.push_back(group_joints[i]);
00117   }
00118 
00119   //now we need to find all the set of joints within this group
00120   //that root distinct subtrees
00121   for (std::size_t i = 0 ; i < joint_model_vector_.size() ; ++i)
00122   {
00123     joint_model_name_vector_.push_back(joint_model_vector_[i]->getName());
00124     bool found = false;
00125     const JointModel *joint = joint_model_vector_[i];
00126     // if we find that an ancestor is also in the group, then the joint is not a root
00127     if (!includesParent(joint, this))
00128       joint_roots_.push_back(joint_model_vector_[i]);
00129   }
00130 
00131   // compute joint_variables_index_map_
00132   unsigned int vector_index_counter = 0;
00133   for (std::size_t i = 0 ; i < joint_model_vector_.size() ; ++i)
00134   {
00135     const std::vector<std::string>& name_order = joint_model_vector_[i]->getVariableNames();
00136     for (std::size_t j = 0; j < name_order.size(); ++j)
00137     {
00138       joint_variables_index_map_[name_order[j]] = vector_index_counter + j;
00139       active_variable_names_.push_back(name_order[j]);
00140       active_variable_names_set_.insert(name_order[j]);
00141     }
00142     joint_variables_index_map_[joint_model_vector_[i]->getName()] = vector_index_counter;
00143     vector_index_counter += name_order.size();
00144   }
00145 
00146   for (std::size_t i = 0 ; i < mimic_joints_.size() ; ++i)
00147   {
00148     const std::vector<std::string>& name_order = mimic_joints_[i]->getVariableNames();
00149     const std::vector<std::string>& mim_name_order = mimic_joints_[i]->getMimic()->getVariableNames();
00150     for (std::size_t j = 0; j < name_order.size(); ++j)
00151       joint_variables_index_map_[name_order[j]] = joint_variables_index_map_[mim_name_order[j]];
00152     joint_variables_index_map_[mimic_joints_[i]->getName()] = joint_variables_index_map_[mimic_joints_[i]->getMimic()->getName()];
00153   }
00154 
00155   // now we need to make another pass for group links (we include the fixed joints here)
00156   std::set<const LinkModel*> group_links_set;
00157   for (std::size_t i = 0 ; i < group_joints.size() ; ++i)
00158     group_links_set.insert(group_joints[i]->getChildLinkModel());
00159 
00160   for (std::set<const LinkModel*>::iterator it = group_links_set.begin(); it != group_links_set.end(); ++it)
00161     link_model_vector_.push_back(*it);
00162 
00163   std::sort(link_model_vector_.begin(), link_model_vector_.end(), &orderLinksByIndex);
00164   for (std::size_t i = 0 ; i < link_model_vector_.size() ; ++i)
00165   {
00166     link_model_name_vector_.push_back(link_model_vector_[i]->getName());
00167     if (link_model_vector_[i]->getShape())
00168       link_model_with_geometry_name_vector_.push_back(link_model_vector_[i]->getName());
00169   }
00170 
00171   // compute updated links
00172   std::set<const LinkModel*> u_links;
00173   for (std::size_t i = 0 ; i < joint_roots_.size() ; ++i)
00174   {
00175     std::vector<const LinkModel*> links;
00176     parent_model->getChildLinkModels(joint_roots_[i], links);
00177     u_links.insert(links.begin(), links.end());
00178   }
00179   for (std::set<const LinkModel*>::iterator it = u_links.begin(); it != u_links.end(); ++it)
00180   {
00181     updated_link_model_vector_.push_back(*it);
00182     updated_link_model_set_.insert(*it);
00183     updated_link_model_name_set_.insert((*it)->getName());
00184     if ((*it)->getShape())
00185     {
00186       updated_link_model_with_geometry_vector_.push_back(*it);
00187       updated_link_model_with_geometry_set_.insert(*it);
00188       updated_link_model_with_geometry_name_set_.insert((*it)->getName());
00189     }
00190   }
00191   std::sort(updated_link_model_vector_.begin(), updated_link_model_vector_.end(), &orderLinksByIndex);
00192   std::sort(updated_link_model_with_geometry_vector_.begin(), updated_link_model_with_geometry_vector_.end(), &orderLinksByIndex);
00193   for (std::size_t i = 0; i < updated_link_model_vector_.size(); ++i)
00194     updated_link_model_name_vector_.push_back(updated_link_model_vector_[i]->getName());
00195   for (std::size_t i = 0; i < updated_link_model_with_geometry_vector_.size(); ++i)
00196     updated_link_model_with_geometry_name_vector_.push_back(updated_link_model_with_geometry_vector_[i]->getName());
00197 
00198   // check if this group should actually be a chain
00199   if (joint_roots_.size() == 1 && joint_model_vector_.size() > 1 && !is_chain_)
00200   {
00201     bool chain = true;
00202     // this would be the leaf of the chain, due to our sorting
00203     for (std::size_t k = group_joints.size() - 1 ; k > 0 ; --k)
00204       if (!group_joints[k]->getParentLinkModel() || group_joints[k]->getParentLinkModel()->getParentJointModel() != group_joints[k-1])
00205       {
00206         chain = false;
00207         break;
00208       }
00209     if (chain)
00210       is_chain_ = true;
00211   }
00212 }
00213 
00214 robot_model::JointModelGroup::~JointModelGroup()
00215 {
00216 }
00217 
00218 bool robot_model::JointModelGroup::isSubgroup(const std::string& group) const
00219 {
00220   for (std::size_t i = 0; i < subgroup_names_.size(); ++i)
00221     if (group == subgroup_names_[i])
00222       return true;
00223   return false;
00224 }
00225 
00226 bool robot_model::JointModelGroup::hasJointModel(const std::string &joint) const
00227 {
00228   return joint_model_map_.find(joint) != joint_model_map_.end();
00229 }
00230 
00231 bool robot_model::JointModelGroup::hasLinkModel(const std::string &link) const
00232 {
00233   return std::find(link_model_name_vector_.begin(), link_model_name_vector_.end(), link) != link_model_name_vector_.end();
00234 }
00235 
00236 const robot_model::JointModel* robot_model::JointModelGroup::getJointModel(const std::string &name) const
00237 {
00238   std::map<std::string, const JointModel*>::const_iterator it = joint_model_map_.find(name);
00239   if (it == joint_model_map_.end())
00240   {
00241     logError("Joint '%s' not found in group '%s'", name.c_str(), name_.c_str());
00242     return NULL;
00243   }
00244   else
00245     return it->second;
00246 }
00247 
00248 void robot_model::JointModelGroup::getVariableRandomValues(random_numbers::RandomNumberGenerator &rng, std::vector<double> &values) const
00249 {
00250   for (std::size_t i = 0  ; i < joint_model_vector_.size() ; ++i)
00251     joint_model_vector_[i]->getVariableRandomValues(rng, values);
00252 }
00253 
00254 void robot_model::JointModelGroup::getVariableRandomValuesNearBy(random_numbers::RandomNumberGenerator &rng, std::vector<double> &values, const std::vector<double> &near, const std::map<robot_model::JointModel::JointType, double> &distance_map) const
00255 {
00256   if (near.size() != variable_count_)
00257   {
00258     logError("The specification of the near-by variable values to sample around for group '%s' should be of size %u but it is of size %u",
00259              name_.c_str(), variable_count_, (unsigned int)near.size());
00260     return;
00261   }
00262 
00263   for (std::size_t i = 0  ; i < joint_model_vector_.size() ; ++i)
00264   {
00265     double distance = 0.0;
00266     std::map<robot_model::JointModel::JointType, double>::const_iterator iter = distance_map.find(joint_model_vector_[i]->getType());
00267     if (iter != distance_map.end())
00268       distance = iter->second;
00269     else
00270       logWarn("Did not pass in distance for %s",joint_model_vector_[i]->getName().c_str());
00271     joint_model_vector_[i]->getVariableRandomValuesNearBy(rng, values, near, distance);
00272   }
00273 }
00274 
00275 void robot_model::JointModelGroup::getVariableRandomValuesNearBy(random_numbers::RandomNumberGenerator &rng, std::vector<double> &values, const std::vector<double> &near, const std::vector<double> &distances) const
00276 {
00277   if (distances.size() != joint_model_vector_.size())
00278   {
00279     logError("When sampling random values nearby for group '%s', distances vector should be of size %u, but it is of size %u",
00280              name_.c_str(), (unsigned int)joint_model_vector_.size(), (unsigned int)distances.size());
00281     return;
00282   }
00283   if (near.size() != variable_count_)
00284   {
00285     logError("The specification of the near-by variable values to sample around for group '%s' should be of size %u but it is of size %u",
00286              name_.c_str(), variable_count_, (unsigned int)near.size());
00287     return;
00288   }
00289 
00290   for (std::size_t i = 0  ; i < joint_model_vector_.size() ; ++i)
00291     joint_model_vector_[i]->getVariableRandomValuesNearBy(rng, values, near, distances[i]);
00292 }
00293 
00294 double robot_model::JointModelGroup::getMaximumExtent(void) const
00295 {
00296   double max_distance = 0.0;
00297   for (std::size_t j = 0 ; j < joint_model_vector_.size() ; ++j)
00298     max_distance += joint_model_vector_[j]->getMaximumExtent() * joint_model_vector_[j]->getDistanceFactor();
00299   return max_distance;
00300 }
00301 
00302 void robot_model::JointModelGroup::getKnownDefaultStates(std::vector<std::string> &default_states) const
00303 {
00304   default_states.clear();
00305   default_states.reserve(default_states_.size());
00306   for (std::map<std::string, std::map<std::string, double> >::const_iterator it = default_states_.begin() ; it != default_states_.end() ; ++it)
00307     default_states.push_back(it->first);
00308 }
00309 
00310 bool robot_model::JointModelGroup::getVariableDefaultValues(const std::string &name, std::map<std::string, double> &values) const
00311 {
00312   std::map<std::string, std::map<std::string, double> >::const_iterator it = default_states_.find(name);
00313   if (it == default_states_.end())
00314     return false;
00315   values = it->second;
00316   return true;
00317 }
00318 
00319 void robot_model::JointModelGroup::getVariableDefaultValues(std::vector<double> &values) const
00320 {
00321   values.reserve(values.size() + joint_model_vector_.size());
00322   for (std::size_t i = 0  ; i < joint_model_vector_.size() ; ++i)
00323     joint_model_vector_[i]->getVariableDefaultValues(values);
00324 }
00325 
00326 void robot_model::JointModelGroup::getVariableDefaultValues(std::map<std::string, double> &values) const
00327 {
00328   for (std::size_t i = 0  ; i < joint_model_vector_.size() ; ++i)
00329     joint_model_vector_[i]->getVariableDefaultValues(values);
00330 }
00331 
00332 std::vector<moveit_msgs::JointLimits> robot_model::JointModelGroup::getVariableDefaultLimits() const
00333 {
00334   std::vector<moveit_msgs::JointLimits> ret_vec;
00335   for(unsigned int i = 0; i < joint_model_vector_.size(); i++)
00336   {
00337     const std::vector<moveit_msgs::JointLimits> &jvec = joint_model_vector_[i]->getVariableDefaultLimits();
00338     ret_vec.insert(ret_vec.end(), jvec.begin(), jvec.end());
00339   }
00340   return ret_vec;
00341 }
00342 
00343 std::vector<moveit_msgs::JointLimits> robot_model::JointModelGroup::getVariableLimits() const
00344 {
00345   std::vector<moveit_msgs::JointLimits> ret_vec;
00346   for(unsigned int i = 0; i < joint_model_vector_.size(); i++)
00347   {
00348     const std::vector<moveit_msgs::JointLimits> &jvec = joint_model_vector_[i]->getVariableLimits();
00349     ret_vec.insert(ret_vec.end(), jvec.begin(), jvec.end());
00350   }
00351   return ret_vec;
00352 }
00353 
00354 void robot_model::JointModelGroup::setVariableLimits(const std::vector<moveit_msgs::JointLimits>& jlim)
00355 {
00356   // the following const_cast is safe because we are in a non-const function that operates on the same model
00357   // the joint is part of
00358   for (unsigned int i = 0; i < joint_model_vector_.size(); i++)
00359     const_cast<JointModel*>(joint_model_vector_[i])->setVariableLimits(jlim);
00360 }
00361 
00362 void robot_model::JointModelGroup::setDefaultIKTimeout(double ik_timeout)
00363 {
00364   default_ik_timeout_ = ik_timeout;
00365   if (solver_instance_)
00366     solver_instance_->setDefaultTimeout(ik_timeout);
00367 }
00368 
00369 void robot_model::JointModelGroup::setSolverAllocators(const std::pair<SolverAllocatorFn, SolverAllocatorMapFn> &solvers)
00370 {
00371   solver_allocators_ = solvers;
00372   if (solver_allocators_.first)
00373   {
00374     solver_instance_ = solver_allocators_.first(this);
00375     if (solver_instance_)
00376     {
00377       ik_joint_bijection_.clear();
00378       const std::vector<std::string> &ik_jnames = solver_instance_->getJointNames();
00379       for (std::size_t i = 0 ; i < ik_jnames.size() ; ++i)
00380       {
00381         std::map<std::string, unsigned int>::const_iterator it = joint_variables_index_map_.find(ik_jnames[i]);
00382         if (it == joint_variables_index_map_.end())
00383         {
00384           logError("IK solver computes joint values for joint '%s' but group '%s' does not contain such a joint.", ik_jnames[i].c_str(), getName().c_str());
00385           solver_instance_.reset();
00386           return;
00387         }
00388         const robot_model::JointModel *jm = getJointModel(ik_jnames[i]);
00389         for (unsigned int k = 0 ; k < jm->getVariableCount() ; ++k)
00390           ik_joint_bijection_.push_back(it->second + k);
00391       }
00392       solver_instance_const_ = solver_instance_;
00393     }
00394   }
00395 }
00396 
00397 bool robot_model::JointModelGroup::canSetStateFromIK(const std::string &tip) const
00398 {
00399   const kinematics::KinematicsBaseConstPtr& solver = getSolverInstance();
00400   if (!solver)
00401     return false;
00402   const std::string &tip_frame = solver->getTipFrame();
00403   if (tip != tip_frame)
00404   {
00405     const LinkModel *lm = getParentModel()->getLinkModel(tip);
00406     if (!lm)
00407       return false;
00408     const LinkModel::AssociatedFixedTransformMap &fixed_links = lm->getAssociatedFixedTransforms();
00409     for (std::map<const LinkModel*, Eigen::Affine3d>::const_iterator it = fixed_links.begin() ; it != fixed_links.end() ; ++it)
00410       if (it->first->getName() == tip_frame)
00411         return true;
00412     return false;
00413   }
00414   else
00415     return true;
00416 }
00417 
00418 void robot_model::JointModelGroup::printGroupInfo(std::ostream &out) const
00419 {
00420   out << "Group '" << name_ << "':" << std::endl;
00421   for (std::size_t i = 0 ; i < joint_model_vector_.size() ; ++i)
00422   {
00423     const std::vector<std::string> &vn = joint_model_vector_[i]->getVariableNames();
00424     for (std::vector<std::string>::const_iterator it = vn.begin() ; it != vn.end() ; ++it)
00425     {
00426       out << "   " << *it << " [";
00427       std::pair<double, double> b;
00428       joint_model_vector_[i]->getVariableBounds(*it, b);
00429       if (b.first <= -std::numeric_limits<double>::max())
00430         out << "DBL_MIN";
00431       else
00432         out << b.first;
00433       out << ", ";
00434       if (b.second >= std::numeric_limits<double>::max())
00435         out << "DBL_MAX";
00436       else
00437         out << b.second;
00438       out << "]";
00439       if (joint_model_vector_[i]->getMimic())
00440         out << " *";
00441       out << std::endl;
00442     }
00443   }
00444 }


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