Helpers.cpp
Go to the documentation of this file.
00001 
00031 #include <urdf_traverser/Helpers.h>
00032 
00033 #include <ros/ros.h>
00034 #include <ros/package.h>
00035 
00036 #include <fcntl.h>
00037 #include <fstream>
00038 #include <string>
00039 
00040 #define BOOST_NO_CXX11_SCOPED_ENUMS
00041 #include <boost/filesystem.hpp>
00042 #undef BOOST_NO_CXX11_SCOPED_ENUMS
00043 
00052 void urdf_traverser::helpers::findAndReplace(const std::string& newStr, const std::string& oldStr, const std::string& in, std::string& out)
00053 {
00054     size_t pos = 0;
00055     out = in;
00056     while ((pos = out.find(oldStr, pos)) != std::string::npos)
00057     {
00058         out = out.replace(pos, oldStr.length(), newStr);
00059         pos += newStr.length();
00060     }
00061 }
00062 
00063 void urdf_traverser::helpers::deleteFile(const char* file)
00064 {
00065     std::remove(file);
00066 }
00067 
00068 bool urdf_traverser::helpers::fileExists(const char* file)
00069 {
00070     return boost::filesystem::exists(file);
00071 }
00072 
00073 std::string urdf_traverser::helpers::getFilename(const char* file)
00074 {
00075     boost::filesystem::path dPath(file);
00076     return dPath.filename().string();
00077 }
00078 
00079 std::string urdf_traverser::helpers::getFilenameWithoutExtension(const char* file)
00080 {
00081     boost::filesystem::path dPath(file);
00082     return dPath.stem().string();
00083 }
00084 
00085 
00086 std::string urdf_traverser::helpers::fileExtension(const char* file)
00087 {
00088     boost::filesystem::path dPath(file);
00089     std::string extension = dPath.extension().string();
00090     extension.erase(0, 1);
00091     return extension;
00092 }
00093 
00094 bool urdf_traverser::helpers::directoryExists(const char* dPath)
00095 {
00096     // using boost
00097     return boost::filesystem::exists(dPath);
00098 }
00099 
00100 std::string urdf_traverser::helpers::getPath(const char * file)
00101 {
00102     boost::filesystem::path dPath(file);
00103     return dPath.parent_path().string();
00104 }
00105 
00106 bool urdf_traverser::helpers::makeDirectoryIfNeeded(const char * dPath)
00107 {
00108     if (directoryExists(dPath)) return true;
00109     try
00110     {
00111         boost::filesystem::path dir(dPath);
00112         boost::filesystem::path buildPath;
00113 
00114         for (boost::filesystem::path::iterator it(dir.begin()), it_end(dir.end()); it != it_end; ++it)
00115         {
00116             buildPath /= *it;
00117             //std::cout << buildPath << std::endl;
00118 
00119             if (!boost::filesystem::exists(buildPath) &&
00120                     !boost::filesystem::create_directory(buildPath))
00121             {
00122                 ROS_ERROR_STREAM("Could not create directory " << buildPath);
00123                 return false;
00124             }
00125         }
00126     }
00127     catch (const boost::filesystem::filesystem_error& ex)
00128     {
00129         ROS_ERROR_STREAM(ex.what());
00130         return false;
00131     }
00132     return true;
00133 }
00134 
00135 bool urdf_traverser::helpers::isDirectoryPath(const std::string& path)
00136 {
00137     if (path.empty()) return false;
00138     if ((path == ".") || (path == "..")) return true;
00139     return path[path.length() - 1] == boost::filesystem::path::preferred_separator;
00140 }
00141 
00142 bool urdf_traverser::helpers::getSubdirPath(const std::string& from, const std::string& to, std::string& result)
00143 {
00144     if (!isDirectoryPath(from))
00145     {
00146         ROS_ERROR_STREAM("Base path (" << from << ") must be a directory");
00147         throw std::exception();
00148     }
00149 
00150     if (from == to)
00151     {
00152         result = ".";
00153         return true;
00154     }
00155 
00156     boost::filesystem::path _from(from);
00157     boost::filesystem::path _to(to);
00158 
00159     boost::filesystem::path _absFrom = boost::filesystem::absolute(_from);
00160     boost::filesystem::path _absTo = boost::filesystem::absolute(_to);
00161 
00162     boost::filesystem::path::iterator it(_absFrom.begin());
00163     boost::filesystem::path::iterator it_end(_absFrom.end());
00164     boost::filesystem::path::iterator it2(_absTo.begin());
00165     boost::filesystem::path::iterator it2_end(_absTo.end());
00166     --it_end;  // don't go to last entry, which will be either a '.' or a file
00167     for (; it != it_end; ++it, ++it2)
00168     {
00169         if (it2 == it2_end) return false; // cannot be proper sub-directory
00170         if (it->string() != it2->string())
00171         {
00172             // ROS_INFO_STREAM("Comp: "<<it->string()<<", "<<it2->string());
00173             return false;
00174         }
00175     }
00176 
00177     boost::filesystem::path buildPath;
00178     for (; it2 != it2_end; ++it2)
00179     {
00180         buildPath /= *it2;
00181     }
00182     result = buildPath.string();
00183     // if the path was a directory, remove the last '.' which was inserted
00184     if (!result.empty() && (result[result.length() - 1] == '.'))
00185         result.erase(result.length() - 1, 1);
00186 
00187     // ROS_INFO_STREAM("PATH RESULT: "<<result);
00188 
00189     boost::filesystem::path _res(result);
00190     if (!_res.is_relative())
00191     {
00192         ROS_ERROR_STREAM("Could not correctly construct a relative path, got "
00193                          << result << " (input: " << from << " and " << to << ")");
00194         return false;
00195     }
00196     return true;
00197 }
00198 
00199 void urdf_traverser::helpers::enforceDirectory(std::string& path, bool printWarn)
00200 {
00201     if (path.empty()) return;
00202     if (!isDirectoryPath(path))
00203     {
00204         if (printWarn)
00205             ROS_WARN_STREAM("Path " << path << " supposed to be a directory but does not end with separator. Enforcing.");
00206         path.append(1, boost::filesystem::path::preferred_separator);
00207     }
00208     assert(isDirectoryPath(path));
00209 }
00210 
00211 
00212 std::string urdf_traverser::helpers::replaceAll(const std::string& text, const std::string& from, const std::string& to)
00213 {
00214     // ROS_INFO_STREAM("Replace "<<from<<" with "<<to);
00215     std::string ret = text;
00216     for (size_t start_pos = ret.find(from); start_pos != std::string::npos; start_pos = ret.find(from, start_pos))
00217     {
00218         // ROS_INFO_STREAM("DO replace "<<from<<" with "<<to);
00219         ret.replace(start_pos, from.length(), to);
00220     }
00221     return ret;
00222 }
00223 
00224 int numDirectories(const std::string& path)
00225 {
00226     // ROS_INFO_STREAM("cnt of path "<<path);
00227     int cnt = 0;
00228     boost::filesystem::path _path(path);
00229     boost::filesystem::path::iterator it(_path.begin());
00230     boost::filesystem::path::iterator it_end(_path.end());
00231     for (; it != it_end; ++it)
00232     {
00233         // ROS_INFO_STREAM(it->string());
00234         // if (it->string()==".") continue;  // because "./" leads to a count of 1 too but should be 0
00235         ++cnt;
00236     }
00237     if (cnt > 0)
00238     {
00239         // count is always one more, as last directory
00240         // is either '.', or it is a file which doesn't count
00241         --cnt;
00242     }
00243     // ROS_INFO_STREAM("Res: "<<cnt);
00244     return cnt;
00245 }
00246 
00247 std::string urdf_traverser::helpers::getDirectory(const std::string& path)
00248 {
00249     if (urdf_traverser::helpers::isDirectoryPath(path)) return path; // already ends with '/'
00250     // does not end with '/' so it must be a file: get the parent
00251     boost::filesystem::path _path(path);
00252     std::string ret = _path.parent_path().string();
00253     // enforce notation to be a directory as we now know it is one
00254     urdf_traverser::helpers::enforceDirectory(ret, false);
00255     return ret;
00256 }
00257 
00258 std::string urdf_traverser::helpers::getDirectoryName(const std::string& path)
00259 {
00260     std::string dir = getDirectory(path);
00261     // dir will now be a directory (enforced to end with / by getDirectory()).
00262     // So parent_path will return path to the parent directory where it looks
00263     // like it was a file.
00264     boost::filesystem::path ret(dir);
00265     return ret.parent_path().filename().string();
00266 }
00267 
00268 
00269 
00270 bool urdf_traverser::helpers::getCommonParentPath(const std::string& p1, const std::string& p2, std::string& result)
00271 {
00272     if (p1.empty() || p2.empty())
00273     {
00274         ROS_ERROR("Both p1 and p2 have to be set in getCommonParentPath()");
00275         return false;
00276     }
00277     boost::filesystem::path __p1(p1);
00278     boost::filesystem::path __p2(p2);
00279     bool correctAbsolute = __p1.is_relative() || __p2.is_relative();
00280 
00281     boost::filesystem::path _p1(boost::filesystem::absolute(__p1));
00282     boost::filesystem::path _p2(boost::filesystem::absolute(__p2));
00283     boost::filesystem::path buildPath;
00284 
00285     boost::filesystem::path::iterator it1(_p1.begin());
00286     boost::filesystem::path::iterator it1_end(_p1.end());
00287     boost::filesystem::path::iterator it2(_p2.begin());
00288     boost::filesystem::path::iterator it2_end(_p2.end());
00289 
00290     int p1Len = numDirectories(p1);
00291     int p2Len = numDirectories(p2);
00292     // ROS_INFO_STREAM("p1: "<<p1<<", p2: "<<p2);
00293     // ROS_INFO_STREAM("p1: "<<p1Len<<", p2: "<<p2Len);
00294     if (p2Len > p1Len)
00295     {
00296         //swap around paths
00297         boost::filesystem::path::iterator tmp(it2);
00298         it2 = it1;
00299         it1 = tmp;
00300         tmp = it2_end;
00301         it2_end = it1_end;
00302         it1_end = tmp;
00303     }
00304 
00305     --it1_end;  // make sure the iteration goes only until the previous-last
00306     // entry, because the last entry is either '.' or a filename
00307     for (; it1 != it1_end; ++it1, ++it2)
00308     {
00309         // ROS_INFO_STREAM("Comp "<<it1->string()<<", 2 "<<it2->string());
00310         if ((it2 == it2_end)
00311                 || (*it1 != *it2))
00312         {
00313             break;
00314         }
00315 
00316         // append the directory
00317         buildPath /= *it1;
00318 
00319         // std::cout << buildPath.string() << std::endl;
00320     }
00321     if (!buildPath.empty())
00322     {
00323         result = buildPath.string();
00324         // make sure notation ends with separator.
00325         // Last element *will* be directory as no files
00326         // have been added in the loop.
00327         enforceDirectory(result, false);
00328         // If the current directory was used to build an absolute path, remove it again.
00329         if (correctAbsolute)
00330         {
00331             std::string currDir = boost::filesystem::current_path().string();
00332             urdf_traverser::helpers::enforceDirectory(currDir, false);
00333             if (!urdf_traverser::helpers::getSubdirPath(currDir, result, result))
00334             {
00335                 ROS_ERROR_STREAM("Could not remove temporarily created current directory for absolute path");
00336                 return false;
00337             }
00338         }
00339         return true;
00340     }
00341     return false;
00342 }
00343 
00344 
00345 
00346 bool urdf_traverser::helpers::getCommonParentPath(const std::set<std::string>& allFiles, std::string& result)
00347 {
00348     if (allFiles.empty())
00349     {
00350         ROS_ERROR("Cannot get common path of empty set");
00351         return false;
00352     }
00353     std::set<std::string>::const_iterator it = allFiles.begin();
00354     std::string commonPath = urdf_traverser::helpers::getDirectory(*it);
00355     ++it;
00356     // ROS_INFO_STREAM("Init cPath: "<<commonPath);
00357     while (it != allFiles.end())
00358     {
00359         std::string dir = urdf_traverser::helpers::getDirectory(*it);
00360         if (!getCommonParentPath(commonPath, dir, commonPath))
00361         {
00362 
00363             ROS_ERROR_STREAM("There is no root between " <<
00364                              dir << " and " << commonPath << ", cannot determine common parent!");
00365         }
00366         // ROS_INFO_STREAM("CPath: "<<commonPath);
00367         ++it;
00368     }
00369     result = commonPath;
00370     return true;
00371 }
00372 
00373 bool urdf_traverser::helpers::getRelativeDirectory(const std::string& path, const std::string& relTo, std::string& result)
00374 {
00375     // ROS_INFO_STREAM("Get relative dir of "<<path<<" to "<<relTo);
00376 
00377     boost::filesystem::path _path(boost::filesystem::absolute(path));
00378     boost::filesystem::path _relTo(boost::filesystem::absolute(relTo));
00379 
00380     std::string commonParent;
00381     if (!getCommonParentPath(path, relTo, commonParent))
00382     {
00383         ROS_ERROR_STREAM("Directories " << path << " and " << relTo << " have no common parent directory.");
00384         return false;
00385     }
00386     // ROS_INFO_STREAM("Common parent: "<<commonParent);
00387 
00388     // get both directories relative to the common parent directory:
00389 
00390     std::string relPath;
00391     if (!urdf_traverser::helpers::getSubdirPath(commonParent, path, relPath))
00392     {
00393         ROS_ERROR_STREAM("The file " << path << " is not in a subdirectory of " << commonParent);
00394         return false;
00395     }
00396     // ROS_INFO_STREAM("Path relative to common: "<<relPath);
00397 
00398     std::string relToTarget;
00399     if (!urdf_traverser::helpers::getSubdirPath(commonParent, relTo, relToTarget))
00400     {
00401         ROS_ERROR_STREAM("Relative path " << relTo << " is not a subdirectory of " << commonParent);
00402         return false;
00403     }
00404     // ROS_INFO_STREAM("relTo relative to common: "<<relToTarget);
00405 
00406     // make sure this is a directory, not a file (remove filename if that's the case)
00407     std::string relToDir = getDirectory(relToTarget);
00408     // ROS_INFO_STREAM("relTo relative to common: "<<relToDir);
00409 
00410     // Go up in the hierarchie the number of directories in \e relTo which it takes
00411     // to get to the common parent directory
00412     int relToLen = numDirectories(relToDir);
00413     // ROS_INFO_STREAM("Num dirs in "<<relToTarget<<"("<<relToDir<<"):"<<relToLen);
00414     std::stringstream upDirs;
00415     for (int i = 0; i < relToLen; ++i)
00416         upDirs << ".." << boost::filesystem::path::preferred_separator;
00417 
00418     // append the relative path from common parent dir to \e path
00419     upDirs << relPath;
00420 
00421     result = upDirs.str();
00422 
00423     return true;
00424 }
00425 
00426 bool urdf_traverser::helpers::writeToFile(const std::string& content, const std::string& filename)
00427 {
00428     std::string dir = getDirectory(filename);
00429     if (!urdf_traverser::helpers::makeDirectoryIfNeeded(dir.c_str()))
00430     {
00431         return false;
00432     }
00433 
00434     std::ofstream outf(filename.c_str());
00435     if (!outf)
00436     {
00437         ROS_ERROR("%s could not be opened for writing!", filename.c_str());
00438         return false;
00439     }
00440     outf << content;
00441     outf.close();
00442     return true;
00443 }
00444 
00445 
00446 // transforms a path specification in the form package://<package-name>/<path> to an absolute path on the computer
00447 std::string urdf_traverser::helpers::packagePathToAbsolute(std::string& packagePath)
00448 {
00449     // ROS_INFO("We have a mesh %s",packagePath.c_str());
00450     char pack[1000];
00451     char rest[1000];
00452     int numScanned = sscanf(packagePath.c_str(), "package://%[^/]/%s", pack, rest);
00453     // ROS_INFO("Pack: %s Rest: %s",pack,rest);
00454     if (numScanned != 2)
00455     {
00456         ROS_ERROR("Only package:// style mesh file specifications supported!");
00457         return std::string();
00458     }
00459 
00460     std::string packPath = ros::package::getPath(pack);
00461 
00462     if (packPath.empty())  // path, if found, should if it's returned by ros::package
00463     {
00464         ROS_ERROR("No package for file specified");
00465         return std::string();
00466     }
00467 
00468     std::stringstream absolute;
00469     absolute << packPath << "/" << rest;
00470 
00471     return absolute.str();
00472 }
00473 
00474 
00475 std::ostream& operator<<(std::ostream& o, const Eigen::Vector3f& v)
00476 {
00477     o << "[" << v[0] << ", " << v[1] << ", " << v[2] << "]";
00478     return o;
00479 }
00480 
00481 
00482 std::ostream& operator<<(std::ostream& o, const Eigen::Vector3d& v)
00483 {
00484     o << "[" << v[0] << ", " << v[1] << ", " << v[2] << "]";
00485     return o;
00486 }
00487 std::ostream& operator<<(std::ostream& o, const Eigen::Quaterniond& v)
00488 {
00489     o << "[" << v.x() << ", " << v.y() << ", " << v.z() << ", " << v.w() << "]";
00490     return o;
00491 }
00492 
00493 std::ostream& operator<<(std::ostream& o, const Eigen::Transform<double, 3, Eigen::Affine>& t)
00494 {
00495     //  o<<"T: trans="<<t.translation()<<" rot="<<Eigen::Quaterniond(t.rotation());
00496     Eigen::AngleAxisd ax(t.rotation());
00497     o << "T: trans=" << Eigen::Vector3d(t.translation()) << " rot=" << ax.angle() << " / " << ax.axis();
00498     return o;
00499 }
00500 
00501 std::ostream& operator<<(std::ostream& o, const Eigen::Matrix4d& m)
00502 {
00503     o << m(0, 0) << "," << m(0, 1) << "," << m(0, 2) << "," << m(0, 3) << "," <<
00504       m(1, 0) << "," << m(1, 1) << "," << m(1, 2) << "," << m(1, 3) << "," <<
00505       m(2, 0) << "," << m(2, 1) << "," << m(2, 2) << "," << m(2, 3) << "," <<
00506       m(3, 0) << "," << m(3, 1) << "," << m(3, 2) << "," << m(3, 3);
00507     return o;
00508 }
00509 
00510 
00511 std::ostream& operator<<(std::ostream& o, const urdf::Pose& p)
00512 {
00513     o << "trans=[" << p.position.x << ", " << p.position.y << ", " << p.position.z << "], ";
00514     o << "rot=[" << p.rotation.x << ", " << p.rotation.y << ", " << p.rotation.z << ", " << p.rotation.w << "]";
00515     return o;
00516 }
00517 
00518 std::ostream& operator<<(std::ostream& o, const urdf::Vector3& p)
00519 {
00520     o << "v=[" << p.x << ", " << p.y << ", " << p.z << "], ";
00521     return o;
00522 }


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