Files
kaptan/docs/src/architecture.md
T

4.9 KiB

Architecture

Kaptan separates immutable board configuration from platform-owned runtime resources and portable flight logic.

board declaration
        │
        ▼
F722 platform / RTIC application ──► data channel ──► MAVLink telemetry
        │
        ├── physical sensor drivers
        └── startup motor-pin inhibition

portable libraries
  math ─► navigation ─► control ─► safety

Each F722 board contract pairs a board-owned UserConfig schema and explicit FACTORY_USER_CONFIG with a board-owned ImmutableConfig. The immutable root is one literal typestate manifest and the sole source of output inhibition, physical routes, driver setup, sensor mount, bootstrap line rates, status LED, image role, and service frequency. The user root contains only settings consumed by that compiled driver graph.

The data channel owns rate selection, mailbox consumption, message encoding, and bounded TX classification. Board code supplies physical routes, target schema, and factory values; it does not receive generic output authority.

Configuration and runtime observability are separate planes:

FILE_CONTROL / FILE_DATA
        │
        ▼
kaptan-file-mavlink ──► virtual FileProvider
                                 │
                           KCFG importer/exporter
                                 │
                           ConfigManager ──► private store

kaptan-log / kaptan-err-reportable
        │
        ▼
kaptan-diagnostics-mavlink ──► platform-owned encoder / DMA TX

The file dialect is intentionally Kaptan-native rather than standard MAVLink FTP, PARAM_*, or a QGC adapter. Its two messages know only bounded paths, bytes, positions, checksums, transfer ownership, and retries. The configuration provider maps /config/user.kcfg to a canonical self-describing artifact. KCFG carries generated metadata and a complete committed value set; the target streams it without retaining a whole-file buffer. Saving imports and validates one complete replacement candidate. The core distinguishes only immutable boot-active values from the latest committed values. A save cannot mutate controller or estimator state in flight.

Target-owned stores use private persistence formats. SITL atomically replaces a bounded CBOR snapshot. F722 alternates compact KCSP snapshots between two erase sectors, retaining only the old and replacement records across the commit boundary. Neither format is exposed as the public KCFG file. Motor allocation/mixer topology is immutable compiled vehicle capability data, never a scalar field or persistence member. F722 recovers operational settings before constructing consumers. Its directly wired local UART accepts only exact-target, CRC-valid Kaptan file requests while physical outputs remain inhibited. CRC is integrity-only; a shared or remote GCS still needs production authentication, source binding, and persistent anti-replay state. Disarmed activation and flight-consumer reconstruction remain separate reviewed work.

The MAVLink dialect root directly includes one-message XML leaves under publish/ and transfer/. The exchange/ contract remains empty until a current consumer justifies a message. There are no category index XML files or separate enum catalogs. The build watches the definitions tree and generates one generated::kaptan module; leaves are never separately generated Rust modules. kaptan-log itself has no MAVLink, platform, time, allocation, or filesystem dependency; its sole configuration coupling is compile-time enum metadata for LevelFilter. kaptan-err-reportable independently owns explicitly assigned reportable-error identity and a bounded nonblocking ingress; it has no logging, MAVLink, platform, filesystem, or clock dependency. Event creation is independent from sink filtering, allowing a future blackbox and MAVLink to select different policies. The platform drains reportable errors before its bounded critical and best-effort log queues and removes a pending record only after TX admission. LOG carries one conventional level plus one bounded text field; ERROR carries an explicitly assigned 16-bit ID and the bounded file:line of the reporting point. Its message kind already identifies a reportable firmware error. Kaptan-native heartbeat and sensor publications remain separate from diagnostics.

See Configuration for KCFG and the file-transfer contract, Logs for the receiver contract, and Errors for derived-error and failure-reporting scope.

Ownership rules

  • A peripheral owner is local to the platform runtime.
  • Portable crates use typed units and validated values rather than raw wire or timer representations.
  • A safety permit is epoch-bound and must be revalidated at the only nonzero output boundary.
  • A failed observation or numerical check does not partially commit estimator, controller, allocator, or safety state.