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

[ROS2] Launch same node several times using same launch file

asked 2022-04-08 13:42:37 -0500

updated 2022-04-08 16:46:37 -0500

Hello everyone!

Perhaps, a bit confusing title, I will try to explain what I want to do:

I am using ROS2 Foxy Fitzroy. I have a C++ node named 'data_processor' which is essentially just a publisher. I have written a launch file takes in arguments and launches the 'data_processor' with a user-defined namespace, named 'data_processor_launch.py'. Now, I want to write a another launch file 'data_processors_all_launch.py', which launches 2 instances of 'data_processor' using the child launch file, but under different namespaces.

I succeed in launching 2 instances of 'data_processors' separately (using the 'data_procesor_launch.py' with namespace 'tm_lm' and using parent launch file 'data_processors_all_launch.py' with just one instance there under namespace 'tb_lm'). But when I try to Include the same launch description twice with different it fails. I believe it should be possible to launch it from one single launch file, because these essentially become different objects.

This is "data_processor_launch.py":

import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.substitutions import LaunchConfiguration

def generate_launch_description():
    value = LaunchConfiguration('namespace', default = 'tb_lm')
    ld = LaunchDescription()
    config = os.path.join(
        get_package_share_directory('loading_motor_dt'),
    'config',
    'params.yaml'
    )

    data_processor=Node(
       package = 'loading_motor_dt',
       namespace = value,
       name = 'data_processor',
       executable = 'currentVoltageFlow',
       parameters = [config]
    )
   d.add_action(data_processor)
   return ld

This is "data_processor_all_launch.py": import os

from click import launch
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource

def generate_launch_description():
    ld = LaunchDescription()

    package_prefix = get_package_share_directory('loading_motor_dt')
    src = PythonLaunchDescriptionSource([package_prefix,'/launch/data_processor_launch.py'])
    launch_tm = IncludeLaunchDescription(src,launch_arguments = {'namespace': 'tm_lm'}.items())
    launch_tb = IncludeLaunchDescription(src,launch_arguments = {'namespace': 'tb_lm'}.items())
    print(launch_tb)
    print(launch_tm)
    ld.add_action(launch_tm)
    ld.add_action(launch_tb)
    return ld

And the following is the error I get when I launch the "data_processor_all_launch.py"

[INFO] [launch]: All log files can be found below /home/sejego/.ros/log/2022-04-08-21-37-47-943060-pop-os-21257
[INFO] [launch]: Default logging verbosity is set to INFO
<launch.actions.include_launch_description.IncludeLaunchDescription object at 0x7f3e72e0c9a0>
<launch.actions.include_launch_description.IncludeLaunchDescription object at 0x7f3e73791880>
Task exception was never retrieved
future: <Task finished name='Task-2' coro=<LaunchService._process_one_event() done, defined at /opt/ros/foxy/lib/python3.8/site-packages/launch/launch_service.py:226> exception=RuntimeError("ExecuteProcess action 'currentVoltageFlow-1': executed more than once: <launch_ros.actions.node.Node object at 0x7f3e723b2700>")>
Traceback (most recent call last):
  File "/opt/ros/foxy/lib/python3.8/site-packages/launch/launch_service.py", line 228, in _process_one_event
    await self.__process_event(next_event)
  File "/opt/ros/foxy/lib/python3.8/site-packages/launch/launch_service.py", line 248, in __process_event
    visit_all_entities_and_collect_futures(entity, self.__context))
  File "/opt/ros/foxy/lib/python3.8/site-packages/launch/utilities/visit_all_entities_and_collect_futures_impl.py", line 45, in visit_all_entities_and_collect_futures
    futures_to_return += visit_all_entities_and_collect_futures(sub_entity, context)
      File "/opt/ros/foxy/lib/python3.8/site-packages/launch/utilities/visit_all_entities_and_collect_futures_impl.py", line 45, in visit_all_entities_and_collect_futures
        futures_to_return += visit_all_entities_and_collect_futures(sub_entity, context)
      File "/opt/ros/foxy/lib/python3.8/site-packages/launch/utilities/visit_all_entities_and_collect_futures_impl.py", line 45, in visit_all_entities_and_collect_futures
        futures_to_return += visit_all_entities_and_collect_futures(sub_entity, context)
      [Previous line repeated 3 more times]
      File "/opt/ros/foxy/lib/python3.8/site-packages/launch/utilities/visit_all_entities_and_collect_futures_impl.py", line 38, in ...
(more)
edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
1

answered 2022-04-09 02:26:56 -0500

updated 2022-04-21 16:06:40 -0500

Okay, after 3 hours or so I figured it out!

So, the problem seems to be with the shared src variable in the data_processor_all_launch.py. I slightly changed both files to enable launching the data_processor_launch.py with user-defined namespaces and to accept the namespace argument from top-level data_processor_all_launch.py.

This is now the data_processor_all_launch.py :

import os

from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions import DeclareLaunchArgument
from launch.actions import IncludeLaunchDescription
from launch.actions import GroupAction
from launch.substitutions import TextSubstitution
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import PushRosNamespace
from launch.substitutions import LaunchConfiguration

def generate_launch_description():

ld = LaunchDescription()

package_prefix = get_package_share_directory('loading_motor_dt')
load_data_processor = PythonLaunchDescriptionSource([package_prefix,'/launch/data_processor_launch.py'])
traction_data_processor = PythonLaunchDescriptionSource([package_prefix,'/launch/data_processor_launch.py'])

launch_traction = GroupAction(
    actions=[
        # push-ros-namespace to set namespace of included nodes
        #PushRosNamespace('tb_lm_left'),
        IncludeLaunchDescription(load_data_processor, launch_arguments = {'namespace':'tb_tm'}.items()),
    ]
)
launch_loading = GroupAction(
    actions=[
        # push-ros-namespace to set namespace of included nodes
        #PushRosNamespace('tb_tm'),
        IncludeLaunchDescription(traction_data_processor, launch_arguments = {'namespace':'tb_tm'}.items()),
    ]
)

ld.add_action(launch_traction)
ld.add_action(launch_loading)
return ld

This is now the data_processor_launch.py:

import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import PushRosNamespace
from launch.actions import GroupAction

def generate_launch_description():

    ns = LaunchConfiguration('namespace', default = 'tb_tm')

    ld = LaunchDescription()
    config = os.path.join(
        get_package_share_directory('loading_motor_dt'),
        'config',
        'params.yaml'
    )

    data_processor=Node(
        package = 'loading_motor_dt',
        name = 'data_processor',
        executable = 'currentVoltageFlow',
        parameters = [config]
    )

    data_processor_with_ns = GroupAction(
        actions=[
            PushRosNamespace(ns),
            data_processor,
        ]
    )

    ld.add_action(data_processor_with_ns)
    return ld

And finally the result:

sejego@pop-os:~/dev_ws$ ros2 node list
/tb_lm_left/data_processor
/tb_tm/data_processor
edit flag offensive delete link more

Comments

I think you wanted other argument here?

#PushRosNamespace('tb_lm_left'),
        IncludeLaunchDescription(load_data_processor, launch_arguments = {'namespace':'tb_tm'}.items()),
ljaniec gravatar image ljaniec  ( 2022-04-09 20:52:16 -0500 )edit
1

@ljaniec you are right, sorry for confusion. I edited my asnwer so it will not be confusing for others. Have a nice day!

sejego gravatar image sejego  ( 2022-04-21 16:07:36 -0500 )edit

Question Tools

1 follower

Stats

Asked: 2022-04-08 13:42:37 -0500

Seen: 1,245 times

Last updated: Apr 21 '22