"""双 RM75 真机遥操作启动入口。 该 launch 文件用于连接左右两台真实 RM75:启动 UDP 手柄接收节点,并分别启动 左、右两个真机遥操作节点。默认不会自动移动到初始点,只有显式设置 `move_to_initial_pose_on_connect:=true` 后才会执行初始化点位移动。 """ from launch import LaunchDescription from launch.actions import DeclareLaunchArgument from launch.conditions import IfCondition from launch.substitutions import LaunchConfiguration, PathJoinSubstitution from launch_ros.actions import Node from launch_ros.parameter_descriptions import ParameterValue from launch_ros.substitutions import FindPackageShare def generate_launch_description() -> LaunchDescription: # 双臂真机默认读取 xr_rm_bringup/config/dual_arm_rm75.yaml。 config_file = PathJoinSubstitution([ FindPackageShare("xr_rm_bringup"), "config", LaunchConfiguration("robot_config"), ]) return LaunchDescription([ # UDP 监听参数,需要与 PICO 端发送地址和端口匹配。 DeclareLaunchArgument("udp_host", default_value="0.0.0.0"), DeclareLaunchArgument("udp_port", default_value="15000"), # 左右 RM75 的默认现场 IP,可在 launch 命令中按实际网络覆盖。 DeclareLaunchArgument("left_robot_ip", default_value="192.168.192.18"), DeclareLaunchArgument("right_robot_ip", default_value="192.168.192.19"), DeclareLaunchArgument("robot_port", default_value="8080"), DeclareLaunchArgument("robot_config", default_value="dual_arm_rm75.yaml"), # 调试时可关闭部分节点,只验证 UDP 或单侧机械臂。 DeclareLaunchArgument("run_udp", default_value="true"), DeclareLaunchArgument("run_left_arm", default_value="true"), DeclareLaunchArgument("run_right_arm", default_value="true"), # 真机默认不自动动臂,确认安全区清空后再手动打开。 DeclareLaunchArgument("move_to_initial_pose_on_connect", default_value="false"), # 接收 PICO/XR 侧 UDP 数据,并按左右手字段分发到对应手柄话题。 Node( package="xr_rm_input", executable="udp_controller_receiver", name="udp_controller_receiver", output="screen", condition=IfCondition(LaunchConfiguration("run_udp")), parameters=[{ "udp_host": LaunchConfiguration("udp_host"), "udp_port": LaunchConfiguration("udp_port"), "left_topic": "/xr/left_controller", "right_topic": "/xr/right_controller", }], ), # 左臂真机节点:连接 left_robot_ip,并读取 left_arm_teleop 参数命名空间。 Node( package="xr_rm_teleop", executable="single_arm_velocity_teleop", name="left_arm_teleop", output="screen", condition=IfCondition(LaunchConfiguration("run_left_arm")), parameters=[ config_file, { "use_mock": False, "robot_ip": LaunchConfiguration("left_robot_ip"), "robot_port": LaunchConfiguration("robot_port"), "move_to_initial_pose_on_connect": ParameterValue( LaunchConfiguration("move_to_initial_pose_on_connect"), value_type=bool, ), }, ], ), # 右臂真机节点:连接 right_robot_ip,并读取 right_arm_teleop 参数命名空间。 Node( package="xr_rm_teleop", executable="single_arm_velocity_teleop", name="right_arm_teleop", output="screen", condition=IfCondition(LaunchConfiguration("run_right_arm")), parameters=[ config_file, { "use_mock": False, "robot_ip": LaunchConfiguration("right_robot_ip"), "robot_port": LaunchConfiguration("robot_port"), "move_to_initial_pose_on_connect": ParameterValue( LaunchConfiguration("move_to_initial_pose_on_connect"), value_type=bool, ), }, ], ), ])