Skip to content
This repository was archived by the owner on Feb 3, 2025. It is now read-only.

Commit 1aea1b3

Browse files
ahcordechapulina
andauthored
[Gazebo 11] Allow gazebo to download models from Fuel in the sdf files (#2822)
Signed-off-by: ahcorde <ahcorde@gmail.com> Signed-off-by: Louise Poubel <louise@openrobotics.org> Co-authored-by: Louise Poubel <louise@openrobotics.org>
1 parent 521ca50 commit 1aea1b3

File tree

8 files changed

+273
-52
lines changed

8 files changed

+273
-52
lines changed

gazebo/Server.cc

+55-13
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,15 @@
3333
#include <sdf/sdf.hh>
3434

3535
#include <ignition/math/Rand.hh>
36-
#include "ignition/common/Profiler.hh"
36+
#include <ignition/common/Profiler.hh>
37+
#include <ignition/common/Filesystem.hh>
38+
#include <ignition/common/URI.hh>
39+
#ifdef _WIN32
40+
// DELETE is defined in winnt.h and causes a problem with
41+
// ignition::fuel_tools::REST::DELETE
42+
#undef DELETE
43+
#endif
44+
#include <ignition/fuel_tools/Interface.hh>
3745

3846
#include "gazebo/gazebo.hh"
3947
#include "gazebo/transport/transport.hh"
@@ -385,15 +393,6 @@ bool Server::GetInitialized() const
385393
bool Server::LoadFile(const std::string &_filename,
386394
const std::string &_physics)
387395
{
388-
// Quick test for a valid file
389-
FILE *test = fopen(common::find_file(_filename).c_str(), "r");
390-
if (!test)
391-
{
392-
gzerr << "Could not open file[" << _filename << "]\n";
393-
return false;
394-
}
395-
fclose(test);
396-
397396
// Load the world file
398397
sdf::SDFPtr sdf(new sdf::SDF);
399398
if (!sdf::init(sdf))
@@ -402,10 +401,53 @@ bool Server::LoadFile(const std::string &_filename,
402401
return false;
403402
}
404403

405-
if (!sdf::readFile(common::find_file(_filename), sdf))
404+
std::string filename = _filename;
405+
auto filenameUri = ignition::common::URI(filename);
406+
407+
if (filenameUri.Scheme() == "http" || filenameUri.Scheme() == "https")
406408
{
407-
gzerr << "Unable to read sdf file[" << _filename << "]\n";
408-
return false;
409+
std::string downloadedDir = common::FuelModelDatabase::Instance()->WorldPath(filename);
410+
// Find the first sdf file in the world path for now, the later intention is
411+
// to load an optional world config file first and if that does not exist,
412+
// continue to load the first sdf file found as done below
413+
for (ignition::common::DirIter file(downloadedDir);
414+
file != ignition::common::DirIter(); ++file)
415+
{
416+
std::string current(*file);
417+
if (ignition::common::isFile(current))
418+
{
419+
std::string fileName = ignition::common::basename(current);
420+
std::string::size_type fileExtensionIndex = fileName.rfind(".");
421+
std::string fileExtension = fileName.substr(fileExtensionIndex + 1);
422+
423+
if (fileExtension == "sdf" || fileExtension == "world")
424+
{
425+
filename = current.c_str();
426+
if (!sdf::readFile(filename, sdf))
427+
{
428+
gzerr << "Unable to read SDF from URL[" << filename << "]\n";
429+
return false;
430+
}
431+
}
432+
}
433+
}
434+
}
435+
else
436+
{
437+
// Quick test for a valid file
438+
FILE *test = fopen(common::find_file(filename).c_str(), "r");
439+
if (!test)
440+
{
441+
gzerr << "Could not open file[" << filename << "]\n";
442+
return false;
443+
}
444+
fclose(test);
445+
446+
if (!sdf::readFile(common::find_file(filename), sdf))
447+
{
448+
gzerr << "Unable to read sdf file[" << filename << "]\n";
449+
return false;
450+
}
409451
}
410452

411453
return this->LoadImpl(sdf->Root(), _physics);

gazebo/common/CommonIface.cc

+20-2
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,16 @@
4444
#include "gazebo/common/Console.hh"
4545
#include "gazebo/common/CommonIface.hh"
4646
#include "gazebo/common/Exception.hh"
47+
#include "gazebo/common/FuelModelDatabase.hh"
4748
#include "gazebo/common/SystemPaths.hh"
4849

50+
#ifdef _WIN32
51+
// DELETE is defined in winnt.h and causes a problem with
52+
// ignition::fuel_tools::REST::DELETE
53+
#undef DELETE
54+
#endif
55+
#include "ignition/fuel_tools/Interface.hh"
56+
4957
using namespace gazebo;
5058

5159
#ifdef _WIN32
@@ -156,13 +164,23 @@ void common::add_search_path_suffix(const std::string &_suffix)
156164
/////////////////////////////////////////////////
157165
std::string common::find_file(const std::string &_file)
158166
{
159-
return common::SystemPaths::Instance()->FindFile(_file, true);
167+
std::string path = common::FuelModelDatabase::Instance()->ModelPath(_file);
168+
if (path.empty())
169+
{
170+
path = common::SystemPaths::Instance()->FindFile(_file, true);
171+
}
172+
return path;
160173
}
161174

162175
/////////////////////////////////////////////////
163176
std::string common::find_file(const std::string &_file, bool _searchLocalPath)
164177
{
165-
return common::SystemPaths::Instance()->FindFile(_file, _searchLocalPath);
178+
std::string path = common::FuelModelDatabase::Instance()->ModelPath(_file);
179+
if (path.empty())
180+
{
181+
path = common::SystemPaths::Instance()->FindFile(_file, _searchLocalPath);
182+
}
183+
return path;
166184
}
167185

168186
/////////////////////////////////////////////////

gazebo/common/FuelModelDatabase.cc

+77-12
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,14 @@
2626

2727
#include <ignition/common/Console.hh>
2828
#include <ignition/common/Filesystem.hh>
29+
#include <ignition/common/URI.hh>
30+
#ifdef _WIN32
31+
// DELETE is defined in winnt.h and causes a problem with
32+
// ignition::fuel_tools::REST::DELETE
33+
#undef DELETE
34+
#endif
2935
#include <ignition/fuel_tools/FuelClient.hh>
36+
#include <ignition/fuel_tools/WorldIdentifier.hh>
3037
#include <sdf/sdf.hh>
3138

3239
#include "gazebo/gazebo_config.h"
@@ -208,31 +215,90 @@ std::string FuelModelDatabase::ModelPath(const std::string &_uri,
208215

209216
if (fuelUri.Scheme() != "http" && fuelUri.Scheme() != "https")
210217
{
211-
gzwarn << "URI not supported by Fuel [" << _uri << "]" << std::endl;
212218
return std::string();
213219
}
214220

215221
std::string path;
222+
std::string fileUrl;
223+
ignition::fuel_tools::ModelIdentifier model;
224+
using namespace ignition::fuel_tools;
216225

217-
if (!_forceDownload)
226+
if ((this->dataPtr->fuelClient->ParseModelUrl(fuelUri, model) &&
227+
!this->dataPtr->fuelClient->CachedModel(fuelUri, path))
228+
|| _forceDownload)
218229
{
219-
if (this->dataPtr->fuelClient->CachedModel(fuelUri, path))
230+
Result result_download =
231+
this->dataPtr->fuelClient->DownloadModel(fuelUri, path);
232+
if (result_download != Result(ResultType::FETCH) ||
233+
result_download != Result(ResultType::FETCH_ALREADY_EXISTS))
234+
{
235+
gzerr << "Unable to download model[" << _uri << "]" << std::endl;
236+
return std::string();
237+
}
238+
else
220239
{
221-
return path;
240+
gzmsg << "Downloaded model URL: " << std::endl
241+
<< " " << _uri << std::endl
242+
<< " to: " << std::endl
243+
<< " " << path << std::endl;
244+
}
245+
}
246+
if (path.empty()) {
247+
if ((this->dataPtr->fuelClient->ParseModelFileUrl(fuelUri, model, fileUrl) &&
248+
!this->dataPtr->fuelClient->CachedModelFile(fuelUri, path))
249+
|| _forceDownload)
250+
{
251+
auto modelUri = _uri.substr(0,
252+
_uri.find("files", model.UniqueName().size())-1);
253+
Result result_download =
254+
this->dataPtr->fuelClient->DownloadModel(ignition::common::URI(modelUri), path);
255+
if (result_download != Result(ResultType::FETCH) ||
256+
result_download != Result(ResultType::FETCH_ALREADY_EXISTS))
257+
{
258+
gzerr << "Unable to download model[" << _uri << "]" << std::endl;
259+
return std::string();
260+
}
261+
else
262+
{
263+
gzmsg << "Downloaded model URL: " << std::endl
264+
<< " " << _uri << std::endl
265+
<< " to: " << std::endl
266+
<< " " << path << std::endl;
267+
path += "/" + fileUrl;
268+
}
222269
}
223270
}
224271

225-
if (!this->dataPtr->fuelClient->DownloadModel(fuelUri, path))
272+
return path;
273+
}
274+
275+
/////////////////////////////////////////////////
276+
std::string FuelModelDatabase::WorldPath(const std::string &_uri, const bool _forceDownload)
277+
{
278+
auto fuelUri = ignition::common::URI(_uri);
279+
280+
if (fuelUri.Scheme() != "http" && fuelUri.Scheme() != "https")
226281
{
227-
gzerr << "Unable to download model[" << _uri << "]" << std::endl;
228282
return std::string();
229283
}
230-
else
284+
285+
std::string path;
286+
std::string fileUrl;
287+
ignition::fuel_tools::WorldIdentifier world;
288+
289+
if ((this->dataPtr->fuelClient->ParseWorldUrl(fuelUri, world) &&
290+
!this->dataPtr->fuelClient->CachedWorld(fuelUri, path)) || _forceDownload)
231291
{
232-
gzmsg << "Downloaded model URL: " << std::endl
233-
<< " " << _uri << std::endl
234-
<< " to: " << std::endl
235-
<< " " << path << std::endl;
292+
this->dataPtr->fuelClient->DownloadWorld(fuelUri, path);
293+
}
294+
// Download the world, if it's a world file URI
295+
else if (this->dataPtr->fuelClient->ParseWorldFileUrl(fuelUri, world, fileUrl) &&
296+
!this->dataPtr->fuelClient->CachedWorldFile(fuelUri, path))
297+
{
298+
auto worldUri = _uri.substr(0,
299+
_uri.find("files", world.UniqueName().size())-1);
300+
this->dataPtr->fuelClient->DownloadWorld(ignition::common::URI(worldUri), path);
301+
path += "/" + fileUrl;
236302
}
237303

238304
return path;
@@ -256,4 +322,3 @@ std::string FuelModelDatabase::CachedFilePath(const std::string &_uri)
256322

257323
return path;
258324
}
259-

gazebo/common/FuelModelDatabase.hh

+15
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@
2121
#include <memory>
2222
#include <string>
2323
#include <vector>
24+
#ifdef _WIN32
25+
// DELETE is defined in winnt.h and causes a problem with
26+
// ignition::fuel_tools::REST::DELETE
27+
#undef DELETE
28+
#endif
2429
#include <ignition/fuel_tools/ClientConfig.hh>
2530
#include <ignition/fuel_tools/ModelIdentifier.hh>
2631

@@ -103,6 +108,16 @@ namespace gazebo
103108
public: std::string ModelPath(const std::string &_uri,
104109
const bool _forceDownload = false);
105110

111+
/// \brief Get the local path to a world.
112+
///
113+
/// Get the path to a world based on a URI. If the world is on
114+
/// a remote server, then the model fetched and installed locally.
115+
/// \param[in] _uri the model uri
116+
/// \param[in] _forceDownload True to skip searching local cache.
117+
/// \return Local path to a world directory
118+
public: std::string WorldPath(const std::string &_uri,
119+
const bool _forceDownload = false);
120+
106121
/// \brief Get the full local path to a cached file based on its URI.
107122
/// \param[in] _uri The file's URI
108123
/// \return Local path to the file

gazebo/gui/InsertModelWidget.cc

-21
Original file line numberDiff line numberDiff line change
@@ -48,21 +48,6 @@ using namespace gui;
4848

4949
static bool gInsertModelWidgetDeleted = false;
5050

51-
/////////////////////////////////////////////////
52-
// TODO: Remove this once Fuel support is fully functional
53-
bool usingFuel()
54-
{
55-
auto useFuel = std::getenv("USE_IGNITION_FUEL");
56-
if (!useFuel || *useFuel == '\0')
57-
return false;
58-
59-
std::string useFuelStr(useFuel);
60-
std::transform(useFuelStr.begin(), useFuelStr.end(),
61-
useFuelStr.begin(), ::tolower);
62-
63-
return useFuelStr != "false" && useFuelStr != "0";
64-
}
65-
6651
/////////////////////////////////////////////////
6752
InsertModelWidget::InsertModelWidget(QWidget *_parent)
6853
: QWidget(_parent), dataPtr(new InsertModelWidgetPrivate)
@@ -523,9 +508,6 @@ bool InsertModelWidget::IsPathAccessible(const boost::filesystem::path &_path)
523508
/////////////////////////////////////////////////
524509
void InsertModelWidget::InitializeFuelServers()
525510
{
526-
if (!usingFuel())
527-
return;
528-
529511
// Get the list of Ignition Fuel servers.
530512
auto servers = common::FuelModelDatabase::Instance()->Servers();
531513

@@ -550,9 +532,6 @@ void InsertModelWidget::InitializeFuelServers()
550532
/////////////////////////////////////////////////
551533
void InsertModelWidget::PopulateFuelServers()
552534
{
553-
if (!usingFuel())
554-
return;
555-
556535
// Get the list of Ignition Fuel servers.
557536
auto servers = common::FuelModelDatabase::Instance()->Servers();
558537

gazebo/rendering/RenderEngine.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ void RenderEngine::LoadPlugins()
465465
/////////////////////////////////////////////////
466466
void RenderEngine::AddResourcePath(const std::string &_uri)
467467
{
468-
if (_uri == "__default__" || _uri.empty())
468+
if (_uri.find("__default__") != std::string::npos || _uri.empty())
469469
return;
470470

471471
std::string path = common::find_file_path(_uri);

0 commit comments

Comments
 (0)