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

Revision history [back]

click to hide/show revision 1
initial version

You can add launch_arguments when you call IncludeLaunchDescription

That said, looking over your sample launch file, I would suggest you to use DeclareLaunchArgument instead of input() to define whatever inputs you want to the launch file, so they can be given without the need for user input.

Question #306935 gives an example (for Crystal, but should still hold up in Foxy).

You can add launch_arguments when you call IncludeLaunchDescription

That said, looking over your sample launch file, I would suggest you to use DeclareLaunchArgument instead of input() to define whatever inputs you want to the launch file, so they can be given without the need for user input.

Question #306935 gives an example (for Crystal, but should still hold up in Foxy).

Edit - Adding a quick example for clarity:

main.launch.py could contain

import os

from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions.declare_launch_argument import DeclareLaunchArgument
from launch.actions.include_launch_description import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node  

def generate_launch_description():
    # defining platform
    platform_arg = DeclareLaunchArgument(
        'platform',
        default_value='newholland_t7',  # default value is optional
        description='select either newholland_t7 or fort_rd25')

    # some other things

    # include secondary launch file that takes in the platform argument
    launch2 = IncludeLaunchDescription(
                       PythonLaunchDescriptionSource([get_package_share_directory('my_package'), '/secondary.launch.py']),
                       launch_arguments=[('platform', LaunchConfiguration('platform')],
                   )

    ld = LaunchDescription()
    ld.add_action(platform_arg )
    ld.add_action(launch2 )

    # add some other actions

    return ld

and then secondary.launch.py could contain:

import os

from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions.declare_launch_argument import DeclareLaunchArgument
from launch.actions.include_launch_description import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node  

def generate_launch_description():
    # defining platform
    platform_arg = DeclareLaunchArgument(
        'platform',
        default_value='newholland_t7',  # default value is optional
        description='select either newholland_t7 or fort_rd25')

    # some other things

    ld = LaunchDescription()
    ld.add_action(platform_arg)

    # add some other actions

    return ld

You can add launch_arguments when you call IncludeLaunchDescription

That said, looking over your sample launch file, I would suggest you to use DeclareLaunchArgument instead of input() to define whatever inputs you want to the launch file, so they can be given without the need for user input.

Question #306935 gives an example (for Crystal, but should still hold up in Foxy).

Edit - Adding a quick example for clarity:

main.launch.py could contain

import os

from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions.declare_launch_argument import DeclareLaunchArgument
from launch.actions.include_launch_description import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node  

def generate_launch_description():
    # defining platform
    platform_arg = DeclareLaunchArgument(
        'platform',
        default_value='newholland_t7',  # default value is optional
        description='select either newholland_t7 or fort_rd25')

    # some other things

    # include secondary launch file that takes in the platform argument
    launch2 = IncludeLaunchDescription(
                       PythonLaunchDescriptionSource([get_package_share_directory('my_package'), '/secondary.launch.py']),
                       launch_arguments=[('platform', LaunchConfiguration('platform')],
                   )

    ld = LaunchDescription()
    ld.add_action(platform_arg )
    ld.add_action(launch2 )

    # add some other actions

    return ld

and then secondary.launch.py could contain:

import os

from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions.declare_launch_argument import DeclareLaunchArgument
from launch.actions.include_launch_description import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node  
from launch.substitutions import PathJoinSubstitution

def generate_launch_description():
    # defining platform
    platform_arg = DeclareLaunchArgument(
        'platform',
        default_value='newholland_t7',  # default value is optional
        description='select either newholland_t7 or fort_rd25')

    # LaunchConfiguration concatenation is a bit indirect, but using additional launch arguments works well (per https://answers.ros.org/question/358655/ros2-concatenate-string-to-launchargument/ )
    platform_yaml = DeclareLaunchArgument('platform_yaml', default_value=[LaunchConfiguration('platform_arg'), '.yaml'])
    platform_urdf = DeclareLaunchArgument('platform_yaml', default_value=[LaunchConfiguration('platform_arg'), '.urdf.xml'])

   # get path to some file depending on the launch argument
   platform_urdf_path = PathJoinSubstitution(get_package_share_directory('my_package'), 'urdf', LaunchConfiguration('platform_urdf'))    
   platform_yaml_path = PathJoinSubstitution(get_package_share_directory('my_package'), 'urdf', LaunchConfiguration('platform_yaml'))    

    # some other things

    ld = LaunchDescription()
    ld.add_action(platform_arg)

    # add some other actions

    return ld

You can add launch_arguments when you call IncludeLaunchDescription

That said, looking over your sample launch file, I would suggest you to use DeclareLaunchArgument instead of input() to define whatever inputs you want to the launch file, so they can be given without the need for user input.

Question #306935 gives an example (for Crystal, but should still hold up in Foxy).

Edit - Adding a quick example for clarity:

main.launch.py could contain

import os

from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions.declare_launch_argument import DeclareLaunchArgument
from launch.actions.include_launch_description import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node  

def generate_launch_description():
    # defining platform
    platform_arg = DeclareLaunchArgument(
        'platform',
        default_value='newholland_t7',  # default value is optional
        description='select either newholland_t7 or fort_rd25')

    # some other things

    # include secondary launch file that takes in the platform argument
    launch2 = IncludeLaunchDescription(
                       PythonLaunchDescriptionSource([get_package_share_directory('my_package'), '/secondary.launch.py']),
                       launch_arguments=[('platform', LaunchConfiguration('platform')],
                   )

    ld = LaunchDescription()
    ld.add_action(platform_arg )
    ld.add_action(launch2 )

    # add some other actions

    return ld

and then secondary.launch.py could contain:

import os

from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions.declare_launch_argument import DeclareLaunchArgument
from launch.actions.include_launch_description import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node  
from launch.substitutions import PathJoinSubstitution

def generate_launch_description():
    # defining platform
    platform_arg = DeclareLaunchArgument(
        'platform',
        default_value='newholland_t7',  # default value is optional
        description='select either newholland_t7 or fort_rd25')

    # LaunchConfiguration concatenation is a bit indirect, but using additional launch arguments works well (per https://answers.ros.org/question/358655/ros2-concatenate-string-to-launchargument/ )
    platform_yaml = DeclareLaunchArgument('platform_yaml', default_value=[LaunchConfiguration('platform_arg'), '.yaml'])
    platform_urdf = DeclareLaunchArgument('platform_yaml', default_value=[LaunchConfiguration('platform_arg'), '.urdf.xml'])

   # get path to some file depending on the launch argument
   platform_urdf_path = PathJoinSubstitution(get_package_share_directory('my_package'), 'urdf', LaunchConfiguration('platform_urdf'))    
   platform_yaml_path = PathJoinSubstitution(get_package_share_directory('my_package'), 'urdf', LaunchConfiguration('platform_yaml'))    

    # some other things

    ld = LaunchDescription()
    ld.add_action(platform_arg)

    # add some other actions

    return ld

More compact solution:

main.launch.py would be the same... and then secondary.launch.py could contain:

import ...

def generate_launch_description():
    # defining platform
    platform_arg = DeclareLaunchArgument(
        'platform',
        default_value='newholland_t7',  # default value is optional
        description='select either newholland_t7 or fort_rd25')

platform_path = PathJoinSubstitution(get_package_share_directory('my_package'), 'urdf', LaunchConfiguration('platform'))

# get contents of urdf file using Command substitution and `cat` command to print file to output
robot_description = Command(['cat ', platform_path, '.urdf.xml'])

urdf_publisher = Node(
    package="robot_state_publisher",
    executable="robot_state_publisher",
    name="robot_state_publisher",
    parameters=[{"robot_description": robot_description}],
    output="screen",
)

visualize_markers = Node(
    package="visualize_markers",
    executable="visualize_markers_node",
    name="visualize_markers",
    parameters=[('parameter_name', [platform_path, '.yaml'])],  # not sure what the intended parameter name is
    output="screen"
)

...

The above works because a Node's 'arguments' take take SomeSubstitutionType, which supports an iterable (a list) of Substitutions (e.g. Launch Configurations) and Text (strings). 'parameters' take SomeParameters which ultimately include SomeSubstitutionType, so they can also accept lists of Substitutions and text.

When either is evaluating the value of a given combination of substitutions and texts, they get concatenated!