The companion collector
Get each run's companion evidence without exporting a journal by hand. The collector reads an allowlist on the companion computer, uploads over mutual TLS, spools offline and never talks to the flight controller.
On this page9
The flight log shows what PX4 did. The companion computer's journal and processes show what the autonomy stack around it was doing, and the collector brings both in after every segment. It is optional: Foxborne works from imported files alone.
What it reads#
Collector policy, at the top right of the Vehicle collectors tab, opens a drawer that shows the policy in force under What the collector reads. In the example dataset it reads:
| Setting | Value |
|---|---|
| Journal units | perception.service, mavlink-router.service, chronyd.service, collector.service, kernel |
| Processes | perception_node, mavlink-routerd |
| Sample rate | 1 per second: CPU, resident memory, restart count |
| Clock | Wall time, monotonic time, boot ID and chrony status on every sample. SYSTEM_TIME pairs from 0.8. |
| Spool budget | 100 MB. When full, low-priority samples go first and a lost-data marker is written. |
| Never collected | Environment variables, process arguments, camera frames. |
Only the listed units leave the vehicle, and everything else in the journal is ignored there. The kernel entry brings the kernel's own messages, such as an OOM kill or a USB disconnect. Admins change the lists, the rate, the budget and the redaction patterns in the collector policy.
What it cannot do#
The same drawer's What the collector cannot do states four limits, and they hold on every vehicle:
- Open a port. It connects outbound only, over mutual TLS, and holds no command channel.
- Talk to the flight controller. It never sends MAVLink, and it cannot arm, move or reconfigure the vehicle.
- Change the autonomy stack. It reads the journal and
/proc, nothing else. - Lose data quietly. Offline samples are spooled, acknowledged before deletion, and any drop is written as a marker.
How it connects#
Each collector connects outbound to your deployment over mutual TLS, with a certificate that belongs to its vehicle alone. It receives that certificate at enrollment, in exchange for a one-time token that expires 30 minutes after the console shows it. Nothing connects to the vehicle, and no port opens on it.
On the Connections tab, all collectors appear as one source, Companion collectors. Its drawer shows Outbound only, mutual TLS under Access, Per-vehicle certificate under Credential and Batched upload after each segment under Schedule.
The collector closes its data into segments and uploads each one as it closes. In the example dataset's INC-0143, its own journal lines on UGV-02 show a segment a minute. One closed while the radio was off the USB bus:
| Time, UTC | The collector's journal line |
|---|---|
| 15:40:10.004 | segment 43 closed, 1.2 MB, uploaded |
| 15:41:10.006 | segment 44 closed, 1.1 MB, upload failed (network unreachable), spooled on the vehicle |
| 15:42:10.003 | segment 45 closed, 1.0 MB, uploaded with 1 spooled segment |
Offline spooling and the lost-data marker#
With no uplink, the collector keeps recording and holds its segments on the vehicle. Spooled data is acknowledged before the collector deletes it, and uploads resume on their own when the link returns.
The spool has a budget, 100 MB by default. When it fills, the collector drops the oldest low-priority samples first and writes a lost-data marker where they were. The gap then shows on the timeline instead of passing unnoticed.
| Example | What the console shows |
|---|---|
| UGV-05 behind the berm | Buffering with 18.4 MB spooled, and the note Working behind the berm. No uplink for 12 minutes, spooling locally. |
| UAS-05 on 25 Sep | 1,204 under Dropped, with the reason Spool budget reached on 25 Sep. Oldest low-priority samples were dropped and marked. |
| UGV-05 in INC-0137 | 31.2 MB spooled during a link loss. The timeline shows collector: uplink restored, uploading 31.2 MB, then collector: upload complete, 38,904 records acknowledged, and no samples were lost. |
Evidence that arrives late keeps its event time. The evidence inspector shows Ingested beside it, with how long after the event it arrived, so a reviewer sees both times.
Redaction on the vehicle#
The collector redacts configured patterns before a line leaves the vehicle. The policy's Redact from journal lines holds regular expressions, by default AKIA[0-9A-Z]{16} and Bearer [A-Za-z0-9._-]+. Text that matches is replaced on the vehicle, before upload.
Settings keeps named Patterns removed from logs, such as AWS access keys and Bearer tokens. It states that they are Applied on the vehicle before upload. See Retention, holds and redaction.
Environment variables, process arguments and camera frames are never collected at all.
A clock on every sample#
Each sample carries wall time, monotonic time, the boot ID and chrony's status. Process samples share the journal's clock and its bound, ±6 ms in run R-0931 of the example dataset. The run page lists them as Companion monotonic, same boot as journal, anchored by Shared boot ID.
The tab's Clock column shows chrony's view on each vehicle. It reads Synced +0.8 ms with the current offset, Not synchronised when chrony has no source or Unknown.
The Vehicle collectors tab#
A summary strip opens the tab. In the example dataset it reads Enrolled 15 of 16, Online 13, Buffering offline 1 and Offline 1. Clock warnings shows 1, and Collector version shows 0.8.1 with 2 on 0.7.3.
The status bar at the bottom of every screen repeats the count as 13 of 15 collectors reporting.
| Column | What it shows |
|---|---|
| Vehicle | The vehicle ID, with the companion's host name under it, for example UGV-02 and ugv02-agx |
| Collector | The installed version. Version 0.7.3 adds No SYSTEM_TIME, and a vehicle without a collector shows Not installed. |
| Clock | Synced with chrony's offset, Not synchronised or Unknown |
| Local spool | None, or a bar with the megabytes held, for example 18.4 of 100 MB |
| Last upload | When the last segment arrived, or Never |
| Dropped | Samples discarded when the spool filled, with the reason on hover, or 0 |
| State | Online, Buffering, Offline or Not enrolled, with a note under the chip when there is one, such as In maintenance since 24 Sep |
Rows without a collector offer Enroll. Rows on an older version offer Update.
Versions 0.8.1 and 0.7.3#
| Version | SYSTEM_TIME pairs | In the example dataset |
|---|---|---|
| 0.8.1 | Recorded | 13 of the 15 enrolled vehicles |
| 0.7.3 | Not recorded, and the tab shows No SYSTEM_TIME | UAS-07 and UGV-06 |
Version 0.8.1 records MAVLink SYSTEM_TIME pairs, which give companion evidence a shared anchor with the flight log. The difference shows when chrony fails. In the example dataset's INC-0139, UAS-07 ran 0.7.3 and chrony never synchronized, so its journal and samples stayed on their own clock.
That report could not say whether a perception crash came before or after the obstacle data stalled. An engineer can still align the clock by hand, and Update an older collector moves a vehicle to 0.8.1.