pxmlw6n2f/Gazebo_Distributed_TCP/gazebo/common/SystemPaths.cc

551 lines
14 KiB
C++

/*
* Copyright (C) 2012 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <iostream>
#include <fstream>
#include <sstream>
#include <boost/filesystem.hpp>
#include <sdf/sdf.hh>
#include <sys/stat.h>
#include <sys/types.h>
// See below for Windows dirent include. cpplint complains about system
// header order if "win_dirent.h" is in the wrong location.
#ifndef _WIN32
#include <dirent.h>
#else
#include "win_dirent.h"
#endif
#include "gazebo/common/Console.hh"
#include "gazebo/common/Exception.hh"
#include "gazebo/common/ModelDatabase.hh"
#include "gazebo/common/SystemPaths.hh"
using namespace gazebo;
using namespace common;
//////////////////////////////////////////////////
SystemPaths::SystemPaths()
{
this->gazeboPaths.clear();
this->ogrePaths.clear();
this->pluginPaths.clear();
this->modelPaths.clear();
try
{
// Get a path suitable for temporary files
this->tmpPath = boost::filesystem::temp_directory_path();
// Get a unique path suitable for temporary files. If there are multiple
// gazebo instances on the same machine, each one will have its own
// temporary directory
this->tmpInstancePath = boost::filesystem::unique_path("gazebo-%%%%%%");
}
catch(const boost::system::error_code &_ex)
{
gzerr << "Failed creating temp directory. Reason: "
<< _ex.message() << "\n";
return;
}
char *homePath = getenv("HOME");
std::string home;
if (!homePath)
home = this->GetTmpPath() + "/gazebo";
else
home = homePath;
sdf::addURIPath("model://", home + "/.gazebo/models");
this->modelPaths.push_back(home + "/.gazebo/models");
char *path = getenv("GAZEBO_LOG_PATH");
std::string fullPath;
if (!path)
{
if (home != this->GetTmpPath() + "/gazebo")
fullPath = home + "/.gazebo";
else
fullPath = home;
}
else
fullPath = path;
DIR *dir = opendir(fullPath.c_str());
if (!dir)
{
#ifdef _WIN32
mkdir(fullPath.c_str());
#else
mkdir(fullPath.c_str(), S_IRWXU | S_IRGRP | S_IROTH);
#endif
}
else
closedir(dir);
this->logPath = fullPath;
this->UpdateModelPaths();
this->UpdateGazeboPaths();
this->UpdatePluginPaths();
this->UpdateOgrePaths();
// Add some search paths
// this->suffixPaths.push_back(std::string("/sdf/") + SDF_VERSION + "/");
this->suffixPaths.push_back("/models/");
this->suffixPaths.push_back("/media/models/");
this->suffixPaths.push_back("/Media/models/");
this->pluginPathsFromEnv = true;
this->gazeboPathsFromEnv = true;
this->modelPathsFromEnv = true;
this->ogrePathsFromEnv = true;
}
/////////////////////////////////////////////////
std::string SystemPaths::GetLogPath() const
{
return this->logPath;
}
/////////////////////////////////////////////////
const std::list<std::string> &SystemPaths::GetGazeboPaths()
{
if (this->gazeboPathsFromEnv)
this->UpdateGazeboPaths();
return this->gazeboPaths;
}
/////////////////////////////////////////////////
const std::list<std::string> &SystemPaths::GetPluginPaths()
{
if (this->pluginPathsFromEnv)
this->UpdatePluginPaths();
return this->pluginPaths;
}
/////////////////////////////////////////////////
const std::list<std::string> &SystemPaths::GetModelPaths()
{
if (this->modelPathsFromEnv)
this->UpdateModelPaths();
return this->modelPaths;
}
/////////////////////////////////////////////////
const std::list<std::string> &SystemPaths::GetOgrePaths()
{
if (this->ogrePathsFromEnv)
this->UpdateOgrePaths();
return this->ogrePaths;
}
/////////////////////////////////////////////////
std::string SystemPaths::GetTmpPath()
{
return this->tmpPath.string();
}
/////////////////////////////////////////////////
std::string SystemPaths::GetTmpInstancePath()
{
return this->tmpInstancePath.string();
}
/////////////////////////////////////////////////
std::string SystemPaths::GetDefaultTestPath()
{
return this->GetTmpInstancePath() + "/gazebo_test";
}
/////////////////////////////////////////////////
void SystemPaths::UpdateModelPaths()
{
std::string delim(":");
std::string path;
char *pathCStr = getenv("GAZEBO_MODEL_PATH");
if (!pathCStr || *pathCStr == '\0')
{
// No env var; take the compile-time default.
path = GAZEBO_MODEL_PATH;
}
else
path = pathCStr;
/// \TODO: Use boost to split string.
size_t pos1 = 0;
size_t pos2 = path.find(delim);
while (pos2 != std::string::npos)
{
sdf::addURIPath("model://", path.substr(pos1, pos2-pos1));
this->InsertUnique(path.substr(pos1, pos2-pos1), this->modelPaths);
pos1 = pos2+1;
pos2 = path.find(delim, pos2+1);
}
this->InsertUnique(path.substr(pos1, path.size()-pos1), this->modelPaths);
}
/////////////////////////////////////////////////
void SystemPaths::UpdateGazeboPaths()
{
std::string delim(":");
std::string path;
char *pathCStr = getenv("GAZEBO_RESOURCE_PATH");
if (!pathCStr || *pathCStr == '\0')
{
// No env var; take the compile-time default.
path = GAZEBO_RESOURCE_PATH;
}
else
path = pathCStr;
size_t pos1 = 0;
size_t pos2 = path.find(delim);
while (pos2 != std::string::npos)
{
this->InsertUnique(path.substr(pos1, pos2-pos1), this->gazeboPaths);
pos1 = pos2+1;
pos2 = path.find(delim, pos2+1);
}
this->InsertUnique(path.substr(pos1, path.size()-pos1), this->gazeboPaths);
}
//////////////////////////////////////////////////
void SystemPaths::UpdatePluginPaths()
{
std::string delim(":");
std::string path;
char *pathCStr = getenv("GAZEBO_PLUGIN_PATH");
if (!pathCStr || *pathCStr == '\0')
{
// No env var; take the compile-time default.
path = GAZEBO_PLUGIN_PATH;
}
else
path = pathCStr;
size_t pos1 = 0;
size_t pos2 = path.find(delim);
while (pos2 != std::string::npos)
{
this->InsertUnique(path.substr(pos1, pos2-pos1), this->pluginPaths);
pos1 = pos2+1;
pos2 = path.find(delim, pos2+1);
}
this->InsertUnique(path.substr(pos1, path.size()-pos1), this->pluginPaths);
}
//////////////////////////////////////////////////
void SystemPaths::UpdateOgrePaths()
{
std::string delim(":");
std::string path;
char *pathCStr = getenv("OGRE_RESOURCE_PATH");
if (!pathCStr || *pathCStr == '\0')
{
// No env var; take the compile-time default.
path = OGRE_RESOURCE_PATH;
}
else
path = pathCStr;
size_t pos1 = 0;
size_t pos2 = path.find(delim);
while (pos2 != std::string::npos)
{
this->InsertUnique(path.substr(pos1, pos2-pos1), this->ogrePaths);
pos1 = pos2+1;
pos2 = path.find(delim, pos2+1);
}
this->InsertUnique(path.substr(pos1, path.size()-pos1), this->ogrePaths);
}
//////////////////////////////////////////////////
std::string SystemPaths::GetWorldPathExtension()
{
return "/worlds";
}
//////////////////////////////////////////////////
std::string SystemPaths::FindFileURI(const std::string &_uri)
{
int index = _uri.find("://");
std::string prefix = _uri.substr(0, index);
std::string suffix = _uri.substr(index + 3, _uri.size() - index - 3);
std::string filename;
// If trying to find a model, return the path to the users home
// .gazebo/models
if (prefix == "model")
{
boost::filesystem::path path;
for (std::list<std::string>::iterator iter = this->modelPaths.begin();
iter != this->modelPaths.end(); ++iter)
{
path = boost::filesystem::path(*iter) / suffix;
if (boost::filesystem::exists(path))
{
filename = path.string();
break;
}
}
// Try to download the model if it wasn't found.
if (filename.empty())
filename = ModelDatabase::Instance()->GetModelPath(_uri, true);
}
else if (prefix.empty() || prefix == "file")
{
// First try to find the file on the current system
filename = this->FindFile(suffix);
}
else if (prefix != "http" && prefix != "https")
gzerr << "Unknown URI prefix[" << prefix << "]\n";
return filename;
}
//////////////////////////////////////////////////
std::string SystemPaths::FindFile(const std::string &_filename,
bool _searchLocalPath)
{
boost::filesystem::path path;
if (_filename.empty())
return path.string();
if (_filename.find("://") != std::string::npos)
{
path = boost::filesystem::path(this->FindFileURI(_filename));
}
else if (_filename[0] == '/')
{
path = boost::filesystem::path(_filename);
// absolute paths are not portable, e.g. when running world or
// or log files on a different machine. To workaround this problem,
// we'll further look for these files in one of gazebo model paths.
// e.g. /tmp/path/to/my_file
// => ${GAZEBO_MODEL_PATH}/tmp/path/to/my_file
// Gazebo log playback makes use of this feature
if (!boost::filesystem::exists(path))
{
for (std::list<std::string>::iterator iter = this->modelPaths.begin();
iter != this->modelPaths.end(); ++iter)
{
auto modelPath = boost::filesystem::path(*iter) / path;
if (boost::filesystem::exists(modelPath))
{
path = modelPath;
break;
}
}
}
}
else
{
bool found = false;
try
{
path = boost::filesystem::operator/(boost::filesystem::current_path(),
_filename);
}
catch(boost::filesystem::filesystem_error &_e)
{
gzerr << "Filesystem error[" << _e.what() << "]\n";
return std::string();
}
if (_searchLocalPath && boost::filesystem::exists(path))
{
found = true;
}
else if ((_filename[0] == '/' || _filename[0] == '.' || _searchLocalPath)
&& boost::filesystem::exists(boost::filesystem::path(_filename)))
{
path = boost::filesystem::path(_filename);
found = true;
}
else
{
std::list<std::string> paths = this->GetGazeboPaths();
for (std::list<std::string>::const_iterator iter = paths.begin();
iter != paths.end() && !found; ++iter)
{
path = boost::filesystem::path((*iter));
path = boost::filesystem::operator/(path, _filename);
if (boost::filesystem::exists(path))
{
found = true;
break;
}
std::list<std::string>::iterator suffixIter;
for (suffixIter = this->suffixPaths.begin();
suffixIter != this->suffixPaths.end(); ++suffixIter)
{
path = boost::filesystem::path(*iter);
path = boost::filesystem::operator/(path, *suffixIter);
path = boost::filesystem::operator/(path, _filename);
if (boost::filesystem::exists(path))
{
found = true;
break;
}
}
}
}
if (!found)
return std::string();
}
if (!boost::filesystem::exists(path))
{
gzerr << "File or path does not exist[" << path << "]\n";
return std::string();
}
return path.string();
}
/////////////////////////////////////////////////
void SystemPaths::ClearGazeboPaths()
{
this->gazeboPaths.clear();
}
/////////////////////////////////////////////////
void SystemPaths::ClearOgrePaths()
{
this->ogrePaths.clear();
}
/////////////////////////////////////////////////
void SystemPaths::ClearPluginPaths()
{
this->pluginPaths.clear();
}
/////////////////////////////////////////////////
void SystemPaths::ClearModelPaths()
{
this->modelPaths.clear();
}
/////////////////////////////////////////////////
void SystemPaths::AddGazeboPaths(const std::string &_path)
{
std::string delim(":");
size_t pos1 = 0;
size_t pos2 = _path.find(delim);
while (pos2 != std::string::npos)
{
this->InsertUnique(_path.substr(pos1, pos2-pos1), this->gazeboPaths);
pos1 = pos2+1;
pos2 = _path.find(delim, pos2+1);
}
this->InsertUnique(_path.substr(pos1, _path.size()-pos1), this->gazeboPaths);
}
/////////////////////////////////////////////////
void SystemPaths::AddOgrePaths(const std::string &_path)
{
std::string delim(":");
size_t pos1 = 0;
size_t pos2 = _path.find(delim);
while (pos2 != std::string::npos)
{
this->InsertUnique(_path.substr(pos1, pos2-pos1), this->ogrePaths);
pos1 = pos2+1;
pos2 = _path.find(delim, pos2+1);
}
this->InsertUnique(_path.substr(pos1, _path.size()-pos1), this->ogrePaths);
}
/////////////////////////////////////////////////
void SystemPaths::AddPluginPaths(const std::string &_path)
{
std::string delim(":");
size_t pos1 = 0;
size_t pos2 = _path.find(delim);
while (pos2 != std::string::npos)
{
this->InsertUnique(_path.substr(pos1, pos2-pos1), this->pluginPaths);
pos1 = pos2+1;
pos2 = _path.find(delim, pos2+1);
}
this->InsertUnique(_path.substr(pos1, _path.size()-pos1), this->pluginPaths);
}
/////////////////////////////////////////////////
void SystemPaths::AddModelPaths(const std::string &_path)
{
std::string delim(":");
size_t pos1 = 0;
size_t pos2 = _path.find(delim);
while (pos2 != std::string::npos)
{
this->InsertUnique(_path.substr(pos1, pos2-pos1), this->modelPaths);
pos1 = pos2+1;
pos2 = _path.find(delim, pos2+1);
}
this->InsertUnique(_path.substr(pos1, _path.size()-pos1), this->modelPaths);
}
/////////////////////////////////////////////////
void SystemPaths::AddModelPathsUpdate(const std::string &_path)
{
this->AddModelPaths(_path);
updateModelRequest(_path);
}
/////////////////////////////////////////////////
void SystemPaths::InsertUnique(const std::string &_path,
std::list<std::string> &_list)
{
if (std::find(_list.begin(), _list.end(), _path) == _list.end())
_list.push_back(_path);
}
/////////////////////////////////////////////////
void SystemPaths::AddSearchPathSuffix(const std::string &_suffix)
{
std::string s;
if (_suffix[0] != '/')
s = std::string("/") + _suffix;
else
s = _suffix;
if (_suffix[_suffix.size()-1] != '/')
s += "/";
this->suffixPaths.push_back(s);
}