3. DDS層
eProsima Fast DDS公開了兩個不同的API,以在不同級別與通信服務交互。主要API是數據分發服務(DDS)數據中心發佈訂閱(DCPS)平臺獨立模型(PIM)API,簡稱DDS DCPS PIM,由Fast DDS遵循的數據分發服務1.4版規範定義。本節旨在解釋Fast DDS下此API的主要特性和使用模式,並對其分爲五個模塊進行深入解釋:
- Core: 它定義了由其他模塊細化的抽象類和接口。它還提供了服務質量(QoS)定義,以及支持中間件的基於通知的交互。
- Domain: 它包含充當服務入口點的DomainParticipant類,以及許多類的工廠。DomainParticipant還充當構成服務的其他對象的容器。
- Publisher: 它描述了發佈端使用的類,包括Publisher和DataWriter類,以及PublisherListener和DataWriterListener接口。
-Subscriber: 它描述了訂閱端使用的類,包括Subscriber和DataReader類,以及SubscriberListener和DataReaderListener接口。 - Topic: 它描述了用於定義通信主題和數據類型的類,包括Topic和TopicDescription類,以及TypeSupport和TopicListener接口。
3.1 Core
此模塊定義其他模塊將使用的基礎結構類和類型。它包含實體類、QoS策略和狀態的定義。
- Entity: 實體是具有狀態的DDS通信對象,可以使用策略進行配置。
- Policy: 控制實體行爲的每個配置對象。
- Status: 與實體關聯的每個對象,其值表示該實體的通信狀態。
3.1.1 Entity
實體是所有DDS實體的抽象基類,意味着支持QoS策略、偵聽器和狀態的對象。
3.1.1.1 Entity的類型
- DomainParticipant: 此實體是服務的入口點,充當發佈服務器、訂閱服務器和主題的工廠。有關詳細信息,請參閱DomainParticipant。
- Publisher: 它充當一個工廠,可以創建任意數量的DataWriter。有關詳細信息,請參閱Publisher。
- Subscriber: 它充當一個工廠,可以創建任意數量的DataReader。有關詳細信息,請參閱訂閱服務器。
- Topic: 此實體位於發佈實體和訂閱實體之間,充當通道。有關詳細信息,請參閱主題。
- DataWriter: 是負責數據分發的對象。有關詳細信息,請參閱DataWriter。
- DataReader: 用於訪問接收數據的對象。有關詳細信息,請參閱DataReader。
下圖顯示了所有DDS實體之間的層次結構:
3.1.1.2 通用實體特徵
所有實體類型都具有實體概念所共有的一些特徵。這些是:
3.1.1.2.1 Entity標識符
每個實體都由一個唯一的ID標識,該ID在DDS實體與其對應的RTPS實體(如果存在)之間共享。該ID存儲在Entity基類上聲明的Instance Handle對象上,可以使用getter函數get_Instance_Handle()訪問該對象。
3.1.1.2.1 QoS策略
可以使用一組配置策略來配置每個實體的行爲。對於每個實體類型,都有一個對應的服務質量(QoS)類,該類對影響所述實體類型的所有策略進行分組。用戶可以創建這些QoS類的實例,根據自己的需要修改包含的策略,並在創建過程中或稍後使用每個實體公開的set_QoS()函數來配置實體(DomainParticipant::set_qos(),Publisher::set_qos(),Subscriber::set.qos(),Topic::set.qos(),DataWriter::set_qos(),DataReader::set.qos())。有關可用策略及其說明的列表,請參閱策略。QoS類及其包含的策略在每個實體類型的文檔中進行了解釋。
3.1.1.2.3 Listener監聽器
偵聽器包含一些函數,實體使用這些函數來響應事件。因此,偵聽器充當異步通知系統,允許實體嚮應用程序通知實體中的狀態更改。因此,偵聽器就像一個異步通知系統,允許實體嚮應用程序通知實體中的狀態更改。
所有實體類型都定義一個抽象偵聽器接口,該接口包含實體將觸發的回調函數,以將狀態更改傳遞給應用程序。用戶可以實現自己的偵聽器,從這些接口繼承並實現應用程序所需的回調。然後,他們可以在創建過程中或稍後使用每個實體公開的set_listener()函數將這些偵聽器鏈接到每個實體(DomainParticipant::set_listenr(),Publisher::set_litener(),Subscriber::set-listener((),Topic::set-liistener()),DataWriter::set _listener。每個實體類型的偵聽器接口及其回調在每個實體類型文檔中進行了解釋。當事件發生時,它由具有非空偵聽器的最低級別實體處理,並且在其StatusTask中啓用了相應的回調。高級偵聽器繼承自低級偵聽器,如下圖所示:
注意:
on_data_on_readers()回調在on_data_available()之前攔截消息。這意味着如果啓用了DomainParticipantListener,用戶應該考慮默認情況下偵聽器使用StatusMask::all()。由於保留了回調實體層次結構,在這種情況下將調用on_data_on_readers()。如果應用程序希望改用on_data_available(),則應禁用Statusask的相應位。
重要:
在創建實體時使用StatusMask::none()僅禁用DDS標準回調:
- on_sample_rejected()
- on_liveliness_changed()
- on_requested_deadline_missed()
- on_requested_incompatible_qos()
- on_data_available()
- on_subscription_matched()
- on_sample_lost()
- on_offered_incompatible_qos()
- on_offered_deadline_missed()
- on_liveliness_lost()
- on_publication_matched()
- on_inconsistent_topic()
- on_data_on_readers()
始終啓用特定於Fast DDS的任何回調:
- on_participant_discovery()
- on_ParticipantAuthentication()
- on_subscriber_discovery()
- on_publisher_discovery()
- on_type_discovery()
- on_type_dependencies_reply()
- on_type_information_received()
- on_unacknowledged_sample_removed()
警告: 只創建一個線程來偵聽每個實現的偵聽器,因此建議保持偵聽器函數的簡單性,將此類信息的處理留給適當的類。
警告:
不要在偵聽器成員函數的範圍內創建或刪除任何實體,因爲這可能會導致未定義的行爲。相反,建議使用Listener類作爲信息通道,並使用上層Entity類來封裝此類行爲。
3.1.1.2.4 Status
每個實體都與一組狀態對象相關聯,這些狀態對象的值表示該實體的通信狀態。這些狀態值的更改會觸發調用相應的Listener回調以異步通知應用程序。有關所有狀態對象的列表及其內容的描述,請參見狀態。在那裏,您還可以找到哪個狀態適用於哪個實體類型。
3.1.1.2.5 StatusCondition
每個實體都有一個StatusCondition,每當其啓用狀態更改時,都會通知它。StatusCondition提供實體和等待集之間的鏈接。有關詳細信息,請參閱“條件和等待集”一節。
3.1.1.2.6 啓用實體
所有實體都可以創建爲已啓用或未啓用。默認情況下,工廠被配置爲創建已啓用的實體,但可以對已啓用的工廠使用EntityFactoryQosPolicy進行更改。禁用的工廠創建禁用的實體,而不管其QoS如何。禁用實體的操作僅限於以下操作:
- Set/Get 實體的QoS策略
- Set/Get 實體監聽器
- Create/Delete 子實體
- 得到實體的狀態,即使他們沒有改變
- 查找操作
在這種狀態下調用的其他函數都會返回NOT_ENABLED.