Capture F1 Volt withdrawal receipts in Card

This commit is contained in:
firestar5683
2026-10-21 10:18:27 -05:00
parent 9de201d18d
commit e9abadd2f4
4 changed files with 52 additions and 9 deletions
+3 -1
View File
@@ -488,10 +488,12 @@ class Car:
# Update carState from CAN
CS = self.CI.update(can_list)
from openpilot.starpilot.car.gm.aol import f1_conventional_lateral_owner
cancel_boot_ns = (time.clock_gettime_ns(time.CLOCK_BOOTTIME)
if (getattr(self.CI.CS, 'ev6_aol_source_healthy', False) or
qualified_honda_stock_aol(self.CP, marked_only=True) or
qualified_gm(self.CP) and is_bolt_present_no_acc_pedal_profile(self.CP) and
qualified_gm(self.CP) and (is_bolt_present_no_acc_pedal_profile(self.CP) or
f1_conventional_lateral_owner(self.CP)) and
int(self.CP.alternativeExperience) in (32, 96)) else 0)
self.observe_ioniq6_long_authority(can_list, CS)
media_owner = getattr(self, 'ioniq6_media', None)
@@ -292,3 +292,40 @@ def test_f1_physical_withdrawal_keeps_only_current_granted_lateral(gesture, case
assert not current['aolAxisState'].longitudinalActive and not native.longitudinalAllowed
finally:
card.vehicle_startup.close()
@pytest.mark.parametrize('gesture', ['foot', 'analog', 'paddle'])
def test_f1_actual_state_update_binds_physical_receipt(gesture):
from openpilot.cereal import messaging
from openpilot.starpilot.aol.tests.test_gm import TestGmAol as GmCardFixture
now = 10_020_000_000
with OpenpilotPrefix(), ExitStack() as cleanup:
settings = Params()
settings.put_bool('AlwaysOnLateral', True, block=True)
card = GmCardFixture.card(params(), settings)
cleanup.callback(card.vehicle_startup.close)
packer = CANPacker(DBC[card.CP.carFingerprint][Bus.pt])
for i in range(100):
cs, _ = tick(card.CI, packer, now - 1_000_000_000 + i * 10_000_000, counter=i % 4, active=False)
class Capture:
def update(self, rows):
self.rows = rows
capture = Capture()
_, frames = tick(capture, packer, now, counter=0, active=False, brake=gesture == 'foot', analog=6 if gesture == 'analog' else 0, regen=gesture == 'paddle')
event = messaging.new_message('can', len(frames), valid=True, logMonoTime=now)
for dst, (address, data, bus) in zip(event.can, frames, strict=True):
dst.address, dst.dat, dst.src = address, data, bus
# Only CAN transport and clocks are fixtures; state_update parses the real bytes.
with (
patch('openpilot.selfdrive.car.card.messaging.drain_sock_raw', return_value=[event.to_bytes()]),
patch('openpilot.selfdrive.car.card.time.monotonic_ns', return_value=now),
patch('openpilot.selfdrive.car.card.time.clock_gettime_ns', return_value=now),
):
cs, _ = card.state_update(defer_radar=True)
assert cs.canValid and not cs.canTimeout
assert cs.brakePressed == (gesture in ('foot', 'analog')) and cs.regenBraking == (gesture == 'paddle')
observed = card._aol_can_observation
assert observed[0] is cs and observed[1:] == (now, now, now)
assert card.aol_gm_withdrawal_source(cs, now) == now
@@ -281,15 +281,19 @@ def exercise_f1(main_action=0, gesture='none'):
for a, data, bus in packets:
safety.safety_fwd_hook(bus, a)
assert safety.safety_rx_hook(native.make_CANPacket(a, bus, data))
cs = card.CI.update([(now, packets)])
raw = messaging.new_message('can', len(packets), valid=True, logMonoTime=now)
for dst, (address, data, bus) in zip(raw.can, packets, strict=True):
dst.address, dst.dat, dst.src = address, data, bus
with (
patch('openpilot.selfdrive.car.card.messaging.drain_sock_raw', return_value=[raw.to_bytes()]),
patch.object(card.sm, 'update', side_effect=lambda timeout, _now=now: receive_card(_now)),
patch('openpilot.selfdrive.car.card.time.monotonic_ns', return_value=now),
patch('openpilot.selfdrive.car.card.time.clock_gettime_ns', return_value=now),
):
cs, _ = card.state_update(defer_radar=True)
safety.safety_tick()
assert cs.canValid and not cs.canTimeout
receive_card(now)
card.update_cruise_speed(cs)
card._aol_can_observation = (cs, now, now, now)
fault = card.aol_disarming_fault(cs, int(card.sm.logMonoTime['onroadEvents']), now)
card.aol_card_intent.update(cs, fault_active=fault, now_ns=now)
card.observe_aol_calibration(cs, now, False)
assert card._aol_can_observation[0] is cs and card._aol_can_observation[1:] == (now, now, now)
allowed = card.aol_card_intent.output(cs)[0]
request = int(allowed) | (2 if sd.aol_axis_decision.desired_longitudinal else 0)
safety.aol_set_host_request(request)
+1 -1
View File
@@ -1 +1 @@
{"protected_inventory_sha256": "f3bc5b02144b32847406e289e06bdeec27313ed197780dac269c5d0d4444f823", "schema_version": 1}
{"protected_inventory_sha256": "723440ff36d2f3e497f2dcf510392adbb9e5c08b7b75f47a2763d86d560acc4e", "schema_version": 1}