Raylib Rainbow Road Update (All)

This commit is contained in:
firestarsdog
2026-07-05 04:39:52 -04:00
parent cbe6eb077e
commit 2fb5fbf3ad
3 changed files with 66 additions and 44 deletions
+5 -22
View File
@@ -8,6 +8,7 @@ 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_param_color, get_theme_color, get_visual_color, is_stock_color_scheme, with_alpha
from openpilot.selfdrive.ui.onroad.starpilot.rainbow_path import RainbowPath
from openpilot.selfdrive.ui.lib.starpilot_visuals import lead_indicator_enabled
from openpilot.selfdrive.ui.ui_state import ui_state, UIStatus
from openpilot.selfdrive.ui.mici.onroad import blend_colors
@@ -19,8 +20,6 @@ from openpilot.system.ui.widgets import Widget
CLIP_MARGIN = 500
MIN_DRAW_DISTANCE = 10.0
MAX_DRAW_DISTANCE = 100.0
RAINBOW_GRADIENT_COLOR_COUNT = 19
RAINBOW_SCROLL_SPEED_DEG_PER_SEC = 60.0
STOCK_LANE_LINES_COLOR = rl.Color(255, 255, 255, 255)
DEFAULT_LANE_LINES_WIDTH = 4.0
DEFAULT_PATH_WIDTH = 6.1
@@ -91,6 +90,7 @@ class ModelRenderer(Widget):
colors=[],
stops=[],
)
self._rainbow_path = RainbowPath()
# Get longitudinal control setting from car parameters
self._params = Params()
@@ -147,6 +147,8 @@ class ModelRenderer(Widget):
self._transform_dirty = False
self._draw_lane_lines()
if self._params.get_bool("RainbowPath", default=False) and sm.valid.get('carState', False):
self._rainbow_path.update(max(sm['carState'].vEgo, 0.0))
self._draw_path(sm)
if render_lead_indicator and radar_state:
@@ -261,8 +263,7 @@ class ModelRenderer(Widget):
"""Pre-calculate experimental mode gradient colors"""
use_rainbow = self._params.get_bool("RainbowPath", default=False)
if use_rainbow:
gradient_bottom, gradient_top = self._get_visible_gradient_bounds()
self._exp_gradient = self._build_rainbow_gradient(gradient_bottom, gradient_top)
self._exp_gradient = self._rainbow_path.get_gradient(0.0, 1.0)
return
if not self._experimental_mode or not self._params.get_bool("AccelerationPath", default=True):
@@ -319,24 +320,6 @@ class ModelRenderer(Widget):
gradient_top = np.clip((float(np.min(visible_track_y)) - self._rect.y) / self._rect.height, 0.0, 1.0)
return float(gradient_bottom), float(gradient_top)
def _build_rainbow_gradient(self, gradient_bottom: float, gradient_top: float) -> Gradient:
hue_offset = (rl.get_time() * RAINBOW_SCROLL_SPEED_DEG_PER_SEC) % 360.0
stops = [i / (RAINBOW_GRADIENT_COLOR_COUNT - 1) for i in range(RAINBOW_GRADIENT_COLOR_COUNT)]
colors = []
for i, stop in enumerate(stops):
hue_progress = i / RAINBOW_GRADIENT_COLOR_COUNT
path_hue = (hue_progress * 360.0 - hue_offset) % 360.0
alpha = np.interp(stop, [0.0, 1.0], [0.48, 0.18])
colors.append(self._hsla_to_color(path_hue / 360.0, 1.0, 0.5, alpha))
return Gradient(
start=(0.0, gradient_bottom),
end=(0.0, gradient_top),
colors=colors,
stops=stops,
)
def _update_lead_vehicle(self, d_rel, v_rel, point, rect):
speed_buff, lead_buff = 10.0, 40.0
+5 -22
View File
@@ -8,6 +8,7 @@ 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_param_color, get_theme_color, get_visual_color, is_stock_color_scheme, with_alpha
from openpilot.selfdrive.ui.onroad.starpilot.rainbow_path import RainbowPath
from openpilot.selfdrive.ui.lib.starpilot_visuals import lead_indicator_enabled
from openpilot.selfdrive.ui.ui_state import ui_state, UIStatus
from openpilot.system.ui.lib.application import gui_app
@@ -18,8 +19,6 @@ from openpilot.system.ui.widgets import Widget
CLIP_MARGIN = 500
MIN_DRAW_DISTANCE = 10.0
MAX_DRAW_DISTANCE = 100.0
RAINBOW_GRADIENT_COLOR_COUNT = 19
RAINBOW_SCROLL_SPEED_DEG_PER_SEC = 60.0
STOCK_LANE_LINES_COLOR = rl.Color(255, 255, 255, 255)
DEFAULT_LANE_LINES_WIDTH = 4.0
DEFAULT_PATH_EDGE_WIDTH = 20.0
@@ -86,6 +85,7 @@ class ModelRenderer(Widget):
colors=[],
stops=[],
)
self._rainbow_path = RainbowPath()
# Get longitudinal control setting from car parameters
self._params = Params()
@@ -127,6 +127,8 @@ class ModelRenderer(Widget):
self._use_rainbow = self._params.get_bool('RainbowPath', default=False)
self._use_accel_path = self._params.get_bool('AccelerationPath', default=True)
self._is_metric = self._params.get_bool('IsMetric')
if self._use_rainbow and sm.valid.get('carState', False):
self._rainbow_path.update(max(sm['carState'].vEgo, 0.0))
lead_info_enabled = self._lead_info_enabled
render_lead_indicator = (
(self._longitudinal_control or lead_info_enabled)
@@ -270,8 +272,7 @@ class ModelRenderer(Widget):
def _update_experimental_gradient(self):
"""Pre-calculate experimental mode gradient colors"""
if self._use_rainbow:
gradient_bottom, gradient_top = self._get_visible_gradient_bounds()
self._exp_gradient = self._build_rainbow_gradient(gradient_bottom, gradient_top)
self._exp_gradient = self._rainbow_path.get_gradient(0.0, 1.0)
return
if not self._experimental_mode or not self._use_accel_path:
@@ -330,24 +331,6 @@ class ModelRenderer(Widget):
gradient_top = np.clip((float(np.min(visible_track_y)) - self._rect.y) / self._rect.height, 0.0, 1.0)
return float(gradient_bottom), float(gradient_top)
def _build_rainbow_gradient(self, gradient_bottom: float, gradient_top: float) -> Gradient:
hue_offset = (rl.get_time() * RAINBOW_SCROLL_SPEED_DEG_PER_SEC) % 360.0
stops = [i / (RAINBOW_GRADIENT_COLOR_COUNT - 1) for i in range(RAINBOW_GRADIENT_COLOR_COUNT)]
colors = []
for i, stop in enumerate(stops):
hue_progress = i / RAINBOW_GRADIENT_COLOR_COUNT
path_hue = (hue_progress * 360.0 - hue_offset) % 360.0
alpha = np.interp(stop, [0.0, 1.0], [0.48, 0.18])
colors.append(self._hsla_to_color(path_hue / 360.0, 1.0, 0.5, alpha))
return Gradient(
start=(0.0, gradient_bottom),
end=(0.0, gradient_top),
colors=colors,
stops=stops,
)
def _update_lead_vehicle(self, d_rel, v_rel, point, rect):
speed_buff, lead_buff = 10.0, 40.0
@@ -0,0 +1,56 @@
from __future__ import annotations
import colorsys
import pyray as rl
from openpilot.system.ui.lib.shader_polygon import Gradient
HUE_RANGE = 120.0
SCROLL_DEG_PER_SEC_PER_MPS = 5.0
ALPHA_BOTTOM = 0.5
ALPHA_TOP = 0.1
NUM_STOPS = 12
def _hsla_to_color(h: float, s: float, l: float, a: float) -> rl.Color:
rgb = colorsys.hls_to_rgb(h, l, s)
return rl.Color(int(rgb[0] * 255), int(rgb[1] * 255), int(rgb[2] * 255), int(a * 255))
class RainbowPath:
"""Rainbow path renderer ported from the FrogPilot/StarPilot Qt C++ UI implementation."""
def __init__(self) -> None:
self._hue_offset: float = 0.0
self._last_time: float = 0.0
def update(self, speed_ms: float) -> None:
"""Accumulate hue offset from vehicle speed. Call once per frame."""
now = rl.get_time()
dt = now - self._last_time if self._last_time > 0.0 else 0.0
self._last_time = now
if speed_ms > 0.0 and dt > 0.0:
self._hue_offset = (self._hue_offset + speed_ms * SCROLL_DEG_PER_SEC_PER_MPS * dt) % 360.0
def get_gradient(self, gradient_bottom: float, gradient_top: float) -> Gradient:
"""Build a Gradient compatible with draw_polygon().
Args:
gradient_bottom: Normalized y-position (0-1) of the path bottom.
gradient_top: Normalized y-position (0-1) of the path top.
"""
stops = [i / (NUM_STOPS - 1) for i in range(NUM_STOPS)]
colors = []
for stop in stops:
path_hue = (stop * HUE_RANGE + self._hue_offset) % 360.0
alpha = ALPHA_BOTTOM + (ALPHA_TOP - ALPHA_BOTTOM) * stop
colors.append(_hsla_to_color(path_hue / 360.0, 1.0, 0.5, alpha))
return Gradient(
start=(0.0, gradient_bottom),
end=(0.0, gradient_top),
colors=colors,
stops=stops,
)