docs: document the kaptan-native protocol
This commit is contained in:
1 parent
5f91465e66
commit
4bc98adbc6
10 files changed
+314
-307
No files matched your search
+48
-53
@@ -27,73 +27,68 @@ The data channel owns rate selection, mailbox consumption, message encoding,
|
|||||||
and bounded TX classification. Board code supplies physical routes, target
|
and bounded TX classification. Board code supplies physical routes, target
|
||||||
schema, and factory values; it does not receive generic output authority.
|
schema, and factory values; it does not receive generic output authority.
|
||||||
|
|
||||||
Configuration and runtime observability are separate, one-way planes:
|
Configuration and runtime observability are separate planes:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Kaptan GCS custom MAVLink V2 messages
|
FILE_CONTROL / FILE_DATA
|
||||||
│ (future: verified signing, source binding, replay state)
|
│
|
||||||
▼
|
▼
|
||||||
kaptan-config-mavlink ──► state-only ConfigProtocol
|
kaptan-file-mavlink ──► virtual FileProvider
|
||||||
│ borrows
|
|
||||||
kaptan-flight-runtime
|
|
||||||
├── one ConfigManager ──► kaptan-config ──► flight schema/store
|
|
||||||
└── one bounded MAVLink log-sink queue
|
|
||||||
│
|
│
|
||||||
kaptan-diagnostics-mavlink payload adapter
|
KCFG importer/exporter
|
||||||
│
|
│
|
||||||
platform-owned sole encoder / DMA TX link
|
ConfigManager ──► private store
|
||||||
|
|
||||||
|
kaptan-log / kaptan-err-reportable
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
kaptan-diagnostics-mavlink ──► platform-owned encoder / DMA TX
|
||||||
```
|
```
|
||||||
|
|
||||||
The generated dialect is intentionally custom rather than a `PARAM_*` or QGC
|
The file dialect is intentionally Kaptan-native rather than standard MAVLink
|
||||||
adapter. The core uses numeric field IDs and typed scalar values; descriptor
|
FTP, `PARAM_*`, or a QGC adapter. Its two messages know only bounded paths,
|
||||||
text is metadata, not a wire identity. Discovery/value reads, exact-index
|
bytes, positions, checksums, transfer ownership, and retries. The configuration
|
||||||
descriptor and enum-option requests, and structured results are custom-dialect
|
provider maps `/config/user.kcfg` to a canonical self-describing artifact.
|
||||||
records. Runtime logs use one bounded text message with a conventional level
|
KCFG carries generated metadata and a complete committed value set; the target
|
||||||
and flags. Remote writes use only schema-described typed scalar setters. The core
|
streams it without retaining a whole-file buffer. Saving imports and validates
|
||||||
owns one RAM transaction and the distinction
|
one complete replacement candidate. The core distinguishes only immutable
|
||||||
between boot-active, committed, and editable candidate snapshots. In the
|
boot-active values from the latest committed values. A save cannot mutate
|
||||||
current P1 policy a commit is restart-only. It cannot mutate controller or
|
controller or estimator state in flight.
|
||||||
estimator state in flight.
|
|
||||||
|
|
||||||
Target-owned stores may serialize one bounded complete CBOR snapshot. SITL
|
Target-owned stores use private persistence formats. SITL atomically replaces a
|
||||||
supplies the host file adapter and atomically replaces that snapshot through a
|
bounded CBOR snapshot. F722 alternates compact `KCSP` snapshots between two
|
||||||
same-directory temporary file. The serialization is not configuration state
|
erase sectors, retaining only the old and replacement records across the commit
|
||||||
and is never exposed by the MAVLink protocol.
|
boundary. Neither format is exposed as the public KCFG file.
|
||||||
Motor allocation/mixer topology is immutable compiled vehicle capability data,
|
Motor allocation/mixer topology is immutable compiled vehicle capability data,
|
||||||
never a scalar field or CBOR candidate member. F722 now recovers operational
|
never a scalar field or persistence member. F722 recovers operational settings
|
||||||
settings from a generic two-slot journal before constructing consumers. Its
|
before constructing consumers. Its directly wired local UART accepts only
|
||||||
directly wired local UART accepts only exact-target, CRC-valid configuration
|
exact-target, CRC-valid Kaptan file requests while physical outputs remain
|
||||||
commands while physical outputs remain inhibited. CRC is integrity-only; a
|
inhibited. CRC is integrity-only; a shared or remote GCS still needs production
|
||||||
shared or remote GCS still needs production authentication, durable audit
|
authentication, source binding, and persistent anti-replay state. Disarmed
|
||||||
logging, source binding, and persistent anti-replay state. Disarmed activation
|
activation and flight-consumer reconstruction remain separate reviewed work.
|
||||||
and flight-consumer reconstruction remain separate reviewed work and cannot be
|
|
||||||
implied by a valid snapshot or CRC.
|
|
||||||
|
|
||||||
Configuration wire layout `2.0` uses one exact response per descriptor or enum
|
The MAVLink dialect root directly includes one-message XML leaves under
|
||||||
option request. The first accepted transaction binds one source principal
|
`publish/` and `transfer/`. The `exchange/` contract remains empty until a
|
||||||
through a bounded post-terminal replay lease; foreign traffic cannot evict a
|
current consumer justifies a message. There are no category index XML files or
|
||||||
lost result before that lease expires.
|
separate enum catalogs. The build watches the definitions tree and generates
|
||||||
|
one `generated::kaptan` module; leaves are never separately generated Rust
|
||||||
The MAVLink dialect root includes `kaptan/config.xml`, `kaptan/log.xml`, and
|
modules. `kaptan-log` itself has
|
||||||
`kaptan/error.xml`.
|
|
||||||
The build watches every fragment and generates one `message::kaptan` module;
|
|
||||||
fragments are never separately generated Rust modules. `kaptan-log` itself has
|
|
||||||
no MAVLink, platform, time, allocation, or filesystem dependency; its sole
|
no MAVLink, platform, time, allocation, or filesystem dependency; its sole
|
||||||
configuration coupling is compile-time enum metadata for `LevelFilter`.
|
configuration coupling is compile-time enum metadata for `LevelFilter`.
|
||||||
`kaptan-err-reportable` independently owns explicitly assigned reportable-error
|
`kaptan-err-reportable` independently owns explicitly assigned reportable-error
|
||||||
identity and a bounded nonblocking ingress; it has
|
identity and a bounded nonblocking ingress; it has no logging, MAVLink,
|
||||||
no logging, MAVLink, platform, filesystem, or clock dependency. Event creation
|
platform, filesystem, or clock dependency. Event creation is independent from
|
||||||
is independent from sink filtering, allowing a future blackbox and MAVLink to
|
sink filtering, allowing a future blackbox and MAVLink to select different
|
||||||
select different policies. The platform drains reportable errors before its bounded
|
policies. The platform drains reportable errors before its bounded critical and
|
||||||
critical and best-effort log queues and removes a pending record only after TX
|
best-effort log queues and removes a pending record only after TX admission.
|
||||||
admission. `KAPTAN_LOG` carries one conventional level plus one bounded text
|
`LOG` carries one conventional level plus one bounded text field; `ERROR`
|
||||||
field; `KAPTAN_ERROR` carries an explicitly assigned 16-bit ID and the bounded
|
carries an explicitly assigned 16-bit ID and the bounded `file:line` of the
|
||||||
`file:line` of the reporting point. Its
|
reporting point. Its message kind already identifies a reportable firmware
|
||||||
message kind already identifies a reportable firmware error. Heartbeat and safety
|
error. Kaptan-native heartbeat and sensor publications remain separate from
|
||||||
telemetry remain separate from diagnostics.
|
diagnostics.
|
||||||
|
|
||||||
See [Configuration](configuration.md) for the deployment matrix and GCS transaction
|
See [Configuration](configuration.md) for KCFG and the file-transfer contract,
|
||||||
contract, [Logs](logs.md) for the receiver contract, and [Errors](errors.md)
|
[Logs](logs.md) for the receiver contract, and [Errors](errors.md)
|
||||||
for derived-error and failure-reporting scope.
|
for derived-error and failure-reporting scope.
|
||||||
|
|
||||||
## Ownership rules
|
## Ownership rules
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ MAVLink telemetry on USART2. It declares no vertical sensor stream. The
|
|||||||
manufacturer's [GEP-F722-HD V2 manual](https://geprc.com/wp-content/uploads/2025/05/GEP-F722-HD-v2%E9%A3%9E%E6%8E%A7_%E4%BA%A7%E5%93%81%E8%AF%B4%E6%98%8E%E4%B9%A6-.pdf)
|
manufacturer's [GEP-F722-HD V2 manual](https://geprc.com/wp-content/uploads/2025/05/GEP-F722-HD-v2%E9%A3%9E%E6%8E%A7_%E4%BA%A7%E5%93%81%E8%AF%B4%E6%98%8E%E4%B9%A6-.pdf)
|
||||||
labels the external UART2 pads `T2` and `R2`.
|
labels the external UART2 pads `T2` and `R2`.
|
||||||
|
|
||||||
Its board-local `UserConfig` factory selects endpoint `1/1`, raw-IMU and
|
Its board-local `UserConfig` factory selects endpoint `1/1`, IMU and
|
||||||
heartbeat publication rates, and an enabled MAVLink diagnostic sink with an
|
heartbeat publication rates, and an enabled MAVLink diagnostic sink with an
|
||||||
`Info` level filter. The web configurator may replace those
|
`Info` level filter. The web configurator may replace those
|
||||||
target-advertised values in the journal. Range
|
target-advertised values in the journal. Range
|
||||||
@@ -59,7 +59,7 @@ Then run:
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
cargo run --locked -p kaptan-configurator -- \
|
cargo run --locked -p kaptan-configurator -- \
|
||||||
--serial /dev/serial/by-id/<adapter> --baud 115200
|
--source-system 255 --serial /dev/serial/by-id/<adapter> --baud 115200
|
||||||
```
|
```
|
||||||
|
|
||||||
Open `http://127.0.0.1:4861`, Save the discovered fields, and manually
|
Open `http://127.0.0.1:4861`, Save the discovered fields, and manually
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ MAVLink telemetry on USART1, and the MTF01 range/optical-flow route on UART4.
|
|||||||
The checked-in manufacturer datasheet is
|
The checked-in manufacturer datasheet is
|
||||||
`firmware/boards/kakute-f7-mini-v3/datasheet.pdf`.
|
`firmware/boards/kakute-f7-mini-v3/datasheet.pdf`.
|
||||||
|
|
||||||
Its board-local `UserConfig` factory selects endpoint `1/1`, raw-IMU, range,
|
Its board-local `UserConfig` factory selects endpoint `1/1`, IMU, range,
|
||||||
optical-flow and heartbeat publication rates, and an enabled MAVLink diagnostic
|
optical-flow and heartbeat publication rates, and an enabled MAVLink diagnostic
|
||||||
sink with an `Info` level filter. The web configurator may replace those
|
sink with an `Info` level filter. The web configurator may replace those
|
||||||
target-advertised values in the journal. Its `ImmutableConfig` keeps the
|
target-advertised values in the journal. Its `ImmutableConfig` keeps the
|
||||||
@@ -64,7 +64,7 @@ Launch the target-described web UI:
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
cargo run --locked -p kaptan-configurator -- \
|
cargo run --locked -p kaptan-configurator -- \
|
||||||
--serial /dev/serial/by-id/<adapter> --baud 115200
|
--source-system 255 --serial /dev/serial/by-id/<adapter> --baud 115200
|
||||||
```
|
```
|
||||||
|
|
||||||
Open `http://127.0.0.1:4861`, edit the discovered fields, press Save, and
|
Open `http://127.0.0.1:4861`, edit the discovered fields, press Save, and
|
||||||
|
|||||||
+141
-177
@@ -1,18 +1,18 @@
|
|||||||
# Configuration
|
# Configuration
|
||||||
|
|
||||||
Kaptan has one generic configuration lifecycle in `kaptan-config`: descriptors,
|
Kaptan has one generic configuration model in `kaptan-config`. Target schemas
|
||||||
typed writes, transactions, validation, scalar snapshots, and a
|
declare typed fields and validation once; derive code generates the stable
|
||||||
power-loss-safe two-slot journal. Target models declare fields once; derive code
|
field registry and schema fingerprint. Boards supply the sole erased-flash
|
||||||
generates the registry consumed by both the protocol and the browser. There is
|
factory values. The browser contains no board, driver, sensor, schema, or
|
||||||
no board, driver, sensor, schema, or parameter catalog in the configurator.
|
parameter catalog.
|
||||||
|
|
||||||
## Current deployment matrix
|
## Current deployment matrix
|
||||||
|
|
||||||
| Deployment | Configuration consumed today | Remote writes |
|
| Deployment | Configuration consumed today | Remote writes |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `kaptan-sitl serve --config FILE.cbor` | One validated Quad-X configuration at process construction. | No live MAVLink endpoint is attached yet. |
|
| `kaptan-sitl serve --config FILE.cbor` | One validated Quad-X configuration at process construction. | No live file endpoint is attached yet. |
|
||||||
| `kaptan-sitl serve` | The validated factory Quad-X configuration. | No persistent store; commits are rejected. |
|
| `kaptan-sitl serve` | The validated factory Quad-X configuration. | No persistent store. |
|
||||||
| STM32F722 image | Board factory settings, or the newest valid flash-journal snapshot. | Enabled on the directly wired local UART while motor pins remain inhibited. |
|
| STM32F722 image | Board factory settings, or the newest valid flash-journal snapshot. | `/config/user.kcfg` on the directly wired local UART while motor pins remain inhibited. |
|
||||||
|
|
||||||
## Web configurator
|
## Web configurator
|
||||||
|
|
||||||
@@ -21,208 +21,172 @@ USB-UART adapter, then run from `firmware`:
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
cargo run --locked -p kaptan-configurator -- \
|
cargo run --locked -p kaptan-configurator -- \
|
||||||
--serial /dev/serial/by-id/<adapter> --baud 115200
|
--source-system 255 --serial /dev/serial/by-id/<adapter> --baud 115200
|
||||||
```
|
```
|
||||||
|
|
||||||
Open `http://127.0.0.1:4861`. Edit discovered fields and press
|
`--source-system` is the configurator's exact MAVLink source identity. Every
|
||||||
Save. Save commits the complete candidate to the inactive flash slot and writes
|
simultaneously connected GCS must use a different nonzero system ID so transfer
|
||||||
the commit marker last. The active runtime does not change. Once Save completes,
|
ownership and retries cannot alias another client.
|
||||||
manually power-cycle the controller to recover the committed journal and
|
|
||||||
activate it.
|
Open `http://127.0.0.1:4861`. On discovery, the configurator downloads the
|
||||||
|
complete `/config/user.kcfg` artifact, validates it, and renders the metadata
|
||||||
|
and values contained in that file. Save produces one complete edited KCFG
|
||||||
|
artifact and uploads it. The target validates the complete candidate before
|
||||||
|
atomically persisting it. The boot-active runtime does not change; manually
|
||||||
|
power-cycle the controller after a successful save when the UI reports that a
|
||||||
|
restart is required.
|
||||||
|
|
||||||
Saving erases one 128-KiB STM32F7 journal sector synchronously. Expect roughly
|
Saving erases one 128-KiB STM32F7 journal sector synchronously. Expect roughly
|
||||||
one second without telemetry or sensor servicing while the target flash
|
one second without telemetry or sensor servicing while the target flash
|
||||||
controller is busy; the host uses a separate five-second Save timeout. Keep the
|
controller is busy; the host gives the final close a separate five-second
|
||||||
vehicle unpowered except for setup power and do not disconnect it during Save.
|
timeout. Keep the vehicle unpowered except for setup power and do not disconnect
|
||||||
|
it during Save.
|
||||||
|
|
||||||
The tool discovers the target's protocol version and schema identity, renders
|
The artifact carries generated field IDs, native scalar kinds, display keys,
|
||||||
advertised descriptors, and reads/writes values only by stable `FieldId`. A new
|
units, bounds, enum choices, factory values, committed values, schema identity,
|
||||||
board or field needs no host release. The board package remains the composition
|
and the derived restart-required state. A new board or field therefore needs no
|
||||||
root for erased-flash defaults; the platform never switches on a board name.
|
configurator release. `u8`, `u16`, and enum-backed values retain their native
|
||||||
Enum-backed fields advertise their valid value/label pairs through exact
|
width rather than being widened at the configuration boundary.
|
||||||
descriptor and option-index requests, so the browser renders a select control
|
|
||||||
without knowing the field key or compiling its choices.
|
|
||||||
|
|
||||||
The Incoming MAVLink table at the bottom groups live, CRC-valid packets by
|
The Incoming MAVLink table groups live, CRC-valid Kaptan packets by source and
|
||||||
source and message ID and shows the measured receive frequency and total count.
|
message ID and shows receive frequency and total count. Selecting a message
|
||||||
Names come from the generated MAVLink dialect decoders; the browser contains no
|
watches its latest decoded value. The separate Runtime logs view retains
|
||||||
message catalog. Selecting a message name shows the latest decoded field values;
|
individual `LOG` and `ERROR` events in receive order, with local receive time,
|
||||||
the diagnostic projection renders the `KAPTAN_ERROR` ID and reporting
|
level, and readable text.
|
||||||
`file:line`. The
|
|
||||||
configurator keeps only one latest value per bounded aggregate,
|
|
||||||
rather than packet history, and clears it for every serial-link session.
|
|
||||||
|
|
||||||
The separate Runtime logs section retains the most recent 512 `KAPTAN_LOG` and
|
## Board ownership
|
||||||
`KAPTAN_ERROR` events in receive order. Each row shows local receive time,
|
|
||||||
decoded level, and readable diagnostic text. Repeated events remain separate;
|
|
||||||
older host-side entries are discarded at the fixed display bound and the UI
|
|
||||||
reports that count. A visible `TRUNCATED` badge marks bounded `KAPTAN_LOG`
|
|
||||||
text. This
|
|
||||||
event history is independent of the packet table's
|
|
||||||
single latest-value projection and resets when the serial link changes.
|
|
||||||
|
|
||||||
Each F722 board owns the exact settings consumed by its compiled image. Both
|
Each F722 board declares one `UserConfig` root for the settings consumed by its
|
||||||
current boards advertise:
|
compiled driver graph. The explicit `FACTORY_USER_CONFIG` literal is the sole
|
||||||
|
erased-flash value. There is no `Default` implementation and no platform-wide
|
||||||
|
union of board schemas.
|
||||||
|
|
||||||
- MAVLink system and component identity;
|
Both current boards expose MAVLink identity, IMU and heartbeat publication
|
||||||
- raw-IMU and heartbeat publication rates; and
|
rates, and the MAVLink log level filter. Kakute also exposes range and
|
||||||
- the MAVLink diagnostic sink's Off/Error/Warn/Info/Debug/Trace level filter.
|
optical-flow rates because its immutable hardware manifest contains an MTF01.
|
||||||
|
Those fields are absent from GEPRC rather than present-but-disabled.
|
||||||
|
|
||||||
The Kakute image also advertises range and optical-flow publication rates
|
The adjacent `IMMUTABLE_CONFIG` literal remains the sole source of facts that
|
||||||
because its immutable route includes an MTF01. The GEPRC image declares no
|
cannot safely be edited as scalar configuration:
|
||||||
vertical sensor, so those fields are absent rather than present-but-disabled.
|
|
||||||
|
|
||||||
The UART baud is the immutable bootstrap link for this first configuration
|
- output-inhibit and status-LED routes;
|
||||||
transport. Pass it explicitly to the host with `--baud`.
|
- IMU model, bus, interrupt route, mount, and driver setup;
|
||||||
|
- MAVLink and optional vertical-sensor routes and bootstrap baud rates;
|
||||||
|
- service-timer frequency; and
|
||||||
|
- compiled image role.
|
||||||
|
|
||||||
Each board declares one `UserConfig` root for its compiled driver graph. That
|
The F722 platform consumes stable semantic field IDs through the generic
|
||||||
root composes board-local `MavlinkConfig` and `TelemetryConfig` records; derive
|
`Config::field_value` boundary. It does not know a board section, Rust field,
|
||||||
code generates recursive routing, validation, and the schema fingerprint. The
|
or aggregate shape. Whole-candidate validation checks both generated local
|
||||||
board's explicit `FACTORY_USER_CONFIG` literal supplies erased-flash values.
|
rules and relationships such as publication budget and immutable hardware
|
||||||
Board-native IDs and publication rates retain their narrow `u8` representation.
|
capabilities.
|
||||||
Compact enums advertise names and values through explicit indexed descriptor
|
|
||||||
metadata rather than a hardcoded browser-side configuration catalog.
|
|
||||||
There is no platform-wide union, reusable concrete board schema, or host-side
|
|
||||||
switch.
|
|
||||||
|
|
||||||
The F722 platform consumes only its stable semantic field IDs through the
|
## KCFG artifact
|
||||||
generic `Config::field_value` boundary; it never names a board section, Rust
|
|
||||||
field, or aggregate shape. Range and optical-flow rates are required only when
|
|
||||||
the immutable hardware manifest exposes those capabilities. Driver- and
|
|
||||||
board-specific fields remain in the same discovered tree without platform
|
|
||||||
forwarding code.
|
|
||||||
|
|
||||||
The adjacent `IMMUTABLE_CONFIG` literal is the complete physical manifest. Its
|
KCFG is the public, canonical import/export representation. It is independent
|
||||||
typestate expression visibly selects the inhibited output pins, IMU route,
|
of MAVLink and of the private storage format. A file contains:
|
||||||
mount and driver setup, MAVLink route and baud, optional vertical-sensor route
|
|
||||||
and baud, status LED, and telemetry-only role. Those choices are not hidden in
|
|
||||||
board-specific getters or a `build()` function.
|
|
||||||
|
|
||||||
The current SITL configuration has only settings consumed by its estimator,
|
- `KCFG` magic and one format version;
|
||||||
controller, safety supervisor, allocator envelope, or MAVLink diagnostic sink:
|
- generated 16-byte schema identity and exact field count;
|
||||||
|
- one canonical self-describing record for every field; and
|
||||||
|
- a big-endian CRC-32C trailer covering the preceding artifact bytes.
|
||||||
|
|
||||||
- prearm dwell;
|
The trailer uses network byte order deliberately. The generic file dialect
|
||||||
- IMU, local-aiding, and command freshness/timing;
|
also calculates CRC-32C over every complete file byte; network-order storage
|
||||||
- position/velocity aiding variance;
|
keeps that independent transfer checksum content-specific instead of producing
|
||||||
- outer-loop gains and acceleration limits;
|
the fixed residue obtained by appending a reflected CRC in little-endian order.
|
||||||
- mass, collective-thrust, and tilt limits;
|
|
||||||
- rate PID gains and limits;
|
|
||||||
- actuator minimum, maximum, and slew limits; and
|
|
||||||
- the restart-only MAVLink diagnostic-sink level filter.
|
|
||||||
|
|
||||||
The fixed Quad-X mixer is intentionally not configurable. It is reviewed
|
An imported file must match the target-generated schema, descriptor metadata,
|
||||||
capability data, not a user-editable array.
|
factory values, field order, native scalar kinds, and exact length. Unknown,
|
||||||
|
duplicate, missing, malformed, noncanonical, out-of-range, and relationally
|
||||||
|
invalid values are rejected. The target stages only the typed candidate and a
|
||||||
|
small parser state; it never buffers the complete public file. Exports are also
|
||||||
|
generated by range directly from compiled metadata and current committed
|
||||||
|
values. One small export plan containing the exact length and checksums is
|
||||||
|
prepared when a read opens and reused for every requested range.
|
||||||
|
|
||||||
Each editable scalar declares its ID, display key, unit, type, and local
|
Schema identity is required because a complete file can otherwise be validly
|
||||||
validation in one `#[config(...)]` attribute. Unannotated fields of a derived
|
encoded while belonging to another firmware schema. It is generated from the
|
||||||
record are configuration children; no per-field section marker is needed.
|
schema and is not a hand-maintained board ID.
|
||||||
Factory values belong to the composition root, not the field attributes or a
|
|
||||||
`Default` implementation. The only handwritten checks are whole-candidate
|
|
||||||
physical relationships such as thrust margin, timing ordering, actuator
|
|
||||||
limits, and compatibility with immutable target capabilities.
|
|
||||||
|
|
||||||
## Immutable hardware topology
|
The artifact header's restart bit describes the committed values in an export.
|
||||||
|
It is not an instruction accepted from an upload: after persistence the target
|
||||||
|
derives restart state by comparing committed values with immutable boot-active
|
||||||
|
values.
|
||||||
|
|
||||||
The checked-in F722 `ImmutableConfig` literals retain the facts that cannot
|
## Generic file dialect
|
||||||
safely be changed by a scalar transaction:
|
|
||||||
|
|
||||||
- IMU model and its fixed body mount (`BodyAligned` or `Yaw180`);
|
Kaptan uses two custom messages rather than standard MAVLink FTP or a family of
|
||||||
- logical MAVLink port and bootstrap baud rate;
|
configuration-specific requests:
|
||||||
- vertical-sensor presence, electrical route, and bootstrap baud rate; and
|
|
||||||
- output-inhibit and status-LED routes; and
|
|
||||||
- service-timer frequency.
|
|
||||||
|
|
||||||
The const typestate expression becomes the platform's sole hardware manifest;
|
```text
|
||||||
there is no second route structure to compare against it. Incomplete or
|
FILE_CONTROL
|
||||||
unsupported IMU, UART, vertical-sensor, status-LED, and output-inhibit
|
FILE_DATA
|
||||||
combinations cannot call `telemetry_only()`. Runtime validation still rejects a
|
```
|
||||||
service frequency the selected timer cannot provide or a baud rate that cannot
|
|
||||||
carry the fixed link budget. The physical port, sensor driver, pins, DMA,
|
|
||||||
timers, and calibration are not file configuration and are not GCS-editable.
|
|
||||||
|
|
||||||
Endpoint identity, raw-IMU/heartbeat rates, and MAVLink diagnostic-sink policy
|
`FILE_CONTROL` opens, closes, aborts, and acknowledges a transfer. It
|
||||||
are overlaid from the recovered operational snapshot before their consumers
|
carries a client-selected nonzero `u16` transfer ID, exact target, position,
|
||||||
are constructed.
|
complete file size, CRC-32C, operation/status, and at most 64 bytes of path or
|
||||||
Pins, sensor models, driver routes, DMA ownership, and calibration remain board
|
result detail. A source does not reuse an ID during the ten-second replay lease.
|
||||||
support or dedicated calibration concerns, not UI-selectable strings.
|
A new ID from the same source may supersede an open only before the first byte
|
||||||
|
has advanced; a progressed abandoned transfer remains pinned until lease expiry.
|
||||||
|
`FILE_DATA` uses the full MAVLink payload budget for a
|
||||||
|
246-byte chunk. The logical final-chunk length follows from the opened file
|
||||||
|
size, so no redundant length field is sent with every data packet. An upload
|
||||||
|
request carries status `UNSPECIFIED`; a read-data response carries status `OK`.
|
||||||
|
All failures remain typed `FILE_CONTROL` responses.
|
||||||
|
|
||||||
## Local persistence
|
The service owns one bounded stop-and-wait transfer. Chunks are sequential;
|
||||||
|
immediate retries are replay-safe, conflicting retries are rejected, and stale
|
||||||
|
transfer IDs cannot mutate a later transfer. A receive fault or bounded lease
|
||||||
|
expiry aborts staged provider state. The generic layer knows only paths, bytes,
|
||||||
|
positions, checksums, ownership, and retry state. It does not parse KCFG or
|
||||||
|
contain configuration policy.
|
||||||
|
|
||||||
SITL and F722 share the same configuration lifecycle and validation rules, but
|
The current provider exposes exactly `/config/user.kcfg`. A successful write
|
||||||
use target-appropriate private persistence formats. Neither format is exposed
|
close has generic status `OK` and content beginning with the authoritative
|
||||||
by the MAVLink configuration protocol.
|
seven-byte KCFG result prefix: restart flag, primary field, related field, and
|
||||||
|
validation-rule code. Its exact layout is `flags:u8 | primary_field:u16 LE |
|
||||||
|
related_field:u16 LE | validation_rule:u16 LE`; flag bit 0, when set, means a
|
||||||
|
restart is required, and every other flag bit is reserved zero. The field
|
||||||
|
sentinel is `0xffff`; rule zero means no rule.
|
||||||
|
KCFG `CONTENT_REJECTED` responses use the same prefix and may append bounded
|
||||||
|
UTF-8 detail. The configurator rejects a successful close with a missing,
|
||||||
|
malformed, or failure-bearing prefix. The file layer passes these bytes through
|
||||||
|
without interpreting them.
|
||||||
|
|
||||||
### SITL CBOR file
|
The directly wired local UART is the initial transport. CRC validates framing
|
||||||
|
integrity, not peer authenticity. Disconnect other transmitters from the board
|
||||||
|
RX line. A shared or remote GCS still requires signing, source/key binding,
|
||||||
|
persistent anti-replay state, and provisioning before this inbound service can
|
||||||
|
be exposed safely.
|
||||||
|
|
||||||
SITL stores one raw, bounded CBOR configuration snapshot directly:
|
## Private persistence
|
||||||
|
|
||||||
- it is a map keyed by the discovered numeric `FieldId`s;
|
SITL and F722 use target-appropriate private persistence. Neither private
|
||||||
- key `0` is `snapshot_format = 2` and reserved key `65535` is the 16-byte
|
format is the public KCFG artifact.
|
||||||
fingerprint generated from the complete schema;
|
|
||||||
- the complete blob is at most 4 KiB; and
|
|
||||||
- malformed, trailing, wrong-format, non-finite, out-of-range, cross-field,
|
|
||||||
and capability-invalid values are rejected.
|
|
||||||
|
|
||||||
The map is exact for the compiled schema: every advertised field is present
|
### SITL CBOR
|
||||||
once. Unknown, duplicate, missing, or indefinite-map keys are rejected. Its
|
|
||||||
field count therefore follows the SITL composition instead of a global
|
|
||||||
parameter list.
|
|
||||||
|
|
||||||
Saving writes a same-directory temporary file, synchronizes its contents, and
|
SITL stores one bounded CBOR snapshot keyed by stable `FieldId`. Saving writes
|
||||||
atomically renames it over the configured file. The file contains no generation
|
a same-directory temporary file, synchronizes it, and atomically renames it
|
||||||
or journal envelope; host filesystem replacement is distinct from the F722
|
over the configured file. The exact map rejects unknown, duplicate, and missing
|
||||||
flash power-loss protocol.
|
fields, wrong schema or format, trailing input, invalid scalar encodings, and
|
||||||
|
complete-model validation failures.
|
||||||
|
|
||||||
### F722 flash journal
|
### F722 flash journal
|
||||||
|
|
||||||
F722 serializes the board's `UserConfig` as a bounded fixed scalar snapshot:
|
F722 stores a compact private `KCSP` scalar snapshot inside a two-slot journal.
|
||||||
a magic/version header and schema fingerprint followed by the exact field count
|
Each entry stores its stable field ID, scalar kind, and value at that kind's
|
||||||
and one `(FieldId, value kind, raw scalar bits)` entry per field. It is not
|
native width; an `u8` is one byte rather than a widened integer slot. Each
|
||||||
CBOR. Recovery rejects a wrong schema, field set, value kind, scalar encoding,
|
journal record includes payload length, CRC-32C, commit marker, and a private
|
||||||
or complete-model validation result.
|
monotonic sequence. Saving erases the inactive slot, programs and verifies the
|
||||||
|
complete replacement, and writes the commit marker last. The previous valid
|
||||||
|
slot remains recoverable across power loss until that point.
|
||||||
|
|
||||||
The snapshot is wrapped in a private journal record containing its payload
|
Only two complete records can exist: the old committed value and its
|
||||||
length, CRC-32C, commit marker, and monotonically increasing sequence. Two
|
replacement. Saves do not append history. The sequence is storage metadata used
|
||||||
independently erasable flash slots hold at most the old and replacement
|
only to select the newer valid slot if both slots survive; it is never exported
|
||||||
snapshots. Saving erases the inactive slot, programs and verifies the complete
|
through KCFG or shown in the UI.
|
||||||
record, then writes its commit marker last; the previous valid slot remains
|
|
||||||
recoverable until then. The private sequence only selects the newer record when
|
|
||||||
both slots are valid. It does not append configuration history.
|
|
||||||
|
|
||||||
There is no migration path because no version has shipped.
|
There is no migration path because no configuration version has shipped.
|
||||||
|
|
||||||
## GCS protocol contract
|
|
||||||
|
|
||||||
The custom dialect is prepared for a first-party GCS without borrowing
|
|
||||||
`PARAM_*` semantics. A client will:
|
|
||||||
|
|
||||||
1. send `KAPTAN_CONFIG_INFO_REQUEST`, require the exact breaking protocol
|
|
||||||
version `2.0`,
|
|
||||||
and retain the target-advertised schema ID as the exact identity of that
|
|
||||||
configuration session;
|
|
||||||
2. request descriptors, enum options, and values by exact index or field ID;
|
|
||||||
3. open a transaction with `KAPTAN_CONFIG_BEGIN`;
|
|
||||||
4. issue typed setters for changed fields;
|
|
||||||
5. validate and commit; and
|
|
||||||
6. treat `COMMITTED_RESTART_REQUIRED` as persistence only, never live
|
|
||||||
activation.
|
|
||||||
|
|
||||||
The directly wired local UART is the initial operational configuration
|
|
||||||
transport. The board composition admits CRC-valid unsigned configuration
|
|
||||||
commands on that link; CRC supplies integrity, not authentication. This does
|
|
||||||
not authorize a shared or remotely reachable MAVLink network. Use a direct
|
|
||||||
adapter connection and disconnect every other transmitter from the board's RX
|
|
||||||
line because the firmware cannot prove electrical exclusivity. Motor outputs
|
|
||||||
remain physically inhibited in both current F722 images.
|
|
||||||
|
|
||||||
The first accepted `BEGIN` binds the one protocol instance to that MAVLink
|
|
||||||
source. The binding and its sole most-recent result remain for a ten-second
|
|
||||||
lease, including after `COMMIT` or `ABORT`, so retrying a lost terminal reply
|
|
||||||
cannot be displaced by another source. A UART receive fault or lease expiry
|
|
||||||
clears the binding; another source may then begin. This is bounded direct-link
|
|
||||||
serialization, not authentication.
|
|
||||||
|
|
||||||
A remotely reachable GCS transport still requires MAVLink signing, source/key
|
|
||||||
binding, persistent anti-replay state, and provisioning/rotation. Those are
|
|
||||||
future additions to the same target-described configuration protocol, not a
|
|
||||||
different board or parameter catalog.
|
|
||||||
+11
-10
@@ -53,30 +53,31 @@ backpressure, retry, and untrusted-input results remain unannotated. In
|
|||||||
particular, transient SPI/I²C `Busy` and unavailable range measurements stay
|
particular, transient SPI/I²C `Busy` and unavailable range measurements stay
|
||||||
inside their service retry/idle paths. In contrast, every logging
|
inside their service retry/idle paths. In contrast, every logging
|
||||||
macro—including `kaptan_log::error!`—produces only
|
macro—including `kaptan_log::error!`—produces only
|
||||||
`KAPTAN_LOG`. Error reporting is not a replacement for safety state,
|
`LOG`. Error reporting is not a replacement for safety state,
|
||||||
actuator inhibit, or typed configuration results.
|
actuator inhibit, or typed configuration results.
|
||||||
|
|
||||||
`kaptan-err-reportable` owns reportable-error identity and its independent
|
`kaptan-err-reportable` owns reportable-error identity and its independent
|
||||||
one-slot ingress. A pending record contains only the compact ID and a static
|
one-slot ingress. A pending record contains only the compact ID and a static
|
||||||
reference to the reporting point's `file:line`. The MAVLink adapter copies that
|
reference to the reporting point's `file:line`. The MAVLink adapter copies that
|
||||||
location into its fixed field when constructing `KAPTAN_ERROR`. Producers never
|
location into its fixed field when constructing `ERROR`. Producers never
|
||||||
encode or transmit MAVLink themselves. Admission is bounded and lossy if a
|
encode or transmit MAVLink themselves. Admission is bounded and lossy if a
|
||||||
different reportable error is already pending.
|
different reportable error is already pending.
|
||||||
|
|
||||||
## What the receiver sees
|
## What the receiver sees
|
||||||
|
|
||||||
- Configuration writes receive authoritative structured failures through
|
- A rejected KCFG upload receives an authoritative `FILE_CONTROL`
|
||||||
`KAPTAN_CONFIG_RESULT`: operation, lifecycle state, field IDs, validation
|
status and bounded readable detail. Invalid user content is not a firmware
|
||||||
rule, and protocol error code. A reportable persistence failure also emits
|
error. A durable-storage failure additionally emits one stable
|
||||||
the storage-only `CommitTransactionError::Store` ID once as
|
`PersistConfigurationError` ID that distinguishes journal geometry, model,
|
||||||
`KAPTAN_ERROR`; replaying the cached command result does not repeat the error
|
sequence, flash-controller, bounds, unlock, and verification
|
||||||
or the flash operation.
|
failures. Replaying the cached close result does not repeat the report or
|
||||||
|
flash operation.
|
||||||
- Reported `ReportableError` values reach the F722 MAVLink worker as a
|
- Reported `ReportableError` values reach the F722 MAVLink worker as a
|
||||||
`KAPTAN_ERROR`, subject to bounded transport admission. The payload is
|
`ERROR`, subject to bounded transport admission. The payload is
|
||||||
`{ error_id, raised_at[96] }`. `raised_at` is a zero-padded UTF-8
|
`{ error_id, raised_at[96] }`. `raised_at` is a zero-padded UTF-8
|
||||||
`file:line` prefix for the reporting point.
|
`file:line` prefix for the reporting point.
|
||||||
The message kind itself identifies an error; no level is duplicated in the
|
The message kind itself identifies an error; no level is duplicated in the
|
||||||
payload. Dynamic human-readable context belongs in `KAPTAN_LOG`, while
|
payload. Dynamic human-readable context belongs in `LOG`, while
|
||||||
structured protocol failures remain in their owning response message.
|
structured protocol failures remain in their owning response message.
|
||||||
- Control, navigation, safety, and simulator error types are derive-ready but
|
- Control, navigation, safety, and simulator error types are derive-ready but
|
||||||
their live owners are not yet attached to a MAVLink worker.
|
their live owners are not yet attached to a MAVLink worker.
|
||||||
|
|||||||
+24
-22
@@ -10,10 +10,10 @@ kaptan_log::error!("sensor transfer failed");
|
|||||||
kaptan_log::trace!("prediction step complete");
|
kaptan_log::trace!("prediction step complete");
|
||||||
```
|
```
|
||||||
|
|
||||||
All five macros emit `KAPTAN_LOG`; their level never selects a different wire
|
All five macros emit `LOG`; their level never selects a different wire
|
||||||
message. When a reportable firmware error escapes a reviewed
|
message. When a reportable firmware error escapes a reviewed
|
||||||
`#[kaptan_err_reportable::propagate]` function, it makes one bounded admission attempt
|
`#[kaptan_err_reportable::propagate]` function, it makes one bounded admission attempt
|
||||||
to the separate `KAPTAN_ERROR` ingress.
|
to the separate `ERROR` ingress.
|
||||||
|
|
||||||
`kaptan-log` formats each event once into a fixed bounded buffer and never
|
`kaptan-log` formats each event once into a fixed bounded buffer and never
|
||||||
sends MAVLink, allocates, blocks, changes flight state, or touches DMA. The
|
sends MAVLink, allocates, blocks, changes flight state, or touches DMA. The
|
||||||
@@ -29,31 +29,33 @@ Panic and hard-fault paths still do not attempt live telemetry.
|
|||||||
|
|
||||||
## Receiver contract
|
## Receiver contract
|
||||||
|
|
||||||
`definitions/kaptan/log.xml` and `definitions/kaptan/error.xml` separate
|
`definitions/publish/log.xml` and `definitions/publish/error.xml` define the
|
||||||
ordinary logs and reportable errors:
|
separate ordinary-log and reportable-error publications:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
KAPTAN_LOG { level, flags, message_length, message[160] }
|
LOG { level, flags, message_length, message[160] }
|
||||||
KAPTAN_ERROR {
|
ERROR {
|
||||||
error_id, raised_at[96]
|
error_id, raised_at[96]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
A GCS decoder generated from the same `kaptan.xml` revision must validate
|
A GCS decoder generated from the same `kaptan.xml` revision must validate
|
||||||
`message_length <= 160` for `KAPTAN_LOG`. `KAPTAN_ERROR.raised_at` is a
|
`message_length <= 160` for `LOG`. `ERROR.raised_at` is a
|
||||||
zero-padded UTF-8 `file:line` prefix; receivers use bytes before the first zero,
|
zero-padded UTF-8 `file:line` prefix; receivers use bytes before the first zero,
|
||||||
or the complete field when no zero is present.
|
or the complete field when no zero is present.
|
||||||
`KAPTAN_LOG.level` accepts only Error (3), Warning (4), Info (6), and Debug
|
`LOG.level` is the typed severity-ordered Kaptan wire enum Trace (1), Debug
|
||||||
(7); Trace is encoded as Debug (7) plus the `TRACE` flag. Other MAVLink
|
(2), Info (3), Warn (4), or Error (5). Off (0) is a filter-only sentinel and
|
||||||
severity numbers are not Kaptan log levels.
|
is never emitted as a `LOG` event. `LOG.flags` currently owns only the
|
||||||
The `KAPTAN_ERROR` message kind already means a reportable firmware error, so it has
|
Truncated bit (1).
|
||||||
|
The `ERROR` message kind already means a reportable firmware error, so it has
|
||||||
no redundant level or flags field.
|
no redundant level or flags field.
|
||||||
|
|
||||||
`error_id` is the stable nonzero catalog number explicitly assigned to the
|
`error_id` is the stable nonzero catalog number explicitly assigned to the
|
||||||
Rust error variant. Renaming or reordering a variant does not change it.
|
Rust error variant. Renaming or reordering a variant does not change it.
|
||||||
`raised_at` identifies the reporting point where the `Err` entered
|
`raised_at` identifies the reporting point where the `Err` entered
|
||||||
diagnostics. Error details requiring
|
diagnostics. Protocol failures remain in their owning response; for example, a
|
||||||
machine action stay in their owning protocol, notably `KAPTAN_CONFIG_RESULT`.
|
rejected KCFG upload returns a `FILE_CONTROL` failure and readable
|
||||||
|
bounded detail.
|
||||||
Delivery is bounded and lossy under link pressure; heartbeat and safety
|
Delivery is bounded and lossy under link pressure; heartbeat and safety
|
||||||
telemetry use separate paths. Logs have no publication rate setting and are
|
telemetry use separate paths. Logs have no publication rate setting and are
|
||||||
not periodic streams. A retained event leaves its MAVLink sink only once the
|
not periodic streams. A retained event leaves its MAVLink sink only once the
|
||||||
@@ -62,10 +64,10 @@ event.
|
|||||||
|
|
||||||
## Filtering
|
## Filtering
|
||||||
|
|
||||||
The single restart-only `mavlink.logging.level_filter` field uses the familiar
|
The single restart-only `mavlink.logging.level_filter` field uses Off (0),
|
||||||
Off, Error, Warn, Info, Debug, and Trace choices. `Info`, for example, accepts
|
Trace (1), Debug (2), Info (3), Warn (4), and Error (5). `Info`, for example,
|
||||||
Error, Warn, and Info log events. `Off` suppresses `KAPTAN_LOG` on MAVLink
|
accepts Info, Warn, and Error log events. `Off` suppresses `LOG` on MAVLink
|
||||||
without suppressing reportable `KAPTAN_ERROR` events or logs sent to another
|
without suppressing reportable `ERROR` events or logs sent to another
|
||||||
sink. There is no separate enable flag and no MAVLink-specific set of extra
|
sink. There is no separate enable flag and no MAVLink-specific set of extra
|
||||||
runtime log levels. F722 uses the validated filter recovered at boot, falling
|
runtime log levels. F722 uses the validated filter recovered at boot, falling
|
||||||
back to its board factory when the journal is empty or invalid.
|
back to its board factory when the journal is empty or invalid.
|
||||||
@@ -73,14 +75,14 @@ back to its board factory when the journal is empty or invalid.
|
|||||||
Events retain the compact typed `Level` and sink configuration retains the
|
Events retain the compact typed `Level` and sink configuration retains the
|
||||||
compact typed `LevelFilter`. Generic schema discovery exposes the filter's
|
compact typed `LevelFilter`. Generic schema discovery exposes the filter's
|
||||||
named choices to the configurator, so the UI carries no hardcoded field list.
|
named choices to the configurator, so the UI carries no hardcoded field list.
|
||||||
Only the MAVLink adapter converts the five event levels to MAVLink's numeric
|
Only the MAVLink adapter converts the five event levels to the typed Kaptan
|
||||||
severity representation; Trace uses MAVLink Debug plus the Trace flag.
|
wire enum.
|
||||||
|
|
||||||
The log ingress is transport-neutral and unfiltered. The tested
|
The log ingress is transport-neutral and unfiltered. The tested
|
||||||
`SitlConfigRuntime` composition applies the configured MAVLink policy when
|
`SitlConfigRuntime` composition applies the configured MAVLink policy when
|
||||||
fanning an event into that sink and proves `kaptan_log::info!` reaches a
|
fanning an event into that sink and proves `kaptan_log::info!` reaches a
|
||||||
generated `KAPTAN_LOG` payload.
|
generated `LOG` payload.
|
||||||
`kaptan-sitl serve` does not yet attach a config/diagnostic MAVLink link. F722
|
`kaptan-sitl serve` does not yet attach a file/diagnostic MAVLink link. F722
|
||||||
images accept only the unsigned configuration service on their directly wired
|
images accept only the unsigned Kaptan file service on their directly wired
|
||||||
local UART; that direct-wire assumption does not extend to a shared or remote
|
local UART; that direct-wire assumption does not extend to a shared or remote
|
||||||
MAVLink network.
|
MAVLink network.
|
||||||
+55
-23
@@ -1,33 +1,36 @@
|
|||||||
# MAVLink and telemetry
|
# MAVLink and telemetry
|
||||||
|
|
||||||
Kaptan emits telemetry using MAVLink 2 framing. Inbound processing is narrowly
|
Kaptan uses MAVLink 2 framing exclusively with the generated Kaptan dialect.
|
||||||
scoped:
|
It neither emits nor accepts messages from `common`, `minimal`, or another
|
||||||
|
dialect. Inbound processing is narrowly scoped:
|
||||||
|
|
||||||
- MAVLink 1 is discarded.
|
- MAVLink 1 is discarded.
|
||||||
- CRC-invalid MAVLink 2 frames are discarded.
|
- CRC-invalid MAVLink 2 frames are discarded.
|
||||||
- Signed frames are discarded because no signature verifier or persistent
|
- Signed frames are discarded because no signature verifier or persistent
|
||||||
replay state exists.
|
replay state exists.
|
||||||
- CRC-valid unsigned MAVLink 2 frames are accepted only for the exact-target
|
- CRC-valid unsigned MAVLink 2 frames are retained only when their message ID
|
||||||
Kaptan configuration service on the directly wired local UART. Other inbound
|
and extra CRC belong to the Kaptan dialect. Exact-target Kaptan file requests
|
||||||
messages do not become authority.
|
are the only inbound records with a current firmware consumer.
|
||||||
|
|
||||||
`TODO(signing)`: any future shared or remote inbound authority requires verified
|
Shared or remote inbound authority is deliberately unsupported. Enabling it
|
||||||
MAVLink 2 signing, configured source/target binding, persistent anti-replay
|
requires verified MAVLink 2 signing, configured source/target binding,
|
||||||
state, and a provisioning/key-rotation policy as one reviewed feature.
|
persistent anti-replay state, and a provisioning/key-rotation policy as one
|
||||||
|
reviewed feature.
|
||||||
|
|
||||||
The local UART is Kaptan's initial operational configuration transport, not an
|
The local UART is Kaptan's initial operational file transport, not an
|
||||||
authenticated remote-control channel. Any transmitter electrically connected
|
authenticated remote-control channel. Any transmitter electrically connected
|
||||||
to that RX line can issue configuration commands, so connect the USB-UART
|
to that RX line can issue file requests, so connect the USB-UART
|
||||||
adapter directly and disconnect other transmitters. The platform retains its
|
adapter directly and disconnect other transmitters. The platform retains its
|
||||||
startup-configured low motor-output state throughout this workflow; no marker
|
startup-configured low motor-output state throughout this workflow; no marker
|
||||||
type is treated as GPIO ownership or command authority. A networked GCS must
|
type is treated as GPIO ownership or command authority. A networked GCS must
|
||||||
add verified signing, source binding, and durable replay protection before it
|
add verified signing, source binding, and durable replay protection before it
|
||||||
can receive authority.
|
can receive authority.
|
||||||
|
|
||||||
Configuration protocol `2.0` admits one source principal from `BEGIN` until
|
The custom Kaptan file service admits one exact source principal for a bounded
|
||||||
its ten-second lease expires or the UART receive path faults. That lease also
|
stop-and-wait transfer. A receive fault or lease expiry aborts its staged
|
||||||
covers the post-commit retry window, preventing another source from evicting a
|
provider state. Completed control replies have a bounded replay path so a lost
|
||||||
lost result. It serializes the direct link but does not authenticate its peer.
|
close response does not repeat a flash operation. This serialization does not
|
||||||
|
authenticate its peer.
|
||||||
|
|
||||||
Telemetry transmission uses bounded frame classes. A critical frame may
|
Telemetry transmission uses bounded frame classes. A critical frame may
|
||||||
replace pending best-effort traffic, but never the DMA-owned active buffer.
|
replace pending best-effort traffic, but never the DMA-owned active buffer.
|
||||||
@@ -37,22 +40,51 @@ later service turn.
|
|||||||
The local web configurator exposes a bounded live view of CRC-valid inbound
|
The local web configurator exposes a bounded live view of CRC-valid inbound
|
||||||
frames. It groups packets by source and message ID and measures receive
|
frames. It groups packets by source and message ID and measures receive
|
||||||
frequency in one-second windows. Selecting a message reveals the latest decoded
|
frequency in one-second windows. Selecting a message reveals the latest decoded
|
||||||
fields, including human-readable `KAPTAN_ERROR` text. This observation path
|
fields, including the readable zero-padded `ERROR.raised_at` reporting
|
||||||
retains one latest value per bounded aggregate rather than packet history and
|
location. This observation path retains one latest value per bounded aggregate
|
||||||
grants no additional command authority.
|
rather than packet history and grants no additional command authority.
|
||||||
|
|
||||||
Diagnostic events also feed a separate bounded Runtime logs view at
|
Diagnostic events also feed a separate bounded Runtime logs view at
|
||||||
`http://127.0.0.1:4861`. That view retains individual `KAPTAN_LOG` and
|
`http://127.0.0.1:4861`. That view retains individual `LOG` and
|
||||||
`KAPTAN_ERROR` events in receive order with local receive time, level, and
|
`ERROR` events in receive order with local receive time, level, and
|
||||||
readable text. Packet inspection remains a latest-value view; it is not used as
|
readable text. Packet inspection remains a latest-value view; it is not used as
|
||||||
log history.
|
log history.
|
||||||
|
|
||||||
The custom Kaptan definitions are aggregated by `definitions/kaptan.xml` from
|
The custom Kaptan definitions are aggregated by `definitions/kaptan.xml` from
|
||||||
`kaptan/config.xml`, `kaptan/log.xml`, and `kaptan/error.xml`.
|
one-message leaves grouped by interaction contract:
|
||||||
`KAPTAN_LOG` is an outbound human-readable four-field record. `KAPTAN_ERROR`
|
|
||||||
|
| Directory | Contract |
|
||||||
|
| --- | --- |
|
||||||
|
| `publish/` | Zero-reply records for any interested receiver. |
|
||||||
|
| `exchange/` | Exact-endpoint requests with one terminal response; currently empty. |
|
||||||
|
| `transfer/` | Exact-endpoint, bounded multi-message sessions. |
|
||||||
|
|
||||||
|
The root includes every message leaf directly; there are no redundant category
|
||||||
|
index files or separate enum catalogs. Placement is a wire-contract
|
||||||
|
classification, while bindgen still generates one flat `generated::kaptan`
|
||||||
|
module. Bare message names are scoped by that sole dialect and must not be
|
||||||
|
merged with another MAVLink dialect. `exchange/` gains its first XML only when
|
||||||
|
an exchange has a current consumer.
|
||||||
|
`LOG` is an outbound human-readable four-field record. `ERROR`
|
||||||
is the separate bounded channel for reportable firmware errors, carrying a
|
is the separate bounded channel for reportable firmware errors, carrying a
|
||||||
stable explicit ID plus the `file:line` of its reporting point, and needs no
|
stable explicit ID plus the `file:line` of its reporting point, and needs no
|
||||||
redundant level field. Configuration messages back the current target-described
|
redundant level field. `FILE_CONTROL` and `FILE_DATA` implement
|
||||||
web configurator and the future signed GCS. See
|
Kaptan's generic virtual-file transport without standard MAVLink FTP
|
||||||
|
compatibility. The current configurator reads and replaces
|
||||||
|
`/config/user.kcfg`. See
|
||||||
[Configuration](configuration.md), [Logs](logs.md), and [Errors](errors.md) for
|
[Configuration](configuration.md), [Logs](logs.md), and [Errors](errors.md) for
|
||||||
the exact contracts.
|
the exact contracts.
|
||||||
|
|
||||||
|
The current scheduled publications are deliberately native rather than
|
||||||
|
projections into a broader dialect:
|
||||||
|
|
||||||
|
| Publication | Current payload |
|
||||||
|
| --- | --- |
|
||||||
|
| `HEARTBEAT` (51027) | The single current initialized/output-inhibited state. |
|
||||||
|
| `IMU` (51028) | Monotonic microseconds, body acceleration in mg, angular rate in mrad/s, and temperature in cdegC. |
|
||||||
|
| `RANGE` (51029) | Monotonic microseconds and downward distance in mm. |
|
||||||
|
| `OPTICAL_FLOW` (51030) | Monotonic microseconds, integer ground-relative velocity in mm/s, distance in mm, and quality. |
|
||||||
|
|
||||||
|
These records preserve the firmware's bounded native values. They do not
|
||||||
|
carry unused sensor IDs, repeated board topology, float projections, narrowed
|
||||||
|
timestamps, or clamped measurements.
|
||||||
+21
-8
@@ -5,14 +5,15 @@ This page collects stable limits and points to the detailed contracts.
|
|||||||
| Surface | Current contract |
|
| Surface | Current contract |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| SITL file | One raw bounded CBOR configuration snapshot, replaced through a same-directory temporary file and atomic rename. |
|
| SITL file | One raw bounded CBOR configuration snapshot, replaced through a same-directory temporary file and atomic rename. |
|
||||||
| F722 persistence | One bounded fixed scalar snapshot inside each slot of a power-loss-safe two-slot flash journal. |
|
| F722 persistence | One bounded native-width scalar snapshot inside each slot of a power-loss-safe two-slot flash journal. |
|
||||||
| Config transaction | One owner-bound RAM transaction with typed scalar writes; commit is restart-required. |
|
| Public config artifact | One canonical self-describing KCFG file containing generated metadata, factory values, and the complete committed candidate. |
|
||||||
| Config discovery | Correlated `KAPTAN_CONFIG_INFO_REQUEST` / `KAPTAN_CONFIG_INFO`, then exact-index descriptor/enum-option and field-value requests. |
|
| File transfer | Custom `FILE_CONTROL` (51025) and `FILE_DATA` (51026), one owner-bound stop-and-wait transfer, 246-byte data chunks, CRC-32C. |
|
||||||
| Diagnostics | `KAPTAN_LOG` (51020) for macro-produced level/text; `KAPTAN_ERROR` (51021) for a bounded reportable `{ error_id, raised_at[96] }` firmware error. |
|
| Diagnostics | `LOG` (51020) for macro-produced level/text; `ERROR` (51021) for a bounded reportable `{ error_id, raised_at[96] }` firmware error. |
|
||||||
| F722 configuration | Target-described fields and board factory defaults; the current local transport is a directly wired unsigned UART with motor outputs physically inhibited. |
|
| Publications | Kaptan-native `HEARTBEAT` (51027), `IMU` (51028), `RANGE` (51029), and `OPTICAL_FLOW` (51030); exact integer units and monotonic `u64` microseconds. |
|
||||||
|
| F722 configuration | `/config/user.kcfg`; target-described fields and board factory values over a directly wired unsigned UART with motor outputs physically inhibited. |
|
||||||
|
|
||||||
Read [Configuration](configuration.md) for the field/consumer matrix and GCS
|
Read [Configuration](configuration.md) for configuration ownership, artifact,
|
||||||
transaction sequence, [Logs](logs.md) for receiver decoding and filtering, and
|
and file contracts, [Logs](logs.md) for receiver decoding and filtering, and
|
||||||
[Errors](errors.md) for reportable errors and panic scope.
|
[Errors](errors.md) for reportable errors and panic scope.
|
||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
@@ -28,8 +29,20 @@ cargo clippy --workspace --all-targets \
|
|||||||
--exclude kaptan-geprc-f722-v2 --locked --offline -- -D warnings
|
--exclude kaptan-geprc-f722-v2 --locked --offline -- -D warnings
|
||||||
cargo clippy -p kaptan-kakute-f7-mini-v3 -p kaptan-geprc-f722-v2 \
|
cargo clippy -p kaptan-kakute-f7-mini-v3 -p kaptan-geprc-f722-v2 \
|
||||||
--target thumbv7em-none-eabihf --locked --offline -- -D warnings
|
--target thumbv7em-none-eabihf --locked --offline -- -D warnings
|
||||||
|
cargo build --release --locked --offline \
|
||||||
|
-p kaptan-kakute-f7-mini-v3 -p kaptan-geprc-f722-v2 \
|
||||||
|
--target thumbv7em-none-eabihf
|
||||||
|
python3 -m unittest scripts/test-analyze-fw.py
|
||||||
|
scripts/analyze-fw.py \
|
||||||
|
target/thumbv7em-none-eabihf/release/kaptan-kakute-f7-mini-v3 \
|
||||||
|
platforms/stm32f7/link/f722/memory.x
|
||||||
|
scripts/analyze-fw.py \
|
||||||
|
target/thumbv7em-none-eabihf/release/kaptan-geprc-f722-v2 \
|
||||||
|
platforms/stm32f7/link/f722/memory.x
|
||||||
```
|
```
|
||||||
|
|
||||||
The target-specific lint verifies the local configuration receiver and journal
|
The target-specific lint verifies the local configuration receiver and journal
|
||||||
path. The host suite separately asserts that configuration ingress cannot reach
|
path. The host suite separately asserts that configuration ingress cannot reach
|
||||||
an actuator path.
|
an actuator path. The ELF checks prove that the flash-busy operation is linked
|
||||||
|
into executable SRAM and reject compiler-outlined control flow or PC-relative
|
||||||
|
literal loads outside that section.
|
||||||
@@ -16,12 +16,12 @@ There is no checked-in platform actuator route:
|
|||||||
|
|
||||||
- no DShot or PWM peripheral implementation is linked;
|
- no DShot or PWM peripheral implementation is linked;
|
||||||
- no TIM3/TIM5 motor task or DMA output path exists;
|
- no TIM3/TIM5 motor task or DMA output path exists;
|
||||||
- MAVLink input is accepted only by the configuration service and has no
|
- only CRC-valid Kaptan-dialect MAVLink input reaches the bounded virtual-file
|
||||||
actuator path;
|
service, which has no actuator path;
|
||||||
- a future verified arm command is still acknowledged as unsupported.
|
- no arm command is defined or admitted.
|
||||||
|
|
||||||
The protocol reference crate remains in the workspace only as a framing and
|
The framing and file-transfer crates do not grant hardware access or actuator
|
||||||
arming-sequence reference. It does not grant hardware access or authority.
|
authority.
|
||||||
|
|
||||||
Run the structural guard after any platform or board change:
|
Run the structural guard after any platform or board change:
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -36,8 +36,8 @@ Open <https://app.gazebosim.org/visualization>, connect to
|
|||||||
|
|
||||||
## Quad-X profile
|
## Quad-X profile
|
||||||
|
|
||||||
SITL starts through the same central `ConfigManager` composition used by the
|
SITL starts through the central `ConfigManager` lifecycle. Create and validate
|
||||||
host protocol tests. Create and validate a private host profile file with:
|
a private host profile file with:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
kaptan-sitl config write-default kaptan-sitl.cbor
|
kaptan-sitl config write-default kaptan-sitl.cbor
|
||||||
@@ -49,9 +49,9 @@ The file selects the restart-only profile used to build the estimator,
|
|||||||
controller, allocator envelope, safety supervisor, and MAVLink log-sink policy at
|
controller, allocator envelope, safety supervisor, and MAVLink log-sink policy at
|
||||||
process start. It is local persistence and never appears on MAVLink.
|
process start. It is local persistence and never appears on MAVLink.
|
||||||
`kaptan-sitl serve` retains
|
`kaptan-sitl serve` retains
|
||||||
the central manager for that boot but does not yet open a MAVLink config/log
|
the central manager for that boot but does not yet open a MAVLink file/log
|
||||||
endpoint; see [Configuration](configuration.md) for the exact transaction contract
|
endpoint; see [Configuration](configuration.md) for the KCFG, file-transfer,
|
||||||
and safety boundary.
|
and safety boundaries.
|
||||||
|
|
||||||
## Limits
|
## Limits
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user