Timestamp origin for zed_wrapper using the stream sender

ZED Box (ZED X) streams RAW VIDEO ONLY (H264, enable_streaming, custom Python sender script using the SDK) to an x86 receiver.
ZED box and x86 are connected via a direct point-to-point Gigabit Ethernet link (no switch/router in between).
Clocks on both machines are synced via chrony.

`On the x86, I’m launching the zed_wrapper ROS 2 node directly against the stream, using:

ros2 launch zed_wrapper zed_camera.launch.py
camera_model:=zedx
stream_address:`

so when i do this the zedbox is only sending the stream and the depth and pointcoud are being generated on the x86 device ryt??
so the header time will be the timestamp given by the zedbox and since im streaming the frames the same images are arrived on the x86 and on the x86 im launching the zedx node using the streamed data so will the frames on the x86 upon arrival have a different timestamp or the same from the zedbox ..

im super confused with that …
im dropping you some csv for reference …
zed_latency_20260911_115817.csv (230.0 KB)
ignore the naming i used in the csv ..

im super confused weather only the images arrive and then on the x86 the wrapper generated the pointcloud and depth ryt so i am subtracting the header time(grab time) with the arrival time(wall time) on the x86 and calculating the latency .. i might be wrong .. please help me with this …

Hi @hamdan11,

Correct. The Local Streaming module transmits only the encoded (H.264/H.265) side by side video, plus the sensors data. On the receiver, the ZED SDK behaves exactly as if the camera were connected locally, so rectification, depth, point cloud, positional tracking and the AI modules all run on the x86 GPU: when a stream is used as input, every module of the ZED API is available on the receiving side.
Reference: Local Video Streaming | StereoLabs

The same. The frame timestamp is generated on the sender when the frame is grabbed, and it travels with the stream; on the receiver, getTimestamp(TIME_REFERENCE::IMAGE) returns the ZED Box timestamp, not the arrival time. The ROS 2 wrapper uses that value for the header.stamp of all the data generated by the same grab (left/right images, depth, disparity, point cloud), because the parameter general.use_pub_timestamps is false by default.

If you set general.use_pub_timestamps: true, the node stamps the messages with the current ROS time on the x86 at publishing time instead. The parameter exists exactly for this kind of test, and comparing the two runs lets you split “sender + network + SDK processing” from “ROS 2 / DDS delivery”:

The method is correct, as long as the two clocks are synchronized, which you are already doing with chrony. What you are measuring is the full chain: grab on the ZED Box, NVENC encoding, network transfer, decoding on the x86, ZED SDK processing (depth and point cloud are computed only if those topics are subscribed), ROS 2 publishing, and DDS delivery to your node.

Three points to be careful about:

  1. The residual offset between the two clocks is a systematic bias added to every sample. chrony with software timestamping typically leaves from a few hundred microseconds up to some milliseconds; check chronyc tracking, and if you ever get negative latency values, that is the offset. If your NICs support hardware timestamping (ethtool -T <iface>), PTP with linuxptp gives much better results on a direct point to point link like yours.
  2. Log one topic at a time. The latency measured on point_cloud/cloud_registered also includes the depth computation and the serialization of a large message, while rgb/image_rect_color is much lighter; mixing them in the same CSV makes the numbers hard to interpret.
  3. The image timestamp is assigned when the frame is available in the SDK buffer on the sender, so the intrinsic camera pipeline latency, fixed and equal to 2-3 frames for GMSL2 cameras like the ZED X, is not included in your measurement. This is explained here, together with how to reduce the end to end latency by increasing general.grab_frame_rate:
    Stereo Node Frequency Tuning | StereoLabs

A quick cross-check that removes all doubts: in your Python sender, print get_timestamp(sl.TIME_REFERENCE.IMAGE) for each grabbed frame; the value must match the header.stamp that you read on the x86 for the same frame.

Best,
Walter

Hi,
Thanks for the clarification but as you can see in the csv file i shared there’s a consistent latency of 100-150ms with `general.use_pub_timestamps: false’ …is that normal ?? with camera being streamed at 60fps..

and also since im just streaming the frames from the zedbox ,only the image frames will be transferred over the network ryt ?? the depth and pointcloud data doesnt stream isnt it i mean the depth and pointcloud will be generated on the frames that arrived from the zedbox correct??

Please note that the correct parameter is debug.use_pub_timestamps.
If this parameter is set to false and you perform a timestamp difference to measure the latency, you get a value that is the sum of the ZED SDK processing time + ROS 2 middleware communication time.
Hence, 100-150ms can be a coherent value, mostly if you are over a network.

I recommed you read these sections of the documentation:

there’s one more issue im facing using the streaming node ..when im running the python file and launching the zed node on the x86 .. in the terminal im getting corrupted frame from the camera grab ..

12.257286647] [zed.zed_node]: Grab status degraded: CORRUPTED FRAME [component_container_isolated-2] [WARN] [1789559012.273077203] [zed.zed_node]: Grab status degraded: CORRUPTED FRAME [component_container_isolated-2] [WARN] [1789559012.288137028] [zed.zed_node]: Grab status degraded: CORRUPTED FRAME [component_container_isolated-2] [WARN] [1789559012.304139442] [zed.zed_node]: Grab status degraded: CORRUPTED FRAME [component_container_isolated-2] [WARN] [1789559012.321323407] [zed.zed_node]: Grab status degraded: CORRUPTED FRAME [component_container_isolated-2] [WARN] [1789559012.339077595] [zed.zed_node]: Grab status degraded: CORRUPTED FRAME

how do i fix this ??
and i verified that the kernel buffers were configured to the max and also jumbo frames are enabled on both the interfaces on the machines .

If you get this warning it means that images are not good.
Can you send sample images to evaluate them?

olated-2] [INFO] [1789707456.895062191] [zed.zed_node]: * Q: [0,0,0,1]
[component_container_isolated-2] [2026-09-18 10:27:37 UTC][ZED][INFO] CORRUPTED FRAME in sl::ERROR_CODE sl::camera::grab(sl::RuntimeParameters)
[component_container_isolated-2] [WARN] [1789707457.043120760] [zed.zed_node]: Grab status degraded: CORRUPTED FRAME
[component_container_isolated-2] [2026-09-18 10:27:37 UTC][ZED][WARNING] Duplicate frame detected
[component_container_isolated-2] [WARN] [1789707457.052996234] [zed.zed_node]: Grab status degraded: CORRUPTED FRAME
[component_container_isolated-2] [WARN] [1789707457.077261858] [zed.zed_node]: Grab status degraded: CORRUPTED FRAME
[component_container_isolated-2] [WARN] [1789707457.089393284] [zed.zed_node]: Grab status degraded: CORRUPTED FRAME
[component_container_isolated-2] [2026-09-18 10:27:55 UTC][ZED][WARNING] Duplicate frame detected
[component_container_isolated-2] [2026-09-18 10:27:55 UTC][ZED][INFO] CORRUPTED FRAME in sl::ERROR_CODE sl::camera::grab(sl::RuntimeParameters) [x4]
[component_container_isolated-2] [WARN] [1789707475.522741869] [zed.zed_node]: Grab status degraded: CORRUPTED FRAME
[component_container_isolated-2] [WARN] [1789707475.539120474] [zed.zed_node]: Grab status degraded: CORRUPTED FRAME







yes i captured the images as soon as the image corruption warning was logged ..
here are the images

This is a false warning indeed.
Can you please record a short SVO (30 seconds is good) and share it with me to test the camera output?

svo_recordings.zip

The images in the SVO are not good, they are clearly overexposed. For this reason the ZED SDK detected corrupted frames.

Please upgrade the ZED SDK to the latest v5.5 to obtain improvements concerning health status checking.