2. ROS2基础与环境搭建
ROS2 Humble Hawksbill是ROS2长期支持(LTS)版本中应用最广泛的一个发行版,基于Ubuntu 22.04 Jammy系统。对于机器人开发者而言,掌握Humble的安装、工作空间的组织方式以及四大核心通信机制(节点、话题、服务、参数),是进入后续视觉识别、Nav2导航与行为树联调实战的基石。本章将围绕环境搭建与核心概念展开,帮助你在最短时间内建立起一套可运行、可扩展的ROS2开发环境,并理解其底层通信逻辑。
上图展示了本章的核心知识框架:环境搭建是基础,四大通信机制是骨架,而后续的视觉识别、导航与行为树则是建立在此之上的应用。下面我们逐一深入。
2.1 ROS2 Humble 安装与系统准备
核心原理:为什么选择 Humble 与 Ubuntu 22.04
ROS2的每个发行版都对应特定的Ubuntu版本,Humble与Ubuntu 22.04的搭配是当前工业界和学术界最稳定的组合之一。Humble属于LTS版本,官方提供长达5年的安全更新与维护,这意味着你的机器人项目在长期运行中不会因为依赖库的过时而被迫迁移。更重要的是,Nav2、OpenCV、行为树库(BehaviorTree.CPP)等主流机器人组件都对Humble做了深度适配,后续章节中的视觉识别与导航联调将直接受益于这种兼容性。
操作流程:从零到可运行的完整安装步骤
安装过程建议严格按照以下顺序执行,避免因源配置或依赖缺失导致的反复排错。首先,确保系统为纯净的Ubuntu 22.04,并更新软件源:
sudo apt update && sudo apt upgrade -y
sudo apt install software-properties-common curl -y
sudo add-apt-repository universe -y
sudo apt update
接着添加ROS2的GPG密钥和软件源,然后安装ROS2 Humble桌面版(包含可视化工具RViz2、仿真工具Gazebo等):
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
sudo apt update
sudo apt install ros-humble-desktop -y
安装完成后,需要配置环境变量。建议将source命令写入~/.bashrc,这样每次打开终端都会自动加载ROS2环境:
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
source ~/.bashrc
~/.bashrc中只保留ROS2的source,避免ROS1的setup.bash干扰ROS2命令。若必须共存,请使用别名或单独脚本切换。
案例拆解:验证安装是否成功
安装完成后,最直接的验证方式是运行C++和Python的发布-订阅示例。打开两个终端,分别执行:
# 终端1:运行C++发布者
ros2 run demo_nodes_cpp talker
# 终端2:运行Python订阅者
ros2 run demo_nodes_py listener
如果终端2持续收到Hello World: N的消息,说明ROS2核心通信正常。此时再打开第三个终端,输入ros2 topic list,你应该能看到/chatter话题。这个简单的测试验证了节点发现、话题通信、命令行工具三个关键环节,是后续所有开发的基础。
常见误区与复盘
- 误区1: 使用
sudo apt install ros-humble-ros-base安装精简版。这会导致缺少RViz2、Gazebo等工具,后续视觉调试和导航仿真将无法进行。建议直接安装ros-humble-desktop。 - 误区2: 忘记安装Python3的colcon扩展。虽然colcon是独立工具,但ROS2的Python包构建需要
python3-colcon-common-extensions,否则colcon build会报错。 - 误区3: 忽略
~/.bashrc的source配置。每次新开终端都要手动source,不仅低效,还容易在后续多终端联调时遗漏环境变量。
2.2 工作空间创建与colcon构建
核心原理:工作空间的逻辑结构
ROS2的工作空间(Workspace)是一个包含多个功能包(Package)的目录树,其标准结构为src(源码)、build(中间文件)、install(安装产物)、log(日志)。src目录存放你编写的所有功能包源码;colcon build命令会读取src下的包,编译后生成可执行文件和库文件到install目录;build目录存放CMake等中间缓存;log目录记录构建日志。理解这个结构对于排查编译错误和运行时找不到包的问题至关重要。
操作流程:创建并构建你的第一个工作空间
# 创建工作空间目录
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws
# 编译工作空间(此时src为空,仅生成目录结构)
colcon build
# 添加环境变量
echo "source ~/ros2_ws/install/setup.bash" >> ~/.bashrc
source ~/.bashrc
接下来,我们创建一个C++功能包作为示例。在src目录下使用ros2 pkg create命令:
cd ~/ros2_ws/src
ros2 pkg create my_robot_pkg --build-type ament_cmake --dependencies rclcpp std_msgs
cd ~/ros2_ws
colcon build --packages-select my_robot_pkg
这里--dependencies参数指定了该包依赖的库,rclcpp是C++的ROS2客户端库,std_msgs提供标准消息类型。构建成功后,install/my_robot_pkg目录下会生成lib和include等子目录。
colcon build时,如果工作空间中同时存在多个包,且其中一个包编译失败,默认情况下整个构建会中止。建议使用--packages-select参数单独编译指定包,或者使用--continue-on-error参数让其他包继续编译。此外,每次修改源码后,务必重新执行colcon build,否则运行的是旧版本的可执行文件。
案例拆解:多包工作空间的依赖管理
假设你的机器人项目包含robot_bringup(启动文件)、robot_vision(视觉处理)、robot_nav(导航)三个包,且robot_bringup依赖后两者。正确的构建顺序是:
cd ~/ros2_ws
colcon build --packages-select robot_vision robot_nav
colcon build --packages-select robot_bringup
如果一次性构建所有包,colcon会自动根据package.xml中的依赖声明排序。但手动分步构建的好处是,当某个包编译失败时,你能快速定位问题,而不会因为依赖链断裂导致整个项目无法构建。在实际项目中,我们通常还会使用colcon build --symlink-install参数,这样Python脚本的修改无需重新编译即可生效,极大提升开发效率。
常见误区与复盘
- 误区1: 在
src目录下直接运行colcon build。这会导致构建产物散落在源码目录中,污染源码。必须在工作空间根目录(即包含src的目录)执行。 - 误区2: 忘记source install目录。即使构建成功,如果不source
install/setup.bash,系统仍然找不到你自定义的包。 - 误区3: 忽略
package.xml中的依赖声明。如果包A依赖包B,但未在A的package.xml中声明,colcon在构建时可能不会自动先构建B,导致链接错误。
2.3 节点、话题、服务、参数核心概念
核心原理:四大通信机制的分工与协作
ROS2的通信架构建立在DDS(数据分发服务)之上,但为了降低开发复杂度,ROS2封装了四种上层通信模式:
| 通信机制 | 通信模式 | 典型应用场景 | 关键命令 |
|---|---|---|---|
| 节点 (Node) | 进程内/间独立单元 | 摄像头驱动、导航算法、决策逻辑 | ros2 node list |
| 话题 (Topic) | 异步、单向、多对多 | 传感器数据流、图像流、里程计 | ros2 topic echo |
| 服务 (Service) | 同步、双向、一对一 | 地图保存、路径规划请求、开关控制 | ros2 service call |
| 参数 (Parameter) | 键值对存储 | PID系数、相机曝光、导航速度限制 | ros2 param set |
节点是ROS2中的最小执行单元,每个节点负责一个特定的功能模块。话题用于持续的数据流传输,发布者不关心谁在订阅,订阅者也不关心谁在发布,这种解耦设计使得系统扩展性极强。服务则适用于需要请求-应答的场景,例如机器人收到一个目标点坐标,导航节点返回规划路径。参数则提供了一种动态配置节点行为的机制,无需修改代码即可调整运行参数。
判断方法:如何选择话题还是服务
在实际开发中,一个常见的困惑是“这个功能应该用话题还是服务”。判断标准如下:
- 如果数据是持续产生的,且接收方需要实时响应,例如激光雷达扫描、摄像头图像,使用话题。
- 如果操作是一次性请求,且需要等待结果,例如“请计算机器人从A到B的路径”,使用服务。
- 如果数据是周期性更新,但接收方只关心最新值,例如电池电压、当前速度,使用话题并配合
transient_local的QoS策略。 - 如果操作需要修改节点内部状态,例如切换导航算法模式,使用服务或参数。
案例拆解:用命令行工具观察通信过程
我们以turtlesim为例,这是一个用于教学的小乌龟仿真器。启动仿真器和控制节点:
ros2 run turtlesim turtlesim_node
ros2 run turtlesim turtle_teleop_key
此时,打开新终端执行ros2 node list,可以看到/turtlesim和/teleop_turtle两个节点。执行ros2 topic list,可以看到/turtle1/cmd_vel(速度指令)和/turtle1/pose(位姿)两个话题。执行ros2 topic echo /turtle1/pose,可以实时看到小乌龟的坐标和角度。这个案例直观展示了节点如何通过话题进行通信:键盘节点发布速度指令,仿真器节点订阅并执行,同时发布位姿信息。
再测试服务机制。执行ros2 service list,可以看到/spawn(生成新乌龟)和/kill(杀死乌龟)等服务。调用生成服务:
ros2 service call /spawn turtlesim/srv/Spawn "{x: 2.0, y: 2.0, theta: 0.0, name: 'turtle2'}"
你会看到仿真器中出现了第二只乌龟。这个请求-应答过程就是服务的典型应用。
常见误区与复盘
- 误区1: 认为话题比服务“高级”。实际上两者适用场景不同,强行用话题实现请求-应答会导致代码复杂且难以调试。
- 误区2: 忽略QoS(服务质量)设置。在视觉识别中,如果订阅者使用默认的QoS,而发布者设置了
Best Effort,可能导致消息接收不到。后续章节会详细讲解。 - 误区3: 参数修改后不保存。通过
ros2 param set修改的参数只在当前会话有效,重启节点后恢复默认值。若需持久化,应使用ros2 param dump生成yaml文件,并在启动时加载。