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

Queued messages do not get sent when shutting down a publisher

asked 2012-12-12 20:56:09 -0600

Benoit Larochelle gravatar image

I noticed that when calling publisher.shutdown(), the messages that are queued for publishing simply get destroyed with the publisher. I could not find any documentation that specified this behavior.

It seems unintuitive to me, especially if I compare to other systems. For example, when I write an e-mail, click send, and close the mail application, it will not just delete the e-mail if it is not yet sent.

I know that when ROS started, it was designed to send streams of data where the loss of a few messages was not important, but this is not always the case. In the applications developed in my project for example, every message is important, and many of them are sent only once. I would therefore need a way to shut down a publisher without losing any messages.

Here's an example that shows the problem:

#include <ros/ros.h>
#include <std_msgs/String.h>

int main(int argc, char** argv)
{
    ros::init(argc, argv, "MyPublisher");

    ros::NodeHandle nh("~");

    ros::Rate oneSecond(1);

    int num = 1;
    while(ros::ok())
    {
        ros::Publisher pub = nh.advertise<std_msgs::String > ("/MyTopic", 10);

        // Waits for the subscribers to connect
        oneSecond.sleep();

        std_msgs::String msg;
        std::stringstream ss;
        ss << "Hello World! " << num++;
        msg.data = ss.str();
        pub.publish(msg);

        pub.shutdown();

        // Moving this line above the shutdown solves the problem
        oneSecond.sleep();
    }

    return 0;
}

In that example, the subscribers never get any message, because the publisher gets shut down before its messages get sent. Swapping shutdown() and sleep() solves the problem.

I am wondering how to solve this properly. Waiting a second before every shutdown() in my application is not nice, and is problematic when it is in the GUI thread (the whole GUI would freeze). Also, I am not guaranteed that one second is enough.

edit retag flag offensive close merge delete

Comments

You are correct. Messages do get lost. Most nodes that care about it do something similar to your sleep before shutdown. It would be nice to have a cleaner solution.

joq gravatar image joq  ( 2012-12-13 04:22:39 -0600 )edit

1 Answer

Sort by ยป oldest newest most voted
0

answered 2012-12-12 21:07:23 -0600

Benoit Larochelle gravatar image

updated 2012-12-12 22:03:57 -0600

Solution #1

One possible solution would be to modify shutdown as such:

Publisher::shutdown(bool sendQueuedMessages = false).

Calling shutdown with true would "kill" the instance as usual, but the TopicManager would not call Publication::drop() but rather mark the Publication as isShuttingDown=true.

At the next call to processPublishQueues(), after sending all messages, the TopicManager would call drop() on all Publication instances marked to be shut down.

In the case where a new publisher for the same topic gets created in the mean time (after shutdown but before processPublishQueues), the TopicManager would simply unmark the Publication as shutting down.

Solution #2

Another possibility would be to create a method Publisher::areQueuesEmpty(). The Publisher would ask the TopicManager, which would ask the Publication, which would ask all SubscriberLinks. Only if all queues for all subscribers are empty would the method return true. The developers would then have to manually manage when they shut down the publisher.

edit flag offensive delete link more

Comments

Note that these are not solutions, but rather proposals, none of which are available in ROS Kinetic. I couldn't find any workaround that currently works.

Dinesh gravatar image Dinesh  ( 2016-07-19 09:30:29 -0600 )edit

Question Tools

2 followers

Stats

Asked: 2012-12-12 20:56:09 -0600

Seen: 989 times

Last updated: Dec 12 '12