From 4419e33dcaf2752a19c574b5de6c8b58119f86e4 Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Sun, 19 Apr 2026 01:06:55 -0500 Subject: [PATCH] Revert "Mici customize?" This reverts commit 979015cd2056983fd2bb4073873c1cf126fc882b. --- selfdrive/ui/lib/starpilot_theme.py | 92 ---------------------- selfdrive/ui/mici/onroad/model_renderer.py | 67 +++------------- selfdrive/ui/onroad/model_renderer.py | 76 +++++++----------- selfdrive/ui/onroad/starpilot/path.py | 25 ++++-- 4 files changed, 54 insertions(+), 206 deletions(-) delete mode 100644 selfdrive/ui/lib/starpilot_theme.py diff --git a/selfdrive/ui/lib/starpilot_theme.py b/selfdrive/ui/lib/starpilot_theme.py deleted file mode 100644 index b244b48034..0000000000 --- a/selfdrive/ui/lib/starpilot_theme.py +++ /dev/null @@ -1,92 +0,0 @@ -from __future__ import annotations - -import json -from pathlib import Path - -import pyray as rl - -from openpilot.common.basedir import BASEDIR - -ACTIVE_THEME_COLORS_PATH = Path(BASEDIR) / "starpilot/assets/active_theme/colors/colors.json" -STOCK_THEME_COLORS_PATH = Path(BASEDIR) / "starpilot/assets/stock_theme/colors/colors.json" - -_FALLBACK_THEME_COLORS = { - "LaneLines": (255, 255, 255, 178), - "LeadMarker": (201, 34, 49, 255), - "Path": (48, 255, 156, 255), - "PathEdge": (38, 209, 125, 255), - "Sidebar1": (255, 255, 255, 178), - "Sidebar2": (255, 255, 255, 255), - "Sidebar3": (255, 255, 255, 255), -} - -_THEME_COLOR_CACHE: dict[str, object] = { - "stamp": None, - "colors": None, -} - - -def _file_stamp(path: Path) -> tuple[str, int | None, int | None]: - try: - stat = path.stat() - return (str(path), stat.st_mtime_ns, stat.st_size) - except OSError: - return (str(path), None, None) - - -def _clamp_channel(value: object, fallback: int) -> int: - try: - return max(0, min(255, int(value))) - except (TypeError, ValueError): - return fallback - - -def _load_color_map(path: Path) -> dict[str, dict[str, int]]: - try: - with path.open() as f: - data = json.load(f) - if isinstance(data, dict): - return data - except (OSError, ValueError, TypeError): - pass - return {} - - -def _build_color(entry: object, fallback: tuple[int, int, int, int]) -> rl.Color: - if isinstance(entry, dict): - red, green, blue, alpha = fallback - return rl.Color( - _clamp_channel(entry.get("red"), red), - _clamp_channel(entry.get("green"), green), - _clamp_channel(entry.get("blue"), blue), - _clamp_channel(entry.get("alpha"), alpha), - ) - return rl.Color(*fallback) - - -def _load_theme_colors() -> dict[str, rl.Color]: - stamp = (_file_stamp(STOCK_THEME_COLORS_PATH), _file_stamp(ACTIVE_THEME_COLORS_PATH)) - if stamp == _THEME_COLOR_CACHE["stamp"] and _THEME_COLOR_CACHE["colors"] is not None: - return _THEME_COLOR_CACHE["colors"] # type: ignore[return-value] - - stock_colors = _load_color_map(STOCK_THEME_COLORS_PATH) - active_colors = _load_color_map(ACTIVE_THEME_COLORS_PATH) - - colors = {} - for key, fallback in _FALLBACK_THEME_COLORS.items(): - colors[key] = _build_color(active_colors.get(key, stock_colors.get(key)), fallback) - - _THEME_COLOR_CACHE["stamp"] = stamp - _THEME_COLOR_CACHE["colors"] = colors - return colors - - -def get_theme_color(key: str, fallback: rl.Color | None = None) -> rl.Color: - color = _load_theme_colors().get(key) - if color is not None: - return color - return fallback if fallback is not None else rl.WHITE - - -def with_alpha(color: rl.Color, alpha: int) -> rl.Color: - return rl.Color(color.r, color.g, color.b, max(0, min(255, int(alpha)))) diff --git a/selfdrive/ui/mici/onroad/model_renderer.py b/selfdrive/ui/mici/onroad/model_renderer.py index 2f26d248bd..b4112fff71 100644 --- a/selfdrive/ui/mici/onroad/model_renderer.py +++ b/selfdrive/ui/mici/onroad/model_renderer.py @@ -4,10 +4,8 @@ import pyray as rl from cereal import messaging, car from dataclasses import dataclass, field from openpilot.common.params import Params -from openpilot.common.constants import CV from openpilot.common.filter_simple import FirstOrderFilter from openpilot.selfdrive.locationd.calibrationd import HEIGHT_INIT -from openpilot.selfdrive.ui.lib.starpilot_theme import get_theme_color, with_alpha from openpilot.selfdrive.ui.ui_state import ui_state, UIStatus from openpilot.selfdrive.ui.mici.onroad import blend_colors from openpilot.selfdrive.ui.mici.onroad.starpilot_status import get_border_color, get_path_edge_color @@ -81,8 +79,7 @@ class ModelRenderer(Widget): ) # Get longitudinal control setting from car parameters - self._params = Params() - if car_params := self._params.get("CarParams"): + if car_params := Params().get("CarParams"): cp = messaging.log_from_bytes(car_params, car.CarParams) self._longitudinal_control = cp.openpilotLongitudinalControl @@ -187,36 +184,21 @@ class ModelRenderer(Widget): def _update_model(self, lead, path_x_array): """Update model visualization data based on model message""" - model_ui_enabled = self._params.get_bool("ModelUI", default=True) - if model_ui_enabled: - path_width = self._path_width_to_half_m(self._params.get_float("PathWidth", return_default=True, default=6.1)) - lane_line_width = self._small_distance_to_half_m(self._params.get_float("LaneLinesWidth", return_default=True, default=4.0)) - road_edge_width = self._small_distance_to_half_m(self._params.get_float("RoadEdgesWidth", return_default=True, default=2.0)) - else: - path_width = 0.9 - lane_line_width = 0.025 - road_edge_width = 0.025 - - if model_ui_enabled and self._params.get_bool("DynamicPathWidth", default=False): - if ui_state.status == UIStatus.ENGAGED: - path_width *= 1.0 - elif ui_state.always_on_lateral_active: - path_width *= 0.75 - else: - path_width *= 0.50 - max_distance = np.clip(path_x_array[-1], MIN_DRAW_DISTANCE, MAX_DRAW_DISTANCE) max_idx = self._get_path_length_idx(self._lane_lines[0].raw_points[:, 0], max_distance) # Update lane lines using raw points + line_width_factor = 0.12 for i, lane_line in enumerate(self._lane_lines): + if i in (1, 2): + line_width_factor = 0.16 lane_line.projected_points = self._map_line_to_polygon( - lane_line.raw_points, lane_line_width * self._lane_line_probs[i], 0.0, max_idx + lane_line.raw_points, line_width_factor * self._lane_line_probs[i], 0.0, max_idx ) # Update road edges using raw points for road_edge in self._road_edges: - road_edge.projected_points = self._map_line_to_polygon(road_edge.raw_points, road_edge_width, 0.0, max_idx) + road_edge.projected_points = self._map_line_to_polygon(road_edge.raw_points, line_width_factor, 0.0, max_idx) # Update path using raw points if lead and lead.status: @@ -232,7 +214,7 @@ class ModelRenderer(Widget): high_pass_acceleration = self._acceleration_x_filter.x - self._acceleration_x_filter2.x y_off = np.interp(high_pass_acceleration, [-1, 0, 1], [0.9 * 2, 0.9, 0.9 / 2]) else: - y_off = path_width + y_off = 0.9 max_idx = self._get_path_length_idx(path_x_array, max_distance) self._path.projected_points = self._map_line_to_polygon( @@ -243,7 +225,7 @@ class ModelRenderer(Widget): def _update_experimental_gradient(self): """Pre-calculate experimental mode gradient colors""" - if not (self._experimental_mode or self._params.get_bool("AccelerationPath", default=True)): + if not self._experimental_mode: return max_len = min(len(self._path.projected_points) // 2, len(self._acceleration_x)) @@ -322,8 +304,7 @@ class ModelRenderer(Widget): np.interp(abs(torque), [0.6, 0.8], [0.0, 1.0]) ) else: - lane_lines_color = get_theme_color("LaneLines", rl.WHITE) - color = with_alpha(lane_lines_color, int(alpha * lane_lines_color.a)) + color = rl.Color(255, 255, 255, int(alpha * 255)) return color @@ -353,28 +334,14 @@ class ModelRenderer(Widget): lateral_ui_active = ui_state.status == UIStatus.ENGAGED or ui_state.always_on_lateral_active allow_throttle = sm['longitudinalPlan'].allowThrottle or not self._longitudinal_control or ui_state.always_on_lateral_active self._blend_filter.update(int(allow_throttle)) - custom_theme_selected = (self._params.get("ColorScheme", encoding="utf-8", default="stock") or "stock").lower() != "stock" - if self._experimental_mode or self._params.get_bool("AccelerationPath", default=True): + if self._experimental_mode: # Draw with acceleration coloring if len(self._exp_gradient.colors) > 1: draw_polygon(self._rect, self._path.projected_points, gradient=self._exp_gradient) else: fallback = get_border_color(ui_state) draw_polygon(self._rect, self._path.projected_points, rl.Color(fallback.r, fallback.g, fallback.b, 90)) - elif custom_theme_selected: - path_color = get_theme_color("Path", rl.Color(48, 255, 156, 255)) - gradient = Gradient( - start=(0.0, 1.0), - end=(0.0, 0.0), - colors=[ - with_alpha(path_color, path_color.a), - with_alpha(path_color, int(path_color.a * 0.55)), - with_alpha(path_color, int(path_color.a * 0.10)), - ], - stops=[0.0, 0.5, 1.0], - ) - draw_polygon(self._rect, self._path.projected_points, gradient=gradient) else: # Blend throttle/no throttle colors based on transition blend_factor = round(self._blend_filter.x * 100) / 100 @@ -512,17 +479,3 @@ class ModelRenderer(Widget): int(inv_t * start.b + t * end.b), int(inv_t * start.a + t * end.a) ) for start, end in zip(begin_colors, end_colors, strict=True)] - - def _small_distance_to_half_m(self, value: float) -> float: - if value <= 0: - return 0.0 - if self._params.get_bool("IsMetric"): - return value / 200.0 - return value * (CV.INCH_TO_CM / 100.0) / 2.0 - - def _path_width_to_half_m(self, value: float) -> float: - if value <= 0: - return 0.0 - if self._params.get_bool("IsMetric"): - return value / 2.0 - return value * CV.FOOT_TO_METER / 2.0 diff --git a/selfdrive/ui/onroad/model_renderer.py b/selfdrive/ui/onroad/model_renderer.py index 20fad26400..5818e8b338 100644 --- a/selfdrive/ui/onroad/model_renderer.py +++ b/selfdrive/ui/onroad/model_renderer.py @@ -5,9 +5,7 @@ from cereal import messaging, car from dataclasses import dataclass, field from openpilot.common.filter_simple import FirstOrderFilter from openpilot.common.params import Params -from openpilot.common.constants import CV from openpilot.selfdrive.locationd.calibrationd import HEIGHT_INIT -from openpilot.selfdrive.ui.lib.starpilot_theme import get_theme_color, with_alpha from openpilot.selfdrive.ui.ui_state import ui_state, UIStatus from openpilot.system.ui.lib.application import gui_app from openpilot.system.ui.lib.shader_polygon import draw_polygon, Gradient @@ -187,24 +185,28 @@ class ModelRenderer(Widget): def _update_model(self, lead, path_x_array): """Update model visualization data based on model message""" - model_ui_enabled = self._params.get_bool('ModelUI', default=True) - if model_ui_enabled: - path_width = self._path_width_to_half_m(self._params.get_float('PathWidth', return_default=True, default=6.1)) - lane_line_width_m = self._small_distance_to_half_m(self._params.get_float('LaneLinesWidth', return_default=True, default=4.0)) - road_edge_width_m = self._small_distance_to_half_m(self._params.get_float('RoadEdgesWidth', return_default=True, default=2.0)) - path_edge_width_pct = np.clip(self._params.get_float('PathEdgeWidth', return_default=True, default=20.0) / 100.0, 0.0, 1.0) - else: - path_width = 0.9 - lane_line_width_m = 0.025 - road_edge_width_m = 0.025 - path_edge_width_pct = 0.0 + path_width = self._params.get_float('PathWidth') # stored in feet, convert to meters + if path_width <= 0: + path_width = 0.9 # default in meters + + lane_line_width = self._params.get_int('LaneLinesWidth') # stored in inches, convert to meters + if lane_line_width <= 0: + lane_line_width = int(0.025 / 0.0254) # default ~1 inch + lane_line_width_m = lane_line_width * 0.0254 + + road_edge_width = self._params.get_int('RoadEdgesWidth') # stored in inches + if road_edge_width <= 0: + road_edge_width = int(0.025 / 0.0254) + road_edge_width_m = road_edge_width * 0.0254 + + path_edge_width_pct = self._params.get_int('PathEdgeWidth') / 100.0 # Dynamic path width - if model_ui_enabled and self._params.get_bool('DynamicPathWidth', default=False): + if self._params.get_bool('DynamicPathWidth'): status = ui_state.status if status == UIStatus.ENGAGED: path_width *= 1.0 - elif ui_state.always_on_lateral_active: + elif status == UIStatus.ALWAYS_ON_LATERAL: path_width *= 0.75 else: path_width *= 0.50 @@ -244,7 +246,7 @@ class ModelRenderer(Widget): def _update_experimental_gradient(self): """Pre-calculate experimental mode gradient colors""" - use_acceleration = self._experimental_mode or self._params.get_bool('AccelerationPath', default=True) + use_acceleration = self._experimental_mode or self._params.get_bool('AccelerationPath') use_rainbow = self._params.get_bool('RainbowPath') and not use_acceleration if not use_acceleration and not use_rainbow: @@ -331,14 +333,19 @@ class ModelRenderer(Widget): def _draw_lane_lines(self): """Draw lane lines and road edges""" - lane_lines_color = get_theme_color("LaneLines", rl.WHITE) + color_scheme = self._params.get('ColorScheme', encoding='utf-8') or 'stock' + lane_lines_color = self._params.get('LaneLinesColor', encoding='utf-8') for i, lane_line in enumerate(self._lane_lines): if lane_line.projected_points.size == 0: continue alpha = np.clip(self._lane_line_probs[i], 0.0, 0.7) - color = with_alpha(lane_lines_color, int(alpha * lane_lines_color.a)) + if color_scheme != 'stock' and lane_lines_color: + base_color = self._hex_to_color(lane_lines_color) + color = rl.Color(base_color.r, base_color.g, base_color.b, int(alpha * 255)) + else: + color = rl.Color(255, 255, 255, int(alpha * 255)) draw_polygon(self._rect, lane_line.projected_points, color) for i, road_edge in enumerate(self._road_edges): @@ -357,26 +364,12 @@ class ModelRenderer(Widget): allow_throttle = sm['longitudinalPlan'].allowThrottle or not self._longitudinal_control self._blend_filter.update(int(allow_throttle)) - use_accel_path = self._params.get_bool('AccelerationPath', default=True) - custom_theme_selected = (self._params.get('ColorScheme', encoding='utf-8', default='stock') or 'stock').lower() != 'stock' + use_accel_path = self._params.get_bool('AccelerationPath') if self._experimental_mode or use_accel_path: if len(self._exp_gradient.colors) > 1: draw_polygon(self._rect, self._path.projected_points, gradient=self._exp_gradient) else: draw_polygon(self._rect, self._path.projected_points, rl.Color(255, 255, 255, 30)) - elif custom_theme_selected: - path_color = get_theme_color("Path", rl.Color(48, 255, 156, 255)) - gradient = Gradient( - start=(0.0, 1.0), - end=(0.0, 0.0), - colors=[ - with_alpha(path_color, path_color.a), - with_alpha(path_color, int(path_color.a * 0.55)), - with_alpha(path_color, int(path_color.a * 0.10)), - ], - stops=[0.0, 0.5, 1.0], - ) - draw_polygon(self._rect, self._path.projected_points, gradient=gradient) else: # Blend throttle/no throttle colors based on transition blend_factor = round(self._blend_filter.x * 100) / 100 @@ -391,13 +384,12 @@ class ModelRenderer(Widget): def _draw_lead_indicator(self): # Draw lead vehicles if available - lead_color = get_theme_color("LeadMarker", rl.Color(201, 34, 49, 255)) for lead in self._lead_vehicles: if not lead.glow or not lead.chevron: continue rl.draw_triangle_fan(lead.glow, len(lead.glow), rl.Color(218, 202, 37, 255)) - rl.draw_triangle_fan(lead.chevron, len(lead.chevron), with_alpha(lead_color, lead.fill_alpha)) + rl.draw_triangle_fan(lead.chevron, len(lead.chevron), rl.Color(201, 34, 49, lead.fill_alpha)) def _update_adjacent_paths(self, max_idx: int, max_distance: float): """Compute adjacent lane path polygons by averaging lane line pairs.""" @@ -639,20 +631,6 @@ class ModelRenderer(Widget): int(a * 255) ) - def _small_distance_to_half_m(self, value: float) -> float: - if value <= 0: - return 0.0 - if self._params.get_bool("IsMetric"): - return value / 200.0 - return value * (CV.INCH_TO_CM / 100.0) / 2.0 - - def _path_width_to_half_m(self, value: float) -> float: - if value <= 0: - return 0.0 - if self._params.get_bool("IsMetric"): - return value / 2.0 - return value * CV.FOOT_TO_METER / 2.0 - @staticmethod def _blend_colors(begin_colors, end_colors, t): if t >= 1.0: diff --git a/selfdrive/ui/onroad/starpilot/path.py b/selfdrive/ui/onroad/starpilot/path.py index dbb6a6e7d5..f0b60b9720 100644 --- a/selfdrive/ui/onroad/starpilot/path.py +++ b/selfdrive/ui/onroad/starpilot/path.py @@ -6,7 +6,6 @@ import numpy as np import pyray as rl from openpilot.selfdrive.ui.lib.starpilot_state import starpilot_state -from openpilot.selfdrive.ui.lib.starpilot_theme import get_theme_color, with_alpha from openpilot.selfdrive.ui.ui_state import ui_state from openpilot.system.ui.lib.shader_polygon import draw_polygon, Gradient @@ -177,10 +176,20 @@ def render_path_edges(renderer) -> None: elif ui_state.traffic_mode_enabled: base_color = rl.Color(201, 34, 49, 241) else: - color_scheme = renderer._params.get("ColorScheme", encoding="utf-8", default="stock") - if color_scheme != "stock": - theme_color = get_theme_color("PathEdge", rl.Color(23, 134, 68, 241)) - base_color = rl.Color(theme_color.r, theme_color.g, theme_color.b, 241) + color_scheme = renderer._params.get("ColorScheme") + if color_scheme and color_scheme.decode("utf-8") != "stock": + path_edges_color = renderer._params.get("PathEdgesColor") + if path_edges_color: + hex_str = path_edges_color.decode("utf-8").lstrip("#") + if len(hex_str) == 6: + r = int(hex_str[0:2], 16) + g = int(hex_str[2:4], 16) + b = int(hex_str[4:6], 16) + base_color = rl.Color(r, g, b, 241) + else: + base_color = rl.Color(23, 134, 68, 241) + else: + base_color = rl.Color(23, 134, 68, 241) else: base_color = None @@ -189,9 +198,9 @@ def render_path_edges(renderer) -> None: start=(0.0, 1.0), end=(0.0, 0.0), colors=[ - with_alpha(base_color, int(255 * 0.4)), - with_alpha(base_color, int(255 * 0.35)), - with_alpha(base_color, 0), + rl.Color(base_color.r, base_color.g, base_color.b, int(255 * 0.4)), + rl.Color(base_color.r, base_color.g, base_color.b, int(255 * 0.35)), + rl.Color(base_color.r, base_color.g, base_color.b, 0), ], stops=[0.0, 0.5, 1.0], )