""" Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. This file is part of sunnypilot and is licensed under the MIT License. See the LICENSE.md file in the root directory for more details. """ import numpy as np import unittest from opendbc.safety.tests.common import CANPackerSafety, CarSafetyTest class GasInterceptorSafetyTest(CarSafetyTest): INTERCEPTOR_THRESHOLD = 0 cnt_gas_cmd = 0 cnt_user_gas = 0 packer: CANPackerSafety @classmethod def setUpClass(cls): if cls.__name__ == "GasInterceptorSafetyTest" or cls.__name__.endswith("Base"): cls.safety = None raise unittest.SkipTest def _interceptor_gas_cmd(self, gas: int): values: dict[str, float | int] = {"PEDAL_COUNTER": self.__class__.cnt_gas_cmd & 0xF} if gas > 0: values["GAS_COMMAND"] = gas * 255. values["GAS_COMMAND2"] = gas * 255. self.__class__.cnt_gas_cmd += 1 return self.packer.make_can_msg_safety("GAS_COMMAND", 0, values) def _interceptor_user_gas(self, gas: int): values = {"INTERCEPTOR_GAS": gas, "INTERCEPTOR_GAS2": gas, "PEDAL_COUNTER": self.__class__.cnt_user_gas} self.__class__.cnt_user_gas += 1 return self.packer.make_can_msg_safety("GAS_SENSOR", 0, values) # Skip non-interceptor user gas tests def test_prev_gas(self): pass def test_no_disengage_on_gas(self): pass def test_prev_gas_interceptor(self): self._rx(self._interceptor_user_gas(0x0)) self.assertFalse(self.safety.get_gas_interceptor_prev()) self._rx(self._interceptor_user_gas(0x1000)) self.assertTrue(self.safety.get_gas_interceptor_prev()) self._rx(self._interceptor_user_gas(0x0)) def test_no_disengage_on_gas_interceptor(self): self.safety.set_controls_allowed(True) for g in range(0x1000): self._rx(self._interceptor_user_gas(g)) # Test we allow lateral, but not longitudinal self.assertTrue(self.safety.get_controls_allowed()) self.assertEqual(g <= self.INTERCEPTOR_THRESHOLD, self.safety.get_longitudinal_allowed()) # Make sure we can re-gain longitudinal actuation self._rx(self._interceptor_user_gas(0)) self.assertTrue(self.safety.get_longitudinal_allowed()) def test_allow_engage_with_gas_interceptor_pressed(self): self._rx(self._interceptor_user_gas(0x1000)) self.safety.set_controls_allowed(True) self._rx(self._interceptor_user_gas(0x1000)) self.assertTrue(self.safety.get_controls_allowed()) self._rx(self._interceptor_user_gas(0)) def test_gas_interceptor_safety_check(self): for gas in np.arange(0, 4000, 100): for controls_allowed in [True, False]: self.safety.set_controls_allowed(controls_allowed) if controls_allowed: send = True else: send = gas == 0 self.assertEqual(send, self._tx(self._interceptor_gas_cmd(gas)))