mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-04 19:43:49 +08:00
Restore flashed Volt LKAS button mapping
This commit is contained in:
@@ -70,6 +70,8 @@ class CarState(CarStateBase):
|
||||
self.buttons_counter = 0
|
||||
|
||||
self.distance_button = 0
|
||||
self.flashed_volt_profile = is_volt_flashed_profile(CP)
|
||||
self.flashed_lkas_button = None
|
||||
self.pedal_sensor_healthy = False
|
||||
self.pedal_sensor_ts_nanos = 0
|
||||
self.bolt_pedal_gear_ts_nanos = 0
|
||||
@@ -535,7 +537,7 @@ class CarState(CarStateBase):
|
||||
# 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
|
||||
if is_volt_flashed_profile(self.CP):
|
||||
if self.flashed_volt_profile:
|
||||
# There is no stock cruise/ACC controller. Preserve the actual EBCM fault.
|
||||
ret.accFaulted = friction_unavailable
|
||||
ret.brakePressed |= bool(pt_cp.vl["ECMEngineStatus"]["BrakePressed"])
|
||||
@@ -684,6 +686,15 @@ class CarState(CarStateBase):
|
||||
ret.buttonEvents = [event for old, new in edges for event in
|
||||
create_button_events(new, old, BUTTONS_DICT, unpressed_btn=CruiseButtons.UNPRESS)] + create_button_events(
|
||||
self.distance_button, prev_distance_button, {1: ButtonType.gapAdjustCruise})
|
||||
if self.flashed_volt_profile:
|
||||
lkas_events = []
|
||||
for pressed in pt_cp.vl_all["ASCMSteeringButton"]["LKAButton"]:
|
||||
if self.flashed_lkas_button is not None:
|
||||
lkas_events.extend(create_button_events(pressed, self.flashed_lkas_button, {1: ButtonType.lkas}))
|
||||
self.flashed_lkas_button = pressed
|
||||
if lkas_events:
|
||||
ret.buttonEvents = [event.to_dict() for event in ret.buttonEvents] + lkas_events
|
||||
|
||||
if ret.vEgo < self.CP.minSteerSpeed:
|
||||
ret.lowSpeedAlert = True
|
||||
|
||||
|
||||
@@ -4,17 +4,17 @@ import math
|
||||
from opendbc.car.gm.cancel_remap import aol_enabled, enabled as cancel_remap_enabled, supported as cancel_remap_supported
|
||||
|
||||
from opendbc.car.structs import CarParams
|
||||
from opendbc.car.gm.values import CAR, GMFlags, control_flags, camera_acc_pedal_profile, is_volt_ascm_longitudinal
|
||||
from opendbc.car.gm.values import CAR, GMFlags, control_flags, camera_acc_pedal_profile, is_volt_ascm_longitudinal, is_volt_flashed_profile
|
||||
from opendbc.car.gm.aol import GM_AOL_ALTERNATIVE_EXPERIENCE, GM_AOL_WORDS, qualified_gm
|
||||
from openpilot.starpilot.aol.policy import AolVehiclePolicy
|
||||
from openpilot.starpilot.aol.intent import AOL_TOGGLE, AolCardIntent
|
||||
from openpilot.starpilot.aol.intent import AOL_TOGGLE, PAUSE_LATERAL, AolCardIntent
|
||||
|
||||
|
||||
def policy_for(cp) -> AolVehiclePolicy:
|
||||
qualified = qualified_gm(cp)
|
||||
return AolVehiclePolicy(intent_supported=qualified, settings_supported=qualified,
|
||||
runtime_supported=qualified, normal_runtime_supported=qualified,
|
||||
lkas_button_supported=False,
|
||||
lkas_button_supported=qualified and is_volt_flashed_profile(cp),
|
||||
full_axis_runtime_required=qualified and aol_enabled(cp),
|
||||
alternative_experience_addition=GM_AOL_ALTERNATIVE_EXPERIENCE if qualified else 0)
|
||||
|
||||
@@ -205,7 +205,7 @@ class GmAolCardIntent(AolCardIntent):
|
||||
"""Follow physical MAIN; a current fault inhibits intent until healthy again."""
|
||||
|
||||
def __init__(self, settings, cp=None):
|
||||
super().__init__(settings, lkas_button_supported=False)
|
||||
super().__init__(settings, lkas_button_supported=is_volt_flashed_profile(cp))
|
||||
self.cp = cp
|
||||
self.requires_fault_observation = True
|
||||
self._main_cycle_required = False
|
||||
@@ -222,6 +222,12 @@ class GmAolCardIntent(AolCardIntent):
|
||||
semantic.buttonEvents = [event for event in CS.buttonEvents if str(event.type) != 'cancel']
|
||||
super().update_auxiliary(semantic, media=media, media_eligible=media_eligible, fault_active=fault_active)
|
||||
|
||||
@property
|
||||
def lkas_action(self):
|
||||
# MAIN still owns automatic arming; a mapped LKAS toggle pauses steering.
|
||||
action = super().lkas_action
|
||||
return PAUSE_LATERAL if action == AOL_TOGGLE else action
|
||||
|
||||
@property
|
||||
def main_action(self):
|
||||
# GM MAIN reports a persistent physical level, not an independent AOL toggle.
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
from opendbc.can import CANPacker
|
||||
from opendbc.car import Bus, structs
|
||||
from opendbc.car.gm.interface import CarInterface
|
||||
from opendbc.car.gm.tests.test_volt_flashed_obd import params as flashed_params, tick
|
||||
from opendbc.car.gm.values import DBC
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.starpilot.aol.intent import AolSettings
|
||||
from openpilot.starpilot.aol.tests.test_gm_startup_main import cases
|
||||
from openpilot.starpilot.aol.vehicle import create_intent, policy_for
|
||||
from openpilot.starpilot.controllers.wheel_actions import button_reported
|
||||
from openpilot.starpilot.ui.feature_settings_owner import FeatureSettingsOwner
|
||||
from openpilot.starpilot.ui.feature_settings_state import row_request
|
||||
|
||||
|
||||
def params():
|
||||
cp = flashed_params()
|
||||
cp.alternativeExperience = 32
|
||||
return cp
|
||||
|
||||
|
||||
def parser():
|
||||
cp = params()
|
||||
return CarInterface(cp), CANPacker(DBC[cp.carFingerprint][Bus.pt])
|
||||
|
||||
|
||||
def feed_lkas(ci, packer, levels, index, cruise=1):
|
||||
now = 1_000_000_000 + index * 10_000_000
|
||||
_, frames = tick(SimpleNamespace(update=lambda _: None), packer, now, index)
|
||||
frames = [m for m in frames if m[0] != 0x1E1]
|
||||
for level in levels:
|
||||
frames.append(packer.make_can_msg('ASCMSteeringButton', 0, {'ACCButtons': cruise, 'ACCAlwaysOne': 1,
|
||||
'LKAButton': level, 'RollingCounter': index % 4}))
|
||||
return ci.update([(now, frames)])
|
||||
|
||||
|
||||
def test_parser_emits_each_lkas_edge_without_cruise_enable():
|
||||
ci, packer = parser()
|
||||
for i in range(40):
|
||||
cs = feed_lkas(ci, packer, [0], i)
|
||||
assert cs.canValid
|
||||
cs = feed_lkas(ci, packer, [1, 0, 1, 1, 0], 40)
|
||||
assert [(str(b.type), b.pressed) for b in cs.buttonEvents] == [('lkas', True), ('lkas', False), ('lkas', True), ('lkas', False)]
|
||||
assert not cs.buttonEnable and not cs.cruiseState.enabled
|
||||
assert not feed_lkas(ci, packer, [], 41).buttonEvents
|
||||
|
||||
|
||||
def test_first_held_sample_is_not_a_new_press():
|
||||
ci, packer = parser()
|
||||
assert not feed_lkas(ci, packer, [1], 0).buttonEvents
|
||||
assert not feed_lkas(ci, packer, [1], 1).buttonEvents
|
||||
assert [(str(b.type), b.pressed) for b in feed_lkas(ci, packer, [0], 2).buttonEvents] == [('lkas', False)]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('mapping', [0, 3, 4, 9])
|
||||
def test_main_arms_at_startup_and_lkas_only_performs_its_mapping(mapping):
|
||||
cp = params()
|
||||
intent = create_intent(cp, AolSettings(True, 0., mapping, 0, (0, 0, 0), (0, 0, 0)), policy_for(cp))
|
||||
cs = structs.CarState(canValid=True, gearShifter='drive', vEgo=10.)
|
||||
cs.cruiseState.available = True
|
||||
intent.update(cs, now_ns=1, fault_active=False)
|
||||
assert intent.allowed_latch and not intent.pause_lateral and not intent.pause_longitudinal
|
||||
for pressed, now in [(True, 2), (False, 3)]:
|
||||
cs.buttonEvents = [structs.CarState.ButtonEvent(type='lkas', pressed=pressed)]
|
||||
intent.update(cs, now_ns=now, fault_active=False)
|
||||
assert intent.allowed_latch and intent.pause_lateral == (mapping in (3, 9))
|
||||
assert intent.pause_longitudinal == (mapping == 4)
|
||||
cs.buttonEvents = []
|
||||
intent.update(cs, now_ns=4, fault_active=False)
|
||||
assert intent.pause_lateral == (mapping in (3, 9))
|
||||
cs.buttonEvents = [structs.CarState.ButtonEvent(type='lkas', pressed=True)]
|
||||
intent.update(cs, now_ns=5, fault_active=False)
|
||||
assert not intent.pause_lateral and not intent.pause_longitudinal and intent.allowed_latch
|
||||
cs.cruiseState.available = False
|
||||
cs.buttonEvents = []
|
||||
intent.update(cs, now_ns=6, fault_active=False)
|
||||
assert not intent.allowed_latch
|
||||
|
||||
|
||||
def test_lkas_row_is_visible_and_assignment_uses_actual_settings_owner(tmp_path):
|
||||
cp = params()
|
||||
saved = Params(str(tmp_path))
|
||||
owner = FeatureSettingsOwner(saved, lambda _: True, vehicle_fingerprint=lambda: str(cp.carFingerprint), vehicle_params=lambda: cp)
|
||||
page = owner.snapshot('wheel', parked=True, system_long=True, lateral_context=True, metric=False)
|
||||
row = next(r for r in page.rows if r.key == 'wheel:LKASButtonControl')
|
||||
assert row.value == 'Off' and row.available and 'Pause steering' in row.choices and 'Toggle AOL' in row.choices
|
||||
assert owner.apply(row_request(row, 'Pause steering'))
|
||||
assert saved.get('LKASButtonControl') == 3
|
||||
|
||||
|
||||
def test_other_gm_profiles_keep_the_existing_lkas_contract():
|
||||
for cp in cases():
|
||||
assert not policy_for(cp).lkas_button_supported
|
||||
assert not button_reported(cp, 'LKASButtonControl')
|
||||
|
||||
|
||||
def test_lkas_does_not_erase_a_simultaneous_set_release():
|
||||
ci, packer = parser()
|
||||
for i in range(40):
|
||||
feed_lkas(ci, packer, [0], i)
|
||||
feed_lkas(ci, packer, [0], 40, cruise=3)
|
||||
cs = feed_lkas(ci, packer, [1], 41)
|
||||
assert cs.buttonEnable
|
||||
assert [(str(b.type), b.pressed) for b in cs.buttonEvents] == [('decelCruise', False), ('lkas', True)]
|
||||
@@ -68,7 +68,10 @@ def button_reported(cp, key):
|
||||
cp.flags & TeslaFlags.AOL_SCREEN_BUTTON)
|
||||
return bool(key in KEYS[5:8] and cp.carFingerprint == CAR.TESLA_MODEL_S_PREAP)
|
||||
if key == 'LKASButtonControl':
|
||||
if brand in ('chrysler', 'gm', 'mazda', 'nissan', 'volkswagen', 'volvo'):
|
||||
if brand == 'gm':
|
||||
from opendbc.car.gm.values import is_volt_flashed_profile
|
||||
return is_volt_flashed_profile(cp)
|
||||
if brand in ('chrysler', 'mazda', 'nissan', 'volkswagen', 'volvo'):
|
||||
return False
|
||||
if brand == 'hyundai':
|
||||
from opendbc.car.hyundai.values import CAR, HyundaiFlags, is_blended
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"protected_inventory_sha256": "dde91e1ce9c780f132c91438b2fb0559f51132e10dea387a6c1f64a03f2da779", "schema_version": 1}
|
||||
{"protected_inventory_sha256": "576253242aefccbd2c9bb70dccf54b8ac10c06832c285e686e0105bacce2fd6c", "schema_version": 1}
|
||||
|
||||
Reference in New Issue
Block a user