Compare commits

..

27 Commits

Author SHA1 Message Date
royjr 03eb57b79c Merge branch 'master' into visuals-confidence-ball 2026-03-02 02:40:52 -05:00
royjr 27cb5c02a3 Merge branch 'master' into visuals-confidence-ball 2026-02-13 22:22:15 -05:00
royjr f7e156d4ab Update ui_state.py 2026-02-13 00:36:56 -05:00
royjr 6ab6c9511f cleaner 2026-02-13 00:18:26 -05:00
royjr 7ba74317c7 Merge branch 'master' into visuals-confidence-ball 2026-02-12 23:49:33 -05:00
royjr d9080a7128 move to ConfidenceBallSP 2026-02-12 23:46:09 -05:00
royjr d954ae4b7a move to AugmentedRoadViewSP 2026-02-12 23:31:24 -05:00
royjr fdda381d1f Merge branch 'master' into visuals-confidence-ball 2026-02-12 23:19:10 -05:00
royjr 68ddad7f5c Update params_metadata.json 2026-02-11 01:44:49 -05:00
royjr 820bef3255 000 2026-02-11 01:41:40 -05:00
royjr dcb80a627b visual 2026-02-11 01:37:57 -05:00
royjr 731108a5a8 simpler 2026-02-11 01:21:46 -05:00
royjr f0dba2446a ConfidenceVisual 2026-02-11 01:14:41 -05:00
royjr 1277503e7a move to visuals panel 2026-02-11 00:47:47 -05:00
royjr dfd5a6a617 Merge branch 'master' into visuals-confidence-ball 2026-02-11 00:38:12 -05:00
royjr fb36ee47b8 Update confidence_ball.py 2026-02-11 00:38:04 -05:00
royjr f44952f09a Merge branch 'master' into visuals-confidence-ball 2026-02-11 00:24:50 -05:00
Jason Wen 88633bc5bf Merge branch 'master' into visuals-confidence-ball 2026-02-08 17:01:31 -05:00
royjr 5f6b9b9b74 Merge branch 'master' into visuals-confidence-ball 2026-02-05 00:53:44 -05:00
royjr f9804e4899 bool 2025-12-31 14:18:16 -05:00
royjr bd41dbcd5d cleaner 2025-12-29 23:08:41 -05:00
royjr 3c54a91ffb Update params_metadata.json 2025-12-29 22:53:10 -05:00
royjr 46b8732a00 Update params_keys.h 2025-12-29 14:47:16 -05:00
royjr c5e3fd7323 add toggle 2025-12-29 14:42:09 -05:00
royjr 7f55fd5b39 Merge branch 'master' into visuals-confidence-ball 2025-12-29 14:35:46 -05:00
royjr 2067dbd823 bar 2025-11-28 00:56:47 -05:00
royjr 67345f59b7 init 2025-11-28 00:45:24 -05:00
10 changed files with 89 additions and 41 deletions
+1
View File
@@ -25,6 +25,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"CarParamsPersistent", {PERSISTENT, BYTES}},
{"CarParamsPrevRoute", {PERSISTENT, BYTES}},
{"CompletedTrainingVersion", {PERSISTENT, STRING, "0"}},
{"ConfidenceVisual", {PERSISTENT | BACKUP, INT, "0"}},
{"ControlsReady", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
{"CurrentBootlog", {PERSISTENT, STRING}},
{"CurrentRoute", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, STRING}},
+15 -21
View File
@@ -32,7 +32,8 @@ def flash_panda(panda_serial: str) -> Panda:
raise
# skip flashing if the detected panda is not supported
if panda.get_type() not in Panda.SUPPORTED_DEVICES:
supported_panda = check_panda_support(panda)
if not supported_panda:
cloudlog.warning(f"Panda {panda_serial} is not supported (hw_type: {panda.get_type()}), skipping flash...")
return panda
@@ -68,19 +69,10 @@ def flash_panda(panda_serial: str) -> Panda:
return panda
def check_panda_support(panda_serials: list[str]) -> bool:
unsupported = []
for serial in panda_serials:
panda = Panda(serial)
hw_type = panda.get_type()
panda.close()
if hw_type in Panda.SUPPORTED_DEVICES:
return True
unsupported.append((serial, hw_type))
for serial, hw_type in unsupported:
cloudlog.warning(f"Panda {serial} is not supported (hw_type: {hw_type}), skipping...")
def check_panda_support(panda) -> bool:
hw_type = panda.get_type()
if hw_type in Panda.SUPPORTED_DEVICES:
return True
return False
@@ -134,17 +126,13 @@ def main() -> None:
cloudlog.info(f"{len(panda_serials)} panda(s) found, connecting - {panda_serials}")
# custom flasher for xnor's Rivian Longitudinal Upgrade Kit
flash_rivian_long(panda_serials)
# skip flashing and health check if no supported panda is detected
if not check_panda_support(panda_serials):
continue
# Flash the first panda
panda_serial = panda_serials[0]
panda = flash_panda(panda_serial)
# flash Rivian longitudinal upgrade panda
flash_rivian_long(panda)
# Ensure internal panda is present if expected
if HARDWARE.has_internal_panda() and not panda.is_internal():
cloudlog.error("Internal panda is missing, trying again")
@@ -155,6 +143,12 @@ def main() -> None:
# log panda fw version
params.put("PandaSignatures", panda.get_signature())
# skip health check if the detected panda is not supported
supported_panda = check_panda_support(panda)
if not supported_panda:
cloudlog.warning(f"Panda {panda.get_usb_serial()} is not supported (hw_type: {panda.get_type()}), skipping health check...")
continue
# check health for lost heartbeat
health = panda.health()
if health["heartbeat_lost"]:
+8 -5
View File
@@ -24,10 +24,12 @@ def draw_circle_gradient(center_x: float, center_y: float, radius: int,
class ConfidenceBall(Widget, ConfidenceBallSP):
def __init__(self, demo: bool = False):
def __init__(self, demo: bool = False, scale: float = 1.0, visual: int = 0):
Widget.__init__(self)
ConfidenceBallSP.__init__(self)
self._demo = demo
self._scale = scale
self._visual = visual
self._confidence_filter = FirstOrderFilter(-0.5, 0.5, 1 / gui_app.target_fps)
def update_filter(self, value: float):
@@ -54,7 +56,7 @@ class ConfidenceBall(Widget, ConfidenceBallSP):
self.rect.height,
)
status_dot_radius = 24
status_dot_radius = int(24 * self._scale)
dot_height = (1 - self._confidence_filter.x) * (content_rect.height - 2 * status_dot_radius) + status_dot_radius
dot_height = self._rect.y + dot_height
@@ -81,6 +83,7 @@ class ConfidenceBall(Widget, ConfidenceBallSP):
top_dot_color = rl.Color(50, 50, 50, 255)
bottom_dot_color = rl.Color(13, 13, 13, 255)
draw_circle_gradient(content_rect.x + content_rect.width - status_dot_radius,
dot_height, status_dot_radius,
top_dot_color, bottom_dot_color)
if not self.update_confidence_visual(content_rect, status_dot_radius, dot_height, top_dot_color, bottom_dot_color):
draw_circle_gradient(content_rect.x + content_rect.width - status_dot_radius,
dot_height, status_dot_radius,
top_dot_color, bottom_dot_color)
@@ -95,6 +95,7 @@ class AugmentedRoadView(CameraView, AugmentedRoadViewSP):
# Draw all UI overlays
self.model_renderer.render(self._content_rect)
AugmentedRoadViewSP.update_fade_out_bottom_overlay(self, self._content_rect)
self.update_confidence_visual(self._content_rect)
self._hud_renderer.render(self._content_rect)
self.alert_renderer.render(self._content_rect)
self.driver_state_renderer.render(self._content_rect)
@@ -120,10 +120,18 @@ class VisualsLayout(Widget):
button_width=350,
inline=False
)
self._confidence_visual = multiple_button_item_sp(
title=lambda: tr("Confidence Visual"),
description=lambda: tr("Display confidence ball or bar on the driving screen."),
buttons=[lambda: tr("Off"), lambda: tr("Ball"), lambda: tr("Bar")],
param="ConfidenceVisual",
inline=False
)
items = list(self._toggles.values()) + [
self._chevron_info,
self._dev_ui_info,
self._confidence_visual,
]
return items
@@ -135,6 +143,8 @@ class VisualsLayout(Widget):
self._dev_ui_info.action_item.set_selected_button(ui_state.params.get("DevUIInfo", return_default=True))
self._confidence_visual.action_item.set_selected_button(ui_state.params.get("ConfidenceVisual", return_default=True))
if ui_state.has_longitudinal_control:
self._chevron_info.set_description(tr(CHEVRON_INFO_DESCRIPTION["enabled"]))
self._chevron_info.action_item.set_selected_button(ui_state.params.get("ChevronInfo", return_default=True))
@@ -4,7 +4,7 @@ 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.selfdrive.ui.onroad.augmented_road_view import BORDER_COLORS
import pyray as rl
from openpilot.selfdrive.ui.ui_state import ui_state, UIStatus
@@ -19,8 +19,26 @@ class ConfidenceBallSP:
@staticmethod
def get_lat_long_dot_color():
from openpilot.selfdrive.ui.onroad.augmented_road_view import BORDER_COLORS
if ui_state.status == UIStatus.LAT_ONLY:
return BORDER_COLORS[UIStatus.LAT_ONLY]
# UIStatus.LONG_ONLY
return BORDER_COLORS[UIStatus.LONG_ONLY]
def update_confidence_visual(self, content_rect, status_dot_radius, dot_height, top_dot_color, bottom_dot_color) -> bool:
if self._visual == 2:
bar_width = int(20 * self._scale)
bar_x = content_rect.x + content_rect.width - bar_width
fill_h = int(content_rect.height * self._confidence_filter.x)
fill_y = int(content_rect.y + (content_rect.height - fill_h))
rl.draw_rectangle(int(bar_x), int(content_rect.y), bar_width, int(content_rect.height), rl.Color(20, 20, 20, 180))
rl.draw_rectangle_gradient_v(int(bar_x), fill_y, bar_width, fill_h, top_dot_color, bottom_dot_color)
return True
elif self._visual == 1:
rl.draw_circle_gradient(int(content_rect.x + content_rect.width - status_dot_radius),
int(dot_height), status_dot_radius,
top_dot_color, bottom_dot_color)
return True
return False
@@ -8,6 +8,7 @@ import pyray as rl
from openpilot.common.filter_simple import FirstOrderFilter
from openpilot.selfdrive.ui.ui_state import UIStatus, ui_state
from openpilot.system.ui.lib.application import gui_app
from openpilot.selfdrive.ui.mici.onroad.confidence_ball import ConfidenceBall
BORDER_COLORS_SP = {
UIStatus.LAT_ONLY: rl.Color(0x00, 0xC8, 0xC8, 0xFF), # Cyan for lateral-only state
@@ -19,6 +20,7 @@ class AugmentedRoadViewSP:
def __init__(self):
self._fade_texture = gui_app.texture("icons_mici/onroad/onroad_fade.png")
self._fade_alpha_filter = FirstOrderFilter(0, 0.1, 1 / gui_app.target_fps)
self._confidence_visual = ConfidenceBall(scale=1.5)
def update_fade_out_bottom_overlay(self, _content_rect):
# Fade out bottom of overlays for looks (only when engaged)
@@ -29,3 +31,9 @@ class AugmentedRoadViewSP:
rl.Rectangle(0, 0, self._fade_texture.width, self._fade_texture.height),
_content_rect, rl.Vector2(0, 0), 0.0,
rl.Color(255, 255, 255, int(255 * fade_alpha)))
def update_confidence_visual(self, _content_rect):
mode = ui_state.confidence_visual
if mode in (1, 2):
self._confidence_visual._visual = mode
self._confidence_visual.render(_content_rect)
+1
View File
@@ -143,6 +143,7 @@ class UIStateSP:
self.true_v_ego_ui = self.params.get_bool("TrueVEgoUI")
self.turn_signals = self.params.get_bool("ShowTurnSignals")
self.boot_offroad_mode = self.params.get("DeviceBootMode", return_default=True)
self.confidence_visual = self.params.get("ConfidenceVisual", return_default=True)
class DeviceSP:
@@ -74,7 +74,7 @@ def _flash_panda(panda: Panda) -> None:
panda.reconnect()
def flash_rivian_long(panda_serials: list[str]) -> None:
def flash_rivian_long(panda: Panda) -> None:
if not os.path.isfile(FW_PATH):
cloudlog.error(f"Rivian longitudinal upgrade firmware not found at {FW_PATH}")
return
@@ -83,19 +83,13 @@ def flash_rivian_long(panda_serials: list[str]) -> None:
cloudlog.info("Not a Rivian, skipping longitudinal upgrade...")
return
for serial in panda_serials:
panda = Panda(serial)
# only flash external black pandas (HW_TYPE_BLACK = 0x03)
if panda.get_type() == b'\x03' and not panda.is_internal():
try:
_flash_panda(panda)
cloudlog.info(f"Successfully flashed xnor's Rivian Longitudinal Upgrade Kit: {serial}")
except Exception:
cloudlog.exception(f"Failed to flash xnor's Rivian Longitudinal Upgrade Kit: {serial}")
panda.close()
return
# only flash external black pandas (HW_TYPE_BLACK = 0x03)
if panda.get_type() == b'\x03' and not panda.is_internal():
try:
_flash_panda(panda)
except Exception:
cloudlog.exception(f"Failed to flash F4 panda {panda.get_usb_serial()}")
if __name__ == '__main__':
flash_rivian_long(Panda.list())
flash_rivian_long(Panda())
+18
View File
@@ -186,6 +186,24 @@
"title": "Completed Training Version",
"description": ""
},
"ConfidenceVisual": {
"title": "Confidence Visual",
"description": "Display confidence ball or bar on the driving screen.",
"options": [
{
"value": 0,
"label": "Off"
},
{
"value": 1,
"label": "Ball"
},
{
"value": 2,
"label": "Bar"
}
]
},
"ControlsReady": {
"title": "Controls Ready",
"description": ""