Ask Your Question
0

does ROS support callback-on-subscription?

asked 2021-02-03 06:51:36 -0500

LukeAI gravatar image

My basic problem is that there is a chain of nodes all doing heavy computational work and all publishing the results to lots of intermediate topics. At any one time, only a small number of the final output topics will actually be needed so it would be great if the information about which computation is necessary could ripple back through the network of nodes with each node automatically unsubscribing to the inputs that aren't relevant to the given outputs, and then resubscribing again as and when they recieve new subscribers to the relevant topic.

(I know lazy publishing is a thing, and you can check how many subscribers there are before doing the computational work needed to publish on a topic - but that doesn't help here with chains of nodes)

What I want could be achieved if I could have a callback triggered in the event of a new subscription/unsubscription. I could hack this with timers and polling getNumSubscribers() but callbacks would be much better.

C++/melodic

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
1

answered 2021-02-03 07:15:58 -0500

gvdhoorn gravatar image

updated 2021-02-03 07:18:37 -0500

(note: you tagged this with melodic, so this is a ROS 1 answer)

You can use subscriber status callbacks for this. See #q335811 and #q11327.

For the details, see the documentation for NodeHandle::advertise<..>(..):

Advertise a topic, with most of the available options, including subscriber status callbacks

This call connects to the master to publicize that the node will be publishing messages on the given topic. This method returns a Publisher that allows you to publish a message on this topic.

This version of advertise allows you to pass functions to be called when new subscribers connect and disconnect. With bare functions it can be used like so:

void connectCallback(const ros::SingleSubscriberPublisher& pub)
{
  // Do something
}
handle.advertise<std_msgs::Empty>("my_topic", 1, (ros::SubscriberStatusCallback)connectCallback);

With class member functions it can be used with boost::bind:

void MyClass::connectCallback(const ros::SingleSubscriberPublisher& pub)
{
  // Do something
}

MyClass my_class;
ros::Publisher pub = handle.advertise<std_msgs::Empty>(
  "my_topic", 1, boost::bind(
    &MyClass::connectCallback, my_class, boost::placeholders::_1));

The callback will be called whenever subscription state changes.

At any one time, only a small number of the final output topics will actually be needed so it would be great if the information about which computation is necessary could ripple back through the network of nodes with each node automatically unsubscribing to the inputs that aren't relevant to the given outputs, and then resubscribing again as and when they recieve new subscribers to the relevant topic.

(I know lazy publishing is a thing, and you can check how many subscribers there are before doing the computational work needed to publish on a topic - but that doesn't help here with chains of nodes)

From your description it does sound like services or actions would be a better choice for the kind of interaction you're trying to implement.

If work should be done when a client wants it, publish-subscribe is not the best pattern to use, as it completely decouples everything, including when something is to be done (ie: the time dimension).

Services and actions place the client firmly in control over when work should be performed.

Using creation and destruction of subscriptions to signal that seems like a poor substitute.


Edit: an alternative could be to use ros::topic::waitForMessage(..) and create your "chain" like that.

Seems even nastier though.

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

1 follower

Stats

Asked: 2021-02-03 06:51:36 -0500

Seen: 31 times

Last updated: Feb 03