fix frame timestamps to use a comparable epoch
steady_clock's epoch is unspecified and typically counts from process start or boot, so the published timestamp_ns could not be compared against another node's timestamps, wall clock or a recording — and it recorded when the node processed the frame rather than when the camera captured it. Publish two keys on every output instead: device_timestamp_ns from sl::Camera::getTimestamp(TIME_REFERENCE::IMAGE), and host_timestamp_ns from system_clock. Both are Unix-epoch nanoseconds, set as dora timestamp parameters. The SDK clock source is pinned to SYSTEM_CLOCK at construction, since it is process-wide and decides the epoch of the device value. Both are kept because the wall clock can step when NTP synchronises after boot on a Jetson, while the device timestamp is what two nodes reading the same frame can agree on. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y7g2cBJ5e3r15ZbJ9WZn8c
This commit is contained in:
@@ -119,6 +119,27 @@ All behavior is controlled via environment variables.
|
||||
|
||||
| Output | Type | Description |
|
||||
|---|---|---|
|
||||
| `image_bgr` | `uint8 [H, W, 3]` | BGR image. Metadata: `shape`, `encoding=bgr8`, intrinsics, `timestamp_ns`. |
|
||||
| `point_cloud` | `float32 [*, 4]` | XYZRGBA point cloud. Shape depends on `ZED_PC_MODE`. Metadata: `units=mm`, intrinsics. |
|
||||
| `camera_info` | `float32 [4]` | `[fx, fy, cx, cy]`. Metadata: `distortion` coefficients. |
|
||||
| `image_bgr` | `uint8 [H, W, 3]` | BGR image. Metadata: `shape`, `encoding=bgr8`, intrinsics, timestamps. |
|
||||
| `point_cloud` | `float32 [*, 4]` | XYZRGBA point cloud. Shape depends on `ZED_PC_MODE`. Metadata: `units=mm`, intrinsics, timestamps. |
|
||||
| `camera_info` | `float32 [4]` | `[fx, fy, cx, cy]`. Metadata: `distortion` coefficients, timestamps. |
|
||||
|
||||
### Timestamps
|
||||
|
||||
Every output carries both clocks, as dora `timestamp` metadata parameters:
|
||||
|
||||
| Key | Epoch | Unit | Source |
|
||||
|---|---|---|---|
|
||||
| `device_timestamp_ns` | Unix epoch (UTC) | nanoseconds | `sl::Camera::getTimestamp(TIME_REFERENCE::IMAGE)` — when the camera captured the frame |
|
||||
| `host_timestamp_ns` | Unix epoch (UTC) | nanoseconds | `std::chrono::system_clock` on the host — when this node published the frame |
|
||||
|
||||
Both are needed. The device timestamp is the capture instant and is the value two
|
||||
nodes reading the same frame agree on; the host timestamp is the one the rest of the
|
||||
dataflow and the session recorder share. On a Jetson the wall clock can step when NTP
|
||||
synchronises after boot, so the device timestamp is recorded alongside the host one
|
||||
rather than in place of it.
|
||||
|
||||
The node calls `sl::setTimestampClock(SYSTEM_CLOCK)` before opening the camera, which
|
||||
is what makes the device timestamp a Unix-epoch value rather than an SDK-default clock.
|
||||
|
||||
Every output for a frame also carries the same `frame_id`, an integer counter starting
|
||||
at 0.
|
||||
|
||||
Reference in New Issue
Block a user