From 2a528414ed142f7a24576d7c6c92fa2cc1fe5f51 Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Tue, 22 Sep 2026 16:44:12 -0500 Subject: [PATCH] Ray Pedal Path --- .../opendbc/car/hyundai/carcontroller.py | 2 +- opendbc_repo/opendbc/car/hyundai/interface.py | 2 +- .../car/hyundai/tests/test_ray_pedal.py | 35 +++++++++++++++++-- .../safety/tests/test_hyundai_ray_pedal.py | 31 ++++++++++++++++ 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/opendbc_repo/opendbc/car/hyundai/carcontroller.py b/opendbc_repo/opendbc/car/hyundai/carcontroller.py index a95c0bec32..0879b8b0a0 100644 --- a/opendbc_repo/opendbc/car/hyundai/carcontroller.py +++ b/opendbc_repo/opendbc/car/hyundai/carcontroller.py @@ -830,7 +830,7 @@ class CarController(CarControllerBase): pedal_ready = CS.ray_pedal_valid and CS.ray_pedal_state == 0 pedal_active = (CC.longActive and pedal_ready and not CC.cruiseControl.override and not CS.out.gasPressed and not CS.out.brakePressed and - not CS.out.cruiseState.enabled and CS.out.vEgo >= self.CP.minEnableSpeed) + not CS.out.cruiseState.enabled) if pedal_active: target = float(np.clip(accel / CarControllerParams.ACCEL_MAX * RAY_PEDAL_COMMAND_CAP, 0.0, RAY_PEDAL_COMMAND_CAP)) diff --git a/opendbc_repo/opendbc/car/hyundai/interface.py b/opendbc_repo/opendbc/car/hyundai/interface.py index 1600681912..4e7d08db5c 100644 --- a/opendbc_repo/opendbc/car/hyundai/interface.py +++ b/opendbc_repo/opendbc/car/hyundai/interface.py @@ -313,7 +313,7 @@ class CarInterface(CarInterfaceBase): ret.pcmCruise = False ret.radarUnavailable = True ret.autoResumeSng = False - ret.minEnableSpeed = 5.0 # pedal-only: no commanded friction brake/standstill hold + ret.minEnableSpeed = -1.0 ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.LONG.value # Car specific configuration overrides diff --git a/opendbc_repo/opendbc/car/hyundai/tests/test_ray_pedal.py b/opendbc_repo/opendbc/car/hyundai/tests/test_ray_pedal.py index d6fd9f0b98..4fc6c7fea0 100644 --- a/opendbc_repo/opendbc/car/hyundai/tests/test_ray_pedal.py +++ b/opendbc_repo/opendbc/car/hyundai/tests/test_ray_pedal.py @@ -32,7 +32,7 @@ def test_ray_pedal_fingerprint_isolation(candidate, fingerprint, has_pedal): if has_pedal: assert not CP.pcmCruise assert CP.safetyConfigs[-1].safetyParam == 0x9405 - assert CP.minEnableSpeed == 5.0 + assert CP.minEnableSpeed == -1.0 assert not CP.autoResumeSng FPCP = CarInterface.get_starpilot_params(candidate, fingerprint, [], CP, SimpleNamespace()) assert FPCP.canUsePedal @@ -128,13 +128,14 @@ def test_ray_without_pedal_keeps_native_gas_detection(): assert ret.gasPressed -def test_ray_controller_heartbeats_and_only_actuates_when_ready(): +@pytest.mark.parametrize("speed", [0.0, 0.1, 1.0, 4.9, 5.0, 12.0]) +def test_ray_controller_heartbeats_and_only_actuates_when_ready(speed): CP = CarInterface.get_params(CAR.KIA_RAY_EV, ray_fingerprint(), [], False, False, False, None) controller = CarController(DBC[CP.carFingerprint], CP) parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("LKAS11", 0), ("CLU11", 0)], 0) CS = SimpleNamespace( lkas11=parser.vl["LKAS11"], clu11=parser.vl["CLU11"], - out=SimpleNamespace(vEgo=12.0, gasPressed=False, brakePressed=False, + out=SimpleNamespace(vEgo=speed, gasPressed=False, brakePressed=False, cruiseState=SimpleNamespace(enabled=False)), ray_pedal_valid=True, ray_pedal_state=5, is_metric=True, ) @@ -169,6 +170,34 @@ def test_ray_controller_heartbeats_and_only_actuates_when_ready(): assert next(dat for addr, dat, bus in messages if addr == 0x200 and bus == 0)[:4] == bytes(4) assert any(addr == 0x4F1 and bus == 0 for addr, _, bus in messages) # cancel stock CC + CS.out.cruiseState.enabled = False + CS.out.brakePressed = True + assert pedal_msg(2.0, 20)[:4] == bytes(4) + CS.out.brakePressed = False + assert pedal_msg(2.0, 24)[4] & 0x80 + assert controller._ray_pedal_gas_last == pytest.approx(0.012) + assert pedal_msg(2.0, 28)[4] & 0x80 + assert controller._ray_pedal_gas_last == pytest.approx(0.024) + CS.out.brakePressed = True + assert pedal_msg(2.0, 32)[:4] == bytes(4) + assert controller._ray_pedal_gas_last == 0.0 + CS.out.brakePressed = False + assert pedal_msg(2.0, 36)[4] & 0x80 + assert controller._ray_pedal_gas_last == pytest.approx(0.012) + + CC.longActive = False + assert pedal_msg(2.0, 40)[:4] == bytes(4) + CC.longActive = True + CC.cruiseControl.override = True + assert pedal_msg(2.0, 44)[:4] == bytes(4) + CC.cruiseControl.override = False + CS.ray_pedal_valid = False + assert pedal_msg(2.0, 48)[:4] == bytes(4) + CS.ray_pedal_valid = True + for fault in range(1, 6): + CS.ray_pedal_state = fault + assert pedal_msg(2.0, 48 + 4 * fault)[:4] == bytes(4) + @pytest.mark.parametrize("candidate", [CAR.KIA_RAY_EV, CAR.HYUNDAI_KONA_EV_NON_SCC]) def test_ray_stock_cruise_cancellation_survives_accelerator_override(candidate): diff --git a/opendbc_repo/opendbc/safety/tests/test_hyundai_ray_pedal.py b/opendbc_repo/opendbc/safety/tests/test_hyundai_ray_pedal.py index 005c0da4d7..111045686c 100644 --- a/opendbc_repo/opendbc/safety/tests/test_hyundai_ray_pedal.py +++ b/opendbc_repo/opendbc/safety/tests/test_hyundai_ray_pedal.py @@ -4,6 +4,7 @@ from opendbc.can import CANPacker from opendbc.car import create_gas_interceptor_command from opendbc.car.structs import CarParams from opendbc.safety.tests.libsafety import libsafety_py +from opendbc.safety.tests.test_hyundai import checksum @pytest.mark.parametrize("param", [0x9405, 0x9C05, 0x9401, 0x1005, 0]) @@ -98,3 +99,33 @@ def test_ray_native_cruise_cancel_allowed_during_pedal_override(controls_allowed pedal_packer = CANPacker("hyundai_kia_ray_pedal") addr, dat, bus = create_gas_interceptor_command(pedal_packer, 0.1, 3) assert not safety.safety_tx_hook(libsafety_py.make_CANPacket(addr, bus, dat)) + + +def test_ray_standstill_launch_obeys_hardware_brake_override(): + safety = libsafety_py.libsafety + safety.set_safety_hooks(CarParams.SafetyModel.hyundai, 0x9405) + safety.init_tests() + packer = CANPacker("hyundai_can_refresh_generated") + pedal_packer = CANPacker("hyundai_kia_ray_pedal") + + def rx(name, values): + addr, dat, bus = checksum(packer.make_can_msg(name, 0, values)) + assert safety.safety_rx_hook(libsafety_py.make_CANPacket(addr, bus, dat)) + + def tx(gas): + addr, dat, bus = create_gas_interceptor_command(pedal_packer, gas, 0) + return safety.safety_tx_hook(libsafety_py.make_CANPacket(addr, bus, dat)) + + rx("WHL_SPD11", {"WHL_SPD_FL": 0, "WHL_SPD_RR": 0}) + assert not safety.get_vehicle_moving() + rx("TCS13", {"DriverOverride": 2}) + safety.set_controls_allowed(True) + assert safety.get_brake_pressed_prev() + assert tx(0) + assert not tx(0.012) + rx("TCS13", {"DriverOverride": 0}) + assert not safety.get_brake_pressed_prev() + assert tx(0.012) + rx("TCS13", {"DriverOverride": 2}) + assert not tx(0.012) + assert tx(0)