Files
AR-Autopilot/arautopilot/core/vessel_config.py
T
alro65 700756c16f 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>
2026-05-17 23:57:18 -04:00

63 lines
1.8 KiB
Python

"""Per-vessel configuration: identification + actuator + PID.
Composes the lower-level configs into one object that lives at the heart
of every ``ProjectConfig``.
"""
from __future__ import annotations
from enum import Enum
from pydantic import BaseModel, ConfigDict, Field
from arautopilot.core.actuator_config import ActuatorConfig
from arautopilot.core.ids import VesselId, new_vessel_id
from arautopilot.core.pid_config import PidConfig
class VesselType(str, Enum):
"""Vessel classes targeted by Phase 1 of the product (brief section 3)."""
YACHT_MOTOR_PLANEO = "yacht_motor_planeo"
"""Planing motor yacht, 30-40 m."""
YACHT_MOTOR_DESPLAZAMIENTO = "yacht_motor_desplazamiento"
"""Displacement motor yacht, 30-40 m."""
SAILBOAT_MOTOR = "sailboat_motor"
"""Sailing yacht under motor (no sail trim). Phase 1 only."""
FISHING_BOAT = "fishing_boat"
"""Fishing vessel, 30 m class."""
SMALL_FERRY = "small_ferry"
"""Small ferry, 30 m class."""
PATROL_BOAT = "patrol_boat"
"""Coastal patrol boat, 30 m class."""
class VesselConfig(BaseModel):
"""Identification, geometry, and control configuration of one vessel."""
model_config = ConfigDict(extra="forbid", validate_assignment=True)
vessel_id: VesselId = Field(default_factory=new_vessel_id)
name: str = Field(min_length=1, max_length=120)
type: VesselType
length_m: float = Field(gt=0.0, le=200.0, description="Length overall, metres.")
displacement_t: float = Field(
default=0.0,
ge=0.0,
le=10_000.0,
description="Loaded displacement, tonnes. 0 means unknown.",
)
max_speed_kn: float = Field(
gt=0.0,
le=80.0,
description="Maximum design speed over ground, knots.",
)
actuator: ActuatorConfig
pid: PidConfig