Merge branch 'master-new' into ccnc-port

This commit is contained in:
royjr
2025-06-28 12:13:26 -04:00
2 changed files with 135 additions and 30 deletions
@@ -7,21 +7,55 @@
#include <algorithm>
#include <QJsonDocument>
#include <QStyle>
#include "common/model.h"
#include "selfdrive/ui/sunnypilot/qt/offroad/settings/models_panel.h"
#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h"
static const QString progressStyleActive = "QProgressBar {"
" font-size: 40px;"
" font-weight: 200;"
" padding: 1px;"
" border: 3px solid black;"
" border-radius: 10px;"
"}"
"QProgressBar::chunk {"
" background-color: #1e79e8;"
" border-radius: 10px;"
"}";
static const QString progressStyleInactive = progressStyleActive +
"QProgressBar::chunk {"
" background-color: transparent;"
"}";
static const QString progressStyleDone = progressStyleActive +
"QProgressBar {"
" color: #33ab4c;"
"}"
"QProgressBar::chunk {"
" background-color: transparent;"
"}";
static const QString progressStyleError = progressStyleActive +
"QProgressBar {"
" color: red;"
"}"
"QProgressBar::chunk {"
" background-color: transparent;"
"}";
ModelsPanel::ModelsPanel(QWidget *parent) : QWidget(parent) {
QVBoxLayout *main_layout = new QVBoxLayout(this);
main_layout->setContentsMargins(50, 20, 50, 20);
ListWidgetSP *list = new ListWidgetSP(this);
ListWidgetSP *list = new ListWidgetSP(this, false);
ScrollViewSP *scroller = new ScrollViewSP(list, this);
main_layout->addWidget(scroller);
const auto current_model = GetActiveModelName();
currentModelLblBtn = new ButtonControlSP(tr("Current Model"), tr("SELECT"), current_model);
currentModelLblBtn = new ButtonControlSP(tr("Current Model"), tr("SELECT"), "", this);
currentModelLblBtn->setValue(current_model);
connect(currentModelLblBtn, &ButtonControlSP::clicked, this, &ModelsPanel::handleCurrentModelLblBtnClicked);
@@ -32,6 +66,29 @@ ModelsPanel::ModelsPanel(QWidget *parent) : QWidget(parent) {
connect(uiStateSP(), &UIStateSP::uiUpdate, this, &ModelsPanel::updateLabels);
list->addItem(currentModelLblBtn);
// Create progress bars for downloads
supercomboProgressBar = createProgressBar(this);
QString supercomboType = tr("Driving Model");
supercomboFrame = createModelDetailFrame(this, supercomboType, supercomboProgressBar);
list->addItem(supercomboFrame);
navigationProgressBar = createProgressBar(this);
QString navigationType = tr("Navigation Model");
navigationFrame = createModelDetailFrame(this, navigationType, navigationProgressBar);
list->addItem(navigationFrame);
visionProgressBar = createProgressBar(this);
QString visionType = tr("Vision Model");
visionFrame = createModelDetailFrame(this, visionType, visionProgressBar);
list->addItem(visionFrame);
policyProgressBar = createProgressBar(this);
QString policyType = tr("Policy Model");
policyFrame = createModelDetailFrame(this, policyType, policyProgressBar);
list->addItem(policyFrame);
list->addItem(horizontal_line());
// LiveDelay toggle
list->addItem(new ParamControlSP("LagdToggle",
tr("Live Learning Steer Delay"),
@@ -40,15 +97,38 @@ ModelsPanel::ModelsPanel(QWidget *parent) : QWidget(parent) {
"../assets/offroad/icon_shell.png"));
}
QProgressBar* ModelsPanel::createProgressBar(QWidget *parent) {
QProgressBar *progressBar = new QProgressBar(parent);
progressBar->setRange(0, 100);
progressBar->setValue(0);
progressBar->setTextVisible(true);
progressBar->setAlignment(Qt::AlignVCenter);
return progressBar;
}
QFrame* ModelsPanel::createModelDetailFrame(QWidget *parent, QString &typeName, QProgressBar *progressBar) {
QFrame *frame = new QFrame(parent);
QHBoxLayout *layout = new QHBoxLayout(frame);
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(50);
layout->addWidget(new QLabel(typeName));
layout->addWidget(progressBar);
frame->setVisible(false);
return frame;
}
/**
* @brief Updates the UI with bundle download progress information
* Reads status from modelManagerSP cereal message and displays status for all models
*/
void ModelsPanel::handleBundleDownloadProgress() {
supercomboFrame->setVisible(false);
visionFrame->setVisible(false);
policyFrame->setVisible(false);
navigationFrame->setVisible(false);
using DS = cereal::ModelManagerSP::DownloadStatus;
if (!model_manager.hasSelectedBundle() && !model_manager.hasActiveBundle()) {
currentModelLblBtn->setDescription(tr("No custom model selected!"));
return;
}
@@ -61,21 +141,27 @@ void ModelsPanel::handleBundleDownloadProgress() {
// Get status for each model type in order
for (const auto &model: models) {
QString typeName;
QString modelName = QString::fromStdString(bundle.getDisplayName());
QProgressBar *progressBar = nullptr;
QFrame *modelFrame = nullptr;
switch (model.getType()) {
case cereal::ModelManagerSP::Model::Type::SUPERCOMBO:
typeName = tr("Driving");
progressBar = supercomboProgressBar;
modelFrame = supercomboFrame;
break;
case cereal::ModelManagerSP::Model::Type::NAVIGATION:
typeName = tr("Navigation");
progressBar = navigationProgressBar;
modelFrame = navigationFrame;
break;
case cereal::ModelManagerSP::Model::Type::VISION:
typeName = tr("Vision");
progressBar = visionProgressBar;
modelFrame = visionFrame;
break;
case cereal::ModelManagerSP::Model::Type::POLICY:
typeName = tr("Policy");
progressBar = policyProgressBar;
modelFrame = policyFrame;
break;
}
@@ -83,31 +169,26 @@ void ModelsPanel::handleBundleDownloadProgress() {
QString line;
if (progress.getStatus() == cereal::ModelManagerSP::DownloadStatus::DOWNLOADING) {
line = tr("Downloading %1 model [%2]... (%3%)").arg(typeName, modelName).arg(progress.getProgress(), 0, 'f', 2);
progressBar->setStyleSheet(progressStyleActive);
progressBar->setValue(progress.getProgress());
progressBar->setFormat(QString(" %1% - %2").arg(static_cast<int>(progress.getProgress())).arg(modelName));
device()->resetInteractiveTimeout();
} else if (progress.getStatus() == cereal::ModelManagerSP::DownloadStatus::DOWNLOADED) {
line = tr("%1 model [%2] %3").arg(typeName, modelName, download_status_changed ? tr("downloaded") : tr("ready"));
progressBar->setStyleSheet(progressStyleDone);
progressBar->setFormat(tr(" %1 - %2").arg(modelName, download_status_changed ? tr("downloaded") : tr("ready")));
} else if (progress.getStatus() == cereal::ModelManagerSP::DownloadStatus::CACHED) {
line = tr("%1 model [%2] %3").arg(typeName, modelName, download_status_changed ? tr("from cache") : tr("ready"));
progressBar->setStyleSheet(progressStyleDone);
progressBar->setFormat(tr(" %1 - %2").arg(modelName, download_status_changed ? tr("from cache") : tr("ready")));
} else if (progress.getStatus() == cereal::ModelManagerSP::DownloadStatus::FAILED) {
line = tr("%1 model [%2] download failed").arg(typeName, modelName);
progressBar->setStyleSheet(progressStyleError);
progressBar->setFormat(tr(" download failed - %1").arg(modelName));
} else {
line = tr("%1 model [%2] pending...").arg(typeName, modelName);
progressBar->setStyleSheet(progressStyleInactive);
progressBar->setFormat(tr(" pending - %1").arg(modelName));
}
status.append(line);
}
currentModelLblBtn->setDescription(status.join("\n"));
if (prev_download_status != download_status) {
switch (bundle.getStatus()) {
case cereal::ModelManagerSP::DownloadStatus::DOWNLOADING:
case cereal::ModelManagerSP::DownloadStatus::CACHED:
case cereal::ModelManagerSP::DownloadStatus::DOWNLOADED:
currentModelLblBtn->showDescription();
break;
case cereal::ModelManagerSP::DownloadStatus::FAILED:
default:
break;
// keep navigation hidden for now to avoid confusion
if (model.getType() != cereal::ModelManagerSP::Model::Type::NAVIGATION) {
modelFrame->setVisible(true);
}
}
prev_download_status = download_status;
@@ -125,6 +206,17 @@ QString ModelsPanel::GetActiveModelName() {
return DEFAULT_MODEL;
}
/**
* @brief Gets the short name of the currently selected model bundle
* @return Display short name of the selected bundle or default model name
*/
QString ModelsPanel::GetActiveModelInternalName() {
if (model_manager.hasActiveBundle()) {
return QString::fromStdString(model_manager.getActiveBundle().getInternalName());
}
return DEFAULT_MODEL;
}
void ModelsPanel::updateModelManagerState() {
const SubMaster &sm = *(uiStateSP()->sm);
model_manager = sm["modelManagerSP"].getModelManagerSP();
@@ -156,7 +248,7 @@ void ModelsPanel::handleCurrentModelLblBtnClicked() {
bundleNames.append(index_to_bundle[index]);
}
currentModelLblBtn->setValue(GetActiveModelName());
currentModelLblBtn->setValue(GetActiveModelInternalName());
const QString selectedBundleName = MultiOptionDialog::getSelection(
tr("Select a Model"), bundleNames, GetActiveModelName(), this);
@@ -197,7 +289,7 @@ void ModelsPanel::updateLabels() {
updateModelManagerState();
handleBundleDownloadProgress();
currentModelLblBtn->setEnabled(!is_onroad && !isDownloading());
currentModelLblBtn->setValue(GetActiveModelName());
currentModelLblBtn->setValue(GetActiveModelInternalName());
}
/**
@@ -7,6 +7,8 @@
#pragma once
#include <QProgressBar>
#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h"
class ModelsPanel : public QWidget {
@@ -17,6 +19,7 @@ public:
private:
QString GetActiveModelName();
QString GetActiveModelInternalName();
void updateModelManagerState();
bool isDownloading() const {
@@ -33,6 +36,8 @@ private:
void handleCurrentModelLblBtnClicked();
void handleBundleDownloadProgress();
void showResetParamsDialog();
QProgressBar* createProgressBar(QWidget *parent);
QFrame* createModelDetailFrame(QWidget *parent, QString &typeName, QProgressBar *progressBar);
cereal::ModelManagerSP::Reader model_manager;
cereal::ModelManagerSP::DownloadStatus download_status{};
cereal::ModelManagerSP::DownloadStatus prev_download_status{};
@@ -59,6 +64,14 @@ private:
bool is_onroad = false;
ButtonControlSP *currentModelLblBtn;
QProgressBar *supercomboProgressBar;
QFrame *supercomboFrame;
QProgressBar *navigationProgressBar;
QFrame *navigationFrame;
QProgressBar *visionProgressBar;
QFrame *visionFrame;
QProgressBar *policyProgressBar;
QFrame *policyFrame;
Params params;
};