ROS2基础与工作空间配置

各位同学好,我是你们的机器人工程师讲师。今天咱们来聊聊ROS2的基础概念和工作空间配置。说实话,ROS2刚出来那会儿,我也有点不适应——毕竟从ROS1过渡过来,很多习惯都得改。但用久了你会发现,ROS2的设计确实更合理,更适合工业级应用。

ROS2核心概念:节点、话题、服务、动作

先说说这几个核心概念。我当年带团队做第一个ROS2项目时,有个新人把节点和话题搞混了,结果调试了一整天。嗯,这里咱们得把基础打牢。

节点(Node)

节点就是ROS2中最基本的执行单元。你可以把它理解成一个独立的小程序,专门负责某一种功能。比如一个机械臂系统,可能有视觉识别节点、运动规划节点、关节控制节点等等。每个节点各司其职,互不干扰。

我个人习惯把节点想象成「车间里的工人」——每个工人只干自己那摊活,但通过某种方式互相配合。这样做的好处是,哪个节点出了问题,单独重启它就行,不影响整个系统。

话题(Topic)

话题是节点之间通信的「广播频道」。一个节点可以往话题上发消息,其他节点可以订阅这个话题来接收消息。这是一种异步通信方式,说白了就是「你发你的,我收我的,互不等候」。

我在项目中遇到过一个问题:某个传感器节点以100Hz的频率发布数据,但处理节点跟不上这个速度。怎么办?ROS2的话题机制天然支持这种场景——处理节点按自己的节奏读取最新数据,不会因为数据积压而崩溃。

关键点:话题通信是单向的、异步的。发布者不知道谁在订阅,订阅者也不知道谁在发布。这种解耦设计让系统非常灵活。

服务(Service)

服务是一种请求-响应式的通信方式。客户端发送请求,服务端处理并返回结果。这就像你打电话问客服:「我的订单到哪了?」客服查完告诉你结果。整个过程是同步的,你得等着。

服务适合那些需要即时响应的操作,比如「打开夹爪」、「查询当前关节角度」。但要注意,如果服务端处理时间太长,客户端会一直阻塞——我曾经因为这个坑导致整个控制循环卡死,后来改用动作才解决。

动作(Action)

动作是ROS2里比较高级的通信机制。它结合了话题和服务的优点:你可以发送一个目标(像服务),同时还能实时接收反馈(像话题),并且可以随时取消任务。

你想想看,机械臂抓取一个物体,这个过程可能需要几秒钟。如果用服务,客户端得傻等;如果用话题,你又没法知道任务什么时候完成。动作就是为这种场景设计的——发送目标后,你可以一边接收进度反馈,一边做其他事情。

通信方式 特点 适用场景
话题 异步、单向、多对多 传感器数据、状态发布
服务 同步、请求-响应 查询、简单指令
动作 异步、可反馈、可取消 长时间任务、复杂控制

创建工作空间与功能包

好了,概念讲完了,咱们动手实践一下。工作空间就是存放ROS2项目的根目录。我建议你给每个项目单独建一个工作空间,别把所有东西都塞在一起——这是我踩过坑后的经验。

创建工作空间

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

# 编译工作空间(第一次需要)
colcon build

执行完 colcon build 后,你会看到 build、install、log 三个文件夹。别慌,这是正常的。记得每次打开新终端都要 source 一下环境变量:

source ~/ros2_ws/install/setup.bash
小技巧:把 source 命令加到 ~/.bashrc 文件里,这样每次打开终端就不用手动执行了。我习惯用 echo "source ~/ros2_ws/install/setup.bash" >> ~/.bashrc 一键搞定。

创建功能包

功能包是ROS2代码的组织单元。一个功能包可以包含节点、配置文件、启动文件等。创建功能包用这个命令:

cd ~/ros2_ws/src
ros2 pkg create my_first_pkg --build-type ament_python --dependencies rclpy std_msgs

参数说明:

  • --build-type ament_python:用Python开发(也可以用ament_cmake做C++)
  • --dependencies rclpy std_msgs:依赖的库,rclpy是ROS2的Python客户端库,std_msgs是标准消息类型

创建成功后,你会看到功能包目录下生成了 package.xml、setup.py、my_first_pkg 等文件。这些文件定义了包的元信息和构建规则。

编写第一个发布-订阅节点

终于到写代码环节了。咱们写一个最简单的发布-订阅程序:发布节点每隔1秒发一个「Hello ROS2」的消息,订阅节点收到后打印出来。

发布节点(publisher.py)

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

class MyPublisher(Node):
    def __init__(self):
        super().__init__('my_publisher')
        self.publisher_ = self.create_publisher(String, 'topic_hello', 10)
        self.timer = self.create_timer(1.0, self.timer_callback)
        self.count = 0

    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.init(args=args)
    node = MyPublisher()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

订阅节点(subscriber.py)

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

class MySubscriber(Node):
    def __init__(self):
        super().__init__('my_subscriber')
        self.subscription = self.create_subscription(
            String, 'topic_hello', self.listener_callback, 10)

    def listener_callback(self, msg):
        self.get_logger().info(f'收到: {msg.data}')

def main(args=None):
    rclpy.init(args=args)
    node = MySubscriber()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()
注意:话题名称 topic_hello 必须完全一致,包括大小写。我曾经因为把话题名写成了 Topic_Hello,结果两个节点互相找不到对方,排查了半天才发现是大小写问题。

配置入口点

在 setup.py 文件中添加入口点,这样就能用 ros2 run 命令启动了:

entry_points={
    'console_scripts': [
        'publisher = my_first_pkg.publisher:main',
        'subscriber = my_first_pkg.subscriber:main',
    ],
},

编译与运行

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

# 打开两个终端,分别运行
ros2 run my_first_pkg publisher
ros2 run my_first_pkg subscriber

看到终端里交替出现「发布: Hello ROS2: 0」「收到: Hello ROS2: 0」了吗?恭喜你,第一个ROS2节点跑起来了!

知识体系总览

下面这张图帮你梳理本章的核心逻辑:

ROS2基础与工作空间配置 - 知识体系 核心概念 • 节点:独立执行单元 • 话题:异步广播通信 • 服务:同步请求-响应 • 动作:可反馈的异步任务 三者各有适用场景 选对工具事半功倍 工作空间配置 • 创建目录结构 • colcon build 编译 • source 环境变量 • 创建功能包 每个项目独立工作空间 避免依赖冲突 发布-订阅实践 • 创建发布者节点 • 创建订阅者节点 • 配置入口点 • 编译与运行 话题名称必须一致 大小写敏感 理论 → 环境 → 实践,三步掌握ROS2基础

说实话,第一次跑通发布-订阅程序时,那种成就感还是很棒的。虽然只是打印了几行字,但这背后是整个ROS2通信机制的运转。后面咱们做机械臂抓取时,这些基础会反复用到。

嗯,今天就到这里。记住:多动手、多调试,遇到问题别怕,ROS2的错误信息其实挺友好的。下次见!

可可精品资料库