Files
swarm-house/docs/02-architecture.md
T
eSlider 5f6fd8462c
CI & Release / Verify simulator (push) Skipped
CI & Release / Trivy scan (push) Skipped
CI & Release / Semantic Release (push) Skipped
CI & Release / Verify simulator (pull_request) Failing after 4s
CI & Release / Trivy scan (pull_request) Skipped
CI & Release / Semantic Release (pull_request) Skipped
docs: audit links, glossary T0-T4, readability pass
Extend glossary with storage floors, source of truth, and linkable anchors.
Fix broken links, pose frame drift, rsync/offload wording, and README tone.
Add docs/improvement audit records and live demo links in design journey.
2026-07-10 10:46:59 +01:00

89 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 02 — Architecture
## On-board: three layers, one Compose file
Every drone runs the same [three-layer](00-glossary.md#architecture-layer-1--ingestion) data plane ([storage floors](00-glossary.md#t0--hot) T0T4 are a separate concept — see [03 — Data platform](03-data-platform.md#storage-floors-tiers)). **Docker Compose under systemd is the only on-board orchestrator.** Cluster orchestrators (Kubernetes, Swarm mode) assume a stable control plane and continuous connectivity — in an ad-hoc mesh with intermittent links that is an anti-pattern. Each drone is fully autonomous; coordination happens through data exchange, not through a shared control plane. Lightweight Kubernetes (k3s) is used on the ground only (warehouse, CI runners, simulation farm — see [06 — Environments](06-environments.md)).
```mermaid
graph TB
subgraph drone [Single drone — Docker Compose under systemd]
subgraph ingestion [Layer 1 — Ingestion]
SENSORS["sensor-ingest<br/>ROS 2 topics / drivers → stream"]
VIDEO["video-analytics<br/>YOLO-like detector, GPU"]
end
subgraph storage [Layer 2 — Storage and transform]
WRITER["parquet-writer<br/>stream → current/ blocks"]
SEALER["sealer<br/>compact closed windows"]
DUCK["DuckDB<br/>in-process SQL over Parquet"]
NVME[("NVMe<br/>Hive-partitioned Parquet")]
end
subgraph serving [Layer 3 — Serving and sync]
HOOK["event hook<br/>fires on new derived data"]
PUB["state publisher<br/>pub/sub broadcast"]
MINIO["MinIO<br/>derived datasets bucket"]
QAPI["query API<br/>peer data requests"]
end
end
SENSORS --> WRITER
VIDEO -->|detections| WRITER
WRITER --> NVME
SEALER --> NVME
DUCK --> NVME
WRITER -->|derived rows| HOOK
HOOK --> PUB
HOOK --> MINIO
QAPI --> DUCK
PUB -.->|mesh| PEERS["peer drones"]
MINIO -.->|replication| PEERS
QAPI -.->|on demand| PEERS
```
### Layer 1 — Ingestion
- `sensor-ingest` subscribes to sensor sources (ROS 2 topics where available, raw drivers otherwise) and normalizes them into typed streams: IMU, barometer, temperature, LiDAR, RSSI, power, and so on.
- `video-analytics` runs a [**YOLO-like**](00-glossary.md#swarm--robotics) object detector on the camera stream. The model is deliberately treated as a swappable, versioned artifact (weights differ per mission and improve over time — see [11 — CI/CD & delivery](11-cicd-delivery.md)). GPU access via nvidia-container-toolkit; ARM64 builds use the vendor's L4T-class base images.
- Both services emit rows, not files. Timestamps are `int64` epoch **nanoseconds** end to end (native for ROS 2; IMU-class rates make milliseconds insufficient).
### Layer 2 — Storage and transform
- `parquet-writer` appends incoming rows into small per-minute Parquet blocks under the partition's `current/` directory (details in [03 — Data platform](03-data-platform.md)).
- `sealer` compacts each closed window into one ZSTD-compressed file and enforces retention quotas on the NVMe.
- DuckDB runs **in-process** inside whichever service needs SQL — there is no database server to babysit.
### Layer 3 — Serving and sync
- The **event hook** is the on-board "lambda": when the writer lands new *derived* rows (state, detections), it triggers registered actions — broadcast, MinIO upload, or a local mission-logic callback. Nothing polls.
- The **state publisher** broadcasts compact position/attitude/detection payloads over the mesh pub/sub (transport analysis in [04 — Swarm sync](04-swarm-sync.md)).
- **Bulk sync** pulls sealed derived partitions from peers over persistent SSH ([rsync](00-glossary.md#bulk-sync) delta transfer); MinIO remains optional where an S3 API is wanted.
- **Peer queries** are read-only DuckDB SQL over SSH forced commands — SELECT-only gate, read-only OS user, columnar responses (the design decision and its reasoning are in [04](04-swarm-sync.md)).
## Communication planes
Three isolated planes with different lifecycles:
```mermaid
graph LR
subgraph planes [Communication planes]
C2["[C2](00-glossary.md#swarm--robotics) control plane<br/>mission intent, narrow, in production"]
DATA["swarm data plane<br/>state broadcast + sync, in production"]
DEV["dev/debug plane<br/>live telemetry, bench only"]
end
OPERATOR["supervising operator<br/>([man-in-the-loop](00-glossary.md#swarm--robotics))"] --> C2
C2 --> SWARM["swarm"]
SWARM <--> DATA
DEV -.->|absent from production builds| SWARM
```
| Plane | Purpose | Bandwidth | In production |
| --- | --- | --- | --- |
| **C2 control plane** | Deliver declarative mission goals and boundaries; receive high-level status. Human supervises intent, not actions | Very low | Yes |
| **Swarm data plane** | State broadcast, derived-data replication, peer queries | The scarce resource; budget per message class | Yes |
| **Dev/debug plane** | Full live telemetry for bench development and [HIL](00-glossary.md#infrastructure--delivery) tests | High | **No — physically absent from production builds** |
The dev plane is not "disabled by config": production images and radio profiles simply do not contain it. That removes an entire attack surface instead of guarding it.
## Out of scope (consumed as services)
Flight control, trajectory planning, mission logic, and model training sit **on top of** this platform: they subscribe to the event hook, query DuckDB, and read the warehouse. Their internals do not affect the platform design beyond the data contracts defined here.