diff --git a/selfdrive/ui/lib/starpilot_status.py b/selfdrive/ui/lib/starpilot_status.py index 9a4510cbd..161c23457 100644 --- a/selfdrive/ui/lib/starpilot_status.py +++ b/selfdrive/ui/lib/starpilot_status.py @@ -27,10 +27,26 @@ def is_longitudinal_only_active(state: UIState) -> bool: return bool(state.sm["selfdriveState"].enabled and not car_control.latActive) +def _override_color_applies(state: UIState) -> bool: + """Only gray the status when the active control mode is being overridden.""" + if state.status != UIStatus.OVERRIDE: + return False + + events = state.sm["onroadEvents"] + lateral_override = any(getattr(event, "overrideLateral", False) for event in events) + longitudinal_override = any(getattr(event, "overrideLongitudinal", False) for event in events) + + if is_longitudinal_only_active(state): + return longitudinal_override + if state.always_on_lateral_active and not state.sm["selfdriveState"].enabled: + return lateral_override + return lateral_override or longitudinal_override + + def get_border_color(state: UIState): enabled = state.sm["selfdriveState"].enabled lateral_active = enabled or state.always_on_lateral_active - if state.status == UIStatus.OVERRIDE: + if _override_color_applies(state): return OVERRIDE_COLOR if is_longitudinal_only_active(state): return LONGITUDINAL_ONLY_COLOR @@ -59,7 +75,7 @@ def get_path_edge_color(state: UIState): def get_screen_edge_color(state: UIState): enabled = state.sm["selfdriveState"].enabled lateral_active = enabled or state.always_on_lateral_active - if state.status == UIStatus.OVERRIDE: + if _override_color_applies(state): return OVERRIDE_COLOR if is_longitudinal_only_active(state): return LONGITUDINAL_ONLY_COLOR diff --git a/selfdrive/ui/tests/test_starpilot_status.py b/selfdrive/ui/tests/test_starpilot_status.py index ea94c24ab..e2c4dc3c9 100644 --- a/selfdrive/ui/tests/test_starpilot_status.py +++ b/selfdrive/ui/tests/test_starpilot_status.py @@ -5,19 +5,21 @@ from openpilot.selfdrive.ui.lib.starpilot_status import ( ENGAGED_COLOR, LONGITUDINAL_ONLY_COLOR, AOL_COLOR, + OVERRIDE_COLOR, get_border_color, get_screen_edge_color, ) from openpilot.selfdrive.ui.ui_state import UIStatus -def _state(*, enabled=False, lat_active=False, aol=False): +def _state(*, enabled=False, lat_active=False, aol=False, status=None, events=()): return SimpleNamespace( sm={ "selfdriveState": SimpleNamespace(enabled=enabled, experimentalMode=False), "carControl": SimpleNamespace(latActive=lat_active), + "onroadEvents": events, }, - status=UIStatus.ENGAGED if enabled else UIStatus.DISENGAGED, + status=status if status is not None else (UIStatus.ENGAGED if enabled else UIStatus.DISENGAGED), always_on_lateral_active=aol, switchback_mode_enabled=False, traffic_mode_enabled=False, @@ -40,3 +42,22 @@ def test_lateral_active_colors_remain_unchanged(): assert _rgb(get_border_color(_state(enabled=True, lat_active=True))) == _rgb(ENGAGED_COLOR) assert _rgb(get_border_color(_state(aol=True))) == _rgb(AOL_COLOR) assert _rgb(get_border_color(_state())) == _rgb(DISENGAGED_COLOR) + + +def test_override_color_matches_active_control_mode(): + lateral_override = SimpleNamespace(overrideLateral=True, overrideLongitudinal=False) + longitudinal_override = SimpleNamespace(overrideLateral=False, overrideLongitudinal=True) + override = UIStatus.OVERRIDE + + # Green: either active-control override is gray. + assert _rgb(get_border_color(_state(enabled=True, lat_active=True, status=override, events=[lateral_override]))) == _rgb(OVERRIDE_COLOR) + assert _rgb(get_border_color(_state(enabled=True, lat_active=True, status=override, events=[longitudinal_override]))) == _rgb(OVERRIDE_COLOR) + + # Pink: steering is already inactive, so only a longitudinal override is gray. + pink_state = _state(enabled=True, status=override, events=[lateral_override]) + assert _rgb(get_border_color(pink_state)) == _rgb(LONGITUDINAL_ONLY_COLOR) + assert _rgb(get_border_color(_state(enabled=True, status=override, events=[longitudinal_override]))) == _rgb(OVERRIDE_COLOR) + + # Blue/AOL: longitudinal override is inactive, so only steering is gray. + assert _rgb(get_border_color(_state(aol=True, status=override, events=[lateral_override]))) == _rgb(OVERRIDE_COLOR) + assert _rgb(get_border_color(_state(aol=True, status=override, events=[longitudinal_override]))) == _rgb(AOL_COLOR)