From e09fc54751d1816d0f7f570f3b518d4c5cb78edd Mon Sep 17 00:00:00 2001 From: FrogAi <91348155+FrogAi@users.noreply.github.com> Date: Sat, 11 May 2024 14:29:53 -0700 Subject: [PATCH] Visuals - Developer UI - Sidebar Display various custom metrics on the sidebar for the CPU, GPU, RAM, IP, and storage used/left. --- selfdrive/thermald/thermald.py | 5 +- selfdrive/ui/qt/sidebar.cc | 129 ++++++++++++++++++++++++++++++--- selfdrive/ui/qt/sidebar.h | 14 ++++ selfdrive/ui/ui.cc | 7 ++ selfdrive/ui/ui.h | 7 ++ system/loggerd/config.py | 11 +++ 6 files changed, 162 insertions(+), 11 deletions(-) diff --git a/selfdrive/thermald/thermald.py b/selfdrive/thermald/thermald.py index 79733d1..291a194 100755 --- a/selfdrive/thermald/thermald.py +++ b/selfdrive/thermald/thermald.py @@ -18,7 +18,7 @@ from openpilot.common.params import Params from openpilot.common.realtime import DT_TRML from openpilot.selfdrive.controls.lib.alertmanager import set_offroad_alert from openpilot.system.hardware import HARDWARE, TICI, AGNOS -from openpilot.system.loggerd.config import get_available_percent +from openpilot.system.loggerd.config import get_available_bytes, get_available_percent, get_used_bytes from openpilot.selfdrive.statsd import statlog from openpilot.common.swaglog import cloudlog from openpilot.selfdrive.thermald.power_monitoring import PowerMonitoring @@ -246,6 +246,9 @@ def thermald_thread(end_event, hw_queue, frogpilot_toggles) -> None: fpmsg = messaging.new_message('frogpilotDeviceState') + fpmsg.frogpilotDeviceState.freeSpace = round(get_available_bytes(default=32.0 * (2 ** 30)) / (2 ** 30)) + fpmsg.frogpilotDeviceState.usedSpace = round(get_used_bytes(default=0.0 * (2 ** 30)) / (2 ** 30)) + pm.send("frogpilotDeviceState", fpmsg) msg.deviceState.freeSpacePercent = get_available_percent(default=100.0) diff --git a/selfdrive/ui/qt/sidebar.cc b/selfdrive/ui/qt/sidebar.cc index 48b9849..095518b 100644 --- a/selfdrive/ui/qt/sidebar.cc +++ b/selfdrive/ui/qt/sidebar.cc @@ -89,11 +89,44 @@ Sidebar::Sidebar(QWidget *parent) : QFrame(parent), onroad(false), flag_pressed( } void Sidebar::mousePressEvent(QMouseEvent *event) { + QRect cpuRect = {30, 496, 240, 126}; + QRect memoryRect = {30, 654, 240, 126}; QRect tempRect = {30, 338, 240, 126}; + static int showChip = 0; + static int showMemory = 0; static int showTemp = 0; - if (tempRect.contains(event->pos())) { + if (cpuRect.contains(event->pos()) && sidebarMetrics) { + showChip = (showChip + 1) % 3; + + isCPU = (showChip == 1); + isGPU = (showChip == 2); + + scene.is_CPU = isCPU; + scene.is_GPU = isGPU; + + params.putBoolNonBlocking("ShowCPU", isCPU); + params.putBoolNonBlocking("ShowGPU", isGPU); + + update(); + } else if (memoryRect.contains(event->pos()) && sidebarMetrics) { + showMemory = (showMemory + 1) % 4; + + isMemoryUsage = (showMemory == 1); + isStorageLeft = (showMemory == 2); + isStorageUsed = (showMemory == 3); + + scene.is_memory = isMemoryUsage; + scene.is_storage_left = isStorageLeft; + scene.is_storage_used = isStorageUsed; + + params.putBoolNonBlocking("ShowMemoryUsage", isMemoryUsage); + params.putBoolNonBlocking("ShowStorageLeft", isStorageLeft); + params.putBoolNonBlocking("ShowStorageUsed", isStorageUsed); + + update(); + } else if (tempRect.contains(event->pos()) && sidebarMetrics) { showTemp = (showTemp + 1) % 3; scene.fahrenheit = showTemp == 2; @@ -156,11 +189,65 @@ void Sidebar::updateState(const UIState &s) { auto frogpilotDeviceState = sm["frogpilotDeviceState"].getFrogpilotDeviceState(); - bool isNumericalTemp = scene.numerical_temp; + isCPU = scene.is_CPU; + isGPU = scene.is_GPU; + isIP = scene.is_IP; + isMemoryUsage = scene.is_memory; + isNumericalTemp = scene.numerical_temp; + isStorageLeft = scene.is_storage_left; + isStorageUsed = scene.is_storage_used; + sidebarMetrics = scene.sidebar_metrics; int maxTempC = deviceState.getMaxTempC(); QString max_temp = scene.fahrenheit ? QString::number(maxTempC * 9 / 5 + 32) + "°F" : QString::number(maxTempC) + "°C"; + if (isCPU || isGPU) { + auto cpu_loads = deviceState.getCpuUsagePercent(); + int cpu_usage = std::accumulate(cpu_loads.begin(), cpu_loads.end(), 0) / cpu_loads.size(); + int gpu_usage = deviceState.getGpuUsagePercent(); + + QString cpu = QString::number(cpu_usage) + "%"; + QString gpu = QString::number(gpu_usage) + "%"; + + QString metric = isGPU ? gpu : cpu; + int usage = isGPU ? gpu_usage : cpu_usage; + + ItemStatus cpuStatus = {{isGPU ? tr("GPU") : tr("CPU"), metric}, currentColors[0]}; + if (usage >= 85) { + cpuStatus = {{isGPU ? tr("GPU") : tr("CPU"), metric}, danger_color}; + } else if (usage >= 70) { + cpuStatus = {{isGPU ? tr("GPU") : tr("CPU"), metric}, warning_color}; + } + setProperty("cpuStatus", QVariant::fromValue(cpuStatus)); + } + + if (isMemoryUsage || isStorageLeft || isStorageUsed) { + int memory_usage = deviceState.getMemoryUsagePercent(); + int storage_left = frogpilotDeviceState.getFreeSpace(); + int storage_used = frogpilotDeviceState.getUsedSpace(); + + QString memory = QString::number(memory_usage) + "%"; + QString storage = QString::number(isStorageLeft ? storage_left : storage_used) + tr(" GB"); + + if (isMemoryUsage) { + ItemStatus memoryStatus = {{tr("MEMORY"), memory}, currentColors[0]}; + if (memory_usage >= 85) { + memoryStatus = {{tr("MEMORY"), memory}, danger_color}; + } else if (memory_usage >= 70) { + memoryStatus = {{tr("MEMORY"), memory}, warning_color}; + } + setProperty("memoryStatus", QVariant::fromValue(memoryStatus)); + } else { + ItemStatus storageStatus = {{isStorageLeft ? tr("LEFT") : tr("USED"), storage}, currentColors[0]}; + if (25 > storage_left && storage_left >= 10) { + storageStatus = {{isStorageLeft ? tr("LEFT") : tr("USED"), storage}, warning_color}; + } else if (10 > storage_left) { + storageStatus = {{isStorageLeft ? tr("LEFT") : tr("USED"), storage}, danger_color}; + } + setProperty("storageStatus", QVariant::fromValue(storageStatus)); + } + } + ItemStatus connectStatus; auto last_ping = deviceState.getLastAthenaPingTime(); if (last_ping == 0) { @@ -207,19 +294,41 @@ void Sidebar::paintEvent(QPaintEvent *event) { // network int x = 58; const QColor gray(0x54, 0x54, 0x54); - for (int i = 0; i < 5; ++i) { - p.setBrush(i < net_strength ? Qt::white : gray); - p.drawEllipse(x, 196, 27, 27); - x += 37; + p.setFont(InterFont(35)); + + if (isIP) { + p.setPen(QColor(0xff, 0xff, 0xff)); + p.save(); + p.setFont(InterFont(30)); + QRect ipBox = QRect(50, 196, 225, 27); + p.drawText(ipBox, Qt::AlignLeft | Qt::AlignVCenter, uiState()->wifi->getIp4Address()); + p.restore(); + } else { + for (int i = 0; i < 5; ++i) { + p.setBrush(i < net_strength ? Qt::white : gray); + p.drawEllipse(x, 196, 27, 27); + x += 37; + } + p.setPen(QColor(0xff, 0xff, 0xff)); } - p.setFont(InterFont(35)); - p.setPen(QColor(0xff, 0xff, 0xff)); const QRect r = QRect(50, 247, 100, 50); p.drawText(r, Qt::AlignCenter, net_type); // metrics drawMetric(p, temp_status.first, temp_status.second, 338); - drawMetric(p, panda_status.first, panda_status.second, 496); - drawMetric(p, connect_status.first, connect_status.second, 654); + + if (isCPU || isGPU) { + drawMetric(p, cpu_status.first, cpu_status.second, 496); + } else { + drawMetric(p, panda_status.first, panda_status.second, 496); + } + + if (isMemoryUsage) { + drawMetric(p, memory_status.first, memory_status.second, 654); + } else if (isStorageLeft || isStorageUsed) { + drawMetric(p, storage_status.first, storage_status.second, 654); + } else { + drawMetric(p, connect_status.first, connect_status.second, 654); + } } diff --git a/selfdrive/ui/qt/sidebar.h b/selfdrive/ui/qt/sidebar.h index 202ddfd..dc5958f 100644 --- a/selfdrive/ui/qt/sidebar.h +++ b/selfdrive/ui/qt/sidebar.h @@ -18,6 +18,11 @@ class Sidebar : public QFrame { Q_PROPERTY(QString netType MEMBER net_type NOTIFY valueChanged); Q_PROPERTY(int netStrength MEMBER net_strength NOTIFY valueChanged); + // FrogPilot properties + Q_PROPERTY(ItemStatus cpuStatus MEMBER cpu_status NOTIFY valueChanged) + Q_PROPERTY(ItemStatus memoryStatus MEMBER memory_status NOTIFY valueChanged) + Q_PROPERTY(ItemStatus storageStatus MEMBER storage_status NOTIFY valueChanged) + public: explicit Sidebar(QWidget* parent = 0); @@ -64,7 +69,16 @@ private: Params params; UIScene &scene; + ItemStatus cpu_status, memory_status, storage_status; + + bool isCPU; + bool isGPU; + bool isIP; + bool isMemoryUsage; bool isNumericalTemp; + bool isStorageLeft; + bool isStorageUsed; + bool sidebarMetrics; std::unordered_map>> themeConfiguration; std::unordered_map flag_imgs; diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 2c1ae4a..9d0fc70 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -347,6 +347,13 @@ void ui_update_frogpilot_params(UIState *s) { scene.fahrenheit = scene.numerical_temp && params.getBool("Fahrenheit"); scene.show_jerk = scene.longitudinal_control && developer_ui && params.getBool("LongitudinalMetrics"); scene.show_tuning = developer_ui && scene.has_auto_tune && params.getBool("LateralMetrics"); + scene.sidebar_metrics = developer_ui && params.getBool("SidebarMetrics"); + scene.is_CPU = scene.sidebar_metrics && params.getBool("ShowCPU"); + scene.is_GPU = scene.sidebar_metrics && params.getBool("ShowGPU"); + scene.is_IP = scene.sidebar_metrics && params.getBool("ShowIP"); + scene.is_memory = scene.sidebar_metrics && params.getBool("ShowMemoryUsage"); + scene.is_storage_left = scene.sidebar_metrics && params.getBool("ShowStorageLeft"); + scene.is_storage_used = scene.sidebar_metrics && params.getBool("ShowStorageUsed"); scene.disable_smoothing_mtsc = params.getBool("MTSCEnabled") && params.getBool("DisableMTSCSmoothing"); scene.disable_smoothing_vtsc = params.getBool("VisionTurnControl") && params.getBool("DisableVTSCSmoothing"); diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index ebb2771..4d66573 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -206,6 +206,12 @@ typedef struct UIScene { bool fps_counter; bool has_auto_tune; bool holiday_themes; + bool is_CPU; + bool is_GPU; + bool is_IP; + bool is_memory; + bool is_storage_left; + bool is_storage_used; bool lead_info; bool live_valid; bool map_open; @@ -229,6 +235,7 @@ typedef struct UIScene { bool show_slc_offset_ui; bool show_steering; bool show_tuning; + bool sidebar_metrics; bool speed_limit_changed; bool speed_limit_controller; bool speed_limit_overridden; diff --git a/system/loggerd/config.py b/system/loggerd/config.py index 5c2c89b..03abe21 100644 --- a/system/loggerd/config.py +++ b/system/loggerd/config.py @@ -27,3 +27,14 @@ def get_available_bytes(default=None): available_bytes = default return available_bytes + +def get_used_bytes(default=None): + try: + statvfs = os.statvfs(Paths.log_root()) + total_bytes = statvfs.f_blocks * statvfs.f_frsize + available_bytes = get_available_bytes(default) + used_bytes = total_bytes - available_bytes + except OSError: + used_bytes = default + + return used_bytes