Approximate Time Synchronizer callback not working in node member class (sync goes out of scope)

asked 2020-06-06 12:15:11 -0600

ignacioalvmar gravatar image

updated 2020-06-09 14:29:47 -0600

Hi folks,

I've been trying to solve this for a while without success. Basically I have a node with several class members and in one of those classes I need to process data from 3 synced topics. I am using Approximate Time Synchronizer. My problem is that the synced callback only gets called once or twice and then stops (sync goes out of scope).

I'll put a simplified version of the node below. The structure is node.cpp instanciates member class A. Class A has a multi-threaded loop. Inside that loop I instanciate ClassB, declare the subscribers and Approximate synchronizer and set the callback for the synchronizer to point to ClassB's function so I can process that data in class B.

I don't know where to create the synchronizer. First I tried having it directly in class B but declaring it in classB's constructor or one of classB's functions got only 1 successful call before sync was destroyed.

As you see below in classA.cpp, now I have put the sync in the loop function where i get it to successfully callback a few times but it eventually stops. I would like to put it in the main funcion of node.cpp like in this example, but I need to pass to the callback the ClassB environment and I need to do that after a bunch of other things happen in Class A.

I appreciate your advice!

node.cpp:

 #include <ros/ros.h>
 #include <node/ClassA.h>
 #include <tf2_ros/transform_listener.h>
 int main(int argc, char** argv){
    ros::init(argc, argv, "node");
    tf2_ros::Buffer buffer(ros::Duration(10));
    tf2_ros::TransformListener tf(buffer);
    node::ClassA lcr("node", buffer);
    ros::spin();
    return (0);
}

class A.h:

#include <node/classB.h>
#include <message_filters/sync_policies/approximate_time.h>
#include <message_filters/subscriber.h>
#include <message_filters/synchronizer.h>
#include <msgs/msgType.h>

using namespace message_filters;

namespace node
{
    Class A
   {
    public: 
        ClassA();
       ~ClassA();
    protected:
        Object* b_;
    private:
        void loop(node::Config &config, double frequency);
        ClassB * b_;
        message_filters::Subscriber<msgs::msgType> subscriber_A;
        message_filters::Subscriber<msgs::msgType> subscriber_B;
        message_filters::Subscriber<msgs::msgType> subscriber_C;
        typedef sync_policies::ApproximateTime<msgs::msgType, msgs::msgType, msgs::msgType> MySyncPolicy;
        typedef Synchronizer<MySyncPolicy> Sync;
        boost::shared_ptr<Sync> sync;
    };
}

classA.cpp:

#include <message_filters/subscriber.h>
#include <message_filters/synchronizer.h>

using namespace message_filters;

namespace node
{
    ClassA::ClassA():
         thread_shutdown_(false)
    { // Constructor for classA
    }
     ClassA::~ClassA(){
          thread_shutdown_ = true;
    }

    objectB_ = new Object ();
    function1();
   }

   void ClassA::function1(){
       // ...
        thread_ = new boost::thread(boost::bind(&ClassA::loop, this, config, loop_frequency));
   }

   void ClassA::loop(node::NodeConfig &config, double frequency){
       ros::NodeHandle nh;

       ros::NodeHandle nh_B("~/" + name_);
       ClassB * b_ = new ClassB(&nh_B, objectB_); // Initialize ClassB instance

       subscriber_A.subscribe(nh_B, "topic1", 1);
       subscriber_B.subscribe(nh_B, "topic2", 1);
       subscriber_C.subscribe(nh_B, "topic3", 1);
       sync.reset(new Sync(MySyncPolicy(20), subscriber_A, subscriber_B, subscriber_C));
       sync->registerCallback(boost::bind(&ClassB::subscribe_synced_callback, b_, _1, _2, _3)); // this gets callback called twice

       while (nh.ok() && !thread_shutdown_)
       {
           //sync->registerCallback(boost::bind(&ClassB::subscribe_synced_callback, b_, _1, _2, _3)); // this gets callback called a few times and then stops
        // do stuff
       }
   }
}

class B.h:

#include <message_filters/sync_policies/approximate_time ...
(more)
edit retag flag offensive close merge delete

Comments

1

Where does thread_shutdown_ come from?

Suggestion: use fewer raw pointers and new. C++ is not Java.

gvdhoorn gravatar image gvdhoorn  ( 2020-06-06 12:22:37 -0600 )edit

It's a bool flag with false by default and it is turned "true" in Class A's destructor. I've updated it in the question to make it clear :)

ignacioalvmar gravatar image ignacioalvmar  ( 2020-06-06 13:35:31 -0600 )edit