mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-13 07:53:45 +08:00
113 lines
6.0 KiB
Python
113 lines
6.0 KiB
Python
"""Shared stock EV authority stays bound to the factory topology and word."""
|
|
import unittest
|
|
|
|
from opendbc.car import gen_empty_fingerprint, structs
|
|
from opendbc.car.hyundai.interface import CarInterface
|
|
from opendbc.car.hyundai.values import CAR, HyundaiFlags
|
|
from opendbc.car.hyundai.canfd_stock_aol import STOCK_EV_CARS, qualified
|
|
from openpilot.starpilot.aol.intent import AolSettings, AOL_TOGGLE
|
|
from openpilot.starpilot.car.hyundai.aol import create_intent, native_accepts_cp, policy_for
|
|
|
|
|
|
def params(identity, alternate=False, release=False):
|
|
fp = gen_empty_fingerprint()
|
|
fp[2][0x110 if alternate else 0x50] = 32 if alternate else 16
|
|
fp[1].update({0x1cf: 8, 0x130: 32, 0x35: 32, 0x175: 24, 0xa0: 24, 0xea: 24, 0x1a0: 32})
|
|
return CarInterface.get_params(identity, fp, [], False, release, False)
|
|
|
|
|
|
class TestCanfdStockProfiles(unittest.TestCase):
|
|
def test_actual_factory_words_and_exact_native_binding(self):
|
|
for identity in STOCK_EV_CARS:
|
|
for alternate in (False, True):
|
|
for release in (False, True):
|
|
cp = params(identity, alternate, release)
|
|
self.assertTrue(qualified(cp))
|
|
self.assertTrue(cp.pcmCruise)
|
|
self.assertFalse(cp.openpilotLongitudinalControl)
|
|
expected = 0x91 if alternate else 0x11
|
|
self.assertEqual(cp.safetyConfigs[0].safetyParam, expected)
|
|
policy = policy_for(cp)
|
|
self.assertTrue(policy.explicit_latch)
|
|
self.assertEqual(policy.safety_param_addition, 0x800)
|
|
cp.safetyConfigs[0].safetyParam |= policy.safety_param_addition
|
|
self.assertTrue(qualified(cp, marked_only=True))
|
|
model = int(cp.safetyConfigs[0].safetyModel.raw)
|
|
self.assertTrue(native_accepts_cp(cp, model, expected | 0x800))
|
|
self.assertFalse(native_accepts_cp(cp, model, (expected | 0x800) ^ 0x80))
|
|
|
|
def test_unsupported_flags_words_experience_and_identity_fail_closed(self):
|
|
cp = params(CAR.KIA_EV6)
|
|
for flag in (HyundaiFlags.HYBRID, HyundaiFlags.CANFD_ANGLE_STEERING,
|
|
HyundaiFlags.CANFD_ALT_BUTTONS, HyundaiFlags.CANFD_CAMERA_SCC):
|
|
bad = cp.as_reader().as_builder()
|
|
bad.flags = int(bad.flags) | int(flag)
|
|
self.assertFalse(qualified(bad))
|
|
for field, value in (('alternativeExperience', 32), ('openpilotLongitudinalControl', True),
|
|
('passive', True), ('dashcamOnly', True), ('notCar', True), ('pcmCruise', False)):
|
|
bad = cp.as_reader().as_builder()
|
|
setattr(bad, field, value)
|
|
self.assertFalse(qualified(bad))
|
|
for word in (0x15, 0x895, 0x1811, 0x811 | 0x4000):
|
|
bad = cp.as_reader().as_builder()
|
|
bad.safetyConfigs[0].safetyParam = word
|
|
self.assertFalse(qualified(bad))
|
|
bad = cp.as_reader().as_builder()
|
|
bad.carFingerprint = CAR.HYUNDAI_IONIQ_6
|
|
self.assertFalse(qualified(bad))
|
|
owner = cp.safetyConfigs[0]
|
|
auxiliary = structs.CarParams.SafetyConfig(safetyModel='noOutput')
|
|
for configs in ([owner, owner], [owner, auxiliary], [auxiliary, owner, owner],
|
|
[structs.CarParams.SafetyConfig(safetyModel='silent'), owner],
|
|
[structs.CarParams.SafetyConfig(safetyModel='noOutput', safetyParam=1), owner],
|
|
[auxiliary, structs.CarParams.SafetyConfig(safetyModel='hyundai', safetyParam=0x11)]):
|
|
bad = cp.as_reader().as_builder()
|
|
bad.safetyConfigs = configs
|
|
self.assertFalse(qualified(bad))
|
|
|
|
def test_supported_two_panda_layout_binds_only_exact_native_owner(self):
|
|
for identity in (CAR.KIA_EV6, CAR.GENESIS_GV70_ELECTRIFIED_1ST_GEN):
|
|
for release in (False, True):
|
|
with self.subTest(identity=identity, release=release):
|
|
cp = params(identity, release=release)
|
|
self.assertEqual(len(cp.safetyConfigs), 1)
|
|
self.assertEqual(str(cp.safetyConfigs[0].safetyModel), 'hyundaiCanfd')
|
|
self.assertEqual(cp.safetyConfigs[0].safetyParam, 0x11)
|
|
owner = structs.CarParams.SafetyConfig(safetyModel=str(cp.safetyConfigs[0].safetyModel),
|
|
safetyParam=int(cp.safetyConfigs[0].safetyParam))
|
|
cp.safetyConfigs = [structs.CarParams.SafetyConfig(safetyModel='noOutput'), owner]
|
|
self.assertTrue(qualified(cp))
|
|
policy = policy_for(cp)
|
|
self.assertTrue(policy.explicit_latch)
|
|
self.assertEqual(policy.safety_param_addition, 0x800)
|
|
cp.safetyConfigs[-1].safetyParam |= policy.safety_param_addition
|
|
self.assertTrue(qualified(cp, marked_only=True))
|
|
model = int(cp.safetyConfigs[-1].safetyModel.raw)
|
|
self.assertTrue(native_accepts_cp(cp, model, 0x811))
|
|
self.assertFalse(native_accepts_cp(cp, int(cp.safetyConfigs[0].safetyModel.raw), 0))
|
|
self.assertFalse(native_accepts_cp(cp, model, 0x891))
|
|
for word in (0x15, 0x815, 0x811 | 0x4000):
|
|
bad = cp.as_reader().as_builder()
|
|
bad.safetyConfigs[-1].safetyParam = word
|
|
self.assertFalse(qualified(bad))
|
|
self.assertFalse(native_accepts_cp(bad, model, word))
|
|
|
|
def test_physical_intent_neutral_press_cancel_and_health(self):
|
|
for identity in STOCK_EV_CARS:
|
|
cp = params(identity)
|
|
intent = create_intent(cp, AolSettings(True, 0., AOL_TOGGLE, AOL_TOGGLE, (0, 0, 0), (0, 0, 0)))
|
|
cs = structs.CarState(canValid=True, gearShifter='drive')
|
|
cs.cruiseState.available = True
|
|
intent.update(cs, now_ns=1, fault_active=False)
|
|
self.assertFalse(intent.allowed_latch)
|
|
cs.buttonEvents = [structs.CarState.ButtonEvent(type='mainCruise', pressed=True)]
|
|
intent.update(cs, now_ns=2, fault_active=False)
|
|
self.assertTrue(intent.allowed_latch)
|
|
cs.buttonEvents = [structs.CarState.ButtonEvent(type='cancel', pressed=True)]
|
|
intent.update(cs, now_ns=3, fault_active=False)
|
|
# Unassigned cruise CANCEL withdraws ACC, not separately mapped lateral.
|
|
self.assertTrue(intent.allowed_latch)
|
|
cs.canValid = False
|
|
intent.update(cs, now_ns=4, fault_active=False)
|
|
self.assertFalse(intent.output(cs)[0])
|