sdformat_urdf
sdformat_urdf copied to clipboard
Handle model:// path in URI
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 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.
@oKermorgant regarding the environment variables, Gazebo will look for URIs (path / URL) in the following order:
- All paths on the
GZ_SIM_RESOURCE_PATH
- Current directory
- Cache ($HOME/.gz)
The SDF_PATH environment variable is not recommended. More details here: https://gazebosim.org/api/sim/7/resources.html
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:
- 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 apackage://
URI, resolve it using resource_retriever". All models in ROS packages could usepackage://
URIs. - Add the ability to resource_retriever to load plugins. Then we could make a plugin that resolved
model://
URIs inros_gz
according to gazebo conventions.
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.
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?
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.
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 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 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