当前位置: 首页 > news >正文

ros2_01

note01

ROS2和ROS最大的区别中间件

中间件:

  1. 介于某两个或者多个节点中间的组件;
  2. 提供多个节点中间通信;

ROS1:中间件是ROS组织自己基于TCP机制建立的,随着现在传感器的升级,数据量越来越大,原先的数据拷贝机制就不再适了

ROS2:

  1. 将进程间通信intra-process自己来做
  2. 其他部分的通信就使用来DDS实现
  3. ROS2将DDS服务接口进行了一层抽象,保证了上层应用层调用接口的统一性
  4. ROS2去掉mater节点

DDS

Data Distribution Service:一种用于分布式系统的通信中间件标准

key points:

  1. 发布-订阅模式
    1. 数据生产者(Publisher)发布数据到主题(Topic)
    2. 数据消费者(Subscriber)订阅感兴趣的主题
    3. 发布者和订阅者之间是解耦的,不需要知道彼此的存在
  2. 数据为中心:
    1. DDS以数据为中心,而不是以节点为中心
    2. 数据通过主题进行标识,主题是数据的逻辑分类
  3. 实时性:
    1. DDS设计用于实时系统,支持低延迟和高吞吐量的数据传输

Domain

定义:一个逻辑隔离的通信空间,只有在同一个域中的节点才能互相通信;每个域有一个唯一的 Domain ID,用于标识不同的域

作用:

  1. 隔离通信:不同域中的节点无法互相通信,即使它们在同一个网络中
  2. 灵活性:可以通过 Domain ID 将系统划分为多个独立的通信空间

Fast DDS中的Domain 通过 DomainParticipant 来管理的

#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>

int main() {
    // 创建 DomainParticipant
    eprosima::fastdds::dds::DomainParticipant* participant =
        eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->create_participant(0);

    // 检查是否创建成功
    if (participant == nullptr) {
        std::cerr << "Failed to create DomainParticipant!" << std::endl;
        return -1;
    }

    std::cout << "DomainParticipant created successfully!" << std::endl;

    // 清理资源
    eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->delete_participant(participant);
    return 0;
}
  1. DomainParticipantFactory
    1. 用于创建和管理 DomainParticipant
    2. 通过 get_instance() 获取单例对象
  2. create_participant(domain_id)
    1. 创建一个 DomainParticipant,参数 domain_id 指定域的 ID
    2. 返回一个指向 DomainParticipant 的指针
  3. delete_participant(participant)
    1. 删除 DomainParticipant,释放资源
Topic

Topic是数据的逻辑分离,每个 Topic 有一个名称和一个数据类型;

发布者(Publisher)将数据发布到 Topic,订阅者(Subscriber)从 Topic 中订阅数据

作用:

  1. 数据分类:通过 Topic 将数据分类,例如“温度数据”或“位置数据”
  2. 解耦:发布者和订阅者不需要知道彼此的存在,只需要知道 Topic 的名称和数据类型
#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
#include <fastdds/dds/topic/Topic.hpp>
#include <fastdds/dds/topic/TypeSupport.hpp>

// 自定义数据类型
class HelloWorld {
public:
    std::string message;
};

int main() {
    // 创建 DomainParticipant
    eprosima::fastdds::dds::DomainParticipant* participant =
        eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->create_participant(0);

    // 注册数据类型
    eprosima::fastdds::dds::TypeSupport type(new HelloWorldPubSubType());
    type.register_type(participant);

    // 创建 Topic
    eprosima::fastdds::dds::Topic* topic = participant->create_topic(
        "HelloWorldTopic",  // Topic 名称
        type.get_type_name(),  // 数据类型名称
        eprosima::fastdds::dds::TOPIC_QOS_DEFAULT  // QoS 配置
    );

    if (topic == nullptr) {
        std::cerr << "Failed to create Topic!" << std::endl;
        return -1;
    }

    std::cout << "Topic created successfully!" << std::endl;

    // 清理资源
    participant->delete_topic(topic);
    eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->delete_participant(participant);
    return 0;
}
  1. TypeSupport:
    1. 用于注册和管理数据类型
    2. HelloWorldPubSubType 是自动生成的数据类型支持
  2. create_topic(name, type_name, qos)
    1. 创建一个 Topic,参数包括 Topic 名称、数据类型名称和 QoS 配置
    2. 返回一个指向 Topic 的指针
  3. delete_topic(topic)
    1. 删除 Topic,释放资源

Publisher 和 Subscriber

  1. Publisher:负责将数据发布到 Topic
  2. Subscriber:负责从 Topic 订阅数据

Topic实现:

  1. 观察者模式(Observer Pattern)
    1. Topic 是数据的逻辑分类,发布者(Publisher)和订阅者(Subscriber)通过 Topic 进行解耦
    2. 发布者将数据发布到 Topic,Topic 负责将数据分发给所有订阅了该 Topic 的订阅者
  2. 中介者模式(Mediator Pattern)
    1. Topic 充当发布者和订阅者之间的中介者,负责管理数据的传递
    2. 发布者和订阅者不需要直接交互,而是通过 Topic 进行通信

Publisher实现:

  1. Publisher 通过 DomainParticipant 的工厂方法(如 create_publisher)创建
  2. 代理模式(Proxy Pattern)
    1. Publisher 是数据发布的代理,负责将数据写入 DDS 中间件
    2. 实际的网络通信和数据传输由 DDS 中间件处理,Publisher 只是一个接口
  3. Publisher 内部维护了一个或多个 DataWriter,用于将数据写入 Topic

DataWriter

DataWriter是publisher一部分,负责将数据写入topic

  1. 数据写入:将应用程序生成的数据发布到 DDS 中间件
  2. QoS 管理:根据配置的 QoS 策略(如可靠性、持久性等)处理数据
  3. 生命周期管理:管理数据的生命周期,例如数据的创建、更新和删除

ROS2的DDS

DDS抽象:
  1. 节点:
    1. ROS 2 引入了 Node 的概念,封装了 DDS 中的 DomainParticipant
    2. 只需要创建和管理 Node,而不需要直接操作 DomainParticipant
  2. Publisher和Subscriber
    1. ROS 2 的 PublisherSubscriber 是对 DDS 中 DataWriterDataReader 的封装
    2. 只需要指定 Topic 名称和数据类型,ROS 2 会自动处理底层的 DDS 对象
  3. 消息Message
    1. ROS 2 使用 消息 作为数据传输的基本单位,消息类型通过 .msg 文件定义
  4. 统一的API
    1. ROS 2 通过 RMW(ROS Middleware Interface) 抽象了底层 DDS 实现的差异
    2. 每种 DDS 实现(如 Fast DDS、Cyclone DDS)都有一个对应的 RMW 实现
    3. 通过环境变量选择使用的 DDS 实现

相关文章:

  • Qt QML - qmldir使用方法详解
  • Leetcode——137 260找出只出现一次的数
  • 【密码学——基础理论与应用】李子臣编著 第六章 祖冲之序列密码 课后习题
  • Trae 下安装 Pylance 插件(仅作为实验,版权由微软所有)
  • 【lerobot】3-开源SO-100 主从臂的舵机位置校正、遥控操作(ubuntu系统)
  • 基于图扩散小波的连接组分析:定位结构-功能映射中的扩散源
  • docker部署GPUStack【Nvidia版本】
  • 【Hot100】239. 滑动窗口最大值
  • Express中间件(Middleware)详解:从零开始掌握(4)
  • 高级java每日一道面试题-2025年4月07日-微服务篇[Nacos篇]-如何监控Nacos的运行状态?
  • 深入探究AI编程能力:ChatGPT及其大规模模型的实现原理
  • 纯PHP编写的聊天室无需数据库,上传虚拟空间就可使用
  • 【PostgreSQL教程】PostgreSQL 特别篇之 语言接口连接PHP
  • [LeetCode 45] 跳跃游戏2 (Ⅱ)
  • Python高级爬虫之JS逆向+安卓逆向1.4节:数据运算
  • Solidity私有函数和私有变量区别,私有变量可以被访问吗
  • 在轨道交通控制系统中如何实现μs级任务同步
  • KiCad 9.0:如何在 PCB 上暴露铜皮(开窗)
  • go中new和make有什么异同?
  • [LeetCode 1306] 跳跃游戏3(Ⅲ)
  • 北理工:开除宫某党籍,免去行政职务,解除聘用关系
  • 全球南方声势卓然壮大的历史逻辑——写在万隆会议召开70周年之际
  • 西藏艺术来到黄浦江畔,“隐秘之门”艺术展外滩三号开幕
  • 林诗栋4比1战胜梁靖崑,晋级世界杯男单决赛将和雨果争冠
  • 观察丨微短剧盛行“拿来主义”,版权保护迫在眉睫
  • 旧电梯换新如何分摊费用?低楼层可以不出钱吗?上海闵行举办讨论会