2013-03-08 85 views
1

我正在嘗試創建最簡單的C#應用​​程序,該程序將允許我獲取選定DDS域中當前可用的主題。但我似乎無法讓它工作。在DDS中訂閱內置主題「DCPSTopic」

// Create the DDS Domain participant on domain ID 0 
DDS.DomainParticipant participant =       
      DDS.DomainParticipantFactory.get_instance().create_participant(
        0, 
        DDS.DomainParticipantFactory.PARTICIPANT_QOS_DEFAULT, 
        null, /* Listener */ 
        DDS.StatusMask.STATUS_MASK_NONE); 
DDS.Subscriber sub = participant.get_builtin_subscriber(); 
DDS.DataReader reader1 = sub.lookup_datareader("DCPSTopic"); 
DDS.TopicBuiltinTopicDataDataReader builtinReader1 = 
         (DDS.TopicBuiltinTopicDataDataReader)reader1; 
DDS.TopicBuiltinTopicDataSeq topicSeq = new DDS.TopicBuiltinTopicDataSeq(10) ; 
DDS.SampleInfoSeq infoSeq = new DDS.SampleInfoSeq(10); 
builtinReader1.read(topicSeq, 
        infoSeq, 
        10, 
        DDS.SampleStateKind.ANY_SAMPLE_STATE, 
        DDS.ViewStateKind.ANY_VIEW_STATE, 
        DDS.InstanceStateKind.ANY_INSTANCE_STATE); 

當運行上面的代碼,我得到的最後一行「Retcode_NoData」異常(builtinReader1.read(...))儘管出版商和用戶都在同一個域中運行,並且發佈(域0)。你知道我的代碼有什麼問題嗎?

順便說一句。我使用RTI Connext 5.0實現DDS。

問候 約翰

回答

1

與RTI Connext,該TopicBuiltinTopic不表現爲人們所預料的。退房C# API DDS::TopicBuiltinTopicData Class Reference的文檔:

注:DDS_TopicBuiltinTopicData內置的主題是爲了傳達有關發現的主題 信息。本主題的示例不是 傳播在電線上的單獨數據包中。而是將數據作爲其他內置主題 (DDS::PublicationBuiltinTopicDataDDS::SubscriptionBuiltinTopicData)所帶信息的一部分發送至 。因此TopicBuiltinTopicData DataReaders將不會收到任何數據。

基本上說:由於在Connext中實現發現的方式,在任何TopicBuiltinTopicData DataReaders中都不會看到任何數據。這就是你在你的代碼片段中觀察到的。

幸運的是,仍然有可能獲得有關巴士話題的信息。這必須通過PublicationBuiltinTopicData和SubscriptionBuiltinTopicData來實現。如果您查看C# API DDS::PublicationBuiltinTopicData Class Reference的文檔,可以看到數據包含字符串字段topic_nametype_name。此外,您可以獲取有關該類型結構的信息,但這是更高級的和特定於實現的。


如果您計劃實施閱讀出版物和訂閱內置主題的三種說法。首先,在硬編碼的名稱代替內置的主題,像你這樣"DCPSTopic"做,最好是參考相應TypeSupport屬性,如:

reader = sub.lookup_datareader(
      DDS.PublicationBuiltinTopicDataTypeSupport.PUBLICATION_TOPIC_NAME); 

然後,它是很好的瞭解,隨着Connext內置的DataReaders將不包含與內置訂閱服務器位於同一DomainParticipant的任何有關出版物或訂閱的樣本。換句話說,您只能看到其他參與者的實體,但不是您自己的實體。

最後,當你的代碼玩弄,我注意到,樣品的讀數,除非我更換了序列的構造函數調用如下沒有工作:在代替

DDS.SampleInfoSeq infoSeq = new DDS.SampleInfoSeq(); 

DDS.SampleInfoSeq infoSeq = new DDS.SampleInfoSeq(10); 

以及類似的數據序列。我不知道這是爲什麼,但它不應該有任何實際的影響。

+0

Reinier您好,感謝您的反饋!我已經實施了您的3條建議,並且現在也正在使用訂閱和發佈內置主題/數據讀取器。但我的應用程序仍然沒有給出任何反饋(除了「Retcode_NoData」例外)。我正在其他DDS應用程序運行的筆記本電腦上運行應用程序,所有這些應用程序都在域0上,但它們不會顯示在我的應用程序中。你有什麼其他的建議可能是錯的?再次感謝! John – Rauhe 2013-03-11 12:00:05

+0

當你在筆記本電腦上運行'rtiddsspy'工具時,你看到什麼嗎?它應該發現總線上的所有DataReader和DataWriters並打印它們的主題,以及所有更新(通過defult)。如果沒有顯示任何結果,那麼您的筆記本電腦的設置有問題。如果它確實顯示了結果,請查看此代碼片段(http://pastebin.com/awEHZTBv),看看它是否適合您?爲了進行調試,我將首先使用筆記本電腦,然後結合RTI的Shapes演示程序運行該代碼段。 – 2013-03-11 13:21:40

+0

我試着運行你的codesnippet而不是我的,你的工作就像它應該是:)內置的TopicReader沒有給出任何結果,但它可能(如你所說)從發佈者/訂閱者讀取主題。非常感謝您的幫助 ! – Rauhe 2013-03-11 14:45:22

1

雷尼爾是對的。 Connext DDS不會直接在TopicBuiltinTopicData中傳播主題;而是在PublicationBuitinTopicDataSubscriptionBuiltinTopicData間接進行。這是DDS規範允許的。

有關於如何使用內建主題的信息在此HOWTO標題爲Detect the presence of DomainParticipants, DataWriters and DataReaders in the DDS Domain。 HOWTO包含一些工作示例代碼。它使用Java而不是C#,但它應該很容易映射。那裏的示例一次只讀取一個Sample,因此您不需要處理序列sytax。

之所以必須使用:

DDS.SampleInfoSeq infoSeq = new DDS.SampleInfoSeq(); 

相反的:

DDS.SampleInfoSeq infoSeq = new DDS.SampleInfoSeq(10); 

是讀取/採取有根據兩種不同的行爲的API傳遞的序列是否是「空」 (即具有零分配/最大長度)或具有分配的長度。

如果序列爲空,這是您使用默認構造函數所獲得的結果,那麼讀/表現爲零拷貝API。這意味着序列中的實際元素與已存儲在中間件內的元素「借出」。出於這個原因,必須傳遞的序列必須是「空」序列,以便中間件知道將內容替換爲對內部元素的引用是可以的。在訪問元素之後,您必須將「借用元素」返回到調用DataReader::return_loan操作的中間件。

如果序列不爲空。然後DDS將假定元素已預先分配,並會嘗試將數據複製到您傳遞的元素中。您顯示的代碼的問題是:

DDS.SampleInfoSeq infoSeq = new DDS.SampleInfoSeq(10); 

只分配序列本身。但不是元素。所以當它嘗試複製時,讀/寫呼叫將失敗。如果你想使用這種非零拷貝API,你必須遵循與分配/分配每一個元素,即呼叫:

for (int i=0; i< 10; i++) { 
    infoSeq.set_at(i, new DDS.SampleInfo()); 
} 

而且同樣適用於數據序列爲好。 如果你這樣做,你不必使用DataReader::return_loan操作。但是會有額外的副本,所以效率較低。

您可以在此HOWTO標題爲Howto use OMG DDS Sequences in C++中找到有關如何使用DDS序列的更多信息。它是用C++編寫的例子,但是這些原則適用於所有的語言。

問候, 赫拉爾

+0

謝謝你的澄清! – Rauhe 2013-03-12 12:55:24