Files
Oleksandr Bezdieniezhnykh bc40ea7300 [AZ-626] Decompose complete: 47 tasks + docs + module layout
Greenfield Steps 1-6 baseline for the autopilot rewrite from legacy
Qt/C++ to a Rust workspace.

- Remove legacy Qt/C++ tree (ai_controller, drone_controller,
  misc/camera, python_scaffold, root Dockerfile, autopilot.pro,
  legacy main.py / requirements.txt).
- Add _docs/00_problem (problem, restrictions, acceptance criteria,
  security approach, input data + fixtures).
- Add _docs/01_solution/solution_draft01.
- Add _docs/02_document (architecture, system-flows, data_model,
  glossary, decision-rationale, deployment, 13 component descriptions,
  tests/ specs, FINAL_report, module-layout).
- Add _docs/02_tasks/todo with 47 task specs (AZ-640..AZ-686, one
  bootstrap + 46 component tasks) and _dependencies_table.md.
- Add .cursor/rules/artifact-srp.mdc (single-responsibility rule for
  canonical _docs artifacts).
- Track autodev state in _docs/_autodev_state.md (Step 6 completed,
  ready for Step 7 Implement).

Jira: bootstrap AZ-626; component epics AZ-627..AZ-639; tasks
AZ-640..AZ-686. Total complexity 173 points across 12 epics.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-19 11:02:01 +03:00

9.1 KiB
Raw Permalink Blame History

Component — mapobjects_store

Layer: Decision + Memory Status: forward-looking design (Rust); on-device working copy of the central MapObjects state, mission-bracketed

1. Purpose

On-device, H3-indexed working copy of the centrally maintained MapObjects state plus the IgnoredItems list, scoped to the active mission's bounding box. Computes new / moved / existing / removed diffs across survey passes and is the source of truth for the operator-decline suppression rule for the duration of the active mission.

This is not a private database. It is hydrated pre-flight from the central missions API (/missions/{id}/mapobjects) and the mission's full pass diff is pushed back post-flight. The central observation log + computed current view are authoritative across missions and across UAVs (architecture.md §7.13).

2. Inputs

Input Source Cadence Notes
Pre-flight pull payload mission_client (from missions API) once per mission Hydrates current_state + pending_ignored.
New detection / movement candidate (with MGRS + class + size) scan_controller per detection Each is classified as new / moved / existing.
IgnoredItem append scan_controller (on operator decline) event (MGRS, class_group) plus operator metadata.
End-of-pass marker scan_controller / mission_executor event per pass over a region Triggers the removed-candidate sweep.
Mission delete cascade suite-level missions API hook (process-level config; not a network call) event Drops mission-scoped objects on mission deletion.
Post-flight push trigger mission_executor once per mission, on terminal state Causes mission_client to drain pending_observations + pending_ignored to the central API.

3. Outputs

Output Consumer Shape
MapObjectClassification scan_controller new | moved | existing | removed_candidate per detection
IgnoredItem match scan_controller suppression flag for (MGRS, class_group)
Pass diff mission_client (post-flight upload) + operator_bridge (optionally surfaced in-flight) new / moved / removed lists per pass
Sync state scan_controller, health aggregator synced | cached_fallback | degraded; pending_observations_count, pending_ignored_count

4. Key Responsibilities

  • Pre-flight hydrate from mission_client pull. Establish current_state and pending_ignored. Surface sync_state (synced or cached_fallback or degraded).
  • Compute H3 cell for each detection at the configured resolution (default res 10, ~15 m edge).
  • Build the composite key H3_cell + class. Maintain an in-memory hashmap; persist asynchronously to disk for crash recovery.
  • Answer queries: classify(detection) → new | moved | existing using k-ring lookup and (distance_threshold_m, move_threshold_m, similar_classes) configuration.
  • After a region's scan-pass ends, return objects in the region that were not re-observed as removed_candidates (the operator decides on actual removal).
  • Maintain the IgnoredItem set; answer suppression queries (is_ignored(MGRS, class_group)).
  • Append every NEW / MOVED / EXISTING / REMOVED-CANDIDATE / IgnoredItem event to pending_observations / pending_ignored for the post-flight push (in-flight central writes are forbidden — Frozen choice 6 in architecture.md §7.3).
  • Post-flight push: hand the contents of pending_observations + pending_ignored to mission_client for POST /missions/{id}/mapobjects and POST /missions/{id}/mapobjects/ignored. On ack, clear pending; on failure, persist for retry.
  • On DELETE /missions/{id} cascade signal (received via mission_client), drop all objects scoped to that mission. The central side cascades as well.

5. Sync state machine

fresh_boot
   │
   ├──> pre-flight pull
   │       │
   │       ├── 200 OK ────────────> synced
   │       ├── unreachable ────────> [operator ack required]
   │       │                           │
   │       │                           ├── ack on cache ──> cached_fallback
   │       │                           └── abort ─────────> BIT fail
   │       └── 4xx ─────────────────> BIT fail
   │
   ├── (during flight; in-process writes only)
   │       │
   │       ├── pending_observations grow
   │       └── pending_ignored grow
   │
   └── post-flight push
           │
           ├── 200 OK on both endpoints ──> synced (pending cleared)
           ├── partial ────────────────────> retry per-endpoint
           └── persistent failure ─────────> degraded (operator warning, manual replay)

6. Internal State

  • In-memory hashmap of (H3_cell + class) → MapObject.
  • IgnoredItem set keyed by (MGRS, class_group).
  • Per-region pass tracker for removed-candidate detection.
  • pending_observations: ordered log of NEW / MOVED / REMOVED-CANDIDATE / EXISTING events not yet pushed centrally.
  • pending_ignored: ordered log of IgnoredItem appends not yet pushed centrally.
  • sync_state: enum + last-pull timestamp + last-push timestamp + last error.
  • Persistence layer (engine TBD — see Open Questions) for crash recovery and post-flight upload durability.

7. Failure Modes

Failure Detection Behaviour
Pre-flight pull unreachable network Surface BIT degradation; operator must acknowledge cached fallback or abort. Never silent.
Pre-flight pull stale beyond freshness window last-fetch-at compared to configured staleness sync_state = degraded; operator must acknowledge or abort.
Persistence write failure engine error Log + retry; in-memory state continues authoritative for this mission; health → yellow.
Persistence corruption on startup checksum / open failure Refuse to start with stale state; require explicit recovery (engine-specific); surface to operator at startup.
H3 query inconsistency near cell boundaries algorithmic Always query the k-ring (k=2 default) so boundary objects are matched anyway.
Mission cascade signal lost absent signal DELETE /missions/{id} is the only cleanup trigger; on lost signal, mission-scoped objects accumulate. Operator-driven manual purge is acceptable.
Post-flight push partial success per-endpoint status Independent retry per endpoint; do not roll back the successful one.
Post-flight push persistent failure bounded retries exhausted sync_state = degraded; pending diff persisted on disk; operator-visible warning; manual replay supported. Mission's central data integrity at risk until replayed.
In-flight crash startup detects non-empty pending_* for a terminated mission mission_client runs the post-flight push at startup before BIT completes for any new mission.

8. Dependencies

In-process: scan_controller, mission_client (for pull/push round-trips), mission_executor (for post-flight trigger).

External: H3 spatial-index library (Rust crate). Persistent store engine — TBD (SQLite + H3 extension / KV / in-memory + snapshot — see Open Questions). Central API contract via mission_client's extension of the missions API (per architecture.md §7.13).

9. Non-Functional Targets

Concern Target
Per-detection classify latency O(1); p99 ≤1 ms
Pre-flight pull time ≤30 s for a 30 km × 30 km mission area (per architecture.md §6 NFR)
Post-flight push time ≤2 min for a 60 min mission's pass diff (per architecture.md §6 NFR)
Persistent-store size (single mission) bounded; configurable retention
Crash recovery time ≤2 s to a usable state; in-flight crash → next-boot push of pending
Boundary correctness guaranteed by k-ring query

10. Open Questions

  • Engine choice (architecture.md §8 Q3): SQLite + H3 extension / KV / in-memory + snapshot.
  • Central API schema details (architecture.md §8 Q7): paging strategy, photo-reference upload mechanism, observation-history retention policy.
  • Conflict resolution rules (architecture.md §8 Q8): exact projection from observation log to current view; REMOVED-claim expiry window; multi-class disambiguation.
  • Optimal H3 resolution per terrain class.
  • Class-group definitions (military_vehicle_group vs concealed_position_group vs movement_candidate) — currently in scan_controller config.

11. References

  • architecture.md §3, §5 Architectural Principles (MapObjects are mission-bracketed and centrally synchronised), §6 NFR, §7.9 MapObjects (H3 spatial index), §7.10 Sync Message Format, §7.11 Target Relocation, §7.12 New vs Existing object detection, §7.13 MapObjects Sync.
  • system-flows.md §F7 MapObjects + ignored-items (in-flight diff), §F8 MapObjects sync (central DB, mission-bracketing).
  • data_model.md §MapObject, §IgnoredItem, §MapObjectObservation, §MapObjectsBundle.
  • ../_docs/02_missions.md (mission cascade contract; new MapObjects endpoints).