ROS使用模板类成员作为主题订阅的回调

时间:2016-09-01 09:42:02

标签: c++ ros

我试图创建一个可以实例化一次的类,并且可以添加ros主题订阅,其中回调是同一成员函数的模板特化。

类ros_topic_subscriber.h文件是

class ROSTopicSubscriber
{
public:

    ROSTopicSubscriber() {}

    ~ROSTopicSubscriber() {}

    template<typename ROSMessageType>
    int init
    (
        const ros::NodeHandle &controller_nh,
        const std::string& topic_name,
        unsigned int buffer_size
    )
    {
        ros::Subscriber sub = controller_nh.subscribe(
            topic_name, 
            buffer_size, 
            &ROSTopicSubscriber::topicCallback<ROSMessageType>,
            this
        );
    }

    /*! \brief Implement this function for your own message!
    */
    template<typename ROSMessageType>
    void topicCallback(const typename ROSMessageType::ConstPtr& msg);


private:

    // No copying of this class is allowed !
    ROSTopicSubscriber(const ROSTopicSubscriber& other) = delete;
    ROSTopicSubscriber(ROSTopicSubscriber&& other) = delete;
    ROSTopicSubscriber& operator=(const ROSTopicSubscriber& other) = delete;
    ROSTopicSubscriber& operator=(ROSTopicSubscriber&& other) noexcept = delete;

};

在我的情况下,topicCallback的一个可能的模板专业化是(在ros_topic_subscriber.cpp文件中)

template<>
void ROSTopicSubscriber::topicCallback<geometry_msgs::Pose>
(
    const geometry_msgs::Pose::ConstPtr& msg
)
{
    std::cout << "msg\n";
}

并且要使用这个类,例如可以做

topic_subscriber_.init<geometry_msgs::Pose>
    (n, "/wintracker/pose", 100);

现在,我得到的编译错误是:

ros_topic_subscriber.h:66:3: 
error: passing ‘const ros::NodeHandle’ as ‘this’ argument of 
‘ros::Subscriber ros::NodeHandle::subscribe(
    const string&, 
    uint32_t, 
    void (T::*)(const boost::shared_ptr<const M>&), 
    T*, 
    const ros::TransportHints&) 
[with M = geometry_msgs::Pose_<std::allocator<void> >; 
    T = hiqp::ROSTopicSubscriber; 
    std::string = std::basic_string<char>; 
    uint32_t = unsigned int]’ 
discards qualifiers [-fpermissive]

为什么在这种情况下会出现此错误消息? 是否有可能实现这种类? 我该如何修复错误?

1 个答案:

答案 0 :(得分:1)

您的ROSTopicSubscriber::init获取controller_nh参数作为const引用,这意味着它只能调用在常量对象上声明为可调用的方法。但是,您尝试调用未以此方式声明的subscribe方法。

方法声明可能在您的代码中看起来像这样:

class NodeHandle {
    // ...
    Subscriber subscribe(/* all the parameters */);
    // ...
}

解决方案取决于subscribe方法是否需要更改NodeHandle对象内的任何内容。如果没有,则在常量对象上将其标记为可调用:

class NodeHandle {
    // ...
    Subscriber subscribe(/* all the parameters */) const; // <- notice const!
    // ...
}

如果subscribe方法更改NodeHandle内的内容,则需要将controller_nh方法的ROSTopicSubscriber::init参数更改为可变(非常量)引用:

int init
(
    ros::NodeHandle &controller_nh, // <- notice const is gone
    const std::string& topic_name,
    unsigned int buffer_size
)