4. 多机器人URDF集成

任务目标

在ROS2中加载多个机器人URDF模型,并在RViz中同时显示。本案例以两个简单两轮机器人为例,通过robot_state_publisher分别发布各机器人的TF与关节状态,最终在RViz中看到两个独立且可区分的机器人模型。

环境依赖

  • Ubuntu 22.04 + ROS2 Humble(或其他ROS2发行版)
  • 安装包:urdf_tutorial、joint_state_publisher、rviz2、xacro
sudo apt install ros-${ROS_DISTRO}-urdf-tutorial ros-${ROS_DISTRO}-joint-state-publisher ros-${ROS_DISTRO}-rviz2 ros-${ROS_DISTRO}-xacro

实现方案

核心思路:为每个机器人创建独立的URDF文件(或xacro),每个URDF中通过ros2_control标签或直接设置frame_prefix参数来区分TF命名空间。启动时分别运行两个robot_state_publisher节点,各自加载对应URDF并设置不同的frame_prefix,从而避免TF树冲突。

关键完整代码

创建multi_robot_demo包,目录结构如下:

multi_robot_demo/
├── urdf/
│   ├── robot1.urdf
│   └── robot2.urdf
├── launch/
│   └── display_multi_robot.launch.py
├── CMakeLists.txt
└── package.xml

robot1.urdf(robot2.urdf仅颜色不同,结构相同):

<robot name="robot1">
  <link name="base_link">
    <visual>
      <geometry><box size="0.4 0.2 0.1"/></geometry>
      <material name="blue"/>
    </visual>
  </link>
  <link name="left_wheel">
    <visual>
      <geometry><cylinder radius="0.05" length="0.03"/></geometry>
      <material name="dark"/>
    </visual>
  </link>
  <link name="right_wheel">
    <visual>
      <geometry><cylinder radius="0.05" length="0.03"/></geometry>
      <material name="dark"/>
    </visual>
  </link>
  <joint name="base_to_left_wheel" type="continuous">
    <parent link="base_link"/>
    <child link="left_wheel"/>
    <origin xyz="0 -0.12 0" rpy="1.5708 0 0"/>
    <axis xyz="0 0 1"/>
  </joint>
  <joint name="base_to_right_wheel" type="continuous">
    <parent link="base_link"/>
    <child link="right_wheel"/>
    <origin xyz="0 0.12 0" rpy="1.5708 0 0"/>
    <axis xyz="0 0 1"/>
  </joint>
  <material name="blue"><color rgba="0.2 0.3 0.9 1.0"/></material>
  <material name="dark"><color rgba="0.1 0.1 0.1 1.0"/></material>
</robot>

display_multi_robot.launch.py:

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

def generate_launch_description():
    pkg_dir = get_package_share_directory('multi_robot_demo')
    
    # 机器人1:TF前缀为robot1_
    robot1_state_publisher = Node(
        package='robot_state_publisher',
        executable='robot_state_publisher',
        name='robot1_state_publisher',
        parameters=[{
            'robot_description': open(os.path.join(pkg_dir, 'urdf', 'robot1.urdf')).read(),
            'frame_prefix': 'robot1_'
        }]
    )
    
    # 机器人2:TF前缀为robot2_
    robot2_state_publisher = Node(
        package='robot_state_publisher',
        executable='robot_state_publisher',
        name='robot2_state_publisher',
        parameters=[{
            'robot_description': open(os.path.join(pkg_dir, 'urdf', 'robot2.urdf')).read(),
            'frame_prefix': 'robot2_'
        }]
    )
    
    # 关节状态发布(两个机器人共用,通过前缀区分)
    joint_state_publisher = Node(
        package='joint_state_publisher',
        executable='joint_state_publisher',
        name='joint_state_publisher',
        parameters=[{'source_list': ['robot1/joint_states', 'robot2/joint_states']}]
    )
    
    rviz2 = Node(
        package='rviz2',
        executable='rviz2',
        name='rviz2',
        arguments=['-d', os.path.join(pkg_dir, 'config', 'multi_robot.rviz')]
    )
    
    return LaunchDescription([
        robot1_state_publisher,
        robot2_state_publisher,
        joint_state_publisher,
        rviz2
    ])

CMakeLists.txt关键部分:

install(DIRECTORY urdf launch config
  DESTINATION share/${PROJECT_NAME}
)

运行与验证

# 构建并source
colcon build --packages-select multi_robot_demo
source install/setup.bash

# 启动
ros2 launch multi_robot_demo display_multi_robot.launch.py

RViz启动后,在左侧Displays面板点击Add,选择RobotModel,将Description Topic分别设为/robot1/robot_description和/robot2/robot_description(需添加两个RobotModel显示)。同时添加TF显示,勾选robot1_和robot2_前缀的TF树。

通过条件:

  • RViz中同时出现两个不同颜色的机器人模型(蓝色为robot1,绿色为robot2);
  • TF树中两个机器人的坐标系互不干扰,各自以robot1_base_link和robot2_base_link为根;
  • 运行ros2 topic list可看到/robot1/joint_states和/robot2/joint_states两个独立话题。
常见问题:若RViz中模型不显示,检查robot_description参数是否被正确加载(ros2 param get /robot1_state_publisher robot_description);若TF前缀未生效,确认frame_prefix参数名正确(ROS2 Humble中为frame_prefix,旧版本为tf_prefix)。