Skip to content

sensing: answer the PC's clock exchange and stamp frames with a documented time - #1437

Closed
gareth-morgan-nv wants to merge 10 commits into
gmorgan/Argusfrom
gmorgan/TimestampAlignment
Closed

gareth-morgan-nv wants to merge 10 commits into
gmorgan/Argusfrom
gmorgan/TimestampAlignment

Conversation

@gareth-morgan-nv

@gareth-morgan-nv gareth-morgan-nv commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The camera-side half of the timing work: the Sensing producer (camera_plugin_sensing) answers the PC's clock exchange and stamps each frame with a documented time, so the PC can place camera video on its own clock. The egocap side (recorder, page, emulator) is in the PR stacked on this one.

  • Clock exchange. Answers the PC's four-timestamp clock-sync requests over LiveKit data messages with the sender's monotonic clock; the wire format is tested against golden bytes.
  • Frame timestamps. --timestamp-basis selects monotonic_us (default; the frame-ready time), capture_monotonic_us (the sensor capture event on CLOCK_MONOTONIC, converted from the SIPL counter or the Argus sensor timestamp through a 1 Hz anchor; the stream fails on an implausible value) or processing_unix_us. The encoder unit's own stamp is published, and pacing follows the frame's stamped clock, not the poll time.
  • SENSING_ENCODER_TIMESTAMP_PROBE=1 logs the stamps the encoder returns.

Limits

  • Frame-ready time is later than the sensor's capture event; neither basis proves physical alignment between camera, glove and controllers.
  • The encoder returns no submitted timestamp, so units are paired with captures by submission order; this can shift after an encoder-internal drop, so per-frame times are not hardware-qualified.

Validation

  • src/plugins/sensing/tests gained clock-sync wire-format and sensor-clock tests; they were not built or run for this split.
  • Not run: the native sender and the Argus/SIPL paths were not built against the SDKs, nothing ran on an Orin, and the sensor-counter conversion (capture_monotonic_us) is unverified on hardware.

Stacked on #1429 (Argus), which stacks on #1428 (RearchBackend) and #1461 (the Orin publisher). The egocap half is #1459.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

@ivany-nv ivany-nv added the NVIDIA label Nov 5, 2026
@gareth-morgan-nv
gareth-morgan-nv force-pushed the gmorgan/TimestampAlignment branch from ba2d1d7 to b7d8f99 Compare November 6, 2026 01:42
@gareth-morgan-nv
gareth-morgan-nv force-pushed the gmorgan/TimestampAlignment branch from b7d8f99 to be24085 Compare November 6, 2026 05:39
@gareth-morgan-nv
gareth-morgan-nv force-pushed the gmorgan/TimestampAlignment branch from be24085 to fbdc7e3 Compare November 6, 2026 05:42
@gareth-morgan-nv
gareth-morgan-nv force-pushed the gmorgan/TimestampAlignment branch from c6f0635 to d9d408f Compare November 6, 2026 18:04
@gareth-morgan-nv
gareth-morgan-nv force-pushed the gmorgan/TimestampAlignment branch from d9d408f to 0dc1c08 Compare November 6, 2026 20:31
@gareth-morgan-nv
gareth-morgan-nv force-pushed the gmorgan/TimestampAlignment branch 2 times, most recently from 30c47c3 to 47356b6 Compare November 8, 2026 22:37
@gareth-morgan-nv
gareth-morgan-nv force-pushed the gmorgan/TimestampAlignment branch 6 times, most recently from 6e2ba3f to 0c5c6e0 Compare November 8, 2026 23:29
@gareth-morgan-nv
gareth-morgan-nv force-pushed the gmorgan/TimestampAlignment branch from 9c5d6e5 to 4465d5d Compare November 9, 2026 23:26
@gareth-morgan-nv gareth-morgan-nv changed the title egocap, sensing: align camera, glove and controller time; show latency and fps sensing: answer the PC's clock exchange and stamp frames with a documented time Nov 9, 2026
@gareth-morgan-nv
gareth-morgan-nv force-pushed the gmorgan/TimestampAlignment branch from 4465d5d to 85b7158 Compare November 10, 2026 02:17
gareth-morgan-nv and others added 8 commits November 10, 2026 14:38
The LiveKit session parses four-timestamp requests (topic
isaaccapture.clock-sync, 13 bytes) in onUserPacketReceived, stamps t2 first on
CLOCK_MONOTONIC, and a small responder thread sends the 29-byte reply to the
requester only, unreliable, with t3 written just before the send. The queue is
bounded; anything else is ignored. The wire format is in clock_sync.hpp. The
frames still declare processing time. Syntax-checked against the pinned SDK
v1.12.4 headers here; not built or run on a Jetson.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
… the Python side

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
…e the encoder's returned stamps

--timestamp-basis=capture_monotonic_us converts the backend's sensor timestamp
(SIPL capture counter as generic-counter ticks, Argus sensor timestamp as
CLOCK_MONOTONIC_RAW ns) through a low-rate anchor pair and fails the stream on
an implausible conversion; the default stays processing time. The units are
assumptions checked per frame, not verified on hardware.
SENSING_ENCODER_TIMESTAMP_PROBE=1 logs returned unit stamps beside the last
submitted one. Host tests cover the mapping.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
…racking times mean

ClockEstimator.mapping(now) grows the uncertainty with the age of the exchange,
so the recording budget cannot pass on a figure from before a reply gap. The
take's timing evidence names what each tracking source's time is (host poll;
controller pose-evaluation time; Manus host time at push) and that physical
alignment is unavailable. The native capture_monotonic_us option is described as
unverified.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
… default

The native sender publishes its monotonic frame-ready time (monotonic_us) by
default; recording accepts that basis alongside the sensor-capture basis, the
take's timing evidence names which, and the page computes latency from either.
The agent-only plan notes move to the git-ignored agentPlans/ folder. Tests
extend the saved-artifact timeline fixture over both bases.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
… no longer exists

FrameMeta lost stamp_us when the application timestamp moved to unix_us; the
frame's own timestamp is the unit's.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
Pacing used the time the polling loop collected a frame, so poll phase jitter could
drop a frame that was due. Compute the sensor capture time before the pacing gate
when that is the published basis and pace on it; otherwise pace on the backend's
hand-over time. A pacing clock that steps back restarts pacing instead of holding
every frame until it catches up.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
track_in_flight pushed a monotonic stamp this branch's FrameMeta does not carry, and
publish_unit used a stamp_us local that the encoder-correlation change had removed.
Push the three fields the struct has, and take the transport timestamp from the
encoder's own unit stamp again.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Gareth Morgan <gmorgan@nvidia.com>
@gareth-morgan-nv

Copy link
Copy Markdown
Contributor Author

Closing as superseded: the camera path is now the camera_streamer architecture (SIPL/Argus sender, AVS1 over TCP, PC receiver and LiveKit bridge; see #1473-#1479). Not merged; the branch and commits are kept.

🤖 Generated with Claude Code

@gareth-morgan-nv

Copy link
Copy Markdown
Contributor Author

This PR is superseded by the camera_streamer PRs:

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants