Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Based on the comments from Lorenz, the problem seems to be that the publisher is too fast; that is, it publishes before the subscriber has opened a direct connection to the publisher. Therefore, the goal is to make the publisher "wait" until all subscribers have established a connection. I don't think that the problem stems from closing the publisher too soon.

Here is an idea that I have not tested, but that should work with multiple subscribers. It is not 100% robust, but assuming that no subscribers comes or leaves exactly when the publisher is launched, it should not have problems.

int numSubscribersConnected = 0;

void connectCallback(const ros::SingleSubscriberPublisher& pub)
{
    numSubscribersConnected++;
}

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

    ros::NodeHandle nh("~");

    ros::Publisher pub = nh.advertise<foo::MyMessage>("/myTopic", 100, connectCallback);

    ros::Time maxTime(ros::Time::now()+1000); // Will wait at most 1000 ms

    while(pub.getNumSubscribers()!=numSubscribersConnected && ros::Time::now()<maxTime)
    {
        sleep(10);
    }

    // Now the publisher is ready

    foo::MyMessage msg;
    pub.publish(msg);

    return 0;
}
click to hide/show revision 2
Fixed a typo with the sleep duration

Based on the comments from Lorenz, the problem seems to be that the publisher is too fast; that is, it publishes before the subscriber has opened a direct connection to the publisher. Therefore, the goal is to make the publisher "wait" until all subscribers have established a connection. I don't think that the problem stems from closing the publisher too soon.

Here is an idea that I have not tested, but that should work with multiple subscribers. It is not 100% robust, but assuming that no subscribers comes or leaves exactly when the publisher is launched, it should not have problems.

int numSubscribersConnected = 0;

void connectCallback(const ros::SingleSubscriberPublisher& pub)
{
    numSubscribersConnected++;
}

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

    ros::NodeHandle nh("~");

    ros::Publisher pub = nh.advertise<foo::MyMessage>("/myTopic", 100, connectCallback);

    ros::Rate poll_rate(100);

    ros::Time maxTime(ros::Time::now()+1000); // Will wait at most 1000 ms

    while(pub.getNumSubscribers()!=numSubscribersConnected && ros::Time::now()<maxTime)
    {
        sleep(10);
poll_rate.sleep();
    }

    // Now the publisher is ready

    foo::MyMessage msg;
    pub.publish(msg);

    return 0;
}
click to hide/show revision 3
Noted that the solution would not work because of getNumSubscribers()

Based on the comments from Lorenz, the problem seems to be that the publisher is too fast; that is, it publishes before the subscriber has opened a direct connection to the publisher. Therefore, the goal is to make the publisher "wait" until all subscribers have established a connection. I don't think that the problem stems from closing the publisher too soon.

Here is an idea that I have not tested, but that should work with multiple subscribers. It is not 100% robust, but assuming that no subscribers comes or leaves exactly when the publisher is launched, it should not have problems.

EDIT: This method would not work because a functionality that I expected available from ROS does not seem to be there. See comments in the code.

int numSubscribersConnected = 0;

void connectCallback(const ros::SingleSubscriberPublisher& pub)
{
    numSubscribersConnected++;
}

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

    ros::NodeHandle nh("~");

    ros::Publisher pub = nh.advertise<foo::MyMessage>("/myTopic", 100, connectCallback);

    ros::Rate poll_rate(100);

    ros::Time maxTime(ros::Time::now()+1000); // Will wait at most 1000 ms

    while(pub.getNumSubscribers()!=numSubscribersConnected // This is wrong. It returns only the number of subscribers that have already established their direct connections to this publisher
    //int numExistingSubscribers = pub.getNumSubscribers();

    // This method does not exist, as far as I know. In the comments below, I suggested having a similar functionality. This method would return the number of total subscribers to this topic over the ROS network
    int numExistingSubscribers = ros::getNumSubscribers("/myTopic");

    while(numExistingSubscribers!=numSubscribersConnected && ros::Time::now()<maxTime)
    {
        poll_rate.sleep();
    }

    // Now the publisher is ready

    foo::MyMessage msg;
    pub.publish(msg);

    return 0;
}