国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

ROS通信機(jī)制之話題(Topics)的發(fā)布與訂閱以及自定義消息的實(shí)現(xiàn)

這篇具有很好參考價(jià)值的文章主要介紹了ROS通信機(jī)制之話題(Topics)的發(fā)布與訂閱以及自定義消息的實(shí)現(xiàn)。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

我們知道在ROS中,由很多互不相干的節(jié)點(diǎn)組成了一個(gè)復(fù)雜的系統(tǒng),單個(gè)的節(jié)點(diǎn)看起來是沒起什么作用,但是節(jié)點(diǎn)之間進(jìn)行了通信之后,相互之間能夠交互信息和數(shù)據(jù)的時(shí)候,就變得很有意思了。
節(jié)點(diǎn)之間進(jìn)行通信的一個(gè)常用方法就是使用話題(topic),話題表示的是一個(gè)定義了類型消息流,比方說,攝像機(jī)產(chǎn)生的數(shù)據(jù)可能就會被發(fā)送到一個(gè)叫做image的話題上,類型是Image的圖片類型。

1、話題概述

話題是一種通過發(fā)布(publish)訂閱(subscribe)進(jìn)行通信的機(jī)制,這在分布式系統(tǒng)中是一種很常見的數(shù)據(jù)交換方式,節(jié)點(diǎn)在發(fā)送數(shù)據(jù)到話題上之前,需要先聲明(advertise)話題名和消息類型,然后與roscore建立一個(gè)連接,roscore將共享它的訂閱者與分享者列表,接著就可以發(fā)布數(shù)據(jù)到這個(gè)話題上了。對于想要從話題上接收消息的節(jié)點(diǎn)來說,需要通過向roscore發(fā)出請求來訂閱這個(gè)話題,訂閱之后,該話題上所有的消息都會被轉(zhuǎn)發(fā)到這個(gè)請求的節(jié)點(diǎn)上,這樣發(fā)布者跟訂閱者就建立起了直接的連接。
它們之間的連接在 Ubuntu18.04版本安裝ROS及出現(xiàn)錯(cuò)誤的處理方法 這篇文章里面有更詳細(xì)地講解,有興趣的可以去了解下。
需要注意的是,同一個(gè)話題上的所有消息必須是同一類型的。另外話題的名字最好是能夠體現(xiàn)發(fā)送的是什么消息,比方說,在PR2機(jī)器人上面 /wide_stereo/right/image_color 的這個(gè)話題,可以直觀的了解到,發(fā)送的右邊相機(jī)的彩色圖像數(shù)據(jù)。

2、話題聲明

2.1、準(zhǔn)備工作

在聲明話題之前,需要先有一個(gè)工作區(qū),對于初次接觸的朋友,更多初始化工作區(qū)與包的詳細(xì)操作,可以查閱:ROS新建工作區(qū)(workspace)與包(package)編譯的實(shí)踐(C++示例)

我們創(chuàng)建一個(gè)test

catkin_create_pkg test rospy

接著在src目錄里面新建一個(gè)topic_publisher.py文件,代碼如下:

import rospy
from std_msgs.msg import Int32 # ROS標(biāo)準(zhǔn)消息包

rospy.init_node('topic_publisher') # 初始化節(jié)點(diǎn)
pub = rospy.Publisher('counter',Int32) # 發(fā)布前先聲明話題名稱與消息類型
rate = rospy.Rate(2) # 速率(Hz)
count = 0
while not rospy.is_shutdown():
    pub.publish(count)
    count += 1
    rate.sleep()

代碼很好理解,初始化節(jié)點(diǎn)和聲明話題,然后就是在rospy沒有關(guān)閉前,每秒鐘發(fā)布2次數(shù)據(jù),其中rate.sleep()就是休息指定頻率的間隔時(shí)間。
由于我們需要運(yùn)行這個(gè)文件,所以需要能夠執(zhí)行的權(quán)限

chmod u+x topic_publisher.py


查看下文件,可以看到有了可執(zhí)行權(quán)限(-rwxrw-r--):

ls -l topic_publisher.py

我們從from std_msgs.msg import Int32可以知道,有了一個(gè)標(biāo)準(zhǔn)消息包std_msgs,所以我們需要告訴ROS的構(gòu)建系統(tǒng),在package.xml文件里面添加依賴項(xiàng)(dependency):

cd ~/catkin_ws/src/test
gpedit package.xml
<depend package="std_msgs" />

添加了依賴項(xiàng)之后,來到工作區(qū)根目錄進(jìn)行編譯:?

cd ~/catkin_ws
catkin_make

這樣就將test包以及話題發(fā)布的Python文件構(gòu)建好了。

2.2、發(fā)布話題

前面有介紹這個(gè)rostopic話題命令的使用,在使用命令前,先啟動節(jié)點(diǎn)管理器roscore,直接輸入roscore命令回車即可
重新開一個(gè)終端,運(yùn)行這個(gè)節(jié)點(diǎn)

rosrun test topic_publisher.py

出現(xiàn)錯(cuò)誤:

import-im6.q16: not authorized `rospy' @ error/constitute.c/WriteImage/1037.
from: can't read /var/mail/std_msgs.msg

/home/yahboom/catkin_ws/src/test/src/topic_publisher.py: line 4: syntax error near unexpected token `'topic_publisher''
/home/yahboom/catkin_ws/src/test/src/topic_publisher.py: line 4: `rospy.init_node('topic_publisher')'

看起來上面Python的代碼有誤,是沒有被授權(quán)的意思,實(shí)質(zhì)是沒有指定解釋器,這里需要告知ROS系統(tǒng),這是一個(gè)Python文件

cd ~/catkin_ws/src/test/src
gedit topic_publisher.py

在代碼最上面添加:#!/usr/bin/env python
然后再次運(yùn)行命令即可

rosrun test topic_publisher.py

我們來看下rostopic在測試和維護(hù)當(dāng)中會經(jīng)常使用到的命令的用法。

2.2.1、rostopic list

再開一個(gè)終端,輸入命令:rostopic list,可以看到多出了一個(gè)counter話題

/counter
/rosout
/rosout_agg

查看話題上面發(fā)布的消息:rostopic echo counter -n 5

data: 527
---
data: 528
---
data: 529
---
data: 530
---
data: 531

如果不加-n 5就是一直打印下去,直到按下Ctrl+C終止

2.2.2、rostopic hz

檢驗(yàn)它是否按照我們期望的速率來發(fā)布消息: rostopic hz counter

subscribed to [/counter]
average rate: 2.003
?? ?min: 0.499s max: 0.499s std dev: 0.00000s window: 2
average rate: 1.997
?? ?min: 0.499s max: 0.502s std dev: 0.00098s window: 4
average rate: 2.000
?? ?min: 0.498s max: 0.502s std dev: 0.00140s window: 6
average rate: 2.000
?? ?min: 0.498s max: 0.502s std dev: 0.00118s window: 8

2.2.3、rostopic info

查看已聲明的話題:rostopic info counter

Type: std_msgs/Int32

Publishers:?
?* /topic_publisher (http://YAB:45599/)

Subscribers: None

這表明counter話題承載的類型是std_msgs/Int32,并且由topic_publisher聲明,運(yùn)行在YAB主機(jī)上,并且通過TCP端口45599來通信,Subscribers: None表示當(dāng)前還沒有訂閱者。

2.2.4、rostopic find

通過類型查詢所有話題:rostopic find std_msgs/Int32

/counter

類型需要給出包名(std_msgs)/消息類型(Int32)

更多rostopic命令的用法,可以查看幫助:rostopic -h

rostopic is a command-line tool for printing information about ROS Topics.

Commands:
?? ?rostopic bw?? ?display bandwidth used by topic 顯示按話題使用的帶寬
?? ?rostopic delay?? ?display delay of topic from timestamp in header 顯示標(biāo)題中時(shí)間戳的話題延遲
?? ?rostopic echo?? ?print messages to screen 將消息打印到屏幕
?? ?rostopic find?? ?find topics by type 按類型查找話題
?? ?rostopic hz?? ?display publishing rate of topic 顯示話題的發(fā)布頻率
?? ?rostopic info?? ?print information about active topic 打印有關(guān)活動話題的信息
?? ?rostopic list?? ?list active topics 列出活動話題
?? ?rostopic pub?? ?publish data to topic 向話題發(fā)布數(shù)據(jù)
?? ?rostopic type?? ?print topic or field type 打印話題或字段類型

Type rostopic <command> -h for more detailed usage, e.g. 'rostopic echo -h'

3、訂閱話題

有了發(fā)布話題之后,現(xiàn)在來寫一個(gè)訂閱的話題,topic_subscriber.py代碼如下:

#!/usr/bin/env python
import rospy
from std_msgs.msg import Int32 # ROS標(biāo)準(zhǔn)消息包

# 定義個(gè)回調(diào)函數(shù)
def callback(msg):
    print(msg.data)

rospy.init_node('topic_subscriber') # 初始化節(jié)點(diǎn)
pub = rospy.Subscriber('counter',Int32,callback) # 多一個(gè)回調(diào)函數(shù)
rospy.spin()

代碼可以看到,大同小異,關(guān)鍵區(qū)別在于訂閱的代碼使用了回調(diào)函數(shù),因?yàn)?strong>ROS是一個(gè)事件驅(qū)動的系統(tǒng),所以在ROS中將會看到大量使用回調(diào)函數(shù)。這里的訂閱,只要每次有消息來時(shí),就會調(diào)用相應(yīng)的回調(diào)函數(shù),并使用接收到的消息作為它的參數(shù)。這里使用rospy.spin()將程序的運(yùn)行交給ROS,避免使用上面發(fā)布話題中的while循環(huán)的一種捷徑,ROS并不是必須要接管程序的主線程。

同樣的,這個(gè)文件因?yàn)橐?zhí)行它,所以添加一個(gè)可執(zhí)行權(quán)限:chmod u+x topic_subscriber.py

rosrun test topic_subscriber.py
850
851
852
853
854
855
...

可以正常的接收到發(fā)布者發(fā)布的消息。然后我們使用可視化工具:rqt_graph來看下它們之間的關(guān)系,如下圖:

ROS通信機(jī)制之話題(Topics)的發(fā)布與訂閱以及自定義消息的實(shí)現(xiàn),機(jī)器人操作系統(tǒng)(ROS),rospy.Publisher,Subscriber,rqt_graph,rostopic,catkin_make,package.xml,CMakeLists.txt

可以看到發(fā)布者(/topic_publisher)通過話題(/counter)將消息傳給訂閱者(/topic_subscriber)

也可以使用命令行進(jìn)行消息發(fā)布:rostopic pub counter std_msgs/Int32 9999999
這樣就插播一條值為9999999的消息,傳給了訂閱者。

現(xiàn)在我們來看下話題的狀態(tài)信息:rostopic info counter

Type: std_msgs/Int32

Publishers:?
?* /topic_publisher (http://YAB:34725/)
?* /rostopic_3918_1692005474115 (http://YAB:45641/)

Subscribers:?
?* /topic_subscriber (http://YAB:42075/)

可以看到這里出現(xiàn)兩個(gè)發(fā)布者,其中一個(gè)就是命令行的,也出現(xiàn)了一個(gè)訂閱者,恩,沒有問題!

4、鎖存話題

在ROS中,消息是短暫的,意味著訂閱可能存在丟失消息的問題,當(dāng)然上面這個(gè)例子發(fā)送頻率比較高,可能沒什么影響,因?yàn)轳R上有新的消息被發(fā)送過來,不過對于有些場景,頻繁發(fā)送消息也不是一個(gè)好主意。
比方說,一個(gè)節(jié)點(diǎn)通過map話題發(fā)送地圖(數(shù)據(jù)類型:nav_msgs/OccupancyGrid),一般來說地圖在一段時(shí)間內(nèi)是不會發(fā)生改變,并且只會在節(jié)點(diǎn)加載完地圖之后發(fā)送一次,如果另外一個(gè)節(jié)點(diǎn)需要這個(gè)地圖就永遠(yuǎn)都無法獲取到了。
因?yàn)榈貓D通常很大,我們也不想經(jīng)常發(fā)送,解決辦法可以將頻率調(diào)低,不過這里的頻率應(yīng)該設(shè)置多大,也是一個(gè)技巧性的問題。
所以這里提供了一個(gè)不錯(cuò)的解決方案,使用鎖存,也就是將話題標(biāo)記為鎖存的時(shí)候,訂閱者在完成訂閱之后將會自動獲取話題上最后一條消息。代碼很簡單,添加一個(gè)參數(shù)即可:?

pub = rospy.Publisher('counter',Int32,latch=True)

在低版本上的參數(shù)是latched,所以在新的版本上就會報(bào)下面這樣的錯(cuò)誤:?

?Traceback (most recent call last):
? File "/home/yahboom/catkin_ws/src/test/src/topic_one.py", line 6, in <module>
? ? pub = rospy.Publisher('counter',Int32,latched=True)
TypeError: __init__() got an unexpected keyword argument 'latched'

需要將latched更改成latch。?

5、自定義消息類型

ROS有豐富的內(nèi)置消息類型,比如上面的std_msgs包定義了一些基本的類型,這些類型數(shù)據(jù)構(gòu)成的定長或變長數(shù)組在Python中經(jīng)過底層的通信反序列化處理,得到元組(tuple)并且可以設(shè)置成元組或列表(list)。

5.1、基本消息類型

ROS中C++與Python的基本消息類型,以及如何序列化,表格如下:

ROS消息類型 序列化結(jié)果 C++類型 C++類型 備注
bool Unsigned 8-bit integer uint8_t bool
int8 Signed 8-bit integer int8_t int
uint8 Unsigned 8-bit integer uint8_t uint8_t uint8[]在Python中是string表示
int16 Signed 16-bit integer int16_t int
uint16 Unsigned 16-bit integer uint16_t int
int32 Signed 32-bit integer int32_t int
uint32 Unsigned 32-bit integer uint32_t int
int64 Signed 64-bit integer int64_t long
uint64 Unsigned 64-bit integer uint64_t long
float32 32-bit IEEE float float float
float64 64-bit IEEE float double float
string ASCII string std::string string ROS不支持Unicode,請使用UTF-8
time secs/nsecs unsigned 32-bit ints ros::Time rospy.Time duration

可以看到C++比Python有更多的原生數(shù)據(jù)類型,需要注意的是:C++節(jié)點(diǎn)和Python節(jié)點(diǎn)之間交換數(shù)據(jù)的時(shí)候,需要注意一些取值范圍的問題,比如說,C++中的Uint8表示無符號整數(shù),當(dāng)Python中的小于0或大于255的數(shù)值傳過來時(shí),就解釋成一個(gè)8位無符號整數(shù),這就會導(dǎo)致一些無法預(yù)測的bug,所以說在Python中使用范圍受限的ROS類型時(shí)一定要小心。
有的時(shí)候,這些內(nèi)置消息類型不夠用,我們需要自己定義一些消息,這些自定義的數(shù)據(jù)類型在ROS同樣是“一等公民”,跟內(nèi)置消息數(shù)據(jù)類型并無差別對待。

5.2、定義新消息

在ROS中自定義消息,是用ROS包中的msg目錄中的消息定義文件來說明,然后catkin_make編譯成與語言有關(guān)的實(shí)現(xiàn)版本,這樣就可以在代碼中使用自定義類型了,先來看一個(gè)定義復(fù)數(shù)的一個(gè)例子,看下具體是怎么操作的:

5.2.1、msg文件

消息文件的定義很簡單直觀,類型 名稱

cd ~/catkin_ws/src/test
mkdir msg
cd msg
gedit Complex.msg

定義實(shí)部和虛部,內(nèi)容如下:

float32 real
float32 imaginary

5.2.2、修改package.xml

為了讓ROS生成語言相關(guān)的消息代碼,我們需要告知構(gòu)建系統(tǒng)新消息的定義,所以需要對package.xmlCMakeLists.txt文件進(jìn)行修改。
編輯package.xml文件

cd ~/catkin_ws/src/test
gedit package.xml

添加以下兩個(gè)節(jié)點(diǎn):

<build_depend>message_generation</build_depend>
<run_depend>message_runtime</run_depend>

后面編譯的時(shí)候如果出錯(cuò):

CMake Error at /opt/ros/melodic/share/catkin/cmake/catkin_package.cmake:224 (message):
? catkin_package() DEPENDS on the catkin package 'message_runtime' which must
? therefore be listed as a run dependency in the package.xml

屬于版本問題,將節(jié)點(diǎn)名稱<run_depend>修改為<exec_depend>即可

5.2.3、修改CMakeLists.txt

接著編輯CMakeLists.txt文件:gedit CMakeLists.txt

添加message_generation,讓catkin能夠找到message_generation包:

?find_package(catkin REQUIRED COMPONENTS rospy std_msgs message_generation)

運(yùn)行時(shí)使用消息:

catkin_package(CATKIN_DEPENDS message_runtime)

告訴catkin我們想要編譯它們:

add_message_files(FILES Complex.msg)

以及將下面這個(gè)注釋去掉:

generate_messages(
? ?DEPENDENCIES
? ?std_msgs
?)

5.2.4、編譯

定義好了之后,catkin就知道了如何編譯了,接下來就回到工作區(qū)根目錄進(jìn)行編譯

cd ~/catkin_ws
catkin_make

編譯成功,沒有問題。我們也可以來看下這個(gè)消息編譯后的代碼,當(dāng)然文件所在路徑,不同點(diǎn)取決于你的Python版本:

cd ~/catkin_ws/devel/lib/python2.7/dist-packages/test/msg
cat _Complex.py

代碼如下:

# This Python file uses the following encoding: utf-8
"""autogenerated by genpy from test/Complex.msg. Do not edit."""
import codecs
import sys
python3 = True if sys.hexversion > 0x03000000 else False
import genpy
import struct


class Complex(genpy.Message):
  _md5sum = "54da470dccf15d60bd273ab751e1c0a1"
  _type = "test/Complex"
  _has_header = False  # flag to mark the presence of a Header object
  _full_text = """float32 real
float32 imaginary
"""
  __slots__ = ['real','imaginary']
  _slot_types = ['float32','float32']

  def __init__(self, *args, **kwds):
    """
    Constructor. Any message fields that are implicitly/explicitly
    set to None will be assigned a default value. The recommend
    use is keyword arguments as this is more robust to future message
    changes.  You cannot mix in-order arguments and keyword arguments.

    The available fields are:
       real,imaginary

    :param args: complete set of field values, in .msg order
    :param kwds: use keyword arguments corresponding to message field names
    to set specific fields.
    """
    if args or kwds:
      super(Complex, self).__init__(*args, **kwds)
      # message fields cannot be None, assign default values for those that are
      if self.real is None:
        self.real = 0.
      if self.imaginary is None:
        self.imaginary = 0.
    else:
      self.real = 0.
      self.imaginary = 0.

  def _get_types(self):
    """
    internal API method
    """
    return self._slot_types

  def serialize(self, buff):
    """
    serialize message into buffer
    :param buff: buffer, ``StringIO``
    """
    try:
      _x = self
      buff.write(_get_struct_2f().pack(_x.real, _x.imaginary))
    except struct.error as se: self._check_types(struct.error("%s: '%s' when writing '%s'" % (type(se), str(se), str(locals().get('_x', self)))))
    except TypeError as te: self._check_types(ValueError("%s: '%s' when writing '%s'" % (type(te), str(te), str(locals().get('_x', self)))))

  def deserialize(self, str):
    """
    unpack serialized message in str into this message instance
    :param str: byte array of serialized message, ``str``
    """
    if python3:
      codecs.lookup_error("rosmsg").msg_type = self._type
    try:
      end = 0
      _x = self
      start = end
      end += 8
      (_x.real, _x.imaginary,) = _get_struct_2f().unpack(str[start:end])
      return self
    except struct.error as e:
      raise genpy.DeserializationError(e)  # most likely buffer underfill


  def serialize_numpy(self, buff, numpy):
    """
    serialize message with numpy array types into buffer
    :param buff: buffer, ``StringIO``
    :param numpy: numpy python module
    """
    try:
      _x = self
      buff.write(_get_struct_2f().pack(_x.real, _x.imaginary))
    except struct.error as se: self._check_types(struct.error("%s: '%s' when writing '%s'" % (type(se), str(se), str(locals().get('_x', self)))))
    except TypeError as te: self._check_types(ValueError("%s: '%s' when writing '%s'" % (type(te), str(te), str(locals().get('_x', self)))))

  def deserialize_numpy(self, str, numpy):
    """
    unpack serialized message in str into this message instance using numpy for array types
    :param str: byte array of serialized message, ``str``
    :param numpy: numpy python module
    """
    if python3:
      codecs.lookup_error("rosmsg").msg_type = self._type
    try:
      end = 0
      _x = self
      start = end
      end += 8
      (_x.real, _x.imaginary,) = _get_struct_2f().unpack(str[start:end])
      return self
    except struct.error as e:
      raise genpy.DeserializationError(e)  # most likely buffer underfill

_struct_I = genpy.struct_I
def _get_struct_I():
    global _struct_I
    return _struct_I
_struct_2f = None
def _get_struct_2f():
    global _struct_2f
    if _struct_2f is None:
        _struct_2f = struct.Struct("<2f")
    return _struct_2f

可以看到生成的這個(gè)消息里面的函數(shù)主要就是做序列化和反序列化操作,序列化(封包)消息到緩沖區(qū),然后反序列化(解包)到消息實(shí)例中。其他一些相關(guān)信息也解釋下:

_md5sum = "54da470dccf15d60bd273ab751e1c0a1"
MD5校驗(yàn)和,這個(gè)主要是ROS用它來確保消息是正確版本。每次修改消息文件,可能都需要重新catkin_make編譯,因?yàn)榭赡艽嬖谄渌募昧舜讼㈩愋?,比如C++就是將這個(gè)MD5校驗(yàn)和編譯進(jìn)了可執(zhí)行文件,所以需要再次編譯,對于Python的字節(jié)碼文件(.pyc)也需要再次編譯,保證它們的校驗(yàn)和能夠匹配起來。
_type = "test/Complex"
類型定義

_full_text = """float32 real
float32 imaginary
"""
__slots__ = ['real','imaginary']
_slot_types = ['float32','float32']

這里就是實(shí)部與虛部定義的類型。

6、使用自定義消息

上面的消息被定義好了之后,接下來我們來看下如何使用它。

6.1、消息發(fā)布

cd ~/catkin_ws/src/test/src
gedit message_publisher.py
#!/usr/bin/env python
import rospy
from test.msg import Complex
from random import random

rospy.init_node('message_publisher')
pub = rospy.Publisher('complex',Complex)
rate = rospy.Rate(2)
while not rospy.is_shutdown():
    msg = Complex()
    msg.real = random()
    msg.imaginary = random()
    pub.publish(msg)
    rate.sleep()

代碼跟原來差不多,沒什么區(qū)別,將自定義的Complex類型跟導(dǎo)入其他標(biāo)準(zhǔn)類型一樣導(dǎo)入,然后就可以創(chuàng)建消息類的實(shí)例了,有了實(shí)例就可以給里面的字段賦值了。

6.2、消息訂閱

有了消息發(fā)布的代碼之后,來寫一個(gè)訂閱的,跟前面的方法一樣,也是使用回調(diào)函數(shù)來觸發(fā):

cd ~/catkin_ws/src/test/src
gedit message_subscriber.py
#!/usr/bin/env python
import rospy
from test.msg import Complex

def callback(msg):
    print('Real:',msg.real)
    print('Imaginary:',msg.imaginary)

rospy.init_node('message_subscriber')
sub = rospy.Subscriber('complex',Complex,callback)
rospy.spin()

最后也添加執(zhí)行權(quán)限:chmod u+x message_subscriber.py

然后開三個(gè)終端分別輸入以下命令:

roscore
rosrun test message_publisher.py
rosrun test message_subscriber.py

輸出結(jié)果如下:

('Real:', 0.7348452806472778)
('Imaginary:', 0.24286778271198273)
('Real:', 0.8839530348777771)
('Imaginary:', 0.4728539288043976)
('Real:', 0.45228102803230286)
('Imaginary:', 0.9694715142250061)
('Real:', 0.7523669004440308)
('Imaginary:', 0.17689673602581024)

6.3、rosmsg命令

先來看下這條消息有關(guān)的命令的幫助:rosmsg -h

rosmsg is a command-line tool for displaying information about ROS Message types.

Commands:
?? ?rosmsg show?? ?Show message description 顯示消息定義
?? ?rosmsg info?? ?Alias for rosmsg show 是show的別名
?? ?rosmsg list?? ?List all messages 列出所有消息
?? ?rosmsg md5?? ?Display message md5sum 顯示MD5校驗(yàn)和
?? ?rosmsg package?? ?List messages in a package 列出包中所有消息
?? ?rosmsg packages?? ?List packages that contain messages 列出包含消息的所有包

Type rosmsg <command> -h for more detailed usage

查看這個(gè)Complex消息內(nèi)容:rosmsg show Complex

[test/Complex]:
float32 real
float32 imaginary

?驗(yàn)證MD5校驗(yàn)和的值: rosmsg md5 Complex

[test/Complex]: 54da470dccf15d60bd273ab751e1c0a1

恩,沒有問題,可以看到輸出的內(nèi)容跟代碼里面的是一樣的。

如果一個(gè)消息包含另一個(gè)消息,也可以遞歸顯示出來,比如:rosmsg show PointStamped

[geometry_msgs/PointStamped]:
std_msgs/Header header
? uint32 seq
? time stamp
? string frame_id
geometry_msgs/Point point
? float64 x
? float64 y
? float64 z

包含headerpoint,都是ROS類型

列舉定義了消息的所有包:rosmsg packages

?actionlib
actionlib_msgs
actionlib_tutorials
bond
control_msgs
controller_manager_msgs
diagnostic_msgs
dynamic_reconfigure
gazebo_msgs
geometry_msgs
map_msgs
nav_msgs
pcl_msgs
roscpp
rosgraph_msgs
rospy_tutorials
sensor_msgs
shape_msgs
smach_msgs
std_msgs
stereo_msgs
test
tf
tf2_msgs
theora_image_transport
trajectory_msgs
turtle_actionlib
turtlesim
visualization_msgs

列舉test包定義的消息:rosmsg package test?

test/Complex

列舉傳感器包定義的消息:rosmsg package sensor_msgs?

sensor_msgs/BatteryState
sensor_msgs/CameraInfo
sensor_msgs/ChannelFloat32
sensor_msgs/CompressedImage
sensor_msgs/FluidPressure
sensor_msgs/Illuminance
sensor_msgs/Image
sensor_msgs/Imu
sensor_msgs/JointState
sensor_msgs/Joy
sensor_msgs/JoyFeedback
sensor_msgs/JoyFeedbackArray
sensor_msgs/LaserEcho
sensor_msgs/LaserScan
sensor_msgs/MagneticField
sensor_msgs/MultiDOFJointState
sensor_msgs/MultiEchoLaserScan
sensor_msgs/NavSatFix
sensor_msgs/NavSatStatus
sensor_msgs/PointCloud
sensor_msgs/PointCloud2
sensor_msgs/PointField
sensor_msgs/Range
sensor_msgs/RegionOfInterest
sensor_msgs/RelativeHumidity
sensor_msgs/Temperature
sensor_msgs/TimeReference

查看其中相機(jī)的消息定義:rosmsg show sensor_msgs/CameraInfo

?std_msgs/Header header
? uint32 seq
? time stamp
? string frame_id
uint32 height
uint32 width
string distortion_model
float64[] D
float64[9] K
float64[9] R
float64[12] P
uint32 binning_x
uint32 binning_y
sensor_msgs/RegionOfInterest roi
? uint32 x_offset
? uint32 y_offset
? uint32 height
? uint32 width
? bool do_rectify

7、發(fā)布者與訂閱者協(xié)同工作

前面是單個(gè)的發(fā)布者和訂閱者,但是節(jié)點(diǎn)也可以同時(shí)是一個(gè)發(fā)布者和訂閱者,或者擁有多個(gè)訂閱和發(fā)布。實(shí)際上在ROS中,節(jié)點(diǎn)最常做的事情就是傳遞消息,并在消息上進(jìn)行計(jì)算,一起來看一個(gè)例子

cd ~/catkin_ws/src/test/src
#發(fā)布者:
gedit doubler_pub.py
#!/usr/bin/env python
import rospy
from std_msgs.msg import Int32
import random

rospy.init_node('doubler_pub')
pub = rospy.Publisher('number',Int32)
rate = rospy.Rate(2)
while not rospy.is_shutdown():
    num = random.randint(1,9)
    pub.publish(num)
    rate.sleep()

添加執(zhí)行權(quán)限:chmod u+x doubler_pub.py

運(yùn)行:rosrun test doubler_pub.py

這里就訂閱上面的發(fā)布,然后做加倍處理之后再發(fā)布,也就是同時(shí)擁有了訂閱和發(fā)布的功能

cd ~/catkin_ws/src/test/src
#加倍操作:
gedit doubler.py
#!/usr/bin/env python
import rospy
from std_msgs.msg import Int32

rospy.init_node('doubler')
def callback(msg):
    print(msg.data)
    doubled = msg.data * 2
    pub.publish(doubled)

sub = rospy.Subscriber('number',Int32,callback)
pub = rospy.Publisher('doubled',Int32)
rospy.spin()

添加執(zhí)行權(quán)限:chmod u+x doubler.py

運(yùn)行:rosrun test doubler.py

訂閱者:gedit doubler_sub.py

#!/usr/bin/env python
import rospy
from std_msgs.msg import Int32

def callback(msg):
    print(msg.data)

rospy.init_node('doubler_sub')
sub = rospy.Subscriber('doubled',Int32,callback)
rospy.spin()

添加執(zhí)行權(quán)限:chmod u+x doubler_sub.py
運(yùn)行:rosrun test doubler_sub.py

如下圖:

ROS通信機(jī)制之話題(Topics)的發(fā)布與訂閱以及自定義消息的實(shí)現(xiàn),機(jī)器人操作系統(tǒng)(ROS),rospy.Publisher,Subscriber,rqt_graph,rostopic,catkin_make,package.xml,CMakeLists.txt

這里的加倍操作,就是在接收到新數(shù)據(jù)之后才發(fā)布,也就是說這個(gè)節(jié)點(diǎn)就是起到一個(gè)信息計(jì)算處理的一個(gè)作用,然后將加倍的數(shù)據(jù)發(fā)布出去。
最后做一個(gè)訂閱者查看下結(jié)果,輸出比對發(fā)現(xiàn)確實(shí)是將數(shù)據(jù)做了加倍處理。文章來源地址http://www.zghlxwxcb.cn/news/detail-671186.html

到了這里,關(guān)于ROS通信機(jī)制之話題(Topics)的發(fā)布與訂閱以及自定義消息的實(shí)現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【ROS2入門】理解 ROS 2 Topics 話題

    【ROS2入門】理解 ROS 2 Topics 話題

    ????????大家好,我是虎哥,從今天開始,我將花一段時(shí)間,開始將自己從ROS1切換到ROS2,在上一篇中,我們一起了解ROS 2中節(jié)點(diǎn)的功能以及與之交互的工具, 這一篇,我們主要會圍繞ROS中另外一個(gè)重要的概念“Topic ”,詳細(xì)其具體的操作指令。 目錄 一、ROS2中話題(Top

    2023年04月08日
    瀏覽(18)
  • ROS學(xué)習(xí)——通信機(jī)制(話題通信③—注意事項(xiàng))

    ROS學(xué)習(xí)——通信機(jī)制(話題通信③—注意事項(xiàng))

    2.1.2 話題通信基本操作A(C++) · Autolabor-ROS機(jī)器人入門課程《ROS理論與實(shí)踐》零基礎(chǔ)教程? ?043話題通信(C++)4_注意事項(xiàng)_Chapter2-ROS通信機(jī)制_嗶哩嗶哩_bilibili 1. int main(int argc, char const *argv[]){} vscode 中的 main 函數(shù) 聲明 int main(int argc, char const *argv[]){},默認(rèn)生成 argv 被 const 修飾,需要

    2024年02月08日
    瀏覽(21)
  • 【ROS】服務(wù)通信、話題通信的應(yīng)用

    【ROS】服務(wù)通信、話題通信的應(yīng)用

    Halo,這里是Ppeua。平時(shí)主要更新C語言,C++,數(shù)據(jù)結(jié)構(gòu)算法…感興趣就關(guān)注我吧!你定不會失望。 本章將來學(xué)習(xí)如何利用話題通信,服務(wù)通信兩種種方式對turtlesim進(jìn)行一個(gè)控制 利用話題通信發(fā)布一個(gè)位姿信息,讓烏龜一直做圓周運(yùn)動 首先,先啟動 turtlesim 這個(gè)節(jié)點(diǎn) 現(xiàn)在可以直

    2024年02月06日
    瀏覽(47)
  • ROS2從入門到精通1-2:詳解ROS2服務(wù)通信機(jī)制與自定義服務(wù)

    ROS2從入門到精通1-2:詳解ROS2服務(wù)通信機(jī)制與自定義服務(wù)

    本專欄旨在通過對ROS2的系統(tǒng)學(xué)習(xí),掌握ROS2底層基本分布式原理,并具有機(jī)器人建模和應(yīng)用ROS2進(jìn)行實(shí)際項(xiàng)目的開發(fā)和調(diào)試的工程能力。 ??詳情:《ROS2從入門到精通》 服務(wù) 是 ROS 圖中節(jié)點(diǎn)之間的另一種通信方法。服務(wù)基于 服務(wù)器-客戶端 模型,不同于話題的 發(fā)布者-訂閱者

    2024年04月09日
    瀏覽(20)
  • 學(xué)習(xí)SLAM:SLAM進(jìn)階(九)以激光點(diǎn)云賦色為例講述如何自定義ROS的消息格式并實(shí)現(xiàn)消息的訂閱與發(fā)布

    目錄 1 為什么需要自定義的ROS消息格式 1.1 簡介 1.2 ROS自定義消息格式的通用結(jié)構(gòu)

    2024年02月09日
    瀏覽(56)
  • 隨手筆記——將ROS圖像話題轉(zhuǎn)為OpenCV圖像格式處理后再轉(zhuǎn)為ROS圖像話題發(fā)布(C++版)

    將ROS圖像話題轉(zhuǎn)為OpenCV圖像格式處理后再轉(zhuǎn)為ROS圖像話題發(fā)布,主要通過cv_bridge的toImageMsg()和toCvCopy()函數(shù)(C++版)。 ? 代碼來自wiki

    2024年02月12日
    瀏覽(27)
  • 【ROS】如何讓ROS中節(jié)點(diǎn)實(shí)現(xiàn)數(shù)據(jù)交換Ⅰ--ROS話題通信

    【ROS】如何讓ROS中節(jié)點(diǎn)實(shí)現(xiàn)數(shù)據(jù)交換Ⅰ--ROS話題通信

    Halo,這里是Ppeua。平時(shí)主要更新C語言,C++,數(shù)據(jù)結(jié)構(gòu)算法…感興趣就關(guān)注我吧!你定不會失望。 roscore 啟動ros核心節(jié)點(diǎn) roscd 將工作空間切換到指定ros功能包 catkin_create_pkg 將工作空間切換到指定ros功能包 ** rqt_graph 啟動節(jié)點(diǎn)間的關(guān)系圖 rosrun 包名 節(jié)點(diǎn)名稱 啟動節(jié)點(diǎn) ( rosrun

    2024年02月02日
    瀏覽(29)
  • [ros][ubuntu]ros在ubuntu18.04上工作空間創(chuàng)建和發(fā)布一個(gè)話題

    [ros][ubuntu]ros在ubuntu18.04上工作空間創(chuàng)建和發(fā)布一個(gè)話題

    構(gòu)建catkin工作空間 ?mkdir -p ~/catkin_ws/src ? ?cd ~/catkin_ws/src ?catkin_init_workspace ?cd ~/catkin_ws/ ?catkin_make 配置環(huán)境變量 ?echo \\\"source ~/catkin_ws/devel/setup.bash\\\" ?~/.bashrc ?source ~/.bashrc 檢查環(huán)境變量 ?echo $ROS_PACKAGE_PATH 遇到錯(cuò)誤:上面操作不需要用sudo 進(jìn)行操作,但是由于初學(xué)者可能存在

    2024年02月10日
    瀏覽(18)
  • 隨手筆記——通過OpenCV獲取圖像轉(zhuǎn)為ROS圖像話題發(fā)布(C++版)

    通過OpenCV獲取圖像轉(zhuǎn)為ROS圖像話題發(fā)布 注:sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(), “bgr8”, image).toImageMsg(); //核心代碼

    2024年02月12日
    瀏覽(28)
  • 【ROS】ROS 發(fā)布和訂閱壓縮圖像消息 CompressedImage

    【ROS】ROS 發(fā)布和訂閱壓縮圖像消息 CompressedImage

    參考 cv_bridge 文檔 其中 “jpg” 表示將圖像壓縮的目標(biāo)格式,還有很多其他參數(shù)可選,如下所示 但親測 “jpg” 壓縮比最大,圖像傳輸占用的帶寬最少 其中 “bgr8” 表示將圖像解析為 “bgr8” 格式,也是 opencv 默認(rèn)的圖像格式 參考 rospy wiki 教程 參考 opencv 中 imencode 與 imdecod

    2024年04月16日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包