zoukankan      html  css  js  c++  java
  • ros中NodeHandle类的subscribe()函数使用报错问题

    在使用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;
    }

    编译通过。

  • 相关阅读:
    ASP.NET很容易的图片裁剪功能
    ASP.NET 你肯定会用到的图片裁剪功能,可按长度或宽度裁剪,也能绘制一个更大图
    最简单的设置Title和关键字方法,方便你做搜索引擎检索
    ASP.NET 图片压缩,等比压缩图片
    不安装MVC3环境在IIS7上部署MVC3项目
    移动端布局(rem+dpr)
    H5网页打开APP
    第二次作业
    第四次
    第三次作业
  • 原文地址:https://www.cnblogs.com/Glucklichste/p/11136909.html
Copyright © 2011-2022 走看看