ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

How to subscribe to a topic at will/on demand?

asked 2012-07-06 04:18:16 -0500

Nishant gravatar image

updated 2012-07-06 05:59:53 -0500

Hello all.

As indicated by the quick response of catagay and Lorenz to my previous question here

I started reading up on how to create publishing and subscribing agents, on the ros tutorials page.

Here is what I understood from the tutorial:

1) The publisher in the example keeps on publishing forever.

2) advertise<std_msgs::string>() is the harbinger of the topic to be published. So this step seems necessary.

3) chatter_pub.publish(msg) is the guy who does the talking. Since he is in a while(ros::ok()), this will publish forever.

4) The subscriber also keeps on subscribing forever.

5) ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback); tells the master to subscribe to the topic and call chatterCallback whenever there is a new message. Because of ros::spin(), however, this subscriber will continue listening to the topic and printing to the screen forever (till node dies, of course).

Based on these points, here are my related questions:

1) Is my understanding enumerated in the points above right? Or am I missing something?

2) What do you mean by " chatterCallback whenever there is a new message."? What does new message mean here? Does it mean that the function is called whenever the message on the topic is updated?

3) Suppose the publisher wants to keep on publishing the topic forever, but the subscriber wants to get messages from the topic only at select locations in my code. Say I want the subscriber to listen to a topic, extract a string from the message, convert it to an integer using atoi() and then print to screen. But I want it to do this in a for loop, while a particular condition in it holds. Is this possible?

4) Can I pass more arguments to the chatterCallback function? say instead of

void chatterCallback(const std_msgs::String::ConstPtr& msg);

I want it to be

void chatterCallback(const std_msgs::String::ConstPtr& msg, int &i, char c);

Is this possible? If yes, what changes do I need to reflect in the argument for the callback function for subscribe()?

5)I ask the above question (4) because I want some way, in which I can bring the result of all that I do in my callback function, into my main() function. Is there a way in which I can do this?

6)In the ROS tutorial I described above, there are the following few lines which escape my understanding. Any idea as to what they mean?

The message is passed in a boost shared_ptr, which means you can store it off if you want, without worrying about it getting deleted underneath you, and without copying the underlying data.

I somehow feel the above lines are related to my questions (4) and (5) above.

7) What happens if I don't use ros::spin() at all, in my subscriber code? Does that mean that the ... (more)

edit retag flag offensive close merge delete



Thanks dornhege. In your response to (3), do you mean that being in the callback is like being in main() itself? Which means variables created and assigned values in the callback continue to exist in main()..?

Nishant gravatar image Nishant  ( 2012-07-06 04:46:19 -0500 )edit

No, the callback is just a function where you react on a new message and do whatever you want - including ignoring it by doing nothing.

dornhege gravatar image dornhege  ( 2012-07-06 04:48:41 -0500 )edit

It might help to split up multiple questions in different "question threads", otherwise there will be multiple mixed answers.

dornhege gravatar image dornhege  ( 2012-07-06 04:49:46 -0500 )edit

Your response to (5) is what I was really looking for. Also, I shall keep in mind to post multiple questions on different threads. I posted all in one, because I thought they were closely related. Thanks! :)

Nishant gravatar image Nishant  ( 2012-07-06 04:56:43 -0500 )edit

Thanks joq! Is that what Thomas D's comment means in the question I referred to above?

Nishant gravatar image Nishant  ( 2012-07-06 05:58:16 -0500 )edit

Yes, that is related.

dornhege gravatar image dornhege  ( 2012-07-07 05:49:34 -0500 )edit

2 Answers

Sort by ยป oldest newest most voted

answered 2012-07-06 04:39:49 -0500

dornhege gravatar image

updated 2012-07-06 04:57:55 -0500

Lorenz gravatar image
  1. In general, yes. Regarding 4) technically it is subscribed once and the callback is called as often as new messages arrive.

  2. for each message someone else publishes on the same topic, the callback is called.

  3. Once you are in the callback function, you are running your code. If you want to skip certain messages, or react to your own code, you can just return from the callback. There is also the possibility to unsubscribe() the subscriber and then the callback will not be called anymore.

  4. The answer to this is: use boost::bind. For your example this probably looks like this (unchecked):

    boost::bind(&chatterCallback, _1, boost::ref(i), c);

  5. Usually the callback would be preferred for structure. If you want to handle something in your main loop, you could either set some global variable currentMessage in you handler and use that or pass a reference to the (local) current message using boost::bind that is updated by the handler.

  6. You should read up on shared pointers to understand that meaning. In short: You can pass the pointer around as you like without this taking time, but you don't need to care about memory management.

edit flag offensive delete link more



The usual solution to sharing information between a callback and other parts of your program is to define the callback as a class method. Then, it has access to all the class data.

joq gravatar image joq  ( 2012-07-06 05:14:36 -0500 )edit

as regard the point 3: how can i unsubscribe from a topic for, for instance, subscribe from another one using the same callback?

mateo_7_7 gravatar image mateo_7_7  ( 2013-06-12 00:29:00 -0500 )edit

For unsubscribing the Subscriber class provides a shutdown() method. Subscribing from another one is just the same as normally, no need to do anything special.

dornhege gravatar image dornhege  ( 2013-06-12 00:35:18 -0500 )edit

the problem is that, to subscribe from another topic (chosen runtime) my subscriber should be defined in a scope that "lives" sufficiently for the process of reading from the topic (it is the reason, i think, the subscribers are define in the main, before the while) but, in the same time,

mateo_7_7 gravatar image mateo_7_7  ( 2013-06-12 03:07:26 -0500 )edit

in a scope that gives me the possibility to update the topic (so a sort of loop)...i really don't know how to do that

mateo_7_7 gravatar image mateo_7_7  ( 2013-06-12 03:09:12 -0500 )edit

answered 2013-07-02 07:44:17 -0500

Phuicy gravatar image

If you are still wanting a solution, I have a package which can be used on demand connect nodes? With a lot customization, such as specifying what happens if not all subscriptions are specified. C++ and Python. External controller api inpython.

edit flag offensive delete link more

Question Tools


Asked: 2012-07-06 04:18:16 -0500

Seen: 10,036 times

Last updated: Jul 02 '13