"""Tests for ``arautopilot.core.actuator_config``.""" from __future__ import annotations import pytest from pydantic import ValidationError from arautopilot.core.actuator_config import ( ActuatorConfig, ActuatorType, is_phase_1, ) def test_defaults_load_without_error() -> None: cfg = ActuatorConfig(type=ActuatorType.HYDRAULIC_REVERSIBLE) assert cfg.type is ActuatorType.HYDRAULIC_REVERSIBLE assert 0 < cfg.deadband_pct < 30 assert cfg.max_rudder_angle_deg <= 45 assert cfg.feedback_required is True def test_phase_1_actuators_are_drivable() -> None: for t in ( ActuatorType.HYDRAULIC_REVERSIBLE, ActuatorType.ELECTRIC_DC_REVERSIBLE, ActuatorType.SERVOMOTOR_FEEDBACK, ActuatorType.STERNDRIVE_ANALOG, ): assert is_phase_1(t) is True cfg = ActuatorConfig(type=t) assert cfg.is_phase_1_supported() is True @pytest.mark.parametrize("t", [ActuatorType.VOLVO_IPS, ActuatorType.MERCURY_ZEUS]) def test_phase_3_actuators_are_modelled_but_not_phase_1(t: ActuatorType) -> None: assert is_phase_1(t) is False cfg = ActuatorConfig(type=t) assert cfg.is_phase_1_supported() is False def test_rejects_max_angle_above_45() -> None: with pytest.raises(ValidationError): ActuatorConfig(type=ActuatorType.HYDRAULIC_REVERSIBLE, max_rudder_angle_deg=50.0) def test_rejects_negative_max_rate() -> None: with pytest.raises(ValidationError): ActuatorConfig(type=ActuatorType.HYDRAULIC_REVERSIBLE, max_rate_dps=-1.0) def test_min_useful_pwm_must_cover_deadband() -> None: """If the actuator needs >5 % to overcome static friction, the min useful PWM cannot be below the deadband — that combination would tell the controller 'commands above 5 % move the rudder' while also 'commands below 8 % do nothing', which is internally inconsistent.""" with pytest.raises(ValidationError): ActuatorConfig( type=ActuatorType.HYDRAULIC_REVERSIBLE, deadband_pct=8.0, min_useful_pwm_pct=5.0, ) def test_rejects_unknown_field() -> None: with pytest.raises(ValidationError): ActuatorConfig(type=ActuatorType.HYDRAULIC_REVERSIBLE, unknown=True) # type: ignore[call-arg] def test_asymmetry_bounds() -> None: with pytest.raises(ValidationError): ActuatorConfig( type=ActuatorType.HYDRAULIC_REVERSIBLE, asymmetry_stbd_over_port=0.1, ) with pytest.raises(ValidationError): ActuatorConfig( type=ActuatorType.HYDRAULIC_REVERSIBLE, asymmetry_stbd_over_port=5.0, )