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

Delay when subscribing to usb_cam/image_raw

asked 2022-10-17 23:59:21 -0500

Gojigu gravatar image

updated 2022-10-18 02:05:11 -0500

I'm having latency issues when using message_filters

After inspection, it was found that it was caused by the delay of the subscribed usb_cam/image_raw.

I used rostopic delay /usb_cam/image_raw to check the delay, the average delay is 0.036s, not sure if this is too long.

Wrote a test program that only subscribes to usb_cam/image_raw, queue_size=1.

class listener:
    def __init__(self):
        self.sub = rospy.Subscriber("usb_cam/image_raw", ImageMsg, self.callback, queue_size=1)

    def callback(self, Cam_img):
        print('---sub---')
        print(Cam_img.header)
        print("================")
        rospy.sleep(3.0)

def main(args):
    rospy.init_node('message_test', anonymous=True)
    ls = listener()
    try:
        rospy.spin()
    except KeyboardInterrupt:
        print("Shutting down")

if __name__ == '__main__':
    main(sys.argv)

The message header is printed every 3 seconds, but the timestamp does not have an interval of 3 seconds after execution.

Here is the output:

---sub---
seq: 47809
stamp: 
  secs: 1666068526
  nsecs: 467627916
frame_id: "c920_camera"
================
---sub---
seq: 47810
stamp: 
  secs: 1666068526
  nsecs: 503613919
frame_id: "c920_camera"
================
---sub---
seq: 47811
stamp: 
  secs: 1666068526
  nsecs: 535569917
frame_id: "c920_camera"
================
---sub---
seq: 47812
stamp: 
  secs: 1666068526
  nsecs: 567602916
frame_id: "c920_camera"
================

How can I reduce the delay?

Thanks in advance.

edit retag flag offensive close merge delete

3 Answers

Sort by ยป oldest newest most voted
1

answered 2022-10-18 16:56:57 -0500

duck-development gravatar image

You can reduce the time if you use au faster PC with less load. Try some real-time kernel settings.

Because your constrains are real-time, but USB is not real-time. There are many software layers. Pictures are a big structure. With small payload and software generated data it is easier to get more consistent data. With the c920 you get maybe compressd images which hast first be converted to raw images, an other processing step.

for topic analysis you may use

rostopic hz  usb_cam/image_raw

as here described to get the analytics.

Otherwise you use python with real-time demands, you have to use c++ for better results

edit flag offensive delete link more

Comments

I think his limits come more from heavy callback than python/C++ raw performances

Vic gravatar image Vic  ( 2022-10-19 06:22:10 -0500 )edit
0

answered 2022-10-19 20:36:37 -0500

Gojigu gravatar image

Thank you all for your explanations and suggestions.

I learned that there shouldn't be too many instructions in the callback that take time to process. Since I am not that familiar with ROS and Python, it may take some time to modify the program.

For I only need to receive an image message once, I will temporarily use rospy.wait_for_message to avoid using image subscribe.

edit flag offensive delete link more
0

answered 2022-10-18 02:29:47 -0500

Vic gravatar image

First, what purpose serves sleeping in your callback? Right now, each message will be put in a queue that waits for the callback to finish before starting again. What you might want to do is printing one message over 20 instead.

edit flag offensive delete link more

Comments

1

Thank you for your reply.

Because there are other tasks in the original program that require execution time, use rospy.sleep to replace the waiting time of other programs.

When using queue_size = 1, shouldn't the latest message be obtained after the callback is completed once?

I found that if the program is executed for a period of time, the step of the timestamp will sometimes be larger, but this situation is irregular

Screenshot

Gojigu gravatar image Gojigu  ( 2022-10-18 02:58:20 -0500 )edit

Because there are other tasks in the original program that require execution time

Try not overloading your callbacks. A callback should be bare-minimum contents, like getting a message and raising a flag (setting a bool to true for example) that the main program will process. A task requiring execution time greater than one millisecond does not belong in a callback.

Vic gravatar image Vic  ( 2022-10-19 06:21:06 -0500 )edit

Because there are other tasks in the original program that require execution time

Try not overloading your callbacks. A callback should be bare-minimum contents, like getting a message and raising a flag (setting a bool to true for example) that the main program will process. A task requiring execution time greater than one millisecond does not belong in a callback.

Vic gravatar image Vic  ( 2022-10-19 06:21:15 -0500 )edit
1

A task requiring execution time greater than one millisecond does not belong in a callback.

that's a rather strong statement which I believe is not necessarily universally true.

There are plenty of (good) nodes doing much more work than what you state would be acceptable in callbacks.

gvdhoorn gravatar image gvdhoorn  ( 2022-10-19 06:29:12 -0500 )edit

Strong statement indeed. Let me reformulate.

A callback's execution time should be less than your node's rate.

Vic gravatar image Vic  ( 2022-10-19 06:43:40 -0500 )edit
1

@Vic is right in that - if you care about performance - then your code needs to spend as little time as possible inside a subscribe callback. As written, your code is locking up the entire ros subsystem for this node - no publishing, no handling of incoming messages, no timers firing for the entire 3 seconds.

The reason your timestamps have unexpected values is that there is message queuing outside of ros. The operating system is buffering incoming messages that are arriving from other ros node(s) - ros begins to handle them when you finally return from the subscribe callback.

Mike Scheutzow gravatar image Mike Scheutzow  ( 2022-10-19 18:51:59 -0500 )edit

@Mike Scheutzow: IIRC rospy uses a more multi-threading approach to handling events (so subscription callbacks). I'm not sure a sleep(..) in one callback blocks event processing completely. It's quite nuanced. See #q9543 fi.

gvdhoorn gravatar image gvdhoorn  ( 2022-10-20 09:41:30 -0500 )edit

@gvdhoorn Thanks for that link. I have just tested multiple publishers to the same topic, and what you say is correct. This is disturbing to me, because 99% of the subscriber callback code that I've reviewed is not thread-safe. The only reason things don't blow up more is because typically a ros topic has only 1 publisher.

Mike Scheutzow gravatar image Mike Scheutzow  ( 2022-10-23 09:29:42 -0500 )edit

Question Tools

2 followers

Stats

Asked: 2022-10-17 23:59:21 -0500

Seen: 321 times

Last updated: Oct 19 '22