mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-10-28 00:53:45 +08:00
Align source fixtures and cover composite MAIN freshness
This commit is contained in:
@@ -16,9 +16,9 @@ from openpilot.starpilot.car.toyota.prius_preferences import PriusFilterPreferen
|
||||
|
||||
def make_ci(identity, params, *, standstill=False):
|
||||
rack = structs.CarParams.CarFw.new_message(ecu=structs.CarParams.Ecu.eps,
|
||||
fwVersion=b'8965B47070' + bytes(6))
|
||||
fwVersion=b'8965B47070' + bytes(6), brand='toyota', address=0x7A1)
|
||||
cp = CarInterface.get_params(identity, {0: {0x2FF: 4}, 1: {}, 2: {}}, [rack], False, False, False)
|
||||
assert cp.safetyConfigs[0].safetyParam == 4169
|
||||
assert cp.safetyConfigs[0].safetyParam == 0xD049
|
||||
ci = CarInterface(cp)
|
||||
ci.CC.prius_filter_input = PriusFilterPreference(cp, params)
|
||||
state = structs.CarState(canValid=True, canTimeout=False, standstill=standstill,
|
||||
|
||||
@@ -12,12 +12,12 @@ def params(car, fp=None, alpha=False):
|
||||
class TestRetrofit(unittest.TestCase):
|
||||
def test_prius_smart_dsu_requires_exact_rack_and_source(self):
|
||||
from opendbc.car.structs import CarParams
|
||||
rack = CarParams.CarFw.new_message(ecu=CarParams.Ecu.eps, fwVersion=b'8965B47070\x00\x00\x00\x00\x00\x00')
|
||||
rack = CarParams.CarFw.new_message(ecu=CarParams.Ecu.eps, fwVersion=b'8965B47070\x00\x00\x00\x00\x00\x00', brand='toyota', address=0x7A1)
|
||||
from opendbc.car.toyota.prius_longitudinal import enabled
|
||||
from opendbc.car.toyota.prius_longitudinal import stopping_decel_rate
|
||||
for alpha in (False, True):
|
||||
cp = CarInterface.get_params(CAR.TOYOTA_PRIUS_RETROFIT, {0: {0x2FF: 4}, 1: {}, 2: {}}, [rack], alpha, False, False)
|
||||
self.assertEqual(cp.safetyConfigs[0].safetyParam, 4169)
|
||||
self.assertEqual(cp.safetyConfigs[0].safetyParam, 0xD049)
|
||||
self.assertTrue(enabled(cp))
|
||||
self.assertFalse(cp.dashcamOnly)
|
||||
self.assertTrue(cp.openpilotLongitudinalControl)
|
||||
@@ -29,14 +29,14 @@ class TestRetrofit(unittest.TestCase):
|
||||
automatic = CarInterface.get_params(CAR.TOYOTA_PRIUS, {0: {0x2FF: 4}, 1: {}, 2: {}}, [rack], False, False, False)
|
||||
self.assertTrue(enabled(automatic))
|
||||
self.assertEqual(automatic.carFingerprint, CAR.TOYOTA_PRIUS)
|
||||
self.assertEqual(automatic.safetyConfigs[0].safetyParam, 4169)
|
||||
self.assertEqual(automatic.safetyConfigs[0].safetyParam, 0xD049)
|
||||
self.assertFalse(automatic.flags & ToyotaFlags.TSS2)
|
||||
self.assertAlmostEqual(automatic.steerActuatorDelay, .14)
|
||||
from opendbc.car.toyota.prius_longitudinal import configured, prepare_stock
|
||||
self.assertTrue(prepare_stock(automatic))
|
||||
self.assertTrue(configured(automatic))
|
||||
self.assertFalse(enabled(automatic))
|
||||
self.assertEqual(automatic.safetyConfigs[0].safetyParam, 4681)
|
||||
self.assertEqual(automatic.safetyConfigs[0].safetyParam, 0xD249)
|
||||
self.assertFalse(automatic.openpilotLongitudinalControl)
|
||||
self.assertTrue(automatic.pcmCruise)
|
||||
self.assertTrue(prepare_stock(automatic))
|
||||
@@ -66,7 +66,7 @@ class TestRetrofit(unittest.TestCase):
|
||||
for field, value in (('passive', True), ('notCar', True), ('dashcamOnly', True),
|
||||
('pcmCruise', False), ('openpilotLongitudinalControl', True),
|
||||
('secOcRequired', True), ('flags', int(ToyotaFlags.GAS_INTERCEPTOR)),
|
||||
('carFingerprint', CAR.TOYOTA_COROLLA), ('alternativeExperience', 160)):
|
||||
('carFingerprint', CAR.TOYOTA_COROLLA), ('alternativeExperience', 96)):
|
||||
rejected = cp.as_reader().as_builder()
|
||||
setattr(rejected, field, value)
|
||||
self.assertFalse(qualified(rejected), field)
|
||||
@@ -75,7 +75,7 @@ class TestRetrofit(unittest.TestCase):
|
||||
rejected.safetyConfigs[0].safetyParam = word
|
||||
self.assertFalse(qualified(rejected), word)
|
||||
self.assertFalse(native_accepts_cp(rejected, int(structs.CarParams.SafetyModel.toyota), word), word)
|
||||
for ae in (0, 1, 33, 128, 160, 256, 288):
|
||||
for ae in (0, 1, 33, 128, 96, 256, 544):
|
||||
rejected = cp.as_reader().as_builder()
|
||||
rejected.alternativeExperience = ae
|
||||
self.assertFalse(qualified(rejected, marked_only=True), ae)
|
||||
@@ -89,7 +89,7 @@ class TestRetrofit(unittest.TestCase):
|
||||
rejected = cp.as_reader().as_builder()
|
||||
rejected.safetyConfigs[0].safetyModel = structs.CarParams.SafetyModel.noOutput
|
||||
self.assertFalse(qualified(rejected))
|
||||
for fp in ({0: {0x2FF: 8}, 1: {}, 2: {}}, {0: {}, 1: {}, 2: {0x343: 8}}):
|
||||
for fp in ({0: {0x2FF: 7}, 1: {}, 2: {}}, {0: {}, 1: {}, 2: {0x343: 8}}):
|
||||
takeover = params(CAR.TOYOTA_MATRIX_RETROFIT, fp, alpha)
|
||||
self.assertTrue(takeover.dashcamOnly)
|
||||
self.assertFalse(qualified(takeover))
|
||||
@@ -114,7 +114,7 @@ class TestRetrofit(unittest.TestCase):
|
||||
|
||||
def test_observed_takeover_requires_paired_port(self):
|
||||
for car in (CAR.TOYOTA_MATRIX_RETROFIT, CAR.TOYOTA_PRIUS_RETROFIT):
|
||||
for fp in ({0: {0x2FF: 8}, 1: {}, 2: {}},
|
||||
for fp in ({0: {0x2FF: 7}, 1: {}, 2: {}},
|
||||
{0: {}, 1: {}, 2: {0x343: 8}}):
|
||||
cp = params(car, fp, True)
|
||||
self.assertTrue(cp.dashcamOnly)
|
||||
@@ -133,7 +133,7 @@ class TestRetrofit(unittest.TestCase):
|
||||
|
||||
def test_retrofit_rack_is_distinct_from_standard_prius(self):
|
||||
from opendbc.car.structs import CarParams
|
||||
fw = CarParams.CarFw.new_message(ecu=CarParams.Ecu.eps, fwVersion=b'8965B47070\x00\x00\x00\x00\x00\x00')
|
||||
fw = CarParams.CarFw.new_message(ecu=CarParams.Ecu.eps, fwVersion=b'8965B47070\x00\x00\x00\x00\x00\x00', brand='toyota', address=0x7A1)
|
||||
fp = {0: {}, 1: {}, 2: {}}
|
||||
cp = CarInterface.get_params(CAR.TOYOTA_PRIUS_RETROFIT, fp, [fw], False, False, False)
|
||||
self.assertFalse(cp.dashcamOnly)
|
||||
@@ -170,7 +170,7 @@ class TestRetrofit(unittest.TestCase):
|
||||
from opendbc.car.toyota.values import DBC
|
||||
|
||||
rack = structs.CarParams.CarFw.new_message(ecu=structs.CarParams.Ecu.eps,
|
||||
fwVersion=b'8965B47070\x00\x00\x00\x00\x00\x00')
|
||||
fwVersion=b'8965B47070\x00\x00\x00\x00\x00\x00', brand='toyota', address=0x7A1)
|
||||
cases = ((CAR.TOYOTA_PRIUS, False, 'ACC_CONTROL', 'DISTANCE', 0),
|
||||
(CAR.TOYOTA_PRIUS_RETROFIT, False, 'ACC_CONTROL', 'DISTANCE', 0),
|
||||
(CAR.TOYOTA_PRIUS, True, 'SDSU', 'FD_BUTTON', 0),
|
||||
@@ -179,7 +179,7 @@ class TestRetrofit(unittest.TestCase):
|
||||
(CAR.TOYOTA_COROLLA_TSS2, False, 'ACC_CONTROL', 'DISTANCE', 2))
|
||||
for car, filtered, message, signal, bus in cases:
|
||||
with self.subTest(car=car, filtered=filtered):
|
||||
cp = CarInterface.get_params(car, {0: {0x2FF: 4} if filtered else {}, 1: {}, 2: {}},
|
||||
cp = CarInterface.get_params(car, {0: {0x2FF: 8} if filtered else {}, 1: {}, 2: {}},
|
||||
[rack] if filtered else [], False, False, False)
|
||||
cs = CarState(cp)
|
||||
parsers = cs.get_can_parsers(cp)
|
||||
|
||||
@@ -72,10 +72,10 @@ class TestZssCaller(unittest.TestCase):
|
||||
fwVersion=b'8965B47070' + bytes(6))
|
||||
cp = CarInterface.get_params(CAR.TOYOTA_PRIUS, {0: {0x23: 8, 0x2FF: 8}, 1: {}, 2: {}}, [rack], False, False, False)
|
||||
self.assertTrue(configured(cp))
|
||||
self.assertEqual(cp.safetyConfigs[0].safetyParam, 4169)
|
||||
self.assertEqual(cp.safetyConfigs[0].safetyParam, 0x8049)
|
||||
sibling = cp.as_reader().as_builder()
|
||||
sibling.flags |= 1 << 17
|
||||
self.assertFalse(configured(sibling))
|
||||
self.assertTrue(prepare_stock(cp))
|
||||
self.assertEqual(cp.safetyConfigs[0].safetyParam, 4681)
|
||||
self.assertEqual(cp.safetyConfigs[0].safetyParam, 0x8249)
|
||||
self.assertTrue(cp.flags & ToyotaFlags.ZSS)
|
||||
|
||||
@@ -55,7 +55,7 @@ class TestPairedPedal(unittest.TestCase):
|
||||
def test_factory_current_words_and_exact_negatives(self):
|
||||
self.assertTrue(pedal.configured(self.cp))
|
||||
self.assertEqual(self.cp.safetyConfigs[0].safetyParam, 0x2049)
|
||||
for fp in ({0: {0x201: 7}, 1: {}, 2: {}}, {0: {}, 1: {0x201: 6}, 2: {}}, {0: {0x201: 6, 0x2FF: 8}, 1: {}, 2: {}}):
|
||||
for fp in ({0: {0x201: 7}, 1: {}, 2: {}}, {0: {}, 1: {0x201: 6}, 2: {}}, {0: {0x201: 5, 0x2FF: 8}, 1: {}, 2: {}}):
|
||||
cp = CarInterface.get_params(self.candidate, fp, firmware(self.candidate), False, False, False)
|
||||
self.assertFalse(pedal.configured(cp))
|
||||
self.assertTrue(pedal.prepare_stock(self.cp))
|
||||
@@ -107,9 +107,9 @@ class TestPairedPedal(unittest.TestCase):
|
||||
self.safety.set_timer(1_300_001)
|
||||
self.assertFalse(self.tx(0.1))
|
||||
self.assertTrue(self.tx(0))
|
||||
for word in (0x2149, 0x2849, 0x3049, 0xA049):
|
||||
for word in (0x2149, 0x2849, 0x3048, 0xA048):
|
||||
self.init(word)
|
||||
self.assertFalse(self.tx(0))
|
||||
self.assertFalse(self.tx(0), hex(word))
|
||||
self.assertFalse(self.tx(0.1))
|
||||
|
||||
def test_native_command_pair_bounds_checksum_bus_and_neutral(self):
|
||||
|
||||
@@ -44,3 +44,59 @@ def test_parent_catalog_and_warm_switch_are_exact(word, parent):
|
||||
finally:
|
||||
safety.set_alternative_experience(0)
|
||||
safety.set_safety_hooks(structs.CarParams.SafetyModel.noOutput, 0)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('word', (0xF149, 0xF349, 0xF04D, 0xF24D))
|
||||
@pytest.mark.parametrize('fault', ('main_off', 'main_stale'))
|
||||
def test_composite_alternate_main_keeps_its_independent_freshness(word, fault):
|
||||
from opendbc.can import CANPacker
|
||||
from opendbc.car import Bus
|
||||
from opendbc.car.toyota import pedal
|
||||
from opendbc.car.toyota.values import CAR, DBC
|
||||
|
||||
safety = libsafety_py.libsafety
|
||||
safety.init_tests()
|
||||
safety.set_alternative_experience(32)
|
||||
assert safety.set_safety_hooks(structs.CarParams.SafetyModel.toyota, word) == 0
|
||||
safety.set_aol_test_heartbeat(True)
|
||||
identity = CAR.LEXUS_GS_F if word in (0xF149, 0xF349) else CAR.LEXUS_IS
|
||||
packer = CANPacker(DBC[identity][Bus.pt])
|
||||
now = 1_000_000
|
||||
counter = 0
|
||||
|
||||
def tick(*, main=True, omit_main=False):
|
||||
nonlocal now, counter
|
||||
now += 10_000
|
||||
safety.set_timer(now)
|
||||
frames = helpers.physical(packer, cruise=True)
|
||||
frames.append(packer.make_can_msg('PCS_HUD', 0, {}))
|
||||
frames.append(packer.make_can_msg('PCM_CRUISE_ALT', 0, {'UI_SET_SPEED': 90}))
|
||||
if not omit_main:
|
||||
frames.append(packer.make_can_msg('DSU_CRUISE', 0, {'MAIN_ON': main, 'SET_SPEED': 90}))
|
||||
address, data, bus = packer.make_can_msg('GAS_SENSOR', 0, {
|
||||
'INTERCEPTOR_GAS': 0, 'INTERCEPTOR_GAS2': 0, 'COUNTER_PEDAL': counter, 'STATE': 0})
|
||||
counter = (counter + 1) & 15
|
||||
data = bytearray(data)
|
||||
data[-1] = pedal.checksum(data)
|
||||
frames.append((address, bytes(data), bus))
|
||||
for address, data, bus in frames:
|
||||
safety.safety_rx_hook(libsafety_py.make_CANPacket(address, bus, data))
|
||||
safety.safety_tick()
|
||||
safety.aol_set_host_request(3)
|
||||
|
||||
try:
|
||||
assert safety.current_safety_config.rx_checks_len == 8
|
||||
for _ in range(30):
|
||||
tick()
|
||||
expected = 1 if word in (0xF349, 0xF24D) else 3
|
||||
assert safety.safety_config_valid()
|
||||
assert safety.aol_get_permission_mask() == expected
|
||||
for _ in range(40):
|
||||
tick(main=False, omit_main=fault == 'main_stale')
|
||||
assert safety.aol_get_permission_mask() == 0
|
||||
for _ in range(30):
|
||||
tick()
|
||||
assert safety.aol_get_permission_mask() == expected
|
||||
finally:
|
||||
safety.set_alternative_experience(0)
|
||||
safety.set_safety_hooks(structs.CarParams.SafetyModel.noOutput, 0)
|
||||
|
||||
@@ -123,18 +123,21 @@ def test_vehicle_fault_rearm_cannot_be_bypassed(factory, field):
|
||||
|
||||
|
||||
|
||||
def test_gm_resolved_fault_accepts_new_successful_engagement_only():
|
||||
def test_gm_resolved_fault_rearms_only_after_healthy_main_observation():
|
||||
owner, cs = GmAolCardIntent(SETTINGS), state()
|
||||
observe(owner, cs, 1, enabled=False, active=False)
|
||||
owner.update(cs, now_ns=2, fault_active=True)
|
||||
assert owner._main_cycle_required and not owner.allowed_latch
|
||||
owner.update(cs, now_ns=3, fault_active=False)
|
||||
assert owner._main_cycle_required and not owner.allowed_latch
|
||||
assert not owner._main_cycle_required and owner.allowed_latch
|
||||
observe(owner, cs, 3, active=False)
|
||||
assert owner._main_cycle_required and not owner.allowed_latch
|
||||
assert not owner._main_cycle_required and owner.allowed_latch
|
||||
observe(owner, cs, 4)
|
||||
assert owner.allowed_latch and not owner._main_cycle_required
|
||||
assert not owner.pause_lateral
|
||||
cs.cruiseState.available = False
|
||||
owner.update(cs, now_ns=5, fault_active=False)
|
||||
assert not owner.allowed_latch
|
||||
|
||||
|
||||
def test_physical_owners_cannot_be_forged_by_host_engagement():
|
||||
|
||||
@@ -866,7 +866,7 @@ class TestGmAol(unittest.TestCase):
|
||||
requested = []
|
||||
for tick in range(18):
|
||||
now = 1_000_000_000 + tick * 10_000_000
|
||||
out, sources = feed_car(ci, packer, now, counter=tick % 4, active=False, brake=True, regen=True)
|
||||
out, sources = feed_car(ci, packer, now, counter=tick % 4, active=False, brake=True, regen=True, eps_status=1)
|
||||
sources = [source for source in sources if source[0] not in (0x1C4, 0xBE, 0xF1)]
|
||||
sources.extend([packer.make_can_msg('AcceleratorPedal2', 0, {'CruiseState': 0}),
|
||||
packer.make_can_msg('ECMAcceleratorPos', 0, {'BrakePedalPos': 12}),
|
||||
|
||||
@@ -16,7 +16,7 @@ def test_complete_sdsu_cp_tunes_retained_for_advertisement(candidate, stock):
|
||||
fp[0][0x2FF] = 4
|
||||
new = CarInterface.get_params(candidate, fp, fw, False, False, False)
|
||||
assert legacy_advert_filter.enabled(new) and advert_filter.enabled(new)
|
||||
assert not toyota_auto_hold_supported(new)
|
||||
assert toyota_auto_hold_supported(new) == toyota_auto_hold_supported(old)
|
||||
if stock:
|
||||
assert rav4h_filter.prepare_stock(old) and advert_filter.prepare_stock(new)
|
||||
assert legacy_advert_filter.configured(new)
|
||||
|
||||
@@ -137,7 +137,7 @@ def test_toyota_default_gap_callback_saves_personality_once(native_session, monk
|
||||
runtime, session, ui, _, _ = native_session
|
||||
rack = structs.CarParams.CarFw.new_message(ecu=structs.CarParams.Ecu.eps,
|
||||
fwVersion=b'8965B47070\x00\x00\x00\x00\x00\x00')
|
||||
ui.CP = CarInterface.get_params(getattr(CAR, vehicle), {0: {0x2FF: 4} if filtered else {}, 1: {}, 2: {}},
|
||||
ui.CP = CarInterface.get_params(getattr(CAR, vehicle), {0: {0x2FF: 8} if filtered else {}, 1: {}, 2: {}},
|
||||
[rack] if filtered else [], False, False, False)
|
||||
ui.has_longitudinal_control = ui.CP.openpilotLongitudinalControl
|
||||
ui.personality = 1
|
||||
|
||||
@@ -218,6 +218,7 @@ def test_actual_main_source_reader_reuses_lifecycle_for_cache_and_persistence():
|
||||
'__getitem__': lambda self, key: cal,
|
||||
'all_checks': lambda self, keys: True,
|
||||
})()
|
||||
sm.seen = {'extrinsicsCalibration': True}
|
||||
sm.valid = {'extrinsicsCalibration': True}
|
||||
sm.logMonoTime = {'extrinsicsCalibration': BASE}
|
||||
sm.recv_time = {'extrinsicsCalibration': BASE / 1e9}
|
||||
@@ -250,7 +251,8 @@ def test_actual_main_source_reader_reuses_lifecycle_for_cache_and_persistence():
|
||||
assert persistence.current_sources('fresh-identity', fresh.source_epoch)[0] == 'fresh-identity'
|
||||
for tick in range(100):
|
||||
gap = BASE + (tick + 1) * 1_000_000_000
|
||||
assert not source_reader(gap).enabled
|
||||
retained = source_reader(gap)
|
||||
assert retained.enabled and retained.source_epoch == fresh.source_epoch
|
||||
sm.logMonoTime['extrinsicsCalibration'] = gap + 1
|
||||
sm.recv_time['extrinsicsCalibration'] = (gap + 1) / 1e9
|
||||
resumed = source_reader(gap + 1)
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"protected_inventory_sha256": "91232f8d24f79ff480b1bf29dfc58b1ec124af6001e6793a0326068b19192c18", "schema_version": 1}
|
||||
{"protected_inventory_sha256": "ffb6b1825429c5d33a8adecb7f88aa090fb9f21d84c94b9cac3e37267e6bd4f4", "schema_version": 1}
|
||||
|
||||
Reference in New Issue
Block a user