Files
AR-Autopilot/arautopilot/core/vessel_config.py
T
alro65 e4812e9b44 sprint-4: Project Editor + .appack compiler + IRudderActuator HAL + dual sensor config
Cherry-pick of ab28cb7 onto main (was missing from main branch history).

Python:
- arautopilot/core/sensor_config.py: RudderSensorConfig + DualRudderSensorConfig
  (AS5048A SPI / potentiometer, dual with cross-validation thresholds)
- arautopilot/core/vessel_config.py: add sensors: DualRudderSensorConfig field
- arautopilot/studio/compiler/appack.py: .appack compiler (ZIP with
  manifest.json + project.yaml + firmware_config.h + install_notes.txt)
- arautopilot/studio/editors/project_editor.py: full project config editor
  (vessel / actuator / sensors / PID, RBAC-gated fields, save/load .yaml/.json)
- arautopilot/studio/main_window.py: wire ProjectEditorWidget into Project tab
- tests: test_sensor_config.py (11 tests) + test_appack_compiler.py (10 tests)

Firmware:
- hal/rudder_actuator_iface.h: IRudderActuator abstract interface
- hal/rudder_actuator_hydraulic.h: reversible hydraulic pump (LEDC PWM)
- hal/rudder_actuator_electric.h: reversible DC motor + deadband compensation
- hal/rudder_actuator_factory.h: build-time type selection via AR_ACTUATOR_TYPE

Tests: 483 passed (was 462, +21 Sprint 4)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 10:29:17 -04:00

74 lines
2.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""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 StrEnum
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
from arautopilot.core.sensor_config import DualRudderSensorConfig, RudderSensorConfig, RudderSensorType
class VesselType(StrEnum):
"""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
sensors: DualRudderSensorConfig = Field(
default_factory=lambda: DualRudderSensorConfig(
primary=RudderSensorConfig(
type=RudderSensorType.AS5048A_SPI,
label="Primary rudder stock",
spi_cs_gpio=10,
)
),
description="Rudder angle sensor(s). Dual config enables cross-validation and failover.",
)