kinematic_model.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 
00037 #include <queue>
00038 #include <cmath>
00039 #include <set>
00040 
00041 #include <ros/ros.h>
00042 #include <planning_models/kinematic_model.h>
00043 #include <geometric_shapes/shape_operations.h>
00044 #include <ros/console.h>
00045 #include <angles/angles.h>
00046 
00047 
00048 /* ------------------------ KinematicModel ------------------------ */
00049 planning_models::KinematicModel::KinematicModel(const urdf::Model &model, 
00050                                                 const std::vector<GroupConfig>& group_configs,
00051                                                 const std::vector<MultiDofConfig>& multi_dof_configs)
00052 {    
00053   model_name_ = model.getName();
00054   if (model.getRoot())
00055   {
00056     const urdf::Link *root = model.getRoot().get();
00057     root_ = buildRecursive(NULL, root, multi_dof_configs);
00058     buildGroups(group_configs);
00059   }
00060   else
00061   {
00062     root_ = NULL;
00063     ROS_WARN("No root link found");
00064   }
00065 }
00066 
00067 planning_models::KinematicModel::KinematicModel(const KinematicModel &source)
00068 {
00069   copyFrom(source);
00070 }
00071 
00072 planning_models::KinematicModel::~KinematicModel(void)
00073 {
00074   for (std::map<std::string, JointModelGroup*>::iterator it = joint_model_group_map_.begin() ; it != joint_model_group_map_.end() ; ++it)
00075   {
00076     delete it->second;
00077   }
00078   //this destroys the whole tree
00079   if(root_) {
00080     delete root_;
00081   }
00082 }
00083 
00084 void planning_models::KinematicModel::exclusiveLock(void) const
00085 {
00086   lock_.lock();
00087 }
00088 
00089 void planning_models::KinematicModel::exclusiveUnlock(void) const
00090 {
00091   lock_.unlock();
00092 }
00093 
00094 void planning_models::KinematicModel::sharedLock(void) const
00095 {
00096   lock_.lock_shared();
00097 }
00098 
00099 void planning_models::KinematicModel::sharedUnlock(void) const
00100 {
00101   lock_.unlock_shared();
00102 }
00103 
00104 const std::string& planning_models::KinematicModel::getName() const {
00105   return model_name_;
00106 }
00107 
00108 void planning_models::KinematicModel::copyFrom(const KinematicModel &source)
00109 {
00110   model_name_ = source.model_name_;
00111 
00112   if (source.root_)
00113   {
00114     root_ = copyRecursive(NULL, source.root_->child_link_model_);
00115     
00116 
00117     const std::map<std::string, JointModelGroup*>& source_group_map = source.getJointModelGroupMap();
00118     std::map< std::string, std::vector<std::string> > groupContent;
00119     std::vector<GroupConfig> group_configs;
00120     std::vector<std::string> empty_strings;
00121     for(std::map<std::string, JointModelGroup*>::const_iterator it = source_group_map.begin();
00122         it != source_group_map.end();
00123         it++) {
00124       group_configs.push_back(GroupConfig(it->first, it->second->getJointModelNames(), empty_strings));
00125     }
00126     buildGroups(group_configs);
00127   } else 
00128   {
00129     root_ = NULL;
00130   }
00131 }
00132 
00133 void planning_models::KinematicModel::buildGroups(const std::vector<GroupConfig>& group_configs) 
00134 {
00135   //the only thing tricky is dealing with subgroups
00136   std::vector<bool> processed(group_configs.size(), false);
00137   while(true) {
00138     //going to make passes until we can't do anything else
00139     bool added = false;
00140     for(unsigned int i = 0; i < group_configs.size(); i++) {
00141       if(!processed[i]) {
00142         //if we haven't processed, check and see if the dependencies are met yet
00143         bool all_subgroups_added = true;
00144         for(unsigned int j = 0; j < group_configs[i].subgroups_.size(); j++) {
00145           if(joint_model_group_map_.find(group_configs[i].subgroups_[j]) ==
00146              joint_model_group_map_.end()) {
00147             all_subgroups_added = false;
00148             break;
00149           }
00150         }
00151         if(all_subgroups_added) {
00152           //only get one chance to do it right
00153           if(addModelGroup(group_configs[i])) {
00154             processed[i] = true;
00155             added = true;
00156           } else {
00157             ROS_WARN_STREAM("Failed to add group " << group_configs[i].name_);
00158           }
00159         }
00160       }
00161     }
00162     if(!added) {
00163       for(unsigned int i = 0; i < processed.size(); i++) {
00164         if(!processed[i]) {
00165           ROS_WARN_STREAM("Could not process group " << group_configs[i].name_ << " due to unmet subgroup dependencies");
00166         }
00167       }
00168       return;
00169     }
00170   }
00171 }
00172 
00173 void planning_models::KinematicModel::removeModelGroup(const std::string& group) {
00174   if(!hasModelGroup(group)) return;
00175   delete joint_model_group_map_[group];
00176   joint_model_group_map_.erase(group);
00177   joint_model_group_config_map_.erase(group);
00178 }
00179 
00180 bool planning_models::KinematicModel::addModelGroup(const planning_models::KinematicModel::GroupConfig& gc)
00181 {
00182   if(joint_model_group_map_.find(gc.name_) != joint_model_group_map_.end()) {
00183     ROS_WARN_STREAM("Already have a model group named " << gc.name_ <<". Not adding.");
00184     return false;
00185   }
00186   std::vector<const JointModel*> jointv;
00187   std::vector<const JointModel*> fixed_jointv;
00188   if(!gc.tip_link_.empty() && !gc.base_link_.empty()) {
00189     if(!gc.subgroups_.empty()) {
00190       ROS_WARN_STREAM("Ignoring subgroups as tip and base are defined for group " << gc.name_);
00191     }
00192     //if this is not a physical robot link but is the world link
00193     bool base_link_is_world_link = (gc.base_link_ == getRoot()->getParentFrameId() &&
00194                                     getLinkModel(gc.base_link_) == NULL);
00195     const LinkModel* base_link = NULL;
00196     if(!base_link_is_world_link) {
00197       base_link = getLinkModel(gc.base_link_);
00198       if(base_link == NULL) {
00199         ROS_WARN_STREAM("Group config " << gc.name_ << " has invalid base link " << gc.base_link_);
00200         return false;
00201       }
00202     }
00203     const LinkModel* tip_link = getLinkModel(gc.tip_link_);
00204     if(tip_link == NULL) {
00205       ROS_WARN_STREAM("Group config " << gc.name_ << " has invalid tip link " << gc.tip_link_);
00206       return false;
00207     }
00208     const LinkModel* lm = tip_link;
00209     bool ok = false;
00210     while(true) {
00211       if(lm == NULL) {
00212         if(base_link_is_world_link) {
00213           ok = true;
00214         }
00215         break;
00216       }
00217       if(lm == base_link) {
00218         ok = true;
00219         break;
00220       }
00221       if(lm->getParentJointModel() == NULL) {
00222         break;
00223       }
00224       //only adding non-fixed joint models
00225       const FixedJointModel* fjm = dynamic_cast<const FixedJointModel*>(lm->getParentJointModel());
00226       if(fjm == NULL) {
00227         jointv.push_back(lm->getParentJointModel());
00228       } else {
00229         fixed_jointv.push_back(fjm);
00230       }
00231       lm = lm->getParentJointModel()->getParentLinkModel();
00232     }
00233     if(!ok) {
00234       ROS_WARN_STREAM("For group " << gc.name_ 
00235                       << " base link " << gc.base_link_ 
00236                       << " does not appear to be a direct descendent of " << gc.tip_link_);
00237       return false;
00238     }
00239     //need to reverse jointv to get things in right order
00240     std::reverse(jointv.begin(), jointv.end());
00241   } else {
00242     if(!gc.subgroups_.empty()) {
00243       std::set<const JointModel*> joint_set;
00244       for(unsigned int i = 0; i < gc.subgroups_.size(); i++) {
00245         if(joint_model_group_map_.find(gc.subgroups_[i]) == joint_model_group_map_.end()) {
00246           ROS_INFO_STREAM("Subgroup " << gc.subgroups_[i] << " not defined so can't add group " << gc.name_);
00247           return false;
00248         }
00249         const JointModelGroup* jmg = joint_model_group_map_.find(gc.subgroups_[i])->second;
00250         for(unsigned int j = 0; j < jmg->getJointModels().size(); j++) {
00251           joint_set.insert(jmg->getJointModels()[j]);
00252         }
00253       }
00254       for(std::set<const JointModel*>::iterator it = joint_set.begin();
00255           it != joint_set.end();
00256           it++) {
00257         jointv.push_back((*it));
00258       }
00259     }
00260     if(gc.joints_.size() == 0 && gc.subgroups_.empty()) {
00261       ROS_WARN_STREAM("Group " << gc.name_ << " must have tip/base links, subgroups, or one or more joints");
00262       return false;
00263     }
00264     for(unsigned int j = 0; j < gc.joints_.size(); j++) {
00265       const JointModel* joint = getJointModel(gc.joints_[j]);
00266       if(joint == NULL) {
00267         ROS_ERROR_STREAM("Group " << gc.name_ << " has invalid joint " << gc.joints_[j]);
00268         return false;
00269       }
00270       jointv.push_back(joint);
00271     }
00272   }
00273   if(jointv.size() == 0) {
00274     ROS_WARN_STREAM("Group " << gc.name_ << " must have at least one valid joint");
00275     return false;
00276   }
00277   joint_model_group_map_[gc.name_] = new JointModelGroup(gc.name_, jointv, fixed_jointv, this);
00278   joint_model_group_config_map_[gc.name_] = gc;
00279   return true;
00280 }
00281 
00282 planning_models::KinematicModel::JointModel* planning_models::KinematicModel::buildRecursive(LinkModel *parent, const urdf::Link *link, 
00283                                                                                              const std::vector<MultiDofConfig>& multi_dof_configs)
00284 {  
00285   JointModel *joint = constructJointModel(link->parent_joint.get(), link, multi_dof_configs);
00286   if(joint == NULL) {
00287     return NULL;
00288   }
00289   joint_model_map_[joint->name_] = joint;
00290   for(JointModel::js_type::const_iterator it = joint->getJointStateEquivalents().begin();
00291       it != joint->getJointStateEquivalents().end();
00292       it++) {
00293     joint_model_map_[it->right] = joint;
00294   }
00295   joint_model_vector_.push_back(joint);
00296   joint->parent_link_model_ = parent;
00297   joint->child_link_model_ = constructLinkModel(link);
00298   if (parent == NULL)
00299     joint->child_link_model_->joint_origin_transform_.setIdentity();
00300   link_model_map_[joint->child_link_model_->name_] = joint->child_link_model_;
00301   link_model_vector_.push_back(joint->child_link_model_);
00302   if(joint->child_link_model_->shape_ != NULL) {
00303     link_models_with_collision_geometry_vector_.push_back(joint->child_link_model_);
00304   }
00305   joint->child_link_model_->parent_joint_model_ = joint;
00306   
00307   for (unsigned int i = 0 ; i < link->child_links.size() ; ++i) {
00308     JointModel* jm = buildRecursive(joint->child_link_model_, link->child_links[i].get(), multi_dof_configs);
00309     if(jm != NULL) {
00310       joint->child_link_model_->child_joint_models_.push_back(jm);
00311     }
00312   }
00313 
00314   return joint;
00315 }
00316 
00317 planning_models::KinematicModel::JointModel* planning_models::KinematicModel::constructJointModel(const urdf::Joint *urdf_joint,
00318                                                                                                   const urdf::Link *child_link,
00319                                                                                                   const std::vector<MultiDofConfig>& multi_dof_configs)
00320 {
00321   const MultiDofConfig* joint_config = NULL;
00322   bool found = false;
00323   for(std::vector<MultiDofConfig>::const_iterator it = multi_dof_configs.begin();
00324       it != multi_dof_configs.end();
00325       it++) {
00326     if(it->child_frame_id == child_link->name) {
00327       if(found == true) {
00328         ROS_WARN_STREAM("KinematicModel - two multi-dof joints with same " << it->child_frame_id << " child frame");
00329       } else {
00330         found = true;
00331         joint_config = &(*it);
00332       }
00333     }
00334   }
00335 
00336   planning_models::KinematicModel::JointModel* result = NULL;
00337 
00338   //must be the root link transform
00339   if(urdf_joint == NULL) {
00340     if(!found) {
00341       ROS_ERROR("Root transform has no multi dof joint config");
00342       return NULL;
00343     }
00344     if(joint_config->type == "Planar") {
00345       result = new PlanarJointModel(joint_config->name, joint_config);
00346     } else if(joint_config->type == "Floating") {
00347       result = new FloatingJointModel(joint_config->name, joint_config);
00348     } else if(joint_config->type == "Fixed"){
00349       result = new FixedJointModel(joint_config->name, joint_config);
00350     } else {
00351       ROS_ERROR_STREAM("Unrecognized type of multi dof joint " << joint_config->type);
00352       return NULL;
00353     }
00354   } else {
00355     switch (urdf_joint->type)
00356     {
00357     case urdf::Joint::REVOLUTE:
00358       {
00359         RevoluteJointModel *j = new RevoluteJointModel(urdf_joint->name, joint_config);
00360         if(urdf_joint->safety)
00361           {
00362             j->setVariableBounds(j->name_, urdf_joint->safety->soft_lower_limit, urdf_joint->safety->soft_upper_limit);
00363           }
00364         else
00365           {
00366             j->setVariableBounds(j->name_, urdf_joint->limits->lower, urdf_joint->limits->upper);
00367           }
00368         j->continuous_ = false;
00369         j->axis_.setValue(urdf_joint->axis.x, urdf_joint->axis.y, urdf_joint->axis.z);
00370         result = j;
00371       }
00372       break;
00373     case urdf::Joint::CONTINUOUS:
00374       {
00375         RevoluteJointModel *j = new RevoluteJointModel(urdf_joint->name, joint_config);
00376         j->continuous_ = true;
00377         j->setVariableBounds(j->name_, -M_PI, M_PI);
00378         j->axis_.setValue(urdf_joint->axis.x, urdf_joint->axis.y, urdf_joint->axis.z);
00379         result = j;
00380       }
00381       break;
00382     case urdf::Joint::PRISMATIC:
00383       {
00384         PrismaticJointModel *j = new PrismaticJointModel(urdf_joint->name, joint_config);
00385         if(urdf_joint->safety)
00386           {
00387             j->setVariableBounds(j->name_, urdf_joint->safety->soft_lower_limit, urdf_joint->safety->soft_upper_limit);
00388           }
00389         else
00390           {
00391             j->setVariableBounds(j->name_, urdf_joint->limits->lower, urdf_joint->limits->upper);
00392           }
00393         j->axis_.setValue(urdf_joint->axis.x, urdf_joint->axis.y, urdf_joint->axis.z);
00394         result = j;
00395       }
00396       break;
00397     case urdf::Joint::FLOATING:
00398       result = new FloatingJointModel(urdf_joint->name, joint_config);
00399       break;
00400     case urdf::Joint::PLANAR:
00401       result = new PlanarJointModel(urdf_joint->name, joint_config);
00402       break;
00403     case urdf::Joint::FIXED:
00404       result = new FixedJointModel(urdf_joint->name, joint_config);
00405       break;
00406     default:
00407       ROS_ERROR("Unknown joint type: %d", (int)urdf_joint->type);
00408       break;
00409     }
00410   }
00411   return result;
00412 }
00413 
00414 namespace planning_models
00415 {
00416 static inline tf::Transform urdfPose2TFTransform(const urdf::Pose &pose)
00417 {
00418   return tf::Transform(tf::Quaternion(pose.rotation.x, pose.rotation.y, pose.rotation.z, pose.rotation.w),
00419                      tf::Vector3(pose.position.x, pose.position.y, pose.position.z));
00420 }
00421 }
00422 
00423 planning_models::KinematicModel::LinkModel* planning_models::KinematicModel::constructLinkModel(const urdf::Link *urdf_link)
00424 {
00425   ROS_ASSERT(urdf_link);
00426   
00427   LinkModel *result = new LinkModel(this);
00428   result->name_ = urdf_link->name;
00429 
00430   if(urdf_link->collision && urdf_link->collision->geometry) {
00431     result->collision_origin_transform_ = urdfPose2TFTransform(urdf_link->collision->origin);
00432     result->shape_ = constructShape(urdf_link->collision->geometry.get());
00433   } else if(urdf_link->visual && urdf_link->visual->geometry){
00434     result->collision_origin_transform_ = urdfPose2TFTransform(urdf_link->visual->origin);
00435     result->shape_ = constructShape(urdf_link->visual->geometry.get());
00436   } else {
00437     result->collision_origin_transform_.setIdentity();
00438     result->shape_ = NULL;
00439   }
00440 
00441   if (urdf_link->parent_joint.get()) {
00442     result->joint_origin_transform_ = urdfPose2TFTransform(urdf_link->parent_joint->parent_to_joint_origin_transform);
00443     ROS_DEBUG_STREAM("Setting joint origin for " << result->name_ << " to " 
00444                     << result->joint_origin_transform_.getOrigin().x() << " " 
00445                     << result->joint_origin_transform_.getOrigin().y() << " " 
00446                     << result->joint_origin_transform_.getOrigin().z());
00447   } else {
00448     ROS_DEBUG_STREAM("Setting joint origin to identity for " << result->name_);
00449     result->joint_origin_transform_.setIdentity();
00450   }
00451   return result;
00452 }
00453 
00454 shapes::Shape* planning_models::KinematicModel::constructShape(const urdf::Geometry *geom)
00455 {
00456   ROS_ASSERT(geom);
00457  
00458   shapes::Shape *result = NULL;
00459   switch (geom->type)
00460   {
00461   case urdf::Geometry::SPHERE:
00462     result = new shapes::Sphere(dynamic_cast<const urdf::Sphere*>(geom)->radius);
00463     break;      
00464   case urdf::Geometry::BOX:
00465     {
00466       urdf::Vector3 dim = dynamic_cast<const urdf::Box*>(geom)->dim;
00467       result = new shapes::Box(dim.x, dim.y, dim.z);
00468     }
00469     break;
00470   case urdf::Geometry::CYLINDER:
00471     result = new shapes::Cylinder(dynamic_cast<const urdf::Cylinder*>(geom)->radius,
00472                                   dynamic_cast<const urdf::Cylinder*>(geom)->length);
00473     break;
00474   case urdf::Geometry::MESH:
00475     {
00476       const urdf::Mesh *mesh = dynamic_cast<const urdf::Mesh*>(geom);
00477       if (!mesh->filename.empty())
00478       {
00479         tf::Vector3 scale(mesh->scale.x, mesh->scale.y, mesh->scale.z);
00480         result = shapes::createMeshFromFilename(mesh->filename, &scale);
00481       }   
00482     } 
00483     break;
00484   default:
00485     ROS_ERROR("Unknown geometry type: %d", (int)geom->type);
00486     break;
00487   }
00488     
00489   return result;
00490 }
00491 
00492 const planning_models::KinematicModel::JointModel* planning_models::KinematicModel::getRoot(void) const
00493 {
00494   return root_;
00495 }
00496 
00497 bool planning_models::KinematicModel::hasJointModel(const std::string &name) const
00498 {
00499   return joint_model_map_.find(name) != joint_model_map_.end();
00500 }
00501 
00502 bool planning_models::KinematicModel::hasLinkModel(const std::string &name) const
00503 {
00504   return link_model_map_.find(name) != link_model_map_.end();
00505 }
00506 
00507 bool planning_models::KinematicModel::hasModelGroup(const std::string &name) const
00508 {
00509   return joint_model_group_map_.find(name) != joint_model_group_map_.end();
00510 }
00511 
00512 const planning_models::KinematicModel::JointModel* planning_models::KinematicModel::getJointModel(const std::string &name) const
00513 {
00514   std::map<std::string, JointModel*>::const_iterator it = joint_model_map_.find(name);
00515   if (it == joint_model_map_.end())
00516   {
00517     ROS_ERROR("Joint '%s' not found", name.c_str());
00518     return NULL;
00519   }
00520   else
00521     return it->second;
00522 }
00523 
00524 const planning_models::KinematicModel::LinkModel* planning_models::KinematicModel::getLinkModel(const std::string &name) const
00525 {
00526   std::map<std::string, LinkModel*>::const_iterator it = link_model_map_.find(name);
00527   if (it == link_model_map_.end())
00528   {
00529     ROS_ERROR("Link '%s' not found", name.c_str());
00530     return NULL;
00531   }
00532   else
00533     return it->second;
00534 }
00535 
00536 void planning_models::KinematicModel::getModelGroupNames(std::vector<std::string> &groups) const
00537 {
00538   groups.clear();
00539   groups.reserve(joint_model_group_map_.size());
00540   for (std::map<std::string, JointModelGroup*>::const_iterator it = joint_model_group_map_.begin() ; it != joint_model_group_map_.end() ; ++it)
00541     groups.push_back(it->second->name_);
00542 }
00543 
00544 void planning_models::KinematicModel::getLinkModelNames(std::vector<std::string> &links) const
00545 {
00546   links.clear();
00547   links.reserve(link_model_vector_.size());
00548   for(unsigned int i = 0; i < link_model_vector_.size(); i++) {
00549     links.push_back(link_model_vector_[i]->getName());
00550   }
00551 }
00552 
00553 void planning_models::KinematicModel::getJointModelNames(std::vector<std::string> &joints) const
00554 {
00555   joints.clear();
00556   joints.reserve(joint_model_vector_.size());
00557   for (unsigned int i = 0 ; i < joint_model_vector_.size() ; ++i)
00558     joints.push_back(joint_model_vector_[i]->getName());
00559 }
00560 
00561 planning_models::KinematicModel::JointModel* planning_models::KinematicModel::copyRecursive(LinkModel *parent, const LinkModel *link)
00562 {
00563   JointModel *joint = copyJointModel(link->parent_joint_model_);
00564   joint_model_map_[joint->name_] = joint;
00565   for(JointModel::js_type::iterator it = joint->joint_state_equivalents_.begin();
00566       it != joint->joint_state_equivalents_.end();
00567       it++) {
00568     joint_model_map_[it->right] = joint;
00569   }
00570   joint_model_vector_.push_back(joint);
00571   joint->parent_link_model_ = parent;
00572   joint->child_link_model_ = new LinkModel(link);
00573   link_model_map_[joint->child_link_model_->name_] = joint->child_link_model_;
00574   joint->child_link_model_->parent_joint_model_ = joint;
00575     
00576   for (unsigned int i = 0 ; i < link->child_joint_models_.size() ; ++i)
00577     joint->child_link_model_->child_joint_models_.push_back(copyRecursive(joint->child_link_model_, link->child_joint_models_[i]->child_link_model_));
00578     
00579   return joint;
00580 }
00581 
00582 planning_models::KinematicModel::JointModel* planning_models::KinematicModel::copyJointModel(const JointModel *joint)
00583 {
00584   JointModel *newJoint = NULL;
00585 
00586   if (dynamic_cast<const FixedJointModel*>(joint))
00587   {
00588     newJoint = new FixedJointModel(dynamic_cast<const FixedJointModel*>(joint));
00589   }
00590   else if (dynamic_cast<const FloatingJointModel*>(joint))
00591   {
00592     newJoint = new FloatingJointModel(dynamic_cast<const FloatingJointModel*>(joint));
00593   }
00594   else if (dynamic_cast<const PlanarJointModel*>(joint))
00595   {
00596     newJoint = new PlanarJointModel(dynamic_cast<const PlanarJointModel*>(joint));
00597   }
00598   else if (dynamic_cast<const PrismaticJointModel*>(joint))
00599   {
00600     newJoint = new PrismaticJointModel(dynamic_cast<const PrismaticJointModel*>(joint));
00601   }
00602   else if (dynamic_cast<const RevoluteJointModel*>(joint))
00603   {
00604     newJoint = new RevoluteJointModel(dynamic_cast<const RevoluteJointModel*>(joint));
00605   }
00606   else
00607     ROS_FATAL("Unimplemented type of joint");
00608     
00609   return newJoint;
00610 }
00611 
00612 void planning_models::KinematicModel::getChildLinkModels(const KinematicModel::LinkModel *parent, 
00613                                                          std::vector<const KinematicModel::LinkModel*> &links) const
00614 {
00615   links.push_back(parent);
00616   std::queue<const KinematicModel::LinkModel*> q;
00617   q.push(parent);
00618   while (!q.empty())
00619   {
00620     const KinematicModel::LinkModel* t = q.front();
00621     q.pop();
00622     
00623     for (unsigned int i = 0 ; i < t->child_joint_models_.size() ; ++i) {
00624       if (t->child_joint_models_[i]->child_link_model_)
00625       {
00626         links.push_back(t->child_joint_models_[i]->child_link_model_);
00627         q.push(t->child_joint_models_[i]->child_link_model_);
00628       }
00629     }
00630   }
00631 }
00632 
00633 void planning_models::KinematicModel::getChildLinkModels(const KinematicModel::JointModel *parent, 
00634                                                          std::vector<const KinematicModel::LinkModel*> &links) const
00635 {
00636   getChildLinkModels(parent->child_link_model_, links);
00637 }
00638 
00639 void planning_models::KinematicModel::getChildJointModels(const KinematicModel::LinkModel *parent, 
00640                                                           std::vector<const KinematicModel::JointModel*> &joints) const
00641 {
00642   const KinematicModel::LinkModel* t = parent;
00643 
00644   std::queue<const KinematicModel::LinkModel*> q;
00645   while(1) {
00646     for (unsigned int i = 0 ; i < t->child_joint_models_.size() ; ++i) {
00647       joints.push_back(t->child_joint_models_[i]);
00648       if (t->child_joint_models_[i]->child_link_model_)
00649       {
00650         q.push(t->child_joint_models_[i]->child_link_model_);
00651       }
00652     }
00653     if(q.empty()) {
00654       break;
00655     }
00656     t = q.front();
00657     q.pop();
00658   } while (!q.empty());
00659 }
00660 
00661 void planning_models::KinematicModel::getChildJointModels(const KinematicModel::JointModel *parent, 
00662                                                           std::vector<const KinematicModel::JointModel*> &joints) const
00663 {
00664   joints.push_back(parent);
00665   if(parent->child_link_model_) {
00666     getChildJointModels(parent->child_link_model_, joints);
00667   }
00668 }
00669 
00670 std::vector<std::string> 
00671 planning_models::KinematicModel::getChildLinkModelNames(const KinematicModel::LinkModel *parent) const
00672 {
00673   std::vector<const KinematicModel::LinkModel*> links;
00674   getChildLinkModels(parent, links);
00675   std::vector<std::string> ret_vec(links.size());
00676   for(unsigned int i = 0; i < links.size(); i++) {
00677     ret_vec[i] = links[i]->getName();
00678   }
00679   return ret_vec;
00680 }
00681 
00682 std::vector<std::string> 
00683 planning_models::KinematicModel::getChildLinkModelNames(const KinematicModel::JointModel *parent) const
00684 {
00685   std::vector<const KinematicModel::LinkModel*> links;
00686   getChildLinkModels(parent,links);
00687   std::vector<std::string> ret_vec(links.size());
00688   for(unsigned int i = 0; i < links.size(); i++) {
00689     ret_vec[i] = links[i]->getName();
00690   }
00691   return ret_vec;
00692 }
00693 
00694 std::vector<std::string> 
00695 planning_models::KinematicModel::getChildJointModelNames(const KinematicModel::LinkModel *parent) const
00696 {
00697   std::vector<const KinematicModel::JointModel*> joints;
00698   getChildJointModels(parent,joints);
00699   std::vector<std::string> ret_vec(joints.size());
00700   for(unsigned int i = 0; i < joints.size(); i++) {
00701     ret_vec[i] = joints[i]->getName();
00702   }
00703   return ret_vec;
00704 }
00705 
00706 std::vector<std::string> 
00707 planning_models::KinematicModel::getChildJointModelNames(const KinematicModel::JointModel *parent) const
00708 {
00709   std::vector<const KinematicModel::JointModel*> joints;
00710   getChildJointModels(parent,joints);
00711   std::vector<std::string> ret_vec(joints.size());
00712   for(unsigned int i = 0; i < joints.size(); i++) {
00713     ret_vec[i] = joints[i]->getName();
00714   }
00715   return ret_vec;
00716 }
00717 
00718 void planning_models::KinematicModel::clearAllAttachedBodyModels()
00719 {
00720   exclusiveLock();
00721   for(unsigned int i =0; i < link_model_vector_.size(); i++) {
00722     link_model_vector_[i]->clearAttachedBodyModels();
00723   }
00724   exclusiveUnlock();
00725 }
00726 
00727 std::vector<const planning_models::KinematicModel::AttachedBodyModel*> planning_models::KinematicModel::getAttachedBodyModels(void) const
00728 {
00729   std::vector<const planning_models::KinematicModel::AttachedBodyModel*> ret_vec;
00730   for(unsigned int i =0; i < link_model_vector_.size(); i++) {
00731     ret_vec.insert(ret_vec.end(), link_model_vector_[i]->getAttachedBodyModels().begin(),
00732                    link_model_vector_[i]->getAttachedBodyModels().end());
00733   }
00734   return ret_vec;
00735 }
00736 
00737 void planning_models::KinematicModel::clearLinkAttachedBodyModels(const std::string& link_name)
00738 {
00739   exclusiveLock();
00740   if(link_model_map_.find(link_name) == link_model_map_.end()) {
00741     exclusiveUnlock();
00742     return;
00743   }
00744   link_model_map_[link_name]->clearAttachedBodyModels();
00745   exclusiveUnlock();
00746 }
00747 
00748 void planning_models::KinematicModel::replaceAttachedBodyModels(const std::string& link_name, 
00749                                                                std::vector<AttachedBodyModel*>& attached_body_vector)
00750 {
00751   exclusiveLock();
00752   if(link_model_map_.find(link_name) == link_model_map_.end())
00753   {
00754     ROS_WARN_STREAM("Model has no link named " << link_name << ".  This is probably going to introduce a memory leak");
00755     exclusiveUnlock();
00756     return;
00757   }
00758   link_model_map_[link_name]->replaceAttachedBodyModels(attached_body_vector);
00759   exclusiveUnlock();
00760 }
00761 
00762 void planning_models::KinematicModel::clearLinkAttachedBodyModel(const std::string& link_name, 
00763                                                                  const std::string& att_name)
00764 {
00765   exclusiveLock();
00766   if(link_model_map_.find(link_name) == link_model_map_.end()) {
00767     exclusiveUnlock();
00768     return;
00769   }
00770   link_model_map_[link_name]->clearLinkAttachedBodyModel(att_name);
00771   exclusiveUnlock();
00772 }
00773 
00774 void planning_models::KinematicModel::addAttachedBodyModel(const std::string& link_name, 
00775                                                            planning_models::KinematicModel::AttachedBodyModel* ab)
00776 {
00777   exclusiveLock();
00778   if(link_model_map_.find(link_name) == link_model_map_.end()) {
00779     ROS_WARN_STREAM("Model has no link named " << link_name << " to attach body to.  This is probably going to introduce a memory leak");
00780     exclusiveUnlock();
00781     return;
00782   }
00783   link_model_map_[link_name]->addAttachedBodyModel(ab);
00784   exclusiveUnlock();
00785 }
00786 
00787 
00788 /* ------------------------ JointModel ------------------------ */
00789 
00790 planning_models::KinematicModel::JointModel::JointModel(const std::string& n) :
00791   name_(n), parent_link_model_(NULL), child_link_model_(NULL)
00792 {
00793 }
00794 
00795 void planning_models::KinematicModel::JointModel::initialize(const std::vector<std::string>& local_joint_names,
00796                                                              const MultiDofConfig* config)
00797 {
00798   for(std::vector<std::string>::const_iterator it = local_joint_names.begin();
00799       it != local_joint_names.end();
00800       it++) {
00801     joint_state_equivalents_.insert(js_type::value_type(*it,*it));
00802   } 
00803   if(config != NULL) {
00804     for(std::map<std::string, std::string>::const_iterator it = config->name_equivalents.begin();
00805         it != config->name_equivalents.end();
00806         it++) {
00807       js_type::left_iterator lit = joint_state_equivalents_.left.find(it->first);
00808       if(lit != joint_state_equivalents_.left.end()) {
00809         joint_state_equivalents_.left.replace_data(lit, it->second);
00810       }
00811     }
00812     parent_frame_id_ = config->parent_frame_id;
00813     child_frame_id_ = config->child_frame_id;
00814   } 
00815   unsigned int i = 0;
00816   for(std::vector<std::string>::const_iterator it = local_joint_names.begin();
00817       it != local_joint_names.end();
00818       it++, i++) {
00819     computation_order_map_index_[i] = joint_state_equivalents_.left.at(*it);
00820   }
00821 
00822   for(js_type::iterator it = joint_state_equivalents_.begin();
00823       it != joint_state_equivalents_.end();
00824       it++) {
00825     setVariableBounds(it->right,-DBL_MAX,DBL_MAX);
00826   }
00827 }
00828 
00829 planning_models::KinematicModel::JointModel::JointModel(const JointModel* joint) {
00830   name_ = joint->name_;
00831   parent_frame_id_  = joint->parent_frame_id_;
00832   child_frame_id_  = joint->child_frame_id_;
00833   joint_state_equivalents_ = joint->joint_state_equivalents_;
00834   joint_state_bounds_ = joint->joint_state_bounds_;
00835 }
00836 
00837 planning_models::KinematicModel::JointModel::~JointModel(void)
00838 {
00839   if (child_link_model_)
00840     delete child_link_model_;
00841 }
00842 
00843 std::string planning_models::KinematicModel::JointModel::getEquiv(const std::string& name) const {
00844   js_type::left_const_iterator lit = joint_state_equivalents_.left.find(name);
00845   if(lit != joint_state_equivalents_.left.end()) {
00846     return lit->second;
00847   } else {
00848     return "";
00849   }
00850 }
00851 
00852 bool planning_models::KinematicModel::JointModel::setVariableBounds(const std::string& variable, double low, double high) {
00853   if(joint_state_equivalents_.right.find(variable) == joint_state_equivalents_.right.end()) {
00854     ROS_WARN_STREAM("Can't find variable " << variable << " to set bounds");
00855     return false;
00856   }
00857   joint_state_bounds_[joint_state_equivalents_.right.at(variable)] = std::pair<double,double>(low, high);
00858   return true;
00859 }
00860 
00861 bool planning_models::KinematicModel::JointModel::getVariableBounds(const std::string& variable, std::pair<double, double>& bounds) const{
00862   if(joint_state_equivalents_.right.find(variable) == joint_state_equivalents_.right.end()) {
00863     ROS_WARN_STREAM("Can't find variable " << variable << " to get bounds");
00864     return false;
00865   }
00866   std::string config_name = joint_state_equivalents_.right.find(variable)->second;
00867   if(joint_state_bounds_.find(config_name) == joint_state_bounds_.end()) {
00868     ROS_WARN_STREAM("No joint bounds for " << config_name);
00869     return false;
00870   }
00871   bounds = joint_state_bounds_.find(config_name)->second;
00872   return true;
00873 }
00874 
00875 void planning_models::KinematicModel::JointModel::getVariableDefaultValuesGivenBounds(std::map<std::string, double>& ret_map) const
00876 {
00877   for(std::map<std::string, std::pair<double, double> >::const_iterator it = joint_state_bounds_.begin();
00878       it != joint_state_bounds_.end();
00879       it++) {
00880     //zero is a valid value
00881     if(it->second.first <= 0.0 && it->second.second >= 0.0) {
00882       ret_map[it->first] = 0.0;
00883     } else {
00884       ret_map[it->first] = (it->second.first + it->second.second)/2.0;
00885     }
00886   }
00887 }
00888 
00889 bool planning_models::KinematicModel::JointModel::isValueWithinVariableBounds(const std::string& variable, const double& value, bool& within_bounds) const 
00890 {
00891   std::pair<double, double> bounds;
00892   if(!getVariableBounds(variable, bounds)) {
00893     return false;
00894   }
00895   if(value < bounds.first || value > bounds.second) {
00896     ROS_DEBUG_STREAM("Violates bounds: Value " << value << " lower " << bounds.first << " upper " << bounds.second);
00897     within_bounds = false;
00898   } else {
00899     ROS_DEBUG_STREAM("Satisfies bounds: Value " << value << " lower " << bounds.first << " upper " << bounds.second);
00900     within_bounds = true;
00901   }
00902   return true;
00903 }
00904 
00905 planning_models::KinematicModel::PlanarJointModel::PlanarJointModel(const std::string& name, const MultiDofConfig* multi_dof_config) 
00906   : JointModel(name)
00907 {
00908   if(multi_dof_config == NULL) {
00909     ROS_WARN("Planar joint needs a config");
00910     return;
00911   }
00912   std::vector<std::string> local_names;
00913   local_names.push_back("planar_x");
00914   local_names.push_back("planar_y");
00915   local_names.push_back("planar_th");
00916   initialize(local_names, multi_dof_config);
00917   setVariableBounds(getEquiv("planar_x"),-DBL_MAX,DBL_MAX);
00918   setVariableBounds(getEquiv("planar_y"),-DBL_MAX,DBL_MAX);
00919   setVariableBounds(getEquiv("planar_th"),-M_PI,M_PI);
00920 }
00921 
00922 tf::Transform planning_models::KinematicModel::PlanarJointModel::computeTransform(const std::vector<double>& joint_values) const 
00923 {
00924   tf::Transform variable_transform;
00925   variable_transform.setIdentity();
00926   if(joint_values.size() != 3) {
00927     ROS_ERROR("Planar joint given too few values");
00928     return variable_transform;
00929   }
00930   variable_transform.setOrigin(tf::Vector3(joint_values[0],
00931                                          joint_values[1],
00932                                          0.0));
00933   variable_transform.setRotation(tf::Quaternion(tf::Vector3(0.0, 0.0, 1.0),
00934                                               joint_values[2]));
00935   return variable_transform;
00936 }
00937 
00938 std::vector<double> planning_models::KinematicModel::PlanarJointModel::computeJointStateValues(const tf::Transform& transform) const 
00939 {
00940   std::vector<double> ret;
00941   ret.push_back(transform.getOrigin().x());
00942   ret.push_back(transform.getOrigin().y());
00943   ret.push_back(transform.getRotation().getAngle()*transform.getRotation().getAxis().z());
00944   return ret;
00945 }
00946 
00947 planning_models::KinematicModel::FloatingJointModel::FloatingJointModel(const std::string& name, 
00948                                                                         const MultiDofConfig* multi_dof_config) 
00949   : JointModel(name)
00950 {
00951   if(multi_dof_config == NULL) {
00952     ROS_WARN("Planar joint needs a config");
00953     return;
00954   }
00955   std::vector<std::string> local_names;
00956   local_names.push_back("floating_trans_x");
00957   local_names.push_back("floating_trans_y");
00958   local_names.push_back("floating_trans_z");
00959   local_names.push_back("floating_rot_x");
00960   local_names.push_back("floating_rot_y");
00961   local_names.push_back("floating_rot_z");
00962   local_names.push_back("floating_rot_w");
00963   initialize(local_names, multi_dof_config);
00964 
00965   setVariableBounds(getEquiv("floating_trans_x"),-DBL_MAX,DBL_MAX);
00966   setVariableBounds(getEquiv("floating_trans_y"),-DBL_MAX,DBL_MAX);
00967   setVariableBounds(getEquiv("floating_trans_z"),-DBL_MAX,DBL_MAX);  
00968   setVariableBounds(getEquiv("floating_rot_x"),-1.0,1.0);
00969   setVariableBounds(getEquiv("floating_rot_y"),-1.0,1.0);
00970   setVariableBounds(getEquiv("floating_rot_z"),-1.0,1.0);
00971   setVariableBounds(getEquiv("floating_rot_w"),-1.0,1.0);
00972 }
00973 
00974 tf::Transform planning_models::KinematicModel::FloatingJointModel::computeTransform(const std::vector<double>& joint_values) const 
00975 {
00976   tf::Transform variable_transform;
00977   variable_transform.setIdentity();
00978   if(joint_values.size() != 7) {
00979     ROS_ERROR("Floating joint given too few values");
00980     return variable_transform;
00981   }
00982   variable_transform.setOrigin(tf::Vector3(joint_values[0], joint_values[1], joint_values[2]));
00983   variable_transform.setRotation(tf::Quaternion(joint_values[3], joint_values[4], joint_values[5], joint_values[6]));
00984   if(joint_values[3] == 0.0 && joint_values[4] == 0.0 && joint_values[5] == 0.0 && joint_values[6] == 0.0) {
00985     ROS_INFO("Setting quaternion with all zeros");
00986   }                  
00987   return variable_transform;
00988 }
00989 
00990 std::vector<double> planning_models::KinematicModel::FloatingJointModel::computeJointStateValues(const tf::Transform& transform) const 
00991 {
00992   std::vector<double> ret;
00993   ret.push_back(transform.getOrigin().x());
00994   ret.push_back(transform.getOrigin().y());
00995   ret.push_back(transform.getOrigin().z());
00996   ret.push_back(transform.getRotation().x());
00997   ret.push_back(transform.getRotation().y());
00998   ret.push_back(transform.getRotation().z());
00999   ret.push_back(transform.getRotation().w());
01000   return ret;
01001 }
01002 
01003 void planning_models::KinematicModel::FloatingJointModel::getVariableDefaultValuesGivenBounds(std::map<std::string, double>& ret_map) const 
01004 {
01005   //the only reasonable default quaternion is (0,0,0,1) - doesn't matter what the bounds are
01006   ret_map[getEquiv("floating_trans_x")] = 0.0;
01007   ret_map[getEquiv("floating_trans_y")] = 0.0;
01008   ret_map[getEquiv("floating_trans_z")] = 0.0;
01009   ret_map[getEquiv("floating_rot_x")] = 0.0;
01010   ret_map[getEquiv("floating_rot_y")] = 0.0;
01011   ret_map[getEquiv("floating_rot_z")] = 0.0;
01012   ret_map[getEquiv("floating_rot_w")] = 1.0;
01013 }
01014 
01015 planning_models::KinematicModel::PrismaticJointModel::PrismaticJointModel(const std::string& name,
01016                                                                           const MultiDofConfig* multi_dof_config) 
01017   : JointModel(name), 
01018     axis_(0.0, 0.0, 0.0) 
01019 {
01020   std::vector<std::string> local_names(1,name);
01021   initialize(local_names, multi_dof_config);
01022 }
01023 
01024 tf::Transform planning_models::KinematicModel::PrismaticJointModel::computeTransform(const std::vector<double>& joint_values) const 
01025 {
01026   tf::Transform variable_transform;
01027   variable_transform.setIdentity();
01028   if(joint_values.size() != 1) {
01029     ROS_ERROR("Prismatic joint given wrong number of values");
01030     return variable_transform;
01031   }
01032   variable_transform.setOrigin(axis_*joint_values[0]);
01033   return variable_transform;
01034 }
01035 
01036 std::vector<double> planning_models::KinematicModel::PrismaticJointModel::computeJointStateValues(const tf::Transform& transform) const
01037 {
01038   std::vector<double> ret;
01039   ret.push_back(transform.getOrigin().dot(axis_));
01040   return ret;
01041 }
01042 
01043 planning_models::KinematicModel::RevoluteJointModel::RevoluteJointModel(const std::string& name,
01044                                                               const MultiDofConfig* multi_dof_config) 
01045   : JointModel(name),
01046     axis_(0.0, 0.0, 0.0), 
01047     continuous_(false)
01048 {
01049   std::vector<std::string> local_names(1,name);
01050   initialize(local_names, multi_dof_config);
01051 }
01052 
01053 tf::Transform planning_models::KinematicModel::RevoluteJointModel::computeTransform(const std::vector<double>& joint_values) const 
01054 {
01055   tf::Transform variable_transform;
01056   variable_transform.setIdentity();
01057   if(joint_values.size() != 1) {
01058     ROS_ERROR("Revolute joint given wrong number of values");
01059     return variable_transform;
01060   }
01061   double val = joint_values.front();
01062   if(continuous_) {
01063     val = angles::normalize_angle(val);
01064   }
01065   variable_transform.setRotation(tf::Quaternion(axis_,val));
01066   return variable_transform;
01067 }
01068 
01069 std::vector<double> planning_models::KinematicModel::RevoluteJointModel::computeJointStateValues(const tf::Transform& transform) const
01070 {
01071   std::vector<double> ret;
01072   ROS_DEBUG_STREAM("Transform angle is " << transform.getRotation().getAngle() 
01073                    << " axis x " << transform.getRotation().getAxis().x()
01074                    << " axis y " << transform.getRotation().getAxis().y()
01075                    << " axis z " << transform.getRotation().getAxis().z());
01076   double val = transform.getRotation().getAngle()*transform.getRotation().getAxis().dot(axis_);
01077   while(val < -M_PI) {
01078     if(val < -M_PI) {
01079       val += 2*M_PI;
01080     }
01081   }
01082   while(val > M_PI) {
01083     if(val > M_PI) {
01084       val -= 2*M_PI;
01085     }
01086   }
01087   ret.push_back(val);
01088   return ret;
01089 }
01090 
01091 bool planning_models::KinematicModel::RevoluteJointModel::isValueWithinVariableBounds(const std::string& variable, 
01092                                                                                       const double& value, 
01093                                                                                       bool& within_bounds) const 
01094 {
01095   if(!continuous_) {
01096     return JointModel::isValueWithinVariableBounds(variable, value, within_bounds);
01097   }
01098   if(!hasVariable(variable)) {
01099     return false;
01100   }
01101   within_bounds = true;
01102   return true;
01103 }
01104 
01105 /* ------------------------ LinkModel ------------------------ */
01106 
01107 planning_models::KinematicModel::LinkModel::LinkModel(const KinematicModel* kinematic_model) : 
01108   kinematic_model_(kinematic_model),
01109   parent_joint_model_(NULL), 
01110   shape_(NULL)
01111 {
01112   joint_origin_transform_.setIdentity();
01113   collision_origin_transform_.setIdentity();
01114 }
01115 
01116 planning_models::KinematicModel::LinkModel::LinkModel(const LinkModel* link_model) :
01117   name_(link_model->name_), 
01118   kinematic_model_(link_model->kinematic_model_),
01119   joint_origin_transform_(link_model->joint_origin_transform_),
01120   collision_origin_transform_(link_model->collision_origin_transform_)
01121 {
01122   if(link_model->shape_) {
01123     shape_ = shapes::cloneShape(link_model->shape_);
01124   } else {
01125     shape_ = NULL;
01126   }
01127   for (unsigned int i = 0 ; i < link_model->attached_body_models_.size() ; ++i)
01128   {
01129     std::vector<shapes::Shape*> shapes;
01130     for(unsigned int j = 0; j < link_model->attached_body_models_[i]->getShapes().size(); j++) {
01131       shapes.push_back(shapes::cloneShape(link_model->attached_body_models_[i]->getShapes()[j]));
01132     }
01133     AttachedBodyModel *ab = new AttachedBodyModel(this, 
01134                                                   link_model->attached_body_models_[i]->getName(),
01135                                                   link_model->attached_body_models_[i]->getAttachedBodyFixedTransforms(),
01136                                                   link_model->attached_body_models_[i]->getTouchLinks(),
01137                                                   shapes);
01138     attached_body_models_.push_back(ab);
01139   }
01140 }
01141 
01142 planning_models::KinematicModel::LinkModel::~LinkModel(void)
01143 {
01144   if (shape_)
01145     delete shape_;
01146   for (unsigned int i = 0 ; i < child_joint_models_.size() ; ++i)
01147     delete child_joint_models_[i];
01148   for (unsigned int i = 0 ; i < attached_body_models_.size() ; ++i)
01149     delete attached_body_models_[i];
01150 }
01151 
01152 void planning_models::KinematicModel::LinkModel::clearAttachedBodyModels() 
01153 {
01154   //assumes exclusive lock has been granted
01155   for (unsigned int i = 0 ; i < attached_body_models_.size() ; ++i)
01156     delete attached_body_models_[i];
01157   attached_body_models_.clear();
01158 }
01159 
01160 void planning_models::KinematicModel::LinkModel::replaceAttachedBodyModels(std::vector<AttachedBodyModel*>& attached_body_vector) 
01161 {
01162   //assumes exclusive lock has been granted
01163   for (unsigned int i = 0 ; i < attached_body_models_.size() ; ++i)
01164     delete attached_body_models_[i];
01165   attached_body_models_.clear();
01166 
01167   attached_body_models_ = attached_body_vector;
01168 }
01169 
01170 void planning_models::KinematicModel::LinkModel::clearLinkAttachedBodyModel(const std::string& att_name) 
01171 {
01172   for(std::vector<AttachedBodyModel*>::iterator it = attached_body_models_.begin();
01173       it != attached_body_models_.end();
01174       it++) {
01175     if((*it)->getName() == att_name) {
01176       delete (*it);
01177       attached_body_models_.erase(it);
01178       return;
01179     }
01180   }
01181 }
01182 
01183 void planning_models::KinematicModel::LinkModel::addAttachedBodyModel(planning_models::KinematicModel::AttachedBodyModel* ab)
01184 {
01185   attached_body_models_.push_back(ab);
01186 }
01187 
01188 /* ------------------------ AttachedBodyModel ------------------------ */
01189 
01190 planning_models::KinematicModel::AttachedBodyModel::AttachedBodyModel(const LinkModel *link, 
01191                                                                       const std::string& nid,
01192                                                                       const std::vector<tf::Transform>& attach_trans,
01193                                                                       const std::vector<std::string>& touch_links,
01194                                                                       std::vector<shapes::Shape*>& shapes)
01195 
01196   : attached_link_model_(link), 
01197     id_(nid)
01198 {
01199   attach_trans_ = attach_trans;
01200   touch_links_ = touch_links;
01201   shapes_ = shapes;
01202 }
01203 
01204 planning_models::KinematicModel::AttachedBodyModel::~AttachedBodyModel(void)
01205 {
01206   for(unsigned int i = 0; i < shapes_.size(); i++) {
01207     delete shapes_[i];
01208   }
01209 }
01210 
01211 /* ------------------------ JointModelGroup ------------------------ */
01212 planning_models::KinematicModel::JointModelGroup::JointModelGroup(const std::string& group_name,
01213                                                                   const std::vector<const JointModel*> &group_joints,
01214                                                                   const std::vector<const JointModel*> &fixed_group_joints,
01215                                                                   const KinematicModel* parent_model) :
01216   name_(group_name)
01217 {
01218   ROS_DEBUG_STREAM("Group " << group_name);
01219 
01220   joint_model_vector_ = group_joints;
01221   fixed_joint_model_vector_ = fixed_group_joints;
01222   joint_model_name_vector_.resize(group_joints.size());
01223 
01224   ROS_DEBUG_STREAM("Joints:");    
01225   for (unsigned int i = 0 ; i < group_joints.size() ; ++i)
01226   {
01227     ROS_DEBUG_STREAM(group_joints[i]->getName());
01228     joint_model_name_vector_[i] = group_joints[i]->getName();
01229     joint_model_map_[group_joints[i]->getName()] = group_joints[i];
01230   }
01231 
01232   ROS_DEBUG_STREAM("Fixed joints:");    
01233   for (unsigned int i = 0 ; i < fixed_joint_model_vector_.size() ; ++i)
01234   {
01235     ROS_DEBUG_STREAM(fixed_joint_model_vector_[i]->getName());
01236   }
01237 
01238   std::vector<const JointModel*> all_joints = group_joints;
01239   all_joints.insert(all_joints.end(), fixed_group_joints.begin(), fixed_group_joints.end());
01240 
01241   //now we need to find all the set of joints within this group
01242   //that root distinct subtrees
01243   std::map<std::string, bool> is_root;
01244   for (unsigned int i = 0 ; i < all_joints.size() ; ++i)
01245   {
01246     bool found = false;
01247     const JointModel *joint = all_joints[i];
01248     //if we find that an ancestor is also in the group, then the joint is not a root
01249     while (joint->getParentLinkModel() != NULL)
01250     {
01251       joint = joint->getParentLinkModel()->getParentJointModel();
01252       if (hasJointModel(joint->name_))
01253       {
01254         found = true;
01255       }
01256     }
01257         
01258     if(!found) {
01259       joint_roots_.push_back(all_joints[i]);
01260       is_root[all_joints[i]->getName()] = true;
01261     } else {
01262       is_root[all_joints[i]->getName()] = false;
01263     }
01264   }
01265 
01266   //now we need to make another pass for group links
01267   std::set<const LinkModel*> group_links_set;
01268   for(unsigned int i = 0; i < all_joints.size(); i++) {
01269     const JointModel *joint = all_joints[i];
01270     //push children in directly
01271     group_links_set.insert(joint->getChildLinkModel());
01272     while (joint->getParentLinkModel() != NULL)
01273     {
01274       if(is_root.find(joint->getName()) != is_root.end() &&
01275          is_root[joint->getName()]) {
01276         break;
01277       }
01278       group_links_set.insert(joint->getParentLinkModel());
01279       joint = joint->getParentLinkModel()->getParentJointModel();
01280     }
01281   }
01282 
01283   ROS_DEBUG("Group links:");
01284   for(std::set<const LinkModel*>::iterator it = group_links_set.begin();
01285       it != group_links_set.end();
01286       it++) {
01287     group_link_model_vector_.push_back(*it);
01288     ROS_DEBUG_STREAM((*it)->getName());
01289   }
01290   //these subtrees are distinct, so we can stack their updated links on top of each other
01291   for (unsigned int i = 0 ; i < joint_roots_.size() ; ++i)
01292   {
01293     std::vector<const LinkModel*> links;
01294     parent_model->getChildLinkModels(joint_roots_[i], links);
01295     updated_link_model_vector_.insert(updated_link_model_vector_.end(), links.begin(), links.end());
01296   }
01297 }
01298 
01299 planning_models::KinematicModel::JointModelGroup::~JointModelGroup(void)
01300 {
01301 }
01302 
01303 bool planning_models::KinematicModel::JointModelGroup::hasJointModel(const std::string &joint) const
01304 {
01305   return joint_model_map_.find(joint) != joint_model_map_.end();
01306 }
01307 
01308 const planning_models::KinematicModel::JointModel* planning_models::KinematicModel::JointModelGroup::getJointModel(const std::string &name)
01309 {
01310   if(!hasJointModel(name)) return NULL;
01311   return joint_model_map_.find(name)->second;
01312 }
01313 


planning_models
Author(s): Ioan Sucan/isucan@willowgarage.com
autogenerated on Mon Dec 2 2013 12:33:37