mirror of https://github.com/commaai/panda.git
Safety Test Refactor: Honda (#495)
* nidec * bosch * button * more common * packer * more packer * readability * tx too * don't need that * delete StdTest * don't need to duplicate this * only nidec has interceptor
This commit is contained in:
parent
0632710acd
commit
1dbed65e38
|
@ -197,59 +197,3 @@ class PandaSafetyTest(PandaSafetyTestBase):
|
|||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
self._rx(self._speed_msg(0))
|
||||
|
||||
# TODO: use PandaSafetyTest for all tests and delete this
|
||||
class StdTest:
|
||||
@staticmethod
|
||||
def test_relay_malfunction(test, addr, bus=0):
|
||||
# input is a test class and the address that, if seen on specified bus, triggers
|
||||
# the relay_malfunction protection logic: both tx_hook and fwd_hook are
|
||||
# expected to return failure
|
||||
test.assertFalse(test.safety.get_relay_malfunction())
|
||||
test.safety.safety_rx_hook(make_msg(bus, addr, 8))
|
||||
test.assertTrue(test.safety.get_relay_malfunction())
|
||||
for a in range(1, 0x800):
|
||||
for b in range(0, 3):
|
||||
test.assertFalse(test.safety.safety_tx_hook(make_msg(b, a, 8)))
|
||||
test.assertEqual(-1, test.safety.safety_fwd_hook(b, make_msg(b, a, 8)))
|
||||
|
||||
@staticmethod
|
||||
def test_manually_enable_controls_allowed(test):
|
||||
test.safety.set_controls_allowed(1)
|
||||
test.assertTrue(test.safety.get_controls_allowed())
|
||||
test.safety.set_controls_allowed(0)
|
||||
test.assertFalse(test.safety.get_controls_allowed())
|
||||
|
||||
@staticmethod
|
||||
def test_spam_can_buses(test, TX_MSGS):
|
||||
for addr in range(1, 0x800):
|
||||
for bus in range(0, 4):
|
||||
if all(addr != m[0] or bus != m[1] for m in TX_MSGS):
|
||||
test.assertFalse(test.safety.safety_tx_hook(make_msg(bus, addr, 8)))
|
||||
|
||||
@staticmethod
|
||||
def test_allow_brake_at_zero_speed(test):
|
||||
# Brake was already pressed
|
||||
test.safety.safety_rx_hook(test._speed_msg(0))
|
||||
test.safety.safety_rx_hook(test._brake_msg(1))
|
||||
test.safety.set_controls_allowed(1)
|
||||
test.safety.safety_rx_hook(test._brake_msg(1))
|
||||
test.assertTrue(test.safety.get_controls_allowed())
|
||||
test.safety.safety_rx_hook(test._brake_msg(0))
|
||||
test.assertTrue(test.safety.get_controls_allowed())
|
||||
# rising edge of brake should disengage
|
||||
test.safety.safety_rx_hook(test._brake_msg(1))
|
||||
test.assertFalse(test.safety.get_controls_allowed())
|
||||
test.safety.safety_rx_hook(test._brake_msg(0)) # reset no brakes
|
||||
|
||||
@staticmethod
|
||||
def test_not_allow_brake_when_moving(test, standstill_threshold):
|
||||
# Brake was already pressed
|
||||
test.safety.safety_rx_hook(test._brake_msg(1))
|
||||
test.safety.set_controls_allowed(1)
|
||||
test.safety.safety_rx_hook(test._speed_msg(standstill_threshold))
|
||||
test.safety.safety_rx_hook(test._brake_msg(1))
|
||||
test.assertTrue(test.safety.get_controls_allowed())
|
||||
test.safety.safety_rx_hook(test._speed_msg(standstill_threshold + 1))
|
||||
test.safety.safety_rx_hook(test._brake_msg(1))
|
||||
test.assertFalse(test.safety.get_controls_allowed())
|
||||
test.safety.safety_rx_hook(test._speed_msg(0))
|
||||
|
|
|
@ -3,15 +3,18 @@ import unittest
|
|||
import numpy as np
|
||||
from panda import Panda
|
||||
from panda.tests.safety import libpandasafety_py
|
||||
from panda.tests.safety.common import StdTest, make_msg, MAX_WRONG_COUNTERS, UNSAFE_MODE
|
||||
import panda.tests.safety.common as common
|
||||
from panda.tests.safety.common import CANPackerPanda, make_msg, \
|
||||
MAX_WRONG_COUNTERS, UNSAFE_MODE
|
||||
|
||||
MAX_BRAKE = 255
|
||||
|
||||
INTERCEPTOR_THRESHOLD = 344
|
||||
N_TX_MSGS = [[0xE4, 0], [0x194, 0], [0x1FA, 0], [0x200, 0], [0x30C, 0], [0x33D, 0]]
|
||||
BH_TX_MSGS = [[0xE4, 0], [0x296, 1], [0x33D, 0]] # Bosch Harness
|
||||
BG_TX_MSGS = [[0xE4, 2], [0x296, 0], [0x33D, 2]] # Bosch Giraffe
|
||||
|
||||
class Btn:
|
||||
CANCEL = 2
|
||||
SET = 3
|
||||
RESUME = 4
|
||||
|
||||
HONDA_N_HW = 0
|
||||
HONDA_BG_HW = 1
|
||||
|
@ -25,283 +28,141 @@ def honda_interceptor_msg(gas, addr):
|
|||
((gas2 & 0xff) << 24) | ((gas2 & 0xff00) << 8)
|
||||
return to_send
|
||||
|
||||
def honda_checksum(msg, addr, len_msg):
|
||||
checksum = 0
|
||||
while addr > 0:
|
||||
checksum += addr
|
||||
addr >>= 4
|
||||
for i in range (0, 2*len_msg):
|
||||
if i < 8:
|
||||
checksum += (msg.RDLR >> (4 * i))
|
||||
else:
|
||||
checksum += (msg.RDHR >> (4 * (i - 8)))
|
||||
return (8 - checksum) & 0xF
|
||||
|
||||
|
||||
class TestHondaSafety(unittest.TestCase):
|
||||
class TestHondaSafety(common.PandaSafetyTest):
|
||||
cnt_speed = 0
|
||||
cnt_gas = 0
|
||||
cnt_button = 0
|
||||
|
||||
PT_BUS = 0
|
||||
|
||||
@classmethod
|
||||
def setUp(cls):
|
||||
cls.safety = libpandasafety_py.libpandasafety
|
||||
cls.safety.set_safety_hooks(Panda.SAFETY_HONDA_NIDEC, 0)
|
||||
cls.safety.init_tests_honda()
|
||||
def setUpClass(cls):
|
||||
if cls.__name__ == "TestHondaSafety":
|
||||
cls.packer = None
|
||||
cls.safety = None
|
||||
raise unittest.SkipTest
|
||||
|
||||
# override these inherited tests. honda doesn't use pcm enable
|
||||
def test_disable_control_allowed_from_cruise(self): pass
|
||||
def test_enable_control_allowed_from_cruise(self): pass
|
||||
|
||||
def _speed_msg(self, speed):
|
||||
bus = 1 if self.safety.get_honda_hw() == HONDA_BH_HW else 0
|
||||
to_send = make_msg(bus, 0x158)
|
||||
to_send[0].RDLR = speed
|
||||
to_send[0].RDHR |= (self.cnt_speed % 4) << 28
|
||||
to_send[0].RDHR |= honda_checksum(to_send[0], 0x158, 8) << 24
|
||||
values = {"XMISSION_SPEED": speed, "COUNTER": self.cnt_speed % 4}
|
||||
self.__class__.cnt_speed += 1
|
||||
return to_send
|
||||
return self.packer.make_can_msg_panda("ENGINE_DATA", self.PT_BUS, values)
|
||||
|
||||
def _button_msg(self, buttons, addr):
|
||||
bus = 1 if self.safety.get_honda_hw() == HONDA_BH_HW else 0
|
||||
to_send = make_msg(bus, addr)
|
||||
to_send[0].RDLR = buttons << 5
|
||||
to_send[0].RDHR |= (self.cnt_button % 4) << 28
|
||||
to_send[0].RDHR |= honda_checksum(to_send[0], addr, 8) << 24
|
||||
def _button_msg(self, buttons):
|
||||
values = {"CRUISE_BUTTONS": buttons, "COUNTER": self.cnt_button % 4}
|
||||
self.__class__.cnt_button += 1
|
||||
return to_send
|
||||
return self.packer.make_can_msg_panda("SCM_BUTTONS", self.PT_BUS, values)
|
||||
|
||||
def _brake_msg(self, brake):
|
||||
bus = 1 if self.safety.get_honda_hw() == HONDA_BH_HW else 0
|
||||
to_send = make_msg(bus, 0x17C)
|
||||
to_send[0].RDHR = 0x200000 if brake else 0
|
||||
to_send[0].RDHR |= (self.cnt_gas % 4) << 28
|
||||
to_send[0].RDHR |= honda_checksum(to_send[0], 0x17C, 8) << 24
|
||||
values = {"BRAKE_PRESSED": brake, "COUNTER": self.cnt_gas % 4}
|
||||
self.__class__.cnt_gas += 1
|
||||
return to_send
|
||||
|
||||
def _alt_brake_msg(self, brake):
|
||||
to_send = make_msg(0, 0x1BE)
|
||||
to_send[0].RDLR = 0x10 if brake else 0
|
||||
return to_send
|
||||
return self.packer.make_can_msg_panda("POWERTRAIN_DATA", self.PT_BUS, values)
|
||||
|
||||
def _gas_msg(self, gas):
|
||||
bus = 1 if self.safety.get_honda_hw() == HONDA_BH_HW else 0
|
||||
to_send = make_msg(bus, 0x17C)
|
||||
to_send[0].RDLR = 1 if gas else 0
|
||||
to_send[0].RDHR |= (self.cnt_gas % 4) << 28
|
||||
to_send[0].RDHR |= honda_checksum(to_send[0], 0x17C, 8) << 24
|
||||
values = {"PEDAL_GAS": gas, "COUNTER": self.cnt_gas % 4}
|
||||
self.__class__.cnt_gas += 1
|
||||
return to_send
|
||||
return self.packer.make_can_msg_panda("POWERTRAIN_DATA", self.PT_BUS, values)
|
||||
|
||||
def _send_brake_msg(self, brake):
|
||||
to_send = make_msg(0, 0x1FA)
|
||||
to_send[0].RDLR = ((brake & 0x3) << 14) | ((brake & 0x3FF) >> 2)
|
||||
return to_send
|
||||
values = {}
|
||||
if self.safety.get_honda_hw() == HONDA_N_HW:
|
||||
values = {"COMPUTER_BRAKE": brake}
|
||||
return self.packer.make_can_msg_panda("BRAKE_COMMAND", 0, values)
|
||||
|
||||
def _send_steer_msg(self, steer):
|
||||
bus = 2 if self.safety.get_honda_hw() == HONDA_BG_HW else 0
|
||||
to_send = make_msg(bus, 0xE4, 6)
|
||||
to_send[0].RDLR = steer
|
||||
return to_send
|
||||
|
||||
def test_spam_can_buses(self):
|
||||
hw_type = self.safety.get_honda_hw()
|
||||
if hw_type == HONDA_N_HW:
|
||||
tx_msgs = N_TX_MSGS
|
||||
elif hw_type == HONDA_BH_HW:
|
||||
tx_msgs = BH_TX_MSGS
|
||||
elif hw_type == HONDA_BG_HW:
|
||||
tx_msgs = BG_TX_MSGS
|
||||
StdTest.test_spam_can_buses(self, tx_msgs)
|
||||
|
||||
def test_relay_malfunction(self):
|
||||
hw = self.safety.get_honda_hw()
|
||||
bus = 2 if hw == HONDA_BG_HW else 0
|
||||
StdTest.test_relay_malfunction(self, 0xE4, bus=bus)
|
||||
|
||||
def test_default_controls_not_allowed(self):
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_manually_enable_controls_allowed(self):
|
||||
StdTest.test_manually_enable_controls_allowed(self)
|
||||
values = {"STEER_TORQUE": steer}
|
||||
return self.packer.make_can_msg_panda("STEERING_CONTROL", 0, values)
|
||||
|
||||
def test_resume_button(self):
|
||||
RESUME_BTN = 4
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.safety.safety_rx_hook(self._button_msg(RESUME_BTN, 0x296))
|
||||
self._rx(self._button_msg(Btn.RESUME))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_set_button(self):
|
||||
SET_BTN = 3
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.safety.safety_rx_hook(self._button_msg(SET_BTN, 0x296))
|
||||
self._rx(self._button_msg(Btn.SET))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_cancel_button(self):
|
||||
CANCEL_BTN = 2
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_rx_hook(self._button_msg(CANCEL_BTN, 0x296))
|
||||
self._rx(self._button_msg(Btn.CANCEL))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_sample_speed(self):
|
||||
self.assertEqual(0, self.safety.get_honda_moving())
|
||||
self.safety.safety_rx_hook(self._speed_msg(100))
|
||||
self._rx(self._speed_msg(100))
|
||||
self.assertEqual(1, self.safety.get_honda_moving())
|
||||
|
||||
def test_prev_brake(self):
|
||||
self.assertFalse(self.safety.get_brake_pressed_prev())
|
||||
self.safety.safety_rx_hook(self._brake_msg(True))
|
||||
self.assertTrue(self.safety.get_brake_pressed_prev())
|
||||
|
||||
def test_disengage_on_brake(self):
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_rx_hook(self._brake_msg(1))
|
||||
self._rx(self._brake_msg(1))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_alt_disengage_on_brake(self):
|
||||
self.safety.set_honda_alt_brake_msg(1)
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_rx_hook(self._alt_brake_msg(1))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
self.safety.set_honda_alt_brake_msg(0)
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_rx_hook(self._alt_brake_msg(1))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_brake_disengage(self):
|
||||
StdTest.test_allow_brake_at_zero_speed(self)
|
||||
StdTest.test_not_allow_brake_when_moving(self, 0)
|
||||
|
||||
def test_prev_gas(self):
|
||||
self.safety.safety_rx_hook(self._gas_msg(False))
|
||||
self.assertFalse(self.safety.get_gas_pressed_prev())
|
||||
self.safety.safety_rx_hook(self._gas_msg(True))
|
||||
self.assertTrue(self.safety.get_gas_pressed_prev())
|
||||
|
||||
def test_prev_gas_interceptor(self):
|
||||
self.safety.safety_rx_hook(honda_interceptor_msg(0x0, 0x201))
|
||||
self._rx(honda_interceptor_msg(0x0, 0x201))
|
||||
self.assertFalse(self.safety.get_gas_interceptor_prev())
|
||||
self.safety.safety_rx_hook(honda_interceptor_msg(0x1000, 0x201))
|
||||
self._rx(honda_interceptor_msg(0x1000, 0x201))
|
||||
self.assertTrue(self.safety.get_gas_interceptor_prev())
|
||||
self.safety.safety_rx_hook(honda_interceptor_msg(0x0, 0x201))
|
||||
self._rx(honda_interceptor_msg(0x0, 0x201))
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
|
||||
def test_disengage_on_gas(self):
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_unsafe_mode_no_disengage_on_gas(self):
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS)
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
|
||||
|
||||
def test_allow_engage_with_gas_pressed(self):
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_disengage_on_gas_interceptor(self):
|
||||
for g in range(0, 0x1000):
|
||||
self.safety.safety_rx_hook(honda_interceptor_msg(0, 0x201))
|
||||
self._rx(honda_interceptor_msg(0, 0x201))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.safety_rx_hook(honda_interceptor_msg(g, 0x201))
|
||||
self._rx(honda_interceptor_msg(g, 0x201))
|
||||
remain_enabled = g <= INTERCEPTOR_THRESHOLD
|
||||
self.assertEqual(remain_enabled, self.safety.get_controls_allowed())
|
||||
self.safety.safety_rx_hook(honda_interceptor_msg(0, 0x201))
|
||||
self._rx(honda_interceptor_msg(0, 0x201))
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
|
||||
def test_unsafe_mode_no_disengage_on_gas_interceptor(self):
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS)
|
||||
for g in range(0, 0x1000):
|
||||
self.safety.safety_rx_hook(honda_interceptor_msg(g, 0x201))
|
||||
self._rx(honda_interceptor_msg(g, 0x201))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.safety_rx_hook(honda_interceptor_msg(0, 0x201))
|
||||
self._rx(honda_interceptor_msg(0, 0x201))
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
|
||||
self.safety.set_controls_allowed(False)
|
||||
|
||||
def test_allow_engage_with_gas_interceptor_pressed(self):
|
||||
self.safety.safety_rx_hook(honda_interceptor_msg(0x1000, 0x201))
|
||||
self._rx(honda_interceptor_msg(0x1000, 0x201))
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_rx_hook(honda_interceptor_msg(0x1000, 0x201))
|
||||
self._rx(honda_interceptor_msg(0x1000, 0x201))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.safety_rx_hook(honda_interceptor_msg(0, 0x201))
|
||||
self._rx(honda_interceptor_msg(0, 0x201))
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
|
||||
def test_brake_safety_check(self):
|
||||
hw = self.safety.get_honda_hw()
|
||||
if hw == HONDA_N_HW:
|
||||
for fwd_brake in [False, True]:
|
||||
self.safety.set_honda_fwd_brake(fwd_brake)
|
||||
for brake in np.arange(0, MAX_BRAKE + 10, 1):
|
||||
for controls_allowed in [True, False]:
|
||||
self.safety.set_controls_allowed(controls_allowed)
|
||||
if fwd_brake:
|
||||
send = False # block openpilot brake msg when fwd'ing stock msg
|
||||
elif controls_allowed:
|
||||
send = MAX_BRAKE >= brake >= 0
|
||||
else:
|
||||
send = brake == 0
|
||||
self.assertEqual(send, self.safety.safety_tx_hook(self._send_brake_msg(brake)))
|
||||
self.safety.set_honda_fwd_brake(False)
|
||||
|
||||
def test_gas_interceptor_safety_check(self):
|
||||
if self.safety.get_honda_hw() == HONDA_N_HW:
|
||||
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.safety.safety_tx_hook(honda_interceptor_msg(gas, 0x200)))
|
||||
|
||||
def test_steer_safety_check(self):
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._send_steer_msg(0x0000)))
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._send_steer_msg(0x1000)))
|
||||
|
||||
def test_spam_cancel_safety_check(self):
|
||||
hw = self.safety.get_honda_hw()
|
||||
if hw != HONDA_N_HW:
|
||||
RESUME_BTN = 4
|
||||
SET_BTN = 3
|
||||
CANCEL_BTN = 2
|
||||
BUTTON_MSG = 0x296
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._button_msg(CANCEL_BTN, BUTTON_MSG)))
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._button_msg(RESUME_BTN, BUTTON_MSG)))
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._button_msg(SET_BTN, BUTTON_MSG)))
|
||||
# do not block resume if we are engaged already
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._button_msg(RESUME_BTN, BUTTON_MSG)))
|
||||
self.assertTrue(self._tx(self._send_steer_msg(0x0000)))
|
||||
self.assertFalse(self._tx(self._send_steer_msg(0x1000)))
|
||||
|
||||
def test_rx_hook(self):
|
||||
|
||||
# TODO: move this test to common
|
||||
# checksum checks
|
||||
SET_BTN = 3
|
||||
for msg in ["btn1", "btn2", "gas", "speed"]:
|
||||
for msg in ["btn", "gas", "speed"]:
|
||||
self.safety.set_controls_allowed(1)
|
||||
if msg == "btn1":
|
||||
if self.safety.get_honda_hw() == HONDA_N_HW:
|
||||
to_push = self._button_msg(SET_BTN, 0x1A6) # only in Honda_NIDEC
|
||||
else:
|
||||
continue
|
||||
if msg == "btn2":
|
||||
to_push = self._button_msg(SET_BTN, 0x296)
|
||||
# TODO: add this coverage back by re-running all tests with the acura dbc
|
||||
# to_push = self._button_msg(Btn.SET, 0x1A6) # only in Honda_NIDEC
|
||||
if msg == "btn":
|
||||
to_push = self._button_msg(Btn.SET)
|
||||
if msg == "gas":
|
||||
to_push = self._gas_msg(0)
|
||||
if msg == "speed":
|
||||
to_push = self._speed_msg(0)
|
||||
self.assertTrue(self.safety.safety_rx_hook(to_push))
|
||||
to_push[0].RDHR = 0 # invalidate checksum
|
||||
self.assertFalse(self.safety.safety_rx_hook(to_push))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
self.assertTrue(self._rx(to_push))
|
||||
if msg != "btn":
|
||||
to_push[0].RDHR = 0 # invalidate checksum
|
||||
self.assertFalse(self._rx(to_push))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
# counter
|
||||
# reset wrong_counters to zero by sending valid messages
|
||||
|
@ -311,161 +172,194 @@ class TestHondaSafety(unittest.TestCase):
|
|||
self.__class__.cnt_button += 1
|
||||
if i < MAX_WRONG_COUNTERS:
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_rx_hook(self._button_msg(SET_BTN, 0x296))
|
||||
self.safety.safety_rx_hook(self._speed_msg(0))
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
self._rx(self._button_msg(Btn.SET))
|
||||
self._rx(self._speed_msg(0))
|
||||
self._rx(self._gas_msg(0))
|
||||
else:
|
||||
self.assertFalse(self.safety.safety_rx_hook(self._button_msg(SET_BTN, 0x296)))
|
||||
self.assertFalse(self.safety.safety_rx_hook(self._speed_msg(0)))
|
||||
self.assertFalse(self.safety.safety_rx_hook(self._gas_msg(0)))
|
||||
self.assertFalse(self._rx(self._button_msg(Btn.SET)))
|
||||
self.assertFalse(self._rx(self._speed_msg(0)))
|
||||
self.assertFalse(self._rx(self._gas_msg(0)))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
# restore counters for future tests with a couple of good messages
|
||||
for i in range(2):
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_rx_hook(self._button_msg(SET_BTN, 0x296))
|
||||
self.safety.safety_rx_hook(self._speed_msg(0))
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
self.safety.safety_rx_hook(self._button_msg(SET_BTN, 0x296))
|
||||
self._rx(self._button_msg(Btn.SET))
|
||||
self._rx(self._speed_msg(0))
|
||||
self._rx(self._gas_msg(0))
|
||||
self._rx(self._button_msg(Btn.SET))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_tx_hook_on_pedal_pressed(self):
|
||||
for mode in [UNSAFE_MODE.DEFAULT, UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS]:
|
||||
for pedal in ['brake', 'gas']:
|
||||
self.safety.set_unsafe_mode(mode)
|
||||
allow_ctrl = False
|
||||
if pedal == 'brake':
|
||||
# brake_pressed_prev and honda_moving
|
||||
self._rx(self._speed_msg(100))
|
||||
self._rx(self._brake_msg(1))
|
||||
elif pedal == 'gas':
|
||||
# gas_pressed_prev
|
||||
self._rx(self._gas_msg(1))
|
||||
allow_ctrl = mode == UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS
|
||||
|
||||
self.safety.set_controls_allowed(1)
|
||||
hw = self.safety.get_honda_hw()
|
||||
if hw == HONDA_N_HW:
|
||||
self.safety.set_honda_fwd_brake(False)
|
||||
self.assertEqual(allow_ctrl, self._tx(self._send_brake_msg(MAX_BRAKE)))
|
||||
self.assertEqual(allow_ctrl, self._tx(self._send_steer_msg(0x1000)))
|
||||
|
||||
# reset status
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
|
||||
self._tx(self._send_brake_msg(0))
|
||||
self._tx(self._send_steer_msg(0))
|
||||
if pedal == 'brake':
|
||||
self._rx(self._speed_msg(0))
|
||||
self._rx(self._brake_msg(0))
|
||||
elif pedal == 'gas':
|
||||
self._rx(self._gas_msg(0))
|
||||
|
||||
|
||||
class TestHondaNidecSafety(TestHondaSafety):
|
||||
|
||||
TX_MSGS = [[0xE4, 0], [0x194, 0], [0x1FA, 0], [0x200, 0], [0x30C, 0], [0x33D, 0]]
|
||||
STANDSTILL_THRESHOLD = 0
|
||||
RELAY_MALFUNCTION_ADDR = 0xE4
|
||||
RELAY_MALFUNCTION_BUS = 0
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x194, 0x33D, 0x30C]}
|
||||
FWD_BUS_LOOKUP = {0: 2, 2: 0}
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerPanda("honda_civic_touring_2016_can_generated")
|
||||
self.safety = libpandasafety_py.libpandasafety
|
||||
self.safety.set_safety_hooks(Panda.SAFETY_HONDA_NIDEC, 0)
|
||||
self.safety.init_tests_honda()
|
||||
|
||||
def test_fwd_hook(self):
|
||||
buss = list(range(0x0, 0x3))
|
||||
msgs = list(range(0x1, 0x800))
|
||||
fwd_brake = [False, True]
|
||||
# normal operation, not forwarding AEB
|
||||
self.FWD_BLACKLISTED_ADDRS[2].append(0x1FA)
|
||||
self.safety.set_honda_fwd_brake(False)
|
||||
super().test_fwd_hook()
|
||||
|
||||
for f in fwd_brake:
|
||||
self.safety.set_honda_fwd_brake(f)
|
||||
blocked_msgs = [0xE4, 0x194, 0x33D]
|
||||
blocked_msgs += [0x30C]
|
||||
if not f:
|
||||
blocked_msgs += [0x1FA]
|
||||
for b in buss:
|
||||
for m in msgs:
|
||||
if b == 0:
|
||||
fwd_bus = 2
|
||||
elif b == 1:
|
||||
fwd_bus = -1
|
||||
elif b == 2:
|
||||
fwd_bus = -1 if m in blocked_msgs else 0
|
||||
|
||||
# assume len 8
|
||||
self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(b, make_msg(b, m, 8)))
|
||||
# TODO: test latching until AEB event is over?
|
||||
# forwarding AEB brake signal
|
||||
self.FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x194, 0x33D, 0x30C]}
|
||||
self.safety.set_honda_fwd_brake(True)
|
||||
super().test_fwd_hook()
|
||||
|
||||
def test_brake_safety_check(self):
|
||||
for fwd_brake in [False, True]:
|
||||
self.safety.set_honda_fwd_brake(fwd_brake)
|
||||
for brake in np.arange(0, MAX_BRAKE + 10, 1):
|
||||
for controls_allowed in [True, False]:
|
||||
self.safety.set_controls_allowed(controls_allowed)
|
||||
if fwd_brake:
|
||||
send = False # block openpilot brake msg when fwd'ing stock msg
|
||||
elif controls_allowed:
|
||||
send = MAX_BRAKE >= brake >= 0
|
||||
else:
|
||||
send = brake == 0
|
||||
self.assertEqual(send, self._tx(self._send_brake_msg(brake)))
|
||||
self.safety.set_honda_fwd_brake(False)
|
||||
|
||||
def test_tx_hook_on_pedal_pressed(self):
|
||||
for pedal in ['brake', 'gas', 'interceptor']:
|
||||
if pedal == 'brake':
|
||||
# brake_pressed_prev and honda_moving
|
||||
self.safety.safety_rx_hook(self._speed_msg(100))
|
||||
self.safety.safety_rx_hook(self._brake_msg(1))
|
||||
elif pedal == 'gas':
|
||||
# gas_pressed_prev
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
elif pedal == 'interceptor':
|
||||
# gas_interceptor_prev > INTERCEPTOR_THRESHOLD
|
||||
self.safety.safety_rx_hook(honda_interceptor_msg(INTERCEPTOR_THRESHOLD+1, 0x201))
|
||||
self.safety.safety_rx_hook(honda_interceptor_msg(INTERCEPTOR_THRESHOLD+1, 0x201))
|
||||
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(honda_interceptor_msg(gas, 0x200)))
|
||||
|
||||
def test_tx_hook_on_interceptor_pressed(self):
|
||||
for mode in [UNSAFE_MODE.DEFAULT, UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS]:
|
||||
self.safety.set_unsafe_mode(mode)
|
||||
# gas_interceptor_prev > INTERCEPTOR_THRESHOLD
|
||||
self._rx(honda_interceptor_msg(INTERCEPTOR_THRESHOLD+1, 0x201))
|
||||
self._rx(honda_interceptor_msg(INTERCEPTOR_THRESHOLD+1, 0x201))
|
||||
allow_ctrl = mode == UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS
|
||||
|
||||
self.safety.set_controls_allowed(1)
|
||||
hw = self.safety.get_honda_hw()
|
||||
if hw == HONDA_N_HW:
|
||||
self.safety.set_honda_fwd_brake(False)
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._send_brake_msg(MAX_BRAKE)))
|
||||
self.assertFalse(self.safety.safety_tx_hook(honda_interceptor_msg(INTERCEPTOR_THRESHOLD, 0x200)))
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._send_steer_msg(0x1000)))
|
||||
self.safety.set_honda_fwd_brake(False)
|
||||
self.assertEqual(allow_ctrl, self._tx(self._send_brake_msg(MAX_BRAKE)))
|
||||
self.assertEqual(allow_ctrl, self._tx(honda_interceptor_msg(INTERCEPTOR_THRESHOLD, 0x200)))
|
||||
self.assertEqual(allow_ctrl, self._tx(self._send_steer_msg(0x1000)))
|
||||
|
||||
# reset status
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.safety.safety_tx_hook(self._send_brake_msg(0))
|
||||
self.safety.safety_tx_hook(self._send_steer_msg(0))
|
||||
self.safety.safety_tx_hook(honda_interceptor_msg(0, 0x200))
|
||||
if pedal == 'brake':
|
||||
self.safety.safety_rx_hook(self._speed_msg(0))
|
||||
self.safety.safety_rx_hook(self._brake_msg(0))
|
||||
elif pedal == 'gas':
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
elif pedal == 'interceptor':
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
|
||||
def test_tx_hook_on_pedal_pressed_on_unsafe_gas_mode(self):
|
||||
for pedal in ['brake', 'gas', 'interceptor']:
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DISABLE_DISENGAGE_ON_GAS)
|
||||
if pedal == 'brake':
|
||||
# brake_pressed_prev and honda_moving
|
||||
self.safety.safety_rx_hook(self._speed_msg(100))
|
||||
self.safety.safety_rx_hook(self._brake_msg(1))
|
||||
allow_ctrl = False
|
||||
elif pedal == 'gas':
|
||||
# gas_pressed_prev
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
allow_ctrl = True
|
||||
elif pedal == 'interceptor':
|
||||
# gas_interceptor_prev > INTERCEPTOR_THRESHOLD
|
||||
self.safety.safety_rx_hook(honda_interceptor_msg(INTERCEPTOR_THRESHOLD+1, 0x201))
|
||||
self.safety.safety_rx_hook(honda_interceptor_msg(INTERCEPTOR_THRESHOLD+1, 0x201))
|
||||
allow_ctrl = True
|
||||
|
||||
self.safety.set_controls_allowed(1)
|
||||
hw = self.safety.get_honda_hw()
|
||||
if hw == HONDA_N_HW:
|
||||
self.safety.set_honda_fwd_brake(False)
|
||||
self.assertEqual(allow_ctrl, self.safety.safety_tx_hook(self._send_brake_msg(MAX_BRAKE)))
|
||||
self.assertEqual(allow_ctrl, self.safety.safety_tx_hook(honda_interceptor_msg(INTERCEPTOR_THRESHOLD, 0x200)))
|
||||
self.assertEqual(allow_ctrl, self.safety.safety_tx_hook(self._send_steer_msg(0x1000)))
|
||||
# reset status
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.safety.set_unsafe_mode(UNSAFE_MODE.DEFAULT)
|
||||
self.safety.safety_tx_hook(self._send_brake_msg(0))
|
||||
self.safety.safety_tx_hook(self._send_steer_msg(0))
|
||||
self.safety.safety_tx_hook(honda_interceptor_msg(0, 0x200))
|
||||
if pedal == 'brake':
|
||||
self.safety.safety_rx_hook(self._speed_msg(0))
|
||||
self.safety.safety_rx_hook(self._brake_msg(0))
|
||||
elif pedal == 'gas':
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
elif pedal == 'interceptor':
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
|
||||
class TestHondaBoschGiraffeSafety(TestHondaSafety):
|
||||
@classmethod
|
||||
def setUp(cls):
|
||||
TestHondaSafety.setUp()
|
||||
cls.safety = libpandasafety_py.libpandasafety
|
||||
cls.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH_GIRAFFE, 0)
|
||||
cls.safety.init_tests_honda()
|
||||
|
||||
def test_fwd_hook(self):
|
||||
buss = range(0x0, 0x3)
|
||||
msgs = range(0x1, 0x800)
|
||||
hw = self.safety.get_honda_hw()
|
||||
bus_rdr_cam = 2 if hw == HONDA_BH_HW else 1
|
||||
bus_rdr_car = 0 if hw == HONDA_BH_HW else 2
|
||||
bus_pt = 1 if hw == HONDA_BH_HW else 0
|
||||
|
||||
blocked_msgs = [0xE4, 0x33D]
|
||||
for b in buss:
|
||||
for m in msgs:
|
||||
if b == bus_pt:
|
||||
fwd_bus = -1
|
||||
elif b == bus_rdr_cam:
|
||||
fwd_bus = -1 if m in blocked_msgs else bus_rdr_car
|
||||
elif b == bus_rdr_car:
|
||||
fwd_bus = bus_rdr_cam
|
||||
|
||||
# assume len 8
|
||||
self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(b, make_msg(b, m, 8)))
|
||||
self._tx(self._send_brake_msg(0))
|
||||
self._tx(self._send_steer_msg(0))
|
||||
self._tx(honda_interceptor_msg(0, 0x200))
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
|
||||
|
||||
class TestHondaBoschHarnessSafety(TestHondaBoschGiraffeSafety):
|
||||
@classmethod
|
||||
def setUp(cls):
|
||||
TestHondaBoschGiraffeSafety.setUp()
|
||||
cls.safety = libpandasafety_py.libpandasafety
|
||||
cls.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH_HARNESS, 0)
|
||||
cls.safety.init_tests_honda()
|
||||
class TestHondaBoschHarnessSafety(TestHondaSafety):
|
||||
TX_MSGS = [[0xE4, 0], [0x296, 1], [0x33D, 0]] # Bosch Harness
|
||||
STANDSTILL_THRESHOLD = 0
|
||||
RELAY_MALFUNCTION_ADDR = 0xE4
|
||||
RELAY_MALFUNCTION_BUS = 0
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x33D]}
|
||||
FWD_BUS_LOOKUP = {0: 2, 2: 0}
|
||||
|
||||
PT_BUS = 1
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerPanda("honda_accord_s2t_2018_can_generated")
|
||||
self.safety = libpandasafety_py.libpandasafety
|
||||
self.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH_HARNESS, 0)
|
||||
self.safety.init_tests_honda()
|
||||
|
||||
def _alt_brake_msg(self, brake):
|
||||
to_send = make_msg(0, 0x1BE)
|
||||
to_send[0].RDLR = 0x10 if brake else 0
|
||||
return to_send
|
||||
|
||||
def test_spam_cancel_safety_check(self):
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.assertTrue(self._tx(self._button_msg(Btn.CANCEL)))
|
||||
self.assertFalse(self._tx(self._button_msg(Btn.RESUME)))
|
||||
self.assertFalse(self._tx(self._button_msg(Btn.SET)))
|
||||
# do not block resume if we are engaged already
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.assertTrue(self._tx(self._button_msg(Btn.RESUME)))
|
||||
|
||||
def test_alt_disengage_on_brake(self):
|
||||
self.safety.set_honda_alt_brake_msg(1)
|
||||
self.safety.set_controls_allowed(1)
|
||||
self._rx(self._alt_brake_msg(1))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
self.safety.set_honda_alt_brake_msg(0)
|
||||
self.safety.set_controls_allowed(1)
|
||||
self._rx(self._alt_brake_msg(1))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
|
||||
class TestHondaBoschGiraffeSafety(TestHondaBoschHarnessSafety):
|
||||
TX_MSGS = [[0xE4, 2], [0x296, 0], [0x33D, 2]] # Bosch Giraffe
|
||||
STANDSTILL_THRESHOLD = 0
|
||||
RELAY_MALFUNCTION_ADDR = 0xE4
|
||||
RELAY_MALFUNCTION_BUS = 2
|
||||
FWD_BLACKLISTED_ADDRS = {1: [0xE4, 0x33D]}
|
||||
FWD_BUS_LOOKUP = {1: 2, 2: 1}
|
||||
|
||||
PT_BUS = 0
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.safety = libpandasafety_py.libpandasafety
|
||||
self.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH_GIRAFFE, 0)
|
||||
self.safety.init_tests_honda()
|
||||
|
||||
def _send_steer_msg(self, steer):
|
||||
values = {"STEER_TORQUE": steer}
|
||||
return self.packer.make_can_msg_panda("STEERING_CONTROL", 2, values)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
Loading…
Reference in New Issue