Merge remote-tracking branch 'sunnypilot/sunnypilot/master' into hkg-angle-steering-2025

This commit is contained in:
Jason Wen
2026-02-28 15:47:57 -05:00
14 changed files with 163 additions and 68 deletions
+1
View File
@@ -170,6 +170,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"OffroadMode", {CLEAR_ON_MANAGER_START, BOOL}},
{"Offroad_TiciSupport", {CLEAR_ON_MANAGER_START, JSON}},
{"OnroadScreenOffBrightness", {PERSISTENT | BACKUP, INT, "0"}},
{"OnroadScreenOffBrightnessMigrated", {PERSISTENT | BACKUP, STRING, "0.0"}},
{"OnroadScreenOffTimer", {PERSISTENT | BACKUP, INT, "15"}},
{"OnroadUploads", {PERSISTENT | BACKUP, BOOL, "1"}},
{"QuickBootToggle", {PERSISTENT | BACKUP, BOOL, "0"}},
@@ -19,6 +19,7 @@ ONROAD_BRIGHTNESS_TIMER_VALUES = {0: 15, 1: 30, **{i: (i - 1) * 60 for i in rang
class OnroadBrightness(IntEnum):
AUTO = 0
AUTO_DARK = 1
SCREEN_OFF = 2
class DisplayLayout(Widget):
@@ -35,7 +36,7 @@ class DisplayLayout(Widget):
title=lambda: tr("Onroad Brightness"),
description="",
min_value=0,
max_value=21,
max_value=22,
value_change_step=1,
label_callback=lambda value: self.update_onroad_brightness(value),
inline=True
@@ -79,7 +80,10 @@ class DisplayLayout(Widget):
if val == OnroadBrightness.AUTO_DARK:
return tr("Auto (Dark)")
return f"{(val - 1) * 5} %"
if val == OnroadBrightness.SCREEN_OFF:
return tr("Screen Off")
return f"{(val - 2) * 5} %"
def _update_state(self):
super()._update_state()
@@ -28,7 +28,7 @@ class BlindSpotIndicators:
@property
def detected(self) -> bool:
return self._blind_spot_left_alpha_filter.x > 0.01 or self._blind_spot_right_alpha_filter.x > 0.01
return ui_state.blindspot and (self._blind_spot_left_alpha_filter.x > 0.01 or self._blind_spot_right_alpha_filter.x > 0.01)
def render(self, rect: rl.Rectangle) -> None:
if not ui_state.blindspot:
+14 -6
View File
@@ -22,6 +22,8 @@ from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.lib.multilang import tr
from openpilot.system.ui.lib.text_measure import measure_text_cached
SLA_ACTIVE_COLOR = rl.Color(0x91, 0x9b, 0x95, 0xff)
class HudRendererSP(HudRenderer):
def __init__(self):
@@ -71,6 +73,8 @@ class HudRendererSP(HudRenderer):
self.show_icbm_status = self.icbm_active_counter > 0
def _draw_set_speed(self, rect: rl.Rectangle) -> None:
long_plan_sp = ui_state.sm['longitudinalPlanSP']
long_override = ui_state.sm['carControl'].cruiseControl.override
self._get_icbm_status()
set_speed_width = UI_CONFIG.set_speed_width_metric if ui_state.is_metric else UI_CONFIG.set_speed_width_imperial
@@ -85,12 +89,16 @@ class HudRendererSP(HudRenderer):
set_speed_color = COLORS.DARK_GREY
if self.is_cruise_set:
set_speed_color = COLORS.WHITE
if ui_state.status == UIStatus.ENGAGED:
max_color = COLORS.ENGAGED
elif ui_state.status == UIStatus.DISENGAGED:
max_color = COLORS.DISENGAGED
elif ui_state.status == UIStatus.OVERRIDE:
max_color = COLORS.OVERRIDE
if long_plan_sp.speedLimit.assist.active:
set_speed_color = SLA_ACTIVE_COLOR if long_override else rl.Color(0, 0xff, 0, 0xff)
max_color = SLA_ACTIVE_COLOR if long_override else rl.Color(0x80, 0xd8, 0xa6, 0xff)
else:
if ui_state.status == UIStatus.ENGAGED:
max_color = COLORS.ENGAGED
elif ui_state.status == UIStatus.DISENGAGED:
max_color = COLORS.DISENGAGED
elif ui_state.status == UIStatus.OVERRIDE:
max_color = COLORS.OVERRIDE
max_str_size = 60 if self.show_icbm_status else 40
max_str_y = 15 if self.show_icbm_status else 27
+36 -25
View File
@@ -6,7 +6,6 @@ See the LICENSE.md file in the root directory for more details.
"""
from dataclasses import dataclass
import math
import pyray as rl
from cereal import custom
@@ -41,9 +40,32 @@ class Colors:
MUTCD_LINES = rl.Color(255, 255, 255, 100)
class SpeedLimitRenderer(Widget):
class SpeedLimitAlertRenderer:
def __init__(self):
super().__init__()
arrow_size = 200
self.arrow_up = gui_app.texture("../../sunnypilot/selfdrive/assets/img_plus_arrow_up.png", arrow_size, arrow_size)
self.arrow_down = gui_app.texture("../../sunnypilot/selfdrive/assets/img_minus_arrow_down.png", arrow_size, arrow_size)
self._pre_active_alpha_filter = FirstOrderFilter(1.0, 0.05, 1 / gui_app.target_fps)
self._pre_active_alert_frame = 0
def update(self):
assist_state = ui_state.sm['longitudinalPlanSP'].speedLimit.assist.state
if assist_state == AssistState.preActive:
self._pre_active_alert_frame += 1
if (self._pre_active_alert_frame % gui_app.target_fps) < (gui_app.target_fps * 0.75):
self._pre_active_alpha_filter.x = 1.0
else:
self._pre_active_alpha_filter.update(0.0)
else:
self._pre_active_alert_frame = 0
self._pre_active_alpha_filter.update(1.0)
class SpeedLimitRenderer(Widget, SpeedLimitAlertRenderer):
def __init__(self):
Widget.__init__(self)
SpeedLimitAlertRenderer.__init__(self)
self.speed_limit = 0.0
self.speed_limit_last = 0.0
@@ -60,7 +82,6 @@ class SpeedLimitRenderer(Widget):
self.speed_limit_ahead_valid = False
self.speed_limit_ahead_frame = 0
self.assist_frame = 0
self.is_cruise_set: bool = False
self.is_cruise_available: bool = True
self.set_speed: float = SET_SPEED_NA
@@ -70,17 +91,13 @@ class SpeedLimitRenderer(Widget):
self.font_bold = gui_app.font(FontWeight.BOLD)
self.font_demi = gui_app.font(FontWeight.SEMI_BOLD)
self.font_norm = gui_app.font(FontWeight.NORMAL)
self._sign_alpha_filter = FirstOrderFilter(1.0, 0.5, 1 / gui_app.target_fps)
arrow_size = 90
self._arrow_up = gui_app.texture("../../sunnypilot/selfdrive/assets/img_plus_arrow_up.png", arrow_size, arrow_size)
self._arrow_down = gui_app.texture("../../sunnypilot/selfdrive/assets/img_minus_arrow_down.png", arrow_size, arrow_size)
@property
def speed_conv(self):
return CV.MS_TO_KPH if ui_state.is_metric else CV.MS_TO_MPH
def update(self):
SpeedLimitAlertRenderer.update(self)
sm = ui_state.sm
if sm.recv_frame["carState"] < ui_state.started_frame:
self.set_speed = SET_SPEED_NA
@@ -143,13 +160,7 @@ class SpeedLimitRenderer(Widget):
sign_rect = rl.Rectangle(x, y, width, UI_CONFIG.set_speed_height + 6 * 2)
if self.speed_limit_assist_state == AssistState.preActive:
self.assist_frame += 1
pulse_value = 0.65 + 0.35 * math.sin(self.assist_frame * math.pi / gui_app.target_fps)
alpha = self._sign_alpha_filter.update(pulse_value)
else:
self.assist_frame = 0
alpha = self._sign_alpha_filter.update(1.0)
alpha = self._pre_active_alpha_filter.x
if ui_state.speed_limit_mode != SpeedLimitMode.off:
self._draw_sign_main(sign_rect, alpha)
@@ -184,19 +195,19 @@ class SpeedLimitRenderer(Widget):
set_speed_rounded = round(self.set_speed)
limit_rounded = round(self.speed_limit_final_last)
bounce_frequency = 2.0 * math.pi / (gui_app.target_fps * 2.5)
bounce_offset = int(20 * math.sin(self.assist_frame * bounce_frequency))
sign_margin = 12
arrow_spacing = int(sign_margin * 1.4)
arrow_x = sign_rect.x + sign_rect.width + arrow_spacing
if set_speed_rounded < limit_rounded:
arrow_y = sign_rect.y + (sign_rect.height - self._arrow_up.height) / 2 + bounce_offset
rl.draw_texture(self._arrow_up, int(arrow_x), int(arrow_y), rl.WHITE)
elif set_speed_rounded > limit_rounded:
arrow_y = sign_rect.y + (sign_rect.height - self._arrow_down.height) / 2 - bounce_offset
rl.draw_texture(self._arrow_down, int(arrow_x), int(arrow_y), rl.WHITE)
icon_alpha = max(0.0, min(self._pre_active_alpha_filter.x * 255.0, 255.0))
if icon_alpha > 0:
color = rl.Color(255, 255, 255, int(icon_alpha))
if set_speed_rounded < limit_rounded:
arrow_y = sign_rect.y + (sign_rect.height - self.arrow_up.height) / 2
rl.draw_texture(self.arrow_up, int(arrow_x), int(arrow_y), color)
elif set_speed_rounded > limit_rounded:
arrow_y = sign_rect.y + (sign_rect.height - self.arrow_down.height) / 2
rl.draw_texture(self.arrow_down, int(arrow_x), int(arrow_y), color)
def _render_vienna(self, rect, val, sub, color, has_limit, alpha=1.0):
center = rl.Vector2(rect.x + rect.width / 2, rect.y + rect.height / 2)
+6 -4
View File
@@ -162,14 +162,16 @@ class DeviceSP:
# For AUTO (Default) and Manual modes (while timer running), use standard brightness
return cur_brightness
# 0: Auto (Default), 1: Auto (Dark)
# 0: Auto (Default), 1: Auto (Dark), 2: Screen Off
if _ui_state.onroad_brightness == OnroadBrightness.AUTO:
return cur_brightness
elif _ui_state.onroad_brightness == OnroadBrightness.AUTO_DARK:
if _ui_state.onroad_brightness == OnroadBrightness.AUTO_DARK:
return cur_brightness
if _ui_state.onroad_brightness == OnroadBrightness.SCREEN_OFF:
return 0.0
# 2-21: 5% - 100%
return float((_ui_state.onroad_brightness - 1) * 5)
# 3-22: 5% - 100%
return float((_ui_state.onroad_brightness - 2) * 5)
@staticmethod
def set_min_onroad_brightness(_ui_state, min_brightness: int) -> int:
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0f4a0bf26cfd2c64939759d43bee839aadfd017a6f74065095a27b03615e55a4
size 26627
oid sha256:ad42ecaeff96a0a6c1a6db67b01e3c0452566906dd3a7f0336a1010ae854d27b
size 60924
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3e451ff31e9b3f144822ab282b8e47cd5a603ca59ff94bd1849271181b86c6b1
size 29220
oid sha256:1fdea39873f60a0c4b216b75792e826f3633091a72ea2abd05740bd6e4e72089
size 63058
+11 -7
View File
@@ -1,3 +1,9 @@
"""
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
import cereal.messaging as messaging
from cereal import log, car, custom
from openpilot.common.constants import CV
@@ -34,7 +40,6 @@ def speed_limit_pre_active_alert(CP: car.CarParams, CS: car.CarState, sm: messag
speed_limit_final_last = sm['longitudinalPlanSP'].speedLimit.resolver.speedLimitFinalLast
speed_limit_final_last_conv = round(speed_limit_final_last * speed_conv)
alert_1_str = ""
alert_2_str = ""
alert_size = AlertSize.none
if CP.openpilotLongitudinalControl and CP.pcmCruise:
@@ -44,13 +49,12 @@ def speed_limit_pre_active_alert(CP: car.CarParams, CS: car.CarState, sm: messag
pcm_long_required_max_set_speed_conv = round(pcm_long_required_max * speed_conv)
speed_unit = "km/h" if metric else "mph"
alert_1_str = "Speed Limit Assist: Activation Required"
alert_2_str = f"Manually change set speed to {pcm_long_required_max_set_speed_conv} {speed_unit} to activate"
alert_size = AlertSize.mid
alert_1_str = f"Speed Limit Assist: set to {pcm_long_required_max_set_speed_conv} {speed_unit} to engage"
alert_size = AlertSize.small
return Alert(
alert_1_str,
alert_2_str,
"",
AlertStatus.normal, alert_size,
Priority.LOW, VisualAlert.none, AudibleAlertSP.promptSingleLow, .1)
@@ -193,7 +197,7 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = {
EventNameSP.speedLimitActive: {
ET.WARNING: Alert(
"Automatically adjusting to the posted speed limit",
"Auto adjusting to speed limit",
"",
AlertStatus.normal, AlertSize.small,
Priority.LOW, VisualAlert.none, AudibleAlertSP.promptSingleHigh, 5.),
@@ -213,7 +217,7 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = {
EventNameSP.speedLimitPending: {
ET.WARNING: Alert(
"Automatically adjusting to the last speed limit",
"Auto adjusting to last speed limit",
"",
AlertStatus.normal, AlertSize.small,
Priority.LOW, VisualAlert.none, AudibleAlertSP.promptSingleHigh, 5.),
+27 -19
View File
@@ -845,86 +845,94 @@
},
{
"value": 2,
"label": "5 %"
"label": "Screen Off"
},
{
"value": 3,
"label": "10 %"
"label": "5 %"
},
{
"value": 4,
"label": "15 %"
"label": "10 %"
},
{
"value": 5,
"label": "20 %"
"label": "15 %"
},
{
"value": 6,
"label": "25 %"
"label": "20 %"
},
{
"value": 7,
"label": "30 %"
"label": "25 %"
},
{
"value": 8,
"label": "35 %"
"label": "30 %"
},
{
"value": 9,
"label": "40 %"
"label": "35 %"
},
{
"value": 10,
"label": "45 %"
"label": "40 %"
},
{
"value": 11,
"label": "50 %"
"label": "45 %"
},
{
"value": 12,
"label": "55 %"
"label": "50 %"
},
{
"value": 13,
"label": "60 %"
"label": "55 %"
},
{
"value": 14,
"label": "65 %"
"label": "60 %"
},
{
"value": 15,
"label": "70 %"
"label": "65 %"
},
{
"value": 16,
"label": "75 %"
"label": "70 %"
},
{
"value": 17,
"label": "80 %"
"label": "75 %"
},
{
"value": 18,
"label": "85 %"
"label": "80 %"
},
{
"value": 19,
"label": "90 %"
"label": "85 %"
},
{
"value": 20,
"label": "95 %"
"label": "90 %"
},
{
"value": 21,
"label": "95 %"
},
{
"value": 22,
"label": "100 %"
}
]
},
"OnroadScreenOffBrightnessMigrated": {
"title": "Onroad Brightness Migration Version",
"description": "This param is to track whether OnroadScreenOffBrightness needs to be migrated."
},
"OnroadScreenOffControl": {
"title": "Onroad Brightness",
"description": "Adjusts the screen brightness while it's in onroad state."
@@ -53,9 +53,34 @@ def main():
print(f"Updated {METADATA_PATH}")
# update onroad screen brightness params
update_onroad_brightness_param()
# update torque versions param
update_torque_versions_param()
def update_onroad_brightness_param():
try:
with open(METADATA_PATH) as f:
params_metadata = json.load(f)
if "OnroadScreenOffBrightness" in params_metadata:
options = [
{"value": 0, "label": "Auto (Default)"},
{"value": 1, "label": "Auto (Dark)"},
{"value": 2, "label": "Screen Off"},
]
for i in range(3, 23):
options.append({"value": i, "label": f"{(i - 2) * 5} %"})
params_metadata["OnroadScreenOffBrightness"]["options"] = options
with open(METADATA_PATH, 'w') as f:
json.dump(params_metadata, f, indent=2)
f.write('\n')
print(f"Updated OnroadScreenOffBrightness options in params_metadata.json with {len(options)} options.")
except Exception as e:
print(f"Failed to update OnroadScreenOffBrightness versions in params_metadata.json: {e}")
def update_torque_versions_param():
with open(TORQUE_VERSIONS_JSON) as f:
current_versions = json.load(f)
@@ -81,5 +106,6 @@ def update_torque_versions_param():
except Exception as e:
print(f"Failed to update TorqueControlTune versions in params_metadata.json: {e}")
if __name__ == "__main__":
main()
View File
+27
View File
@@ -0,0 +1,27 @@
"""
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
from openpilot.common.swaglog import cloudlog
ONROAD_BRIGHTNESS_MIGRATION_VERSION: str = "1.0"
def run_migration(_params):
# migrate OnroadScreenOffBrightness
if _params.get("OnroadScreenOffBrightnessMigrated") != ONROAD_BRIGHTNESS_MIGRATION_VERSION:
try:
val = _params.get("OnroadScreenOffBrightness")
if val >= 2: # old: 5%, new: Screen Off
new_val = val + 1
_params.put("OnroadScreenOffBrightness", new_val)
log_str = f"Successfully migrated OnroadScreenOffBrightness from {val} to {new_val}."
else:
log_str = "Migration not required for OnroadScreenOffBrightness."
_params.put("OnroadScreenOffBrightnessMigrated", ONROAD_BRIGHTNESS_MIGRATION_VERSION)
cloudlog.info(log_str + f" Setting OnroadScreenOffBrightnessMigrated to {ONROAD_BRIGHTNESS_MIGRATION_VERSION}")
except Exception as e:
cloudlog.exception(f"Error migrating OnroadScreenOffBrightness: {e}")
+4
View File
@@ -22,6 +22,8 @@ from openpilot.system.version import get_build_metadata
from openpilot.system.hardware.hw import Paths
from openpilot.system.hardware import PC
from openpilot.sunnypilot.system.params_migration import run_migration
def manager_init() -> None:
save_bootlog()
@@ -49,6 +51,8 @@ def manager_init() -> None:
if params.get_bool("RecordFrontLock"):
params.put_bool("RecordFront", True)
run_migration(params)
# set unset params to their default value
for k in params.all_keys():
default_value = params.get_default_value(k)