ROS----roscpp Overview Publishers and Subscribers

·  roscpp/Overview/Publishersand Subscribers

1.发布到主题

另请参阅:ros :: NodeHandle :: advertise()API文档ros :: Publisher API文档ros :: NodeHandle API文档
创建一个将消息发布到主题的句柄是使用ros :: NodeHandle类完成的,NodeHandles概述中详细介绍了该类
该NodeHandle::advertise()方法用于创建一个ros::Publisher是用来在一个主题,如发布:

切换行号显示

   1ros::Publisherpub = nh.advertise<std_msgs::String>("topic_name", 5);

   2std_msgs::Stringstr;

   3str.data = "helloworld";

   4pub.publish(str);

注意:NodeHandle :: advertise()可能(尽管很少)返回一个空的ros :: Publisher。将来这些案例可能会引发异常,但现在他们只是打印一个错误。您可以通过以下方式检查:

切换行号显示

   1if (!pub)

   2{

   3...

   4}

1.1内部处理发布Intraprocess Publishing

当相同主题的发布者和订阅者都存在于同一个节点内时,roscpp可以跳过序列化/反序列化步骤(可能会节省大量处理和延迟)。它只能做到这一点,尽管如果消息发布为shared_ptr:

   1ros::Publisherpub = nh.advertise<std_msgs::String>("topic_name", 5);

   2std_msgs::StringPtrstr(newstd_msgs::String);

   3str->data = "helloworld";

   4pub.publish(str);

发布的这种形式是什么可以让nodelets这么大的战胜在单独的进程节点。
请注意,以这种方式发布时,您和roscpp之间存在隐式合同:您可能不会修改发送后发送的信息,因为该指针会直接传递给任何内部进程订阅者。如果您想发送另一条消息,则必须分配一个新消息并发送该消息。

1.2发布商选项PublisherOptions

advertise()的简单版本的签名是:

切换行号显示

1template<classM>

2ros::Publisheradvertise(conststd::string& topic, uint32_tqueue_size, boollatch = false);

  • M [必填]
这是一个模板参数,指定要在主题上发布的消息类型

topic [必填]

这是要发布的主题。

queue_size [必需]

这是传出消息队列的大小。如果你发布的速度比roscpp更快,那么roscpp会开始删除旧的消息。这里的值为0意味着无限的队列,这可能是危险的。有关更多信息,请参阅rospy文档,了解如何选择合适的queue_size

latch [可选]

启用连接上的“锁定”。当连接锁定时,最后发布的消息将被保存并自动发送给将来连接的任何用户。这对于缓慢更改静态数据(如地图)很有用。请注意,如果同一主题上存在多个发布者,并在同一个节点上实例化,则只会发送该节点上次发布的消息,而不是每个发布者上一次发布的单个主题发布的消息。

1.3发布者手柄上的其他操作OtherOperations on the Publisher Handle

ros :: Publisher是内部引用计数----这意味着复制它们非常快,并且不会创建ros :: Publisher的“新”版本。一旦ros :: Publisher的所有副本都被破坏,主题将被关闭。这有一些例外:
1.      ros :: shutdown()被调用---这会关闭所有发布者(以及其他所有内容)。
2.   ros:: Publisher :: shutdown()被调用。这将关闭这个话题,除非有......
3.      对同一主题多次调用NodeHandle :: advertise(),并使用相同的消息类型。在这种情况下,关于特定主题的所有ros :: Publisher都被视为彼此的副本。

ros :: Publisher实现==!=<运算符,并且可以在std :: mapstd :: set等中使用它们

您可以使用ros :: Publisher :: getTopic()方法检索出版商的主题。

1.4.publish()行为和排队publish()behavior and queueing

roscpp中的publish()是异步的,并且只有在该主题上连接了订阅者时才起作用。 publish()本身意味着速度非常快,所以它尽可能地做到尽可能少的工作:
1.      将消息序列化到缓冲区
  1. 将该缓冲区推入队列以供稍后处理
然后通过roscpp的内部线程之一尽快为其推送的队列进行服务,在该队列中,每个连接的订阅者都将其放入队列中 - 第二组队列是大小设置为queue_size参数的队列()。 如果其中一个队列填满,则在将下一条消息添加到队列之前,最旧的消息将被丢弃。
请注意,传输级别上可能还有一个OS级别的队列,例如TCP / UDP发送缓冲区。

2.订阅主题

另请参见:ros :: NodeHandle :: subscribe()API文档ros ::订阅者API文档ros :: NodeHandle API文档ros :: TransportHints API文档
订阅主题也使用ros :: NodeHandle类完成(在NodeHandles概述中有更详细的介绍)。使用全局函数的简单订阅将如下所示:

切换行号显示

   1voidcallback(conststd_msgs::StringConstPtr& str)

   2{

   3...

   4}

   5

   6...

   7ros::Subscribersub = nh.subscribe("my_topic", 1, callback);

2.1订户选项

有很多不同版本的ros :: NodeHandle ::subscribe(),但简单的版本归结为:

切换行号显示

   1template<classM>

   2ros::Subscribersubscribe(conststd::string& topic, uint32_tqueue_size, <callback, whichmayinvolvemultiplearguments>, constros::TransportHints& transport_hints = ros::TransportHints());

M[通常不需要]----这是一个模板参数,指定要在主题上发布的消息类型。对于这个subscribe()的大多数版本,你不需要明确地定义它,因为编译器可以从你指定的回调中推断出它。

Topic---要订阅的主题

queue_size----这是roscpp将用于您的回调的传入消息队列大小。如果邮件到达太快而你无法跟上,roscpp将开始丢弃邮件。这里的值0意味着无限的队列,这可能是危险的。

<callback>----根据您使用的subscribe()版本,这可能是几类。最常见的是一个类方法指针和一个指向类实例的指针。这在后面会有更详细的解释。

transport_hints----传输提示允许您为roscpp的传输层指定提示。这使您可以指定喜欢使用UDP传输,使用tcp nodelay等方式,这在后面会有更详细的介绍。

2.2回调签名CallbackSignature

回调的签名是:

切换行号显示

   1void  callbackconst  boost :: shared_ptr < Message  const >&);

每个生成的消息都提供了共享指针类型的typedef,因此您也可以使用,例如:

切换行号显示

   1void  callbackconst  std_msgs :: StringConstPtr&);

要么

切换行号显示

   1void  callbackconst  std_msgs :: String :: ConstPtr&);

其他有效签名[ROS 1.1+]

ROS 1.1开始,我们也支持上述回调的变体:

切换行号显示

   1void  callbackboost :: shared_ptr < std_msgs :: String  const >;

   2void  callbackstd_msgs :: StringConstPtr;

   3void  callbackstd_msgs :: String :: ConstPtr;

   4void  callbackconst  std_msgs :: String&);

   void  callbackstd_msgs :: String;

   6void  callbackconst  ros :: MessageEvent < std_msgs :: String  const >&);

你也可以请求一个非const的消息,在这种情况下,如果需要的话,将会创建一个副本(即在一个节点中有多个同一主题的订阅):

切换行号显示

   1void  callbackconst  boost :: shared_ptr < std_msgs :: String >&);

   2void  callbackboost :: shared_ptr < std_msgs :: String >;

   3void  callbackconst  std_msgs :: StringPtr&);

   4void  callbackconst  std_msgs :: String :: Ptr&);

   void  callbackstd_msgs :: StringPtr;

   6void  callbackstd_msgs :: String :: Ptr;

   7void  callbackconst  ros :: MessageEvent < std_msgs :: String >&);

该MessageEvent的版本描述如下。

2.3回调类型

roscpp支持boost :: function支持的任何回调函数
  1. 功能
  2. 类方法
  3. 函子对象(包括boost :: bind

2.3.1功能

函数是最容易使用的:

切换行号显示

   1voidcallback(conststd_msgs::StringConstPtr& str)

   2{

   3...

   4}

   5

   6...

   7ros::Subscribersub = nh.subscribe("my_topic", 1, callback);

2.3.2类方法

类方法也很容易,但它们需要额外的参数:

切换行号显示

   1void  Foo :: callbackconst  std_msgs :: StringConstPtrmessage

   2{

   3}

   4

   5...

   6Foo  foo_object ;

   7ros :: Subscriber  sub = nhsubscribe“ my_topic ”1,&Foo :: callback,&foo_object;

2.3.3Functor对象

函子对象是声明operator()的类,例如:

切换行号显示

   1classFoo

   2{

   3public:

   4  voidoperator()(conststd_msgs::StringConstPtr& message)

   5  {

   6  }

   7};

传递给subscribe()的函子必须是可复制的。在foo函子可以搭配使用subscribe()像这样:

切换行号显示

  1ros::Subscribersub = nh.subscribe<std_msgs::String>("my_topic", 1, Foo());

注意:当使用函数对象(例如boost :: bind)时,必须明确指定消息类型作为模板参数,因为在这种情况下编译器不能推导出它。

2.4MessageEvent [ROS 1.1+]

MessageEvent类允许您检索从订阅回调中的消息的元数据:

切换行号显示

   1void  callbackconst  ros :: MessageEvent < std_msgs :: String  const >event

   2{

   3  const  std :: stringpublisher_name = eventgetPublisherName();

   4  const  ros :: M_stringheader = eventgetConnectionHeader();

     ros :: Time  receipt_time = eventgetReceiptTime();

   6

   7  const  std_msgs :: StringConstPtrmsg = eventgetMessage();

   8}

(有关连接头中字段的详细信息,请参阅ROS / Connection Header

2.5排队和懒惰的反序列化Queueingand Lazy Deserialization

当消息首次到达某个主题时,它将被放入一个队列,其大小由subscribe()中queue_size参数指定。如果队列已满并且有新消息到达,则最旧的消息将被丢弃。此外,消息实际上并未反序列化,直到需要它的第一个回调即将被调用。

2.6运输提示Transport Hints

另请参阅:ros :: TransportHints API文档

ros :: TransportHints用于指定您希望传输层为此主题行为的提示。例如,如果您想要指定“unreliable”连接(并且不允许“可靠”连接作为后退):

切换行号显示

   1ros :: Subscriber  sub = nh.subscribe“ my_topic ”1callbackros :: TransportHints().unreliable());

请注意,ros ::TransportHints使用命名参数成语,这是一种方法链接形式。这意味着您可以执行以下操作:

切换行号显示

   1ros::TransportHints()

   2        .unreliable()

   3        .reliable()

   4        .maxDatagramSize(1000)

   5        .tcpNoDelay();

就像这个例子一样,您可以指定多个不同的传输选项(不可靠以及可靠)。如果您订阅的主题上的发布者不支持第一个连接(不可靠),则连接将与第二个(可靠)连接(如果支持)。在这种情况下,两种方法的顺序很重要,因为它决定了所考虑的传输的顺序。
您目前不能在发布服务器端指定传输提示。这可能是未来的一个选择。

猜你喜欢

转载自blog.csdn.net/cookie909/article/details/79842351
今日推荐