之前看depthimage_to_laserscan
包,发现它的订阅发布采用的是所谓 lazy模式。今天研究了一下,发现并不复杂。先看advertise
函数的一个原型:
1 | Publisher ros::NodeHandle::advertise(const std::string& topic, |
原来有三个原型,我们常用的是第一个,这个是第二个,第三个就极其罕见了,形参是个AdvertiseOptions类型。
话题有订阅者时,发布者会触发connect_cb
函数,停止订阅时又触发disconnect_cb
函数。如果让它们做类成员函数,就使用Boost::bind
形式,tracked_object
暂时不用。所以程序可以这样写:
1 | void connectCb(const ros::SingleSubscriberPublisher& singlePub) |
可以用
rostopic echo topic
测试
再来看depthimage_to_laserscan
的程序,构造函数里是这样的:
1 | pub_ = n.advertise<sensor_msgs::LaserScan>("scan", 10, |
它是把两个函数用成员函数的形式,
connectCb
是这样的:1 | if (!sub_ && pub_.getNumSubscribers() > 0) |
而depthCb
是:
1 | sensor_msgs::LaserScanPtr scan_msg = dtl_.convert_msg(depth_msg, info_msg); |
显然逻辑是这样的:有其他节点订阅
scan
话题时,发布者里才订阅image_raw
话题,然后才会发布scan
话题的实际消息,所谓的lazy就是scan
话题的消息发布
disconnectCb
里,如果另一个节点不再订阅scan
话题,本节点就会sub_.shutdown();
;如果再有订阅scan
,又可以通过connectCb
使用sub_
,设计确实很巧妙