Skip to content

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

5 Commits

Folders and files

Repository files navigation

RoboCup 2026 SSL Radio Communications Challenge — Wi-Fi (Team GreenTea)

English version (submission). Japanese master: README_JP.md. Self-contained: the relevant parts of the three source repositories are vendored under components/ (provenance in components/PROVENANCE.md): GreenTea_NetworkLatencyViewer (measurement system, master bac5076), robot_comm_spec (protocol spec, v2.1.0-dev adbd58b), SanRei_HID (production HID firmware, dev 1132740).

Contents

  • I Overview — 1 Executive summary
  • II System under test — 2 Network and communication / 3 Hardware and firmware
  • III Measurement methodology — 4 Measurement points and sampling / 5 Time synchronization and accuracy / 6 Data design for multi-point matching
  • IV Results — 7 Reported items in detail / 8 Network switch demonstration
  • V Reproducibility and deliverables — 9 Reproduction guide / technology transfer / 10 Public deliverables

Part I — Overview

1. Executive Summary

In Team GreenTea, so that the system can comply with the radio regulations of each country, the coach (control PC) and each robot exchange commands and telemetry over Wi-Fi/UDP. This submission reports the communication quality of that radio segment as the prescribed 7 items. Because the uplink (broadcast telemetry) and downlink (unicast commands) are asymmetric in transmission scheme, we adopt one-way latency — measured as one-way delay (OWD), independently for each direction. It is acquired with an AP-independent overlay measurement that modifies neither the coach, the production firmware, nor the AP (6 robots @ 60 Hz, 5 GHz W52, 6-hour continuous run). The system under test is in §2–§3, the methodology in §4–§6, the computation and detail of each value in §7, and the rule's switch demonstration in §8.

1.1 Reported items (radio-environment-dependent)

Because these items vary at the venue, the pre-measurement is accompanied by a venue measurement (own AP, real match run, 2026-07-03). They are summarized in Table 1 (computation, sample sizes, and caveats of the pre-measurement in §7.1–§7.7; venue conditions and detail in §7.9).

Table 1: Reported items (radio-environment-dependent).

Item Pre-measurement (W52, 6 h, 6 robots @ 60 Hz) Venue (real match, 2nd half ch116, 7 robots @ 100 Hz) Notes
One-way latency (OWD), downlink (all data) Mean 3.41 / Var 11.54 ms² (SD 3.40) / median 2.84 / p99 14.64 / Max 370.4 ms Mean 5.41 / Var 31.1 ms² (SD 5.58) / median 3.24 / p99 26.69 / Max 60.9 ms 0 samples >1 s in both. §7.1 / §7.9
One-way latency (OWD), downlink (<p99, top-1% trimmed) Mean 3.22 / Var 4.20 ms² / median 2.82 — (not reported for this run) §7.1 / §7.9
One-way latency (OWD), uplink (all data) Mean 3.54 / Var 5.97 ms² (SD 2.44) / median 2.45 / p99 12.93 / Max 51.0 ms median 2.60 / p95 10.53 / p99 23.24 / Max 44.2 ms (Mean/Var not reported) radio_metrics (52000), HID→wire. §7.2 / §7.9
One-way latency (OWD), uplink (<p99, top-1% trimmed) Mean 3.42 / Var 4.59 ms² / median 2.43 — (not reported for this run) §7.2 / §7.9
Average Packet Loss, downlink 0.0071 % (worst single robot; 6-robot average 0.0058%) ≈ 0.01 % (2nd-half ch116 steady; worst r3 2.1%) Per Wi-Fi frame. Denominator/wrap in §7.3; venue in §7.9
Average Packet Loss, uplink 0 % (0 losses observed) — (not computed) §7.3
Data Rate (base-station view) Mean ≈ 30.7 kbit/s /robot / Variance ≈ 0 ≈ 51.2 kbit/s /robot (100 Hz × 64 B; ≈ 358 kbit/s for 7 robots) Pre-measurement: downlink 60 Hz × 64 B, ≈ 184.3 kbit/s for 6 robots (§7.4)

Venue measurement = own AP, real match match_ch104_0703 (1st half ch104 / 2nd half ch116, WPA2, ~100 Hz, 6–7 robots). The table above shows the 2nd half (ch116, steady state). In the 1st half, a DFS (Dynamic Frequency Selection: the rule requiring a device to vacate parts of the 5 GHz band when it detects radar) radar avoidance (ch104→ch116 CSA = Channel Switch Announcement) caused a ≈ 62 s full outage (confirmed in the AP syslog, §7.9). Conditions differ from the pre-measurement in several ways — comparison in §7.9. The OWD/loss values above are the steady-state performance while connected.

1.2 Reported items (radio-environment-independent)

Invariant at the venue. Summarized in Table 2 (details in §7–§8; hardware in §3).

Table 2: Reported items (radio-environment-independent).

Item Value Notes
Start Up Time median 3.29 s (mean 3.31 / max 3.70 / sd 0.13, n=18 = 6 robots × 3) cold boot → Got IP (§7.6)
Power Consumption TX-peak ≤ 1.26 W; time-average ≈ 0.3–0.5 W (HID = ESP32-C5, datasheet-derived estimate, not bench-measured) TX duty < 1% (60 Hz RX / ~2 Hz TX), so RX/idle-dominated. Datasheet breakdown and basis in §7.7
Cost HID = Seeed XIAO ESP32-C5 ¥1,259/robot (= $7.78) @¥161.78/USD (2026-06-26). AP is infrastructure, counted separately. Details in §3.1
Network Switch (rule demonstration) recv→GOT_IP mean 1366 ms (→WPA2 1.15 s / →Open 1.57 s, n=12) on-device SWMARK (§8)
Detect Interference Yes Detected via sniffer (PROMISC): RSSI / retry bit / neighboring AP beacons (§7.5)
Firmware Source SanRei_HID (§3.2) editable
eCAD / Hardware COTS module configuration (§3.1) no custom board

1.3 Accuracy and reproducibility

  • Measurement accuracy (dominant error of the cross-domain segment): PPS bridge residual sd ≈ 3.7 µs (120 s windowed, 6 h W52, after removing ≈ 10.5 ppm drift; §5.3).
  • Reproducibility (OWD): reproduced by running the bundled analysis/plot_owd.py against data/ (downlink join n=7,777,299, uplink join n=253,709).
  • Reproducibility (packet loss): the 24-bit cycle_count unwrap and the denominator rx_dl 7,777,460 are reproduced separately by the vendored owd_analyzer/longagg.py (see analysis/README.md).
  • Difference from the source document: phase3_findings §2.24 uses a different join condition (different wire-side deduplication, OWD sample 7.39M), but the median / p99 conclusions agree.

Part II — System under test

2. Network and Communication

Shows how uplink and downlink are configurationally asymmetric, fixing the premise of one-way delay measurement (§1). Protocol authority: robot_comm_spec (downlink_command.md / uplink_telemetry.md / radio_metrics.md)

2.1 Topology (normal operation)

SanRei's robot communication connects the coach (control PC) and each robot's HID (radio interface, ESP32-C5) over Wi-Fi 5 GHz / UDP. Inside the robot the HID is connected to the CU (STM32) over UART, bridging Wi-Fi ↔ the robot's internal bus. The measured target of this challenge is the Coach↔HID Wi-Fi UDP segment (Figure 1).

flowchart LR
  COACH["Coach PC<br/>sends control commands to all robots"]
  SW["switch"]
  AP["AP (team AP: Linksys Velop WRT Pro 7, 5GHz, unmodified)"]
  subgraph ROBOT["Robot"]
    HID["HID (ESP32-C5)<br/>one per robot"]
    CU["CU (STM32H743)"]
    HID -->|UART 115200| CU
  end
  COACH -->|wired| SW
  SW -->|wired| AP
  AP -. "★measured: air Wi-Fi 5GHz / UDP" .-> HID
Loading

Figure 1: Network topology in normal operation. The Coach↔HID Wi-Fi 5 GHz / UDP segment is the measured target.

  • AP-independent design: the AP is never modified, allowing measurement even on a shared Wi-Fi. The method applies to any standards-compliant 802.11 AP without reconfiguration (the current values are obtained with the team AP: Linksys Velop WRT Pro 7, model LN6001-JP).
  • Scope of the claim: "AP-independent" refers to the method, not the absolute numbers. Radio-environment-dependent values (Table 1) are re-measured per venue, and venue-AP specifics (beacon interval/DTIM) are not separately validated here.

2.2 Port-based communication

Communication is a port-based scheme that identifies the logical channel and the robot by the UDP port number. Each channel distinguishes an individual robot by base port + robot_id, and the direction (downlink/uplink) and purpose are separated by port range (Table 3).

Table 3: Port-based logical channels and measured targets.

Direction Logical channel Port Transmission Origin Measured
downlink normal command 40000 + robot_id unicast (mDNS robot<id>.local) coach ✅
downlink EMS / OTA (shared) 40999 broadcast coach —
downlink HID control (hid_bridge) 41000 + robot_id unicast coach —
uplink normal telemetry 50000 + robot_id broadcast CU origin (HID relay) —
uplink CAN telemetry 51000 + robot_id broadcast HID (CAN diagnostics) —
uplink Radio Metrics 52000 + robot_id broadcast HID (Wi-Fi metadata) ✅
  • The port alone (source/destination base + id) uniquely identifies "which robot, which direction, which kind of frame."
  • The differing transmission scheme between downlink (unicast) and uplink (broadcast) is the configurational basis of the up/down latency asymmetry stated in §1.
  • The payload of a downlink normal command (64 B) carries the transmit-cycle counter cycle_count, which becomes the multi-point matching key (matching design in §6).
  • Network switch: the set_ssid command (v2.1.0) on the HID control channel (hid_bridge, downlink 41000 + robot_id) switches the AP the HID connects to. This corresponds to the rule's "demonstration of rapid switching between different radio networks" (demonstration in §8).

3. Hardware and Firmware

Presents, in one place, the COTS modules and the firmware that make up the system under test.

3.1 Hardware configuration (COTS modules)

This team uses a combination of COTS modules, with no eCAD of a custom board (per the rules, commercial modules may publish the interface only). The configuration is shown in Table 4.

Table 4: Hardware configuration (COTS modules).

Role Module (COTS) Key spec Connection
HID (radio interface, radio module) Seeed XIAO ESP32-C5 Wi-Fi 6 (802.11ax HE, 5 GHz; 11ax association confirmed: phase3_findings §2.11) UART 115200 with CU
sniffer ESP32-C5 devkit promiscuous + GPIO PPS RasPi USB UART
measurement host Raspberry Pi 5 eth0 SPAN + /dev/pps0 —
AP Linksys Velop WRT Pro 7 (LN6001-JP) Wi-Fi 7 unit; this measurement is a 5 GHz 11ax/HE link wired
switch (SPAN) TP-Link TL-SG105E (easy smart) port mirror —

Interface: the external IF of the radio module (HID) is Wi-Fi (UDP, §2.2) and UART with the CU (2 wires TX/RX, 115200 8N1, no flow control); see Figure 2.

flowchart LR
  COACH["Coach PC"] -. "Wi-Fi 5GHz / UDP" .-> HID["HID (ESP32-C5)<br/>radio module"]
  HID -- "UART TX → RX" --> CU["CU (STM32H743)"]
  CU -- "UART TX → RX" --> HID
Loading

Figure 2: External interfaces of the HID (radio module). Wi-Fi/UDP toward the coach, UART (TX/RX) toward the CU.

BOM / Cost (Power/Cost details in §1.2 / §7.7):

  • The Cost of the reported target (the radio solution) is the HID module ¥1,259/robot (= $7.78) (one per robot).
  • The AP (¥44,000 ≈ $272) is infrastructure that a venue-provided AP can substitute, so it is counted separately.
  • The whole measurement system (≈ ¥45k) is a reference value outside the reported scope.

3.2 Firmware (source, build)

The firmware has two lines: the production HID (center of evaluation) and the measurement system (auxiliary to the method).

A. Production HID (SanRei_HID, ESP32-C5)

Bridges Wi-Fi UDP ↔ the robot's interior (UART/CAN) and emits radio_metrics (rx_dlb/hb); see Table 5.

Table 5: Main sources of the production HID firmware.

Element Source
ESP32C5Controller (main) src/ESP32C5Controller
metrics_radio.cpp/.h (measurement emit) same as above
  • Docker build (recommended, IDE-independent): src/ESP32C5Controller/ bundles a Dockerfile (Ubuntu 22.04 + arduino-cli + esp32:esp32 core) + docker-compose.yml + build.sh. Run cd components/SanRei_HID/src/ESP32C5Controller && docker compose run build to produce ESP32C5Controller.ino.bin.
  • Local direct: arduino-cli compile -b esp32:esp32:XIAO_ESP32C5 ./ESP32C5Controller.ino (board = Seeed XIAO ESP32-C5). Linux instructions in docs/Build_Linux.md.

B. Measurement system (GreenTea_NetworkLatencyViewer)

The measurement-system firmware is listed in Table 6.

Table 6: Measurement-system firmware.

Firmware Role Source
sniffer promiscuous, TSF embedding, GPIO PPS tools/esp_firmware/sniffer
metrics_radio radio_metrics library .../metrics_radio
metrics_radio_reflector HID emulation for testing .../metrics_radio_reflector
arduino-cli upload -p /dev/ttyUSB0 --fqbn esp32:esp32:esp32c5 tools/esp_firmware/sniffer

FQBN note: the production HID is the XIAO board (esp32:esp32:XIAO_ESP32C5), while the sniffer/measurement devkits use the generic esp32:esp32:esp32c5 — they are different board variants (see Table 4), not a typo.


Part III — Measurement methodology

One-way delay (OWD) is obtained as the difference between the clocks of two different devices. Approximating the one-way delay as RTT/2 would average away — and thereby hide — the very up/down asymmetry we set out to measure, so this submission measures each direction independently (the rule lists both one-way and round-trip latency; the round-trip figure is obtained as the sum of the per-direction medians, ≈ 2.84 + 2.45 = 5.29 ms). OWD is meaningful only once the time axes are aligned, so this part proceeds in the order where to observe (§4 measurement points) → how to align the clocks onto one axis (§5 time synchronization) → how to match observations into the same frame (§6 data design).

4. Sampling Method and Measurement Points (overlaid on the operational configuration)

Defines where and how to observe the communication path. The time synchronization that fuses the observed times onto one axis is in §5.

Without changing the normal operating configuration at all, we overlay a measurement system centered on the Raspberry Pi 5 (hereafter RasPi). The coach PC and the robots' production firmware carry no measurement code (black boxes), and the AP is not modified. A single frame is observed with timestamps at up to four measurement points.

4.1 Measurement points P0–P3

Real-data frames flow along the top row (downlink: coach→HID, uplink: the reverse), and at each measurement point they are tapped and aggregated to the RasPi 5 on the bottom row (Figure 3). Thin line = wired, dotted = air, thick = measurement tap.

flowchart LR
  COACH["Coach PC<br/>P0 send (embeds cycle_count)"]
  SW["switch"]
  AP["AP<br/>(team AP, unmodified)"]
  HID["HID (ESP32-C5)<br/>P3 rx/tx"]
  SNF["sniffer (ESP32-C5)<br/>promiscuous"]
  RPI["Raspberry Pi 5<br/>aggregates P1/P2/P3 + PPS time fusion"]
  COACH -->|wired| SW
  SW -->|wired| AP
  AP -. air 5GHz .-> HID
  AP -. "P2 sniff air" .-> SNF
  SW ==>|P1 SPAN mirror| RPI
  SNF ==>|P2| RPI
  HID ==>|P3 radio_metrics| RPI
  SNF -. PPS 1Hz GPIO→/dev/pps0 .-> RPI
Loading

Figure 3: Measurement points P0–P3 overlaid on the operational configuration. Each point is tapped and aggregated to the RasPi 5; times are fused via PPS.

The role of each measurement point is given in Table 7.

Table 7: Measurement points P0–P3.

Symbol Measurement point Acquired by Acquired time (clock domain)
P0 coach send coach PC (payload-embedded) embeds join key cycle_count
P1 wire (wired arrival) RasPi5 eth0 (SPAN mirror receive) NIC hardware timestamp (SO_TIMESTAMPING, UNIX time domain; column t_wire_phc)
P2 air (over-the-air send/receive) sniffer (ESP32-C5, promiscuous) AP TSF (per frame)
P3 HID (terminal rx/tx) HID itself (declared via radio_metrics) AP TSF (rx_dlb / hb)
  • For the downlink, a frame passes in the order P0→P1→P2→P3. For the uplink, P3 (HID send) →P2 (air)→P1 (wired arrival).
  • P2/P3 are AP TSF and P1 (wire) is the RasPi's UNIX time. The two domains are fused onto a single time axis by the PPS bridge of §5 (P0 is the origin of the join key cycle_count).

4.2 Acquisition method at each measurement point

  • P1 wire: the RasPi's eth0 is connected to the switch's SPAN mirror destination and receives via AF_PACKET + SO_TIMESTAMPING, timestamping frame arrival with the NIC hardware RX timestamp (UNIX time domain, analysis column t_wire_phc). Being the RasPi's local clock, there is no systematic error within the RasPi segment.
  • P2 air (sniffer): the ESP32-C5 is put in promiscuous mode and records esp_timer in each frame-receive callback → a separate task assigns tsf_us by midpoint-fit linear conversion of (esp_timer, AP TSF) every 100 ms (using the midpoint t_mid=(t_before+t_after)/2 because t_before alone worsens the residual p99). The callback time matches the HW RX timestamp within ±1 µs.
  • P3 HID: the HID records esp_timer at the instant of rx/tx, converts it to AP TSF by windowed linear regression, and declares t_rx_tsf_us / t_tx_tsf_us via radio_metrics (52000+id). Same AP TSF domain as P2.
  • Clock fusion: P2/P3 (AP TSF) and P0/P1 (UNIX) are fused onto a single axis by the PPS bridge of §5 (residual sd ≈ 3.7 µs).

4.3 Limit of capturing the downlink air (P2) with many robots

As the number of robots grows, the AP aggregates downlink unicast per-STA into A-MPDU, so the promiscuous sniffer (P2) cannot demodulate frames addressed to other STAs and drops them structurally, depending on transmission order (measured: 2 robots ~89% → 6 robots ~16%). We therefore measure downlink OWD with the air-independent P1 (wire) + P3 (HID). The uplink can be captured uniformly across all STAs and P2 is usable in principle, but in the submitted run the sniffer's MAC matching does not hold, so the air-leg decomposition is not obtained (phase3_findings §2.24). Uplink OWD is computed endpoint-to-endpoint from the HID send anchor tx (P3) → wire (P1) (canonical definition in §6.2, results in §7.2).


5. Time Synchronization and Accuracy

Because one-way delay is the difference between clocks of different devices, we establish the time reference that aligns the observations of §4 onto one axis, and evaluate its precision. The starting point is confirming that multiple Wi-Fi devices connected wirelessly can hold a common clock.

5.1 TSF synchronization between Wi-Fi devices

In IEEE 802.11, the beacon the AP periodically transmits (interval ~100 ms here) contains a TSF (Timing Synchronization Function) timestamp, and every STA connected to the same AP aligns its own TSF counter to it. That is, devices under the same AP can share a µs-resolution common clock (AP TSF) without any wiring.

This measurement applies that property to two Wi-Fi devices: the robot's HID (ESP32-C5) and a sniffer (ESP32-C5). Because both synchronize to the same AP's beacon, the TSF each reads via esp_wifi_get_tsf_time() lies on the same time axis. This lets us directly subtract the time of a frame one observes over the air (air) and a frame the other receives/transmits at the terminal (HID) on the same AP TSF.

  • Verification: We made both the HID and the sniffer emit a GPIO pulse at the TSF 1-second boundary (the moment tsf_us crosses a multiple of 10⁶), and measured the time difference Δt of the two pulses with an ADALM2000. With the submitted GPTimer-based PPS the inter-device Δt is median +4.4 µs / sd 5.0 µs (idle, unimodal; phase3_findings §2.22) — small and stable, corroborating that "the two Wi-Fi devices are synchronized to the AP at the same precision."

5.2 Giving TSF-domain time to the measurement RasPi

§5.1 showed the HID and sniffer can hold a common clock, AP TSF. On the other hand, we need to observe wired-segment packets too, and to aggregate the measurement logs each device produces in one place. This measurement concentrates that role on the RasPi (§4). The RasPi is the core of the measurement system: it receives the wired frames between the AP and the coach via SPAN mirror and timestamps them (§4.1 P1), and also collects logs from the HID and sniffer.

This measurement therefore has two clock domains: the AP TSF domain kept by the sniffer and HID, and the UNIX time (CLOCK_REALTIME) the RasPi uses for the P1 wire timestamps. Since OWD is meaningful only on a synchronized time axis, the focus of this section is to also give the measurement RasPi a TSF-domain time — a mechanism that bridges AP TSF to UNIX time — and to quantify the residual within and across each domain.

The concrete means of joining the two domains is the PPS (Pulse Per Second) signal the sniffer gives the RasPi. Since the sniffer is synchronized to AP TSF (§5.1), it can output a 1 Hz pulse on GPIO at the AP TSF 1-second boundary (the moment tsf_us crosses a multiple of 10⁶). This pulse is wired to the RasPi's GPIO (/dev/pps0), and the RasPi timestamps the pulse arrival with its own UNIX time. This yields, once per second, a correspondence pair between "a given AP TSF boundary value" and "the UNIX time at that instant," from which the offset joining the two domains is obtained: bridge_offset = unix_assert − tsf_boundary/1e6 — through the sniffer's PPS, the measurement RasPi is given AP-TSF-domain time. The synchronization method and residual of each domain are summarized in Table 8.

Table 8: Clock-domain synchronization method and residual.

Synchronization Method Precision (residual)
within TSF domain (air↔HID) both TSF-synchronized to the same AP's beacon (§5.1); taken as TSF-to-TSF difference µs order (does not include bridging error)
TSF ↔ UNIX bridge sniffer outputs GPIO 1-PPS at the AP TSF 1-second boundary → RasPi /dev/pps0 timestamps in UNIX. bridge_offset has its drift removed linearly per 120 s window residual sd ≈ 3.7 µs (6 h W52, dominant error of the cross-domain segment)

5.3 Accuracy summary

What "120 s windowing" means: rather than approximating the TSF↔UNIX bridge_offset with a single straight line over the whole 6 h, the method splits time into 120-second windows and fits a separate straight line in each window. Because clock drift (≈10.5 ppm) varies slowly, joining local straight lines (piecewise-linear approximation) gives a smaller residual than a single global fit, settling at sd ≈ 3.7 µs (a single global fit gives about 1400 µs). Each window additionally rejects sparse PPS-pair glitches with a 3σ test before the final refit (mostly single-sample UART-transport spikes); 3.7 µs is the post-refit bulk residual, and the rare tail excursions (≪ 1 % of pulses) are larger but sparse and do not move the OWD percentiles. Implemented in analysis/plot_owd.py.

  • Dominant error of the cross-domain segment = PPS bridge residual sd ≈ 3.7 µs (sniffer↔RasPi, 120 s windowed, 6 h W52, after linear removal of ≈ 10.5 ppm drift). The accuracy of downlink OWD (which crosses the UNIX-domain P1 and the TSF-domain P3) is set by this value (Figure 4).
  • Within the TSF domain (air↔HID) it is a TSF-to-TSF difference, free of bridging error, on the order of µs.
  • sd 3.7 µs is only the bridge component. PPS generation jitter (the submitted firmware's GPTimer hardware PPS) is idle 1σ ~5 µs (unimodal; phase3_findings §2.22), but the 120 s linear fit averages out the per-pulse jitter, so the bridge residual settles at sd ~3.7 µs. The full OWD additionally includes the HID-side TSF-anchor jitter (idle sd ~5 µs); combined in quadrature the sync uncertainty is RSS ≈ √(3.7² + 5²) ≈ 6 µs, i.e. < 0.5 % of the 2.84 ms median OWD — it does not change the conclusions.
  • NTP is unnecessary for this measurement: OWD is computed from the PPS bridge (relative offset), so the RasPi's NTP absolute-time error (chrony, RMS ~0.3 ms in this run) does not affect OWD. The coach clock is not used either.
  • Uplink measurement traffic (broadcast) does not affect time synchronization: uplink broadcast can worsen downlink delay (self-interference; canonical description in §6.2, quantitative evidence in §7.8), but time synchronization holds on a separate path. PPS is over GPIO wiring (Wi-Fi-independent) and TSF is beacon synchronization, so airtime contention does not change the accuracy of the time axis. The bridge residual is sd ≈ 3.7 µs at idle; under heavy co-channel contention the PPS pulse is preempted by Wi-Fi RX and it relaxes to sd ≈ 23 µs (phase3_findings §2.19), still < 1 % of a ms-scale OWD — the PPS bridge is maintained even when downlink OWD itself degrades.

PPS bridge drift and residual

Figure 4: Measured PPS bridge for the submitted run (6 h, W52). (a) bridge_offset drifts linearly at about 10.5 ppm (removed by 120 s windowing). (b) After removal, the residual is centered at 0 within sd ≈ 3.7 µs (window-averaged, phase3_findings §2.24), which is the dominant error of the cross-domain segment (downlink OWD, etc.). Raw data: data/batch_6r_060hz_6h_w52ch36 (pps_gpio/pps_uart).


6. Data Design for Multi-point Matching

A design that lets observations acquired at different measurement points be matched later as the same frame.

Because each measurement point timestamps independently, the payload needs a unique matching key to link observations. This submission uses the unique counter the sender increments on each transmission as the key, and each observation point matches by reading just the key cheaply from a fixed offset, without parsing the whole packet (Table 9).

Table 9: Multi-point matching keys.

Target frame Matching key Notes
downlink normal command (40000+id) cycle_count (transmit-cycle counter) coach origin. Packet loss is also computed from gaps
radio_metrics (52000+id, uplink/hb, etc.) hid_seq the fixed-length leading meta (offset 9) is parsed by sniffer / wire

6.1 Downlink command layout (fixed 64 bytes)

A downlink normal command is a fixed 64 bytes and embeds the matching key cycle_count (Table 10).

Table 10: Downlink command layout (fixed 64 bytes, excerpt).

offset field type purpose
00–01 header 0xFF 0xC3 frame detection
02 robot_id uint8 robot identification
51–53 cycle_count uint24 LE transmit-cycle counter (per-cycle loss/arrival key, wraps over 0–16,777,215)
63 checksum XOR ^ 0xFF —
  • The wired (wire) / air observation points do not parse JSON; they identify a downlink frame by reading only cycle_count (51–53) from this fixed offset.
  • Downlink OWD is SPAN→HID (wire PHC + TSF bridge), joined on cycle_count.

6.2 The meta of radio_metrics (off-board matching header)

On the uplink side (broadcast), the HID places a fixed-length HEX meta at the head of each JSON of the radio_metrics it sends (52000+id). meta is the first key of the JSON, and because serialization always begins with {"meta":" (9 bytes), the HEX value always appears at offset 9 from the payload head (by the rule of not placing variable-length elements before it). The layout is shown in Table 11.

Table 11: Layout of the radio_metrics meta (leading fixed-length HEX).

HEX byte content
0–1 magic 0x52 0x4D (ASCII "RM", radio_metrics frame detection)
2 meta format version (0x01)
3 type (04=rx_dlb / 03=hb)
4 robot_id
5–8 hid_seq (uint32 big-endian, monotonically increasing counter shared across all types)
  • An off-board observer can match the same frame across air / wire / host-socket without JSON parsing just by "reading 18 HEX from payload offset 9 → confirming the magic is RM → obtaining (robot_id, hid_seq)."
  • meta contains only values fixed before transmission (counters, IDs). The on-air transmit time is observed by the sniffer (not embedded in the payload).
  • Uplink broadcast affects downlink delay (self-interference): uplink measurement broadcast consumes airtime and can worsen the delay and capacity of the downlink, which is the measured target. On the other hand it does not affect time synchronization (mechanism and measurements in §5.3). Quantitative evidence for uplink volume → downlink latency is in §7.8.
  • rx_dlb (batch, type 04): to suppress self-interference, downlink receive records are bundled into one UDP broadcast, aggregating the uplink measurement frames to ~2 Hz/robot. The recs array holds per-record cycle_count / t_rx_tsf−base (delta-compressed) / rssi (obtaining downlink OWD, loss, RSSI). Gaps in bseq (batch sequence) separate report (UDP) loss from downlink loss.
  • The segment decomposition (air leg) of uplink OWD could in principle be obtained by matching air (P2) and wire (P1) on hid_seq, but it is not obtained in this run because the sniffer's MAC matching does not hold (source phase3_findings §2.24). The reported value is the endpoint-to-endpoint OWD from the send anchor tx (P3), which the HID reads in software just before broadcast, → wire (P1), and includes the HID→air channel access + internal TX queue.

Authority: downlink_command.md / radio_metrics.md


Part IV — Results

7. Reported Items in Detail

From the data acquired by the measurement system of §4–§6, each reported item is shown with its formula, sample size, and caveats (summary values are in §1).

Measurement conditions (recommended submission run): coach (pc_emulator sends downlink 40000+id as 60 Hz unicast, 6 robots) → Linksys Velop WRT Pro 7 (5 GHz W52 ch36 (non-DFS), open auth) → each HID (ESP32-C5, rx_dlb batch measurement firmware). 6 hours continuous. Source: phase3_findings §2.24.

Population and trimmed estimators: the headline reports two estimators — all data (untrimmed) and top-1%-trimmed (<p99). The p95 / p99 / p99.9 values are printed as reference tail markers (not a multi-stage removal). The headline median 2.84 ms is the untrimmed value, and the full tail is shown in the Figure 5b CCDF. A range guard of −50 to 20000 ms to reject non-physical divergent values is also applied, but in this run 0 samples matched, so no data was removed.

7.1 One-way latency (downlink)

  • Computation: t_hid_rx_tsf/1e6 + bridge_off(t_wire_phc) − t_wire_phc (SPAN→HID, air-independent). Joins the wire and HID downlink-receive records on (robot_id, cycle_count), excluding wire captures of the same cycle spanning >0.1 s (same cycle_count-value collisions).
  • Sample size: OWD join n=7,777,299 (of rx_dl 7,777,460, the part matching wire). phase3_findings §2.24 uses a different join condition (7.39M, p99 14.67 ms); sample sizes differ slightly but the median/p99 conclusions agree (our pipeline: p99 14.64 ms).
  • Result: all data Mean 3.41 / Var 11.54 ms² (SD 3.40) / median 2.84 / p99 14.64 / Max 370.4 ms (0 samples >1 s). After the <p99 (top-1%) trim Mean 3.22 / Var 4.20 ms² / median 2.82.

7.2 One-way latency (uplink)

  • Computation: t_wire_phc − (tx/1e6 + bridge_off(t_wire_phc)) (HID→wire). tx is the send TSF anchor the HID reads in software just before broadcasting rx_dlb (P3). Joined with uplink wire (52000) on (robot_id, hid_seq).
  • Sample size: n=253,709 (per rx_dlb UDP frame, ~2 Hz/robot).
  • Result: all data Mean 3.54 / Var 5.97 ms² (SD 2.44) / median 2.45 / p99 12.93 / Max 51.0 ms. After the <p99 (top-1%) trim Mean 3.42 / Var 4.59 ms² / median 2.43.
  • Supplementary notes: Representativeness — production uplink 50000 is a CU-origin/transparent channel that cannot embed a matching key (meta), so it cannot be matched multi-point; uplink delay is measured on radio_metrics 52000 (rx_dlb), which carries hid_seq. Both 50000 and 52000 are broadcast on the same Wi-Fi link with no ACK/retry, so they share the same air behavior. This is verified directly: production uplink frames pair with their tx_ul anchors at 99.963 % (79 unpaired / 215,623, phase3_findings §2.8), i.e. the production path is itself near-lossless and the 52000 measurement is representative of it. Endpoint asymmetry — downlink OWD is wire→HID (P1→P3), whereas uplink OWD is HID-send-anchor→wire (P3→P1): an endpoint-to-endpoint OWD that includes the HID→air channel access + internal TX queue on the near side, not a pure over-the-air comparison with downlink (air-leg decomposition not obtained in this run, §4.3 / phase3_findings §2.24).

The up/down OWD distributions are shown in Figure 5.

Uplink/downlink OWD distribution

Figure 5: Up/down one-way latency (OWD) (submitted run). (a) Both distributions peak at 2–3 ms (downlink mean 3.41 / uplink 3.54 ms). (b) Comparing the tails by CCDF (log-y), the downlink has the heavier tail (downlink p99 14.64 ms, max 370.4 ms off-chart; uplink p99 12.93 ms, max 51.0 ms; axis labels are rounded — exact values in Table 1 / §7.1). Raw data: data/batch_6r_060hz_6h_w52ch36.

7.3 Packet loss (downlink and uplink)

  • Downlink: cycle_count gaps (dedup) of downlink commands, counted per Wi-Fi frame.
    • Result: 0.0071 % (worst single robot; 6-robot average 0.0058%).
    • Denominator: the expected sent count (per-robot ≈ 1.30M; the 6-robot aggregate received rx_dl 7,777,460 + gaps).
    • Wrap handling: cycle_count is the coach AI's transmit counter continuous from startup and is not reset to 0 per run. In this run it was near the 24-bit ceiling at the start and each robot wrapped to 0 once during the run (data: each robot min 0 / max 16,777,215, distinct ≈ 1.30M ≈ 60 Hz×6 h, span(max−min)=16.78M). A naïve max−min would mistake the real 1.30M for 16.77M, so gaps are counted after 24-bit unwrap.
  • Uplink: bseq gaps of rx_dlb (1 UDP = 1 Wi-Fi frame) = uplink Wi-Fi frame loss. 0 % (0 losses observed), n=253,709. Uplink frame rate ≈ 2 Hz/robot.

Venue robustness / worst case: loss degradation under load and contention (up to 11.60 % under external uplink contention, etc.) is presented in §7.8 as part of the uplink-volume vs downlink-performance relationship.

7.4 Data rate

payload × send rate (base-station view). downlink 60 Hz × 64 B = ≈ 30.7 kbit/s /robot, ≈ 184.3 kbit/s for 6 robots (Variance ≈ 0).

7.5 Interference detection

Detector (inputs → decision): the sniffer in promiscuous mode provides, per frame, RSSI, the 802.11 retry bit, and neighboring-AP beacons (foreign SSIDs/BSSIDs on the channel); from the multi-point pipeline we additionally derive the AP-queue-freeze rule: a run of consecutive packets with wifi_leg (wire→HID air-side latency) > 100 ms is flagged as one interference / queue-freeze event. Output is a per-event flag with timestamp, duration, and RSSI/retry context — i.e. an operational decision, not just a log.

Demonstrated example (ch112): on the calibration run on the DFS channel ch112 the detector flagged 65 events / 6 h (~11/h), max freeze 2517 ms, inter-event median 245 s (phase3_findings §2.5) — the queue-freeze failure mode characterized quantitatively.

Applied to the submitted W52 run: W52 ch36 is non-DFS, so the radar/queue-freeze trigger cannot fire; running the same wifi_leg > 100 ms detector over the run yields 0 events flagged (consistent with the downlink tail having 0 samples > 1 s, §7.1). Neighboring-AP/RSSI/retry monitoring remains live. → Yes (interference is detected when present; the submitted run is clean).

Live detection at the venue: in the first half of the real match (§7.9) we captured a simultaneous all-STA disconnect and, by cross-checking the AP syslog, identified the cause as a DFS radar detection → automatic channel avoidance (CSA, ch104→ch116) (Radar found on channel=105/5528 → Changing to DFS chan 116 (5580 MHz) → hostapd channel switch: freq=5580; 8 radar events that day; ≈ 62 s full outage). A worked example of interference detection in a real environment.

(The bundled sniffer_frame.parquet holds a 939k-frame air subset — the raw capture is ~4.77M frames over the 6 h. Many downlink unicast frames are structurally dropped by A-MPDU aggregation (§4.3), so the air leg is not used for reported OWD.)

7.6 Start up time

cold boot via esptool hard_reset → capture "WiFi Got IP" (= downlink receivable) in the boot banner with a host timestamp. median 3.29 s (mean 3.31 / max 3.70 / sd 0.13, n=18 = 6 robots × 3), 0 reconnects.

  • Measurement condition: the firmware's boot SSID is hardcoded to the WPA2 network, so this is the cold-boot association figure for the WPA2 default SSID.
  • Conservativeness: most of the ~3 s is association + DHCP; the 4-way handshake is only tens of ms. Cold-boot with open auth is untested but expected to be faster by the absence of the handshake (phase3_findings §2.23), so 3.29 s is a conservative (worst-case) bound.
  • Distinction: this is cold-boot association, a different scenario from the runtime SSID switch (§8, →Open is slower).

7.7 Power and cost

the radio module (HID = ESP32-C5) alone is the reported target (Cost = module unit price, Power = HID alone).

Power:

  • Status: a datasheet-derived estimate, not bench-measured (module current draw was not instrumented for this run). The "~17 W" in the internal log is the whole measurement rig — RasPi 5 + sniffer + switch + USB-Eth — not the HID.
  • Basis: the ESP32-C5 datasheet gives RX/idle ≈ 80–100 mA (≈ 0.27–0.33 W @3.3 V) and a 5 GHz TX peak ≈ 381 mA (≈ 1.26 W).
  • Workload: the HID receives at 60 Hz and transmits rx_dlb at only ~2 Hz, so the TX duty cycle is < 1 %. The time-average is RX/idle-dominated, i.e. ≈ 0.3–0.5 W, with ≤ 1.26 W as the instantaneous TX-peak ceiling.
  • Reporting policy: we report a single derived estimate (no Variance) and flag bench measurement as future work. Power is radio-environment-independent, so this figure is final regardless of venue.

Cost:

  • Value: ¥1,259/robot (= $7.78) — the per-robot radio module (Seeed XIAO ESP32-C5, which bundles antenna/regulator/USB on a certified module).
  • Exclusion rationale: the AP/RasPi/switch are shared infrastructure, not per-robot radio cost, and the AP is venue-substitutable (§3.1), so they are excluded from the per-robot figure.
  • Details: hardware configuration and BOM in §3.1.

7.8 Uplink traffic volume vs downlink latency (self-interference and external contention)

Airtime consumed in the uplink direction directly degrades the latency and loss of the downlink — the measured target. We show this relationship with three lines of evidence: (1) an A/B measurement that varies only our own uplink reporting scheme (self-interference), (2) a 6-hour comparison between the past per-frame submission baseline and the submitted batch run, and (3) an external-STA uplink load test (external contention).

(1) Self-interference A/B — only the uplink scheme varied (Table 12): with an identical setup (6 robots simultaneously, 25 s spot measurements per downlink load), the uplink reporting scheme was switched from per-frame rx_dl (one broadcast per received downlink frame = uplink frame rate of downlink-rate × 6 robots) → batch rx_dlb (~12 frames/s total) → wired USB (uplink fully removed), measuring downlink latency (SPAN→HID, phase3_findings §2.24):

Table 12: Downlink latency by uplink reporting scheme (A/B spot measurement, SPAN→HID p99).

Downlink load per-frame (uplink = downlink rate × 6 robots) batch rx_dlb (uplink ~12 frames/s total) USB (uplink 0)
100 Hz p99 76 ms p99 17.7 ms (median 2.61) p99 7.6 ms
200 Hz p99 142 ms (collapse) p99 18.3 ms (median 2.77) p99 7.4 ms

The more uplink traffic, the worse the downlink p99 — monotonically (batching improves it 4.3×/7.7×; USB with uplink fully removed is the lower bound). Since only the uplink scheme was varied under identical conditions, this directly demonstrates the uplink-volume → downlink-latency relationship.

(2) 6-hour sustained-run comparison — past per-frame baseline vs the submitted batch run (Table 13): the pre-submission baseline sent uplink reports per-frame (6 robots @ 60 Hz = uplink ~360 frames/s) and suffered heavy downlink tail/loss degradation. Comparison with the submitted run, which batches the uplink (~12 frames/s total, a 30× reduction; phase3_findings §2.24):

Table 13: Downlink performance, per-frame 6 h (past baseline) vs batch 6 h (submitted).

Metric per-frame 6 h (ch112, uplink ~360 frames/s) batch 6 h (W52, submitted, uplink ~12 frames/s)
downlink median 3.05 ms 2.84 ms
downlink p99 46.7 ms 14.67 ms (3.2× better)
downlink max 466 ms + DFS freeze 803 ms 370.4 ms (0 samples > 1 s)
downlink loss (all 6 robots) 0.10–0.14 % 0.0071 % (14–20× better)
bridge residual sd 11.7 µs 3.7 µs
  • Fairness note: this 6-hour comparison also differs in channel (ch112 DFS vs W52 non-DFS), so the max/freeze differences are not attributable to self-interference alone (they include the disappearance of DFS-induced freezes). median/p95/p99 are the robust comparison axes; the same-condition causal evidence is the A/B of Table 12 (phase3_findings §2.24).

(3) External contention — uplink load from other STAs (venue robustness / worst case): the submitted run is a clean single-AP environment, so the failure modes a venue can induce were characterized in a co-channel saturation stress test (ch112, iperf3 UDP load, phase3_findings §2.21).

  • Tolerance region: the downlink command path stays loss-free with single-digit-ms tails up to ~60 Mbit/s offered, then degrades sharply at channel saturation.
  • Saturation cliff: at the capacity cliff (~70 Mbit/s offered) downlink loss reaches 3.88 %.
  • Uplink contention (worst): under heavy uplink contention from other STAs downlink loss rises to 11.60 % (vs 4.64 % for downlink-direction load), because external uplink traffic wins the medium via CSMA/EDCA and starves the AP's downlink TXOP. The median stays low; it is the tail and loss that degrade.
  • Practical implication (phase3_findings §2.21.3): the dominant venue threat to control delivery is uplink saturation by other teams/spectators, not the team's own AP load — so interference monitoring (§7.5) should watch channel saturation / uplink contention, not average bandwidth.

Conclusion: whether the uplink traffic is our own measurement reporting (Tables 12–13) or from external STAs (phase3_findings §2.21), more uplink traffic consistently worsens downlink latency and loss. This is the empirical basis both for the rx_dlb design that aggregates uplink reporting to ~2 Hz/robot (§6.2) and for the interference-monitoring policy of watching uplink / channel saturation (§7.5).

7.9 Venue measurement (own AP, real match run)

We measured a real match during the event, with our own AP installed at the venue, over two halves (match_ch104_0703 [1st half] / match_ch104_0703_2nd [2nd half], 2026-07-03, WPA2, ~100 Hz). The methodology is identical to the pre-measurement (PPS bridge → SPAN→HID; §7.1–§7.3). Detailed report: results/match_ch104_0703_RESULTS.md.

  • Conditions: 1st half = 6 robots (id1–5,7), ch104 (5520 MHz); 2nd half = 7 robots (id2–8), ch116 (5580 MHz). Bridge residual sd 13.4 µs (1st half, includes CSA transient) / 6.8 µs (2nd half).
  • Results (steady-state while connected, CSA transient excluded):
    • 1st half (ch104→116): downlink median 3.26 ms / p99 38.19 / Max 158.3 ms (n=261,783), uplink median 2.73 ms (0 samples > 1 s).
    • 2nd half (ch116, steady): downlink median 3.24 ms / p99 26.69 ms / Max 60.9 ms (n=387,775), uplink median 2.60 ms / p99 23.24 ms (n=10,149). Downlink steady loss ≈ 0.01 % (r2/r5/r6/r7 at 0.005–0.008%; worst r3 only 2.1%). 0 samples > 1 s.
  • Actual uplink volume (including non-measurement traffic): from this run's uplink logs, each robot emits ≈ 10 frames/s (production telemetry ~6.8 + measurement rx_dlb ~3.2; per-robot range 3–15/s; production ≈ 34 kbit/s/robot). The measurement (rx_dlb) is only a fraction of the total; since total uplink volume degrades the downlink (§7.8), the policy is to aggregate uplink as much as possible.
  • Main event: DFS radar avoidance (CSA) — the key finding of this run. In the 1st half at 18:06:55 the AP detected radar (AP syslog: Radar found on channel=105, freq=5528 MHz) and automatically performed a CSA from ch104 to ch116 (Changing to DFS chan 116 (5580 MHz), hostapd channel switch: freq=5580). All STAs went disassoc → CSA → re-associate on ch116, a ≈ 62 s full outage (8 radar events that day). This materializes the mid-match DFS-band radar avoidance risk (ch104/ch116) with real data.
    • Unlike the earlier ch52 outage (no radar in the AP log), here the AP log clearly records radar + CSA → the rule's interference detection (§7.5) worked in a live environment.
    • The 2nd half (ch116) was stable with no outage (continuous apart from one re-sync transient).
  • Caveats: under WPA2 the air point (P2) cannot read the encrypted payload, so segment decomposition is unavailable (total downlink OWD and loss are computed over the wire path). Pitfall after CSA: if the sniffer keeps capturing while its TSF drifts from the robots', OWD silently breaks; we exclude the TSF-mismatch transient bins (sane < 90 %) before computing (the windowed bridge re-fits before/after the CSA, recovering OWD on both the ch104 and ch116 segments). The raw data is not bundled due to size (the analysis script results/match_ch104_0703_analyze.py is bundled and reads the NAS run directory).

The comparison with the pre-measurement (submission-grade benchmark) is shown in Table 14. Since several conditions differ, this is positioning — how the real-match environment shifts the benchmark — not a like-for-like ranking.

Table 14: Downlink/uplink performance, pre-measurement vs venue real match (2nd half ch116).

Metric Pre-measurement (batch_6r_060hz_6h_w52ch36) Venue 2nd half (match_ch104_0703_2nd)
Conditions 6 robots / 60 Hz / Open / W52 ch36 (non-DFS) / 6 h 7 robots / 100 Hz / WPA2 / ch116 (DFS) / 13.8 min
downlink median 2.84 ms 3.24 ms (×1.14)
downlink p95 / p99 8.22 / 14.64 ms 18.16 / 26.69 ms (×1.8)
downlink Var 11.54 ms² 31.1 ms²
downlink Max 370.4 ms 60.9 ms
downlink > 1 s 0 samples 0 samples
uplink median / p99 2.45 / 12.93 ms 2.60 / 23.24 ms
loss 0.0071 % ≈ 0.01 % (worst r3 2.1%)
all-client outage none 1st-half DFS-CSA ≈62 s outage (§7.9); 2nd half none

The OWD distribution is compared across the pre-measurement and the venue match (1st/2nd half), with downlink (unicast) and uplink (broadcast) placed side by side per run, in Figure 6 (each box annotates median/p99/max; downlink also annotates loss).

Downlink and uplink OWD box plot, pre-measurement vs venue match

Figure 6: Downlink & uplink OWD box plot (pre-measurement W52 6 h / venue 1st half ch104→116 / venue 2nd half ch116, downlink & uplink side by side per run, CSA transient excluded). Downlink medians are 2.84 (pre) / 3.24 (2nd) / 3.26 ms (1st); uplink medians are 2.45 (pre) / 2.61 (2nd) / 2.62 ms (1st), all within a control cycle. Downlink loss (received/sent) is < 0.01 % for pre and 2nd half, and 0.83 % for the 1st half (whole-half value, including the ≈62 s DFS outage). The 1st half is wider on both directions from the CSA (DL p99 38, Max 158 / UL p99 36). Uplink is an endpoint OWD (HID tx-anchor → wire; includes near-end channel access + TX queue, not a pure over-the-air comparison; §6.2 / §4.3); it sits slightly below downlink because broadcast carries no ACK/retry plus the endpoint definition. The per-half × up/down breakdown is in match_ch104_owd_box.png.

Reading:

  • Steady-state degrades by ×1.14 (median, 2.84→3.24 ms) and ×1.8 (p99, 14.6→26.7 ms) vs the benchmark — a compound of "Open→WPA2 (encryption, retries)", "60→100 Hz (more load)", and "an empty W52 channel → a congested DFS band".
  • Max is smaller at the venue (60.9 < 370.4 ms, 2nd half) because the 6-hour pre-measurement captured rarer tail events. Both have zero samples above 1 s (no multi-second stalls); the medians (2.84 / 3.24 ms) are within a 100 Hz control cycle (10 ms), while the p99 (14.6 / 26.7 ms) exceeds 10 ms — reducing the tail is the remaining task.
  • Loss is ≈ 0.01 % in the 2nd half — close to the benchmark's 0.0071 % (r3 alone 2.1%).
  • The one heavy event is the DFS radar avoidance (1st half, ≈62 s outage). Confirmed as radar + CSA in the AP log — a live application of the interference detection of §7.5.

7.10 Reference: our-robots-only match (low uplink)

As a bonus, we measured a scrimmage between our own robots (prod_ch116_0703, ch116, ~24 min, 8 robots). Both sides emit ~7 frames/s of uplink per robot (production) — i.e. this represents the case of low-uplink teams playing each other.

  • Downlink OWD (SPAN→HID, n=275,176): median 2.16 ms / p95 11.0 / p99 16.73 ms / Max 74.0 ms / 0 samples > 1 s.
  • Downlink loss ≈ 0.74 % (received/sent = wire-sent vs rx_dl-received; per robot 0.07–1.35%). No all-client outage (uplink continuous throughout).
  • Better than the pre-measurement (median 2.84 ms) and the venue match (3.24 ms) — the best steady-state latency of all runs.

→ This shows the converse of §7.8 with real data: the lower the total uplink, the better the downlink; well-behaved (low-uplink) teams stay extremely stable even in a live match.

Loss note: the cycle_count-gap method over-reports (~21 %) for this run because cycle_count is the coach's global counter and each robot receives only its own addressed cycles; the true loss is the received/sent ratio ≈ 0.74 %.


8. Network Switch Demonstration (rule requirement)

In addition to the 7 reported items, the rule requires a "demonstration of rapid switching between different radio networks." Our configuration addresses this with the set_ssid command of robot_comm_spec v2.1.0.

  • Means: sending { "type": "set_ssid", "ssid": "<target>", "password": "<optional>" } to the HID control channel (hid_bridge, downlink port 41000 + robot_id, JSON) makes the HID switch the AP it connects to.
  • Because it is a directed connection with an explicit SSID, it can connect to a hidden AP as well.
  • After switching, responses (telemetry / hid_status) move to the new network side, so the commanding PC follows too.

Measurement method: an on-device marker (SWMARK) is added to the HID firmware, recording in HID millis the set_ssid receive time (recv) and the connection-complete GOT_IP (= downlink receivable) time. Their difference, recv→conn, is taken as the switch time. Open(TEAM_SSID_OPEN) ↔ WPA2(TEAM_SSID) was toggled 6 times.

Results (on-device SWMARK, r1/r2 × 6 toggles, n=12) are shown in Table 15.

Table 15: Network switch time (recv→GOT_IP).

Switch direction Switch time (recv→GOT_IP)
→ WPA2 (normal) ≈ 1.15 s (1142–1162 ms, stable)
→ Open ≈ 1.57 s (1560–1620 ms, stable)
overall mean 1366 ms / min 1142 / max 1620 / sd ~210 (dominated by the directional difference)
  • →Open is slower (WPA2 1.15 s < Open 1.57 s, consistent across both robots and all trials). This reverses the handshake-based intuition that WPA2 should be slower due to its 4-way handshake. The reason is a conjecture (not verified on-device): WPA2 (TEAM_SSID) is the firmware's default SSID, so →WPA2 reconnects to a known network via a fast scan/association path (possibly with PMKSA caching), whereas →Open targets a non-default SSID that requires a fresh scan and full association each time. The stable ~420 ms gap points to a scan/association-path difference rather than the handshake (which would make WPA2 the slower one).
  • Two measurement methods, SWMARK authoritative: Table 15 is the definitive figure from the on-device SWMARK method (recv→GOT_IP, network/batch-independent). The adopted values are the SWMARK 1.15 / 1.57 s.
  • Reference: the cycle_count-gap method and the 8.40/9.48 s outages: we also measured with a cycle_count-gap method. Most values were ~0 (<1 cycle), but it occasionally recorded an 8.40 s / 9.48 s outage (→normal mean 0.47 s/max 8.40 s, →open mean 0.68 s/max 9.48 s, outlier-dominated). This is an artifact stemming from the firmware behavior of reverting to the default SSID when not connected plus the toggle script's confusion of directional attribution (including batch-flush confounding and partial reconnection), not the true switch delay. Both methods are listed in the bundled data/ssid_switch_2026-06-26/README.md.
  • Behavior of the time domain: on re-association the TSF jumps to the new AP's value, but the HID and sniffer re-synchronize to the new AP's beacon. The calibration ring is also cleared at re-association and re-calibrates on the new AP's TSF (§5.1), so the measurement time axis recovers automatically after the switch.

Source / raw data: data/ssid_switch_2026-06-26 (on-device marker values + method). Reference: hid_bridge.md set_ssid

Reproduction note: switch time and startup time (§7.6) are hardware-in-the-loop measurements and, unlike the 5 OWD/loss metrics, cannot be re-run from the bundled data/ alone. The parsing/analysis scripts (switch_marker.py, switch_time.py, startup_time/measure.py) are vendored under owd_analyzer/. The raw on-device serial dumps (SWMARK markers) and boot-banner logs, however, are live captures requiring the 6 robots and are not bundled; the SWMARK instrumentation is a firmware variant of SanRei_HID.


Part V — Reproducibility and deliverables

9. Reproduction Guide (for other teams, technology transfer)

Aim: let other teams reproduce this measurement method on their own AP / robots in the shortest path. Core: modify neither the coach, the production firmware, nor the AP — just "overlay" the RasPi measurement system. Being AP-independent, a venue-provided AP is fine.

9.1 Minimal configuration

  • Raspberry Pi 5 (RPi OS)
  • an L2 switch capable of port mirroring (SPAN) (e.g. TP-Link TL-SG105E)
  • ESP32-C5 ×1 (sniffer: promiscuous + GPIO 1-PPS)
  • the Wi-Fi device under measurement (your own HID equivalent) and an AP (your own or venue-provided)

9.2 Setup

  1. switch: mirror the AP-connection port → to RasPi eth0.
  2. RasPi eth0: acquire wired frames with promisc on, AF_PACKET + SO_TIMESTAMPING (P1, NIC hardware timestamp, UNIX time domain t_wire_phc).
  3. sniffer: synchronize to the target AP, capture air in promiscuous mode, assign AP TSF to each frame (P2). Output 1-PPS on GPIO at the TSF 1-second boundary.
  4. PPS wiring: sniffer GPIO → RasPi /dev/pps0 (dtoverlay=pps-gpio). This establishes the AP TSF ↔ RasPi UNIX bridge (§5).
  5. device under measurement: embed the matching key (unique counter) at a fixed offset in the payload (adapt to your own protocol).

9.3 Running the measurement

  • Record wire + sniffer + PPS with the RasPi daemon (gtnlv-rpid equivalent).
  • Send the target traffic.
  • Build the PPS bridge with owd_analyzer → compute one-way OWD and loss (command examples in testplan.md).

9.4 Adaptation points for your own environment

  • How the matching key is embedded (offset, bit width, wrap) to fit your protocol.
  • The sniffer's destination filter (OUI/MAC) to your device.
  • Port numbers, unicast/broadcast distinction.
  • For many-robot downlink, air capture is missing due to A-MPDU aggregation, so measure downlink OWD with the air-independent wire + terminal declaration (§4.3).

References: GreenTea_NetworkLatencyViewer / SanRei_HID / robot_comm_spec


10. Public Deliverables (editable / source)

The editable deliverables (firmware, analysis, protocol, raw data) are listed in Table 16.

Table 16: Public deliverables and their locations.

Deliverable Location
production HID firmware SanRei_HID/src/ESP32C5Controller (§3.2)
measurement-system firmware GreenTea_NetworkLatencyViewer/tools/esp_firmware (§3.2)
protocol spec robot_comm_spec
headline-figure reproduction analysis/plot_owd.py (OWD, canonical) + owd_analyzer/longagg.py (loss)
analysis scripts (team-internal CSV pipeline) GreenTea_NetworkLatencyViewer/tools/owd_analyzer
raw data data/
live test plan GreenTea_NetworkLatencyViewer/testplan.md

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages