Skip to content
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

Merged
merged 11 commits into from
Mar 5, 2024
Merged

Resolve URIs relative to file path #1373

merged 11 commits into from
Mar 5, 2024

Conversation

iche033
Copy link
Contributor

@iche033 iche033 commented Feb 22, 2024

🎉 New feature

Marked as draft to get feedback. I'll add test and update other resolveURI 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:

          <mesh>
            <uri>some_local_path/box.obj</uri>
          </mesh>

so I extended sdf::findFile to support searching files relative to the model.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 the SetStoreResolvedURIs function name. We'll need to deprecate the original function in main.

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

  • Signed all commits for DCO
  • Added tests
  • Added example and/or tutorial
  • Updated documentation (as needed)
  • Updated migration guide (as needed)
  • Consider updating Python bindings (if the library has them)
  • codecheck passed (See contributing)
  • All tests passed (See test coverage)
  • While waiting for a review on your PR, please help review another open pull request to support the maintainers

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.

@iche033 iche033 marked this pull request as draft February 22, 2024 23:23
@github-actions github-actions bot added the 🎵 harmonic Gazebo Harmonic label Feb 22, 2024
@iche033 iche033 changed the base branch from sdf14 to sdf13 February 22, 2024 23:23
@iche033 iche033 added 🌱 garden Ignition Garden and removed 🎵 harmonic Gazebo Harmonic labels Feb 22, 2024
Copy link

codecov bot commented Feb 22, 2024

Codecov Report

Attention: Patch coverage is 95.34884% with 2 lines in your changes are missing coverage. Please review.

Project coverage is 87.59%. Comparing base (edd5d0b) to head (83af965).
Report is 1 commits behind head on sdf13.

Files Patch % Lines
src/ParserConfig.cc 33.33% 2 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

Copy link
Member

@scpeters scpeters left a 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


/// \brief Get the path to the SDF file.
/// \return Full path to SDF file.
public: const std::string &FilePath() const;
Copy link
Member

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

Copy link
Contributor Author

@iche033 iche033 Feb 23, 2024

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

Copy link
Member

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();
Copy link
Member

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)

Copy link
Contributor Author

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

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());
Copy link
Member

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

Copy link
Member

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();
Copy link
Collaborator

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?

Copy link
Contributor Author

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


/// \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);
Copy link
Collaborator

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:
    1. First do the normal sdf::findFile call
    2. If that fails, prepend the parent directory and try again. (Or we can swap these steps)
  • If the URI is absolute, just do the normal sdf::findFile.

Copy link
Contributor Author

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]>
EXPECT_TRUE(sdf::filesystem::exists(scriptUri));
EXPECT_TRUE(sdf::filesystem::exists(meshVisualUri));
EXPECT_TRUE(sdf::filesystem::exists(meshColUri));
}
Copy link
Collaborator

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.

Copy link
Contributor Author

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]>
@iche033 iche033 requested a review from azeey March 2, 2024 00:12
Signed-off-by: Ian Chen <[email protected]>
@azeey
Copy link
Collaborator

azeey commented Mar 4, 2024

@iche033 Looks like there's a build error on windows.

@iche033
Copy link
Contributor Author

iche033 commented Mar 4, 2024

@iche033 Looks like there's a build error on windows.

fixed in f51bd4b

Copy link
Member

@scpeters scpeters left a 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

src/Utils.cc Show resolved Hide resolved
src/Utils.cc Show resolved Hide resolved
test/integration/resolve_uris.cc Outdated Show resolved Hide resolved
test/integration/resolve_uris.cc Outdated Show resolved Hide resolved
@iche033 iche033 merged commit 2246db8 into sdf13 Mar 5, 2024
13 checks passed
@iche033 iche033 deleted the resolve_uri_filepath branch March 5, 2024 17:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🌱 garden Ignition Garden
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

3 participants