sprint-0: foundations -- data model, seed library, tests, demo

Initial commit. Delivers what the brief calls 'Sprint 0 - Foundations'
(see docs/AR_Autopilot_brief.md section 12):

- Complete repository structure (arautopilot package + firmware, display,
  installer, tools placeholders + docs).
- Core data model (Pydantic v2): modes, alarms, actuator config, PID
  config + gain scheduling, vessel config, knob state machine, project
  config with YAML/JSON serialisation.
- Seed library: 2 actuator profiles (hydraulic & electric DC reversible)
  and 2 default tunings (yacht motor planeo 30 m and 40 m). Conservative
  literature values, NOT the integrator's production tuning IP.
- Firmware skeleton: only src/hal/pinout.h with the 21 I/O contract for
  the AR-NMEA-IO v1.0 board. No drivers, no main loop.
- Studio stubs (real PySide6 app starts in Sprint 4).
- pytest suite (80 tests, all green): modes, alarms, actuator, PID
  (incl. gain interpolation and the +/-50% adaptive bound from brief
  section 6), vessel, knob state, project config, library loader,
  end-to-end roundtrip.
- examples/sprint0_demo.py - the acceptance demo from the brief.

Acceptance criteria met:
- pytest green (80/80)
- demo creates, saves (YAML + JSON), reloads, and verifies a full
  ProjectConfig using the seed library
- repository ready for tag `sprint-0-approved`

See CHANGELOG.md for the detailed scope.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-17 23:57:18 -04:00
commit 700756c16f
54 changed files with 3855 additions and 0 deletions
+112
View File
@@ -0,0 +1,112 @@
// =============================================================================
// AR-Autopilot v1 — Pinout for AR-NMEA-IO v1.0 board (ESP32-DOWD)
// =============================================================================
//
// Sprint 0: pin contract only. No drivers, no main loop. This file is the
// source of truth for which physical I/O carries which logical function for
// the autopilot application; the firmware code in Sprint 1+ consumes it.
//
// Hardware reference: AR-NMEA-IO v1.0 (same board used by VMS-Sailor).
// 21 user I/O: 4 analog inputs, 5 digital inputs, 1 RPM/frequency input,
// 10 digital outputs, plus dedicated RS-485 (Modbus), CAN (NMEA 2000) and
// WiFi (OTA only).
//
// Source: brief section 4.1 "Asignación típica de puertos para piloto
// motor 30-40 m".
//
// NOTE: The numeric GPIO assignments below are PLACEHOLDERS aligned with the
// AR-NMEA-IO schematic. They will be confirmed and locked in Sprint 1
// against the real board revision. Do not depend on them yet.
// =============================================================================
#pragma once
// -----------------------------------------------------------------------------
// Firmware identity
// -----------------------------------------------------------------------------
#define AR_AUTOPILOT_FW_NAME "AR-Autopilot"
#define AR_AUTOPILOT_FW_VERSION "0.1.0-sprint0"
#define AR_AUTOPILOT_HW_BOARD "AR-NMEA-IO v1.0"
#define AR_AUTOPILOT_MCU "ESP32-DOWD"
// -----------------------------------------------------------------------------
// Analog inputs (4)
// AI1 — Rudder angle position sensor (pot / Hall, 0-10 V or 4-20 mA)
// AI2 — System battery voltage
// AI3 — Actuator current (shunt or Hall) — overcurrent protection
// AI4 — Reserved (future: hydraulic pressure)
// -----------------------------------------------------------------------------
#define PIN_AI1_RUDDER_ANGLE 36 // GPIO36 / ADC1_CH0 / SVP
#define PIN_AI2_BATTERY_VOLTAGE 39 // GPIO39 / ADC1_CH3 / SVN
#define PIN_AI3_ACTUATOR_CURRENT 34 // GPIO34 / ADC1_CH6
#define PIN_AI4_RESERVED 35 // GPIO35 / ADC1_CH7
// -----------------------------------------------------------------------------
// Digital inputs (5)
// DI1 — "Engage / Disengage" push-button on bridge console (ALWAYS DISENGAGES)
// DI2 — Port-side rudder mechanical limit switch
// DI3 — Starboard-side rudder mechanical limit switch
// DI4 — External critical alarm (VMS blackout, genset critical)
// DI5 — Manual confirmation (emergency override)
// -----------------------------------------------------------------------------
#define PIN_DI1_DISENGAGE_BUTTON 32 // GPIO32 — wakes from light sleep
#define PIN_DI2_LIMIT_SWITCH_PORT 33 // GPIO33
#define PIN_DI3_LIMIT_SWITCH_STBD 25 // GPIO25
#define PIN_DI4_EXTERNAL_ALARM 26 // GPIO26
#define PIN_DI5_MANUAL_CONFIRM 27 // GPIO27
// -----------------------------------------------------------------------------
// RPM / frequency input (1)
// RPM1 — Reserved (future: rotation sensor if applicable)
// -----------------------------------------------------------------------------
#define PIN_RPM1_RESERVED 14 // GPIO14 — PCNT-capable
// -----------------------------------------------------------------------------
// Digital outputs (10)
// DO1 — Pump/motor command PORT (direction)
// DO2 — Pump/motor command STARBOARD (direction)
// DO3 — Master power enable to actuator (relay)
// DO4 — Audible alarm
// DO5 — "Pilot engaged" console lamp
// DO6..DO10 — Reserved
// -----------------------------------------------------------------------------
#define PIN_DO1_PUMP_PORT 13 // GPIO13
#define PIN_DO2_PUMP_STBD 12 // GPIO12
#define PIN_DO3_ACTUATOR_POWER 15 // GPIO15
#define PIN_DO4_BUZZER 2 // GPIO2 — on-board LED on many boards; check schematic
#define PIN_DO5_ENGAGED_LAMP 4 // GPIO4
#define PIN_DO6_RESERVED 16 // GPIO16
#define PIN_DO7_RESERVED 17 // GPIO17
#define PIN_DO8_RESERVED 5 // GPIO5
#define PIN_DO9_RESERVED 18 // GPIO18
#define PIN_DO10_RESERVED 19 // GPIO19
// -----------------------------------------------------------------------------
// Communication buses (board-level; pins shown for reference, drivers in Sprint 1)
// -----------------------------------------------------------------------------
// RS-485 (Modbus RTU to dedicated display)
#define PIN_RS485_TX 21 // U2_TXD
#define PIN_RS485_RX 22 // U2_RXD
#define PIN_RS485_DE 23 // driver enable
// CAN bus (NMEA 2000 backbone)
#define PIN_CAN_TX 3 // U0_RXD on some boards — verify
#define PIN_CAN_RX 1 // U0_TXD on some boards — verify
// -----------------------------------------------------------------------------
// Control-loop frequencies (logical; consumed by Sprint 2+ PID code)
// -----------------------------------------------------------------------------
#define AR_INNER_LOOP_HZ 50 // rudder position controller
#define AR_OUTER_LOOP_HZ 10 // heading controller
#define AR_RUDDER_SENSOR_SAMPLE_HZ 100 // ADC sample rate for AI1
#define AR_WATCHDOG_TIMEOUT_MS 2000 // brief section 7
// -----------------------------------------------------------------------------
// Safety constants
// -----------------------------------------------------------------------------
#define AR_DEFAULT_MAX_RUDDER_DEG 35 // ± from amidships
#define AR_DEFAULT_MAX_RUDDER_RATE_DPS 6 // degrees/second
#define AR_DEFAULT_OFF_COURSE_DEG 10 // warning threshold
#define AR_SEVERE_OFF_COURSE_DEG 30 // auto-disengage threshold
#define AR_SEVERE_OFF_COURSE_HOLD_MS 5000 // duration before auto-disengage
#define AR_HEADING_SENSOR_TIMEOUT_MS 5000 // auto-disengage if no PGN 127250