UrdfTraverser.cpp
Go to the documentation of this file.
00001 
00031 #include <urdf_traverser/Helpers.h>
00032 #include <urdf_traverser/Functions.h>
00033 #include <urdf_traverser/UrdfTraverser.h>
00034 #include <urdf_traverser/PrintModel.h>
00035 #include <urdf_traverser/JointNames.h>
00036 #include <urdf_traverser/DependencyOrderedJoints.h>
00037 
00038 #include <string>
00039 #include <ros/ros.h>
00040 #include <ros/package.h>
00041 
00042 #include <map>
00043 #include <vector>
00044 #include <set>
00045 #include <fstream>
00046 #include <algorithm>
00047 
00048 #define RAD_TO_DEG 180/M_PI
00049 
00050 using urdf_traverser::UrdfTraverser;
00051 
00052 std::string UrdfTraverser::getRootLinkName() const
00053 {
00054     LinkConstPtr root = this->model->getRoot();
00055     if (!root)
00056     {
00057         ROS_ERROR("Loaded model has no root");
00058         return "";
00059     }
00060     return root->name;
00061 }
00062 
00063 bool UrdfTraverser::printModel(const std::string& fromLink, bool verbose)
00064 {
00065     return urdf_traverser::printModel(*this, fromLink, verbose);
00066 }
00067 
00068 bool UrdfTraverser::printModel(bool verbose)
00069 {
00070     return urdf_traverser::printModel(*this, verbose);
00071 }
00072 
00073 
00074 bool UrdfTraverser::getDependencyOrderedJoints(std::vector<JointPtr>& result,
00075         const JointPtr& from_joint, bool allowSplits, bool onlyActive)
00076 {
00077     return urdf_traverser::getDependencyOrderedJoints(*this, result, from_joint, allowSplits, onlyActive);
00078 }
00079 
00080 bool UrdfTraverser::getDependencyOrderedJoints(std::vector<JointPtr>& result, const LinkPtr& from_link,
00081         bool allowSplits, bool onlyActive)
00082 {
00083     return urdf_traverser::getDependencyOrderedJoints(*this, result, from_link->name, allowSplits, onlyActive);
00084 }
00085 
00086 
00087 bool UrdfTraverser::getJointNames(const std::string& fromLink,
00088                                   const bool skipFixed, std::vector<std::string>& result)
00089 {
00090     std::string rootLink = fromLink;
00091     if (rootLink.empty())
00092     {
00093         rootLink = getRootLinkName();
00094     }
00095 
00096     // get root link
00097     LinkPtr root_link;
00098     this->model->getLink(rootLink, root_link);
00099     if (!root_link)
00100     {
00101         ROS_ERROR("no root link %s", fromLink.c_str());
00102         return false;
00103     }
00104 
00105     return urdf_traverser::getJointNames(*this, rootLink, skipFixed, result);
00106 }
00107 
00108 int UrdfTraverser::getChildJoint(const JointPtr& joint, JointPtr& child)
00109 {
00110     LinkPtr childLink = getChildLink(joint);
00111     if (!childLink)
00112     {
00113         ROS_ERROR("Consistency: all joints must have child links");
00114         return -2;
00115     }
00116     if (childLink->child_joints.size() > 1)
00117     {
00118         return -1;
00119     }
00120     if (childLink->child_joints.empty())
00121     {
00122         // this is the end link, and we've defined the end
00123         // frame to be at the same location as the last joint,
00124         // so no rotation should be needed?
00125         return 0;
00126     }
00127     // there must be only one joint
00128     child = childLink->child_joints.front();
00129     return 1;
00130 }
00131 
00132 urdf_traverser::LinkPtr UrdfTraverser::getChildLink(const JointConstPtr& joint)
00133 {
00134     LinkPtr childLink;
00135     model->getLink(joint->child_link_name, childLink);
00136     return childLink;
00137 }
00138 
00139 urdf_traverser::LinkConstPtr UrdfTraverser::readChildLink(const JointConstPtr& joint) const
00140 {
00141     LinkPtr childLink;
00142     model->getLink(joint->child_link_name, childLink);
00143     return childLink;
00144 }
00145 
00146 urdf_traverser::JointPtr UrdfTraverser::getParentJoint(const JointConstPtr& joint)
00147 {
00148     LinkConstPtr parentLink = model->getLink(joint->parent_link_name);
00149     if (!parentLink) return JointPtr();
00150     return parentLink->parent_joint;
00151 }
00152 
00153 urdf_traverser::JointConstPtr UrdfTraverser::readParentJoint(const JointConstPtr& joint) const
00154 {
00155     LinkConstPtr parentLink = model->getLink(joint->parent_link_name);
00156     if (!parentLink) return JointPtr();
00157     return parentLink->parent_joint;
00158 }
00159 
00160 
00161 
00162 bool UrdfTraverser::hasChildLink(const LinkConstPtr& link, const std::string& childName) const
00163 {
00164     for (unsigned int i = 0; i < link->child_links.size(); ++i)
00165     {
00166         LinkPtr childLink = link->child_links[i];
00167         if (childLink->name == childName) return true;
00168     }
00169     return false;
00170 }
00171 
00172 
00173 int UrdfTraverser::traverseTreeTopDown(const std::string& linkName, boost::function< int(RecursionParamsPtr&)> link_cb,
00174                                        RecursionParamsPtr& params, bool includeLink)
00175 {
00176     LinkPtr link = getLink(linkName);
00177     if (!link)
00178     {
00179         ROS_ERROR_STREAM("Could not get Link " << linkName);
00180         return -1;
00181     }
00182     return traverseTreeTopDown(link, link_cb, params, includeLink, 0);
00183 }
00184 
00185 int UrdfTraverser::traverseTreeTopDown(const LinkPtr& link, boost::function< int(RecursionParamsPtr&)> link_cb,
00186                                        RecursionParamsPtr& params, bool includeLink, unsigned int level)
00187 {
00188     if (includeLink)
00189     {
00190         params->setParams(link, level);
00191         int link_ret = link_cb(params);
00192         if (link_ret <= 0)
00193         {
00194             // stopping traversal
00195             return link_ret;
00196         }
00197     }
00198 
00199     level += 1;
00200     for (std::vector<LinkPtr>::const_iterator child = link->child_links.begin();
00201             child != link->child_links.end(); child++)
00202     {
00203         LinkPtr childLink = *child;
00204         if (childLink)
00205         {
00206             params->setParams(childLink, level);
00207             int link_ret = link_cb(params);
00208             if (link_ret <= 0)
00209             {
00210                 // stopping traversal
00211                 return link_ret;
00212             }
00213 
00214             // recurse down the tree
00215             int ret = traverseTreeTopDown(childLink, link_cb, params, false, level);
00216             if (ret < 0)
00217             {
00218                 ROS_ERROR("Error parsing branch of %s", childLink->name.c_str());
00219                 return -1;
00220             }
00221         }
00222         else
00223         {
00224             ROS_ERROR("root link: %s has a null child!", link->name.c_str());
00225             return false;
00226         }
00227     }
00228     return 1;
00229 };
00230 
00231 int UrdfTraverser::traverseTreeBottomUp(const std::string& linkName, boost::function< int(RecursionParamsPtr&)> link_cb,
00232                                         RecursionParamsPtr& params, bool includeLink)
00233 {
00234     LinkPtr link = getLink(linkName);
00235     if (!link)
00236     {
00237         ROS_ERROR_STREAM("Could not get Link " << linkName);
00238         return -1;
00239     }
00240     return traverseTreeBottomUp(link, link_cb, params, includeLink, 0);
00241 }
00242 
00243 
00244 
00245 int UrdfTraverser::traverseTreeBottomUp(const LinkPtr& link, boost::function<int(RecursionParamsPtr&)> link_cb,
00246                                         RecursionParamsPtr& params, bool includeLink, unsigned int level)
00247 {
00248     std::set<std::string> toTraverse;
00249     for (unsigned int i = 0; i < link->child_links.size(); ++i)
00250     {
00251         LinkPtr childLink = link->child_links[i];
00252         toTraverse.insert(childLink->name);
00253     }
00254 
00255     for (std::set<std::string>::iterator it = toTraverse.begin(); it != toTraverse.end(); ++it)
00256     {
00257         if (!hasChildLink(link, *it))
00258         {
00259             ROS_ERROR_STREAM("Consistency: Link " << link->name << " does not have child " << *it << " any more.");
00260             return -1;
00261         }
00262 
00263         LinkPtr childLink;
00264         this->model->getLink(*it, childLink);
00265 
00266         if (childLink)
00267         {
00268             // ROS_INFO("Traversal into child %s",childLink->name.c_str());
00269             // recurse down the tree
00270             int travRes = traverseTreeBottomUp(childLink, link_cb, params, true, level + 1);
00271             if (travRes == 0)
00272             {
00273                 ROS_INFO("Stopping traversal at %s", childLink->name.c_str());
00274                 return 0;
00275             }
00276             else if (travRes < 0)
00277             {
00278                 ROS_ERROR("Error parsing branch of %s", childLink->name.c_str());
00279                 return -1;
00280             }
00281             // childLink = params->result;
00282         }
00283         else
00284         {
00285             ROS_ERROR("root link: %s has a null child!", link->name.c_str());
00286             return -1;
00287         }
00288     }
00289 
00290     if (!includeLink)
00291     {
00292         return 1;
00293     }
00294     // ROS_INFO("Callback for link %s",link->name.c_str());
00295     params->setParams(link, level);
00296     int cbRet = link_cb(params);
00297     if (cbRet < 0)
00298     {
00299         ROS_ERROR("Error parsing branch of %s", link->name.c_str());
00300         return -1;
00301     }
00302     return cbRet;
00303 }
00304 
00305 
00306 urdf_traverser::LinkPtr UrdfTraverser::getLink(const std::string& name)
00307 {
00308     LinkPtr ptr;
00309     this->model->getLink(name, ptr);
00310     return ptr;
00311 }
00312 
00313 urdf_traverser::LinkConstPtr UrdfTraverser::readLink(const std::string& name) const
00314 {
00315     LinkPtr ptr;
00316     this->model->getLink(name, ptr);
00317     return ptr;
00318 }
00319 
00320 urdf_traverser::JointPtr UrdfTraverser::getJoint(const std::string& name)
00321 {
00322     JointPtr ptr;
00323     if (this->model->joints_.find(name) == this->model->joints_.end()) ptr.reset();
00324     else ptr = this->model->joints_.find(name)->second;
00325     return ptr;
00326 }
00327 
00328 urdf_traverser::JointConstPtr UrdfTraverser::readJoint(const std::string& name) const
00329 {
00330     JointConstPtr ptr;
00331     if (this->model->joints_.find(name) == this->model->joints_.end()) ptr.reset();
00332     else ptr = this->model->joints_.find(name)->second;
00333     return ptr;
00334 }
00335 
00336 
00337 void UrdfTraverser::printJointNames(const std::string& fromLink)
00338 {
00339     std::vector<std::string> jointNames;
00340     if (!getJointNames(fromLink, false, jointNames))
00341     {
00342         ROS_WARN("Could not retrieve joint names to print on screen");
00343     }
00344     else
00345     {
00346         ROS_INFO_STREAM("Joint names starting from " << fromLink << ":");
00347         for (int i = 0; i < jointNames.size(); ++i) ROS_INFO_STREAM(jointNames[i]);
00348         ROS_INFO("---");
00349     }
00350 }
00351 
00352 bool UrdfTraverser::loadModelFromFile(const std::string& urdfFilename)
00353 {
00354     std::string xml_file;
00355     if (!getModelFromFile(urdfFilename, xml_file))
00356     {
00357         ROS_ERROR("Could not load file");
00358         return false;
00359     }
00360 
00361     boost::filesystem::path filePath(urdfFilename);
00362     setModelDirectory(filePath.parent_path().string());
00363     ROS_INFO_STREAM("Setting base model directory to " << modelDir);
00364 
00365     if (!loadModelFromXMLString(xml_file))
00366     {
00367         ROS_ERROR("Could not load file");
00368         return false;
00369     }
00370     return true;
00371 }
00372 
00373 
00374 
00375 bool UrdfTraverser::loadModelFromXMLString(const std::string& xmlString)
00376 {
00377     bool success = model->initString(xmlString);
00378     if (!success)
00379     {
00380         ROS_ERROR("Could not load model from XML string");
00381         return false;
00382     }
00383     return true;
00384 }
00385 
00386 /*bool UrdfTraverser::loadModelFromParameterServer()
00387 {
00388     if (!model->initParam("robot_description")) return false;
00389     isScaled = false;
00390     return true;
00391 }*/
00392 
00393 
00394 bool UrdfTraverser::getModelFromFile(const std::string& filename, std::string& xml_string) const
00395 {
00396     std::fstream xml_file(filename.c_str(), std::fstream::in);
00397     if (xml_file.is_open())
00398     {
00399         while (xml_file.good())
00400         {
00401             std::string line;
00402             std::getline(xml_file, line);
00403             xml_string += (line + "\n");
00404         }
00405         xml_file.close();
00406         return true;
00407     }
00408 
00409     ROS_ERROR("Could not open file [%s] for parsing.", filename.c_str());
00410     return false;
00411 }
00412 
00413 urdf_traverser::EigenTransform UrdfTraverser::getTransform(const LinkPtr& from_link,  const JointPtr& to_joint)
00414 {
00415     LinkPtr link1 = from_link;
00416     LinkPtr link2;
00417     this->model->getLink(to_joint->child_link_name, link2);
00418     if (!link1 || !link2)
00419     {
00420         ROS_ERROR("Invalid joint specifications (%s, %s), first needs parent and second child",
00421                   link1->name.c_str(), link2->name.c_str());
00422     }
00423     return urdf_traverser::getTransform(link1, link2);
00424 }


urdf_traverser
Author(s): Jennifer Buehler
autogenerated on Fri Mar 1 2019 03:38:07