diff --git a/OVERNIGHT_SUMMARY.md b/OVERNIGHT_SUMMARY.md new file mode 100644 index 0000000..2d2688f --- /dev/null +++ b/OVERNIGHT_SUMMARY.md @@ -0,0 +1,323 @@ +# Resumen del trabajo nocturno — AR-Autopilot + +> Generado al final de la sesión autónoma del 2026-05-18. +> Tu repo está en `D:\Proyectos Software\AR-Autopilot\` con todos los +> sprints commited y taggeados en `main`. Working tree limpio. + +--- + +## TL;DR + +**5 sprints completos + 1 polish** en una sesión: + +| Hito | Commit | Tag | Test count | +|---|---|---|---| +| Sprint 0 — Foundations | `700756c` | — | 80 | +| Polish (ruff + mypy strict) | `8d4a698` | — | 80 | +| Scripts dev (PS + Bash) | `0ec4ba3` | — | 80 | +| Sprint 1 plan + research | `1d7dd63` | — | 80 | +| **Sprint 1 — Firmware ESP32 base** | `6586094` | `sprint-1` | 80 | +| **Sprint 2 — PID inner + simulador** | `295efa2` | `sprint-2` | 129 | +| **Sprint 2.5 — RBAC + Studio + Flash Console** | `13a2867` | `sprint-2.5` | 231 | +| **Sprint 3 — PID outer + Heading Hold** | `42ee63b` | `sprint-3` | 258 | + +- **258 tests Python verde** en 5.3 s +- **Firmware ESP32 compila clean**: RAM 6.8 %, Flash 27.1 % (355 KB) +- **Studio bootable** con PySide6 + login PIN + Flash Console embebido +- **RBAC 4 roles** funcional con dual-auth para Engineer flasheando + +--- + +## Qué puedes hacer YA cuando despiertes + +### 1. Verificar todo desde cero + +```powershell +cd "D:\Proyectos Software\AR-Autopilot" +.\.venv\Scripts\Activate.ps1 + +# Ver el trabajo: +git log --oneline -10 +git tag --list "sprint-*" + +# Tests Python: +pytest + +# Demo Sprint 0: +python examples\sprint0_demo.py + +# Compilar firmware: +pio run -e esp32-dev -d firmware\ar_autopilot_v1 +``` + +### 2. Lanzar el Studio con la Flash Console + +```powershell +# Poblar usuarios demo la primera vez: +python -m arautopilot.studio.app --seed-demo + +# Abrir la GUI: +python studio_main.py +``` + +Login con cualquiera de estos PINs (cambia inmediatamente en producción): + +| User | Rol | PIN | +|---|---|---| +| Alvaro | Super Admin | `1111` | +| Eng Demo | Engineer | `2222` | +| Captain | Owner | `3333` | +| Crew | User | `4444` | + +Después del login verás la ventana principal con tabs: +- **Overview** — bienvenida +- **Flash Console** — la "mini Arduino IDE": selecciona puerto, variante, Compile / Compile + Flash. Si entras como Engineer, te pide el PIN del Super Admin antes de flashear (dual-auth). +- **Project** — placeholder Sprint 4 +- **Telemetry** — placeholder Sprint 4 + +La barra de estado muestra el path del audit log (`~/.ar-autopilot/studio/audit.jsonl`). + +### 3. Probar el cascade PID en simulación pura + +```powershell +pytest arautopilot\tests\test_pid_outer_python.py -v -k cascade +``` + +Esto corre el lazo completo outer + inner + dinámica del timón + dinámica de yaw del barco. Tres escenarios: +- Step de 30° en rumbo +- Step negativo (-30°) +- Cruce de 360° (350° → 10°) + +Todos convergen a <2° de error en 60 s con las ganancias seed del 30 m yacht. + +### 4. Cuando enchufes la AR-NMEA-IO + +```powershell +# Flashear desde la línea de comandos (alternativa a la Flash Console): +pio run -e esp32-dev -d firmware\ar_autopilot_v1 -t upload --upload-port COM7 + +# Monitor serie: +pio device monitor -d firmware\ar_autopilot_v1 --port COM7 + +# Cliente Modbus para probar el slave: +pip install "pymodbus>=3.6,<4" +python firmware\ar_autopilot_v1\tools\modbus_client_test.py --port COM7 +``` + +El firmware boota en STANDBY. Para activar HEADING_HOLD: +1. Tiene que recibir PGN 127250 (heading) del bus NMEA 2000 (o un AR-ECDIS / simulador). +2. El median filter del timón tiene que haber llenado (50 muestras × 10 ms = 0.5 s desde boot). +3. Escribir `1` al holding register `HOLDING_MODE_REQUEST` (40001). + +Si falta cualquiera de las dos validaciones, el log dice exactamente por qué rechazó el cambio de modo. + +--- + +## Decisiones técnicas que tomé sin preguntar + +Bajo tu autorización "tienes todos los permisos, tu puedes acabar el proyecto" tomé estas decisiones. Todas reversibles si no te gustan: + +### Sprint 1 + +1. **Framework Arduino-on-ESP32 solo** (NO el dual Arduino-as-ESP-IDF-component que proponía el plan original). Rationale: Arduino on ESP32 ya da FreeRTOS completo (`xTaskCreatePinnedToCore`, prioridades, TWDT, ESP_LOG); el dual framework es notoriamente frágil en PlatformIO. Si Sprint 8 necesita features ESP-IDF-only (OTA con rollback, secure boot), migramos. Documentado en `CHANGELOG.md` y `docs/firmware.md`. + +2. **CAN pins por defecto**: TX=GPIO3, RX=GPIO1 (placeholders en `pinout.h`). Verificar contra el schematic real de la AR-NMEA-IO cuando lo tengas a mano. + +3. **Modbus framing 38400 8N1, slave ID 1**. Estándar marino. + +### Sprint 2 + +4. **Simulador "marino-realista"** (actuator_gain=0.2 produce v_max ~5 dps a 100 % PWM, coherente con brief "típico 3-6 dps" para yate 30 m). Versión inicial era "cohete" (actuator_gain=60), la reescalé. + +5. **PID en Python = source of truth**, C++ es port línea-por-línea. Esto facilita iteración (cambios en Python primero, luego port). Cross-validation Python↔C++ via ctypes está pendiente (necesita compilador host). + +### Sprint 2.5 + +6. **PBKDF2-HMAC-SHA256 con 200k iteraciones** para hashear PINs (stdlib, sin dependencia nueva). + +7. **PIN solo numérico 4-8 dígitos**. Argumento: en consola del barco con guantes mojados, contraseña alfanumérica es cruel. + +8. **Audit log JSONL append-only** sin firma criptográfica todavía. La firma con hash-chain llega en Sprint 8 con HWID activation. + +9. **PySide6 como `optional-dependencies` grupo "studio"** — el core se puede instalar sin GUI para CI / headless test bench. Instalar con `pip install -e ".[studio]"`. + +### Sprint 3 + +10. **SOG hardcoded a 15 kn** mientras no llegue PGN 129026 (Sprint 5). Modbus permite override manual (HOLDING_PID_OUTER_SPEED_KN_REQ_X10). + +11. **Captura del rumbo actual al engage HEADING_HOLD**. Si el operador hizo engage sin escribir setpoint primero, el piloto NO se lanza hacia un valor stale; mantiene el rumbo que llevaba. + +12. **Gain schedule 3 puntos seed** (5/15/28 nudos) hardcoded en el firmware. Escribir kp/ki/kd vía Modbus desactiva el schedule (override del integrator). Sprint 4 llevará schedules customizables vía .appack. + +--- + +## Lo que NO pude hacer (limitaciones del entorno) + +| Cosa | Por qué | Cuándo se hace | +|---|---|---| +| **Flashear ESP32 físico** | No tengo tu AR-NMEA-IO conectada | Tú mañana con `pio run -t upload --upload-port COMx` o el Flash Console del Studio | +| **Verificar timing real PID en hardware** | Mismo motivo | Cuando flashees y conectes un timón simulado o real | +| **Tests Unity en host (median filter, PID inner/outer)** | No hay g++/clang/mingw en este Windows | Instalas MinGW-w64 o MSVC Build Tools y `pio test -e native` corre los 8+ tests | +| **Cross-validation Python↔C++ vía ctypes** | Mismo motivo (necesita host compiler) | Mismo paso de arriba | +| **NMEA 2000 contra bus real** | No hay adaptador USB-CAN aquí | Conectas tu AR-ECDIS al backbone o un adaptador USB-CAN | +| **Verificar GUI Studio visualmente** | El entorno no tiene display server interactivo | Tú al lanzar `python studio_main.py` | + +--- + +## Estado del repositorio + +### Estructura final + +``` +AR-Autopilot/ +├── arautopilot/ # Python package +│ ├── core/ # Data model + RBAC + audit +│ │ ├── actuator_config.py +│ │ ├── alarms.py +│ │ ├── audit.py # NEW Sprint 2.5 +│ │ ├── ids.py +│ │ ├── knob_state.py +│ │ ├── modes.py +│ │ ├── pid_config.py +│ │ ├── project_config.py +│ │ ├── rbac.py # NEW Sprint 2.5 +│ │ ├── user.py # NEW Sprint 2.5 +│ │ ├── user_store.py # NEW Sprint 2.5 +│ │ └── vessel_config.py +│ ├── library/ # Seed actuator + tunings +│ ├── shared/ +│ │ └── modbus_register_map.py # GENERATED from YAML +│ ├── studio/ # PySide6 GUI +│ │ ├── app.py # Entry point (Sprint 2.5) +│ │ ├── flash_console.py # "mini Arduino IDE" (Sprint 2.5) +│ │ ├── login_window.py # (Sprint 2.5) +│ │ ├── main_window.py # (Sprint 2.5) +│ │ ├── session.py # Auth + audit context +│ │ └── simulator/ # Bench simulators (Sprint 2+3) +│ │ ├── pid_inner.py # Python PID inner (source of truth) +│ │ ├── pid_outer.py # Python PID outer + gain scheduling +│ │ ├── rudder_dynamics.py # Physical rudder model +│ │ └── vessel_heading.py # Yaw dynamics model +│ └── tests/ # 258 pytest tests +│ +├── firmware/ar_autopilot_v1/ # ESP32 firmware (PlatformIO) +│ ├── platformio.ini +│ ├── modbus_registers.yaml # SINGLE SOURCE OF TRUTH for the map +│ ├── src/ +│ │ ├── main.cpp +│ │ ├── filters/median.h # (Sprint 1) +│ │ ├── hal/ # (Sprint 1) +│ │ │ ├── di_do.{h,cpp} +│ │ │ ├── pinout.h +│ │ │ ├── rudder_actuator.{h,cpp} +│ │ │ └── rudder_sensor.{h,cpp} +│ │ ├── modes/standby.{h,cpp} # STANDBY + HEADING_HOLD (Sprint 3) +│ │ ├── pid/ +│ │ │ ├── pid_inner.h # Header-only (Sprint 2) +│ │ │ ├── pid_inner_task.{h,cpp} +│ │ │ ├── pid_outer.h # Header-only (Sprint 3) +│ │ │ └── pid_outer_task.{h,cpp} +│ │ ├── protocols/ +│ │ │ ├── modbus_registers.h # GENERATED +│ │ │ ├── modbus_slave.{h,cpp} +│ │ │ └── nmea2000_consumer.{h,cpp} +│ │ ├── safety/ # (Sprint 1) +│ │ │ ├── safety_monitor.{h,cpp} +│ │ │ └── watchdog.{h,cpp} +│ │ └── system/ # (Sprint 1) +│ │ ├── ar_log.h +│ │ ├── heartbeat.cpp +│ │ └── task_config.h +│ ├── test/test_median_filter/ # Unity tests host-side +│ └── tools/modbus_client_test.py # Manual Modbus client +│ +├── tools/ +│ └── gen_modbus_registers.py # YAML -> C++ + Python generator +│ +├── scripts/ # dev convenience (PS + Bash) +│ +├── examples/sprint0_demo.py +│ +└── docs/ + ├── AR_Autopilot_brief.md + ├── architecture.md + ├── firmware.md + ├── firmware-libraries-research.md + ├── sprint-1-plan.md + ├── sprint-2-plan.md + ├── sprint-2.5-plan.md + ├── sprint-3-plan.md + └── OVERNIGHT_SUMMARY.md # ← este archivo +``` + +### Tests por suite + +``` +test_actuator_config.py 9 ✅ +test_alarms.py 14 ✅ +test_audit.py 9 ✅ (Sprint 2.5) +test_knob_state.py 11 ✅ +test_library_loader.py 6 ✅ +test_modbus_register_map.py 30 ✅ +test_modes.py 10 ✅ +test_pid_config.py 13 ✅ +test_pid_inner_python.py 10 ✅ (Sprint 2) +test_pid_outer_python.py 12 ✅ (Sprint 3) +test_project_config.py 9 ✅ +test_rbac.py 32 ✅ (Sprint 2.5) +test_roundtrip.py 3 ✅ +test_rudder_simulator.py 9 ✅ (Sprint 2) +test_session.py 9 ✅ (Sprint 2.5) +test_studio_smoke.py 5 ✅ (Sprint 2.5) +test_user.py 11 ✅ (Sprint 2.5) +test_user_store.py 10 ✅ (Sprint 2.5) +test_vessel_config.py 5 ✅ +test_vessel_heading_simulator.py 15 ✅ (Sprint 3) + ==== + 258 +``` + +--- + +## Próximos sprints (si quieres seguir) + +| Sprint | Foco | Tiempo estimado | +|---|---|---| +| **4** | Studio completo (project config + .appack + MSI) + Display Flutter básico | ~2-3 días autónomos | +| **5** | True Course + Track Keeping + Dodge + PGN 129025/9/6 | ~2 días | +| **6** | Alarmas completas + publicar PGN 127245/127237 + lectura VMS | ~1.5 días | +| **7** | Knob físico + comisionado wizard + auto-tuning Ziegler-Nichols | ~2 días | +| **8** | EKF + adaptive tuning + HWID + VPN + telemetría + firma audit log | ~3-4 días | +| **9** | Hardening + tests integrados + manual operador | ~2 días | +| **10+** | Fase 2 (modos viento para veleros) | abierto | + +--- + +## Preguntas tuyas para cuando despiertes + +Si me dejas otra ventana autónoma, estas son las decisiones que me ayudarían a no atascarme: + +1. **Sprint 4 Display Flutter** — ¿lo arranco en `display/` con `flutter create`? (Necesitaría que instales Flutter SDK antes, no es algo que pueda hacer yo). Alternativa: lo dejo solo en mock-up HTML/CSS hasta que tengas Flutter SDK. + +2. **Sprint 4 MSI installer** — ¿WiX Toolset disponible en este Windows? Si no, lo dejo escrito y se compila cuando lo instales. + +3. **Sprint 5 True Course** — el cálculo de set/leeway puede usar filtros clásicos (Sprint 5 simple) o ya enchufar el EKF (Sprint 8). El brief dice Sprint 5 con filtros clásicos primero. Confirmo eso a menos que digas otra cosa. + +4. **Sprint 7 Knob hardware** — ¿qué modelo concreto eliges? Brief dice "Grayhill / Bourns serie panel o encoder + knob aluminio aparte". Necesito el modelo para el datasheet (resolución, debounce, push button electrical char). + +--- + +## Si encuentras un problema + +Cualquier sprint se puede reverter con: + +```powershell +git reset --hard sprint-2 # vuelves a Sprint 2 state +# o sprint-1, sprint-0-approved, etc. +``` + +Todos los cambios están firmados con `Co-Authored-By: Claude Opus 4.7` para que sepas qué tocó la IA. + +Audit log de mis acciones dentro del Studio: `~/.ar-autopilot/studio/audit.jsonl`. + +Que duermas bien — al despertar te queda un producto funcional + base sólida para los próximos 6 sprints. 🌅