🤖 第01课:ROS2概述与安装

ROS2基础 ✅ Docker验证通过

📋 课程目标

🧠 什么是ROS2?

ROS2(Robot Operating System 2)并不是一个真正的操作系统,而是一个面向机器人的中间件框架。它提供了一系列工具、库和约定,旨在简化跨多种机器人平台创建复杂且健壮的机器人行为。

🔑 ROS2的核心价值

📐 ROS1 vs ROS2 架构对比

┌─────────────── ROS1 架构 ───────────────┐ ┌─────────────── ROS2 架构 ───────────────┐ │ │ │ │ │ ┌──────┐ ┌──────┐ ┌──────┐ │ │ ┌──────┐ ┌──────┐ ┌──────┐ │ │ │Node A│◄──►│Master│◄──►│Node B│ │ │ │Node A│◄══►│ DDS │◄══►│Node B│ │ │ └──────┘ └──────┘ └──────┘ │ │ └──────┘ ║ ║ └──────┘ │ │ │ 单点故障 │ │ │ ║ ┌──────┐ ║ │ │ └────────TCP/IP──────┘ │ │ ╚═══►│Node C│◄═══╝ │ │ │ │ └──────┘ │ │ ❌ 依赖Master中心节点 │ │ ✅ 去中心化,DDS自动发现 │ │ ❌ 单点故障风险 │ │ ✅ 实时性支持 │ │ ❌ 无内置安全机制 │ │ ✅ 内置加密与认证(SROS2) │ │ ❌ 仅支持Linux │ │ ✅ 跨平台(Linux/macOS/Windows) │ └──────────────────────────────────────────┘ └──────────────────────────────────────────┘
特性ROS1ROS2
通信中间件自研TCP/UDPDDS (Data Distribution Service)
发现机制中心化(Master)去中心化(DDS自动发现)
实时性不支持支持(RMW配置)
安全性无内置SROS2(加密/认证/访问控制)
平台仅LinuxLinux/macOS/Windows
QoS丰富的QoS策略
生命周期Lifecycle Node
进程内通信不支持支持(零拷贝)

🏗️ ROS2架构层次

┌─────────────────────────────────────────────┐ │ 应用层 (Application) │ │ 导航 │ 操控 │ 感知 │ 规划 │ 仿真 │ 工具 │ ├─────────────────────────────────────────────┤ │ 客户端库 (Client Libraries) │ │ rclcpp(C++) │ rclpy(Python) │ rcl(Rust) │ ├─────────────────────────────────────────────┤ │ rcl (ROS Client Library) │ │ 语言无关的核心C库,统一API │ ├─────────────────────────────────────────────┤ │ RMW (ROS Middleware) │ │ Fast-DDS │ CycloneDDS │ Connext │ iceoryx │ ├─────────────────────────────────────────────┤ │ DDS (Data Distribution Service) │ │ 发布/订阅 │ 服务 │ QoS │ 发现 │ 安全 │ ├─────────────────────────────────────────────┤ │ 操作系统 (OS Abstraction) │ │ Linux │ macOS │ Windows │ RTOS │ └─────────────────────────────────────────────┘

📦 ROS2发行版

发行版代号发布日期EOL状态
HumbleHawksbill2022-052027-05🟢 LTS推荐
IronIrwini2023-052024-11🔴 已EOL
JazzyJalisco2024-052029-05🟢 LTS推荐
Rolling-滚动-🟡 开发版

本课程使用 ROS2 Humble(LTS长期支持版,支持到2027年),搭配Ubuntu 22.04。

🛠️ 安装方法一:Ubuntu原生安装

设置Locale与添加ROS2仓库

# 设置UTF-8编码
sudo apt update && sudo apt install locales
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 GPG密钥
sudo apt install software-properties-common
sudo add-apt-repository universe
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

# 添加ROS2仓库
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

sudo apt update
sudo apt install ros-humble-desktop-full -y

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

环境配置

# 添加到bashrc
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
source ~/.bashrc

# 验证安装
ros2 --version

🐳 安装方法二:Docker安装(推荐用于学习)

Docker方式无需修改宿主系统,非常适合学习和实验:

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

# 启动ROS2容器(带图形界面支持)
docker run -it \
  --name ros2-humble \
  -e DISPLAY=$DISPLAY \
  -v /tmp/.X11-unix:/tmp/.X11-unix \
  osrf/ros:humble-desktop-full \
  /bin/bash

# 进入已创建的容器
docker start ros2-humble
docker exec -it ros2-humble /bin/bash
💡 提示:Docker方式是本课程推荐的安装方法。它隔离了ROS2环境,不会影响宿主系统,且可以随时重建。

✅ 安装验证

安装完成后,运行以下命令验证:

# Source环境
source /opt/ros/humble/setup.bash

# 检查ROS2版本
ros2 --version
# 预期输出: ros2 cli version: ...

# 查看可用命令
ros2 pkg list | head -20

# 运行demo节点测试通信
# 终端1:运行发布者
ros2 run demo_nodes_cpp talker &

# 终端2:运行订阅者
ros2 run demo_nodes_py listener

如果看到 talker 输出 "Hello World" 消息,listener 接收到相同消息,说明安装成功! ✅

🔬 Docker环境下的完整验证脚本

#!/bin/bash
# ros2_install_verify.sh - ROS2安装验证脚本
# ✅ 在Docker容器 osrf/ros:humble-desktop-full 中验证通过

echo "========== ROS2 安装验证 =========="

# 1. 检查环境变量
echo "[1/6] 检查环境变量..."
if [ -z "$AMENT_PREFIX_PATH" ]; then
    echo "  ⚠️  AMENT_PREFIX_PATH 未设置,正在source..."
    source /opt/ros/humble/setup.bash
fi
echo "  ✅ AMENT_PREFIX_PATH = $AMENT_PREFIX_PATH"

# 2. 检查ROS2命令
echo "[2/6] 检查ros2命令..."
ros2 --version && echo "  ✅ ros2命令可用" || echo "  ❌ ros2命令不可用"

# 3. 检查核心包
echo "[3/6] 检查核心包..."
for pkg in rclcpp rclpy std_msgs geometry_msgs nav_msgs sensor_msgs; do
    if ros2 pkg prefix $pkg &>/dev/null; then
        echo "  ✅ $pkg 已安装"
    else
        echo "  ❌ $pkg 未安装"
    fi
done

# 4. 检查DDS实现
echo "[4/6] 检查DDS实现..."
echo "  RMW Implementation: $RMW_IMPLEMENTATION"
ros2 doctor --report 2>/dev/null | grep "middleware" || echo "  使用默认DDS"

# 5. 测试节点通信
echo "[5/6] 测试节点通信..."
timeout 5 ros2 run demo_nodes_cpp talker &
TALKER_PID=$!
sleep 1
timeout 3 ros2 run demo_nodes_py listener 2>&1 | head -5
kill $TALKER_PID 2>/dev/null
echo "  ✅ 节点通信测试完成"

# 6. 检查工作空间
echo "[6/6] 检查工作空间..."
mkdir -p ~/ros2_ws/src
echo "  ✅ 工作空间已创建: ~/ros2_ws"

echo ""
echo "========== 验证结果 =========="
echo "🎉 ROS2 Humble 安装验证完成!"
echo "下一步:创建你的第一个ROS2包"
echo "  mkdir -p ~/ros2_ws/src"
echo "  cd ~/ros2_ws/src"
echo "  ros2 pkg create my_first_pkg --build-type ament_python"

🗂️ ROS2工作空间结构

ros2_ws/ ← 工作空间根目录 ├── src/ ← 源码目录(所有ROS2包) │ ├── my_package/ ← 自定义包 │ │ ├── package.xml ← 包元数据 │ │ ├── setup.py ← Python包构建 │ │ ├── setup.cfg ← 包配置 │ │ ├── resource/ ← 资源标记文件 │ │ └── my_package/ ← Python模块 │ │ └── __init__.py │ └── another_pkg/ ├── build/ ← 构建中间文件(自动生成) ├── install/ ← 安装目录(自动生成) └── log/ ← 构建日志(自动生成)

🔧 核心概念预览

在后续课程中,我们将深入学习以下ROS2核心概念:

概念作用课程
Node(节点)执行计算的进程第02课
Topic(话题)发布/订阅消息通信第03课
Service(服务)请求/响应同步通信第04课
Action(动作)长时间任务的异步通信第05课
Parameter(参数)节点运行时配置第06课
Launch(启动)多节点启动编排第07课

💻 第一个ROS2包(实操)

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

# 创建Python包
ros2 pkg create my_first_ros2_pkg \
  --build-type ament_python \
  --dependencies rclpy std_msgs

# 查看生成的文件
tree my_first_ros2_pkg/
# my_first_ros2_pkg/
# ├── package.xml
# ├── setup.cfg
# ├── setup.py
# ├── resource/
# │   └── my_first_ros2_pkg
# ├── test/
# │   ├── test_copyright.py
# │   ├── test_flake8.py
# │   └── test_pep257.py
# └── my_first_ros2_pkg/
#     └── __init__.py

# 构建包
cd ~/ros2_ws
colcon build --packages-select my_first_ros2_pkg

# 加载环境
source install/setup.bash

# 验证包
ros2 pkg list | grep my_first
# 预期输出: my_first_ros2_pkg
💡 colcon 是ROS2的构建工具,类似于ROS1的 catkin_make。常用选项:

📝 第一个ROS2节点(Python)

编辑 ~/ros2_ws/src/my_first_ros2_pkg/my_first_ros2_pkg/my_first_node.py

#!/usr/bin/env python3
"""第一个ROS2节点 - 发布定时消息"""

import rclpy
from rclpy.node import Node
from std_msgs.msg import String


class MyFirstNode(Node):
    """自定义ROS2节点,定时发布问候消息"""

    def __init__(self):
        # 调用父类构造器,节点名为'first_node'
        super().__init__('first_node')

        # 创建发布者:话题名'greeting',消息类型String,队列大小10
        self.publisher_ = self.create_publisher(String, 'greeting', 10)

        # 创建定时器:每0.5秒调用一次
        self.timer = self.create_timer(0.5, self.timer_callback)

        # 计数器
        self.count = 0

        self.get_logger().info('🎉 第一个ROS2节点已启动!')

    def timer_callback(self):
        """定时器回调函数"""
        msg = String()
        msg.data = f'Hello ROS2! 计数: {self.count}'
        self.publisher_.publish(msg)
        self.get_logger().info(f'发布: "{msg.data}"')
        self.count += 1


def main(args=None):
    # 初始化rclpy
    rclpy.init(args=args)

    # 创建节点
    node = MyFirstNode()

    try:
        # 保持节点运行
        rclpy.spin(node)
    except KeyboardInterrupt:
        pass
    finally:
        # 清理
        node.destroy_node()
        rclpy.shutdown()


if __name__ == '__main__':
    main()

更新 setup.pyentry_points

entry_points={
    'console_scripts': [
        'first_node = my_first_ros2_pkg.my_first_node:main',
    ],
},

构建并运行:

cd ~/ros2_ws
colcon build --packages-select my_first_ros2_pkg --symlink-install
source install/setup.bash

# 运行节点
ros2 run my_first_ros2_pkg first_node

# 另开终端查看话题
ros2 topic echo /greeting

验证结果:节点每0.5秒发布一条消息,ros2 topic echo 可以看到输出。

📝 第一个ROS2节点(C++)

创建C++版本的第一个节点:

// first_node_cpp.cpp - C++版本第一个ROS2节点
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
#include <chrono>
#include <memory>
#include <string>

using namespace std::chrono_literals;

class FirstNodeCpp : public rclcpp::Node {
public:
    FirstNodeCpp() : Node("first_node_cpp"), count_(0) {
        // 创建发布者
        publisher_ = this->create_publisher<std_msgs::msg::String>("greeting_cpp", 10);

        // 创建定时器,500ms间隔
        timer_ = this->create_wall_timer(500ms,
            std::bind(&FirstNodeCpp::timer_callback, this));

        RCLCPP_INFO(this->get_logger(), "🎉 C++第一个ROS2节点已启动!");
    }

private:
    void timer_callback() {
        auto message = std_msgs::msg::String();
        message.data = "Hello ROS2 from C++! 计数: " + std::to_string(count_++);
        RCLCPP_INFO(this->get_logger(), "发布: '%s'", message.data.c_str());
        publisher_->publish(message);
    }

    rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
    rclcpp::TimerBase::SharedPtr timer_;
    size_t count_;
};

int main(int argc, char *argv[]) {
    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<FirstNodeCpp>());
    rclcpp::shutdown();
    return 0;
}

🔧 colcon构建系统详解

colcon常用命令

命令说明
colcon build构建所有包
colcon build --packages-select PKG只构建指定包
colcon build --symlink-install符号链接安装(Python推荐)
colcon build --cmake-args -DCMAKE_BUILD_TYPE=ReleaseRelease模式构建
colcon test运行测试
colcon test-result --all查看测试结果
colcon list列出工作空间中的包

🎯 练习题

📝 练习1:修改发布频率

将第一个节点的定时器频率从0.5秒改为1.0秒,观察消息发布间隔变化。

提示:修改 create_timer(0.5, ...)create_timer(1.0, ...)

📝 练习2:创建C++版本的ROS2包

使用 ros2 pkg create --build-type ament_cmake 创建一个C++包,实现与Python版本相同的功能。

ros2 pkg create my_cpp_pkg \
  --build-type ament_cmake \
  --dependencies rclcpp std_msgs

📝 练习3:使用ros2命令行工具

运行第一个节点后,使用以下命令探索:

# 查看所有活跃节点
ros2 node list

# 查看所有话题
ros2 topic list

# 查看话题信息
ros2 topic info /greeting

# 查看话题频率
ros2 topic hz /greeting

# 查看节点信息
ros2 node info /first_node

📝 练习4:Docker中的ROS2开发环境

创建一个带持久化工作空间的Docker容器:

# 创建宿主工作空间目录
mkdir -p ~/ros2_docker_ws

# 启动带卷挂载的容器
docker run -it \
  --name ros2-dev \
  -v ~/ros2_docker_ws:/root/ros2_ws \
  osrf/ros:humble-desktop-full \
  /bin/bash

🏆 成就解锁

🏅 初入ROS2世界

经验值:+100 XP

📚 扩展阅读