Alex44
Alex44

Reputation: 3855

ROS: Binding a callback function and a object member to a subscriber node

I'm writing a class with the goal to provide a model to rviz. The class shall be able to subscribe a topic to simulate some movements. Therefore I want to use node.subscribe but the problem is, that subscribe expects a static void function. That means I have no access to my class members and methods.

Is there any possibility to do this?

Here the shortened code:

MyClass.h

class MyClass
{
    private:
        tf::Transform transform;
        ros::Subscriber subscriber;

    public:
        int publish ();

    private:
        static void callback ( std_msgs::Float64MultiArray msg);
};

MyClass.cpp

MyClass::MyClass( )
{
    this->subscriber =
      this->node.subscribe( "topic_id",
                            1,
                            &MyClass::callback,
                            this->transform);
}

void MyClass::callback( std_msgs::Float64MultiArray msg, tf::Transform &transform)
{
    std::vector<double> data(4);
    data = msg.data;

    transform->setRotation( tf::Quaternion(data[0], data[1], data[2], data[3]) );
    publish ();
}

Upvotes: 2

Views: 9811

Answers (1)

Vtik
Vtik

Reputation: 3130

According to ROS wiki, there's no such need for a static void. I quote this as a reference from here:

callback

Depending on the version of subscribe() you're using, this may be any of a few things. The most common is a class method pointer and a pointer to the instance of the class. This is explained in more detail later.

Thus, just declare your callback as a class method pointer without the static qualifier and it should work just fine.

Another point is that it would be better to use boost::bind if you callback will need some arguments in the subscriber description. (see this answer). But, that's not needed here since you can access your private attribute transform inside the class method callback.

Here's the corrected header code (as obvious as it might be), with adding the node::handler because I don't really know what your node is :

class MyClass
{
    private:
        ros::NodeHandle ph_;
        tf::Transform transform;
        ros::Subscriber subscriber;

    public:
        int publish ();

    private:
        void callback (const std_msgs::Float64MultiArray::ConstPtr& msg);
};

and cpp file :

MyClass::MyClass( ) : ph_("~")
{
    subscriber = ph_.subscribe( "topic_id",
                            1,
                            &MyClass::callback,
                            this);
}

void MyClass::callback(const std_msgs::Float64MultiArray::ConstPtr& msg)
{
    std::vector<double> data(4);
    data = msg.data;

    transform->setRotation( tf::Quaternion(data[0], data[1], data[2], data[3]) );
    publish ();
}

Cheers,

Upvotes: 4

Related Questions