mirror of
https://github.com/azaion/autopilot.git
synced 2026-06-22 11:11:15 +00:00
[AZ-653] gimbal_controller ViewPro A40 vendor UDP transport (batch 10)
ci/woodpecker/push/build-arm Pipeline failed
ci/woodpecker/push/build-arm Pipeline failed
Implements the vendor wire protocol for the A40 gimbal (XOR-8 checksum, not CRC16 — task spec corrected against ArduPilot AP_Mount_Viewpro.h): frame encode/decode, typed FrameId/CameraCommand/ImageSensor, A1 angles, C1 camera, C2 set-zoom command builders, and a tokio UdpSocket transport with bounded retry, per-command deadline, and atomic vendor-fault counters surfaced via faults()/health(). GimbalControllerHandle::set_pose and zoom now ride the transport when wired; remain disabled when no transport is bound. 32/32 gimbal_controller tests green; workspace test suite green except for a pre-existing flake in mission_executor::state_machine::ac3_bounded_retry_then_success that reproduces only under parallel workspace test load (passes 5/5 in isolation; flagged in batch 8 report, unrelated to this batch). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# ViewPro A40 Vendor Transport
|
||||
|
||||
**Task**: AZ-653_gimbal_a40_transport
|
||||
**Name**: ViewPro A40 vendor protocol UDP transport
|
||||
**Description**: UDP transport, frame encode/decode, CRC16 (vendor spec), bounded retry on command timeout. Surface vendor faults to health.
|
||||
**Complexity**: 5 points
|
||||
**Dependencies**: AZ-640_initial_structure
|
||||
**Component**: gimbal_controller
|
||||
**Tracker**: AZ-653
|
||||
**Epic**: AZ-634
|
||||
|
||||
## Problem
|
||||
|
||||
The gimbal is a ViewPro A40 vendor product reachable over UDP using a vendor-specified frame format with CRC16. The transport layer must encode and decode every command/response frame this codebase issues (yaw, pitch, zoom, feedback request, mode commands), validate CRC on inbound frames, and re-issue on timeout with bounded retry. The vendor protocol is fixed by the camera — the device's binary protocol is a `restrictions.md` constraint, not a design choice.
|
||||
|
||||
## Outcome
|
||||
|
||||
- `A40Transport::send(cmd) -> Result<A40Response, A40Error>` writes a CRC-correct vendor frame to the configured UDP endpoint and awaits the matching response within a deadline.
|
||||
- Inbound frames are CRC-validated; mismatches are dropped and counted as `vendor_faults_total{kind="crc"}`.
|
||||
- Bounded retry on timeout (default 3 attempts; configurable).
|
||||
- Health surface: `commands_per_min`, `vendor_faults_total`, `last_command_in_flight`.
|
||||
|
||||
## Scope
|
||||
|
||||
### Included
|
||||
- UDP socket (single endpoint).
|
||||
- CRC16 (vendor polynomial) encode/decode helpers.
|
||||
- Frame encoders for yaw / pitch / zoom commands + feedback request.
|
||||
- Frame decoders for yaw / pitch / zoom feedback + vendor fault frames.
|
||||
- Bounded retry on timeout.
|
||||
|
||||
### Excluded
|
||||
- Sweep pattern primitive (task 15).
|
||||
- Smooth-pan plan execution (task 16).
|
||||
- Centre-on-target primitive (task 17).
|
||||
- Vendor protocol *specification* — assumed to be reverse-engineered or vendor-supplied separately; this task implements against the documented frame layout in `misc/camera/a8/` (which is the predecessor model A8; A40 differs in command codes per architecture.md).
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
**AC-1: CRC round-trip**
|
||||
Given the encoder produces a yaw command frame for `yaw = 30°`
|
||||
When the same frame is fed back through the decoder
|
||||
Then the decoded command matches and `vendor_faults_total{kind="crc"} = 0`.
|
||||
|
||||
**AC-2: CRC mismatch counted**
|
||||
Given an inbound frame with corrupted CRC
|
||||
When the decoder consumes it
|
||||
Then the frame is dropped and `vendor_faults_total{kind="crc"}` increments by 1.
|
||||
|
||||
**AC-3: Command timeout retries**
|
||||
Given a fake A40 endpoint that drops the first command silently
|
||||
When `send(yaw_cmd)` is called with default 3 attempts
|
||||
Then the call succeeds on retry; `vendor_faults_total{kind="timeout"}` reports 1.
|
||||
|
||||
**AC-4: Cap exhaustion returns explicit error**
|
||||
Given the endpoint never responds
|
||||
When `send(yaw_cmd)` is called
|
||||
Then after 3 attempts the call returns `Err(MaxRetriesExceeded)` and the error surfaces to the caller.
|
||||
|
||||
## Non-Functional Requirements
|
||||
|
||||
**Performance**
|
||||
- Single command round-trip: ≤200 ms on a healthy link (well under the ≤500 ms decision-to-movement budget).
|
||||
|
||||
**Reliability**
|
||||
- CRC mismatches counted, never silent.
|
||||
- Bounded retry; no infinite retry.
|
||||
|
||||
## Constraints
|
||||
|
||||
- Vendor protocol is fixed; no negotiation.
|
||||
- One A40 per autopilot instance.
|
||||
|
||||
## Runtime Completeness
|
||||
|
||||
- **Named capability**: ViewPro A40 vendor protocol on UDP.
|
||||
- **Production code that must exist**: real CRC16; real UDP socket; real per-command encoder/decoder.
|
||||
- **Allowed external stubs**: in tests, a UDP echo with vendor-frame replay can simulate the camera.
|
||||
- **Unacceptable substitutes**: a generic "send raw bytes and assume success" path is unacceptable — the protocol's frame format and CRC are non-negotiable.
|
||||
Reference in New Issue
Block a user