Latency Measurement

OCP measures round-trip latency by sending a timestamp from the vehicle, through the operator, and back. If the measured latency exceeds the configured latency_limit (default 500ms), OCP raises the HighLatency fault. See Faults for details.

Timestamp round-trip

The timestamp travels through the following path:

  • Vehicle OCP generates timestamp - OCP creates ack_time (an elapsed-time timestamp) and ack_time_mac (a MAC computed with a private key that is randomized on system start). These are included in the control message sent to the vehicle integration code over TCP.

  • Vehicle integration code echoes timestamp - Your code receives the control message, copies ack_time and ack_time_mac into the response message, and sends it back to OCP over the same TCP connection. See Vehicle side for the message format.

  • OCP embeds timestamp in video - OCP takes the returned timestamps and embeds them as metadata (SEI) in the outgoing video stream.

  • Video is transmitted - Oden transmits the video from vehicle to operator.

  • Operator OCP extracts timestamp - OCP on the operator side makes the timestamp available to the operator environment (web view or shared data).

  • Operator echoes timestamp back - The timestamp is returned to OCP on the operator side. How this happens depends on the operator configuration.

  • Timestamp sent to vehicle - OCP includes the returned timestamp in the next control message sent back to the vehicle.

  • Vehicle OCP validates and measures - OCP validates the timestamp via the MAC to ensure the timestamp was not tampered with, then computes the round-trip latency as current_time - returned_ack_time.

The ack_time and ack_time_mac values must be passed through unmodified at every step. The either is validated on the vehicle; if it does not match, the timestamp is rejected and latency measurement will not work.

The measured latency includes: vehicle integration processing time, video transmission latency including network, and operator processing time.

Operator configurations

On the operator side, OCP reads the gamepad directly and sends it as controller input unless ocp_disable_gamepad is set (see Disabling OCP gamepad input). The timestamp echo-back and optional user data depend on how the operator side is configured.

There are four configurations. In all cases, OCP handles the gamepad — the difference is in how timestamps are echoed back and how user data flows.

OCP only (no web view, no custom plugin)

OCP reads the gamepad and sends control commands. OCP handles the timestamp round-trip internally by extracting the timestamp from the incoming video stream and echoing it back in the next control message. Latency measurement works out of the box. No user data is sent.

This is the simplest configuration.

Web view

When a web view is active, the web view handles the timestamp echo. OCP still reads and sends gamepad input by default.

The web view handles two cases automatically:

  • No custom JS sends data: The web view auto-echoes the timestamp on its own. No user data is sent.

  • Custom JS calls sendNamedUserMessage: The web view stops auto-echoing and instead injects the timestamp into each sendNamedUserMessage call. Custom data can be sent to the vehicle.

odenClient.sendNamedUserMessage("ocp_client_user_data", {
  active_vehicle: "my_vehicle",
  client_user_data: {
    "my_vehicle": {
      user_data: { steering_mode: "manual" },
      ocp_disable_gamepad: false
    }
  }
});

See Operator side for the full web view API.

Player-side TCP

An external application connects to the player-side TCP server and handles the timestamp echo. The application reads ack_time and ack_time_mac from the vehicle feedback data and returns them as ack_time_returned and ack_time_mac_returned in the client data message. See Player side TCP for details.

Custom operator plugin (no web view)

A custom Oden plugin handles the timestamp echo and can provide its own user data. The plugin uses shared data channels to communicate with OCP:

Reading from OCP

The plugin reads the vehicle_ocp shared data, which contains VehicleFeedbackData including ack_time (u64) and ack_time_mac (u32).

Writing back to OCP

The plugin publishes to the client_ocp shared data with the following fields:

  • ack_time_returned - the ack_time value from vehicle_ocp, passed through unmodified

  • ack_time_mac_returned - the ack_time_mac value from vehicle_ocp, passed through unmodified

  • user_data - optional custom data to send to the vehicle

  • ocp_disable_gamepad - optional, see Disabling OCP gamepad input

See Plugins for general plugin information. Contact your representative for the plugin SDK.

Disabling OCP gamepad input

By default, OCP reads the connected gamepad and sends it as controller input to the vehicle. This can be disabled by setting ocp_disable_gamepad: true in the data sent back to OCP (from the web view, a custom plugin, or a player-side TCP client).

When ocp_disable_gamepad is set to true:

  • OCP stops sending gamepad controller input to the vehicle.

  • The InputLost fault is suppressed (since no gamepad input is expected).

  • The web view, plugin, or TCP client is responsible for providing control input through its own means.

This is used when the operator interface provides its own control scheme - for example, a custom web UI with on-screen controls or a plugin that reads from a different input device.

Client data source locking

By default, OCP handles timestamp echo-back internally — no external client data source is needed and latency measurement works out of the box.

This default behavior can be overridden by exactly one external source: web view, custom plugin, or player-side TCP. The first source that sends client data to OCP becomes the locked source. Once locked, OCP only accepts data from that source.

If OCP detects data from a second source after locking, it treats this as a configuration error:

  • An error is logged identifying both the locked source and the conflicting source.

  • All client data communication is stopped — including from the source that was previously working.

  • A restart is required to recover.

This strict behavior exists because multiple sources sending timestamps and user data simultaneously would cause unpredictable latency measurement and control behavior. Rather than silently producing wrong results, OCP fails visibly.

Summary

Configuration Gamepad input Timestamp echo User data

OCP only

OCP reads & sends

OCP self-echoes from video

None

Web view, no custom JS

OCP reads & sends

Web view auto-echoes

None

Web view + custom JS

OCP reads & sends (unless disabled)

Web view auto-injects into sendNamedUserMessage

Via web view JS

Custom plugin

OCP reads & sends (unless disabled)

Plugin reads vehicle_ocp, writes client_ocp

Via plugin shared data

Player-side TCP

OCP reads & sends (unless disabled)

TCP client reads ack_time/ack_time_mac, echoes back

Via TCP JSON messages