Skip to content

How to launch multiple arm with single description file? #825

@catmulti7

Description

@catmulti7

Hi,
I've got a dual-arm system which has 2 UR5 arms fixed on a base. My plan is to run 2 driver in different namespace and control these arms separately with MoveIt2.
Since it is possible that two arm collide with each other or base, I want to wrote a description file include base and both arm so MoveIt can plan a safe path for me. I have done this with ROS1, but I'm not sure if I can do same thing with ROS2.
I followed UniversalRobots/Universal_Robots_ROS2_Description#70 to write the description file, but I'm not so sure about how to launch driver in different namespace. I tried to run ur_control.launch.py twice with different namespace, but it seems only one arm is launched successfully. Here is my launch file.

import os
from ament_index_python.packages import get_package_share_directory
from launch.actions import IncludeLaunchDescription
from launch import LaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.actions import DeclareLaunchArgument, LogInfo
from launch.substitutions import LaunchConfiguration

from launch.actions import GroupAction
from launch_ros.actions import PushRosNamespace


def generate_launch_description():

    ur_type = LaunchConfiguration('ur_type') 
    arm_0_robot_ip = LaunchConfiguration('arm_0_robot_ip') 
    arm_0_controller_file = LaunchConfiguration('arm_0_controller_file') 
    arm_0_tf_prefix = LaunchConfiguration('arm_0_tf_prefix') 
    arm_0_script_command_port = LaunchConfiguration('arm_0_script_command_port')

    arm_1_robot_ip = LaunchConfiguration('arm_1_robot_ip') 
    arm_1_controller_file = LaunchConfiguration('arm_1_controller_file') 
    arm_1_tf_prefix = LaunchConfiguration('arm_1_tf_prefix') 
    arm_1_script_command_port = LaunchConfiguration('arm_1_script_command_port')

    # # UR specific arguments
    ur_type_arg = DeclareLaunchArgument(
            "ur_type",
            default_value='ur5',
            description="Type/series of used UR robot.",
            choices=["ur3", "ur3e", "ur5", "ur5e", "ur10", "ur10e", "ur16e", "ur20"],
    )
    arm_0_robot_ip_arg = DeclareLaunchArgument(
            "arm_0_robot_ip",
            default_value='192.168.56.3',
            description="IP address by which the robot can be reached.",
    )
    arm_0_controller_file_arg = DeclareLaunchArgument(
            "arm_0_controller_file",
            default_value="arm_0_ur_controllers.yaml",
            description="YAML file with the controllers configuration.",
    )
    arm_0_tf_prefix_arg = DeclareLaunchArgument(
            "arm_0_tf_prefix",
            default_value="arm_0_",
            description="tf_prefix of the joint names, useful for \
            multi-robot setup. If changed, also joint names in the controllers' configuration \
            have to be updated.",
    )

    arm_0_script_command_port_arg =  DeclareLaunchArgument(
            "arm_0_script_command_port",
            default_value="50001",
            description="Port that will be opened to forward script commands from the driver to the robot",
        )


    arm_1_robot_ip_arg = DeclareLaunchArgument(
            "arm_1_robot_ip",
            default_value='192.168.56.101',
            description="IP address by which the robot can be reached.",
    )
    arm_1_controller_file_arg = DeclareLaunchArgument(
            "arm_1_controller_file",
            default_value="arm_1_ur_controllers.yaml",
            description="YAML file with the controllers configuration.",
    )
    arm_1_tf_prefix_arg = DeclareLaunchArgument(
            "arm_1_tf_prefix",
            default_value="arm_1_",
            description="tf_prefix of the joint names, useful for \
            multi-robot setup. If changed, also joint names in the controllers' configuration \
            have to be updated.",
    )
    arm_1_script_command_port_arg =  DeclareLaunchArgument(
            "arm_1_script_command_port",
            default_value="50006",
            description="Port that will be opened to forward script commands from the driver to the robot",
        )

    

    ur_launch_dir = get_package_share_directory('ur_robot_driver')

    arm_0 = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(os.path.join(ur_launch_dir, 'launch', 'ur_control.launch.py')),
        launch_arguments={'ur_type': ur_type,
                          'robot_ip': arm_0_robot_ip,
                          'controllers_file': arm_0_controller_file,
                          'tf_prefix': arm_0_tf_prefix,
                          'script_command_port': arm_0_script_command_port}.items())
    
    arm_0_with_namespace = GroupAction(
     actions=[
         PushRosNamespace('arm_0'),
         arm_0
      ]
    )

    arm_1 = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(os.path.join(ur_launch_dir, 'launch', 'ur_control.launch.py')),
        launch_arguments={'ur_type': ur_type,
                          'robot_ip': arm_1_robot_ip,
                          'controllers_file': arm_1_controller_file,
                          'tf_prefix': arm_1_tf_prefix,
                          'script_command_port': arm_1_script_command_port
                          }.items())
    
    arm_1_with_namespace = GroupAction(
     actions=[
         PushRosNamespace('arm_1'),
         arm_1
      ]
    )

    
    return LaunchDescription([
        ur_type_arg,
        arm_0_robot_ip_arg,
        arm_0_controller_file_arg,
        arm_0_tf_prefix_arg,
        arm_0_script_command_port_arg,
        arm_1_robot_ip_arg,
        arm_1_controller_file_arg,
        arm_1_tf_prefix_arg,
        arm_1_script_command_port_arg,
        arm_0_with_namespace,
        arm_1_with_namespace
    ])

and I got

[ur_ros2_control_node-12] terminate called after throwing an instance of 'std::system_error'
[ur_ros2_control_node-12]   what():  Failed to bind socket for port 50001 to address. Reason: Address already in use: Address already in use
[ur_ros2_control_node-1] [WARN] [1695810663.355767038] [UR_Client_Library:arm_0_]: Connection attempt on port 50001 while maximum number of clients (1) is already connected. Closing connection.
[ur_ros2_control_node-1] [WARN] [1695810663.363975935] [UR_Client_Library:arm_0_]: Connection attempt on port 50004 while maximum number of clients (1) is already connected. Closing connection.
[ur_ros2_control_node-1] [WARN] [1695810663.372521821] [UR_Client_Library:arm_0_]: Connection attempt on port 50005 while maximum number of clients (1) is already connected. Closing connection.

I already set different ports for both arms in description file so this error really confuse me. My description file is here
I hope somebody can give me a instruction about how to fix my launch file or a example of launch multiple arm.
Thank you for reading my issue and help me.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions