-
Notifications
You must be signed in to change notification settings - Fork 100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Resolve URIs relative to file path #1373
Conversation
Signed-off-by: Ian Chen <[email protected]>
Signed-off-by: Ian Chen <[email protected]>
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## sdf13 #1373 +/- ##
=======================================
Coverage 87.58% 87.59%
=======================================
Files 128 128
Lines 17095 17132 +37
=======================================
+ Hits 14972 15006 +34
- Misses 2123 2126 +3 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the concept looks good to me, and I left a few comments
include/sdf/ParserConfig.hh
Outdated
|
||
/// \brief Get the path to the SDF file. | ||
/// \return Full path to SDF file. | ||
public: const std::string &FilePath() const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would be more specific with this naming, like URIRelativePath
because FilePath
is already used in the Element
class and many other DOM classes that are loaded directly from a file, but since ParserConfig
represents configuration, not data loaded from a file, I would use a different name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I gave a shot at naming: SetRelativeURISearchPath
. Not tied to it, happy to change to a better name. a83998c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good
src/SDF.cc
Outdated
@@ -115,6 +116,16 @@ std::string findFile(const std::string &_filename, bool _searchLocalPath, | |||
{ | |||
return path; | |||
} | |||
else if (!_config.FilePath().empty()) | |||
{ | |||
auto p = std::filesystem::path(_config.FilePath()).parent_path(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would recommend storing the parent path directly in ParserConfig
so that this kind of manipulation isn't required at this level. This could be added to the Set*
method in ParserConfig
like:
void ParserConfig::SetURIRelativePath(const std::string &, bool _stripNonFolderSuffix)
(the names probably need work)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved path manipulation logic out of this function in a83998c.
I didn't add the second arg though (_stripNonFolderSuffix
) as the new naming should hopefully suggest that it expects a dir path and not a file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Signed-off-by: Ian Chen <[email protected]>
src/Heightmap.cc
Outdated
@@ -324,11 +325,14 @@ Errors Heightmap::Load(ElementPtr _sdf, const ParserConfig &_config) | |||
return errors; | |||
} | |||
|
|||
auto config = _config; | |||
auto path = std::filesystem::path(this->dataPtr->filePath).parent_path(); | |||
config.SetRelativeURISearchPath(path.string()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that SetRelativeURISearchPath
is called here to unconditionally override the previous value in the ParserConfig
object passed to Load
. I think that probably makes sense, I'm trying to think it through to be sure.
Do we want to emit a warning if the value isn't empty before overwriting it? I haven't had a chance to think this through yet.
cc @azeey
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like @azeey's suggestion in #1373 (comment)
src/Heightmap.cc
Outdated
@@ -324,11 +325,14 @@ Errors Heightmap::Load(ElementPtr _sdf, const ParserConfig &_config) | |||
return errors; | |||
} | |||
|
|||
auto config = _config; | |||
auto path = std::filesystem::path(this->dataPtr->filePath).parent_path(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
filePath
may not be set if, for example, the object was constructed programmatically or the SDF input was a string. Can you guard against that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it should just return an empty string. I added a check nevertheless 443dfd2
include/sdf/ParserConfig.hh
Outdated
|
||
/// \brief Get the storeResolvedURIs flag value. | ||
/// \return True if the parser will attempt to resolve any URIs found and | ||
/// store them. False to preserve original URIs | ||
public: bool StoreResolvedURIs() const; | ||
|
||
/// \brief Set the path to search for URIs with relative path. | ||
/// \param[in] _path Path to search. | ||
public: void SetRelativeURISearchPath(const std::string &_path); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm concerned that this will be confusing for users, especially since there's a chance for the value to be overwritten. It seems to me we're adding a public API to implement something that should be hidden from the user.
I propose an alternative that does not require adding anything new to ParserConfig:
Let's extend resolveURI
to take an optional parent directory as an argument. Then it could do the following:
- If the URI is relative:
- First do the normal
sdf::findFile
call - If that fails, prepend the parent directory and try again. (Or we can swap these steps)
- First do the normal
- If the URI is absolute, just do the normal
sdf::findFile
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for suggestions. I implemented the proposed changes in 70e897e. The resolveURI
function now takes an optional set of search paths for resolving URIs.
Signed-off-by: Ian Chen <[email protected]>
Signed-off-by: Ian Chen <[email protected]>
Signed-off-by: Ian Chen <[email protected]>
Signed-off-by: Ian Chen <[email protected]>
EXPECT_TRUE(sdf::filesystem::exists(scriptUri)); | ||
EXPECT_TRUE(sdf::filesystem::exists(meshVisualUri)); | ||
EXPECT_TRUE(sdf::filesystem::exists(meshColUri)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to see a test where the input is an SDF string, not a file, so as to exercise the situation where sdf::Element::FilePath
returns an empty string. It's not clear to me what parent_path
returns in that case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added test for loading sdf from string. In this case, parent_path
will be empty string so it's then up to the user callback function to search for the uri file. c130219
Signed-off-by: Ian Chen <[email protected]>
Signed-off-by: Ian Chen <[email protected]>
@iche033 Looks like there's a build error on windows. |
Signed-off-by: Ian Chen <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just some minor suggestions; looks good to me
Signed-off-by: Ian Chen <[email protected]>
🎉 New feature
Marked as draft to get feedback. I'll add test and update otherresolveURI
instances if we decide this is the way to go.This PR is ready for review
Summary
Alternative approach to gazebosim/gz-physics#599 for resolving mesh URI relative to
FilePath()
.The following URIs are commonly used:
so I extended.sdf::findFile
to support searching files relative to themodel.sdf
file path* Update: Extended
resolveURI
to take additional search paths when resolving URIs.To actually load the mesh, we'll also need to call
SetStoreResolvedURIs
in gz-sim. Note, I also fixed the typo in theSetStoreResolvedURIs
function name. We'll need to deprecate the original function inmain
.Alternatives considered
The other way is to specify a findFile user callback but it is difficult to do as the user callback needs to take in a different file path (path to model.sdf) for each URI. Given that this relative path URI usage is quite common, I added support directly to
sdf::findFile
instead.Checklist
codecheck
passed (See contributing)Note to maintainers: Remember to use Squash-Merge and edit the commit message to match the pull request summary while retaining
Signed-off-by
messages.