大家好,我是小白小帅,在日常基于ros2开发移动机器人和学习过程中,个人总结和收集了一些关于ros2的问题(共25道),这些问题也是面试中可能涉及到的一些知识点,对于我个人就是一个简单的记录,但是为了让这些知识点更加丰富全面一些,我也是偷个懒让chatgpt基于我的记录优化和整理了一下,如果有些细节不到位或者不足的地方,欢迎小伙伴们指正,希望大家一起进步!(后续也会更新中级和高级的问题记录)
1、什么是ROS 2?它的基本架构是什么?
什么是 ROS 2?
ROS 2(Robot Operating System 2)是一个开源的、灵活的机器人操作系统,它为机器人应用提供了一套中间件和工具集合,帮助开发者创建、控制和调试机器人。它是 ROS 1 的继任者,设计上着重于支持更复杂的应用场景,如实时性能、分布式系统、跨平台支持和更高的安全性。
ROS 2 的核心目的是为机器人开发提供高效的通信机制、模块化的软件架构以及丰富的开发工具,旨在满足工业、研究和商业应用中对机器人系统的高标准要求。
ROS 2 的基本架构
ROS 2 的架构基于分布式系统设计,并使用了 DDS(Data Distribution Service) 作为其底层中间件,用于实现不同节点之间的高效通信。它的架构可以分为以下几个关键组件:
1. 节点(Node)
- 节点是 ROS 2 的基本计算单元。每个节点都可以运行一个或多个功能模块(如传感器数据处理、控制算法等)。
- 每个节点都可以通过话题、服务或动作与其他节点进行通信。
- 在 ROS 2 中,节点被设计为独立且可以动态加载、卸载。
2. 话题(Topic)
- 话题用于实现节点间的发布/订阅通信模式。节点可以发布消息到一个话题,其他节点可以订阅这个话题以接收消息。
- 话题是ROS 2通信中的重要组成部分,通常用于发送传感器数据、控制命令等。
3. 服务(Service)
- 服务提供了一种同步的请求/响应通信方式。节点可以通过请求服务并等待响应来实现控制命令等功能。
- 不同于话题的发布/订阅机制,服务是请求-响应模式,适用于需要直接交互的场景。
4. 动作(Action)
- 动作是ROS 2提供的一种用于执行长时间运行任务的通信机制,允许客户端发送目标并接收反馈。
- 动作通过定义目标、反馈和结果三部分信息,使得机器人能够执行复杂任务,并在过程中提供反馈信息。
5. 中间件(DDS)
- ROS 2 使用 DDS(Data Distribution Service) 作为其底层通信机制。DDS 是一个标准化的中间件协议,专门用于分布式系统中的数据传输。
- 它支持实时性、高可靠性、可伸缩性和灵活的 QoS(Quality of Service)策略,可以在不同的网络环境下确保消息的可靠传输。
6. 参数服务器(Parameter Server)
- ROS 2 允许每个节点使用 参数 来进行配置。节点可以获取、设置或更改参数,以便在运行时动态调整其行为。
- 参数服务器是一个集中的存储机制,用于保存节点的配置参数。
7. 调度与执行(Executor)
- 在 ROS 2 中,Executor 用于调度和管理多个节点的执行。ROS 2 提供了不同的执行器以支持不同的调度需求(如单线程、多线程)。
- 通过调度器,ROS 2 可以有效管理多个并发节点,提高性能和响应速度。
8. 生命周期管理(Lifecycle)
- ROS 2 引入了 生命周期管理,用于更精确地控制节点的生命周期。
- 生命周期节点可以根据需求启动、暂停、恢复或停止,以提高系统的健壮性和灵活性。
9. 跨平台支持
- ROS 2 支持多个操作系统平台,包括 Linux、Windows、macOS 和嵌入式系统(如ROS 2的嵌入式实现
micro-ROS
)。 - 跨平台支持意味着开发者可以在不同的操作系统上开发和运行ROS 2应用,方便各种硬件平台的接入。
10. 安全性
- ROS 2 引入了安全性功能,以确保机器人系统的数据传输和通信的安全性。它通过 DDS-Security 实现节点间的身份验证、加密和数据完整性验证。
ROS 2 的基本组件总结
- 节点(Node):机器人系统的基本执行单元。
- 话题(Topic):发布/订阅模型,传输数据。
- 服务(Service):请求/响应模型,处理控制和查询。
- 动作(Action):长时间任务和反馈机制。
- DDS(中间件):底层通信框架,提供实时数据分发。
- 参数服务器:节点的可配置参数管理。
- 生命周期管理:节点的启动、暂停、停止控制。
- 跨平台支持:支持多个操作系统。
- 安全性:提供数据加密、身份验证等安全机制。
总结
ROS 2 是一个模块化、灵活、可扩展的机器人操作系统,通过引入 DDS、生命周期管理和跨平台支持等特性,解决了 ROS 1 的一些局限性,特别是在实时性、分布式系统和安全性方面。它适用于各种机器人系统,从实验室研究到工业生产和商业机器人应用。
2、ROS 2 与 ROS 1 的主要区别有哪些?
ROS 2 与 ROS 1 虽然在功能上有很多相似之处,但在架构设计、通信机制、实时性支持、跨平台兼容性、安全性等方面有显著的区别。以下是 ROS 2 和 ROS 1 的主要区别:
1. 通信中间件:ROS 2 基于 DDS,而 ROS 1 使用自定义的通信协议
- ROS 1 使用自定义的 TCP/UDP 协议(如 TCPROS 和 UDPROS)来处理节点之间的通信。这种方式的灵活性较低,且对于复杂的网络配置和分布式系统来说,扩展性不足。
- ROS 2 则基于 DDS(Data Distribution Service) 作为通信中间件。DDS 是一个标准化的分布式通信框架,支持实时性、可靠性、可扩展性和 QoS(Quality of Service)等高级功能,适用于复杂的分布式系统。
- ROS 2 中的 DDS 实现了节点自动发现、可配置的传输层和安全性等特性,显著提高了系统的灵活性和性能。
2. 实时性支持
- ROS 1 并没有原生的实时性支持。如果要实现实时控制,开发者需要大量修改底层代码,并使用第三方工具或库来进行定制。
- ROS 2 从设计之初就考虑了实时性。由于 DDS 的支持,ROS 2 能够为高性能、实时性要求高的应用提供更好的通信和调度方案。此外,ROS 2 还引入了可定制的 Executor,用于管理节点的执行顺序和优先级,从而更好地支持实时任务。
3. 生命周期管理(Lifecycle)
- ROS 1 没有提供标准的节点生命周期管理,节点通常只有“启动”和“停止”两种状态。
- ROS 2 引入了节点的 Lifecycle 管理,允许开发者精细控制节点的状态(如未配置、已激活、已关闭等),从而提高系统的稳定性和运行时控制。这对于机器人系统的部署和调试尤其重要。
4. 跨平台支持
- ROS 1 主要针对 Linux(尤其是 Ubuntu)进行开发,虽然可以移植到其他平台,但支持有限。Windows 和 macOS 的支持并不完善。
- ROS 2 从设计之初就考虑了跨平台支持,提供了对 Linux、Windows 和 macOS 的官方支持。此外,ROS 2 还支持嵌入式设备(如 RTOS)和微控制器上的轻量化版本(如 micro-ROS),扩展了 ROS 系统在不同硬件平台上的适用性。
5. 安全性
- ROS 1 的通信并不具备原生的安全机制,没有内置加密、身份验证或数据完整性验证功能。因此在对安全性有高要求的应用中,开发者需要自己实现相关的安全措施。
- ROS 2 基于 DDS 提供了内置的安全性支持,符合 DDS-Security 标准。它包括 身份验证、访问控制、加密 等功能,可以确保节点间通信的机密性、完整性和可认证性,适用于对安全性要求较高的场景,如工业机器人和无人驾驶系统。
6. QoS(Quality of Service)支持
- ROS 1 中没有内置的 QoS 控制,所有节点通信的可靠性、消息丢失容忍度、延迟控制等都无法灵活配置,导致一些复杂网络场景下的性能欠佳。
- ROS 2 引入了基于 DDS 的 QoS 配置。开发者可以灵活地控制通信的可靠性、持久性、历史消息保存、延迟等参数,从而优化不同应用的通信性能。例如,可以在低带宽环境下选择
Best Effort
模式,或者在关键任务中选择Reliable
模式。
7. 调度与执行模型
- ROS 1 中的节点是相对独立的,调度和执行依赖于操作系统的进程调度,无法实现对节点执行的精细控制。
- ROS 2 提供了可配置的 Executor,允许开发者控制节点的执行策略,支持单线程、多线程等多种调度方式。这样可以优化系统性能,特别是在实时性要求较高的系统中。
8. 网络架构
- ROS 1 使用基于主机的集中式网络架构,依赖于 ROS Master 来进行节点的注册和发现。如果主机失效,整个 ROS 系统就会瘫痪,系统的扩展性也因此受到限制。
- ROS 2 不再依赖中心化的 ROS Master,而是采用了 分布式发现机制。每个节点可以自动发现其他节点并建立通信链接,使系统更加灵活,并能够适应分布式或不稳定的网络环境。
9. 包管理和构建工具
- ROS 1 使用 catkin 作为包管理和构建工具,虽然功能强大,但对复杂的多包项目支持不足,且有一定的学习曲线。
- ROS 2 引入了更现代化的构建工具 colcon,它简化了包的构建和管理流程,特别是对多包工作区的支持更为灵活。同时,colcon 支持并行构建、测试、打包等功能,极大提升了开发效率。
10. 多机器人支持
- ROS 1 支持多机器人系统,但需要复杂的手动配置,如话题和命名空间的手动管理等。
- ROS 2 更加原生地支持多机器人系统,利用 DDS 的自动发现和 QoS 配置,能更好地管理多个机器人的通信和数据流,提高多机器人系统的易用性和可扩展性。
11. 嵌入式支持
- ROS 1 对嵌入式系统的支持较弱,无法高效地运行在资源受限的设备上。
- ROS 2 提供了对嵌入式系统的支持,如通过 micro-ROS 可以在资源受限的微控制器上运行 ROS 2,适用于无人机、智能传感器等需要高性能但硬件资源有限的场景。
总结
ROS 2 是 ROS 1 的重大改进版本,解决了 ROS 1 在实时性、分布式支持、跨平台、嵌入式和安全性方面的不足。ROS 2 更适合复杂的工业、商用和研究领域,特别是在多机器人系统、实时控制、分布式网络和安全通信方面表现更为出色。
3、什么是节点(Node)?如何在ROS 2中创建一个简单的节点?
什么是节点(Node)?
在 ROS 2 中,节点(Node) 是机器人应用程序的基本组成单元。节点负责执行特定的功能,比如处理传感器数据、控制运动、发布或订阅消息等。每个 ROS 2 系统通常由多个节点组成,它们通过 ROS 2 的通信机制(如话题、服务、动作)进行交互和协作。
节点的特点:
- 模块化:每个节点通常执行一个独立的任务,可以互相独立开发、测试和部署。
- 通信能力:节点可以通过发布/订阅消息、请求/响应服务等机制与其他节点通信。
- 分布式:节点可以分布在不同的计算机或硬件设备上,利用 ROS 2 的分布式架构进行数据交换和协作。
- 独立性:每个节点是独立的进程,具有自己的生命周期,易于扩展和维护。
如何在 ROS 2 中创建一个简单的节点?
ROS 2 提供了多种编程语言支持,最常用的是 Python 和 C++。接下来我们分别介绍如何在这两种语言中创建一个简单的 ROS 2 节点。
1. 使用 Python 创建一个简单的节点
步骤 1:创建工作区和包
首先,创建一个 ROS 2 工作区,并在其中创建一个包含 Python 节点的包。
# 创建一个工作区
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws
# 创建一个 ROS 2 包,依赖于 rclpy(Python API)
ros2 pkg create --build-type ament_python my_python_pkg --dependencies rclpy
步骤 2:编写节点代码
在 my_python_pkg
包的 my_python_pkg
文件夹中创建一个 Python 文件(如 simple_node.py
),并编写一个简单的 ROS 2 节点。
# simple_node.py
import rclpy # ROS 2 Python客户端库
from rclpy.node import Node # Node类
class SimpleNode(Node):
def __init__(self):
# 调用父类构造函数,命名节点为'simple_node'
super().__init__('simple_node')
# 使用定时器每1秒调用一次callback函数
self.timer = self.create_timer(1.0, self.timer_callback)
def timer_callback(self):
self.get_logger().info('Hello, ROS 2!')
def main(args=None):
rclpy.init(args=args) # 初始化rclpy
node = SimpleNode() # 创建节点实例
rclpy.spin(node) # 让节点进入循环并保持活跃
node.destroy_node() # 销毁节点
rclpy.shutdown() # 关闭rclpy
if __name__ == '__main__':
main()
步骤 3:配置 setup.py
在 my_python_pkg
包的根目录下,修改 setup.py
文件,确保 Python 文件可以被正确安装和执行。
from setuptools import setup
package_name = 'my_python_pkg'
setup(
name=package_name,
version='0.0.0',
packages=[package_name],
install_requires=['setuptools'],
zip_safe=True,
maintainer='Your Name',
maintainer_email='your.email@example.com',
description='A simple Python ROS 2 node',
license='Apache License 2.0',
entry_points={
'console_scripts': [
'simple_node = my_python_pkg.simple_node:main',
],
},
)
步骤 4:构建和运行节点
构建包并运行刚才创建的节点。
# 构建工作区
cd ~/ros2_ws
colcon build
# 在新的终端中,运行节点
source install/setup.bash
ros2 run my_python_pkg simple_node
你将会看到终端中每隔一秒打印一次 “Hello, ROS 2!”。
2. 使用 C++ 创建一个简单的节点
步骤 1:创建工作区和包
与 Python 类似,首先创建一个 C++ 包。
# 创建一个工作区
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws
# 创建一个 ROS 2 包,依赖于 rclcpp(C++ API)
ros2 pkg create --build-type ament_cmake my_cpp_pkg --dependencies rclcpp
步骤 2:编写节点代码
在 my_cpp_pkg/src
文件夹中创建一个 C++ 文件(如 simple_node.cpp
),并编写一个简单的 ROS 2 节点。
// simple_node.cpp
#include "rclcpp/rclcpp.hpp"
class SimpleNode : public rclcpp::Node
{
public:
SimpleNode() : Node("simple_node") // 初始化节点名为 'simple_node'
{
// 创建定时器,每隔1秒调用一次timer_callback函数
timer_ = this->create_wall_timer(
std::chrono::seconds(1),
std::bind(&SimpleNode::timer_callback, this));
}
private:
void timer_callback()
{
RCLCPP_INFO(this->get_logger(), "Hello, ROS 2!");
}
rclcpp::TimerBase::SharedPtr timer_; // 定时器指针
};
int main(int argc, char * argv[])
{
rclcpp::init(argc, argv); // 初始化rclcpp
auto node = std::make_shared<SimpleNode>(); // 创建节点实例
rclcpp::spin(node); // 保持节点运行
rclcpp::shutdown(); // 关闭rclcpp
return 0;
}
步骤 3:修改 CMakeLists.txt
在 my_cpp_pkg
包的根目录下,修改 CMakeLists.txt
文件,确保 C++ 文件可以被正确编译。
cmake_minimum_required(VERSION 3.5)
project(my_cpp_pkg)
# 寻找依赖项
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
add_executable(simple_node src/simple_node.cpp) # 添加可执行文件
ament_target_dependencies(simple_node rclcpp) # 设置依赖关系
install(TARGETS
simple_node
DESTINATION lib/${PROJECT_NAME})
ament_package()
步骤 4:构建和运行节点
构建 C++ 包并运行节点。
# 构建工作区
cd ~/ros2_ws
colcon build
# 在新的终端中,运行节点
source install/setup.bash
ros2 run my_cpp_pkg simple_node
你将会看到终端中每隔一秒打印一次 “Hello, ROS 2!”。
总结
在 ROS 2 中,节点是构建机器人应用的基本模块,负责执行具体的功能。通过编写简单的 Python 或 C++ 代码,我们可以创建节点并让它们执行周期性任务。ROS 2 提供了简洁且灵活的 API,允许开发者快速构建和管理复杂的机器人系统。
4、什么是话题(Topic)?如何在ROS 2中发布和订阅话题?
什么是话题(Topic)?
话题(Topic) 是 ROS 2 中用于节点之间进行消息传递的通信机制,采用 发布/订阅(Publish/Subscribe) 模型。通过话题,一个节点可以发布特定类型的消息,而其他节点可以订阅该话题以接收消息。这种模型适用于数据流的广播和分发,如传感器数据发布、多节点之间共享信息等。
话题的工作原理:
- 发布者(Publisher):负责在某个话题上发布消息。可以有多个节点作为同一话题的发布者。
- 订阅者(Subscriber):负责订阅某个话题,并接收该话题上的消息。可以有多个节点订阅同一话题。
- 消息(Message):发布者和订阅者之间通过标准化的消息类型进行通信。消息类型可以是 ROS 2 定义的标准类型(如
std_msgs
),也可以是用户自定义的类型。
这种解耦的通信方式允许发布者和订阅者在彼此不知情的情况下进行通信,提高了系统的灵活性和模块化。
如何在 ROS 2 中发布和订阅话题
接下来,我将介绍如何使用 Python 和 C++ 创建一个发布者和订阅者节点。
1. 使用 Python 发布和订阅话题
步骤 1:创建一个 ROS 2 包
首先,创建一个包含 Python 节点的 ROS 2 包:
# 创建一个工作区
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws
# 创建一个依赖于rclpy和std_msgs的包
ros2 pkg create --build-type ament_python my_topic_pkg --dependencies rclpy std_msgs
步骤 2:编写发布者节点代码
在 my_topic_pkg
包的 my_topic_pkg
文件夹中创建一个 Python 文件 publisher_node.py
,用于发布消息。
# publisher_node.py
import rclpy
from rclpy.node import Node
from std_msgs.msg import String # 导入String消息类型
class MinimalPublisher(Node):
def __init__(self):
super().__init__('minimal_publisher') # 初始化节点名
self.publisher_ = self.create_publisher(String, 'topic', 10) # 创建发布者,话题名为'topic'
timer_period = 1.0 # 定时器周期(1秒)
self.timer = self.create_timer(timer_period, self.timer_callback)
def timer_callback(self):
msg = String()
msg.data = 'Hello, ROS 2!' # 发布消息内容
self.publisher_.publish(msg) # 发布消息
self.get_logger().info('Publishing: "%s"' % msg.data)
def main(args=None):
rclpy.init(args=args)
minimal_publisher = MinimalPublisher()
rclpy.spin(minimal_publisher) # 保持节点运行
minimal_publisher.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
步骤 3:编写订阅者节点代码
接下来,在 my_topic_pkg
包的 my_topic_pkg
文件夹中创建另一个 Python 文件 subscriber_node.py
,用于订阅消息。
# subscriber_node.py
import rclpy
from rclpy.node import Node
from std_msgs.msg import String # 导入String消息类型
class MinimalSubscriber(Node):
def __init__(self):
super().__init__('minimal_subscriber') # 初始化节点名
self.subscription = self.create_subscription(
String,
'topic', # 订阅的话题名
self.listener_callback,
10)
self.subscription # 防止垃圾回收
def listener_callback(self, msg):
self.get_logger().info('I heard: "%s"' % msg.data)
def main(args=None):
rclpy.init(args=args)
minimal_subscriber = MinimalSubscriber()
rclpy.spin(minimal_subscriber) # 保持节点运行
minimal_subscriber.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
步骤 4:修改 setup.py
确保在 setup.py
文件中正确配置了入口点,以便可以执行节点。修改 my_topic_pkg
包的根目录中的 setup.py
文件:
from setuptools import setup
package_name = 'my_topic_pkg'
setup(
name=package_name,
version='0.0.0',
packages=[package_name],
install_requires=['setuptools'],
zip_safe=True,
maintainer='Your Name',
maintainer_email='your.email@example.com',
description='A simple publisher and subscriber example in ROS 2',
license='Apache License 2.0',
entry_points={
'console_scripts': [
'publisher_node = my_topic_pkg.publisher_node:main',
'subscriber_node = my_topic_pkg.subscriber_node:main',
],
},
)
步骤 5:构建并运行节点
构建包并运行发布者和订阅者节点:
# 构建工作区
cd ~/ros2_ws
colcon build
# 在一个终端中,运行发布者节点
source install/setup.bash
ros2 run my_topic_pkg publisher_node
# 在另一个终端中,运行订阅者节点
source install/setup.bash
ros2 run my_topic_pkg subscriber_node
你将会看到发布者节点每秒发布一次 “Hello, ROS 2!”,订阅者节点则会显示接收到的消息。
2. 使用 C++ 发布和订阅话题
步骤 1:创建一个 ROS 2 包
创建一个包含 C++ 节点的 ROS 2 包:
# 创建一个工作区
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws
# 创建一个依赖于rclcpp和std_msgs的包
ros2 pkg create --build-type ament_cmake my_cpp_topic_pkg --dependencies rclcpp std_msgs
步骤 2:编写发布者节点代码
在 my_cpp_topic_pkg/src
文件夹中创建一个 C++ 文件 publisher_node.cpp
,用于发布消息。
// publisher_node.cpp
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp" // 导入String消息类型
class MinimalPublisher : public rclcpp::Node
{
public:
MinimalPublisher()
: Node("minimal_publisher")
{
publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10); // 创建发布者
timer_ = this->create_wall_timer(
std::chrono::seconds(1),
std::bind(&MinimalPublisher::timer_callback, this)); // 创建定时器,每秒发布消息
}
private:
void timer_callback()
{
auto message = std_msgs::msg::String();
message.data = "Hello, ROS 2!";
RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
publisher_->publish(message);
}
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
rclcpp::TimerBase::SharedPtr timer_;
};
int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<MinimalPublisher>());
rclcpp::shutdown();
return 0;
}
步骤 3:编写订阅者节点代码
在 my_cpp_topic_pkg/src
文件夹中创建另一个 C++ 文件 subscriber_node.cpp
,用于订阅消息。
// subscriber_node.cpp
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp" // 导入String消息类型
class MinimalSubscriber : public rclcpp::Node
{
public:
MinimalSubscriber()
: Node("minimal_subscriber")
{
subscription_ = this->create_subscription<std_msgs::msg::String>(
"topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, std::placeholders::_1));
}
private:
void topic_callback(const std_msgs::msg::String::SharedPtr msg) const
{
RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg->data.c_str());
}
rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
};
int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<MinimalSubscriber>());
rclcpp::shutdown();
return 0;
}
步骤 4:修改 CMakeLists.txt
在 my_cpp_topic_pkg
包的根目录下,修改 CMakeLists.txt
文件以包含发布者和订阅者节点的编译规则:
cmake_minimum_required(VERSION 3.5)
project(my_cpp_topic_pkg)
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
add_executable(publisher_node src/publisher_node.cpp
)
ament_target_dependencies(publisher_node rclcpp std_msgs)
add_executable(subscriber_node src/subscriber_node.cpp)
ament_target_dependencies(subscriber_node rclcpp std_msgs)
install(TARGETS
publisher_node
subscriber_node
DESTINATION lib/${PROJECT_NAME})
ament_package()
步骤 5:构建并运行节点
构建 C++ 包并运行节点:
# 构建工作区
cd ~/ros2_ws
colcon build
# 在一个终端中,运行发布者节点
source install/setup.bash
ros2 run my_cpp_topic_pkg publisher_node
# 在另一个终端中,运行订阅者节点
source install/setup.bash
ros2 run my_cpp_topic_pkg subscriber_node
发布者和订阅者节点将通过话题 topic
进行通信,发布者每秒发布一次消息,订阅者接收并打印消息。
总结
在 ROS 2 中,话题是一种用于节点间消息传递的机制,通过发布/订阅模型实现。ROS 2 提供了简洁的 API 供开发者通过 Python 或 C++ 创建发布者和订阅者节点,实现数据流的实时传输和分发。这种模型非常适用于分布式系统中不同节点之间的通信。
5、ROS 2 中的服务(Service)与话题有什么区别?
在 ROS 2 中,服务(Service) 和 话题(Topic) 都是节点间通信的方式,但它们在通信模式和使用场景上有显著的区别。
1. 通信模式的区别
话题(Topic)
- 发布/订阅模式(Publish/Subscribe):在话题模型中,数据通过“发布”和“订阅”方式传递。
- 异步通信:发布者和订阅者是解耦的,消息的传递是异步的。发布者发布消息后,订阅者在任何时刻都可以接收这些消息。
- 无请求/响应机制:订阅者收到的消息不会直接影响发布者,消息的处理不需要等待响应。
- 典型应用场景:实时数据流(如传感器数据、里程计数据、图像流)等。
服务(Service)
- 请求/响应模式(Request/Response):服务的通信模型采用“请求”和“响应”的方式,类似于远程过程调用(RPC)。客户端发送请求,服务端处理后返回响应。
- 同步通信:请求的发起者(客户端)会等待响应,在服务端处理完请求并返回结果之前,客户端无法继续执行。
- 典型应用场景:如控制命令、获取某个资源的状态、执行特定任务等。
2. 使用场景的区别
- 话题:适用于需要实时持续传输大量数据的场景。例如:传感器数据(激光雷达、摄像头)、机器人状态信息(如位置、速度)、其他实时数据流等。多个节点可以同时订阅同一个话题,进行异步的数据交换。
- 服务:适用于需要请求和响应的场景。例如:获取机器人当前状态、请求执行某个动作、获取特定的配置信息等。服务提供者在收到请求后,需要处理并返回结果,通常用于客户端对特定任务的控制。
3. ROS 2 中的实现方式
话题:
- 发布者(Publisher):将消息发布到某个话题。
- 订阅者(Subscriber):订阅话题,接收消息。
示例:
# 发布者节点
publisher = node.create_publisher(String, 'topic_name'