sdformat_urdf icon indicating copy to clipboard operation
sdformat_urdf copied to clipboard

Handle model:// path in URI

Open oKermorgant opened this issue 1 year ago • 9 comments

Hi,

This PR is to convert URI's starting with model:// to absolute paths, by using classical Gazebo environment variables.

While it does not answer all cases (http link / relative path), many models just rely on model:// meshes which are resolved here.

I am not sure on the order the environment variables should be processed (see here).

oKermorgant avatar Apr 04 '23 17:04 oKermorgant

@oKermorgant Thanks for your contribution! Do you mind refactoring the header a bit based on the suggestions by the workflow run, like one here, it's mostly reformatting, missing spaces, etc.

quarkytale avatar May 03 '23 22:05 quarkytale

@oKermorgant regarding the environment variables, Gazebo will look for URIs (path / URL) in the following order:

  1. All paths on the GZ_SIM_RESOURCE_PATH
  2. Current directory
  3. Cache ($HOME/.gz)

The SDF_PATH environment variable is not recommended. More details here: https://gazebosim.org/api/sim/7/resources.html

quarkytale avatar Aug 16 '23 20:08 quarkytale

This is an interesting one. On the ROS side resource_retriever can handle package:// URIs, but by default SDFormat only supports model://.

libsdformat is able to parse URDF, and during that it converts package:// to model://, and as long as someone makes their package add its installed model directory to gazebo related paths (like an ament environment hook with a dsv file containing prepend-non-duplicate;IGN_GAZEBO_RESOURCE_PATH;@CMAKE_INSTALL_PREFIX@/share/@PROJECT_NAME@/models) then gazebo can load models from a ROS package using the model:// URI. libsdformat also has anAPI for adding paths to look at per URI scheme.

I think my favorite solution would be one or both of these instead of resolving the URI here:

  1. Add an API to libsdformat that registered a callback for a URI scheme. Then we could add a plugin to ros_gz that said "if given a package:// URI, resolve it using resource_retriever". All models in ROS packages could use package:// URIs.
  2. Add the ability to resource_retriever to load plugins. Then we could make a plugin that resolved model:// URIs in ros_gz according to gazebo conventions.

sloretz avatar Aug 28 '23 18:08 sloretz

Hi,

Indeed the whole thing is about ROS and Gazebo coupling through having to parse possibly the same URDF and SDF files.

To my experience, URIs starting with package:// (e.g. classical URDF) may not be resolved by Gazebo, which does not understand pure ROS packages. On the opposite, ROS has no idea what a model:// is. I tend to use file://$(find pkg) with xacro but then problems arise when sharing a robot description among several computers, as the absolute path may not be valid on another computer.

I came into this issue when playing with pure Gazebo models I wanted to run a robot_state_publisher for, hence resolving model:// URIs. If any broader approach seems useful I'll be happy to help.

oKermorgant avatar Aug 30 '23 17:08 oKermorgant

Recently ran into this problem and opened #25 without noticing this PR.

I think @sloretz's suggestions make sense. I could work on 1) if it is still unimplemented?

Yadunund avatar Feb 13 '24 03:02 Yadunund

Hi, I am not familiar enough with libsdformat and ros_gz plugins to deal with the suggestions, so feel free to tackle this one.

For my use cases resolving URI based on Gazebo environment variables is fine, though dealing with nested models would be a bit better.

oKermorgant avatar Feb 13 '24 09:02 oKermorgant

The problem with (1) is that we have a chicken and egg problem. Gazebo plugins are currently read from SDF files, which requires loading the model or world SDF that also contains the paths we need to resolve. The plugin would not have a chance to configure libsdformat to know about package://.

Another solution might be to add the share directories (actually the parent of that) of all the dependencies of a package to GZ_SIM_RESOURCE_PATH before starting Gazebo. Then, Gazebo should be able to resolve paths like package://<package_name>/models/foo. For example, if we have the following files installed

<prefix>/turtlebot3_gazebo/share/turtlebot3_gazebo/models/turtlebot3_waffle
<prefix>/turtlebot3_gazebo/share/turtlebot3_gazebo/models/turtlebot3_waffle/model-1_4.sdf
<prefix>/turtlebot3_gazebo/share/turtlebot3_gazebo/models/turtlebot3_waffle/model.config
<prefix>/turtlebot3_gazebo/share/turtlebot3_gazebo/models/turtlebot3_waffle/model.sdf

We can add <prefix>/turtlebot3_gazebo/share/ to GZ_SIM_RESOURCE_PATH , which is the output of os.path.join(get_package_prefix('turtlebot3_gazebo'), 'share') or "$(ros2 pkg prefix turtlebot3_gazebo)/share" (not ros2 pkg prefix --share turtlebot3_gazebo since that includes an extra package name at the end). Gazebo should then be able to resolve package://turtlebot3_gazebo/models/turtlebot3_waffle.

We would provide a launch helper python module to do this. https://github.com/gazebosim/ros_gz/pull/492/ is doing something similar on a more global scale to replicate what we had in Gazebo Classic. Maybe adding all available packages instead of just dependencies to the path might work too.

azeey avatar Feb 14 '24 19:02 azeey

@azeey the approach you shared worked like a charm! ✨ I added the <prefix>/ros_pkg/share to my gazebo_paths.dsv.in file such that GZ_SIM_RESOURCE_PATH is set as recommended when I source the workspace.

This commit could serve as a useful reference for others.

Further, I've opened https://github.com/ros/sdformat_urdf/pull/26 to add information from your comment to the README. I guess we could close this PR and my ticket with that?

Yadunund avatar Feb 17 '24 15:02 Yadunund

@Yadunund Glad it worked! I've also created https://github.com/gazebosim/ros_gz/issues/497 that would eventually allow us to do (1) from https://github.com/ros/sdformat_urdf/pull/20#issuecomment-1696208691

azeey avatar Feb 17 '24 17:02 azeey