Files
StarPilot/openpilot/starpilot/ui/onroad_conditional.py
T
firestar5683 db1c5a7445 Fix startup locks and restore onroad behavior
Release inherited Params locks correctly across fork and exec. Preserve qualified lateral armed intent through temporary faults, restore the Big UI CEM gauge, improve speed typography, and hide unavailable CEM initialization text. Include matching device artifacts and focused regression coverage.
2026-10-13 19:44:58 -05:00

64 lines
3.2 KiB
Python

"""Short, source-bound labels for accepted conditional mode receipts."""
import pyray as rl
from openpilot.starpilot.conditional_mode.policy import ModeChoice, Reason
from openpilot.starpilot.ui.onroad_state import AlertSize
from openpilot.starpilot.ui.onroad_state import OnroadState
_CEM_HOLD_REASONS = {3: "cem_curve", 4: "cem_lead", 5: "cem_signal", 6: "cem_speed",
7: "cem_speed_limit", 8: "cem_stop"}
_CCM_HOLD_REASONS = {4: "ccm_lead", 6: "ccm_speed"}
_REASONS = {reason.value: (reason.name[4:] if reason.name.startswith(('CEM_', 'CCM_')) else reason.name).replace('_', ' ')
for reason in Reason}
_HIDDEN_REASONS = frozenset((Reason.SCENE_UNAVAILABLE.value, Reason.UNAVAILABLE.value))
def reason(state: OnroadState) -> str | None:
"""Resolve the accepted planner reason, including its authoritative held status."""
preview = state.visual_preview
if preview is not None and preview.cem_reason in ('CURVE', 'LEAD', 'STOP LIGHT', 'SPEED'):
return {'CURVE': 'cem_curve', 'LEAD': 'cem_lead', 'STOP LIGHT': 'cem_stop', 'SPEED': 'cem_speed'}[preview.cem_reason]
value = (state.conditional_effective if state.longitudinal_active else None) or getattr(state, 'conditional_perception', None)
if value is None or value.choice not in (ModeChoice.CEM, ModeChoice.CCM) or value.reason in _HIDDEN_REASONS:
return None
if value.reason == 'cem_hold' and value.choice is ModeChoice.CEM:
return _CEM_HOLD_REASONS.get(getattr(value, 'status_code', 0))
if value.reason == 'ccm_hold' and value.choice is ModeChoice.CCM:
return _CCM_HOLD_REASONS.get(getattr(value, 'status_code', 0))
return value.reason
def stop_active(state: OnroadState) -> bool:
"""One accepted stop state for the light icon and the conditional orange border."""
if state.alert.size == AlertSize.FULL or state.longitudinal_overridden:
return False
value = state.conditional_effective
preview = state.visual_preview
return bool(reason(state) == 'cem_stop' and
(preview is not None and preview.cem_reason == 'STOP LIGHT' or
state.longitudinal_active and value is not None and value.choice is ModeChoice.CEM and value.effective_experimental))
def status(state: OnroadState) -> tuple[str, str, rl.Color] | None:
preview = state.visual_preview
if preview is not None and preview.cem_reason in ('CURVE', 'LEAD', 'STOP LIGHT', 'SPEED'):
if state.alert.size == AlertSize.FULL:
return None
return 'CEM', f'PREVIEW {preview.cem_reason}', rl.Color(112, 192, 216, 255)
value = (state.conditional_effective if state.longitudinal_active else None) or getattr(state, 'conditional_perception', None)
if value is None or value.choice not in (ModeChoice.CEM, ModeChoice.CCM):
return None
if value.reason in _HIDDEN_REASONS or value.reason in ('no_trigger', 'manual_chill', 'manual_experimental', 'ccm_veto'):
return None
# The text is selected from known policy reasons, never rendered from wire text.
detail = _REASONS.get(reason(state))
if detail is None:
return None
family = 'CEM' if value.choice is ModeChoice.CEM else 'CCM'
color = rl.Color(112, 192, 216, 255) if value.effective_experimental else rl.Color(255, 155, 63, 255)
return family, detail, color