Ask Your Question
1

General Subscriber's Callback in C++

asked 2011-09-20 03:52:44 -0500

safzam gravatar image

Hi all, Is there any way to make one general callback in c++ that can be executed for every subscriber? I mean every callback needs type of the message but I want one callback that should be generally and dynamically executable for all subscriber. I can do this in python but need to do in c++. Has someone done this? Thanks in advance, regards, safdar

edit retag flag offensive close merge delete

Comments

Can you be a little clearer about what you mean by a generally and dynamically executable callback? The roscpp implementation is designed to take advantage of C++ types and requires you to know the type of the function to call back. Maybe your use case or what you are doing in python would help.
tfoote gravatar image tfoote  ( 2011-09-20 18:33:08 -0500 )edit
I mean , for example I have two different nodes publishing one publishes int type message on toip1 and other publishes on topic2. Now I need to make certainly two subscriber s1 for topic1 and s2 for topic2. But I want to have one callback for both of these s1 and s2. Is it possible in C++? regards
safzam gravatar image safzam  ( 2011-09-20 20:13:41 -0500 )edit

4 Answers

Sort by ยป oldest newest most voted
1

answered 2011-09-21 00:14:36 -0500

If both topics publish the same message type, you can definitely use the same callback for both subscriptions, although you won't be able to tell which message came from which topic.

Otherwise, you could always delegate the work to a third function, like this:

void processInt (int a)
{
  // Lots of computation here
}

void callback1 (MyMessageConstPtr msg)
{
  processInt (msg->int_value);
}

void callback2 (MyOtherMessageConstPtr msg)
{
  processInt (msg->other_int_value);
}

int main (int argc, char** argv)
{
  ros::init (argc, argv, "my_node");
  ros::NodeHandle node;
  ros::Subscriber s1 = node.subscribe<MyMessage>("topic1", 1, callback1);
  ros::Subscriber s2 = node.subscribe<MyOtherMessage>("topic2", 1, callback2);
  ros::spin();
  return 0;
}
edit flag offensive delete link more

Comments

Hi, I have done the same way before but it needs as many functions as we have different datatypes which I dont know in prior for example. So I want to avoid all so many functions. Is there other way?
safzam gravatar image safzam  ( 2011-09-21 04:16:04 -0500 )edit
In C++ you need to know the data types when writing the program if you want to work with the data in the messages.
Lorenz gravatar image Lorenz  ( 2011-09-21 04:50:41 -0500 )edit
0

answered 2011-09-21 03:49:28 -0500

It might be dirty, but you can try with:

void callback(void* data) {
    static_cast<MyMessageConstPtr>(data) //if you need to
}

but I will strongly advice against this.

edit flag offensive delete link more

Comments

This works only if data is always a MyMessageConstPtr, and then you could have gone ahead and used the correct parameter type in the first place. Alternatively, you could use a templated callback.
roehling gravatar image roehling  ( 2011-09-21 04:03:30 -0500 )edit
Hi it seems to me fine, but it does not work with me and gives error like '__s_getDataType' is not a member of 'void*'...I also changed it and tried other way round like void callbak(void data) and callback(void *data) but none of them worked :-(. Can you please fix it? thanks
safzam gravatar image safzam  ( 2011-09-21 04:20:12 -0500 )edit
callback(void *data) works. You just need to cast the function pointer when subscribing, e.g. nh.subscribe<Int32>("topic2",1,reinterpret_cast<void (*)(Int32ConstPtr)>(&callback)). However, I don't understand why you want to do this since the data pointer in the callback will be useless.
Lorenz gravatar image Lorenz  ( 2011-09-21 04:45:55 -0500 )edit
Thanks.It works. Now if I provide topic name and type on commandline. Topicname works but type gives error. Like nh.subscribe<Int32>(argv[1],1,reinterpret_cast<void (*)(argv[2])>(&callback)). Is it possible to give commandline topic name and msg_type? I want to have only 1 dynamic subscriber.Thnx
safzam gravatar image safzam  ( 2011-09-22 02:54:35 -0500 )edit
you could, but then in the code you will have a big IF-THEN cascade for all the possible message types. Unfortunately C++ does not have the level of introspection Python enjoys.
Lorenzo Riano gravatar image Lorenzo Riano  ( 2011-09-22 05:03:43 -0500 )edit
Thank you very much for the guidance :-). regards
safzam gravatar image safzam  ( 2011-09-24 03:33:59 -0500 )edit
No problem! For the community benefit, you should select the right answer (if the problem is solved) and thumbs up for the good ones. Maybe an edit of your original post with the final solution you chose will be good as well.
Lorenzo Riano gravatar image Lorenzo Riano  ( 2011-09-25 03:52:03 -0500 )edit
0

answered 2011-09-21 04:51:32 -0500

You could use templates if all your messages have a common member variable which you need. Let's say it is an int called int_value. Then you could write

void processInt (int a)
{
  // Your real work goes here again
}

template<typename MsgPtr>
void genericCallback (MsgPtr m)
{
  processInt (m->int_value);
}

I'm still not sure what you want to achieve, though. If you have lots of messages with basically the same layout, why not use just one message and add an extra variable that encodes the intended type?

edit flag offensive delete link more
-1

answered 2011-09-20 20:13:19 -0500

safzam gravatar image

Hi tfoote, I mean , for example I have two different nodes publishing one publishes int type message on toip1 and other publishes on topic2. Now I need to make certainly two subscriber s1 for topic1 and s2 for topic2. But I want to have one callback for both of these s1 and s2. Is it possible in C++? regards

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

Stats

Asked: 2011-09-20 03:52:44 -0500

Seen: 2,436 times

Last updated: Sep 21 '11