mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-08-03 17:19:24 +08:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 813ef1ee65 | |||
| 3749b49186 | |||
| 6bea70ac86 | |||
| 25b6f84bb0 | |||
| 73092daefc |
@@ -25,7 +25,6 @@ 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}},
|
||||
|
||||
+21
-15
@@ -32,8 +32,7 @@ def flash_panda(panda_serial: str) -> Panda:
|
||||
raise
|
||||
|
||||
# skip flashing if the detected panda is not supported
|
||||
supported_panda = check_panda_support(panda)
|
||||
if not supported_panda:
|
||||
if panda.get_type() not in Panda.SUPPORTED_DEVICES:
|
||||
cloudlog.warning(f"Panda {panda_serial} is not supported (hw_type: {panda.get_type()}), skipping flash...")
|
||||
return panda
|
||||
|
||||
@@ -69,10 +68,19 @@ def flash_panda(panda_serial: str) -> Panda:
|
||||
return panda
|
||||
|
||||
|
||||
def check_panda_support(panda) -> bool:
|
||||
hw_type = panda.get_type()
|
||||
if hw_type in Panda.SUPPORTED_DEVICES:
|
||||
return True
|
||||
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...")
|
||||
|
||||
return False
|
||||
|
||||
@@ -126,13 +134,17 @@ 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")
|
||||
@@ -143,12 +155,6 @@ 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"]:
|
||||
|
||||
@@ -24,12 +24,10 @@ def draw_circle_gradient(center_x: float, center_y: float, radius: int,
|
||||
|
||||
|
||||
class ConfidenceBall(Widget, ConfidenceBallSP):
|
||||
def __init__(self, demo: bool = False, scale: float = 1.0, visual: int = 0):
|
||||
def __init__(self, demo: bool = False):
|
||||
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):
|
||||
@@ -56,7 +54,7 @@ class ConfidenceBall(Widget, ConfidenceBallSP):
|
||||
self.rect.height,
|
||||
)
|
||||
|
||||
status_dot_radius = int(24 * self._scale)
|
||||
status_dot_radius = 24
|
||||
dot_height = (1 - self._confidence_filter.x) * (content_rect.height - 2 * status_dot_radius) + status_dot_radius
|
||||
dot_height = self._rect.y + dot_height
|
||||
|
||||
@@ -83,7 +81,6 @@ class ConfidenceBall(Widget, ConfidenceBallSP):
|
||||
top_dot_color = rl.Color(50, 50, 50, 255)
|
||||
bottom_dot_color = rl.Color(13, 13, 13, 255)
|
||||
|
||||
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)
|
||||
draw_circle_gradient(content_rect.x + content_rect.width - status_dot_radius,
|
||||
dot_height, status_dot_radius,
|
||||
top_dot_color, bottom_dot_color)
|
||||
|
||||
@@ -95,7 +95,6 @@ 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,18 +120,10 @@ 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
|
||||
|
||||
@@ -143,8 +135,6 @@ 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.
|
||||
"""
|
||||
import pyray as rl
|
||||
from openpilot.selfdrive.ui.onroad.augmented_road_view import BORDER_COLORS
|
||||
from openpilot.selfdrive.ui.ui_state import ui_state, UIStatus
|
||||
|
||||
|
||||
@@ -19,26 +19,8 @@ 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,7 +8,6 @@ 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
|
||||
@@ -20,7 +19,6 @@ 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)
|
||||
@@ -31,9 +29,3 @@ 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)
|
||||
|
||||
@@ -143,7 +143,6 @@ 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: Panda) -> None:
|
||||
def flash_rivian_long(panda_serials: list[str]) -> None:
|
||||
if not os.path.isfile(FW_PATH):
|
||||
cloudlog.error(f"Rivian longitudinal upgrade firmware not found at {FW_PATH}")
|
||||
return
|
||||
@@ -83,13 +83,19 @@ def flash_rivian_long(panda: Panda) -> None:
|
||||
cloudlog.info("Not a Rivian, skipping longitudinal upgrade...")
|
||||
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()}")
|
||||
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
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
flash_rivian_long(Panda())
|
||||
flash_rivian_long(Panda.list())
|
||||
|
||||
@@ -186,24 +186,6 @@
|
||||
"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": ""
|
||||
|
||||
Reference in New Issue
Block a user