Controls - Model Management - Model Randomizer

This commit is contained in:
FrogAi
2024-07-19 00:10:35 -07:00
parent d86004f249
commit 0184727891
7 changed files with 333 additions and 2 deletions
@@ -1,4 +1,5 @@
import os
import random
from types import SimpleNamespace
@@ -186,7 +187,13 @@ class FrogPilotVariables:
current_model = self.params_memory.get("CurrentModel", encoding='utf-8')
current_model_name = self.params_memory.get("CurrentModelName", encoding='utf-8')
if toggle.model_manager and available_models and current_model is None:
toggle.model = self.params.get("Model", block=True, encoding='utf-8')
toggle.model_randomizer = self.params.get_bool("ModelRandomizer")
if toggle.model_randomizer:
blacklisted_models = (self.params.get("BlacklistedModels", encoding='utf-8') or '').split(',')
existing_models = [model for model in available_models.split(',') if model not in blacklisted_models and os.path.exists(os.path.join(MODELS_PATH, f"{model}.thneed"))]
toggle.model = random.choice(existing_models) if existing_models else DEFAULT_MODEL
else:
toggle.model = self.params.get("Model", block=True, encoding='utf-8')
else:
toggle.model = current_model
if not os.path.exists(os.path.join(MODELS_PATH, f"{toggle.model}.thneed")):
@@ -0,0 +1,235 @@
#include "selfdrive/frogpilot/ui/qt/widgets/model_reviewer.h"
ModelReview::ModelReview(QWidget *parent) : QFrame(parent) {
mainLayout = new QStackedLayout(this);
ratingLayout = new QVBoxLayout();
ratingLayout->setContentsMargins(50, 25, 50, 20);
questionLabel = addLabel(ratingLayout, "What would you rate that drive?", "question");
QHBoxLayout *ratingButtonsLayout = new QHBoxLayout();
QStringList emojis = {"🤩", "🙂", "🤔", "🙁", "🤕"};
QList<int> scores = {100, 80, 60, 40, 20};
for (int i = 0; i < emojis.size(); ++i) {
QPushButton *ratingButton = createButton(emojis[i], "rating_button", scores[i], 150, 150);
connect(ratingButton, &QPushButton::clicked, this, &ModelReview::onRatingButtonClicked);
ratingButtons.append(ratingButton);
ratingButtonsLayout->addWidget(ratingButton);
}
ratingLayout->addLayout(ratingButtonsLayout);
blacklistButton = createButton("Blacklist this model", "blacklist_button", 0, 600, 100);
connect(blacklistButton, &QPushButton::clicked, this, &ModelReview::onBlacklistButtonClicked);
ratingLayout->addWidget(blacklistButton, 0, Qt::AlignCenter);
QWidget *ratingWidget = new QWidget(this);
ratingWidget->setLayout(ratingLayout);
mainLayout->addWidget(ratingWidget);
modelInfoLayout = new QVBoxLayout();
modelInfoLayout->setContentsMargins(50, 25, 50, 20);
titleLabel = addLabel(modelInfoLayout, "The model used during that drive was:", "title");
modelLabel = addLabel(modelInfoLayout, "", "model");
QSpacerItem *spacer = new QSpacerItem(20, 75, QSizePolicy::Minimum, QSizePolicy::Fixed);
modelInfoLayout->addItem(spacer);
QVBoxLayout *bottomLayout = new QVBoxLayout();
modelScoreLabel = addLabel(bottomLayout, "Current Model Score: 0", "score");
modelRankLabel = addLabel(bottomLayout, "Current Model Rank: 0", "rank");
totalDrivesLabel = addLabel(bottomLayout, "Total Model Drives: 0", "drives");
totalOverallDrivesLabel = addLabel(bottomLayout, "Total Overall Model Drives: 0", "drives");
blacklistMessageLabel = addLabel(bottomLayout, "", "blacklist_message");
modelInfoLayout->addLayout(bottomLayout);
QWidget *modelInfoWidget = new QWidget(this);
modelInfoWidget->setLayout(modelInfoLayout);
mainLayout->addWidget(modelInfoWidget);
setStyleSheet(R"(
ModelReview {
background-color: #333333;
border-radius: 5px;
}
QLabel[type="drives"], QLabel[type="question"], QLabel[type="rank"], QLabel[type="score"], QLabel[type="title"] {
font-size: 50px;
font-weight: semi-bold;
color: #FFFFFF;
}
QLabel[type="model"] {
font-size: 75px;
font-weight: bold;
color: #FFFFFF;
}
QLabel[type="blacklist_message"] {
font-size: 40px;
font-weight: bold;
color: #C92231;
}
QPushButton[type="rating_button"] {
font-size: 75px;
font-weight: bold;
padding: 10px;
color: #FFFFFF;
background-color: #555555;
border: 2px solid #FFFFFF;
border-radius: 5px;
}
QPushButton[type="rating_button"]:hover {
background-color: #777777;
}
QPushButton[type="blacklist_button"] {
font-size: 50px;
font-weight: bold;
padding: 10px;
color: #C92231;
background-color: #000000;
border: 2px solid #FFFFFF;
border-radius: 5px;
}
)");
}
QLabel *ModelReview::addLabel(QVBoxLayout *layout, const QString &text, const QString &type) {
QLabel *label = new QLabel(text, this);
label->setProperty("type", type);
label->setAlignment(Qt::AlignCenter);
layout->addWidget(label);
return label;
}
QPushButton *ModelReview::createButton(const QString &text, const QString &type, int rating, int width, int height) {
QPushButton *button = new QPushButton(text, this);
button->setProperty("type", type);
button->setProperty("rating", rating);
button->setFixedSize(width, height);
return button;
}
void ModelReview::showEvent(QShowEvent *event) {
currentModel = QString::fromStdString(paramsMemory.get("CurrentModelName"));
currentModelFiltered = processModelName(currentModel);
if (modelRated) {
mainLayout->setCurrentIndex(1);
} else {
mainLayout->setCurrentIndex(0);
}
checkBlacklistButtonVisibility();
}
void ModelReview::mousePressEvent(QMouseEvent *e) {
if (mainLayout->currentIndex() != 1) {
return;
}
paramsMemory.putBool("DriveRated", true);
}
void ModelReview::updateLabel() {
modelLabel->setText(currentModel.remove(QRegularExpression("[🗺️👀📡]")).remove(QRegularExpression(" \\(Default\\)")));
modelScoreLabel->setText(QString("Current Model Score: %1").arg(finalRating));
totalDrivesLabel->setText(QString("Total Model Drives: %1").arg(totalDrives));
modelRankLabel->setText(QString("Current Model Rank: %1").arg(getModelRank()));
totalOverallDrivesLabel->setText(QString("Total Overall Drives: %1").arg(totalOverallDrives));
mainLayout->setCurrentIndex(1);
QTimer::singleShot(30000, this, [this]() {
paramsMemory.putBool("DriveRated", true);
modelRated = false;
});
}
void ModelReview::onRatingButtonClicked() {
int newRating = qobject_cast<QPushButton*>(sender())->property("rating").toInt();
QString drivesParam = QString("%1Drives").arg(currentModelFiltered);
std::string drivesParamStd = drivesParam.toStdString();
totalDrives = params.getInt(drivesParamStd) + 1;
QString ratingParam = QString("%1Score").arg(currentModelFiltered);
std::string ratingParamStd = ratingParam.toStdString();
int currentRating = params.getInt(ratingParamStd);
finalRating = (currentRating * (totalDrives - 1) + newRating) / totalDrives;
params.putIntNonBlocking(drivesParamStd, totalDrives);
params.putIntNonBlocking(ratingParamStd, finalRating);
modelRated = true;
updateLabel();
}
void ModelReview::onBlacklistButtonClicked() {
params.putIntNonBlocking(QString("%1Score").arg(currentModelFiltered).toStdString(), 0);
if (!blacklistedModels.contains(currentModel)) {
blacklistedModels.append(currentModel);
params.putNonBlocking("BlacklistedModels", blacklistedModels.join(",").toStdString());
}
blacklistMessageLabel->setText("Model successfully blacklisted!");
updateLabel();
}
void ModelReview::checkBlacklistButtonVisibility() {
QStringList availableModels = QString::fromStdString(params.get("AvailableModels")).split(",");
blacklistedModels = QString::fromStdString(params.get("BlacklistedModels")).split(",", QString::SkipEmptyParts);
QStringList selectableModels;
for (const QString &model : availableModels) {
if (!blacklistedModels.contains(model)) {
selectableModels.append(model);
}
}
blacklistButton->setVisible(selectableModels.size() > 1);
}
int ModelReview::getModelRank() {
QStringList availableModels = QString::fromStdString(params.get("AvailableModelsNames")).split(",");
QList<QPair<QString, int>> modelScores;
totalOverallDrives = 0;
for (const QString &model : availableModels) {
QString scoreParam = QString("%1Score").arg(processModelName(model));
int modelScore = params.getInt(scoreParam.toStdString());
QString drivesParam = QString("%1Drives").arg(processModelName(model));
int modelDrives = params.getInt(drivesParam.toStdString());
totalOverallDrives += modelDrives;
modelScores.append(qMakePair(processModelName(model), modelScore));
}
std::sort(modelScores.begin(), modelScores.end(), [](const QPair<QString, int> &a, const QPair<QString, int> &b) {
return a.second > b.second;
});
QString processedCurrentModel = processModelName(currentModel);
for (int i = 0; i < modelScores.size(); ++i) {
if (modelScores[i].first == processedCurrentModel) {
return i + 1;
}
}
return -1;
}
QString ModelReview::processModelName(const QString &modelName) {
QString modelCleaned = modelName;
modelCleaned = modelCleaned.remove(QRegularExpression("[🗺️👀📡]")).simplified();
QString scoreParam = modelCleaned.remove(QRegularExpression("[^a-zA-Z0-9()-]")).replace(" ", "").simplified();
scoreParam = scoreParam.replace("(Default)", "").replace("-", "");
return scoreParam;
}
@@ -0,0 +1,62 @@
#pragma once
#include <QComboBox>
#include "selfdrive/ui/ui.h"
class ModelReview : public QFrame {
Q_OBJECT
public:
explicit ModelReview(QWidget *parent = nullptr);
private slots:
void onBlacklistButtonClicked();
void onRatingButtonClicked();
private:
int getModelRank();
QLabel *addLabel(QVBoxLayout *layout, const QString &text, const QString &type);
QPushButton *createButton(const QString &text, const QString &type, int rating, int width, int height);
QString processModelName(const QString &modelName);
void checkBlacklistButtonVisibility();
void mousePressEvent(QMouseEvent *e) override;
void showEvent(QShowEvent *event) override;
void updateLabel();
QStackedLayout *mainLayout;
QVBoxLayout *ratingLayout;
QVBoxLayout *modelInfoLayout;
Params params;
Params paramsMemory{"/dev/shm/params"};
QLabel *blacklistMessageLabel;
QLabel *modelLabel;
QLabel *modelRankLabel;
QLabel *modelScoreLabel;
QLabel *questionLabel;
QLabel *titleLabel;
QLabel *totalDrivesLabel;
QLabel *totalOverallDrivesLabel;
QString currentModel;
QString currentModelFiltered;
QStringList blacklistedModels;
QPushButton *blacklistButton;
QList<QPushButton*> ratingButtons;
bool modelRated;
int finalRating;
int totalDrives;
int totalOverallDrives;
};
+1 -1
View File
@@ -24,7 +24,7 @@ widgets_src = ["ui.cc", "qt/widgets/input.cc", "qt/widgets/wifi.cc",
"qt/widgets/scrollview.cc", "qt/widgets/cameraview.cc", "#third_party/qrcode/QrCode.cc",
"qt/request_repeater.cc", "qt/qt_window.cc", "qt/network/networking.cc", "qt/network/wifi_manager.cc",
"../frogpilot/ui/qt/widgets/drive_stats.cc", "../frogpilot/ui/qt/widgets/frogpilot_controls.cc",
"../frogpilot/navigation/ui/navigation_settings.cc",
"../frogpilot/ui/qt/widgets/model_reviewer.cc", "../frogpilot/navigation/ui/navigation_settings.cc",
"../frogpilot/ui/qt/offroad/control_settings.cc", "../frogpilot/ui/qt/offroad/vehicle_settings.cc",
"../frogpilot/ui/qt/offroad/visual_settings.cc"]
+12
View File
@@ -14,6 +14,7 @@
#endif
#include "selfdrive/frogpilot/ui/qt/widgets/drive_stats.h"
#include "selfdrive/frogpilot/ui/qt/widgets/model_reviewer.h"
// HomeWindow: the container for the offroad and onroad UIs
@@ -172,9 +173,16 @@ OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) {
left_widget->addWidget(new QWidget);
#endif
left_widget->addWidget(new DriveStats);
left_widget->addWidget(new ModelReview);
left_widget->setStyleSheet("border-radius: 10px;");
left_widget->setCurrentIndex(1);
connect(uiState(), &UIState::driveRated, [=]() {
left_widget->setCurrentIndex(1);
});
connect(uiState(), &UIState::reviewModel, [=]() {
left_widget->setCurrentIndex(2);
});
home_layout->addWidget(left_widget, 1);
@@ -246,6 +254,10 @@ void OffroadHome::refresh() {
model = model.remove("(Default)").trimmed();
}
if (uiState()->scene.model_randomizer) {
model = "Mystery Model 👻";
}
date->setText(QLocale(uiState()->language.mid(5)).toString(QDateTime::currentDateTime(), "dddd, MMMM d"));
version->setText(getBrand() + " v" + getVersion().left(14).trimmed() + " - " + model);
+11
View File
@@ -299,6 +299,9 @@ void ui_update_frogpilot_params(UIState *s, Params &params) {
bool radarless_model = params.get("Model") == "radical-turtle";
scene.lead_detection_threshold = longitudinal_tune && !radarless_model ? params.getInt("LeadDetectionThreshold") / 100.0f : 0.5;
bool model_manager = params.getBool("ModelManagement");
scene.model_randomizer = model_manager && params.getBool("ModelRandomizer");
scene.tethering_config = params.getInt("TetheringEnabled");
if (scene.tethering_config == 2) {
WifiManager(s).setTetheringEnabled(true);
@@ -328,6 +331,8 @@ void UIState::updateStatus() {
if (scene.started) {
status = STATUS_DISENGAGED;
scene.started_frame = sm->frame;
} else if (scene.started_timer > 15*60*UI_FREQ && scene.model_randomizer) {
emit reviewModel();
}
started_prev = scene.started;
scene.world_objects_visible = false;
@@ -385,8 +390,14 @@ void UIState::update() {
update_toggles = false;
}
if (paramsMemory.getBool("DriveRated")) {
emit driveRated();
paramsMemory.remove("DriveRated");
}
// FrogPilot variables that need to be constantly updated
scene.conditional_status = scene.conditional_experimental && scene.enabled ? paramsMemory.getInt("CEStatus") : 0;
scene.started_timer = scene.started || started_prev ? scene.started_timer + 1 : 0;
}
void UIState::setPrimeType(PrimeType type) {
+4
View File
@@ -130,6 +130,7 @@ typedef struct UIScene {
bool experimental_mode_via_screen;
bool has_lead;
bool map_open;
bool model_randomizer;
bool online;
bool onroad_distance_button;
bool parked;
@@ -186,6 +187,9 @@ signals:
void primeChanged(bool prime);
void primeTypeChanged(PrimeType prime_type);
// FrogPilot signals
void driveRated();
void reviewModel();
private slots:
void update();