ROS2 Humble 2026 最新安装指南及多机器人仿真实战

ROS2 Humble 2026 年最新安装教程,涵盖 Ubuntu 22.04 环境配置、多机器人仿真(Gazebo Harmonic)、ROS2 Control、Nav2 集成,附完整代码示例

ROS2 Humble 多机器人仿真 ROS2 Control Gazebo Harmonic 2026 机器人开发
ROS2 Humble 2026 最新安装指南及多机器人仿真实战

ROS2 Humble 2026 最新安装指南及多机器人仿真实战

ROS2 Humble Hawksbill 是当前 LTS 版本,支持到 2027 年 5 月。2026 年,随着 Gazebo Harmonic 的成熟和 ROS2 Control 生态的完善,ROS2 已经成为机器人开发的事实标准。

本文基于 2026 年最新实践,系统讲解 ROS2 Humble 的安装配置、多机器人仿真架构、ROS2 Control 集成,以及与 Nav2 导航框架的配合使用。无论你是 ROS1 迁移用户还是 ROS2 新手,都能快速上手。

你将学到:

  • ✅ ROS2 Humble 2026 最新安装方式(apt / Docker / 源码)
  • ✅ Gazebo Harmonic 多机器人仿真配置
  • ✅ ROS2 Control 硬件抽象层实战
  • ✅ 多机器人命名空间与 TF 管理
  • ✅ 与 Nav2、MoveIt2 集成

1. ROS2 Humble 安装

1.1 系统要求

  • 操作系统:Ubuntu 22.04 LTS(推荐)
  • 替代系统:RHEL 9、Windows 10/11、macOS(部分功能)
  • 内存:8GB+(推荐 16GB)
  • 存储:20GB+(含 Gazebo 和依赖)
  • GPU:可选,用于 Gazebo 渲染加速

1.2 安装方式对比

方式优点缺点适用场景
apt 安装简单快速,自动依赖版本固定,不易定制生产环境
Docker隔离环境,可复现图形界面需额外配置CI/CD、多版本共存
源码编译完全可控,最新功能编译时间长(1-2 小时)开发/贡献代码

1.3 apt 安装(推荐)

# 设置 locale
sudo apt update && sudo apt install locales -y
sudo locale-gen en_US en_US.UTF-8
sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
export LANG=en_US.UTF-8

# 添加 ROS2 软件源
sudo apt install software-properties-common -y
sudo add-apt-repository universe -y
sudo apt update && sudo apt install curl -y
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key \
  -o /usr/share/keyrings/ros-archive-keyring.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] \
  http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | \
  sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null

# 安装 ROS2 Humble Desktop
sudo apt update
sudo apt install ros-humble-desktop -y

# 安装开发工具
sudo apt install ros-dev-tools -y

# 配置环境
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
source ~/.bashrc

# 验证安装
ros2 --version
# 应输出:ros2 1.0.0 或更高

# 运行示例
ros2 run demo_nodes_cpp talker &
ros2 run demo_nodes_py listener
# 应看到消息传递

1.4 Docker 安装

# 拉取官方镜像
docker pull osrf/ros:humble-desktop-full

# 运行容器(带图形界面)
docker run -it --rm \
  --net=host \
  --privileged \
  -e DISPLAY=$DISPLAY \
  -v /tmp/.X11-unix:/tmp/.X11-unix \
  osrf/ros:humble-desktop-full \
  bash

# 或使用 rocker(推荐,自动处理 X11)
pip install rocker
rocker --x11 --nvidia osrf/ros:humble-desktop-full

1.5 源码编译(高级)

# 安装依赖
sudo apt update && sudo apt install -y \
  python3-flake8 python3-pytest python3-pip \
  python3-rosdep python3-colcon-common-extensions

# 初始化 rosdep
sudo rosdep init
rosdep update

# 创建工作空间
mkdir -p ~/ros2_humble/src
cd ~/ros2_humble

# 下载源码
wget https://raw.githubusercontent.com/ros2/ros2/humble/ros2_humble.repos
vcs import src < ros2_humble.repos

# 安装依赖
rosdep install --from-paths src --ignore-src --rosdistro humble -y

# 编译
colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release

# 配置环境
echo "source ~/ros2_humble/install/setup.bash" >> ~/.bashrc

2. Gazebo Harmonic 多机器人仿真

2.1 Gazebo 版本选择

2026 年,Gazebo 有两个主要版本:

  • Gazebo Classic(11.x):已停止维护,仅用于旧项目
  • Gazebo Harmonic(新版):推荐,与 ROS2 深度集成
# 安装 Gazebo Harmonic
sudo apt install ros-humble-gz-harmonic -y

# 或安装完整桌面版
sudo apt install ros-humble-gz-harmonic-desktop -y

2.2 创建机器人 URDF

<!-- urdf/simple_robot.urdf.xacro -->
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="simple_robot">
  
  <!-- 参数 -->
  <xacro:arg name="namespace" default="robot1"/>
  <xacro:arg name="robot_id" default="1"/>
  
  <!-- 基础属性 -->
  <xacro:property name="ns" value="$(arg namespace)"/>
  <xacro:property name="id" value="$(arg robot_id)"/>
  
  <!-- 底盘 -->
  <link name="base_link">
    <visual>
      <geometry>
        <box size="0.5 0.3 0.1"/>
      </geometry>
      <material name="blue">
        <color rgba="0 0 0.8 1"/>
      </material>
    </visual>
    <collision>
      <geometry>
        <box size="0.5 0.3 0.1"/>
      </geometry>
    </collision>
    <inertial>
      <mass value="5.0"/>
      <inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/>
    </inertial>
  </link>
  
  <!-- 轮子 -->
  <xacro:macro name="wheel" params="prefix x y">
    <link name="${prefix}_wheel">
      <visual>
        <geometry>
          <cylinder radius="0.05" length="0.02"/>
        </geometry>
        <material name="black"/>
      </visual>
      <collision>
        <geometry>
          <cylinder radius="0.05" length="0.02"/>
        </geometry>
      </collision>
      <inertial>
        <mass value="0.5"/>
        <inertia ixx="0.001" ixy="0" ixz="0" iyy="0.001" iyz="0" izz="0.001"/>
      </inertial>
    </link>
    
    <joint name="${prefix}_wheel_joint" type="continuous">
      <parent link="base_link"/>
      <child link="${prefix}_wheel"/>
      <origin xyz="${x} ${y} -0.05" rpy="${-pi/2} 0 0"/>
      <axis xyz="0 0 1"/>
    </joint>
  </xacro:macro>
  
  <xacro:wheel prefix="left" x="-0.15" y="0.18"/>
  <xacro:wheel prefix="right" x="-0.15" y="-0.18"/>
  
  <!-- 激光雷达 -->
  <link name="lidar_link">
    <visual>
      <geometry>
        <cylinder radius="0.05" length="0.05"/>
      </geometry>
    </visual>
  </link>
  
  <joint name="lidar_joint" type="fixed">
    <parent link="base_link"/>
    <child link="lidar_link"/>
    <origin xyz="0.2 0 0.1" rpy="0 0 0"/>
  </joint>
  
  <!-- Gazebo 插件 -->
  <gazebo>
    <plugin filename="libgz-sim-ros2-system.so" name="gz::sim::systems::Ros2">
      <namespace>${ns}</namespace>
    </plugin>
  </gazebo>
  
  <gazebo reference="lidar_link">
    <sensor type="gpu_lidar" name="lidar">
      <pose>0 0 0 0 0 0</pose>
      <topic>${ns}/scan</topic>
      <update_rate>10</update_rate>
      <ray>
        <scan>
          <horizontal>
            <samples>360</samples>
            <resolution>1</resolution>
            <min_angle>-3.14159</min_angle>
            <max_angle>3.14159</max_angle>
          </horizontal>
        </scan>
        <range>
          <min>0.1</min>
          <max>10.0</max>
        </range>
      </ray>
    </sensor>
  </gazebo>
  
  <!-- 差速驱动插件 -->
  <gazebo>
    <plugin filename="libgz-sim-diff-drive-system.so" name="gz::sim::systems::DiffDrive">
      <left_joint>left_wheel_joint</left_joint>
      <right_joint>right_wheel_joint</right_joint>
      <wheel_separation>0.36</wheel_separation>
      <wheel_radius>0.05</wheel_radius>
      <odom_publish_frequency>10</odom_publish_frequency>
      <topic>${ns}/cmd_vel</topic>
      <odom_topic>${ns}/odom</odom_topic>
      <tf_topic>${ns}/tf</tf_topic>
      <frame_id>${ns}/odom</frame_id>
      <child_frame_id>${ns}/base_link</child_frame_id>
    </plugin>
  </gazebo>
  
</robot>

2.3 多机器人启动文件

# launch/multi_robot.launch.py
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription, GroupAction
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import PathJoinSubstitution, LaunchConfiguration
from launch_ros.actions import Node, PushRosNamespace
from ament_index_python.packages import get_package_share_directory
import os

def generate_launch_description():
    pkg_gz_sim = get_package_share_directory('gz_sim')
    pkg_robot = get_package_share_directory('my_robot')
    
    # Gazebo 世界文件
    world_file = os.path.join(pkg_robot, 'worlds', 'empty.world')
    
    # 启动 Gazebo
    gz_sim = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            os.path.join(pkg_gz_sim, 'launch', 'gz_sim.launch.py')
        ),
        launch_arguments={'world': world_file}.items()
    )
    
    # 生成多个机器人
    robots = []
    num_robots = 3
    
    for i in range(num_robots):
        namespace = f'robot{i+1}'
        x_pos = i * 2.0
        
        # 启动单个机器人
        robot_group = GroupAction([
            PushRosNamespace(namespace),
            
            # Robot State Publisher
            Node(
                package='robot_state_publisher',
                executable='robot_state_publisher',
                name='robot_state_publisher',
                parameters=[{
                    'robot_description': 
                        open(os.path.join(pkg_robot, 'urdf', 'simple_robot.urdf.xacro')).read(),
                    'frame_prefix': f'{namespace}/'
                }]
            ),
            
            # 在 Gazebo 中生成机器人
            Node(
                package='gz_sim',
                executable='create',
                arguments=[
                    '-name', namespace,
                    '-x', str(x_pos),
                    '-y', '0.0',
                    '-z', '0.1',
                    '-file', os.path.join(pkg_robot, 'urdf', 'simple_robot.urdf.xacro'),
                    '--ros-args', '-p', f'namespace:={namespace}'
                ]
            ),
        ])
        
        robots.append(robot_group)
    
    return LaunchDescription([
        gz_sim,
        *robots,
        
        # RViz
        Node(
            package='rviz2',
            executable='rviz2',
            name='rviz2',
            arguments=['-d', os.path.join(pkg_robot, 'rviz', 'multi_robot.rviz')]
        )
    ])

2.4 命名空间与 TF 管理

多机器人系统的关键是命名空间隔离和 TF 树管理。

命名空间规则:

  • 每个机器人有独立的命名空间:robot1/, robot2/, …
  • 所有话题、服务、动作都在命名空间下
  • TF 帧使用 frame_prefix 区分:robot1/base_link, robot2/base_link

TF 树结构:

world
├── robot1/odom
│   └── robot1/base_link
│       ├── robot1/lidar_link
│       └── robot1/camera_link
├── robot2/odom
│   └── robot2/base_link
│       └── ...
└── robot3/odom
    └── robot3/base_link
        └── ...

Robot State Publisher 配置:

Node(
    package='robot_state_publisher',
    executable='robot_state_publisher',
    parameters=[{
        'robot_description': robot_desc,
        'frame_prefix': 'robot1/',  # 关键:添加前缀
        'use_sim_time': True
    }]
)

3. ROS2 Control 集成

3.1 ROS2 Control 架构

ROS2 Control 是 ROS2 的硬件抽象层,提供统一的控制接口:

┌─────────────────────────────────────────┐
│         Controller Manager              │
│  ┌──────────┐  ┌──────────┐            │
│  │ Joint    │  │ Diff     │            │
│  │ Position │  │ Drive    │  ...       │
│  │ Controller│ │Controller│            │
│  └──────────┘  └──────────┘            │
├─────────────────────────────────────────┤
│         Hardware Interface              │
│  ┌──────────────────────────────────┐  │
│  │  System / Actuator / Sensor      │  │
│  └──────────────────────────────────┘  │
└─────────────────────────────────────────┘

3.2 配置 ROS2 Control

<!-- urdf/robot_ros2_control.xacro -->
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro">
  
  <ros2_control name="GazeboSimSystem" type="system">
    <hardware>
      <plugin>gz_ros2_control/GazeboSimSystem</plugin>
    </hardware>
    
    <joint name="left_wheel_joint">
      <command_interface name="velocity">
        <param name="min">-10</param>
        <param name="max">10</param>
      </command_interface>
      <state_interface name="position"/>
      <state_interface name="velocity"/>
    </joint>
    
    <joint name="right_wheel_joint">
      <command_interface name="velocity">
        <param name="min">-10</param>
        <param name="max">10</param>
      </command_interface>
      <state_interface name="position"/>
      <state_interface name="velocity"/>
    </joint>
  </ros2_control>
  
  <gazebo>
    <plugin filename="libgz_ros2_control-system.so" name="gz::sim::systems::GzRos2Control">
      <parameters>$(find my_robot)/config/controllers.yaml</parameters>
      <namespace>$(arg namespace)</namespace>
    </plugin>
  </gazebo>
  
</robot>

控制器配置:

# config/controllers.yaml
controller_manager:
  ros__parameters:
    update_rate: 100  # Hz
    
    joint_state_broadcaster:
      type: joint_state_broadcaster/JointStateBroadcaster
    
    diff_drive_controller:
      type: diff_drive_controller/DiffDriveController

diff_drive_controller:
  ros__parameters:
    left_wheel_names: ["left_wheel_joint"]
    right_wheel_names: ["right_wheel_joint"]
    
    wheel_separation: 0.36
    wheel_radius: 0.05
    
    # 里程计
    publish_rate: 50.0
    base_frame_id: "base_link"
    odom_frame_id: "odom"
    enable_odom_tf: true
    
    # 速度限制
    linear:
      x:
        has_velocity_limits: true
        has_acceleration_limits: true
        max_velocity: 1.0
        min_velocity: -1.0
        max_acceleration: 1.0
    angular:
      z:
        has_velocity_limits: true
        has_acceleration_limits: true
        max_velocity: 1.5
        min_velocity: -1.5
        max_acceleration: 2.0

3.3 启动控制器

# launch/controllers.launch.py
from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription([
        # Controller Manager
        Node(
            package='controller_manager',
            executable='ros2_control_node',
            parameters=[
                os.path.join(get_package_share_directory('my_robot'), 'config', 'controllers.yaml')
            ],
            output='screen'
        ),
        
        # 加载控制器
        Node(
            package='controller_manager',
            executable='spawner',
            arguments=['joint_state_broadcaster', '--controller-manager', '/controller_manager'],
            output='screen'
        ),
        
        Node(
            package='controller_manager',
            executable='spawner',
            arguments=['diff_drive_controller', '--controller-manager', '/controller_manager'],
            output='screen'
        ),
    ])

4. 多机器人导航

4.1 为每个机器人启动 Nav2

# launch/multi_robot_nav2.launch.py
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription, GroupAction
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node
from ament_index_python.packages import get_package_share_directory
import os

def generate_launch_description():
    nav2_bringup_dir = get_package_share_directory('nav2_bringup')
    
    robots = ['robot1', 'robot2', 'robot3']
    
    robot_groups = []
    for robot_name in robots:
        # 每个机器人独立的 Nav2 实例
        nav2_group = GroupAction([
            IncludeLaunchDescription(
                PythonLaunchDescriptionSource(
                    os.path.join(nav2_bringup_dir, 'launch', 'bringup_launch.py')
                ),
                launch_arguments={
                    'namespace': robot_name,
                    'map': os.path.join(get_package_share_directory('my_robot'), 'maps', 'map.yaml'),
                    'params_file': os.path.join(get_package_share_directory('my_robot'), 'config', f'nav2_{robot_name}.yaml'),
                    'use_sim_time': 'true',
                    'autostart': 'true',
                    'use_composition': 'false',
                    'use_respawn': 'true',
                }.items()
            )
        ])
        robot_groups.append(nav2_group)
    
    return LaunchDescription([
        *robot_groups,
    ])

4.2 多机器人任务分配

#!/usr/bin/env python3
"""多机器人任务分配器"""
import rclpy
from rclpy.node import Node
from nav2_simple_commander.robot_navigator import BasicNavigator
from geometry_msgs.msg import PoseStamped
import tf_transformations

class MultiRobotCoordinator(Node):
    def __init__(self):
        super().__init__('multi_robot_coordinator')
        
        # 为每个机器人创建导航器
        self.robots = {}
        for i in range(1, 4):
            name = f'robot{i}'
            self.robots[name] = BasicNavigator(f'{name}_navigator', namespace=name)
        
        # 等待所有机器人就绪
        for name, nav in self.robots.items():
            nav.waitUntilNav2Active()
            self.get_logger().info(f'{name} 就绪')
        
        # 分配任务
        self.assign_tasks()
    
    def assign_tasks(self):
        """分配任务给各机器人"""
        tasks = {
            'robot1': (2.0, 0.0, 0.0),
            'robot2': (0.0, 2.0, 1.57),
            'robot3': (-2.0, 0.0, 3.14),
        }
        
        for robot_name, (x, y, theta) in tasks.items():
            nav = self.robots[robot_name]
            
            goal_pose = PoseStamped()
            goal_pose.header.frame_id = 'map'
            goal_pose.header.stamp = self.get_clock().now().to_msg()
            goal_pose.pose.position.x = x
            goal_pose.pose.position.y = y
            
            q = tf_transformations.quaternion_from_euler(0, 0, theta)
            goal_pose.pose.orientation.x = q[0]
            goal_pose.pose.orientation.y = q[1]
            goal_pose.pose.orientation.z = q[2]
            goal_pose.pose.orientation.w = q[3]
            
            self.get_logger().info(f'{robot_name} 前往 ({x}, {y})')
            nav.goToPose(goal_pose)
        
        # 监控任务进度
        self.monitor_tasks()
    
    def monitor_tasks(self):
        """监控所有任务进度"""
        rate = self.create_rate(1.0)
        
        while rclpy.ok():
            all_done = True
            
            for name, nav in self.robots.items():
                if not nav.isTaskComplete():
                    all_done = False
                    feedback = nav.getFeedback()
                    if feedback:
                        self.get_logger().info(
                            f'{name}: 距离 {feedback.distance_remaining:.2f}m'
                        )
            
            if all_done:
                self.get_logger().info('所有任务完成!')
                break
            
            rate.sleep()

def main():
    rclpy.init()
    coordinator = MultiRobotCoordinator()
    rclpy.spin(coordinator)
    rclpy.shutdown()

if __name__ == '__main__':
    main()

5. 常见问题与优化

5.1 多机器人 TF 冲突

问题: 多个机器人的 TF 帧名称冲突

解决: 确保每个机器人的 frame_prefix 正确设置

# Robot State Publisher
Node(
    package='robot_state_publisher',
    executable='robot_state_publisher',
    parameters=[{
        'frame_prefix': f'robot{i}/'  # 每个机器人不同的前缀
    }]
)

5.2 Gazebo 性能优化

问题: 多机器人仿真帧率低

解决:

# 降低物理引擎频率
gz sim -r --physics-engine DART --iterations-per-second 100

# 减少传感器频率
# 激光雷达:10 Hz → 5 Hz
# 相机:30 Hz → 15 Hz

# 使用 headless 模式(无渲染)
gz sim -s -r world.sdf  # 服务器模式

5.3 命名空间话题调试

# 查看所有话题
ros2 topic list

# 查看特定机器人的话题
ros2 topic list | grep robot1

# 监听特定话题
ros2 topic echo /robot1/cmd_vel

# 查看 TF 树
ros2 run tf2_tools view_frames
evince frames.pdf

6. FAQ 常见问题

Q1: ROS2 Humble 支持到什么时候?

ROS2 Humble Hawksbill 是 LTS 版本,官方支持到 2027 年 5 月。2026 年仍然是生产环境的推荐选择。

Q2: Gazebo Classic 和 Gazebo Harmonic 有什么区别?

Gazebo Classic(11.x)已停止维护,仅用于旧项目兼容。Gazebo Harmonic 是新版,与 ROS2 深度集成,支持 SDF 1.9、更好的物理引擎、插件系统重构。新项目必须使用 Harmonic。

Q3: 多机器人仿真中 TF 帧冲突怎么解决?

关键是为每个机器人的 robot_state_publisher 设置不同的 frame_prefix。例如 robot1/、robot2/,这样 TF 帧会自动命名为 robot1/base_link、robot2/base_link,避免冲突。

Q4: ROS2 Control 和直接发布 cmd_vel 有什么区别?

直接发布 cmd_vel 是开环控制,无法精确控制轮子转速。ROS2 Control 提供闭环控制、硬件抽象、统一的控制器接口,支持差速驱动、全向轮、机械臂等多种硬件,是生产环境的最佳实践。

Q5: 多机器人导航需要为每个机器人单独启动 Nav2 吗?

是的。每个机器人需要独立的 Nav2 实例,使用不同的命名空间、参数文件(nav2_robot1.yaml、nav2_robot2.yaml)。本文第 4 节提供了完整的启动代码。

7. 相关资源

站内文章:

外部资源:

8. SEO 优化

Title: ROS2 Humble 2026 最新安装指南及多机器人仿真实战

Description: ROS2 Humble 2026 年最新安装教程,涵盖 Ubuntu 22.04 环境配置、多机器人仿真(Gazebo Harmonic)、ROS2 Control、Nav2 集成,附完整代码示例

FAQ Schema:

{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "ROS2 Humble 支持到什么时候?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "ROS2 Humble Hawksbill 是 LTS 版本,官方支持到 2027 年 5 月。2026 年仍然是生产环境的推荐选择。"
      }
    },
    {
      "@type": "Question",
      "name": "Gazebo Classic 和 Gazebo Harmonic 有什么区别?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Gazebo Classic(11.x)已停止维护,仅用于旧项目兼容。Gazebo Harmonic 是新版,与 ROS2 深度集成,支持 SDF 1.9、更好的物理引擎、插件系统重构。新项目必须使用 Harmonic。"
      }
    },
    {
      "@type": "Question",
      "name": "多机器人仿真中 TF 帧冲突怎么解决?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "关键是为每个机器人的 robot_state_publisher 设置不同的 frame_prefix。例如 robot1/、robot2/,这样 TF 帧会自动命名为 robot1/base_link、robot2/base_link,避免冲突。"
      }
    },
    {
      "@type": "Question",
      "name": "ROS2 Control 和直接发布 cmd_vel 有什么区别?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "直接发布 cmd_vel 是开环控制,无法精确控制轮子转速。ROS2 Control 提供闭环控制、硬件抽象、统一的控制器接口,支持差速驱动、全向轮、机械臂等多种硬件,是生产环境的最佳实践。"
      }
    },
    {
      "@type": "Question",
      "name": "多机器人导航需要为每个机器人单独启动 Nav2 吗?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "是的。每个机器人需要独立的 Nav2 实例,使用不同的命名空间、参数文件(nav2_robot1.yaml、nav2_robot2.yaml)。"
      }
    }
  ]
}

总结

本文系统讲解了 ROS2 Humble 2026 最新实践:

  1. ✅ 三种安装方式(apt / Docker / 源码)
  2. ✅ Gazebo Harmonic 多机器人仿真
  3. ✅ ROS2 Control 硬件抽象层
  4. ✅ 多机器人命名空间与 TF 管理
  5. ✅ Nav2 多机器人导航集成

下一步:

实践出真知,动手试试吧!如果遇到问题,欢迎在评论区交流。