Skip to content

Commit

Permalink
safety tests: clean up measurement tests (commaai#1694)
Browse files Browse the repository at this point in the history
* hmm this works

* hyundai fix in another pr

* support testing integer torque

cmt

* there we go

* Revert "there we go"

This reverts commit 6c5a19a.

* Revert "support testing integer torque"

This reverts commit 2c38107.

* clean up

* Update tests/safety/common.py
  • Loading branch information
sshane authored Oct 24, 2023
1 parent 229107f commit 331829b
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 39 deletions.
69 changes: 32 additions & 37 deletions tests/safety/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,22 @@ def _generic_limit_safety_check(self, msg_function: MessageFunction, min_allowed
should_tx = (should_tx or v == inactive_value) and msg_allowed
self.assertEqual(self._tx(msg_function(v)), should_tx, (controls_allowed, should_tx, v))

def _common_measurement_test(self, msg_func: Callable, min_value: float, max_value: float, factor: int,
meas_min_func: Callable[[], int], meas_max_func: Callable[[], int]):
"""Tests accurate measurement parsing, and that the struct is reset on safety mode init"""
for val in np.arange(min_value, max_value, 0.5):
for i in range(MAX_SAMPLE_VALS):
self.assertTrue(self._rx(msg_func(val + i * 0.1)))

# assert close by one decimal place
self.assertAlmostEqual(meas_min_func() / factor, val, delta=0.1)
self.assertAlmostEqual(meas_max_func() / factor - 0.5, val, delta=0.1)

# ensure sample_t is reset on safety init
self._reset_safety_hooks()
self.assertEqual(meas_min_func(), 0)
self.assertEqual(meas_max_func(), 0)


class InterceptorSafetyTest(PandaSafetyTestBase):

Expand Down Expand Up @@ -620,45 +636,10 @@ def test_reset_torque_measurements(self):
self.assertEqual(self.safety.get_torque_meas_min(), 0)
self.assertEqual(self.safety.get_torque_meas_max(), 0)

class MeasurementSafetyTest(PandaSafetyTestBase):
DEG_TO_CAN: float = 1

@classmethod
def setUpClass(cls):
if cls.__name__ == "MeasurementSafetyTest":
cls.safety = None
raise unittest.SkipTest

@abc.abstractmethod
def _angle_meas_msg(self, angle: float):
pass

@abc.abstractmethod
def _speed_msg(self, speed):
pass
class AngleSteeringSafetyTest(PandaSafetyTestBase):

def common_measurement_test(self, msg_func, min_value, max_value, factor, get_min_func, get_max_func):
for val in np.arange(min_value, max_value, 0.5):
for i in range(MAX_SAMPLE_VALS):
self.assertTrue(self._rx(msg_func(val + i * 0.1)))

# assert close by one decimal place
self.assertAlmostEqual(get_min_func() / factor, val, delta=0.1)
self.assertAlmostEqual(get_max_func() / factor - 0.5, val, delta=0.1)

# ensure sample_t is reset on safety init
self._reset_safety_hooks()
self.assertEqual(get_min_func(), 0)
self.assertEqual(get_max_func(), 0)

def test_vehicle_speed_measurements(self):
self.common_measurement_test(self._speed_msg, 0, 80, VEHICLE_SPEED_FACTOR, self.safety.get_vehicle_speed_min, self.safety.get_vehicle_speed_max)

def test_steering_angle_measurements(self):
self.common_measurement_test(self._angle_meas_msg, -180, 180, self.DEG_TO_CAN, self.safety.get_angle_meas_min, self.safety.get_angle_meas_max)


class AngleSteeringSafetyTest(MeasurementSafetyTest):
DEG_TO_CAN: int
ANGLE_RATE_BP: List[float]
ANGLE_RATE_UP: List[float] # windup limit
ANGLE_RATE_DOWN: List[float] # unwind limit
Expand All @@ -669,10 +650,18 @@ def setUpClass(cls):
cls.safety = None
raise unittest.SkipTest

@abc.abstractmethod
def _speed_msg(self, speed):
pass

@abc.abstractmethod
def _angle_cmd_msg(self, angle: float, enabled: bool):
pass

@abc.abstractmethod
def _angle_meas_msg(self, angle: float):
pass

def _set_prev_desired_angle(self, t):
t = int(t * self.DEG_TO_CAN)
self.safety.set_desired_angle_last(t)
Expand All @@ -685,6 +674,12 @@ def _reset_speed_measurement(self, speed):
for _ in range(MAX_SAMPLE_VALS):
self._rx(self._speed_msg(speed))

def test_vehicle_speed_measurements(self):
self._common_measurement_test(self._speed_msg, 0, 80, VEHICLE_SPEED_FACTOR, self.safety.get_vehicle_speed_min, self.safety.get_vehicle_speed_max)

def test_steering_angle_measurements(self):
self._common_measurement_test(self._angle_meas_msg, -180, 180, self.DEG_TO_CAN, self.safety.get_angle_meas_min, self.safety.get_angle_meas_max)

def test_angle_cmd_when_enabled(self):
# when controls are allowed, angle cmd rate limit is enforced
speeds = [0., 1., 5., 10., 15., 50.]
Expand Down
4 changes: 2 additions & 2 deletions tests/safety/test_subaru.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from panda import Panda
from panda.tests.libpanda import libpanda_py
import panda.tests.safety.common as common
from panda.tests.safety.common import CANPackerPanda, MeasurementSafetyTest
from panda.tests.safety.common import CANPackerPanda
from functools import partial

class SubaruMsg(enum.IntEnum):
Expand Down Expand Up @@ -52,7 +52,7 @@ def gen2_long_additional_tx_msgs():
def fwd_blacklisted_addr(lkas_msg=SubaruMsg.ES_LKAS):
return {SUBARU_CAM_BUS: [lkas_msg, SubaruMsg.ES_DashStatus, SubaruMsg.ES_LKAS_State, SubaruMsg.ES_Infotainment]}

class TestSubaruSafetyBase(common.PandaSafetyTest, MeasurementSafetyTest):
class TestSubaruSafetyBase(common.PandaSafetyTest):
FLAGS = 0
STANDSTILL_THRESHOLD = 0 # kph
RELAY_MALFUNCTION_ADDR = SubaruMsg.ES_LKAS
Expand Down

0 comments on commit 331829b

Please sign in to comment.