Files
autopilot/_docs/02_tasks/todo/AZ-642_mavlink_codec.md
T
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

4.3 KiB
Raw Blame History

MAVLink Message Codec (§7.7 Surface)

Task: AZ-642_mavlink_codec Name: MAVLink v2 encode/decode for the §7.7 surface Description: Encode and decode the ~1015 MAVLink v2 messages this codebase needs (the §7.7 surface only) with strict validation. Complexity: 5 points Dependencies: AZ-640_initial_structure Component: mavlink_layer Tracker: AZ-642 Epic: AZ-637

Problem

Autopilot speaks a deliberately narrow MAVLink command surface (per architecture.md §7.7 — ~1015 messages). Adding messages outside that list requires explicit design review. A hand-rolled MAVLink v2 codec must encode outbound messages with correct sequence numbers, system / component IDs, and (when enabled) signing, and decode inbound messages with strict validation — rejecting malformed frames, unknown IDs, and signing failures.

Outcome

  • Outbound encoder produces wire-correct MAVLink v2 frames for the message surface in §7.7 with monotonically incrementing per-link sequence numbers.
  • Inbound decoder parses the same surface, rejecting malformed frames, unknown message IDs, and frames with sequence-number gaps (logged, not hard-failed).
  • Decoded messages are exposed as a typed MavlinkMessage enum (one variant per supported message kind) on the inbound channel.
  • Per-message-kind parse error counters are exposed via health().

Scope

Included

  • Encode + decode for HEARTBEAT (bidir), COMMAND_LONG outbound subset (arm/disarm, takeoff, set-mode, change-speed, change-alt, land, RTL), COMMAND_ACK inbound, MISSION_COUNT, MISSION_REQUEST_INT, MISSION_ITEM_INT, MISSION_ACK, MISSION_SET_CURRENT, MISSION_CURRENT, MISSION_ITEM_REACHED, MISSION_CLEAR_ALL, GLOBAL_POSITION_INT, ATTITUDE, SYS_STATUS, EXTENDED_SYS_STATE, STATUSTEXT, SET_MODE.
  • Per-link outbound tx_seq counter with wrap-around handling.
  • Strict size + CRC validation; reject malformed frames.
  • Unknown message IDs counted and dropped (not hard-failed).
  • Sequence-number gap detection (logged, not fatal).

Excluded

  • Transport and reconnect (task 02).
  • Heartbeat scheduling (task 02).
  • Ack demultiplexing to callers (task 04).
  • MAVLink-2 signing (task 04).
  • Any message not in the §7.7 surface — adding new messages requires design review.

Acceptance Criteria

AC-1: Round-trip every supported message Given the encoder produces a frame for each message kind in the §7.7 surface with deterministic field values When the same frame is fed back through the decoder Then the typed MavlinkMessage matches the original fields and parse_errors_total does not increment.

AC-2: Malformed frame is rejected Given a byte buffer with a truncated payload or a wrong CRC When the decoder consumes it Then the frame is dropped, parse_errors_total{kind="crc" | "truncated"} increments by 1, and the codec continues processing subsequent bytes.

AC-3: Unknown message ID is counted, not fatal Given an inbound frame with a message ID outside the §7.7 surface When the decoder consumes it Then the frame is dropped, parse_errors_total{kind="unknown_id"} increments by 1, and decoding continues.

AC-4: SITL round-trip Given an ArduPilot SITL instance configured for udp://127.0.0.1:14550 When mavlink_layer emits a COMMAND_LONG for MAV_CMD_NAV_RETURN_TO_LAUNCH Then SITL receives the command and replies with a matching COMMAND_ACK; the decoder emits a MavlinkMessage::CommandAck with result = MAV_RESULT_ACCEPTED.

Non-Functional Requirements

Performance

  • Per-message encode + decode round-trip: ≤50 ms p99 on a healthy link (per description.md §8).

Reliability

  • No silent acceptance of malformed or signed-mismatch frames.

Constraints

  • Hand-rolled — no third-party MAVLink SDK.
  • Adding any message outside the §7.7 surface requires an explicit design review noted in the PR description.

Runtime Completeness

  • Named capability: MAVLink v2 wire-correct encode/decode for the §7.7 command surface.
  • Production code that must exist: real byte-level encoder + decoder; CRC computation; sequence number handling.
  • Allowed external stubs: ArduPilot SITL is the conformance reference for the SITL round-trip AC.
  • Unacceptable substitutes: a JSON or human-readable "MAVLink-like" envelope is not acceptable — the wire format must be MAVLink v2.