【Nodelet】系列(一)——Nodelet介紹

目錄

一、為什么需要nodelet

如果有多個(gè)進(jìn)程需要使用包含大量數(shù)據(jù)(如圖像或點(diǎn)云)的消息,則將消息打包、發(fā)送,然后解包可能需要一些時(shí)間。

圖像和點(diǎn)云數(shù)據(jù)

Nodelets 旨在提供一種在單個(gè)機(jī)器上、單個(gè)進(jìn)程中運(yùn)行多個(gè)算法的方法,而不會(huì)在進(jìn)程內(nèi)傳遞消息時(shí)產(chǎn)生復(fù)制成本。roscpp中通過優(yōu)化可以在同一節(jié)點(diǎn)內(nèi)的發(fā)布和訂閱調(diào)用之間進(jìn)行零復(fù)制指針傳遞,可以直接傳遞指針,降低了拷貝內(nèi)存的操作和降低網(wǎng)絡(luò)流量。

如果兩個(gè)進(jìn)程在同一臺(tái)計(jì)算機(jī)上,則只發(fā)送指向該數(shù)據(jù)(如圖像或點(diǎn)云)的指針比通過 TCP 發(fā)送數(shù)據(jù)本身更快,Nodelet僅適用于同一臺(tái)計(jì)算機(jī)上的不同進(jìn)程,因?yàn)橐慌_(tái)計(jì)算機(jī)的指針對(duì)另一臺(tái)計(jì)算機(jī)沒有意義。

nodelets 不會(huì)使進(jìn)程更快,但它是一種從一個(gè)進(jìn)程到另一個(gè)進(jìn)程獲取信息的更快方法。一個(gè)好的經(jīng)驗(yàn)法則是始終使用node(因?yàn)樗鼈兏子谑褂们腋`活),除非遇到消息傳遞對(duì)于應(yīng)用程序來說太慢并導(dǎo)致問題的情況,那么才會(huì)考慮使用 nodelet。

二、nodelet如何實(shí)現(xiàn)多個(gè)節(jié)點(diǎn)通信

2.1 nodelet共享指針

ROS中不同節(jié)點(diǎn)以基于socket的發(fā)布/訂閱模式(Publish/Subscribe)進(jìn)行通訊時(shí),存在消息數(shù)據(jù)的復(fù)制,從而增大了通信延遲。

Nodelet采用共享指針(shared_ptr)技術(shù)來實(shí)現(xiàn)節(jié)點(diǎn)之間的數(shù)據(jù)共享。在Nodelet中,一個(gè)節(jié)點(diǎn)可以將某個(gè)數(shù)據(jù)結(jié)構(gòu)打包成一個(gè)共享指針,然后將這個(gè)共享指針傳遞給另一個(gè)節(jié)點(diǎn),另一個(gè)節(jié)點(diǎn)可以通過共享指針來訪問和修改這個(gè)數(shù)據(jù)結(jié)構(gòu),而不需要進(jìn)行數(shù)據(jù)復(fù)制。這樣,多個(gè)節(jié)點(diǎn)可以在同一份數(shù)據(jù)上進(jìn)行操作,從而避免了數(shù)據(jù)復(fù)制帶來的性能損失。

TCOROS與Nodelet

2.2 nodelet的消息類型

如果希望no-copy pub/sub工作,必須將ROS消息類型發(fā)布為shared_ptr共享指針類型,當(dāng)消息被發(fā)布為shared_ptr,roscpp可以跳過序列化/反序列化步驟(可能節(jié)省大量的處理和延遲)。

示例:

ros::Publisher pub = nh.advertise<std_msgs::String>("topic_name", 5);
std_msgs::StringPtr str(new std_msgs::String);
str->data = "hello world";
pub.publish(str);

其中str變量類型為std_msgs::StringPtr,但是publisher的模板類仍為std_msgs::String類型,在ROS中,發(fā)布話題的類型通常不是指針類型。

當(dāng)我們創(chuàng)建一個(gè) std_msgs::StringPtr 類型的消息并發(fā)布它時(shí),pub.publish()函數(shù)會(huì)自動(dòng)地處理指針,將其解引用并獲取實(shí)際的消息內(nèi)容。

publish函數(shù)能夠自動(dòng)處理指針,主要是因?yàn)樗且粋€(gè)模板函數(shù),可以根據(jù)提供的參數(shù)類型自動(dòng)地推導(dǎo)消息類型。在處理指針類型的消息時(shí),publish函數(shù)會(huì)自動(dòng)解引用指針并獲取實(shí)際的消息內(nèi)容。

查看ROS的publish.h文件可以看到Publisher類有一個(gè)重載的publish函數(shù),專門用于處理智能指針類型的消息,如下面代碼的第一個(gè)函數(shù)。這個(gè)重載的publish函數(shù)會(huì)自動(dòng)解引用智能指針,從而獲取實(shí)際的消息內(nèi)容。

template <typename M>
      void publish(const boost::shared_ptr<M>& message) const
    {// 其他代碼...
     // 自動(dòng)解引用指針并調(diào)用publish函數(shù)
      publish(boost::bind(serializeMessage<M>, boost::ref(*message)), m);
    }

template<typename M>
void Publisher::publish(const M& message) {
  // 其他代碼...

      publish(boost::bind(serializeMessage<M>, boost::ref(message)), m);
}

這意味著它可以接受實(shí)際的消息類型,也可以接受指向消息類型的智能指針。當(dāng)我們傳遞一個(gè)智能指針(如 boost::shared_ptr)時(shí),編譯器會(huì)自動(dòng)推導(dǎo)參數(shù)類型為智能指針類型,然后調(diào)用實(shí)現(xiàn)的 publish 函數(shù)。

注意,當(dāng)用這種方式發(fā)布,不可以修改發(fā)送后的消息,因?yàn)橹羔槙?huì)直接傳遞到用戶的任何進(jìn)程內(nèi)。

三、nodelet如何管理多個(gè)節(jié)點(diǎn)

3.1 ROS插件機(jī)制

ROS通過提供插件(pluginlib)的形式實(shí)現(xiàn)算法(算法類),作為插件動(dòng)態(tài)加載以打破構(gòu)建時(shí)間依賴性。而Nodelet通過動(dòng)態(tài)加載這些插件,將算法類動(dòng)態(tài)加載到同一個(gè)節(jié)點(diǎn)中,同時(shí)為這些類提供獨(dú)立的名稱空間,這樣盡管不同的類在同一個(gè)進(jìn)程中運(yùn)行,但從外部看,nodelet就像一個(gè)單獨(dú)的節(jié)點(diǎn)一樣。

3.2 nodelet中各個(gè)節(jié)點(diǎn)關(guān)系

下圖中/my_ros_node相機(jī)驅(qū)動(dòng)節(jié)點(diǎn),而/standalone_nodelet為nodelet的管理節(jié)點(diǎn),這兩個(gè)節(jié)點(diǎn)通過共享指針/standalone_nodelet/bond進(jìn)行通信,可以看到節(jié)點(diǎn)與該話題存在雙向箭頭連接,即代表是nodelet共享指針通信!

nodelet通信

/standalone_nodelet是管理節(jié)點(diǎn)名稱,作為nodelet整體,對(duì)外通過topic與其它普通節(jié)點(diǎn)進(jìn)行通信,如下圖中的其它節(jié)點(diǎn)通過訂閱/my_ros_node/image_raw/image_topic話題,可以接收到/my_ros_node節(jié)點(diǎn)發(fā)出的話題,但是rqt_graph命令中,仍然是從/standalone_nodelet節(jié)點(diǎn)節(jié)點(diǎn)訂閱!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容