通信中間件 Fast DDS 基礎概念簡述與通信示例

從事汽車軟件開發(fā),通信中間件繞不開,當前最火熱的無非有 2 種:Some/IP 和 DDS。DDS 是一種分布式通信標準,有很多商業(yè)和開源的實現(xiàn),F(xiàn)ast DDS 是其中的一種。它在 ROS2 中被應用,而 Apollo 中的 CyberRT 框架中也有它的身影。
講 Fast DDS 之前先講什么是 DDS。
1. 什么是 DDS ?
DDS 是 OMG 組織發(fā)布的一種中間件協(xié)議和 API 標準,它將系統(tǒng)的組件集成在一起,提供業(yè)務和任務關鍵型物聯(lián)網 (IoT) 應用程序所需的低延遲數(shù)據(jù)連接、極高的可靠性和可擴展架構。
DDS(Data Distribution Service,數(shù)據(jù)分發(fā)服務) 是一種以數(shù)據(jù)為中心的通信協(xié)議,用于分布式軟件應用程序通信。
它描述了支持 數(shù)據(jù)提供者(Data Providers) 和 數(shù)據(jù)消費者(Data Consumers) 之間通信的通信應用程序編程接口 (API) 和通信語義。
要學習 DDS 就不能忽略它的模型:DCPS(以數(shù)據(jù)為中心的發(fā)布訂閱模型)。
DCPS 有 3 個關鍵實體:
- publication entities: 定義消息生成對象及相關屬性
- subscription entities:定義消息消費對象及相關屬性
- configuration entities:定義傳輸相關的屬性如 Topic 類型,通信的 QoS(服務質量)。
QoS 是一個非常重要的概念,DDS 使用 QoS 來定義 DDS 實體的行為特征。QoS 由單獨的 QoS 策略(源自 QoSPolicy 的類型的對象)組成。
2. 什么是 Fast-DDS?
DDS 是一套標準,它有很多實現(xiàn),有商業(yè)的,也有開源的。
商業(yè):RTI 開源: Cyclone DDS、Fast-DDS
所以,F(xiàn)ast DDS 是一種開源的 DDS 標準實現(xiàn),它由 ePromise 公司發(fā)布并維護。
3. 什么是 DCPS?
先看看 Fast DDS 官方文檔中的一張圖。
在這里插入圖片描述
DDS 是以數(shù)據(jù)為中心的通信模型,那么這個數(shù)據(jù)中心是什么呢?
我個人的理解是以 Topic 為代表的消息對象就是 DDS 中的數(shù)據(jù)中心。
通過 Topic 的紐帶關系,可以將數(shù)據(jù)生成為數(shù)據(jù)消費對象連接起來,并且可以通過 QoS 執(zhí)行通信服務質量策略。
在 DCPS 模型中,有 4 個基礎的概念:
- Publisher:它是負責創(chuàng)建和配置其實現(xiàn)的 DataWriters 的 DCPS 實體。DataWriter 是負責實際發(fā)布消息的實體。每個 DataWriter 都有一個分配的 Topic,在該 Topic 下發(fā)布消息。
- Subscriber:它負責接收在其訂閱的 Topic下發(fā)布的數(shù)據(jù)。它為一個或多個 DataReader 對象提供服務,這些對象負責將新數(shù)據(jù)的可用性傳達給應用程序。
- Topic(話題):它是綁定發(fā)布和訂閱的實體。它在 DDS 域中是唯一的。通過TopicDescription,它允許發(fā)布和訂閱數(shù)據(jù)類型的統(tǒng)一。
- Domain(領域):這是用于鏈接所有發(fā)布者和訂閱者的概念,屬于一個或多個應用程序,它們在不同主題下交換數(shù)據(jù)。這些參與域的單個應用程序稱為 DomainParticipant。DDS 域由域 ID 標識。DomainParticipant 定義域 ID 以指定它所屬的 DDS 域。具有不同 ID 的兩個 DomainParticipants 不知道彼此在網絡中的存在。因此,可以創(chuàng)建多個通信通道。這適用于涉及多個DDS應用程序的場景,它們各自的 DomainParticipants 相互通信,但這些應用程序不得干擾。DomainParticipant 充當其他 DCPS 實體的容器,充當發(fā)布者、訂閱者和主題實體的工廠,并在域中提供管理服務。
DDS 是一種通過信息,而 DCPS 是一個抽象的模型概念,實際上映射到具體的代碼維度,則需要 DomainParticipants 作為容器去承載 Publisher、Subsriber、Topic 等等。
可以這樣理解:
- Domain 是項目組
- Topic 是項目生產過程各類相關產出物,如需求文檔、概要設計、產品方案、測試用例等
- DomainParticipant 代表項目中不同的參與組織如UI小組、產品小組、開發(fā)小組、測試小組等等
- Publisher 和 Subscriber 代表不同小組中對外輸出文檔和接受信息的窗口角色
- QoS 代表不同的文檔在各個小組流轉時,雙方對于文件傳輸狀態(tài)的質量要求
在這里插入圖片描述
最后說明一下,如何理解 QoS 呢?
你可以聯(lián)想到,假如你是寫代碼的,產品經理傳遞文件給你時的方法和需要你反饋的時效,以及測試人員傳遞文檔給你要求的時效是不一樣的。
當然,這里只是類比,為了幫助大家加深理解,真正的 DDS 不一定這樣。
4. 什么是 RTPS ?
RTPS 是 Real-Time Publish Subscribe 的縮寫,它是 DDS 的通信中間件,是發(fā)布-訂閱模式,通信能力強大,支持 UDP/IP、TCP 及共享內存。
RTPS 是 DDS 通信的根基,它內部有一樣重要的概念:
- Domain
- RTPSParticipant
- Topic
- Attributes
- Change
- History
- RTPSWriter
- RTPSReader
RTPS 中定義了一個 Domain 的概念,它定義了一個單獨的通信平面。幾個域可以同時獨立地共存。一個域包含任意數(shù)量的 RTPSParticipant,即能夠發(fā)送和接收數(shù)據(jù)的元素。
RTPSParticipants 使用 EndPoint 進行通信:
- RTPSWriter:能夠發(fā)送數(shù)據(jù)的 EndPoint 端點。
- RTPSReader:能夠接收數(shù)據(jù)的 EndPoint 端點。
RTPSParticipant 可以有任意數(shù)量的寫入器和讀取器端點。
在這里插入圖片描述
Topic 定義和標記正在交換的數(shù)據(jù)。主題不屬于特定 DomainParticipant。DomainParticipant 通過 RTPSWriters 對 Topic 發(fā)布的數(shù)據(jù)進行更改,并通過 RTPSReaders 接收與其訂閱的 Topic 相關的數(shù)據(jù)。
在 Fast DDS 中最基礎的通信單元稱為 Change,它表示在 Topic 下寫入的數(shù)據(jù)的更新。RTPSReaders/RTPSWriters 在其 History 中注冊這些 Change,History 是一種用作最近更改緩存的數(shù)據(jù)結構。
在 eProsima Fast DDS 的默認配置中,當您通過 RTPSWriter 端點發(fā)布更改時,會在后臺執(zhí)行以下步驟:
-
Change 將添加到 RTPSWriter 的 History 中。
-
RTPSWriter 將 Change 發(fā)送到它知道的任何 RTPSReaders。
-
接收到數(shù)據(jù)后,RTPSReaders 用新的 Change 更新他們的 History。
Fast DDS 支持多種配置,允許更改 RTPSWriters/RTPSReaders 的行為。修改 RTPS 實體的默認配置意味著 RTPSWriters 和 RTPSReaders 之間的數(shù)據(jù)交換流發(fā)生變化。此外,通過選擇服務質量 (QoS) 策略,您可以通過多種方式影響這些歷史緩存的管理方式,但通信循環(huán)保持不變。
5. Fast DDS 和 RTPS 關系?
前文說過 RTPS 是 DDS 的基礎,實際上完整的 Fast DDS 架構分為 4 層:
- Application Layer
- FAST DDS Layer
- RTPS Layer
- Tranport Layer
在這里插入圖片描述
Application 指的是采用 Fast DDS API 的各類應用。
DDS Layer 主要定義一個系統(tǒng)中不同的 Domain,在同一個 Domain 下 Topic 按規(guī)則通信。
Fast RTPS 是通信協(xié)調層,是下層 Transport 的抽象。
Transport 層處理底層 UDP、TCP、SHM(共享內存)。
6. 一個簡單的 Fast DDS 示例
要使用 Fast DDS 首先需要安裝它,有 bin、Source、docker image 3 種方式,但 bin 和 docker image 需要到官網預留個人信息才能下載,所以,我們可以考慮源碼下載。
要下載 3 份源碼:
- vendor
- fast cdr
- fast dds
我選擇的是在 ubuntu 下用 cmake 方式編譯。
可以參考這個地址:DDS安裝
當然,還要下載編譯 Fast DDS Gen,它是一個工具,能夠將 IDL 文件轉換成 C++ 代碼。
現(xiàn)在考慮寫一個最基礎的 DDS 應用。
我們首先需要知道一個最小的 DDS 應該包含什么。
- 消息.IDL
- 數(shù)據(jù)發(fā)布器對應的.cpp
- 數(shù)據(jù)接收器對應的.cpp
- CMakeLists.txt
消息數(shù)據(jù)通過 IDL 文件定義。
IDL 功能很強大,定義了基礎數(shù)據(jù)類型、數(shù)組、窗器、map、枚舉、注解等等。[3]
fastddsgen 可以將其轉換成 c++ 數(shù)據(jù)結構體。
在這里插入圖片描述
通過 fastddsgen 可以轉換成 C++ 類。
現(xiàn)在我們可以編寫一個簡單的 IDL
在這里插入圖片描述
然后可以通過 fastddsgen 快速生成代碼。
在這里插入圖片描述
最終會自動產生好幾個代碼文件。
在這里插入圖片描述
FrankTestDDS.idl 被轉換成 FrankTestDDS.cxx 和它應對的 .h 文件。
其它的 FrankTestDDSPubSubMain 之類是 fastddsgen 自動生成的,用于實現(xiàn)發(fā)布和訂閱演示代碼。
我們先觀察 CMakeLists.txt。
在這里插入圖片描述
我們可以發(fā)現(xiàn),整個工程依賴于 fastcdr 和 fastrtps 兩個庫,之后,代表消息數(shù)據(jù)經 idl 轉換后的 FrankTestDDS.cxx 被編譯成庫的形式。
這樣后面編譯的 FrankTestDDS 這個可執(zhí)行文件就可以鏈接消息庫,保證了應用代碼和消息的解耦。
現(xiàn)在我要試驗 FastDDS 的發(fā)布-訂閱功能。我在生成的 FrankTestDDSPublisher.cxx 中添加了一些代碼。
在這里插入圖片描述
st 是我們的消息體,我將其中的 msg 賦值。
同時,我還得修改 FrankTestSubscriber.cxx 的代碼。
在這里插入圖片描述
現(xiàn)在,我們可以編譯代碼并嘗試運行了。
mkdir build
cd build
cmake ..
make
然后,分別在兩個終端中運行 publisher 和 subscriber
./FrankTestDDS publisher
./FrankTestDDS subscriber
在這里插入圖片描述
我們可以看到,通信正常,這也說明我們可以開始通過 fast dds 干活了。
至于高階內容,需要結合業(yè)務實際需求了,比如大量傳輸攝像頭圖片、點云數(shù)據(jù)、控制命令等等。我們得處理好相應的數(shù)據(jù)結構轉換和 QOS 定義。這個在本文中就不展開了。
參考
- https://www.dds-foundation.org/what-is-dds-3/
- https://fast-dds.docs.eprosima.com/en/latest/fastdds/getting_started/definitions.html
- https://www.omg.org/spec/IDL/4.2/PDF
???????????????? END ????????????????
推薦閱讀
【2】Linux開發(fā)coredump文件分析實戰(zhàn)分享
【3】CPU中的程序是怎么運行起來的 必讀
【4】cartographer環(huán)境建立以及建圖測試
本公眾號全部原創(chuàng)干貨已整理成一個目錄,回復[ 資源 ]即可獲得。
