Embedded Linux platform / 2024 to present
HeliOS
HeliOS hides routine Linux administration without hiding the system from its developers.
Explore repositoryOperations should feel calm, even when the system is not.
Each screen translates a device responsibility into an operator task: understand health, register hardware, change persistent settings, or recover a unit without administering Linux services.
A vision appliance has to make camera discovery, graph authoring, performance tuning, robot output, updates, and support legible to a team that should never need to administer Linux.
The implementation still needs clear hot-path, API, peripheral, image, and failure boundaries so one change does not destabilize the whole device.
I built a local-first platform around generated contracts and supervised services.
The browser configures and observes a separate engine over the API; Styx and Daedalus own reusable media and graph concerns; Gaia and Buildroot reproduce the system image; persistent data, A/B roots, USB networking, and diagnostic hooks provide field safeguards.
One operator surface over replaceable services.
The browser, API, processing engine, hardware services, update system, and recovery path all run on the camera computer. A team sees one appliance, while media capture and graph execution remain reusable runtimes below product-specific behavior.
- 01 Operator layer
Local Svelte UI · HTTP · WebSocket
- 02 Product services
API · engine · peripherals · updater · recovery
- 03 Runtime layer
Styx capture · Daedalus graph · product plugins
- 04 System image
Buildroot Linux · supervised services · two bootable slots · persistent setup
- Ethernet
- USB networking
- Local diagnostics
- Restart policy
- Failure bundles
- Previous image retained
The decisions beneath the summary.
Appliance workflow
The browser is the operator’s entry point for device discovery, camera and sensor registration, visual pipeline authoring, live tuning, metrics, benchmarking, updates, logs, and support evidence. The UI talks through generated HTTP and WebSocket clients, while the API coordinates the engine and other services over explicit local boundaries. That keeps the interaction coherent without putting frame processing, hardware control, and update policy into the web server.
- Contract boundary: Rust schemas generate the HTTP, event, and TypeScript definitions, so a backend change cannot rely on a separately handwritten browser model
- First-run behavior: a new unit can start with working stream and pipeline presets, but the seeding rule will not overwrite later operator changes
- Field assumption: the entire workflow remains on one local URL because competition robots cannot rely on cloud connectivity
Frame hot path
helios-engine owns camera-to-result execution. Styx supplies discovery, capture, FrameLease ownership, queues, and media stages; Daedalus validates and schedules editable processing graphs. HeliOS plugin crates add the product’s CV, AI, NetworkTables, and LED behavior. The API can configure and observe the engine without becoming part of the frame path, and the lower runtimes remain useful outside this product.
- Control boundary: local inter-process messages let the API change configuration without joining the engine’s frame and worker lifecycle
- Operator consequence: graph validation, live node metrics, and benchmarks expose an expensive or invalid pipeline before a team relies on it in a competition match
- Robot boundary: NetworkTables, the protocol commonly used to exchange FRC robot data, remains a product output plugin instead of a graph-runtime dependency
Services and failure domains
API, engine, peripherals, updater, and recovery responsibilities run as separate systemd services with explicit startup and restart relationships. A failed engine should not remove the configuration interface; an update service should not own sensors; and support data should be gathered automatically while the relevant process and logs still exist.
- Failure policy: systemd defines dependency order, restart behavior, and automatic diagnostic collection when a core service exits
- Isolation benefit: peripheral or update code can restart or change without expanding the frame engine’s responsibility
- Support path: one bundle gathers service logs, system state, and product evidence that a remote team can send without shell access
Image, state, and recovery
Gaia composes the HeliOS Buildroot image for CM5 hardware, including applications, services, kernel and device-tree work, filesystems, and disk layout. Replaceable root slots hold system software while DATA holds mutable device state. Input fingerprints can skip unchanged frontend work, and direct USB networking or serial paths remain available when the normal robot network is not.
- Update safeguard: two read-only system slots retain the previous bootable image while a replacement is installed
- State safeguard: operator configuration lives outside the system image, so replacing software does not also erase device setup
- Release boundary: Gaia layers separate the base OS, board boot mechanics, product content, and update policy so a board change does not fork the whole build
What this work does not claim.
HeliOS is a local device platform, not a cloud fleet-management product.
A/B roots reduce system-update risk, but arbitrary changes to mutable application data still need compatible migrations.
Camera, device-tree, boot, and hardware-service validation must run on supported CM5 and camera hardware; generic CI cannot prove those physical paths.
Architecture, evidence, and limits.
Explore repository ↗Architecture
- 01 Local operator surface
one on-device URL fronts the static interface and its HTTP and WebSocket APIs, so normal use does not depend on cloud access
- 02 Separate failure domains
API, engine, peripherals, updater, and recovery services can restart and collect diagnostics without becoming one process
- 03 Product policy over reusable runtimes
HeliOS composes Styx and Daedalus, while CV, AI, NetworkTables, and LED behavior stays in product plugin crates
- 04 Immutable system slots plus mutable data
updates replace the inactive root image while user configuration survives on a separate partition
Validation
- 01 Deployment evidence
repository-owned Gaia layers, Buildroot overlays, service units, and cross-compiled applications produce the CM5 image used by the product
- 02 Contract evidence
Rust schemas generate the browser API clients, reducing undocumented drift between the operator interface and backend services
- 03 Failure-path evidence
systemd hooks retain service diagnostics, and USB gadget networking remains available when normal Ethernet configuration is unavailable
Why it matters in practice.
- 01Replaces command-line service setup with one local workflow for cameras, pipelines, live health, updates, logs, and recovery
- 02Keeps frame processing outside the web server, allowing the operator interface, API, engine, peripherals, and updater to fail or evolve at their own boundaries
- 03Preserves a field recovery path with a previous system image, separate user data, failure bundles, and direct USB networking
- Image and build workflow
- Device service packaging
- CM5 deployment
- Product integration
- Buildroot / Gaia
- Linux
- Bash
- Rust services
- Image builds