version: sunnypilot v2026.002.000 (staging) date: 2026-07-21T07:44:02 master commit: 2c334ede443d7391d27575af8c854a095ba702a8
151 lines
6.4 KiB
Python
151 lines
6.4 KiB
Python
import pytest
|
|
|
|
from opendbc.car.structs import car
|
|
from openpilot.common.constants import CV
|
|
from openpilot.common.parameterized import parameterized_class
|
|
from openpilot.common.params import Params
|
|
from openpilot.selfdrive.car.cruise import V_CRUISE_INITIAL
|
|
from openpilot.selfdrive.car.tests.test_cruise_speed import TestVCruiseHelper
|
|
|
|
ButtonEvent = car.CarState.ButtonEvent
|
|
ButtonType = car.CarState.ButtonEvent.Type
|
|
|
|
|
|
# TODO: test pcmCruise and pcmCruiseSpeed
|
|
@parameterized_class(('pcm_cruise', 'pcm_cruise_speed'), [(False, True)])
|
|
class TestCustomAccIncrements(TestVCruiseHelper):
|
|
def setup_method(self):
|
|
TestVCruiseHelper.setup_method(self)
|
|
self.params = Params()
|
|
self.reset_custom_params()
|
|
|
|
def reset_custom_params(self) -> None:
|
|
"""Reset to default custom ACC parameters"""
|
|
self.params.put_bool("CustomAccIncrementsEnabled", False, block=True)
|
|
self.params.put("CustomAccShortPressIncrement", 1, block=True)
|
|
self.params.put("CustomAccLongPressIncrement", 5, block=True)
|
|
self.v_cruise_helper.read_custom_set_speed_params()
|
|
|
|
def press_button_short(self, button_type: car.CarState.ButtonEvent.Type) -> None:
|
|
"""Simulate a short button press (press + release)"""
|
|
CS = car.CarState(cruiseState={"available": True})
|
|
CS.buttonEvents = [ButtonEvent(type=button_type, pressed=True)]
|
|
self.v_cruise_helper.update_v_cruise(CS, enabled=True, is_metric=True)
|
|
|
|
CS.buttonEvents = [ButtonEvent(type=button_type, pressed=False)]
|
|
self.v_cruise_helper.update_v_cruise(CS, enabled=True, is_metric=True)
|
|
|
|
def press_button_long(self, button_type: car.CarState.ButtonEvent.Type) -> None:
|
|
"""Simulate a long button press (50+ frames)"""
|
|
CS = car.CarState(cruiseState={"available": True})
|
|
CS.buttonEvents = [ButtonEvent(type=button_type, pressed=True)]
|
|
self.v_cruise_helper.update_v_cruise(CS, enabled=True, is_metric=True)
|
|
|
|
# Hold for 50 frames to trigger long press
|
|
CS.buttonEvents = []
|
|
for _ in range(50):
|
|
self.v_cruise_helper.update_v_cruise(CS, enabled=True, is_metric=True)
|
|
|
|
CS.buttonEvents = [ButtonEvent(type=button_type, pressed=False)]
|
|
self.v_cruise_helper.update_v_cruise(CS, enabled=True, is_metric=True)
|
|
|
|
def set_custom_increments(self, enabled: bool, short_inc: int, long_inc: int) -> None:
|
|
"""Set custom ACC increment parameters"""
|
|
self.params.put_bool("CustomAccIncrementsEnabled", enabled, block=True)
|
|
self.params.put("CustomAccShortPressIncrement", short_inc, block=True)
|
|
self.params.put("CustomAccLongPressIncrement", long_inc, block=True)
|
|
self.v_cruise_helper.read_custom_set_speed_params()
|
|
|
|
def test_default_behavior_when_disabled(self):
|
|
"""Test that default increments are used when custom ACC is disabled"""
|
|
self.set_custom_increments(enabled=False, short_inc=5, long_inc=10)
|
|
self.enable(V_CRUISE_INITIAL * CV.KPH_TO_MS, False, False)
|
|
|
|
initial_speed = self.v_cruise_helper.v_cruise_kph
|
|
|
|
# Short press should increment by 1 (default)
|
|
self.press_button_short(ButtonType.accelCruise)
|
|
assert self.v_cruise_helper.v_cruise_kph == initial_speed + 1
|
|
|
|
@pytest.mark.parametrize("increment", (1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
|
|
def test_custom_short_press_increments(self, increment):
|
|
"""Test custom short press increments (1-10)"""
|
|
self.set_custom_increments(enabled=True, short_inc=increment, long_inc=5)
|
|
self.enable(50 * CV.KPH_TO_MS, False, False)
|
|
|
|
initial_speed = self.v_cruise_helper.v_cruise_kph
|
|
self.press_button_short(ButtonType.accelCruise)
|
|
|
|
if increment in (5, 10):
|
|
# Should round to nearest increment
|
|
expected_speed = ((initial_speed // increment) + 1) * increment
|
|
else:
|
|
expected_speed = initial_speed + increment
|
|
|
|
assert self.v_cruise_helper.v_cruise_kph == expected_speed
|
|
|
|
@pytest.mark.parametrize("increment", (1, 5, 10))
|
|
def test_custom_long_press_increments(self, increment):
|
|
"""Test custom long press increments (1, 5, 10)"""
|
|
self.set_custom_increments(enabled=True, short_inc=1, long_inc=increment)
|
|
self.enable(50 * CV.KPH_TO_MS, False, False)
|
|
|
|
initial_speed = self.v_cruise_helper.v_cruise_kph
|
|
self.press_button_long(ButtonType.accelCruise)
|
|
|
|
if increment in (5, 10):
|
|
# Should round to nearest increment
|
|
expected_speed = ((initial_speed // increment) + 1) * increment
|
|
else:
|
|
expected_speed = initial_speed + increment
|
|
|
|
assert self.v_cruise_helper.v_cruise_kph == expected_speed
|
|
|
|
@pytest.mark.parametrize("button_type", [ButtonType.accelCruise, ButtonType.decelCruise])
|
|
def test_accel_decel_symmetry(self, button_type):
|
|
"""Test that acceleration and deceleration work symmetrically"""
|
|
self.set_custom_increments(enabled=True, short_inc=3, long_inc=5)
|
|
self.enable(50 * CV.KPH_TO_MS, False, False)
|
|
|
|
initial_speed = self.v_cruise_helper.v_cruise_kph
|
|
self.press_button_short(button_type)
|
|
|
|
expected_change = 3 if button_type == ButtonType.accelCruise else -3
|
|
assert self.v_cruise_helper.v_cruise_kph == initial_speed + expected_change
|
|
|
|
def test_rounding_behavior(self):
|
|
"""Test rounding behavior for 5 and 10 increments"""
|
|
test_cases = [
|
|
(47, 5, 50), # 47 -> 50 (round up to next 5)
|
|
(45, 5, 50), # 45 -> 50 (already at 5, increment by 5)
|
|
(43, 10, 50), # 43 -> 50 (round up to next 10)
|
|
(40, 10, 50), # 40 -> 50 (already at 10, increment by 10)
|
|
]
|
|
|
|
for initial, increment, expected in test_cases:
|
|
self.set_custom_increments(enabled=True, short_inc=increment, long_inc=increment)
|
|
self.reset_cruise_speed_state()
|
|
self.enable(initial * CV.KPH_TO_MS, False, False)
|
|
|
|
self.press_button_short(ButtonType.accelCruise)
|
|
assert self.v_cruise_helper.v_cruise_kph == expected
|
|
|
|
def test_invalid_values_fallback(self):
|
|
"""Test that invalid values fallback to safe defaults"""
|
|
# Test invalid short increment
|
|
self.set_custom_increments(enabled=True, short_inc=-1, long_inc=5)
|
|
self.enable(50 * CV.KPH_TO_MS, False, False)
|
|
|
|
initial_speed = self.v_cruise_helper.v_cruise_kph
|
|
self.press_button_short(ButtonType.accelCruise)
|
|
assert self.v_cruise_helper.v_cruise_kph == initial_speed + 1 # Should fallback to 1
|
|
|
|
# Test invalid long increment
|
|
self.reset_cruise_speed_state()
|
|
self.set_custom_increments(enabled=True, short_inc=1, long_inc=99)
|
|
self.enable(50 * CV.KPH_TO_MS, False, False)
|
|
|
|
initial_speed = self.v_cruise_helper.v_cruise_kph
|
|
self.press_button_long(ButtonType.accelCruise)
|
|
assert self.v_cruise_helper.v_cruise_kph == initial_speed + 10 # Should fallback to 10
|