Robotics StackExchange | Archived questions

Using Realtime Publisher in a for-loop

Hi everyone,

I don't have much experience with Realtime Publishers yet. So I can't understand the following behaviour:

I have a map of messages and want to publish each of them in a for-loop. For some reason, the following works as supposed:

  for (auto& msg : map)
  {
    ROS_INFO("hello");
    msg.second.header.stamp = ros::Time::now();
    if (rt_publisher_->trylock())
    {
      rt_publisher_->msg_ = msg.second;
      rt_publisher_->unlockAndPublish();
    }
  }

The map contains about seven elements and the loop is called at 100 Hz.

If I comment out the ROS_INFO it won't work. That is, there's no error, the messages just aren't being published. This does not depend on the publisher's queue size. So my guess is that the publisher needs some time between to runs? What would be the best way to implement this?

Asked by labude on 2022-09-17 05:23:01 UTC

Comments

Please explain why you chose a Realtime Publisher. How many messages per second are you trying to publish?

Asked by Mike Scheutzow on 2022-09-17 11:20:22 UTC

I've only seen this behaviour (ie: lost messages) with publishers (real-time or not) if the queue size is too small.

The fact adding a ROS_INFO(..) changes the behaviour you observe does seem to point in the direction of subscribers taking longer than you give them to receive the messages.

How many elements are in map on average? And what's the size of the queue?

Asked by gvdhoorn on 2022-09-17 12:03:50 UTC

The loop is called 100 times per second, iterating over ~7 elements in the map. I tested it with queue sizes ranging from 1 to 1000, all with the same result.

I have to use the realtime publisher because the code shown is part of a ros controller requiring real time. To verify that the problem is due to the rt publisher I replaced it with the 'normal' publisher and everything worked well.

Asked by labude on 2022-09-17 17:44:43 UTC

Answers

  1. You really should look at the implementation of trylock() and unlockAndPublish(). I doubt it's what you want, and the queue size is 1.
  2. The way your code is using trylock() is going to randomly discard messages.
  3. Attempting to send 700 messages per second through a ros publish/subscribe connection is a bad idea. It's unlikely to behave well.

Asked by Mike Scheutzow on 2022-09-18 10:43:56 UTC

Comments

You're right, I think the problem was that trylock() can't be called so fast in the for loop. Inserting a ROS_INFO() added a little delay so that locking and unlocking worked properly.

I solved the problem by concatenating all messages to a single big message (which in my case didn't matter to the subscriber) and publishing only that message at 100Hz.

Asked by labude on 2022-09-28 08:44:11 UTC