ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | Q&A answers.ros.org
Ask Your Question
0

In ROS2 is it possible to set GAZEBO_MODEL_PATH in launch file?

asked 2022-02-27 05:39:26 -0600

joseecm gravatar image

updated 2022-03-01 07:54:46 -0600

I use ROS2 Galactic and have a package that spawn a URDF robot model in Gazebo. The problem is that the URDF model uses meshes files and Gazebo is not able to find them if I don't append the package install path to GAZEBO_MODEL_PATH. Using the following line the model load without problem:

export GAZEBO_MODEL_PATH=$GAZEBO_MODEL_PATH:/home/ros/Documents/ROS2/ros2_ws/install/mars_robot/share/mars_robot

But I am wondering if it is possible to set that environment variable inside a launch file. I have tried with the following code but it doesn't work.

import os
import xacro

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
from launch_ros.actions import Node
from launch.actions import SetEnvironmentVariable

def generate_launch_description():

    gazebo = IncludeLaunchDescription(
                PythonLaunchDescriptionSource([os.path.join(
                    get_package_share_directory('gazebo_ros'), 'launch'), '/gazebo.launch.py']),
             )

    xacro_robot_pkg_path = os.path.join(
        get_package_share_directory('mars_robot'))

    xacro_file = os.path.join(xacro_robot_pkg_path,
                              'urdf',
                              'mars_robot.xacro')

    doc = xacro.parse(open(xacro_file))
    xacro.process_doc(doc)
    params = {'robot_description': doc.toxml()}

    node_robot_state_publisher = Node(
        package='robot_state_publisher',
        executable='robot_state_publisher',
        output='screen',
        parameters=[params]
    )

    spawn_entity = Node(package='gazebo_ros', executable='spawn_entity.py',
                        arguments=['-topic', 'robot_description',
                                   '-entity', 'mars_robot'],
                        output='screen')

    return launch.LaunchDescription([
        SetEnvironmentVariable(name='GAZEBO_MODEL_PATH', value='/home/ros/Documents/ROS2/ros2_ws/install/mars_robot/share/mars_robot'),
        gazebo,
        node_robot_state_publisher,
        spawn_entity,
    ])

Am I doing something wrong or symply it is not possible what i am trying?

Thanks for your help and best regards.

edit retag flag offensive close merge delete

4 Answers

Sort by » oldest newest most voted
0

answered 2022-02-27 17:09:26 -0600

ljaniec gravatar image

I think you are seeking this functionality:

https://docs.ros.org/en/galactic/How-...

This issue has some examples for using set_env in XML or from launch.actions import SetEnvironmentVariable in Python.

edit flag offensive delete link more

Comments

Thanks for your answer. I have seen the examples and I don't see any difference between them and the use of SetEnvironmentVariable in my code. But the fact is:

This works: export GAZEBO_MODEL_PATH=/home/ros/Documents/ROS2/ros2_ws/install/mars_robot/share/mars_robot

This doesn't work: SetEnvironmentVariable(name='GAZEBO_MODEL_PATH', value='/home/ros/Documents/ROS2/ros2_ws/install/mars_robot/share/mars_robot'),

Any idea what could be the reason?

Best regards.

joseecm gravatar image joseecm  ( 2022-03-01 04:01:21 -0600 )edit

I can see the difference in your return value with LaunchDescription instead of launch.LaunchDescription. It shouldn't matter, though. Maybe try the version with GroupAction too? Is the part with env_value correct for sure? You can try to use SetEnvironmentVariable with some dummy variable with hard-coded value just to see if it's working. Then try to modify the GAZEBO_MODEL_PATH with your path as string - if it works, try to use your env_value too. In the end, you should try @Fetullah Atas version in his answer too.

ljaniec gravatar image ljaniec  ( 2022-03-01 06:19:43 -0600 )edit

I have edited mi original post to simplify the code. As you can see I have hardcoded the path I want to set in GAZEBO_MODEL_PATH, using the same I use with export. The code doesn't work. When I run the launch file Gazebo keeps loading for little more than a minute and at the end links with references to meshes files doesn't appear. I have also try the version with GroupAction and what propose @Fetullah Atas in his answer, but with the same result. I really don't know what is happening.

joseecm gravatar image joseecm  ( 2022-03-01 08:04:18 -0600 )edit

Can you add --verbose to the Gazebo launch parameters? Just to see what kind of problems Gazebo have with this

ljaniec gravatar image ljaniec  ( 2022-03-01 08:42:23 -0600 )edit
1

answered 2022-03-01 05:05:56 -0600

Yes that is possible;

For instance;

from ament_index_python.packages import get_package_share_directory
import os
os.environ['GAZEBO_MODEL_PATH'] = os.path.join(get_package_share_directory('your_gazebo_pkg'),'models')
edit flag offensive delete link more

Comments

Hello, thanks for your answer.

Using the following line on the code also doesn't work:

os.environ['GAZEBO_MODEL_PATH'] = '/home/ros/Documents/ROS2/ros2_ws/install/mars_robot/share/mars_robot'

There must be any difference between setting an environment variable using export and doing it inside launch file because one way works but the other not.

joseecm gravatar image joseecm  ( 2022-03-01 07:02:42 -0600 )edit

Are you sure you are marking the models folder for installation in your CmakeLists ?

Fetullah Atas gravatar image Fetullah Atas  ( 2022-03-01 07:38:17 -0600 )edit

You need to collect all your gazebo models in one folder named “models”, you also need to make sure this folder is installed alongside maybe your “launch” folder in CmakeLists. Finally, you need append your path with “models” as well, “…mars_robot/models/“

Fetullah Atas gravatar image Fetullah Atas  ( 2022-03-01 07:44:43 -0600 )edit

I have no CmakeLists because it is a python package.

joseecm gravatar image joseecm  ( 2022-03-01 08:12:10 -0600 )edit
1

answered 2022-03-01 10:15:25 -0600

joseecm gravatar image

updated 2022-03-01 10:16:54 -0600

When things don't seem to make sense, it's better to stop and review those seemingly unimportant things that you don't doubt you're doing right, because you're probably making a silly mistake. And that is precisely what was happening to me. Both the use of SetEnvironmentVariable and os.environ work correctly when I use them inside the launch file. The problem was that to save typing the same thing many times in the console, I was using the option to reuse previous commands and I didn't realize that I was executing another launch file that had the same name except for one character. That's why no matter what I modified in the code it never worked.

The following code works perfectly:

import os
import xacro

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
from launch_ros.actions import Node
from launch.actions import SetEnvironmentVariable

def generate_launch_description():

    pkg_install_path = get_package_share_directory('mars_robot')

    if 'GAZEBO_MODEL_PATH' in os.environ:
        model_path =  os.environ['GAZEBO_MODEL_PATH'] + ':' + pkg_install_path
    else:
        model_path =  pkg_install_path

    gazebo = IncludeLaunchDescription(
                PythonLaunchDescriptionSource([os.path.join(
                    get_package_share_directory('gazebo_ros'), 'launch'), '/gazebo.launch.py']),
             )

    xacro_robot_pkg_path = os.path.join(
        get_package_share_directory('mars_robot'))

    xacro_file = os.path.join(xacro_robot_pkg_path,
                              'urdf',
                              'mars_robot.xacro')

    doc = xacro.parse(open(xacro_file))
    xacro.process_doc(doc)
    params = {'robot_description': doc.toxml()}

    node_robot_state_publisher = Node(
        package='robot_state_publisher',
        executable='robot_state_publisher',
        output='screen',
        parameters=[params]
    )

    spawn_entity = Node(package='gazebo_ros', executable='spawn_entity.py',
                        arguments=['-topic', 'robot_description',
                                   '-entity', 'mars_robot'],
                        output='screen')

    return LaunchDescription([
        SetEnvironmentVariable(name='GAZEBO_MODEL_PATH', value=model_path),
        gazebo,
        node_robot_state_publisher,
        spawn_entity,
    ])

Thanks to @ljaniec and @Fetullah Atas for their help, they both gave me a correct solution and allowed me to learn a bit more.

edit flag offensive delete link more
0

answered 2022-03-01 08:57:39 -0600

tompe17 gravatar image

I use sdf file and have a script that spawn the sdf file and the script finds the model.sdf. The meshes are found it seems if they are specified relative to the model directory used (I cannot find documentation of exactly what "model" means here...):

  <mesh>
    <uri>model://matrice_100/meshes/lrs_m100.dae</uri>
  </mesh>

This works for me. I also found https://stackoverflow.com/questions/8... which talks about why the simple approach just setting the environment from Python variable will not work. Maybe some of the suggestions there can be adopted to solve it by setting the variable.

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

2 followers

Stats

Asked: 2022-02-27 05:39:26 -0600

Seen: 338 times

Last updated: Mar 01