ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
1

[ROS2] How best to conditionally include a prefix in a launch.py file

asked 2020-10-19 18:49:55 -0500

paul.frivold gravatar image

I have a simple .launch.py file in ROS2 Foxy:

def generate_launch_description():
    n = launch_ros.actions.Node(
        package='my_pkg',
        executable='my_node',
        prefix='some_prefix'
    )

    return launch.LaunchDescription([n])

However, I'd like to only add the launch prefix if some condition is True.

I have several nodes where I'd be conditionally adding the prefix, so putting an if around the all of the launch_ros.actions.Node() calls would be rather ugly.

Any advice on the cleanest way to do this? Can I use substitutions for this somehow?

edit retag flag offensive close merge delete

3 Answers

Sort by ยป oldest newest most voted
2

answered 2020-10-27 14:02:39 -0500

paul.frivold gravatar image

updated 2020-10-27 15:54:48 -0500

Edit: Just stumbled across a simpler solution in Gazebo's launch files: https://github.com/shiveshkhaitan/gaz...

def generate_launch_description():
    use_prefix = (EnvironmentVariable('SOME_VAR', default_value='0').perform(LaunchContext()) == '1')
    n = launch_ros.actions.Node(
        package='my_pkg',
        executable='my_node',
        prefix=PythonExpression(['"some_prefix" if "1" == "', EnvironmentVariable('SOME_VAR', default_value='0'), '" else ""']),
    )

return launch.LaunchDescription([n])

Anyway, here's my original solution:

I ended up using a custom Substitution. Not sure if that's the cleanest solution, but it worked for me.

class ConditionalText(Substitution):
    def __init__(self, text, condition):
        self.text = text
        self.condition = condition

    def perform(self, context: 'LaunchContext') -> Text:
        if self.condition:
            return self.text
        else:
            return ''

Putting everything together:

def generate_launch_description():
    use_prefix = (EnvironmentVariable('SOME_VAR', default_value='0').perform(LaunchContext()) == '1')
    n = launch_ros.actions.Node(
        package='my_pkg',
        executable='my_node',
        prefix=ConditionalText('some_prefix', use_prefix),
    )

return launch.LaunchDescription([n])
edit flag offensive delete link more
3

answered 2020-10-20 13:25:57 -0500

jacobperron gravatar image

You might be able to use launch.substitutions.LaunchConfiguration to achieve what you want.

For example, the following will substitute the value of the launch argument "my_arg" if it is provided or an empty string if it is not:

 n = launch_ros.actions.Node(
     package='my_pkg',
     executable='my_node',
     prefix=launch.substitutions.LaunchConfiguration('my_arg', default='')
 )

"my_arg" can be set from the command line like so:

ros2 launch my.launch.py my_arg:="some_prefix"

Alternatively, you can set the argument inside a launch file with launch.actions.SetLaunchConfiguration. Here's a complete example based on your question:

def generate_launch_description():
    set_launch_config = launch.actions.SetLaunchConfiguration(
        'my_arg', 'some_prefix'
    )
    n = launch_ros.actions.Node(
        package='my_pkg',
        executable='my_node',
        prefix='some_prefix'
    )

    return launch.LaunchDescription([set_launch_config, n])

Note, I think using SetlaunchConfiguration precludes setting the value from the command-line.

edit flag offensive delete link more

Comments

Hey there, thanks for the answer! Sorry for being so slow to follow up.

In my case I wanted to set the prefix if a certain environment variable was set to a certain value. So using launch configuration didn't really work for me. That said, I didn't realize you could set it like that, hmm interesting.

In the end I created a custom substitution class, not sure if that's the cleanest solution, but it worked for me.

paul.frivold gravatar image paul.frivold  ( 2020-10-27 13:53:49 -0500 )edit
1

Cool, glad you found a solution. I'm not sure how much control you have over that environment variable, but you could also use it's value directly as the prefix.

jacobperron gravatar image jacobperron  ( 2020-10-27 15:34:42 -0500 )edit

Just stumbled across another possible solution from Gazebo's Github:

prefix=PythonExpression(['"some_prefix" if "1" == "', EnvironmentVariable('SOME_VAR', default_value='0'), '" else ""'])
paul.frivold gravatar image paul.frivold  ( 2020-10-27 15:57:22 -0500 )edit
0

answered 2020-10-28 00:36:51 -0500

KenYN gravatar image

What I use is this:

DeclareLaunchArgument('bag_version', default_value=['v2'], description='BAG file version, v1 or v2'),
DeclareLaunchArgument('bag_full_path', default_value=[''], description='Full path to BAG file'),

Ros1BagPlayNode = launch.actions.ExecuteProcess(
    cmd=['ros2', 'bag', 'play', '-s', 'rosbag_v2', LaunchConfiguration('bag_full_path')],
    name='rosbag_play',
    output='log',
    condition=IfCondition(PythonExpression(["'", LaunchConfiguration('bag_version'), "' == 'v1'"]))
)
Ros2BagPlayNode = launch.actions.ExecuteProcess(
    cmd=['ros2', 'bag', 'play', LaunchConfiguration('bag_full_path')],
    name='rosbag_play',
    output='log',
    condition=IfCondition(PythonExpression(["'", LaunchConfiguration('bag_version'), "' == 'v2'"]))
)

Then I can use ros2 launch foo.launch.py bag_full_path:=/a/b/c.bag bag_version:=v1 to allow me to switch between v1 and v2 bag file playback. If you're launching a Node, though, the above method is better.

edit flag offensive delete link more

Comments

2

If you want to condition on a LaunchConfiguration, I recommend trying out LaunchConfigurationEquals and LaunchConfigurationNotEquals (available since Foxy). Example usage:

Ros1BagPlayNode = launch.actions.ExecuteProcess(
    cmd=['ros2', 'bag', 'play', '-s', 'rosbag_v2', LaunchConfiguration('bag_full_path')],
    name='rosbag_play',
    output='log',
    condition=LaunchConfigurationEquals('bag_version', 'v1')
)
jacobperron gravatar image jacobperron  ( 2020-10-28 11:57:08 -0500 )edit

Thanks - I remember a few months back following that GitHub issue, so it's good to see it's been implemented.

KenYN gravatar image KenYN  ( 2020-10-29 01:38:37 -0500 )edit

Question Tools

2 followers

Stats

Asked: 2020-10-19 18:49:55 -0500

Seen: 2,560 times

Last updated: Oct 28 '20