0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

ROS機(jī)器人操作系統(tǒng)的實(shí)現(xiàn)原理(下)

jf_78858299 ? 來(lái)源:古月居 ? 作者:robinvista ? 2023-05-19 17:42 ? 次閱讀

注釋表明Stream是個(gè)基類(lèi),輸入輸出流IStream和OStream都繼承自它。

Stream的成員變量data_是個(gè)指針,指向序列化的字節(jié)流開(kāi)始的位置,它的類(lèi)型是uint8_t。

在Ubuntu系統(tǒng)中,uint8_t的定義是typedef unsigned char uint8_t;

所以u(píng)int8_t就是一個(gè)字節(jié),可以用size_of()函數(shù)檢驗(yàn)。data_指向的空間就是保存字節(jié)流的。

輸出流類(lèi)OStream用來(lái)序列化一個(gè)對(duì)象,它引用了serialize函數(shù),如下。

struct OStream : public Stream
{
  static const StreamType stream_type = stream_types::Output;
  OStream(uint8_t* data, uint32_t count) : Stream(data, count) {}
  /* Serialize an item to this output stream*/
  template<typename T>
  ROS_FORCE_INLINE void next(const T& t)
{
    serialize(*this, t);
  }
  template<typename T>
  ROS_FORCE_INLINE OStream& operator<<(const T& t)
  {
    serialize(*this, t);
    return *this;
  }
};

輸入流類(lèi)IStream用來(lái)反序列化一個(gè)字節(jié)流,它引用了deserialize函數(shù),如下。

struct ROSCPP_SERIALIZATION_DECL IStream : public Stream
{
  static const StreamType stream_type = stream_types::Input;
  IStream(uint8_t* data, uint32_t count) : Stream(data, count) {}
  /* Deserialize an item from this input stream */
  template<typename T>
  ROS_FORCE_INLINE void next(T& t)
{
    deserialize(*this, t);
  }
  template<typename T>
  ROS_FORCE_INLINE IStream& operator>>(T& t)
  {
    deserialize(*this, t);
    return *this;
  }
};

自然,serialize函數(shù)和deserialize函數(shù)就是改變數(shù)據(jù)形式的地方,它們的定義在比較靠前的地方。它們都接收兩個(gè)模板,都是內(nèi)聯(lián)函數(shù),然后里面沒(méi)什么東西,只是又調(diào)用了Serializer類(lèi)的成員函數(shù)write和read。所以,serialize和deserialize函數(shù)就是個(gè)二道販子。

// Serialize an object.  Stream here should normally be a ros::serialization::OStream
template<typename T, typename Stream>
inline void serialize(Stream& stream, const T& t)
{
  Serializer

所以,我們來(lái)分析Serializer類(lèi),如下。我們發(fā)現(xiàn),write和read函數(shù)又調(diào)用了類(lèi)型里的serialize函數(shù)和deserialize函數(shù)。

頭別暈,這里的serialize和deserialize函數(shù)跟上面的同名函數(shù)不是一回事。

注釋中說(shuō):“Specializing the Serializer class is the only thing you need to do to get the ROS serialization system to work with a type”(要想讓ROS的序列化功能適用于其它的某個(gè)類(lèi)型,你唯一需要做的就是特化這個(gè)Serializer類(lèi))。

這就涉及到的另一個(gè)知識(shí)點(diǎn)——模板特化(template specialization)。

template<typename T> struct Serializer
{
  // Write an object to the stream.  Normally the stream passed in here will be a ros::serialization::OStream
  template<typename Stream>
  inline static void write(Stream& stream, typename boost::call_traits
{
    t.serialize(stream.getData(), 0);
  }
   // Read an object from the stream.  Normally the stream passed in here will be a ros::serialization::IStream
  template<typename Stream>
  inline static void read(Stream& stream, typename boost::call_traits
{
    t.deserialize(stream.getData());
  }
  // Determine the serialized length of an object.
  inline static uint32_t serializedLength(typename boost::call_traits
{
    return t.serializationLength();
  }
};

接著又定義了一個(gè)帶參數(shù)的宏函數(shù)ROS_CREATE_SIMPLE_SERIALIZER(Type),然后把這個(gè)宏作用到了ROS中的10種基本數(shù)據(jù)類(lèi)型,分別是:uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double。

說(shuō)明這10種數(shù)據(jù)類(lèi)型的處理方式都是類(lèi)似的??吹竭@里大家應(yīng)該明白了,write和read函數(shù)都使用了memcpy函數(shù)進(jìn)行數(shù)據(jù)的移動(dòng)。

注意宏定義中的template<>語(yǔ)句,這正是模板特化的標(biāo)志,關(guān)鍵詞template后面跟一對(duì)尖括號(hào)。

關(guān)于模板特化可以看這里。

#define ROS_CREATE_SIMPLE_SERIALIZER(Type) \\
  template<> struct Serializer \\
  { \\
    template

對(duì)于其它類(lèi)型的數(shù)據(jù),例如bool、std::string、std::vector、ros::Time、ros::Duration、boost::array等等,它們各自的處理方式有細(xì)微的不同,所以不再用上面的宏函數(shù),而是用模板特化的方式每種單獨(dú)定義,這也是為什么serialization.h這個(gè)文件這么冗長(zhǎng)。

對(duì)于int、double這種單個(gè)元素的數(shù)據(jù),直接用上面特化的Serializer類(lèi)中的memcpy函數(shù)實(shí)現(xiàn)序列化。

對(duì)于vector、array這種多個(gè)元素的數(shù)據(jù)類(lèi)型怎么辦呢?方法是分成幾種情況,對(duì)于固定長(zhǎng)度簡(jiǎn)單類(lèi)型的(fixed-size simple types),還是用各自特化的Serializer類(lèi)中的memcpy函數(shù)實(shí)現(xiàn),沒(méi)啥太大區(qū)別。

對(duì)于固定但是類(lèi)型不簡(jiǎn)單的(fixed-size non-simple types)或者既不固定也不簡(jiǎn)單的(non-fixed-size, non-simple types)或者固定但是不簡(jiǎn)單的(fixed-size, non-simple types),用for循環(huán)遍歷,一個(gè)元素一個(gè)元素的單獨(dú)處理。

那怎么判斷一個(gè)數(shù)據(jù)是不是固定是不是簡(jiǎn)單呢?這是在roscpp_traits文件夾中的message_traits.h完成的。

其中采用了萃取Type Traits,這是相對(duì)高級(jí)一點(diǎn)的編程技巧了,筆者也不太懂。

對(duì)序列化的介紹暫時(shí)就到這里了,有一些細(xì)節(jié)還沒(méi)講,等筆者看懂了再補(bǔ)。

2、消息訂閱發(fā)布

2.1ROS的本質(zhì)

如果問(wèn)ROS的本質(zhì)是什么,或者用一句話概括ROS的核心功能。那么,筆者認(rèn)為ROS就是個(gè)通信庫(kù),讓不同的程序節(jié)點(diǎn)能夠相互對(duì)話。

很多文章和書(shū)籍在介紹ROS是什么的時(shí)候,經(jīng)常使用“ROS是一個(gè)通信框架”這種描述。

但是筆者認(rèn)為這種描述并不是太合適?!翱蚣堋笔莻€(gè)對(duì)初學(xué)者非常不友好的抽象詞匯,用一個(gè)更抽象難懂的概念去解釋一個(gè)本來(lái)就不清楚的概念,對(duì)初學(xué)者起不到任何幫助。

而且筆者嚴(yán)重懷疑絕大多數(shù)作者能對(duì)機(jī)器人的本質(zhì)或者軟件框架能有什么太深的理解,他們的見(jiàn)解不會(huì)比你我深刻多少。

既然提到本質(zhì),那我們就深入到最基本的問(wèn)題。

在接觸無(wú)窮的細(xì)節(jié)之前,我們不妨先做一個(gè)哲學(xué)層面的思考。

那就是,為什么ROS要解決通信問(wèn)題?

機(jī)器人涉及的東西千千萬(wàn)萬(wàn),機(jī)械、電子、軟件、人工智能無(wú)所不包,為什么底層的設(shè)計(jì)是一套用來(lái)通信的程序而不是別的東西。

到目前為止,我還沒(méi)有看到有人討論過(guò)這個(gè)問(wèn)題。這要回到機(jī)器人或者智能的本質(zhì)。

當(dāng)我們?cè)谡務(wù)摍C(jī)器人的時(shí)候,最首要的問(wèn)題不是硬件設(shè)計(jì),而是對(duì)信息的處理。一個(gè)機(jī)器人需要哪些信息,信息從何而來(lái),如何傳遞,又被誰(shuí)使用,這些才是最重要的問(wèn)題。

人類(lèi)飛不鳥(niǎo),游不過(guò)魚(yú),跑不過(guò)馬,力不如牛,為什么卻自稱(chēng)萬(wàn)物之靈呢。

因?yàn)槿擞写竽X,而且人類(lèi)大腦處理的信息更多更復(fù)雜。

拋開(kāi)物質(zhì),從信息的角度看,人與動(dòng)物、與機(jī)器人存在很多相似的地方。

機(jī)器人由許多功能模塊組成,它們之間需要協(xié)作才能形成一個(gè)有用的整體,機(jī)器人與機(jī)器人之間也需要協(xié)作才能形成一個(gè)有用的系統(tǒng),要協(xié)作就離不開(kāi)通信。

需要什么樣的信息以及信息從何而來(lái)不是ROS首先關(guān)心的,因?yàn)檫@取決于機(jī)器人的應(yīng)用場(chǎng)景。

因此,ROS首先要解決的是通信的問(wèn)題,即如何建立通信、用什么方式通信、通信的格式是什么等等一系列具體問(wèn)題。

帶著這些問(wèn)題,我們看看ROS是如何設(shè)計(jì)的。

2.2客戶(hù)端庫(kù)

實(shí)現(xiàn)通信的代碼在ros_comm包中,如下。

其中clients文件夾一共有127個(gè)文件,看來(lái)是最大的包了。

現(xiàn)在我們來(lái)到了ROS最核心的地帶。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 機(jī)器人
    +關(guān)注

    關(guān)注

    210

    文章

    28003

    瀏覽量

    205567
  • 操作系統(tǒng)
    +關(guān)注

    關(guān)注

    37

    文章

    6617

    瀏覽量

    123037
  • ROS
    ROS
    +關(guān)注

    關(guān)注

    1

    文章

    276

    瀏覽量

    16921
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    ROS機(jī)器人開(kāi)發(fā)更便捷,基于RK3568J+Debian系統(tǒng)發(fā)布!

    本帖最后由 Tronlong創(chuàng)龍科技 于 2024-7-19 17:18 編輯 ROS系統(tǒng)是什么 ROS(Robot Operating System)是一個(gè)適用于機(jī)器人的開(kāi)源的
    發(fā)表于 07-09 11:38

    【IntoRobot Atom試用體驗(yàn)】解決Atom搭建機(jī)器人操作系統(tǒng)問(wèn)題(二)

    根據(jù)上一篇文章解決Atom搭建機(jī)器人操作系統(tǒng)問(wèn)題(一),在做庫(kù)移植的時(shí)候會(huì)遇到以下問(wèn)題。。。。/main.cpp:1:17: fatal error: ros.h: No such file
    發(fā)表于 04-07 22:00

    機(jī)器人操作系統(tǒng)淺析

    機(jī)器人操作系統(tǒng)淺析
    發(fā)表于 09-28 11:43

    請(qǐng)問(wèn)能分享ROS機(jī)器人操作系統(tǒng)的一些資料嗎?

    菜鳥(niǎo)想要學(xué)習(xí)ROS機(jī)器人操作系統(tǒng),但是沒(méi)能找到系統(tǒng)的資料,請(qǐng)問(wèn)有哪位大神研究過(guò),可以分享一些資料嗎?跪謝了?。。。。。。。?!
    發(fā)表于 02-19 23:14

    創(chuàng)龍TL5728-EasyEVM-A4開(kāi)發(fā)板如何移植ros機(jī)器人操作系統(tǒng)?

    創(chuàng)龍TL5728-EasyEVM-A4開(kāi)發(fā)板如何移植ros機(jī)器人操作系統(tǒng)?
    發(fā)表于 01-02 09:32

    ROS 2 Crystal Clemmys版機(jī)器人操作系統(tǒng)補(bǔ)充說(shuō)明

    ROS 2 Crystal Clemmys版機(jī)器人操作系統(tǒng)補(bǔ)充說(shuō)明
    發(fā)表于 06-10 11:29

    ROS RIKIBOT基礎(chǔ)--使用系列 第一章節(jié)】ROS機(jī)器人硬件系統(tǒng) 精選資料分享

    主控制器ROS控制器采用樹(shù)莓派4B或者Jetson Nano,運(yùn)行運(yùn)行Ubuntu Mate18.04或Ubuntu18.04系統(tǒng),具體型號(hào)有差異。系統(tǒng)安裝有ROS
    發(fā)表于 07-30 06:59

    ROS機(jī)器人開(kāi)發(fā)更便捷,基于RK3568J+Debian系統(tǒng)發(fā)布!

    ROS系統(tǒng)是什么 ROS(Robot Operating System)是一個(gè)適用于機(jī)器人的開(kāi)源的元操作系統(tǒng)。它提供了
    發(fā)表于 11-30 16:01

    ROS是什么?機(jī)器人操作系統(tǒng)ROS的介紹

    ROS 是 Robot Operating System 的縮寫(xiě),原本是斯坦福大學(xué)的一個(gè)機(jī)器人項(xiàng)目,后 來(lái)由 WillowGarage 公司發(fā)展,目前由 OSRF(Open Source
    發(fā)表于 09-13 17:23 ?14次下載
    <b class='flag-5'>ROS</b>是什么?<b class='flag-5'>機(jī)器人</b><b class='flag-5'>操作系統(tǒng)</b><b class='flag-5'>ROS</b>的介紹

    ROS的含義與機(jī)器人操作系統(tǒng)ROS的介紹

    Operating System 的縮寫(xiě),原本是斯坦福大學(xué)的一個(gè)機(jī)器人項(xiàng)目,后來(lái)由 WillowGarage 公司發(fā)展,目前由 OSRF(Open Source Robotics Foundation,Inc)公司維護(hù)的開(kāi)源項(xiàng)目。 1、首先是一個(gè)操作系統(tǒng) 根據(jù) wiki
    發(fā)表于 09-26 14:08 ?12次下載

    機(jī)器人操作系統(tǒng)ROS)是一種用于機(jī)器人開(kāi)發(fā)的元操作系統(tǒng)

    拋開(kāi)它的名字,ROS并不是一個(gè)真正的操作系統(tǒng)。相反,它是一個(gè)框架和服務(wù)的集合,這些框架和服務(wù)提供了類(lèi)似操作系統(tǒng)的功能,運(yùn)行在由機(jī)器人硬件支撐的異構(gòu)計(jì)算機(jī)集群之上。
    的頭像 發(fā)表于 10-12 16:53 ?7007次閱讀

    機(jī)器人操作系統(tǒng)ROS詳細(xì)介紹

    機(jī)器人操作系統(tǒng)ROS詳細(xì)介紹 ROS機(jī)器人 操作系統(tǒng),RobotOperatingSyste
    發(fā)表于 11-18 18:09 ?2313次閱讀

    ROS機(jī)器人操作系統(tǒng)實(shí)現(xiàn)原理(上)

    本文介紹ROS機(jī)器人操作系統(tǒng)(Robot Operating System)的實(shí)現(xiàn)原理,從最底層分析ROS代碼是如何
    的頭像 發(fā)表于 05-19 17:41 ?943次閱讀
    <b class='flag-5'>ROS</b><b class='flag-5'>機(jī)器人</b><b class='flag-5'>操作系統(tǒng)</b>的<b class='flag-5'>實(shí)現(xiàn)</b>原理(上)

    ROS機(jī)器人操作系統(tǒng)

    可能很多初學(xué)者聽(tīng)到機(jī)器人操作系統(tǒng),就被“操作系統(tǒng)”幾個(gè)字嚇住了。其實(shí)簡(jiǎn)單點(diǎn)說(shuō),**ROS就是一個(gè)分布式的通信框架,幫助程序進(jìn)程之間更方便地通信。
    的頭像 發(fā)表于 05-19 17:46 ?2081次閱讀
    <b class='flag-5'>ROS</b><b class='flag-5'>機(jī)器人</b><b class='flag-5'>操作系統(tǒng)</b>

    一個(gè)機(jī)器人操作系統(tǒng)(ROS)節(jié)點(diǎn)系統(tǒng)

    電子發(fā)燒友網(wǎng)站提供《一個(gè)機(jī)器人操作系統(tǒng)(ROS)節(jié)點(diǎn)系統(tǒng).zip》資料免費(fèi)下載
    發(fā)表于 07-06 10:49 ?0次下載
    一個(gè)<b class='flag-5'>機(jī)器人</b><b class='flag-5'>操作系統(tǒng)</b>(<b class='flag-5'>ROS</b>)節(jié)點(diǎn)<b class='flag-5'>系統(tǒng)</b>