Restore classic Hyundai AOL steering dashboard icons

This commit is contained in:
firestar5683
2026-10-20 21:43:04 -05:00
parent 5cf5637d65
commit ea916e50bd
5 changed files with 104 additions and 6 deletions
@@ -23,6 +23,7 @@ from opendbc.car.hyundai.hyundaicanfd import CanBus
from opendbc.car.hyundai.ray_pedal import create_ray_pedal_command, ray_pedal_gas, ray_pedal_enabled
from opendbc.car.hyundai.ioniq6_longitudinal import Ioniq6LongitudinalPolicy
from opendbc.car.hyundai.canfd_dash_icons import CanFDDashIcons
from opendbc.car.hyundai.classic_scc_aol import qualified as qualified_classic_stock_aol
from opendbc.car.hyundai.canfd_stock_aol import qualified as qualified_canfd_stock_aol
from opendbc.car.hyundai.ev6_aol import qualified as qualified_ev6_aol
from opendbc.car.hyundai.g90_longitudinal import G90LongitudinalPolicy
@@ -144,6 +145,8 @@ class CarController(CarControllerBase):
self.ioniq6_bsm_enabled = ioniq6_status
self.ev6_aol_status = CP.carFingerprint == CAR.KIA_EV6 and (qualified_canfd_stock_aol(CP) or qualified_ev6_aol(CP))
self.canfd_dash_icons = CanFDDashIcons() if ioniq6_status or self.torque_ev_scc_enabled or self.ev6_aol_status else None
self.classic_dash_icons = CanFDDashIcons() if qualified_classic_stock_aol(CP, marked_only=True) and CP.carFingerprint != CAR.KIA_RAY_EV else None
self.classic_lfa_icon = None
self.ioniq6_bsm_counter = 0
self.ioniq6_bsm_last_can_ns = 0
self._ray_pedal = ray_pedal_enabled(CP)
@@ -168,6 +171,8 @@ class CarController(CarControllerBase):
if self.CP.carFingerprint == CAR.KIA_EV6_2025 and self.CP.dashcamOnly:
return actuators.as_builder(), []
hud_control = CC.hudControl
if self.classic_dash_icons is not None:
self.classic_lfa_icon = self.classic_dash_icons.update(self.frame, CC.enabled, CC.latActive)
if self.CP.carFingerprint == CAR.KIA_RAY_EV:
if CC.latActive:
self._ray_disengage_frame = None
@@ -316,7 +321,8 @@ class CarController(CarControllerBase):
torque_fault, CS.lkas11, sys_warning, sys_state, hud_enabled,
hud_control.leftLaneVisible, hud_control.rightLaneVisible,
left_lane_warning, right_lane_warning,
ray_lka_icon=(self._ray_lfa_icon or 1) if self.CP.carFingerprint == CAR.KIA_RAY_EV else None))
ray_lka_icon=(self._ray_lfa_icon or 1) if self.CP.carFingerprint == CAR.KIA_RAY_EV else None,
aol_lka_icon=(self.classic_lfa_icon or 1) if self.classic_lfa_icon is not None else None))
if _projection is not None and can_sends:
if not is_blended(self.CP) and (self.CP.carFingerprint != CAR.KIA_RAY_EV or self._ray_lkas11_active):
_projection.emit('hyundai.LKAS11', apply_torque, apply_steer_req, can_sends[-1])
@@ -365,7 +371,7 @@ class CarController(CarControllerBase):
lfa_icon = 2 if CC.enabled or CC.latActive else 3 if disengaging else 0
can_sends.append(hyundaican.create_blended_lfahda(self.packer, self.CAN, self.frame, lfa_icon))
else:
can_sends.append(hyundaican.create_lfahda_mfc(self.packer, CC.enabled))
can_sends.append(hyundaican.create_lfahda_mfc(self.packer, CC.enabled, lfa_icon=self.classic_lfa_icon))
# 5 Hz ACC options
if self.frame % 20 == 0 and self.CP.openpilotLongitudinalControl and not self._ray_pedal and self.blended_longitudinal is None:
@@ -9,7 +9,7 @@ hyundai_checksum = mk_crc8_fun(CRC8J1850, init_crc=0xFD, xor_out=0xDF)
def create_lkas11(packer, frame, CP, apply_torque, steer_req,
torque_fault, lkas11, sys_warning, sys_state, enabled,
left_lane, right_lane,
left_lane_depart, right_lane_depart, ray_lka_icon=None):
left_lane_depart, right_lane_depart, ray_lka_icon=None, aol_lka_icon=None):
values = {s: lkas11[s] for s in [
"CF_Lkas_LdwsActivemode",
"CF_Lkas_LdwsSysState",
@@ -55,6 +55,8 @@ def create_lkas11(packer, frame, CP, apply_torque, steer_req,
values["CF_Lkas_FcwOpt_USM"] = 2 if enabled else 1
if CP.carFingerprint == CAR.KIA_RAY_EV and ray_lka_icon is not None:
values["CF_Lkas_FcwOpt_USM"] = ray_lka_icon
if aol_lka_icon is not None:
values["CF_Lkas_FcwOpt_USM"] = aol_lka_icon
# SysWarning 4 = keep hands on wheel
# SysWarning 5 = keep hands on wheel (red)
@@ -123,9 +125,9 @@ def create_clu11(packer, frame, clu11, button, CP):
return packer.make_can_msg("CLU11", bus, values)
def create_lfahda_mfc(packer, enabled):
def create_lfahda_mfc(packer, enabled, *, lfa_icon=None):
values = {
"LFA_Icon_State": 2 if enabled else 0,
"LFA_Icon_State": (2 if enabled else 0) if lfa_icon is None else lfa_icon,
}
return packer.make_can_msg("LFAHDA_MFC", 0, values)
@@ -0,0 +1,89 @@
import pytest
from opendbc.can import CANParser
from opendbc.car import Bus, gen_empty_fingerprint, structs
from opendbc.car.hyundai.classic_scc_aol import aol_word, qualified
from opendbc.car.hyundai.interface import CarInterface
from opendbc.car.hyundai.values import CAR, DBC
from opendbc.safety.tests.libsafety.libsafety_py import make_CANPacket
from opendbc.safety.tests import test_hyundai_classic_scc_aol as native_fixture
def controller(identity=CAR.HYUNDAI_SONATA_HYBRID, *, marked=True):
fp = gen_empty_fingerprint()
fp[0][0x391] = 8
fp[2][0x485] = 4
cp = CarInterface.get_params(identity, fp, [], False, False, False)
if marked:
cp.safetyConfigs[0].safetyParam = aol_word(cp)
cp.alternativeExperience = 32
assert qualified(cp, marked_only=True)
ci = CarInterface(cp)
ci.update([])
parser = CANParser(DBC[identity][Bus.pt], [('LKAS11', 0), ('LFAHDA_MFC', 0)], 0)
return ci, parser
def step(ci, parser, *, enabled=False, lateral=False):
cc = structs.CarControl(enabled=enabled, latActive=lateral)
frame = ci.CC.frame
actuators, packets = ci.CC.update(cc.as_reader(), ci.CS, 10_000_000_000 + frame * 10_000_000)
parser.update((10_000_000_000 + frame * 10_000_000, packets))
return actuators, packets
@pytest.mark.parametrize('icon', ['LKAS11', 'LFAHDA_MFC'])
def test_recorded_sonata_lateral_only_native_permission_matches_active_dash(icon):
case = native_fixture.TestHyundaiClassicSccAol(methodName='runTest')
case.setUp()
try:
ci, parser = controller()
assert ci.CP.safetyConfigs[0].safetyParam == 0xC02
assert not ci.CP.openpilotLongitudinalControl and ci.CP.pcmCruise
case.reset(0xC02)
for _ in range(6):
case.feed(0xC02, main=True, source='BCM_PO_11')
case.feed(0xC02, main=True, source='BCM_PO_11', pressed=True)
permission = case.request(1)
assert permission == 1 and case.safety.safety_config_valid()
assert not case.safety.get_controls_allowed()
actuators, packets = step(ci, parser, lateral=bool(permission & 1))
for address, data, bus in packets:
assert case.safety.safety_tx_hook(make_CANPacket(address, bus, data))
signal = 'CF_Lkas_FcwOpt_USM' if icon == 'LKAS11' else 'LFA_Icon_State'
assert parser.vl[icon][signal] == 2
assert actuators.torque == 0.0 and actuators.accel == 0.0
assert all(address not in (0x420, 0x421) for address, _, _ in packets)
finally:
case.tearDown()
@pytest.mark.parametrize('identity', [CAR.HYUNDAI_SONATA_HYBRID, CAR.HYUNDAI_SONATA, CAR.HYUNDAI_ELANTRA_2021, CAR.HYUNDAI_KONA_EV])
def test_qualified_classic_stock_icons_follow_actual_lateral_and_original_blink(identity):
ci, parser = controller(identity)
original = ci.CP.to_dict()
for frame in range(101):
step(ci, parser, lateral=frame == 0)
expected = 2 if frame == 0 else 3 if frame < 100 else 0
assert parser.vl['LKAS11']['CF_Lkas_FcwOpt_USM'] == (expected or 1)
if frame % 5 == 0:
assert parser.vl['LFAHDA_MFC']['LFA_Icon_State'] == expected
assert parser.vl['LKAS11']['CR_Lkas_StrToqReq'] == 0
assert parser.vl['LKAS11']['CF_Lkas_MsgCount'] == frame % 16
assert ci.CP.to_dict() == original
@pytest.mark.parametrize('marked', [False, True])
@pytest.mark.parametrize('enabled,lateral,lkas,lfa', [(False, False, 1, 0), (True, False, 2, 2), (True, True, 2, 2)])
def test_existing_ordinary_and_inactive_dash_behavior_is_preserved(marked, enabled, lateral, lkas, lfa):
ci, parser = controller(marked=marked)
step(ci, parser, enabled=enabled, lateral=lateral)
assert parser.vl['LKAS11']['CF_Lkas_FcwOpt_USM'] == lkas
assert parser.vl['LFAHDA_MFC']['LFA_Icon_State'] == lfa
def test_unmarked_configuration_does_not_gain_lateral_only_icon_override():
ci, parser = controller(marked=False)
step(ci, parser, lateral=True)
assert parser.vl['LKAS11']['CF_Lkas_FcwOpt_USM'] == 1
assert parser.vl['LFAHDA_MFC']['LFA_Icon_State'] == 0
+1 -1
View File
@@ -1 +1 @@
{"protected_inventory_sha256": "f7b1b124343980c9dac4009161c3fb323e22c80c46877348fcdc16ffe82a040e", "schema_version": 1}
{"protected_inventory_sha256": "9a2493649474b945d892fae1e9bba846cf1ff7420c07b88e543ac59b436581de", "schema_version": 1}
+1
View File
@@ -33,6 +33,7 @@ DEBUG_SAFETY_CLASS_TARGETS = {
RELEASE_TARGETS = (
"opendbc_repo/opendbc/car/hyundai/tests/test_classic_aol_dash.py",
"opendbc_repo/opendbc/car/hyundai/tests/test_g90_continuity.py",
"opendbc_repo/opendbc/car/hyundai/tests/test_disable_response.py",
"openpilot/starpilot/aol/tests/test_angle_stop_native_feedback.py",