mirror of
https://github.com/infiniteCable2/opendbc.git
synced 2026-02-18 13:03:52 +08:00
This commit introduces various safety features required for the SunnyPilot project into the car safety interfaces. A significant change is the addition of "safety_mads.h" file which includes the necessary declarations and definitions for maintaining safety in car operations, such as updating the button state and controlling the vehicle based on current conditions. The "safety_mads.h" file is then included in safety.h. Code related to the lateral control of the vehicle, handling of button presses, and car safety checks for different car models are updated to accommodate these new safety features. Furthermore, updates are made to ensure vehicle control remains safe and transitions between control states happen correctly. This not only enhances the safety functions of the system but also enables greater connectivity with the SunnyPilot system.
302 lines
11 KiB
Python
Executable File
302 lines
11 KiB
Python
Executable File
#!/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
|
|
|
|
|
|
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]}
|
|
FWD_BUS_LOOKUP = {0: 2, 2: 0}
|
|
|
|
MAX_RATE_UP = 2
|
|
MAX_RATE_DOWN = 3
|
|
MAX_TORQUE = 270
|
|
|
|
MAX_RT_DELTA = 112
|
|
RT_INTERVAL = 250000
|
|
|
|
DRIVER_TORQUE_ALLOWANCE = 250
|
|
DRIVER_TORQUE_FACTOR = 2
|
|
|
|
# Safety around steering req bit
|
|
MIN_VALID_STEERING_FRAMES = 89
|
|
MAX_INVALID_STEERING_FRAMES = 2
|
|
MIN_VALID_STEERING_RT_INTERVAL = 810000 # a ~10% buffer, can send steer up to 110Hz
|
|
|
|
PT_BUS = 0
|
|
SCC_BUS = 2
|
|
STEER_BUS = 0
|
|
STEER_MSG = ""
|
|
GAS_MSG = ("", "")
|
|
BUTTONS_TX_BUS = 1
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
if cls.__name__ == "TestHyundaiCanfdBase":
|
|
cls.packer = None
|
|
cls.safety = None
|
|
raise unittest.SkipTest
|
|
|
|
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"WHEEL_SPEED_{i}": speed * 0.03125 for i in range(1, 5)}
|
|
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)
|
|
|
|
def _acc_state_msg(self, enable):
|
|
values = {"MainMode_ACC": enable}
|
|
return self.packer.make_can_msg_panda("SCC_CONTROL", self.SCC_BUS, values)
|
|
|
|
def _lkas_button_msg(self, enabled):
|
|
values = {"LDA_BTN": enabled}
|
|
return self.packer.make_can_msg_panda("CRUISE_BUTTONS", self.PT_BUS, values)
|
|
|
|
def _main_cruise_button_msg(self, enabled):
|
|
return self._button_msg(0, enabled)
|
|
|
|
|
|
class TestHyundaiCanfdLFASteeringBase(TestHyundaiCanfdBase):
|
|
|
|
TX_MSGS = [[0x12A, 0], [0x1A0, 1], [0x1CF, 0], [0x1E0, 0]]
|
|
RELAY_MALFUNCTION_ADDRS = {0: (0x12A,)} # LFA
|
|
FWD_BLACKLISTED_ADDRS = {2: [0x12A, 0x1E0]}
|
|
FWD_BUS_LOOKUP = {0: 2, 2: 0}
|
|
|
|
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([
|
|
# 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 TestHyundaiCanfdLFASteering(TestHyundaiCanfdLFASteeringBase):
|
|
pass
|
|
|
|
|
|
@parameterized_class([
|
|
# 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 TestHyundaiCanfdLFASteeringAltButtons(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 _lkas_button_msg(self, enabled):
|
|
values = {"LDA_BTN": enabled}
|
|
return self.packer.make_can_msg_panda("CRUISE_BUTTONS_ALT", 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)))
|
|
|
|
|
|
class TestHyundaiCanfdLKASteeringEV(TestHyundaiCanfdBase):
|
|
|
|
TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0]]
|
|
RELAY_MALFUNCTION_ADDRS = {0: (0x50,)} # LKAS
|
|
FWD_BLACKLISTED_ADDRS = {2: [0x50, 0x2a4]}
|
|
FWD_BUS_LOOKUP = {0: 2, 2: 0}
|
|
|
|
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,)} # LKAS_ALT
|
|
FWD_BLACKLISTED_ADDRS = {2: [0x110, 0x362]}
|
|
FWD_BUS_LOOKUP = {0: 2, 2: 0}
|
|
|
|
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,), 1: (0x1a0,)} # LKAS, 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)
|
|
|
|
def _tx_acc_state_msg(self, enable):
|
|
values = {"MainMode_ACC": enable}
|
|
return self.packer.make_can_msg_panda("SCC_CONTROL", 0, values)
|
|
|
|
# Tests longitudinal for ICE, hybrid, EV cars with LFA steering
|
|
@parameterized_class([
|
|
# 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 TestHyundaiCanfdLFASteeringLong(HyundaiLongitudinalBase, TestHyundaiCanfdLFASteeringBase):
|
|
|
|
FWD_BLACKLISTED_ADDRS = {2: [0x12a, 0x1e0, 0x1a0, 0x160]}
|
|
|
|
RELAY_MALFUNCTION_ADDRS = {0: (0x12A, 0x1a0)} # LFA, SCC_CONTROL
|
|
|
|
DISABLED_ECU_UDS_MSG = (0x7D0, 0)
|
|
DISABLED_ECU_ACTUATION_MSG = (0x1a0, 0)
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
if cls.__name__ == "TestHyundaiCanfdLFASteeringLong":
|
|
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 _tx_acc_state_msg(self, enable):
|
|
values = {"MainMode_ACC": enable}
|
|
return self.packer.make_can_msg_panda("SCC_CONTROL", 0, values)
|
|
|
|
# no knockout
|
|
def test_tester_present_allowed(self):
|
|
pass
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|