Helpers.cpp
Go to the documentation of this file.
00001 
00031 #include <urdf2inventor/Helpers.h>
00032 
00033 #include <ros/ros.h>
00034 #include <ros/package.h>
00035 
00036 #define BOOST_NO_CXX11_SCOPED_ENUMS
00037 #include <boost/filesystem.hpp>
00038 #undef BOOST_NO_CXX11_SCOPED_ENUMS
00039 
00040 #include <fcntl.h>
00041 #include <fstream>
00042 #include <string>
00043 
00044 
00053 // handle for stdout redirect
00054 int stdout_fd;
00055 
00056 void urdf2inventor::helpers::resetStdOut()
00057 {
00058     if (stdout_fd < 0)
00059     {
00060         return;
00061     }
00062     fflush(stdout);
00063     if (dup2(stdout_fd, STDOUT_FILENO) < 0)
00064     {
00065         ROS_ERROR("Could not restore stdout");
00066         return;
00067     }
00068     close(stdout_fd);
00069 
00070     // setbuf(stdout,NULL);//reset to unnamed buffer
00071 }
00072 
00073 // See http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/redirecting-standard-io.html
00074 void urdf2inventor::helpers::redirectStdOut(const char * toFile)
00075 {
00076     fflush(stdout);
00077 
00078     mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
00079     int file = open(toFile, O_CREAT | O_APPEND | O_WRONLY, mode);
00080     if (file < 0)
00081     {
00082         ROS_ERROR("could not create new output stream %s: %s", toFile, strerror(errno));
00083         return;
00084     }
00085     stdout_fd = dup(STDOUT_FILENO);                // Clone stdout to a new descriptor
00086     if (dup2(file, STDOUT_FILENO) < 0)
00087     {
00088         ROS_ERROR("could not redirect output stream");
00089         return;      // Change stdout to file
00090     }
00091     // close(file);  // stdout is still valid
00092 
00093     // setvbuf(stdout,toString,_IOFBF,stringSize);
00094 }
00095 
00096 
00097 
00098 bool urdf2inventor::helpers::writeFiles(const std::map<std::string, std::set<std::string> >& files, const std::string& outputDir)
00099 {
00100     bool ret = true;
00101     boost::filesystem::path _outputDir(boost::filesystem::absolute(outputDir));
00102 
00103     for (std::map<std::string, std::set<std::string> >::const_iterator mit = files.begin(); mit != files.end(); ++mit)
00104     {
00105         for (std::set<std::string>::const_iterator tit = mit->second.begin(); tit != mit->second.end(); ++tit)
00106         {
00107             boost::filesystem::path fullPath;
00108             boost::filesystem::path tFile(mit->first);
00109             if (tFile.is_relative())
00110             {
00111                 fullPath = _outputDir;
00112             }
00113             else
00114             {
00115                 // outputDir should be a superdirectory of tFile, or print a warning
00116                 std::string testRelParent;
00117                 if (!urdf_traverser::helpers::getSubdirPath(outputDir, tFile.string(), testRelParent))
00118                 {
00119                     ROS_WARN_STREAM("File " << tFile.string() << " given as absolute path, but it is not in a subdirectory of " << outputDir);
00120                 }
00121             }
00122             fullPath /= tFile;
00123             // ROS_INFO_STREAM("cp "<<*tit<<" "<<fullPath.string());
00124 
00125             // first, create directory if needed
00126             std::string targetTexDir = urdf_traverser::helpers::getDirectory(fullPath.string());
00127             if (!urdf_traverser::helpers::makeDirectoryIfNeeded(targetTexDir.c_str()))
00128             {
00129                 ROS_ERROR_STREAM("Could not create directory " << targetTexDir);
00130                 ret = false;
00131                 continue;
00132             }
00133 
00134             try
00135             {
00136                 // copy the file
00137                 // copy_option::fail_if_exists would be proper but annoying to debug
00138                 boost::filesystem::copy_file(*tit, fullPath, boost::filesystem::copy_option::overwrite_if_exists);
00139             }
00140             catch (const boost::filesystem::filesystem_error& ex)
00141             {
00142                 ROS_ERROR_STREAM("Could not copy file: " << ex.what());
00143                 ret = false;
00144                 continue;
00145             }
00146         }
00147     }
00148 
00149     return ret;
00150 }
00151 
00152 
00153 bool urdf2inventor::helpers::fixFileReferences(
00154     const std::string& modelDir,
00155     const std::string& fileDir,
00156     const std::string& fileRootDir,
00157     const std::set<std::string>& filesInUse,
00158     std::string& modelString,
00159     std::map<std::string, std::set<std::string> >& filesToCopy)
00160 {
00161     if (filesInUse.empty()) return true;
00162 
00163     std::string _fileDir(fileDir);
00164     urdf_traverser::helpers::enforceDirectory(_fileDir, false);
00165 
00166     // do error checking first
00167     std::string testCommonParent;
00168     if (!urdf_traverser::helpers::getCommonParentPath(filesInUse, testCommonParent))
00169     {
00170         ROS_ERROR_STREAM("Could not find common parent path of all files");
00171         return false;
00172     }
00173     // test: testCommonParent must be a subdirectory to fileRootDir, or the same directory.
00174     std::string testRelParent;
00175     if (!urdf_traverser::helpers::getSubdirPath(fileRootDir, testCommonParent, testRelParent))
00176     {
00177         ROS_ERROR_STREAM("File " << testCommonParent << " is not in a subdirectory of " << fileRootDir);
00178         return false;
00179     }
00180     // end error checking
00181 
00182     // now iterate through all file files and change references in \e modelString
00183     for (std::set<std::string>::iterator itFile = filesInUse.begin(); itFile != filesInUse.end(); ++itFile)
00184     {
00185         std::string absFile = *itFile;
00186         std::string file;
00187         if (!urdf_traverser::helpers::getSubdirPath(fileRootDir, absFile, file))
00188         {
00189             ROS_ERROR_STREAM("File " << absFile << " is not in a subdirectory of " << fileRootDir);
00190             continue;
00191         }
00192         // ROS_INFO_STREAM("Relative file: "<<file);
00193 
00194         std::stringstream filePath;  // the absolute path the the file
00195         filePath << _fileDir << file;
00196 
00197         std::string newFileReference;
00198         if (!urdf_traverser::helpers::getRelativeDirectory(filePath.str(), modelDir, newFileReference))
00199         {
00200             ROS_ERROR_STREAM("Could not determine relative directory between " << filePath.str()
00201                              << " and " << modelDir << ".");
00202             continue;
00203         }
00204 
00205         // replace all occurrences in mesh string
00206         // ROS_INFO_STREAM("Replacing new file reference: "<<newFileReference);
00207 
00208         // first, replace all full filenames with paths
00209         modelString = urdf_traverser::helpers::replaceAll(modelString,
00210                       absFile, newFileReference);
00211 
00212         // now, replace all remaining occurrences of the path with a version without
00213         // path separators (this is only in case there is left-over names made up of the path)
00214         boost::filesystem::path _absFileMod(absFile);
00215         _absFileMod.replace_extension("");
00216         boost::filesystem::path _texRefMod(newFileReference);
00217         _texRefMod.replace_extension("");
00218         std::string texRefMod = urdf_traverser::helpers::replaceAll(_texRefMod.string(), "/", "_");
00219         texRefMod = urdf_traverser::helpers::replaceAll(texRefMod, ".", "_");
00220         modelString = urdf_traverser::helpers::replaceAll(modelString,
00221                       _absFileMod.string(), texRefMod);
00222 
00223         // ROS_INFO_STREAM("File to copy to "<<filePath.str()<<" : "<<absFile);
00224         // add this file to the result set
00225         filesToCopy[filePath.str()].insert(absFile);
00226     }
00227     return true;
00228 }
00229 


urdf2inventor
Author(s): Jennifer Buehler
autogenerated on Fri Mar 1 2019 03:38:11