Skip to content

E2E latency measurements - #50

Open
stephen-derosa wants to merge 4 commits into
mainfrom
sderosa/BOT-471-latency-measurement
Open

stephen-derosa wants to merge 4 commits into
mainfrom
sderosa/BOT-471-latency-measurement

Conversation

@stephen-derosa

@stephen-derosa stephen-derosa commented Jul 21, 2026 •

Copy link
Copy Markdown
Collaborator

Overview

  • Replaces measure_latency and its custom ROS pub/sub path with lightweight LTTng tracepoints in the normal forwarding path.
  • Removes the custom latency messages, probe nodes, integration test, and Foxglove layout.
  • Adds offline JSON/CSV analysis with percentile reporting and optional CI budgets.
  • When tracing is disabled, no timestamps, correlation IDs, allocations, or additional ROS endpoints are introduced.

Testing

  • Bridge build with LTTng enabled
  • Unit and credentialed integration suites
  • Analyzer pytest, Flake8, and pep257
  • End-to-end ROS → LiveKit → ROS trace capture
  • JSON and CSV output generation

Example results

50 Hz Docker smoke test with 1,113 complete records and 1,093 measured samples:

Metric p50 p95 p99
End to end 4.454 ms 8.615 ms 25.351 ms
Bridge internal 0.053 ms 0.098 ms 0.174 ms
LiveKit transport 3.312 ms 6.749 ms 15.310 ms
image

@linear-code

linear-code Bot commented Jul 21, 2026 •

Copy link
Copy Markdown
BOT-471 Latency Measurement

Goal: calculate and determine internal bridge latency. The goal is very very small so we get to hang our hat on the same number the cpp sdk uses.

single computer, two bridges

custom ROS message:

T0= pub to bridge

T1 = bridge receives

T2 = bridge forwards over livekit

T3 = livekit receives

T4 = bridge pubs

T5 = sub receives

Review in Linear

@stephen-derosa
stephen-derosa marked this pull request as draft July 21, 2026 20:04
@stephen-derosa stephen-derosa changed the title overly complex latency measurements latency measurements Jul 21, 2026
@stephen-derosa
stephen-derosa force-pushed the sderosa/BOT-471-latency-measurement branch 2 times, most recently from 862a8e7 to ec681f3 Compare July 23, 2026 02:34
@stephen-derosa
stephen-derosa requested a review from Copilot July 23, 2026 03:54

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an end-to-end latency measurement workflow for ros2_livekit_bridge, including a typed latency probe topic that is specially forwarded (with T1–T4 stamping) and supporting tooling to publish probes, compute rolling percentile stats, and run a CI regression guard.

Changes:

  • Introduces measure_latency config support and a dedicated typed forwarding path for /ros2_livekit_bridge/latency/timestamp → /ros2_livekit_bridge/latency/timestamp_rx.
  • Adds latency probe publisher/subscriber utilities + a helper launch file for running a full measurement across two ROS domains.
  • Adds new message definitions and an integration test to guard against bridge-internal latency regressions; updates docs/config accordingly.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/test/waveshare_launch/config/waveshare_livekit_robot.yaml Enables measure_latency for waveshare robot config.
src/test/waveshare_launch/config/waveshare_livekit_controller.yaml Enables measure_latency for waveshare controller config.
src/test/test_utilities/scripts/latency_probe_subscriber.py New node to compute rolling latency percentiles and publish LatencyStats.
src/test/test_utilities/scripts/latency_probe_publisher.py New node to publish LatencyTimestamps probes (T0 end).
src/test/test_utilities/package.xml Updates runtime dependencies for new latency tooling.
src/test/test_utilities/launch/latency_measurement.launch.py New launch file to run two bridges + probes in separate ROS domains.
src/test/test_utilities/CMakeLists.txt Installs the new probe scripts.
src/ros2_livekit_bridge/test/integration/latency_e2e_test.cpp New integration regression guard for bridge-internal latency.
src/ros2_livekit_bridge/test/integration/bridge_e2e_fixture.hpp Adds measure_latency option support to the integration fixture YAML generator.
src/ros2_livekit_bridge/src/topic_forwarder.cpp Implements the dedicated typed latency probe forwarding path (stamp + republish).
src/ros2_livekit_bridge/src/ros2_livekit_bridge.cpp Plumbs measure_latency config into TopicForwarder options.
src/ros2_livekit_bridge/README.md Documents how to characterize and regress latency using the new probes.
src/ros2_livekit_bridge/launch/livekit_bridge_local.launch.py Minor formatting change (currently introduces whitespace noise).
src/ros2_livekit_bridge/include/ros2_livekit_bridge/topic_forwarder.hpp Adds latency topic constants and option flag documentation/fields.
src/ros2_livekit_bridge/include/ros2_livekit_bridge/ros2_livekit_bridge.hpp Stores measure_latency_ in the bridge node.
src/ros2_livekit_bridge_msgs/package.xml Adds message package dependencies for new msg types.
src/ros2_livekit_bridge_msgs/msg/LatencyTimestamps.msg New probe message carrying T0–T5 and payload padding.
src/ros2_livekit_bridge_msgs/msg/LatencyStats.msg New stats message for rolling summaries.
src/ros2_livekit_bridge_msgs/msg/LatencyMetric.msg New per-segment percentile summary message.
src/ros2_livekit_bridge_msgs/CMakeLists.txt Generates the new msg interfaces.
src/ros2_livekit_bridge_config/schema/ros2_livekit_bridge_config.schema.json Adds measure_latency config field (description currently out of sync with implementation).
docs/configuration.md Documents measure_latency behavior and links to the package README.
Comments suppressed due to low confidence (1)

src/ros2_livekit_bridge_msgs/msg/LatencyStats.msg:37

  • Typo in field comment: "receceives" -> "receives" (and the message name should match LatencyTimestamps).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/ros2_livekit_bridge_config/schema/ros2_livekit_bridge_config.schema.json Outdated
Comment thread src/ros2_livekit_bridge/include/ros2_livekit_bridge/topic_forwarder.hpp Outdated
Comment thread src/ros2_livekit_bridge/launch/livekit_bridge_local.launch.py
Comment thread src/test/test_utilities/package.xml
@stephen-derosa
stephen-derosa force-pushed the sderosa/BOT-471-latency-measurement branch from a666e5d to 37eaaf4 Compare July 23, 2026 04:05
@stephen-derosa
stephen-derosa marked this pull request as ready for review July 23, 2026 04:05
}
}

void TopicForwarder::readInboundLatencyTrack(std::shared_ptr<InboundDataTrackState> state) {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

id really like a more isolated place for this latency work to live

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 3 comments.

Comment thread src/test/test_utilities/scripts/latency_probe_subscriber.py Outdated
Comment thread src/ros2_livekit_bridge_msgs/msg/LatencyStats.msg Outdated
Comment thread src/ros2_livekit_bridge/test/integration/latency_e2e_test.cpp Outdated
@stephen-derosa stephen-derosa changed the title latency measurements E2E latency measurements Jul 27, 2026
@stephen-derosa
stephen-derosa force-pushed the sderosa/BOT-471-latency-measurement branch 6 times, most recently from 5672ccd to b02e22d Compare July 28, 2026 18:02
Comment on lines +25 to +28
float64 p50_ms
float64 p90_ms
float64 p95_ms
float64 p99_ms

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume these are percentiles? might be good to add some # comments to the fields

Comment on lines +63 to +72
/// @brief ROS topic the bridge subscribes to (and the LiveKit data-track name it
/// forwards on) for latency probes, created only when measure_latency is set.
inline constexpr const char* kLatencyTimestampTopic = "/ros2_livekit_bridge/latency/timestamp";
/// @brief ROS type string for latency probe messages.
inline constexpr const char* kLatencyTimestampMsgType = "ros2_livekit_bridge_msgs/msg/LatencyTimestamps";
/// @brief ROS topic the receiving bridge republishes inbound latency probes on.
/// Deliberately distinct from @ref kLatencyTimestampTopic so the outbound
/// subscription never re-forwards a republished probe (no cross-bridge loop).
inline constexpr const char* kLatencyTimestampRxTopic = "/ros2_livekit_bridge/latency/timestamp_rx";

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't a hard blocker, but I feel a little iffy about a custom topic for latency measurement, for a couple reasons:

  1. Specfic topics and types hard coded into the bridge
  2. Additional logic in the bridge just for this use case (this PR has a decent chunk of bridge changes which gives me pause)
  3. Latency can heavily depend on message sizes and serialization complexity, the latency .msg as defined is pretty flat and easy

If I were at this, I would go with tracing tools (like chromium tracing) or even RCLCPP_TRACE log statements that could be compiled in/out, each statement having a sequence ID that could be traced, then some sort of orchestration script that runs two bridges and monitors the log output to aggregate results. I get that's more complex, but then we could measure image topics, custom topics, ROS topics, etc. and see how things perform and where the bottlenecks are.

Given we only really control the bridge latency, the ROS latency isn't our domain and livekit latencies are measurable elsewhere in our codebases, an E2E number + log trace statements for our bridge portions seem good enough to me without custom config/logic for a specific topic.

Thoughts?

@stephen-derosa
stephen-derosa force-pushed the sderosa/BOT-471-latency-measurement branch 2 times, most recently from f740366 to d66d8bf Compare July 29, 2026 15:47
Comment thread src/test/latency_tools/launch/latency_measurement.launch.py
@stephen-derosa
stephen-derosa force-pushed the sderosa/BOT-471-latency-measurement branch from 5b0e2a7 to 406f5b0 Compare July 29, 2026 17:15
Comment thread docs/latency.md

### Regression budgets

The analyzer can act as a CI gate:

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a bit of AI overkill i was planning to remove, but thought id leave it in to see if you see value in having this as a cI gate @alan-george-lk

@stephen-derosa
stephen-derosa force-pushed the sderosa/BOT-471-latency-measurement branch 3 times, most recently from 0e97d6a to b4e73f9 Compare July 29, 2026 17:32
)


def _probe_publisher(context):

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ros2 topic pub is the workload generator -- it creates the source-side rmw_publish event used as T0 and gives the sending bridge messages to forward.

]


def _probe_subscriber(_context):

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ros2 topic hz is the destination subscriber -- It creates the final rmw_take event used as T5. It also confirms that messages are arriving at the expected rate.

@stephen-derosa
stephen-derosa force-pushed the sderosa/BOT-471-latency-measurement branch 3 times, most recently from 860cc76 to 2eef12a Compare July 30, 2026 02:15
@stephen-derosa
stephen-derosa force-pushed the sderosa/BOT-471-latency-measurement branch 2 times, most recently from 4476666 to 4327011 Compare August 7, 2026 04:30
@stephen-derosa

Copy link
Copy Markdown
Collaborator Author

discussed in sync: going to use compile time macros such as TRACING_ENABLED to gate code being used or not.

North star would be to create create reports nightly

@stephen-derosa
stephen-derosa force-pushed the sderosa/BOT-471-latency-measurement branch from 4327011 to ff84101 Compare August 27, 2026 22:25
@stephen-derosa
stephen-derosa requested a review from a team as a code owner August 27, 2026 22:25
@stephen-derosa
stephen-derosa force-pushed the sderosa/BOT-471-latency-measurement branch from ff84101 to 971dc02 Compare August 27, 2026 22:34
@stephen-derosa
stephen-derosa force-pushed the sderosa/BOT-471-latency-measurement branch from 0380169 to 5e55f44 Compare September 2, 2026 02:11

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants