mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-02-18 14:13:53 +08:00
@@ -14,7 +14,7 @@ from openpilot.system.ui.lib.application import gui_app, FontWeight, FONT_SCALE
|
||||
from openpilot.system.ui.lib.text_measure import measure_text_cached
|
||||
|
||||
|
||||
class E2eAlertsRenderer:
|
||||
class CircularAlertsRenderer:
|
||||
def __init__(self):
|
||||
self._green_light_alert_img = gui_app.texture("../../sunnypilot/selfdrive/assets/images/green_light.png", 250, 250)
|
||||
self._lead_depart_alert_img = gui_app.texture("../../sunnypilot/selfdrive/assets/images/lead_depart.png", 250, 250)
|
||||
@@ -23,6 +23,9 @@ class E2eAlertsRenderer:
|
||||
self._e2e_alert_frame = 0
|
||||
self._green_light_alert = False
|
||||
self._lead_depart_alert = False
|
||||
self._standstill_timer = False
|
||||
self._standstill_elapsed_time = 0.0
|
||||
self._is_standstill = False
|
||||
self._alert_text = ""
|
||||
self._alert_img = None
|
||||
self._allow_e2e_alerts = False
|
||||
@@ -30,14 +33,22 @@ class E2eAlertsRenderer:
|
||||
def update(self) -> None:
|
||||
sm = ui_state.sm
|
||||
lp_sp = sm['longitudinalPlanSP']
|
||||
car_state = sm['carState']
|
||||
self._green_light_alert = lp_sp.e2eAlerts.greenLightAlert
|
||||
self._lead_depart_alert = lp_sp.e2eAlerts.leadDepartAlert
|
||||
self._standstill_timer = ui_state.standstill_timer
|
||||
self._is_standstill = car_state.standstill
|
||||
|
||||
if not ui_state.started:
|
||||
self._standstill_elapsed_time = 0.0
|
||||
|
||||
self._allow_e2e_alerts = sm['selfdriveState'].alertSize == log.SelfdriveState.AlertSize.none and \
|
||||
sm.recv_frame['driverStateV2'] > ui_state.started_frame
|
||||
|
||||
if self._green_light_alert or self._lead_depart_alert:
|
||||
self._e2e_alert_display_timer = 3 * gui_app.target_fps
|
||||
# reset onroad sleep timer for e2e alerts
|
||||
ui_state.reset_onroad_sleep_timer()
|
||||
|
||||
if self._e2e_alert_display_timer > 0:
|
||||
self._e2e_alert_frame += 1
|
||||
@@ -49,11 +60,22 @@ class E2eAlertsRenderer:
|
||||
elif self._lead_depart_alert:
|
||||
self._alert_text = "LEAD VEHICLE\nDEPARTING"
|
||||
self._alert_img = self._lead_depart_alert_img
|
||||
|
||||
elif self._standstill_timer and self._is_standstill:
|
||||
self._alert_img = None
|
||||
self._standstill_elapsed_time += 1.0 / gui_app.target_fps
|
||||
minute = int(self._standstill_elapsed_time / 60)
|
||||
second = int(self._standstill_elapsed_time - (minute * 60))
|
||||
self._alert_text = f"{minute:01d}:{second:02d}"
|
||||
self._e2e_alert_frame += 1
|
||||
|
||||
else:
|
||||
self._e2e_alert_frame = 0
|
||||
if not self._is_standstill:
|
||||
self._standstill_elapsed_time = 0.0
|
||||
|
||||
def render(self, rect: rl.Rectangle) -> None:
|
||||
if not self._allow_e2e_alerts or self._e2e_alert_display_timer <= 0:
|
||||
if not self._allow_e2e_alerts or (self._e2e_alert_display_timer <= 0 and not (self._standstill_timer and self._is_standstill)):
|
||||
return
|
||||
|
||||
e2e_alert_size = 250
|
||||
@@ -67,7 +89,12 @@ class E2eAlertsRenderer:
|
||||
|
||||
# Pulse logic
|
||||
is_pulsing = (self._e2e_alert_frame % gui_app.target_fps) < (gui_app.target_fps / 2.5)
|
||||
frame_color = rl.Color(255, 255, 255, 75) if is_pulsing else rl.Color(0, 255, 0, 75)
|
||||
|
||||
# Standstill Timer (STOPPED) should be static white
|
||||
if self._e2e_alert_display_timer == 0 and self._standstill_timer and self._is_standstill:
|
||||
frame_color = rl.Color(255, 255, 255, 75)
|
||||
else:
|
||||
frame_color = rl.Color(255, 255, 255, 75) if is_pulsing else rl.Color(0, 255, 0, 75)
|
||||
|
||||
# Draw Circle
|
||||
rl.draw_circle_v(center, e2e_alert_size, rl.Color(0, 0, 0, 190))
|
||||
@@ -75,7 +102,7 @@ class E2eAlertsRenderer:
|
||||
rl.draw_ring(center, e2e_alert_size - 7.5, e2e_alert_size + 7.5, 0, 360, 0, frame_color)
|
||||
|
||||
# Draw Image
|
||||
if self._alert_img:
|
||||
if self._alert_img and self._e2e_alert_display_timer > 0:
|
||||
img_x = int(center.x - self._alert_img.width / 2)
|
||||
img_y = int(center.y - self._alert_img.height / 2)
|
||||
rl.draw_texture(self._alert_img, img_x, img_y, rl.WHITE)
|
||||
@@ -94,8 +121,22 @@ class E2eAlertsRenderer:
|
||||
# Draw lines upwards from bottom
|
||||
current_y = bottom_y - (len(lines) * text_size * FONT_SCALE)
|
||||
|
||||
for line in lines:
|
||||
measure = measure_text_cached(font, line, text_size, spacing)
|
||||
line_x = center.x - measure.x / 2
|
||||
rl.draw_text_ex(font, line, rl.Vector2(line_x, current_y), text_size, spacing, txt_color)
|
||||
current_y += text_size * FONT_SCALE
|
||||
if self._e2e_alert_display_timer == 0 and self._standstill_timer and self._is_standstill:
|
||||
# Standstill Timer Text
|
||||
alert_alt_text = "STOPPED"
|
||||
top_text_size = 80
|
||||
measure_top = measure_text_cached(font, alert_alt_text, top_text_size, spacing)
|
||||
top_y = alert_rect.y + alert_rect.height / 3.5
|
||||
rl.draw_text_ex(font, alert_alt_text, rl.Vector2(center.x - measure_top.x / 2, top_y), top_text_size, spacing, rl.Color(255, 175, 3, 240))
|
||||
|
||||
# Timer
|
||||
timer_text_size = 100
|
||||
measure_timer = measure_text_cached(font, self._alert_text, timer_text_size, spacing)
|
||||
timer_y = (alert_rect.y + alert_rect.height) - (alert_rect.height / 5) - measure_timer.y
|
||||
rl.draw_text_ex(font, self._alert_text, rl.Vector2(center.x - measure_timer.x / 2, timer_y), timer_text_size, spacing, rl.WHITE)
|
||||
else:
|
||||
for line in lines:
|
||||
measure = measure_text_cached(font, line, text_size, spacing)
|
||||
line_x = center.x - measure.x / 2
|
||||
rl.draw_text_ex(font, line, rl.Vector2(line_x, current_y), text_size, spacing, txt_color)
|
||||
current_y += text_size * FONT_SCALE
|
||||
@@ -15,7 +15,7 @@ from openpilot.selfdrive.ui.sunnypilot.onroad.rocket_fuel import RocketFuel
|
||||
from openpilot.selfdrive.ui.sunnypilot.onroad.speed_limit import SpeedLimitRenderer
|
||||
from openpilot.selfdrive.ui.sunnypilot.onroad.smart_cruise_control import SmartCruiseControlRenderer
|
||||
from openpilot.selfdrive.ui.sunnypilot.onroad.turn_signal import TurnSignalController
|
||||
from openpilot.selfdrive.ui.sunnypilot.onroad.e2e_alerts import E2eAlertsRenderer
|
||||
from openpilot.selfdrive.ui.sunnypilot.onroad.circular_alerts import CircularAlertsRenderer
|
||||
|
||||
|
||||
class HudRendererSP(HudRenderer):
|
||||
@@ -27,7 +27,7 @@ class HudRendererSP(HudRenderer):
|
||||
self.speed_limit_renderer = SpeedLimitRenderer()
|
||||
self.smart_cruise_control_renderer = SmartCruiseControlRenderer()
|
||||
self.turn_signal_controller = TurnSignalController()
|
||||
self.e2e_alerts_renderer = E2eAlertsRenderer()
|
||||
self.circular_alerts_renderer = CircularAlertsRenderer()
|
||||
self._torque_bar = TorqueBar(scale=3.0, always=True)
|
||||
|
||||
def _update_state(self) -> None:
|
||||
@@ -36,7 +36,7 @@ class HudRendererSP(HudRenderer):
|
||||
self.speed_limit_renderer.update()
|
||||
self.smart_cruise_control_renderer.update()
|
||||
self.turn_signal_controller.update()
|
||||
self.e2e_alerts_renderer.update()
|
||||
self.circular_alerts_renderer.update()
|
||||
|
||||
def _render(self, rect: rl.Rectangle) -> None:
|
||||
super()._render(rect)
|
||||
@@ -52,7 +52,7 @@ class HudRendererSP(HudRenderer):
|
||||
self.speed_limit_renderer.render(rect)
|
||||
self.smart_cruise_control_renderer.render(rect)
|
||||
self.turn_signal_controller.render(rect)
|
||||
self.e2e_alerts_renderer.render(rect)
|
||||
self.circular_alerts_renderer.render(rect)
|
||||
|
||||
if ui_state.rocket_fuel:
|
||||
self.rocket_fuel.render(rect, ui_state.sm)
|
||||
|
||||
@@ -129,6 +129,7 @@ class UIStateSP:
|
||||
self.active_bundle = self.params.get("ModelManager_ActiveBundle")
|
||||
self.custom_interactive_timeout = self.params.get("InteractivityTimeout", return_default=True)
|
||||
self.speed_limit_mode = self.params.get("SpeedLimitMode", return_default=True)
|
||||
self.standstill_timer = self.params.get_bool("StandstillTimer")
|
||||
|
||||
# Onroad Screen Brightness
|
||||
self.onroad_brightness = int(float(self.params.get("OnroadScreenOffBrightness", return_default=True)))
|
||||
|
||||
Reference in New Issue
Block a user