在使用ros写订阅者时,代码如下:
#include "ros/ros.h" #include "std_msgs/String.h" #include <boost/thread.hpp> #include <sensor_msgs/PointCloud2.h> #include <nav_msgs/Odometry.h> #include <typeinfo> class multiThreadListener { public: void chatterCallback1(const nav_msgs::Odometry::ConstPtr &input_msg, std::string topicName); void chatterCallback2(const sensor_msgs::PointCloud2ConstPtr& input_msg, std::string topicName); multiThreadListener(); private: ros::NodeHandle n; std::string name1; std::string name2; ros::Subscriber sub1; ros::Subscriber sub2; }; multiThreadListener::multiThreadListener() { name1 = "/navsat/odom"; name2 = "/radar_cloud"; sub1 = n.subscribe("/navsat/odom", 10, boost::bind(&multiThreadListener::chatterCallback1, this, _1, name1)); sub2 = n.subscribe("/radar_cloud", 10, boost::bind(&multiThreadListener::chatterCallback2, this,_1, name2)); } void multiThreadListener::chatterCallback1(const nav_msgs::Odometry::ConstPtr &input_msg, std::string topicName) { ROS_INFO("I heard: [%s]", topicName); ros::Rate loop_rate(0.5);//block chatterCallback1() loop_rate.sleep(); } void multiThreadListener::chatterCallback2(const sensor_msgs::PointCloud2ConstPtr& input_msg, std::string topicName) { ROS_INFO("I heard: [%s]", topicName); ros::Rate loop_rate(0.5);//block chatterCallback2() loop_rate.sleep(); } int main(int argc, char **argv) { ros::init(argc, argv, "multi_sub"); multiThreadListener listener_obj; ros::MultiThreadedSpinner s(2); ros::spin(s); return 0; }
编译总是报如下错,
error: no matching function for call to ‘ros::NodeHandle::subscribe(const char [13], int, boost::_bi::bind_t<void, boost::_mfi::mf2<void, multiThreadListener,
const boost::shared_ptr<const nav_msgs::Odometry_<std::allocator<void> > >&, std::__cxx11::basic_string<char> >, boost::_bi::list3<boost::_bi::value<multiThreadListener*>,
boost::arg<1>, boost::_bi::value<std::__cxx11::basic_string<char> > > >)’ sub1 = n.subscribe("/navsat/odom", 10, boost::bind(&multiThreadListener::chatterCallback1, this, _1, name1));
原因是subscribe()函数在使用函数对象时,如boost::bind()函数返回的对象,必须要明确指定消息类型作为模板参数,因为编译器无法推断它。
上面就是没有指明导致的错误。
在查看NodeHandle.h源码查看subscribe()函数的定义如下
template<class M, class T> Subscriber subscribe(const std::string& topic, uint32_t queue_size, void(T::*fp)(M), T* obj, const TransportHints& transport_hints = TransportHints()) { ... } template<class M, class T> Subscriber subscribe(const std::string& topic, uint32_t queue_size, void(T::*fp)(const boost::shared_ptr<M const>&), T* obj, const TransportHints& transport_hints = TransportHints()) { ... } template<class M, class T> Subscriber subscribe(const std::string& topic, uint32_t queue_size, void(T::*fp)(M), const boost::shared_ptr<T>& obj, const TransportHints& transport_hints = TransportHints()) { ... } template<class M, class T> Subscriber subscribe(const std::string& topic, uint32_t queue_size, void(T::*fp)(const boost::shared_ptr<M const>&), const boost::shared_ptr<T>& obj, const TransportHints& transport_hints = TransportHints()) { ... } template<class M> Subscriber subscribe(const std::string& topic, uint32_t queue_size, void(*fp)(M), const TransportHints& transport_hints = TransportHints()) { ... } template<class M> Subscriber subscribe(const std::string& topic, uint32_t queue_size, void(*fp)(const boost::shared_ptr<M const>&), const TransportHints& transport_hints = TransportHints()) { ... } 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()) { ... } template<class M, class C> Subscriber subscribe(const std::string& topic, uint32_t queue_size, const boost::function<void (C)>& callback, const VoidConstPtr& tracked_object = VoidConstPtr(), const TransportHints& transport_hints = TransportHints()) { ... }
很显然,subscribe是模板函数,在传入boost::function类型时,需要传入模板参数,上面的代码
sub2 = n.subscribe("/radar_cloud", 10, boost::bind(&multiThreadListener::chatterCallback2, this,_1, name2));
传入了三个参数,第三个参数中的chatterCallback2()的第一个参数时sensor_msgs::PointCloud2ConstPtr,其定义是
typedef boost::shared_ptr< ::sensor_msgs::PointCloud2 const> sensor_msgs::PointCloud2ConstPtr
显然,上面代码使用的subscribe()函数是下面这个版本
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()) { ... }
故,正确的代码应该如下
#include "ros/ros.h" #include "std_msgs/String.h" #include <boost/thread.hpp> #include <sensor_msgs/PointCloud2.h> #include <nav_msgs/Odometry.h> #include <typeinfo> class multiThreadListener { public: void chatterCallback1(const nav_msgs::Odometry::ConstPtr &input_msg, std::string topicName); void chatterCallback2(const sensor_msgs::PointCloud2ConstPtr& input_msg, std::string topicName); multiThreadListener(); private: ros::NodeHandle n; std::string name1; std::string name2; ros::Subscriber sub1; ros::Subscriber sub2; }; multiThreadListener::multiThreadListener() { name1 = "/navsat/odom"; name2 = "/radar_cloud"; sub1 = n.subscribe<nav_msgs::Odometry>("/navsat/odom", 10, boost::bind(&multiThreadListener::chatterCallback1, this, _1, name1)); sub2 = n.subscribe<sensor_msgs::PointCloud2>("/radar_cloud", 10, boost::bind(&multiThreadListener::chatterCallback2, this,_1, name2)); } void multiThreadListener::chatterCallback1(const nav_msgs::Odometry::ConstPtr &input_msg, std::string topicName) { ROS_INFO("I heard: [%s]", topicName); ros::Rate loop_rate(0.5);//block chatterCallback1() loop_rate.sleep(); } void multiThreadListener::chatterCallback2(const sensor_msgs::PointCloud2ConstPtr& input_msg, std::string topicName) { ROS_INFO("I heard: [%s]", topicName); ros::Rate loop_rate(0.5);//block chatterCallback2() loop_rate.sleep(); } int main(int argc, char **argv) { ros::init(argc, argv, "multi_sub"); multiThreadListener listener_obj; ros::MultiThreadedSpinner s(2); ros::spin(s); return 0; }
编译通过。