Reuse exact GM configuration checks in driving hot paths

This commit is contained in:
firestar5683
2026-10-31 17:00:37 -05:00
parent b6e25bfa6d
commit ddd67e58bc
4 changed files with 90 additions and 17 deletions
+15 -13
View File
@@ -136,6 +136,8 @@ class CarState(CarStateBase):
return self.car_gps_tracker.get()
def update(self, can_parsers) -> structs.CarState:
bolt_pedal_profile = is_bolt_pedal_profile(self.CP)
volt_camera_removed = is_volt_camera_removed(self.CP)
pt_cp = can_parsers[Bus.pt]
cam_cp = can_parsers[Bus.cam]
loopback_cp = can_parsers[Bus.loopback]
@@ -157,7 +159,7 @@ class CarState(CarStateBase):
self.bolt_pedal_removed_stock_active = bool(pt_cp.vl["ECMCruiseControl"]["CruiseActive"])
present_no_acc_pedal = (is_bolt_present_no_acc_pedal_profile(self.CP) or
is_bolt_present_no_acc_pedal_profile(self.CP, stock_only=True))
if is_bolt_pedal_profile(self.CP) or present_no_acc_pedal:
if bolt_pedal_profile or present_no_acc_pedal:
self.bolt_pedal_gear_ts_nanos = (self.conventional_cancel_credit.gear_ns if present_no_acc_pedal else
pt_cp.ts_nanos["ECMPRDNL2"]["PRNDL2"])
self.bolt_pedal_main_ts_nanos = pt_cp.ts_nanos["ECMEngineStatus"]["CruiseMainOn"]
@@ -233,7 +235,7 @@ class CarState(CarStateBase):
("ASCMSteeringButton", "RollingCounter"), ("ECMPRDNL2", "PRNDL2"))
self.ordinary_removed_sources = tuple(pt_cp.ts_nanos[name][field] for name, field in names)
if (is_volt_camera_removed(self.CP) or self.camera_pedal_profile is not None and
if (volt_camera_removed or self.camera_pedal_profile is not None and
self.camera_pedal_profile.topology in ("gateway", "ascm", "sdgm") and not self.camera_pedal_profile.longitudinal):
names = (("PSCMStatus", "LKATorqueDelivered"), ("EBCMWheelSpdRear", "RLWheelSpd"),
("AcceleratorPedal2", "CruiseState"), ("ECMEngineStatus", "CruiseMainOn"),
@@ -308,7 +310,7 @@ class CarState(CarStateBase):
if is_volt_longitudinal(self.CP):
# Observe only actual resume/driver sources, using the finalized brake owner.
alternate = is_volt_gateway_alternate_brake(self.CP) or (
is_volt_camera_removed(self.CP) and bool(self.CP.flags & GMFlags.NO_ACCELERATOR_POS_MSG))
volt_camera_removed and bool(self.CP.flags & GMFlags.NO_ACCELERATOR_POS_MSG))
c9 = self.CP.networkLocation == NetworkLocation.fwdCamera and not (
gm_control_word(self.CP) & (GMSafetyFlags.ASCM_INTERCEPT | GMSafetyFlags.SDGM) and
not gm_control_word(self.CP) & GMSafetyFlags.BRAKE_C9)
@@ -328,7 +330,7 @@ class CarState(CarStateBase):
gm_auto_hold = is_gm_auto_hold(self.CP)
if gm_auto_hold:
alternate = is_volt_gateway_alternate_brake(self.CP)
alternate_force = alternate or (is_volt_camera_removed(self.CP) and bool(self.CP.flags & GMFlags.NO_ACCELERATOR_POS_MSG)) or (
alternate_force = alternate or (volt_camera_removed and bool(self.CP.flags & GMFlags.NO_ACCELERATOR_POS_MSG)) or (
self.camera_pedal_profile is not None and self.camera_pedal_profile.volt and
self.camera_pedal_profile.brake_source == BrakeSource.F1)
c9 = self.CP.networkLocation == NetworkLocation.fwdCamera and (
@@ -387,7 +389,7 @@ class CarState(CarStateBase):
not (self.hybrid_profile is not None and self.hybrid_profile.removed) and not removed_pedal):
if not is_conventional_cc_pedal_profile(self.CP):
self.pt_lka_steering_cmd_counter = pt_cp.vl["ASCMLKASteeringCmd"]["RollingCounter"]
if not self.bolt_cc_removed and not is_volt_camera_removed(self.CP) and not is_ordinary_camera_removed(self.CP):
if not self.bolt_cc_removed and not volt_camera_removed and not is_ordinary_camera_removed(self.CP):
self.cam_lka_steering_cmd_counter = cam_cp.vl["ASCMLKASteeringCmd"]["RollingCounter"]
# This is to avoid a fault where you engage while still moving backwards after shifting to D.
@@ -428,7 +430,7 @@ class CarState(CarStateBase):
ret.brakePressed = (pt_cp.vl["EBCMBrakePedalPosition"]["BrakePedalPosition"] / 0xD0 >= .10
if self.CP.flags & GMFlags.NO_ACCELERATOR_POS_MSG else
pt_cp.vl["ECMAcceleratorPos"]["BrakePedalPos"] >= 8)
elif is_volt_camera_removed(self.CP):
elif volt_camera_removed:
ret.brakePressed = pt_cp.vl["ECMEngineStatus"]["BrakePressed"] != 0
elif is_volt_gateway_alternate_brake(self.CP):
pedal_position = pt_cp.vl["EBCMBrakePedalPosition"]["BrakePedalPosition"]
@@ -489,7 +491,7 @@ class CarState(CarStateBase):
self.pedal_sensor_ts_nanos = 0
self.pedal_sensor_counter = None
if self.pedal_sensor_healthy:
if is_bolt_pedal_profile(self.CP):
if bolt_pedal_profile:
ret.gasPressed = first + second > 1190
elif self.camera_pedal_profile is not None and self.camera_pedal_profile.longitudinal:
ret.gasPressed = ret.gasPressed or first + second > 1190
@@ -517,7 +519,7 @@ class CarState(CarStateBase):
# 1 - latched
ret.seatbeltUnlatched = pt_cp.vl["BCMDoorBeltStatus"]["LeftSeatBelt"] == 0
if int(self.CP.safetyConfigs[0].safetyParam) == 0x1CD and is_bolt_pedal_profile(self.CP):
if int(self.CP.safetyConfigs[0].safetyParam) == 0x1CD and bolt_pedal_profile:
self.bolt_acc_brake_clock_ns = cam_cp.ts_nanos["EBCMFrictionBrakeCmd"]["RollingCounter"]
self.bolt_acc_brake_clock_counter = int(cam_cp.vl["EBCMFrictionBrakeCmd"]["RollingCounter"])
@@ -536,7 +538,7 @@ class CarState(CarStateBase):
ret.accFaulted = acc_state == AccState.FAULTED or (friction_unavailable and not secondary_only)
ret.cruiseState.enabled = pt_cp.vl["AcceleratorPedal2"]["CruiseState"] != AccState.OFF
if is_volt_camera_removed(self.CP):
if volt_camera_removed:
# A missing camera can leave the ECU faulted; that is not engaged cruise.
ret.cruiseState.enabled &= pt_cp.vl["AcceleratorPedal2"]["CruiseState"] != AccState.FAULTED
ret.cruiseState.standstill = pt_cp.vl["AcceleratorPedal2"]["CruiseState"] == AccState.STANDSTILL
@@ -571,7 +573,7 @@ class CarState(CarStateBase):
if self.CP.carFingerprint in NO_ACC_BOLT_CAR and not self.bolt_cc_profile:
ret.accFaulted = False
ret.cruiseState.enabled = pt_cp.vl["ECMCruiseControl"]["CruiseActive"] != 0 if pedal_stock_no_acc else False
if is_bolt_pedal_profile(self.CP):
if bolt_pedal_profile:
self.bolt_pedal_standstill_ts_nanos = pt_cp.ts_nanos["AcceleratorPedal2"]["CruiseState"]
stamp = self.bolt_pedal_standstill_ts_nanos
ret.cruiseState.standstill = (0 < stamp <= pt_cp._last_update_nanos and
@@ -580,7 +582,7 @@ class CarState(CarStateBase):
else:
ret.cruiseState.standstill = False
if (self.hybrid_profile is None and not removed_pedal and self.volt_cc_pedal_profile is None and self.CP.networkLocation == NetworkLocation.fwdCamera
and not is_volt_camera_removed(self.CP)
and not volt_camera_removed
and not is_conventional_cc_pedal_profile(self.CP) and not is_ordinary_camera_removed(self.CP)
and not (self.camera_pedal_profile is not None and self.camera_pedal_profile.removed)):
if (self.CP.carFingerprint not in ALT_ACCS or self.camera_pedal_profile is not None or is_ordinary_camera_profile(self.CP) or
@@ -611,13 +613,13 @@ class CarState(CarStateBase):
if (self.CP.carFingerprint in (ORDINARY_ASCM_CAR | ORDINARY_SDGM_CAR) or
is_ordinary_camera_profile(self.CP) or is_ordinary_camera_profile(self.CP, longitudinal=True) or
self.CP.carFingerprint in (CAR.CHEVROLET_VOLT_ASCM, CAR.CHEVROLET_VOLT_CAMERA, CAR.CHEVROLET_VOLT_2019)) and not is_volt_camera_removed(self.CP) and \
self.CP.carFingerprint in (CAR.CHEVROLET_VOLT_ASCM, CAR.CHEVROLET_VOLT_CAMERA, CAR.CHEVROLET_VOLT_2019)) and not volt_camera_removed and \
not is_ordinary_camera_removed(self.CP):
self.stock_fcw_alert = int(cam_cp.vl["ASCMActiveCruiseControlStatus"]["FCWAlert"]) & 0x3
ret.stockFcw = self.stock_fcw_alert != 0
if (self.CP.carFingerprint == CAR.CHEVROLET_BOLT_ACC_2022_2023_PEDAL and
is_bolt_pedal_profile(self.CP) and not removed_pedal):
bolt_pedal_profile and not removed_pedal):
self.stock_fcw_alert = int(cam_cp.vl["ASCMActiveCruiseControlStatus"]["FCWAlert"]) & 0x3
ret.stockFcw = self.stock_fcw_alert != 0
@@ -1,5 +1,6 @@
"""Optional planner owners follow the finalized GM driving ownership."""
from opendbc.car.config_cache import cached_config
from opendbc.car.gm.lateral import lane_centering_supported
from opendbc.car.gm.suburban import stopping_decel_rate
from opendbc.car.gm.values import (malibu_hybrid_profile, camera_acc_pedal_profile, control_flags, CAR, GMFlags, GMSafetyFlags,
@@ -20,15 +21,20 @@ def longitudinal_supported(cp) -> bool:
try:
if not _healthy(cp) or not cp.openpilotLongitudinalControl or cp.pcmCruise:
return False
return (volt_cc_pedal_profile(cp) is not None or camera_acc_pedal_profile(cp) is not None or is_ordinary_camera_profile(cp, longitudinal=True) or
return _longitudinal_owner(cp)
except (AttributeError, IndexError, TypeError, ValueError):
return False
@cached_config
def _longitudinal_owner(cp) -> bool:
return (volt_cc_pedal_profile(cp) is not None or camera_acc_pedal_profile(cp) is not None or is_ordinary_camera_profile(cp, longitudinal=True) or
is_ordinary_cc_profile(cp) or is_conventional_cc_pedal_profile(cp) or malibu_hybrid_profile(cp) is not None or
is_ordinary_ascm_profile(cp, longitudinal=True) or is_ordinary_sdgm_profile(cp, longitudinal=True)
or is_volt_longitudinal(cp) or is_volt_cc_longitudinal(cp) or is_bolt_euv_longitudinal(cp) or
is_bolt_pedal_profile(cp) or
(control_flags(cp) == int(GMFlags.CC_LONG) and is_bolt_cc_profile(cp)) or
(control_flags(cp) == 0 and stopping_decel_rate(cp) is not None))
except (AttributeError, IndexError, TypeError, ValueError):
return False
def display_supported(cp) -> bool:
@@ -0,0 +1,65 @@
"""Static admission remains exact; live authority is never cached."""
from types import SimpleNamespace
from unittest.mock import patch
import pytest
from opendbc.car.gm import feature_capabilities as capabilities
from opendbc.car.gm.tests.test_bolt_pedal import params
from opendbc.car.gm.values import CAR, is_bolt_pedal_profile
from opendbc.car.gm.interface import CarInterface
from openpilot.starpilot.aol.tests.test_gm import _configurations
from openpilot.starpilot.aol.tests.test_gm_held_native import parse, NOW
def uncached(cp):
return bool(capabilities._healthy(cp) and cp.openpilotLongitudinalControl and not cp.pcmCruise and
capabilities._longitudinal_owner.__wrapped__(cp))
def test_all_finalized_gm_profiles_keep_their_original_capability():
for cp in _configurations():
assert capabilities.longitudinal_supported(cp) == uncached(cp)
assert capabilities.longitudinal_supported(cp.as_reader()) == uncached(cp)
assert capabilities._longitudinal_owner.cache_info().currsize <= 8
@pytest.mark.parametrize('field,value', [('brand', 'hyundai'), ('carFingerprint', 'unknown'), ('flags', 0),
('passive', True), ('dashcamOnly', True), ('notCar', True), ('pcmCruise', True),
('openpilotLongitudinalControl', False), ('alphaLongitudinalAvailable', True), ('networkLocation', 'gateway'),
('safetyParam', 0), ('safetyModel', 'noOutput'), ('safetyConfigs', []), ('alternativeExperience', 1)])
def test_configuration_mutations_never_reuse_an_old_capability(field, value):
cp = params(CAR.CHEVROLET_BOLT_CC_2018_2021, pedal=True, camera=True)
alias = cp.as_reader()
assert capabilities.longitudinal_supported(cp)
if field in ('safetyParam', 'safetyModel'):
setattr(cp.safetyConfigs[0], field, value)
else:
setattr(cp, field, value)
assert capabilities.longitudinal_supported(cp) == uncached(cp)
assert capabilities.longitudinal_supported(alias) == uncached(cp)
def test_other_brands_and_stock_longitudinal_skip_snapshot_work():
cp = params(CAR.CHEVROLET_BOLT_CC_2018_2021, pedal=True, camera=True)
for brand, stock in [('hyundai', False), ('honda', False), ('gm', True)]:
cp.brand = brand
cp.openpilotLongitudinalControl = not stock
with patch.object(capabilities, '_longitudinal_owner', side_effect=AssertionError('unnecessary ownership snapshot')):
assert not capabilities.longitudinal_supported(cp)
def test_carstate_qualifies_once_per_sample_and_rechecks_next_sample():
cp = params(CAR.CHEVROLET_BOLT_CC_2018_2021, pedal=True, camera=True)
ci = CarInterface(cp)
shell = SimpleNamespace(CP=cp)
for tick in range(40):
stamp = NOW + tick * 10_000_000
ci.update([(stamp, parse(shell, stamp, counter=tick % 4, packets_only=True))])
with patch('opendbc.car.gm.carstate.is_bolt_pedal_profile', wraps=is_bolt_pedal_profile) as qualify:
for tick, blocked in enumerate((False, True, False), 40):
ci.CS.CP.notCar = blocked
stamp = NOW + tick * 10_000_000
before = len(qualify.call_args_list)
ci.update([(stamp, parse(shell, stamp, counter=tick % 4, packets_only=True))])
current = [call for call in qualify.call_args_list[before:] if not call.kwargs.get('stock_only', False)]
assert len(current) == 1
assert is_bolt_pedal_profile(ci.CS.CP) is not blocked
+1 -1
View File
@@ -1 +1 @@
{"protected_inventory_sha256": "dabfff0be2893804d33116e4de36581871df656eba9f080a56dacc251284802d", "schema_version": 1}
{"protected_inventory_sha256": "59cca55bbc8f9f8d42bee954161022f1014f9087f480d4b0b77ff6b27116542a", "schema_version": 1}