Skip to content

ROS 2 Migration: Gazebo ROS Paths

Oğuz Özdemir edited this page Dec 19, 2023 · 6 revisions

Overview

If your package is exporting resources like models and plugins that need to be found by Gazebo, you need to install them and export the install paths. Gazebo will look on those paths to resolve URI schemas like model:// and package://.

On ROS 1, there were 2 ways to export your packages paths so that they're picked up by gazebo_ros:

  1. Using <export><gazebo_ros....></export>
  2. Loading the gazebo_ros_paths plugin

This pages describes how to migrate both of these for ROS 2.

gazebo_ros_paths plugin

  • The functionality is offered by gazebo_ros_paths.py in gazebo_ros.
  • It is no longer a plugin but a python script which is used by gzserver.launch.py and gzclient.launch.py while launch gzserver and gzclient respectively.
  • The plugin no longer sources gazebo's setup.sh.
  • This is convenient when using gazebo_ros's launch files, but the environment variables won't be set when you source your setup file.

Usage

  1. Install resources like models, plugins, worlds and other media files. You can do the following on your CMakeLists.txt for example:

    install(DIRECTORY
      models
      DESTINATION share/${PROJECT_NAME}/
    )
    install(DIRECTORY
      worlds
      DESTINATION share/${PROJECT_NAME}/
    )
    install(DIRECTORY
      media
      DESTINATION share/${PROJECT_NAME}/
    )
    install(TARGETS
      myPlugin
      DESTINATION lib
    )
    
  2. Inside your package.xml, export the install paths above:

    <export>
      <gazebo_ros gazebo_plugin_path="lib"/>
      <gazebo_ros gazebo_model_path="${prefix}/models"/>
      <gazebo_ros gazebo_media_path="${prefix}/worlds:${prefix}/media"/>
    </export>
    

    The variables correspond to the following environment variables:

    • gazebo_plugin_path: GAZEBO_PLUGIN_PATH
    • gazebo_model_path: GAZEBO_MODEL_PATH
    • gazebo_media_path: GAZEBO_RESOURCE_PATH

    This will not set the environment variables directly, but will make the values available to gazebo_ros.

  3. Include gazebo.launch.py in your launch file, and that will set the environment variables correctly. For example:

    from ament_index_python.packages import get_package_share_directory
    from launch import LaunchDescription
    from launch.actions import IncludeLaunchDescription
    from launch.launch_description_sources import PythonLaunchDescriptionSource
    
    def generate_launch_description():
    
        pkg_gazebo_ros = get_package_share_directory('gazebo_ros')
    
        return LaunchDescription([
            IncludeLaunchDescription(
                PythonLaunchDescriptionSource(
                    os.path.join(pkg_gazebo_ros, 'launch', 'gazebo.launch.py'),
                )
            )
        ])
    

    You can also use the GazeboRosPaths script directly, as done here.

env hooks

  • Env hooks directly set variables needed by Gazebo when your package's setup file is sourced.

Usage

  1. Install resources the same way as above.

  2. Create an env-hooks directory with files to be sourced. For example, project_name.sh.in:

    # $AMENT_CURRENT_PREFIX is replaced with /opt/ros/<distro>/share/ on clean builds, that's why using $COLCON_CURRENT_PREFIX instead.
    ament_prepend_unique_value GAZEBO_MODEL_PATH "$COLCON_CURRENT_PREFIX/share/@PROJECT_NAME@/models"
    ament_prepend_unique_value GAZEBO_RESOURCE_PATH "$COLCON_CURRENT_PREFIX/share/@PROJECT_NAME@/worlds"
    ament_prepend_unique_value GAZEBO_RESOURCE_PATH "$COLCON_CURRENT_PREFIX/share/@PROJECT_NAME@/media"
    ament_prepend_unique_value GAZEBO_PLUGIN_PATH "$COLCON_CURRENT_PREFIX/lib"
    

    Since ROS 2 Eloquent, you can also use .dsv files. A project_name.dsv.in template would look like this:

    prepend-non-duplicate;GAZEBO_MODEL_PATH;share/@PROJECT_NAME@/models
    prepend-non-duplicate;GAZEBO_RESOURCE_PATH;share/@PROJECT_NAME@/worlds
    prepend-non-duplicate;GAZEBO_RESOURCE_PATH;share/@PROJECT_NAME@/media
    prepend-non-duplicate;GAZEBO_PLUGIN_PATH;share/@PROJECT_NAME@/plugins
    
  3. In your CMakeLists.txt file, generate the templates with:

    ament_environment_hooks("${CMAKE_CURRENT_SOURCE_DIR}/env-hooks/${PROJECT_NAME}.sh.in")
    ament_environment_hooks("${CMAKE_CURRENT_SOURCE_DIR}/env-hooks/${PROJECT_NAME}.dsv.in")
    

Now when your source setup.sh, the variables will be properly set.

Example

A quick example to explain the easiest way to use env-hooks.

Imagine this is your package, you will need the following structure:

robot_description_package/
-env-hooks/
--robot_description_package.dsv.in
-models
--my_robot_model/
---meshes/
----my_mesh.stl
---my_robot.urdf
---model.config
CMakeLists.txt
package.xml

Your robot_description_package.dsv.in file will look like this:

prepend-non-duplicate;GAZEBO_MODEL_PATH;share/robot_description_package/models

In myrobot.urdf you will use the following line to address your mesh (Note that you start your path file directly after the path as dictated in your dsv file):

<visual>
  <geometry>
    <mesh filename="model://my_robot_model/meshes/my_mesh.stl"/>
  </geometry>
</visual>

In 'model.config' you define some basic stuff about your robot, a simple file would look something like this (of course you don't need to add an author):

<?xml version="1.0"?>

<model>
  <name>myRobot</name>
  <version>2.0</version>
  <sdf version="1.6">my_robot.urdf</sdf>

  <author>
    <name>yourname</name>
    <email>yourname@TODO.TODO</email>
  </author>

  <description>
    your description
  </description>
</model>

In your CMakeLists.txt you will need to add the following lines:

install(
  DIRECTORY models
  DESTINATION share/${PROJECT_NAME}
)

ament_environment_hooks("${CMAKE_CURRENT_SOURCE_DIR}/env-hooks/robot_description_package.dsv.in")

And then you should be ready to go! If you want more models, it will look something like this:

robot_description_package/
-env-hooks/
--robot_description_package.dsv.in
-models
--my_robot_model/
---meshes/
----my_mesh.stl
---my_robot.urdf
---model.config
--my_second_model/
---meshes/
----my_second_mesh.stl
---my_second_robot.urdf
---model.config
CMakeLists.txt
package.xml

And all you will need to do is write the model.config for your second robot, and that's it.