diff --git a/README.md b/README.md deleted file mode 100644 index 57cbee0..0000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# kaptan - -TODO diff --git a/boards/geprc-f722-v2/README.md b/boards/geprc-f722-v2/README.md deleted file mode 100644 index b333000..0000000 --- a/boards/geprc-f722-v2/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# GEPRC GEP-F722-HD V2 - -Build from the workspace root: - -```sh -cargo build --release -p kaptan-geprc-f722-v2 --target thumbv7em-none-eabihf -``` diff --git a/boards/kakute-f7-mini-v3/README.md b/boards/kakute-f7-mini-v3/README.md deleted file mode 100644 index 938ed0b..0000000 --- a/boards/kakute-f7-mini-v3/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# Kakute F7 Mini V3 - -Kaptan support for the Holybro Kakute F7 Mini V3. - -The checked-in manufacturer manual is [Holybro_KakuteF7_Mini_V3_Manual_v1.0.pdf](Holybro_KakuteF7_Mini_V3_Manual_v1.0.pdf). - -## Build - -Build the firmware from the workspace root: - -```sh -cargo build --release -p kaptan-kakute-f7-mini-v3 --target thumbv7em-none-eabihf -``` - -Create its DFU (device firmware update) image: - -```sh -./scripts/create-dfu-image.sh target/thumbv7em-none-eabihf/release/kaptan-kakute-f7-mini-v3 -``` - -The converter derives the `.bin` path and matching board `memory.x`, then prints the firmware size report. It uses rustup's `llvm-tools-preview` component which the workspace toolchain installs automatically. - -## Flash over USB DFU - -1. Disconnect the board from USB. -2. Hold the `Boot` button. -3. Connect USB, then release `Boot`. The board should enumerate as STM32 DFU. -4. Flash the generated image: - -```sh -dfu-util --alt 0 --dfuse-address 0x08000000:leave --download target/thumbv7em-none-eabihf/release/kaptan-kakute-f7-mini-v3.bin -``` - -## UART - -| USB-to-UART adapter | FC | -| --- | --- | -| `RX` | `T1` | -| `GND` | `G` | -| `TX` | `R1` | diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..0877f22 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,12 @@ +MDBOOK ?= mdbook + +.PHONY: build serve test + +build: + $(MDBOOK) build + +serve: + $(MDBOOK) serve --open + +test: + $(MDBOOK) test diff --git a/docs/book.toml b/docs/book.toml new file mode 100644 index 0000000..536fb04 --- /dev/null +++ b/docs/book.toml @@ -0,0 +1,21 @@ +[book] +title = "Kaptan Developer Manual" +description = "Architecture, board bring-up, simulation, and contributor guidance for Kaptan." +authors = ["Kaptan contributors"] +language = "en" +src = "src" + +[build] +# Keep generated site files out of the Markdown source tree. +build-dir = "../target/docs" +create-missing = false + +[output.html] +default-theme = "light" +preferred-dark-theme = "navy" +git-repository-url = "https://github.com/Orkavian/kaptan" +edit-url-template = "https://github.com/Orkavian/kaptan/edit/main/{path}" +additional-css = ["theme/kaptan.css"] +additional-js = ["theme/kaptan.js"] +fold = { enable = true, level = 1 } +smart-punctuation = true diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md new file mode 100644 index 0000000..356a602 --- /dev/null +++ b/docs/src/SUMMARY.md @@ -0,0 +1,13 @@ +# Summary + +- [Kaptan Developer Manual](index.md) +- [Getting started](getting-started.md) +- [Architecture](architecture.md) + - [Safety boundary](safety-boundary.md) + - [MAVLink and telemetry](mavlink.md) +- [Boards](boards/index.md) + - [Kakute F7 Mini V3](boards/kakute-f7-mini-v3.md) + - [GEPRC GEP-F722-HD V2](boards/geprc-f722-v2.md) +- [Host SITL](sitl.md) +- [Development and verification](development.md) +- [Reference](reference.md) diff --git a/docs/src/architecture.md b/docs/src/architecture.md new file mode 100644 index 0000000..6834f30 --- /dev/null +++ b/docs/src/architecture.md @@ -0,0 +1,35 @@ +# Architecture + +Kaptan separates immutable board configuration from platform-owned runtime +resources and portable flight logic. + +```text +board declaration + │ + ▼ +F722 platform / RTIC application ──► data channel ──► MAVLink telemetry + │ + ├── physical sensor drivers + └── motor-pin inhibit interlock + +portable libraries + math ─► navigation ─► control ─► safety +``` + +The board contract selects one immutable `BoardProfile`. The checked-in +profile is `TelemetryOnly`; `ExternalControlOnly` is represented explicitly +but rejected at validation time because it has no reviewed runtime. + +The data channel owns rate selection, mailbox consumption, message encoding, +and bounded TX classification. Board code supplies physical routes and +telemetry configuration; it does not receive generic output authority. + +## 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. diff --git a/docs/src/boards/geprc-f722-v2.md b/docs/src/boards/geprc-f722-v2.md new file mode 100644 index 0000000..8bd5d0e --- /dev/null +++ b/docs/src/boards/geprc-f722-v2.md @@ -0,0 +1,14 @@ +# GEPRC GEP-F722-HD V2 + +The GEPRC GEP-F722-HD V2 board declaration uses the ICM-42688-P on SPI3 and +MAVLink telemetry on USART2. It declares no vertical sensor stream. + +Build and package from the workspace root: + +```sh +cargo build --release -p kaptan-geprc-f722-v2 --target thumbv7em-none-eabihf +./scripts/create-dfu-image.sh target/thumbv7em-none-eabihf/release/kaptan-geprc-f722-v2 +``` + +The resulting image is telemetry-only and has the shared physical motor-pin +inhibit boundary. diff --git a/docs/src/boards/index.md b/docs/src/boards/index.md new file mode 100644 index 0000000..e73c4b3 --- /dev/null +++ b/docs/src/boards/index.md @@ -0,0 +1,12 @@ +# Boards + +Board pages describe supported hardware topology, build products, and safe +verification. They do not declare a board flight-ready. + +| Board | MCU family | Primary IMU | MAVLink UART | +| --- | --- | --- | --- | +| [Kakute F7 Mini V3](kakute-f7-mini-v3.md) | STM32F722 | MPU-6000 | USART1 | +| [GEPRC GEP-F722-HD V2](geprc-f722-v2.md) | STM32F722 | ICM-42688-P | USART2 | + +All board images share the motor-pin inhibit boundary described in +[Safety boundary](../safety-boundary.md). diff --git a/docs/src/boards/kakute-f7-mini-v3.md b/docs/src/boards/kakute-f7-mini-v3.md new file mode 100644 index 0000000..1e56618 --- /dev/null +++ b/docs/src/boards/kakute-f7-mini-v3.md @@ -0,0 +1,41 @@ +# Kakute F7 Mini V3 + +The Holybro Kakute F7 Mini V3 board declaration uses the MPU-6000 on SPI1, +MAVLink telemetry on USART1, and the MTF01 range/optical-flow route on UART4. +The checked-in manufacturer datasheet is +`boards/kakute-f7-mini-v3/datasheet.pdf`. + +## Build and package + +From the workspace root: + +```sh +cargo build --release -p kaptan-kakute-f7-mini-v3 --target thumbv7em-none-eabihf +./scripts/create-dfu-image.sh target/thumbv7em-none-eabihf/release/kaptan-kakute-f7-mini-v3 +``` + +The packaging script derives the matching binary and linker layout, then +prints the flash and RAM report. + +## Flash over USB DFU + +1. Disconnect USB. +2. Hold the board's `Boot` button. +3. Connect USB, then release `Boot` once the STM32 DFU device enumerates. +4. Flash the generated image: + +```sh +dfu-util --alt 0 --dfuse-address 0x08000000:leave --download target/thumbv7em-none-eabihf/release/kaptan-kakute-f7-mini-v3.bin +``` + +## Telemetry wiring + +Use a 3.3 V USB-to-UART adapter with crossed data lines and common ground: + +| Adapter | Flight controller | +| --- | --- | +| `RX` | `T1` | +| `TX` | `R1` | +| `GND` | `G` | + +This wiring is telemetry only. It does not enable motor control. diff --git a/docs/src/development.md b/docs/src/development.md new file mode 100644 index 0000000..ec30d3b --- /dev/null +++ b/docs/src/development.md @@ -0,0 +1,42 @@ +# Development and verification + +## Fast host checks + +```sh +cargo test --workspace --offline +cargo clippy --workspace --all-targets --offline --exclude kaptan-geprc-f722-v2 --exclude kaptan-kakute-f7-mini-v3 -- -D warnings +cargo clippy -p platform-stm32f7 --all-targets --offline -- -D warnings +cargo fmt --check +git diff --check +``` + +## Target checks + +```sh +cargo check -p kaptan-geprc-f722-v2 --release --target thumbv7em-none-eabihf --offline +cargo check -p kaptan-kakute-f7-mini-v3 --release --target thumbv7em-none-eabihf --offline +``` + +## Strict core coverage + +```sh +scripts/report-test-coverage.sh +``` + +The strict gate requires 100% line and branch coverage for `kaptan-math`, +`kaptan-navigation`, `kaptan-control`, and `kaptan-safety`. It isolates each +core package's coverage artifacts, unions LCOV source-line records, and uses +full LLVM source spans to merge generic branch instantiations without lowering +the gate. + +## Simulation acceptance + +```sh +python3 tools/sitl/world-structure-test.py +python3 -m unittest tools/sitl/test_kaptan_sim.py +tools/sitl/e2e-smoke.sh +``` + +The Docker smoke is intentionally separate from host unit tests because it +builds the pinned base images, Rust binary, Gazebo plugin, and full loopback +plant. diff --git a/docs/src/getting-started.md b/docs/src/getting-started.md new file mode 100644 index 0000000..7cf4576 --- /dev/null +++ b/docs/src/getting-started.md @@ -0,0 +1,42 @@ +# Getting started + +## Prerequisites + +Use the repository toolchain, Rust 1.90. The workspace declares the embedded +F7 targets and `llvm-tools-preview` in `rust-toolchain.toml`. + +For host development, run: + +```sh +cargo test --workspace --offline +cargo clippy --workspace --all-targets --offline --exclude kaptan-geprc-f722-v2 --exclude kaptan-kakute-f7-mini-v3 -- -D warnings +``` + +Bare-metal board packages are not host-test targets. Check them with the +target-specific commands in [Development and verification](development.md). + +## Repository layout + +| Path | Responsibility | +| --- | --- | +| `boards/` | Immutable board declarations and linker layouts. | +| `platforms/stm32f7/` | Reviewed F722 RTIC platform and peripheral ownership. | +| `libs/` | Typed math, estimation, control, safety, protocol, and driver crates. | +| `tools/sitl/` | Host-only closed-loop Gazebo simulation. | +| `docs/` | This Markdown documentation site. | + +Do not add board-local READMEs. Add a page here instead, then link it from +`SUMMARY.md`. + +## Build the documentation website + +The manual is an [mdBook](https://rust-lang.github.io/mdBook/) project. Build +it locally with a compatible `mdbook` binary: + +```sh +make -C docs build +``` + +The generated static site is written to `target/docs/`. The GitHub Pages +workflow builds that same output from `main`; enable **GitHub Actions** as the +repository's Pages publishing source once, then deployments are automatic. diff --git a/docs/src/index.md b/docs/src/index.md new file mode 100644 index 0000000..3875500 --- /dev/null +++ b/docs/src/index.md @@ -0,0 +1,27 @@ +# Kaptan Developer Manual + +Kaptan is an embedded Rust flight-controller project. This manual is the +single source of project documentation: board support, safety boundaries, +simulation, development workflow, and design references live here as +Markdown. + +The checked-in firmware is telemetry-only. It does not expose physical motor +authority, and no document in this site should be read as a physical-flight +release claim. + +## Start here + +- New contributors should read [Getting started](getting-started.md). +- Board work belongs under [Boards](boards/index.md). +- The currently supported closed-loop simulation is [Host SITL](sitl.md). +- Before submitting changes, follow [Development and verification](development.md). + +## Documentation conventions + +Documentation is centralized in `docs/src/`; source directories do not carry +README files. Keep pages in Markdown, add each page to `SUMMARY.md`, and place +commands beside the assumptions and safety boundary they depend on. + +`TODO(configuration)` marks a required configuration contract that has not +been implemented. It is not permission for an operator to substitute runtime +values or bypass an immutable build-time safety decision. diff --git a/docs/src/mavlink.md b/docs/src/mavlink.md new file mode 100644 index 0000000..8487aa8 --- /dev/null +++ b/docs/src/mavlink.md @@ -0,0 +1,20 @@ +# MAVLink and telemetry + +Kaptan emits telemetry using MAVLink 2 framing. The production receiver does +not promote inbound MAVLink frames to authority records: + +- MAVLink 1 is discarded. +- CRC-invalid MAVLink 2 frames are discarded. +- Signed frames are discarded because no signature verifier or persistent + replay state exists. +- Unsigned MAVLink 2 frames are also discarded; a V2 CRC detects corruption, + not authentication. + +`TODO(signing)`: any future inbound authority requires verified MAVLink 2 +signing, configured source/target binding, persistent anti-replay state, and a +provisioning/key-rotation policy as one reviewed feature. + +Telemetry transmission uses bounded frame classes. A critical frame may +replace pending best-effort traffic, but never the DMA-owned active buffer. +Completion retries preserve ordering and retain a transiently busy frame for a +later service turn. diff --git a/docs/src/reference.md b/docs/src/reference.md new file mode 100644 index 0000000..fe5b1cd --- /dev/null +++ b/docs/src/reference.md @@ -0,0 +1,19 @@ +# Reference + +## Build-time configuration + +Board configuration is immutable in the compiled image. Runtime parameter +updates and ground-station tuning are not exposed by the checked-in firmware. + +`TODO(configuration)`: a future configuration system must validate and stage +an entire profile while disarmed, commit it atomically, and prove that outputs +remain inhibited throughout staging, activation, and power-loss recovery. + +## Simulation package reproducibility + +The host SITL Docker build uses digest-pinned base images and the locked Rust +dependency graph. The signed Gazebo APT feed is not snapshot-pinned. + +`TODO(reproducibility)`: snapshot/version-pin the Gazebo package set and +verify the repository signing-key fingerprint before treating the simulator +image as byte-for-byte reproducible release input. diff --git a/docs/src/safety-boundary.md b/docs/src/safety-boundary.md new file mode 100644 index 0000000..86efe97 --- /dev/null +++ b/docs/src/safety-boundary.md @@ -0,0 +1,24 @@ +# Safety boundary + +Every checked-in F722 image inhibits PB0, PB1, PB4, and PB5 before normal +board initialization. The interlock configures each pin as a low, push-pull +GPIO output; it runs before clocks, board routing, UART setup, or RTIC tasks. + +There is no checked-in platform actuator route: + +- no DShot or PWM peripheral implementation is linked; +- no TIM3/TIM5 motor task or DMA output path exists; +- MAVLink input has no production authority path; +- a future verified arm command is still acknowledged as unsupported. + +The protocol reference crate remains in the workspace only as a framing and +arming-sequence reference. It does not grant hardware access or authority. + +Run the structural guard after any platform or board change: + +```sh +cargo test -p platform-stm32f7 --test platform_safety_boundary --offline +``` + +This boundary is deliberately stronger than an application-level disarm flag: +it removes the physical actuator implementation from the platform image. diff --git a/docs/src/sitl.md b/docs/src/sitl.md new file mode 100644 index 0000000..e7fe8d9 --- /dev/null +++ b/docs/src/sitl.md @@ -0,0 +1,40 @@ +# Host SITL + +Host SITL is Kaptan's deterministic closed-loop simulation tier. Gazebo sends +simulated IMU and declared noisy local position/velocity observations over a +private loopback protocol. The Rust process runs the ESKF, safety supervisor, +trajectory, controller, and allocator, then returns four virtual motor +fractions to Gazebo. + +It is a pre-bench software gate, not a physical-flight validation. + +## Run the closed loop + +```sh +docker compose -f tools/sitl/compose.yaml up -d --build +tools/sitl/kaptan-sim ready +tools/sitl/kaptan-sim move 5 3 1 --wait +tools/sitl/kaptan-sim land 0 0 --wait +docker compose -f tools/sitl/compose.yaml down +``` + +For the reproducible command-path gate, use: + +```sh +tools/sitl/e2e-smoke.sh +``` + +The smoke scenario verifies ascent, translation, descent, landing, flat-plane +proximity, and zero applied motor fractions after landing. Its reference world +contains only a visual landing pad; the pad has no collision geometry and +never contributes a controller or truth observation. + +Open , connect to +`ws://localhost:9002`, and leave authorization blank to view the world. + +## Limits + +This model does not validate terrain, vision, flow/range sensing, wind, +vibration, battery/ESC behavior, sensor latency/jitter, actuator faults, or +physical touchdown sensing. Add those only as a reviewed sensor/contact model, +not as a display-only shortcut. diff --git a/docs/theme/kaptan.css b/docs/theme/kaptan.css new file mode 100644 index 0000000..5d6a8cf --- /dev/null +++ b/docs/theme/kaptan.css @@ -0,0 +1,47 @@ +:root { + --kaptan-ink: #142033; + --kaptan-blue: #1769aa; + --kaptan-sky: #e8f3fb; + --kaptan-border: #d4dfeb; +} + +.content main { + max-width: 58rem; + margin: 0 auto; +} + +.content h1, +.content h2, +.content h3 { + color: var(--kaptan-ink); + font-weight: 700; + letter-spacing: -0.02em; +} + +.content h1 { + border-bottom: 3px solid var(--kaptan-blue); + padding-bottom: 0.45rem; +} + +.content a { + color: var(--kaptan-blue); +} + +.content table { + border: 1px solid var(--kaptan-border); + border-radius: 0.5rem; + overflow: hidden; +} + +.content blockquote { + border-left-color: var(--kaptan-blue); + background: var(--kaptan-sky); +} + +.sidebar .sidebar-scrollbox { + border-right: 1px solid var(--kaptan-border); +} + +.nav-chapters { + border-top: 1px solid var(--kaptan-border); +} diff --git a/docs/theme/kaptan.js b/docs/theme/kaptan.js new file mode 100644 index 0000000..dc6a94d --- /dev/null +++ b/docs/theme/kaptan.js @@ -0,0 +1,5 @@ +"use strict"; + +// Keep a small stable hook for future theme enhancements without replacing +// mdBook's built-in navigation, search, or theme picker. +document.documentElement.classList.add("kaptan-docs");