openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

288 lines
10 KiB

#!/usr/bin/env python3
from parameterized import parameterized_class
import unittest
from opendbc.car.hyundai.values import HyundaiSafetyFlags
from opendbc.car.structs import CarParams
from opendbc.safety.tests.libsafety import libsafety_py
import opendbc.safety.tests.common as common
from opendbc.safety.tests.common import CANPackerPanda
from opendbc.safety.tests.hyundai_common import HyundaiButtonBase, HyundaiLongitudinalBase
# All combinations of radar/camera-SCC and gas/hybrid/EV cars
ALL_GAS_EV_HYBRID_COMBOS = [
# Radar SCC
{"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 0, "SAFETY_PARAM": 0},
{"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 0, "SAFETY_PARAM": HyundaiSafetyFlags.EV_GAS},
{"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 0, "SAFETY_PARAM": HyundaiSafetyFlags.HYBRID_GAS},
# Camera SCC
{"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.CAMERA_SCC},
{"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.EV_GAS | HyundaiSafetyFlags.CAMERA_SCC},
{"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.HYBRID_GAS | HyundaiSafetyFlags.CAMERA_SCC},
]
class TestHyundaiCanfdBase(HyundaiButtonBase, common.PandaCarSafetyTest, common.DriverTorqueSteeringSafetyTest, common.SteerRequestCutSafetyTest):
TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0]]
STANDSTILL_THRESHOLD = 12 # 0.375 kph
FWD_BLACKLISTED_ADDRS = {2: [0x50, 0x2a4]}
MAX_RATE_UP = 2
MAX_RATE_DOWN = 3
MAX_TORQUE_LOOKUP = [0], [270]
MAX_RT_DELTA = 112
DRIVER_TORQUE_ALLOWANCE = 250
DRIVER_TORQUE_FACTOR = 2
# Safety around steering req bit
MIN_VALID_STEERING_FRAMES = 89
MAX_INVALID_STEERING_FRAMES = 2
PT_BUS = 0
SCC_BUS = 2
STEER_BUS = 0
STEER_MSG = ""
GAS_MSG = ("", "")
BUTTONS_TX_BUS = 1
def _torque_driver_msg(self, torque):
values = {"STEERING_COL_TORQUE": torque}
return self.packer.make_can_msg_panda("MDPS", self.PT_BUS, values)
def _torque_cmd_msg(self, torque, steer_req=1):
values = {"TORQUE_REQUEST": torque, "STEER_REQ": steer_req}
return self.packer.make_can_msg_panda(self.STEER_MSG, self.STEER_BUS, values)
def _speed_msg(self, speed):
values = {f"WHL_Spd{pos}Val": speed * 0.03125 for pos in ["FL", "FR", "RL", "RR"]}
return self.packer.make_can_msg_panda("WHEEL_SPEEDS", self.PT_BUS, values)
def _user_brake_msg(self, brake):
values = {"DriverBraking": brake}
return self.packer.make_can_msg_panda("TCS", self.PT_BUS, values)
def _user_gas_msg(self, gas):
values = {self.GAS_MSG[1]: gas}
return self.packer.make_can_msg_panda(self.GAS_MSG[0], self.PT_BUS, values)
def _pcm_status_msg(self, enable):
values = {"ACCMode": 1 if enable else 0}
return self.packer.make_can_msg_panda("SCC_CONTROL", self.SCC_BUS, values)
def _button_msg(self, buttons, main_button=0, bus=None):
if bus is None:
bus = self.PT_BUS
values = {
"CRUISE_BUTTONS": buttons,
"ADAPTIVE_CRUISE_MAIN_BTN": main_button,
}
return self.packer.make_can_msg_panda("CRUISE_BUTTONS", bus, values)
class TestHyundaiCanfdLFASteeringBase(TestHyundaiCanfdBase):
TX_MSGS = [[0x12A, 0], [0x1A0, 1], [0x1CF, 0], [0x1E0, 0]]
RELAY_MALFUNCTION_ADDRS = {0: (0x12A, 0x1E0)} # LFA, LFAHDA_CLUSTER
FWD_BLACKLISTED_ADDRS = {2: [0x12A, 0x1E0]}
STEER_MSG = "LFA"
BUTTONS_TX_BUS = 2
SAFETY_PARAM: int
@classmethod
def setUpClass(cls):
super().setUpClass()
if cls.__name__ in ("TestHyundaiCanfdLFASteering", "TestHyundaiCanfdLFASteeringAltButtons"):
cls.packer = None
cls.safety = None
raise unittest.SkipTest
def setUp(self):
self.packer = CANPackerPanda("hyundai_canfd_generated")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, self.SAFETY_PARAM)
self.safety.init_tests()
@parameterized_class(ALL_GAS_EV_HYBRID_COMBOS)
class TestHyundaiCanfdLFASteering(TestHyundaiCanfdLFASteeringBase):
pass
class TestHyundaiCanfdLFASteeringAltButtonsBase(TestHyundaiCanfdLFASteeringBase):
SAFETY_PARAM: int
def setUp(self):
self.packer = CANPackerPanda("hyundai_canfd_generated")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_ALT_BUTTONS | self.SAFETY_PARAM)
self.safety.init_tests()
def _button_msg(self, buttons, main_button=0, bus=1):
values = {
"CRUISE_BUTTONS": buttons,
"ADAPTIVE_CRUISE_MAIN_BTN": main_button,
}
return self.packer.make_can_msg_panda("CRUISE_BUTTONS_ALT", self.PT_BUS, values)
def _acc_cancel_msg(self, cancel, accel=0):
values = {"ACCMode": 4 if cancel else 0, "aReqRaw": accel, "aReqValue": accel}
return self.packer.make_can_msg_panda("SCC_CONTROL", self.PT_BUS, values)
def test_button_sends(self):
"""
No button send allowed with alt buttons.
"""
for enabled in (True, False):
for btn in range(8):
self.safety.set_controls_allowed(enabled)
self.assertFalse(self._tx(self._button_msg(btn)))
def test_acc_cancel(self):
# FIXME: the CANFD_ALT_BUTTONS cars are the only ones that use SCC_CONTROL to cancel, why can't we use buttons?
for enabled in (True, False):
self.safety.set_controls_allowed(enabled)
self.assertTrue(self._tx(self._acc_cancel_msg(True)))
self.assertFalse(self._tx(self._acc_cancel_msg(True, accel=1)))
self.assertFalse(self._tx(self._acc_cancel_msg(False)))
@parameterized_class(ALL_GAS_EV_HYBRID_COMBOS)
class TestHyundaiCanfdLFASteeringAltButtons(TestHyundaiCanfdLFASteeringAltButtonsBase):
pass
class TestHyundaiCanfdLKASteeringEV(TestHyundaiCanfdBase):
TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0]]
RELAY_MALFUNCTION_ADDRS = {0: (0x50, 0x2a4)} # LKAS, CAM_0x2A4
FWD_BLACKLISTED_ADDRS = {2: [0x50, 0x2a4]}
PT_BUS = 1
SCC_BUS = 1
STEER_MSG = "LKAS"
GAS_MSG = ("ACCELERATOR", "ACCELERATOR_PEDAL")
def setUp(self):
self.packer = CANPackerPanda("hyundai_canfd_generated")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEERING | HyundaiSafetyFlags.EV_GAS)
self.safety.init_tests()
# TODO: Handle ICE and HEV configurations once we see cars that use the new messages
class TestHyundaiCanfdLKASteeringAltEV(TestHyundaiCanfdBase):
TX_MSGS = [[0x110, 0], [0x1CF, 1], [0x362, 0]]
RELAY_MALFUNCTION_ADDRS = {0: (0x110, 0x362)} # LKAS_ALT, CAM_0x362
FWD_BLACKLISTED_ADDRS = {2: [0x110, 0x362]}
PT_BUS = 1
SCC_BUS = 1
STEER_MSG = "LKAS_ALT"
GAS_MSG = ("ACCELERATOR", "ACCELERATOR_PEDAL")
def setUp(self):
self.packer = CANPackerPanda("hyundai_canfd_generated")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEERING | HyundaiSafetyFlags.EV_GAS |
HyundaiSafetyFlags.CANFD_LKA_STEERING_ALT)
self.safety.init_tests()
class TestHyundaiCanfdLKASteeringLongEV(HyundaiLongitudinalBase, TestHyundaiCanfdLKASteeringEV):
TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0], [0x51, 0], [0x730, 1], [0x12a, 1], [0x160, 1],
[0x1e0, 1], [0x1a0, 1], [0x1ea, 1], [0x200, 1], [0x345, 1], [0x1da, 1]]
RELAY_MALFUNCTION_ADDRS = {0: (0x50, 0x2a4), 1: (0x1a0,)} # LKAS, CAM_0x2A4, SCC_CONTROL
DISABLED_ECU_UDS_MSG = (0x730, 1)
DISABLED_ECU_ACTUATION_MSG = (0x1a0, 1)
STEER_MSG = "LFA"
GAS_MSG = ("ACCELERATOR", "ACCELERATOR_PEDAL")
STEER_BUS = 1
def setUp(self):
self.packer = CANPackerPanda("hyundai_canfd_generated")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEERING |
HyundaiSafetyFlags.LONG | HyundaiSafetyFlags.EV_GAS)
self.safety.init_tests()
def _accel_msg(self, accel, aeb_req=False, aeb_decel=0):
values = {
"aReqRaw": accel,
"aReqValue": accel,
}
return self.packer.make_can_msg_panda("SCC_CONTROL", 1, values)
# Tests longitudinal for ICE, hybrid, EV cars with LFA steering
class TestHyundaiCanfdLFASteeringLongBase(HyundaiLongitudinalBase, TestHyundaiCanfdLFASteeringBase):
FWD_BLACKLISTED_ADDRS = {2: [0x12a, 0x1e0, 0x1a0, 0x160]}
RELAY_MALFUNCTION_ADDRS = {0: (0x12A, 0x1E0, 0x1a0, 0x160)} # LFA, LFAHDA_CLUSTER, SCC_CONTROL, ADRV_0x160
DISABLED_ECU_UDS_MSG = (0x7D0, 0)
DISABLED_ECU_ACTUATION_MSG = (0x1a0, 0)
@classmethod
def setUpClass(cls):
if cls.__name__ == "TestHyundaiCanfdLFASteeringLongBase":
cls.safety = None
raise unittest.SkipTest
def setUp(self):
self.packer = CANPackerPanda("hyundai_canfd_generated")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.LONG | self.SAFETY_PARAM)
self.safety.init_tests()
def _accel_msg(self, accel, aeb_req=False, aeb_decel=0):
values = {
"aReqRaw": accel,
"aReqValue": accel,
}
return self.packer.make_can_msg_panda("SCC_CONTROL", 0, values)
def test_tester_present_allowed(self, ecu_disable: bool = True):
super().test_tester_present_allowed(ecu_disable=not self.SAFETY_PARAM & HyundaiSafetyFlags.CAMERA_SCC)
@parameterized_class(ALL_GAS_EV_HYBRID_COMBOS)
class TestHyundaiCanfdLFASteeringLong(TestHyundaiCanfdLFASteeringLongBase):
@classmethod
def setUpClass(cls):
if cls.__name__ == "TestHyundaiCanfdLFASteeringLong":
cls.safety = None
raise unittest.SkipTest
@parameterized_class(ALL_GAS_EV_HYBRID_COMBOS)
class TestHyundaiCanfdLFASteeringLongAltButtons(TestHyundaiCanfdLFASteeringLongBase, TestHyundaiCanfdLFASteeringAltButtonsBase):
@classmethod
def setUpClass(cls):
if cls.__name__ == "TestHyundaiCanfdLFASteeringLongAltButtons":
cls.safety = None
raise unittest.SkipTest
def setUp(self):
self.packer = CANPackerPanda("hyundai_canfd_generated")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.LONG | HyundaiSafetyFlags.CANFD_ALT_BUTTONS | self.SAFETY_PARAM)
self.safety.init_tests()
def test_acc_cancel(self):
# Alt buttons does not use SCC_CONTROL to cancel if longitudinal
pass
if __name__ == "__main__":
unittest.main()