Pre-alpha

TrialONE for ROS 2

Point it at a log. It says what broke, why, and where the fix goes — as a file and a line in your own repository.

Quickstart

01

Install

Python 3.10 or newer, nothing else. Tested on Ubuntu 24.04 with Python 3.12 in a clean virtualenv. One command, no repository to clone.

# Ubuntu ships ensurepip separately; skip if you already have it
sudo apt install -y python3-venv

python3 -m venv .venv && source .venv/bin/activate
pip install https://trialone.wiki/trialone-0.1.0-py3-none-any.whl

trialone --help          # should list: diagnose, demo, watch, verify, fleet
02

See it work — 30 seconds, no key

A bundled recording with a real mid-run lidar dropout. It runs end to end and prints a finding, so you know the install is good before you point it at anything of yours.

trialone demo
03

Your own log

ROS 2 keeps them under ~/.ros/log/, one directory per run, with launch.log inside. A rosbag2 directory, an .mcap, a dmesg dump or a GDB backtrace work just as well — the format is sniffed.

trialone diagnose ~/.ros/log/<run>/launch.log

This is the deterministic half: it decodes what the machine reported about itself. It will tell you, at the end, that you are seeing only that half — and the one line that turns on the other.

04

The whole thing

One key. The provider follows from whichever one is set, so there is nothing else to configure. --project is your workspace, and it is what turns “this topic looks wrong” into a file and a line in your own code.

export ANTHROPIC_API_KEY=...     # or OPENROUTER_API_KEY, or GEMINI_API_KEY

trialone diagnose ~/.ros/log/<run>/launch.log \
    --project ~/ws/src \
    --symptom "the arm stops mid-cycle after a few minutes" \
    --explain --json

--symptom is worth the ten seconds: it is what you observed, in one sentence, and it steers the diagnosis toward the failure you actually care about rather than the loudest thing in the log. Measured cost of a run with --explain: about two cents.

05

What you get back

output/diagnosis_<name>.txt     # the full report, same as stdout
output/diagnosis_<name>.json    # one record per finding, nine fixed fields

The JSON is the handoff format: symptom, causal chain, the condition with its measured values, change class, affected files and lines, acceptance criterion, blast radius, effort. It is what you hand to a coding agent — Claude Code, Codex, Aider — rather than re-typing the finding yourself.

Your three questions

“how TrialONE integrates with ROS 2”

It reads what is already on disk — launch and console logs, rosbag2, MCAP. The format is sniffed, so you never pick a parser. Add --project ~/ws/src and findings resolve into your own code instead of stopping at a topic name; parameter files are found structurally, so you do not list them either. It does not attach to a running graph yet.

“what logs or data it needs”

One log file is enough to start. Also accepted: HDF5/CSV of repeated operations, ULog, ArduPilot .BIN, dmesg and kernel oops, GDB backtraces, firmware panic dumps. The workspace path is optional and it is what makes the output actionable.

“whether it can run locally”

Yes — that is the diagram below. Detection is deterministic and runs entirely on your machine. The interpretation layer calls a model, and you pick the provider, a local one included. Raw recordings never leave the machine.

What runs where

your machine launch.log ~/ws/src detect deterministic · local explain calls your model what is anomalous your model provider or a local model signal names, measured values file:line + patch nine fixed fields, JSON coding agent engineer software physical
The pale arrow is the only thing that leaves your machine — signal names and the values the interpretation step measured. The recording itself never does, and the provider on the other end is yours to choose.

What comes out

Unedited, from a public ros2_control incident: a joint_state_broadcaster that intermittently fails to configure with Resource temporarily unavailable, then a segfault in the executor destructor. Two hours and a maintainer, in the original thread.

The fix

Code/Setting that owns it: the `lock_memory` parameter in
`ros2_control_node.cpp` (line 64) and the system's RLIMIT_MEMLOCK.
It defaults to `has_realtime`, which is true on a PREEMPT_RT kernel.

Option A — in the launch/params file:
  controller_manager:
    ros__parameters:
      lock_memory: false

Option B — system configuration:
  * soft memlock unlimited
  * hard memlock unlimited

And in the same report — what it did not verify

the diagnosis names `mlockall`, `preempt_rt`, `rlimit_memlock` —
these appear neither in the artifact, nor in the deterministic
findings, nor in any tool result.

NAMED BUT NEVER OPENED: `/etc/security/limits.conf`

That second block is the part we care most about. Those three terms genuinely are knowledge rather than measurement — they are nowhere in the log — and the report says so instead of letting them pass as findings. Every report carries the same accounting: which instruments were used, which were never touched, which paths do not exist in your tree, and which claim of absence was never actually searched for.

What it does not do yet