ROS2(Robot Operating System 2)并不是一个真正的操作系统,而是一个面向机器人的中间件框架。它提供了一系列工具、库和约定,旨在简化跨多种机器人平台创建复杂且健壮的机器人行为。
| 特性 | ROS1 | ROS2 |
|---|---|---|
| 通信中间件 | 自研TCP/UDP | DDS (Data Distribution Service) |
| 发现机制 | 中心化(Master) | 去中心化(DDS自动发现) |
| 实时性 | 不支持 | 支持(RMW配置) |
| 安全性 | 无内置 | SROS2(加密/认证/访问控制) |
| 平台 | 仅Linux | Linux/macOS/Windows |
| QoS | 无 | 丰富的QoS策略 |
| 生命周期 | 无 | Lifecycle Node |
| 进程内通信 | 不支持 | 支持(零拷贝) |
| 发行版 | 代号 | 发布日期 | EOL | 状态 |
|---|---|---|---|---|
| Humble | Hawksbill | 2022-05 | 2027-05 | 🟢 LTS推荐 |
| Iron | Irwini | 2023-05 | 2024-11 | 🔴 已EOL |
| Jazzy | Jalisco | 2024-05 | 2029-05 | 🟢 LTS推荐 |
| Rolling | - | 滚动 | - | 🟡 开发版 |
本课程使用 ROS2 Humble(LTS长期支持版,支持到2027年),搭配Ubuntu 22.04。
设置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方式无需修改宿主系统,非常适合学习和实验:
# 拉取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
安装完成后,运行以下命令验证:
# 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 接收到相同消息,说明安装成功! ✅
#!/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核心概念:
| 概念 | 作用 | 课程 |
|---|---|---|
| Node(节点) | 执行计算的进程 | 第02课 |
| Topic(话题) | 发布/订阅消息通信 | 第03课 |
| Service(服务) | 请求/响应同步通信 | 第04课 |
| Action(动作) | 长时间任务的异步通信 | 第05课 |
| Parameter(参数) | 节点运行时配置 | 第06课 |
| Launch(启动) | 多节点启动编排 | 第07课 |
# 创建工作空间
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
catkin_make。常用选项:
colcon build — 构建所有包colcon build --packages-select PKG — 只构建指定包colcon build --symlink-install — 符号链接安装(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.py 的 entry_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 可以看到输出。
创建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 build | 构建所有包 |
colcon build --packages-select PKG | 只构建指定包 |
colcon build --symlink-install | 符号链接安装(Python推荐) |
colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release | Release模式构建 |
colcon test | 运行测试 |
colcon test-result --all | 查看测试结果 |
colcon list | 列出工作空间中的包 |
将第一个节点的定时器频率从0.5秒改为1.0秒,观察消息发布间隔变化。
提示:修改 create_timer(0.5, ...) 为 create_timer(1.0, ...)
使用 ros2 pkg create --build-type ament_cmake 创建一个C++包,实现与Python版本相同的功能。
ros2 pkg create my_cpp_pkg \
--build-type ament_cmake \
--dependencies rclcpp std_msgs
运行第一个节点后,使用以下命令探索:
# 查看所有活跃节点
ros2 node list
# 查看所有话题
ros2 topic list
# 查看话题信息
ros2 topic info /greeting
# 查看话题频率
ros2 topic hz /greeting
# 查看节点信息
ros2 node info /first_node
创建一个带持久化工作空间的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
经验值:+100 XP