cartographer订阅话题的函数封装
Posted COCO_PEAK_NOODLE
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cartographer订阅话题的函数封装相关的知识,希望对你有一定的参考价值。
template <typename MessageType>
::ros::Subscriber SubscribeWithHandler(
void (Node::*handler)(int, const std::string&,
const typename MessageType::ConstPtr&),
const int trajectory_id, const std::string& topic,
::ros::NodeHandle* const node_handle, Node* const node) {
return node_handle->subscribe<MessageType>(
topic, kInfiniteSubscriberQueueSize,
boost::function<void(const typename MessageType::ConstPtr&)>(
[node, handler, trajectory_id,
topic](const typename MessageType::ConstPtr& msg) {
(node->*handler)(trajectory_id, topic, msg);
}));
}
知识点-1:typename MessageType::ConstPtr,我们知道MessageType是模板类型,但是系统不知道MessageType::ConstPtr是类型还是啥?所以加上typename告诉系统这是个类型,所以我们一般用typename告知系统这是个类型。
知识点-2: 函数指针作为参数,它是成员函数指针,所以调用的时候要这么用
(node->*handler)(trajectory_id, topic, msg);
知识点-3:lamda表达式,使用lamda表达式可以构建函数的body,这里的boost::function可以替换为
std::function
参考文章
【C++】std::function与函数指针
C++11新特性:参数绑定——std::bind
C++11 中的std::function和std::bind
C++Lambda表达式
深究篇
我们来看下为什么能这么用?
subscribe是一个模板函数,我们看下它的定义
/**
* \\brief Subscribe to a topic, version for arbitrary boost::function object
*
* This method connects to the master to register interest in a given
* topic. The node will automatically be connected with publishers on
* this topic. On each message receipt, callback is invoked and passed a shared pointer
* to the message received. This message should \\b not be changed in place, as it
* is shared with any other subscriptions to this topic.
*
* This version of subscribe allows anything bindable to a boost::function object
*
* \\param M [template] M here is the message type
* \\param topic Topic to subscribe to
* \\param queue_size Number of incoming messages to queue up for
* processing (messages in excess of this queue capacity will be
* discarded).
* \\param callback Callback to call when a message has arrived
* \\param tracked_object A shared pointer to an object to track for these callbacks. If set, the a weak_ptr will be created to this object,
* and if the reference count goes to 0 the subscriber callbacks will not get called.
* Note that setting this will cause a new reference to be added to the object before the
* callback, and for it to go out of scope (and potentially be deleted) in the code path (and therefore
* thread) that the callback is invoked from.
* \\param transport_hints a TransportHints structure which defines various transport-related options
* \\return On success, a Subscriber that, when all copies of it go out of scope, will unsubscribe from this topic.
* On failure, an empty Subscriber which can be checked with:
\\verbatim
void callback(const std_msgs::Empty::ConstPtr& message){...}
ros::NodeHandle nodeHandle;
ros::Subscriber sub = nodeHandle.subscribe("my_topic", 1, callback);
if (sub) // Enter if subscriber is valid
{
...
}
\\endverbatim
* \\throws InvalidNameException If the topic name begins with a tilde, or is an otherwise invalid graph resource name
* \\throws ConflictingSubscriptionException If this node is already subscribed to the same topic with a different datatype
*/
template<class M>
Subscriber subscribe(const std::string& topic, uint32_t queue_size, const boost::function<void (const boost::shared_ptr<M const>&)>& callback,
const VoidConstPtr& tracked_object = VoidConstPtr(), const TransportHints& transport_hints = TransportHints())
{
SubscribeOptions ops;
ops.template init<M>(topic, queue_size, callback);
ops.tracked_object = tracked_object;
ops.transport_hints = transport_hints;
return subscribe(ops);
}
看到这也回调函数的定义方式和我们的不同啊,这也是知识点-1的原因,为啥要复用typename。因为MessageType::ConstPtr这是啥我们不知道,这个要使用者自己定义ConstPtr,不然使用这个模板函数会出错。
boost::function<void (const boost::shared_ptr<M const>&)>& callback
那我们按照定义方式定义不久可以了吗?所以我们这样改写也是可以的
template <typename MessageType>
::ros::Subscriber SubscribeWithHandler(
void (Node::*handler)(int, const std::string&,
const boost::shared_ptr<MessageType const>&),
const int trajectory_id, const std::string& topic,
::ros::NodeHandle* const node_handle, Node* const node) {
return node_handle->subscribe<MessageType>(
topic, kInfiniteSubscriberQueueSize,
boost::function<void(const boost::shared_ptr<MessageType const>&)>(
[node, handler, trajectory_id,
topic](const boost::shared_ptr<MessageType const>& msg) {
(node->*handler)(trajectory_id, topic, msg);
}));
我们再来看下ConstPtr的定义,与我们的形参一致
typedef boost::shared_ptr< ::sensor_msgs::LaserScan_<ContainerAllocator> const> ConstPtr;
以上是关于cartographer订阅话题的函数封装的主要内容,如果未能解决你的问题,请参考以下文章