Generating communication delay and timing it with ROS subscriber and publisher
I am subscribing to the /odom topic of my turtlebot3 in ROS melodic and Gazebo simulation. I want to do testing on the communication delay with ROS with a constant delay of 50 ms with subscriber and publisher. What are some ways I could do this in my C++ ROS node? Say I want to first subscribe to the /odom topic, then publish a Twist message with a delay of 50ms in addition to the computation time, how would I achieve this? I also want to time the time it takes between first receiving the subscribed /odom topic message, then doing some computation, and then to the time where it gets publish to the cmd_vel topic in the form of a Twist message. What code would I use to time this reliably in my C++ node?
Edit after suggestion in comments: I want to benchmark ROS network performance (ie: inside nodes), or performance of computation (ie: between nodes) via nodes that I created.
Asked by hunterlineage1 on 2023-03-19 02:04:18 UTC
Answers
I think this package called message_filters
can achieve this behavior quite easily.
The
TimeSequencer
filter guarantees that messages will be called in temporal order according to their header's timestamp. TheTimeSequencer
is constructed with a specific delay which specifies how long to queue up messages before passing them through. A callback for a message is never invoked until the messages' time stamp is out of date by at least delay. However, for all messages which are out of date by at least the delay, their callback are invoked and guaranteed to be in temporal order. If a message arrives from a time prior to a message which has already had its callback invoked, it is thrown away.(...)
The C++ version takes both a delay an an update rate. The update rate determines how often the sequencer will check its queue for messages that are ready to be pass through. The last argument is the number of messages to queue up before beginning to throw some away.
message_filters::Subscriber<std_msgs::String> sub(nh, "my_topic", 1);
message_filters::TimeSequencer<std_msgs::String> seq(sub, ros::Duration(0.1), ros::Duration(0.01), 10);
seq.registerCallback(myCallback);
I highlighted the important bit about possible throwaway messages.
Asked by ljaniec on 2023-03-20 03:52:10 UTC
Comments
Could you elaborate on how the OP would make this deterministic enough for his "[..] testing on the communication delay with ROS"? The only way I could see message_filters
working is by either modifying the sources of all nodes that should undergo testing, or write a dedicated, generic and stand-alone node which uses message_filters
to introduce the delay, then republish.
Both options seem like either too invasive, or adding an undesirable non-deterministic aspect to any communication path through the node-graph (ie: it's very hard to schedule async communication and node execution deterministically).
Asked by gvdhoorn on 2023-03-20 04:06:05 UTC
I assumed modifications to the source code, yes, it is intrusive. The question seemed more basic to me, perhaps only for testing the internal network's ability to carry messages in a personal project. This approach does not survive as general repeatable testing for many different nodes. I would like the OP to comment on what technical level is desired here.
Asked by ljaniec on 2023-03-20 05:26:05 UTC
@ljaniec @gvdhoorn It does seem hard to schedule async communication and node execution deterministically. I am able to make modifications to my source code; it can be as intrusive as needed. The technical level desired here is that I should be able to test the internal network's ability to carry messages with different delay times.
Asked by hunterlineage1 on 2023-03-21 12:26:50 UTC
Comments
Quick note: I would suggest to look at using the
tc
command (should be part ofiproute
) instead of doing this at the application level.Asked by gvdhoorn on 2023-03-19 04:12:46 UTC
@gvdhoorn where can I find out more about the tc command from iproute? I tried searching for iproute with ROS and this was the only thing I could find: https://index.ros.org/d/iproute2/
Asked by hunterlineage1 on 2023-03-19 16:16:02 UTC
It's not a ROS package.
iproute
is an Ubuntu package. Information abouttc
can be found in many places, for instance theman
page oftc
. But there are also many blogs/forum posts detailing how to usetc
to introduce artificial latency, package loss, etc to network connections.I would suggest to clarify whether you want to benchmark your own code, whether you are interested in generic benchmarking of a whole ROS application and whether you want to benchmark ROS network performance (ie: inside nodes), or performance of computation (ie: between nodes).
Asked by gvdhoorn on 2023-03-20 03:03:31 UTC