FrogPilot 0.9.7

This commit is contained in:
FrogAi
2024-06-27 10:22:08 -07:00
parent da00915ac8
commit b705b02e70
682 changed files with 181798 additions and 1348 deletions
+45 -10
View File
@@ -13,6 +13,9 @@
#include "selfdrive/ui/qt/maps/map_settings.h"
#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
HomeWindow::HomeWindow(QWidget* parent) : QWidget(parent) {
@@ -65,6 +68,13 @@ void HomeWindow::updateState(const UIState &s) {
body->setEnabled(true);
slayout->setCurrentWidget(body);
}
if (s.scene.started) {
showDriverView(s.scene.driver_camera_timer >= 10, true);
if (s.scene.map_open) {
showSidebar(false);
}
}
}
void HomeWindow::offroadTransition(bool offroad) {
@@ -73,24 +83,32 @@ void HomeWindow::offroadTransition(bool offroad) {
if (offroad) {
slayout->setCurrentWidget(home);
} else {
showSidebar(params.getBool("Sidebar"));
slayout->setCurrentWidget(onroad);
}
}
void HomeWindow::showDriverView(bool show) {
void HomeWindow::showDriverView(bool show, bool started) {
if (show) {
emit closeSettings();
slayout->setCurrentWidget(driver_view);
sidebar->setVisible(show == false);
} else {
slayout->setCurrentWidget(home);
if (started) {
slayout->setCurrentWidget(onroad);
sidebar->setVisible(params.getBool("Sidebar"));
} else {
slayout->setCurrentWidget(home);
sidebar->setVisible(show == false);
}
}
sidebar->setVisible(show == false);
}
void HomeWindow::mousePressEvent(QMouseEvent* e) {
// Handle sidebar collapsing
if ((onroad->isVisible() || body->isVisible()) && (!sidebar->isVisible() || e->x() > sidebar->width())) {
sidebar->setVisible(!sidebar->isVisible() && !onroad->isMapVisible());
params.putBool("Sidebar", sidebar->isVisible());
}
}
@@ -130,6 +148,9 @@ OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) {
QObject::connect(alert_notif, &QPushButton::clicked, [=] { center_layout->setCurrentIndex(2); });
header_layout->addWidget(alert_notif, 0, Qt::AlignHCenter | Qt::AlignLeft);
date = new ElidedLabel();
header_layout->addWidget(date, 0, Qt::AlignHCenter | Qt::AlignLeft);
version = new ElidedLabel();
header_layout->addWidget(version, 0, Qt::AlignHCenter | Qt::AlignRight);
@@ -145,19 +166,26 @@ OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) {
home_layout->setContentsMargins(0, 0, 0, 0);
home_layout->setSpacing(30);
// left: MapSettings/PrimeAdWidget
// left: MapSettings
QStackedWidget *left_widget = new QStackedWidget(this);
#ifdef ENABLE_MAPS
left_widget->addWidget(new MapSettings);
#else
left_widget->addWidget(new QWidget);
#endif
left_widget->addWidget(new PrimeAdWidget);
left_widget->setStyleSheet("border-radius: 10px;");
left_widget->addWidget(new DriveStats);
left_widget->setCurrentIndex(uiState()->hasPrime() ? 0 : 1);
connect(uiState(), &UIState::primeChanged, [=](bool prime) {
left_widget->setCurrentIndex(prime ? 0 : 1);
ModelReview *modelReview = new ModelReview(this);
left_widget->addWidget(modelReview);
left_widget->setStyleSheet("border-radius: 10px;");
left_widget->setCurrentIndex(1);
connect(modelReview, &ModelReview::driveRated, [=]() {
left_widget->setCurrentIndex(1);
});
connect(uiState(), &UIState::reviewModel, [=]() {
left_widget->setCurrentIndex(2);
});
home_layout->addWidget(left_widget, 1);
@@ -195,6 +223,8 @@ OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) {
timer = new QTimer(this);
timer->callOnTimeout(this, &OffroadHome::refresh);
QObject::connect(uiState(), &UIState::togglesUpdated, this, &OffroadHome::refresh);
setStyleSheet(R"(
* {
color: white;
@@ -224,7 +254,12 @@ void OffroadHome::hideEvent(QHideEvent *event) {
}
void OffroadHome::refresh() {
version->setText(getBrand() + " " + QString::fromStdString(params.get("UpdaterCurrentDescription")));
QString model = processModelName(uiState()->scene.model_name);
date->setText(QLocale(uiState()->language.mid(5)).toString(QDateTime::currentDateTime(), "dddd, MMMM d"));
version->setText(getBrand() + " v" + getVersion().left(14).trimmed() + " - " + model);
date->setVisible(util::system_time_valid());
bool updateAvailable = update_widget->refresh();
int alerts = alerts_widget->refresh();
+7 -1
View File
@@ -39,6 +39,9 @@ private:
OffroadAlert* alerts_widget;
QPushButton* alert_notif;
QPushButton* update_notif;
// FrogPilot variables
ElidedLabel* date;
};
class HomeWindow : public QWidget {
@@ -53,7 +56,7 @@ signals:
public slots:
void offroadTransition(bool offroad);
void showDriverView(bool show);
void showDriverView(bool show, bool started=false);
void showSidebar(bool show);
void showMapPanel(bool show);
@@ -69,6 +72,9 @@ private:
DriverViewWindow *driver_view;
QStackedLayout *slayout;
// FrogPilot variables
Params params;
private slots:
void updateState(const UIState &s);
};
+96 -1
View File
@@ -75,7 +75,7 @@ void MapWindow::initLayers() {
QVariantMap transition;
transition["duration"] = 400; // ms
m_map->setPaintProperty("navLayer", "line-color", QColor("#31a1ee"));
m_map->setPaintProperty("navLayer", "line-color", getNavPathColor(uiState()->scene.navigate_on_openpilot));
m_map->setPaintProperty("navLayer", "line-color-transition", transition);
m_map->setPaintProperty("navLayer", "line-width", 7.5);
m_map->setLayoutProperty("navLayer", "line-cap", "round");
@@ -110,6 +110,50 @@ void MapWindow::initLayers() {
// TODO: remove, symbol-sort-key does not seem to matter outside of each layer
m_map->setLayoutProperty("carPosLayer", "symbol-sort-key", 0);
}
// Credit goes to jakethesnake420!
if (!m_map->layerExists("buildingsLayer")) {
qDebug() << "Initializing buildingsLayer";
QVariantMap buildings;
buildings["id"] = "buildingsLayer";
buildings["source"] = "composite";
buildings["source-layer"] = "building";
buildings["type"] = "fill-extrusion";
buildings["minzoom"] = 15;
m_map->addLayer("buildingsLayer", buildings);
m_map->setFilter("buildingsLayer", QVariantList({"==", "extrude", "true"}));
QVariantList fillExtrusionHight = {
"interpolate",
QVariantList{"linear"},
QVariantList{"zoom"},
15, 0,
15.05, QVariantList{"get", "height"}
};
QVariantList fillExtrusionBase = {
"interpolate",
QVariantList{"linear"},
QVariantList{"zoom"},
15, 0,
15.05, QVariantList{"get", "min_height"}
};
QVariantList fillExtrusionOpacity = {
"interpolate",
QVariantList{"linear"},
QVariantList{"zoom"},
15, 0,
15.5, .6,
17, .6,
20, 0
};
m_map->setPaintProperty("buildingsLayer", "fill-extrusion-color", QColor("grey"));
m_map->setPaintProperty("buildingsLayer", "fill-extrusion-opacity", fillExtrusionOpacity);
m_map->setPaintProperty("buildingsLayer", "fill-extrusion-height", fillExtrusionHight);
m_map->setPaintProperty("buildingsLayer", "fill-extrusion-base", fillExtrusionBase);
m_map->setLayoutProperty("buildingsLayer", "visibility", "visible");
}
}
void MapWindow::updateState(const UIState &s) {
@@ -127,6 +171,21 @@ void MapWindow::updateState(const UIState &s) {
}
prev_time_valid = sm.valid("clocks");
if (sm.updated("modelV2")) {
// set path color on change, and show map on rising edge of navigate on openpilot
bool nav_enabled = sm["modelV2"].getModelV2().getNavEnabled() &&
(sm["controlsState"].getControlsState().getEnabled() || uiState()->scene.always_on_lateral_active);
if (nav_enabled != uiState()->scene.navigate_on_openpilot) {
if (loaded_once) {
m_map->setPaintProperty("navLayer", "line-color", getNavPathColor(nav_enabled));
}
if (nav_enabled) {
emit requestVisible(true);
}
}
uiState()->scene.navigate_on_openpilot = nav_enabled;
}
if (sm.updated("liveLocationKalman")) {
auto locationd_location = sm["liveLocationKalman"].getLiveLocationKalman();
auto locationd_pos = locationd_location.getPositionGeodetic();
@@ -234,6 +293,41 @@ void MapWindow::updateState(const UIState &s) {
route_rcv_frame = sm.rcv_frame("navRoute");
updateDestinationMarker();
}
// Credit to jakethesnake420
if (loaded_once && (sm.rcv_frame("uiPlan") != model_rcv_frame)) {
auto locationd_location = sm["liveLocationKalman"].getLiveLocationKalman();
auto model_path = model_to_collection(locationd_location.getCalibratedOrientationECEF(), locationd_location.getPositionECEF(), sm["uiPlan"].getUiPlan().getPosition());
QMapLibre::Feature model_path_feature(QMapLibre::Feature::LineStringType, model_path, {}, {});
QVariantMap modelV2Path;
modelV2Path["type"] = "geojson";
modelV2Path["data"] = QVariant::fromValue<QMapLibre::Feature>(model_path_feature);
m_map->updateSource("modelPathSource", modelV2Path);
model_rcv_frame = sm.rcv_frame("uiPlan");
}
// Map Styling - Credit goes to OPKR!
int map_style = uiState()->scene.map_style;
if (map_style != previous_map_style) {
std::array<std::string, 11> styleUrls = {
"mapbox://styles/commaai/clkqztk0f00ou01qyhsa5bzpj", // Stock openpilot
"mapbox://styles/mapbox/streets-v11", // Mapbox Streets
"mapbox://styles/mapbox/outdoors-v11", // Mapbox Outdoors
"mapbox://styles/mapbox/light-v10", // Mapbox Light
"mapbox://styles/mapbox/dark-v10", // Mapbox Dark
"mapbox://styles/mapbox/satellite-v9", // Mapbox Satellite
"mapbox://styles/mapbox/satellite-streets-v11", // Mapbox Satellite Streets
"mapbox://styles/mapbox/navigation-day-v1", // Mapbox Navigation Day
"mapbox://styles/mapbox/navigation-night-v1", // Mapbox Navigation Night
"mapbox://styles/mapbox/traffic-night-v2", // Mapbox Traffic Night
"mapbox://styles/mike854/clt0hm8mw01ok01p4blkr27jp" // mike854's (Satellite hybrid)
};
m_map->setStyleUrl(QString::fromStdString(styleUrls[map_style]));
}
previous_map_style = map_style;
}
void MapWindow::setError(const QString &err_str) {
@@ -366,6 +460,7 @@ void MapWindow::pinchTriggered(QPinchGesture *gesture) {
void MapWindow::offroadTransition(bool offroad) {
if (offroad) {
clearRoute();
uiState()->scene.navigate_on_openpilot = false;
routing_problem = false;
} else {
auto dest = coordinate_from_param("NavDestination");
+10
View File
@@ -70,10 +70,20 @@ private:
MapInstructions* map_instructions;
MapETA* map_eta;
// Blue with normal nav, green when nav is input into the model
QColor getNavPathColor(bool nav_enabled) {
return nav_enabled ? QColor("#31ee73") : QColor("#31a1ee");
}
void clearRoute();
void updateDestinationMarker();
uint64_t route_rcv_frame = 0;
// FrogPilot variables
int previous_map_style;
uint64_t model_rcv_frame = 0;
private slots:
void updateState(const UIState &s);
+4 -1
View File
@@ -8,12 +8,15 @@
#include <eigen3/Eigen/Dense>
#include <QGeoCoordinate>
#include "common/params.h"
#include "common/util.h"
#include "common/transformations/coordinates.hpp"
#include "common/transformations/orientation.hpp"
#include "cereal/messaging/messaging.h"
const QString MAPBOX_TOKEN = util::getenv("MAPBOX_TOKEN").c_str();
const QString MAPBOX_TOKEN = !util::getenv("MAPBOX_TOKEN").empty() ? util::getenv("MAPBOX_TOKEN").c_str() :
!Params().get("MapboxSecretKey").empty() ? QString::fromStdString(Params().get("MapboxSecretKey")) :
QString();
const QString MAPS_HOST = util::getenv("MAPS_HOST", MAPBOX_TOKEN.isEmpty() ? "https://maps.comma.ai" : "https://api.mapbox.com").c_str();
const QString MAPS_CACHE_PATH = "/data/mbgl-cache-navd.db";
+8
View File
@@ -41,3 +41,11 @@ void MapPanel::toggleMapSettings() {
emit mapPanelRequested();
show();
}
void MapPanel::showEvent(QShowEvent *event) {
uiState()->scene.map_open = true;
}
void MapPanel::hideEvent(QHideEvent *event) {
uiState()->scene.map_open = false;
}
+4
View File
@@ -18,4 +18,8 @@ public slots:
private:
QStackedLayout *content_stack;
// FrogPilot widgets
void hideEvent(QHideEvent *event);
void showEvent(QShowEvent *event);
};
+9 -1
View File
@@ -62,7 +62,7 @@ MapSettings::MapSettings(bool closeable, QWidget *parent) : QFrame(parent) {
title->setStyleSheet("color: #FFFFFF; font-size: 54px; font-weight: 600;");
heading->addWidget(title);
auto *subtitle = new QLabel(tr("Manage at connect.comma.ai"), this);
subtitle = new QLabel(tr("Manage at connect.comma.ai"), this);
subtitle->setStyleSheet("color: #A0A0A0; font-size: 40px; font-weight: 300;");
heading->addWidget(subtitle);
}
@@ -93,6 +93,8 @@ MapSettings::MapSettings(bool closeable, QWidget *parent) : QFrame(parent) {
setStyleSheet("MapSettings { background-color: #333333; }");
QObject::connect(NavManager::instance(), &NavManager::updated, this, &MapSettings::refresh);
wifi = new WifiManager(this);
}
void MapSettings::showEvent(QShowEvent *event) {
@@ -138,6 +140,12 @@ void MapSettings::refresh() {
for (; n < widgets.size(); ++n) widgets[n]->setVisible(false);
setUpdatesEnabled(true);
// Use IP for NOO without Prime
if (!uiState()->hasPrime()) {
QString ipAddress = QString("%1:8082").arg(wifi->getIp4Address());
subtitle->setText(tr("Manage at %1").arg(ipAddress));
}
}
void MapSettings::navigateTo(const QJsonObject &place) {
+6
View File
@@ -12,6 +12,7 @@
#include <QVBoxLayout>
#include "common/params.h"
#include "selfdrive/ui/qt/network/wifi_manager.h"
#include "selfdrive/ui/qt/util.h"
#include "selfdrive/ui/qt/widgets/controls.h"
@@ -64,6 +65,11 @@ private:
DestinationWidget *work_widget;
std::vector<DestinationWidget *> widgets;
// FrogPilot variables
QLabel *subtitle;
WifiManager *wifi;
signals:
void closeSettings();
};
+27 -5
View File
@@ -6,7 +6,6 @@
#include <QScrollBar>
#include <QStyle>
#include "selfdrive/ui/ui.h"
#include "selfdrive/ui/qt/qt_window.h"
#include "selfdrive/ui/qt/util.h"
#include "selfdrive/ui/qt/widgets/controls.h"
@@ -127,9 +126,21 @@ AdvancedNetworking::AdvancedNetworking(QWidget* parent, WifiManager* wifi): QWid
ListWidget *list = new ListWidget(this);
// Enable tethering layout
tetheringToggle = new ToggleControl(tr("Enable Tethering"), "", "", wifi->isTetheringEnabled());
std::vector<QString> tetheringSelection{tr("Off"), tr("Always"), tr("Only Onroad"), tr("Until Reboot")};
tetheringToggle = new ButtonParamControl("TetheringEnabled", tr("Enable Tethering"),
tr("Allow tethering with your data SIM and keep it active either while driving or continuously."),
"", tetheringSelection);
if (params.getInt("TetheringEnabled") == 3) {
params.remove("TetheringEnabled");
tetheringToggle->setCheckedButton(0);
}
QButtonGroup *buttonGroup = tetheringToggle->findChild<QButtonGroup *>();
if (buttonGroup) {
QObject::connect(buttonGroup, QOverload<int>::of(&QButtonGroup::buttonClicked), [this](int id) {
toggleTethering(id);
});
}
list->addItem(tetheringToggle);
QObject::connect(tetheringToggle, &ToggleControl::toggleFlipped, this, &AdvancedNetworking::toggleTethering);
// Change tethering password
ButtonControl *editPasswordButton = new ButtonControl(tr("Tethering Password"), tr("EDIT"));
@@ -221,8 +232,8 @@ void AdvancedNetworking::refresh() {
update();
}
void AdvancedNetworking::toggleTethering(bool enabled) {
wifi->setTetheringEnabled(enabled);
void AdvancedNetworking::toggleTethering(int id) {
wifi->setTetheringEnabled(id == 1 || id == 3);
tetheringToggle->setEnabled(false);
}
@@ -290,6 +301,17 @@ WifiUI::WifiUI(QWidget *parent, WifiManager* wifi) : QWidget(parent), wifi(wifi)
color: #696969;
}
)");
// FrogPilot variables
QObject::connect(uiState(), &UIState::uiUpdate, this, &WifiUI::updateState);
}
void WifiUI::updateState(const UIState &s) {
if (!isVisible() || s.sm->frame % UI_FREQ != 0) {
return;
}
refresh();
}
void WifiUI::refresh() {
+6 -2
View File
@@ -6,6 +6,7 @@
#include "selfdrive/ui/qt/widgets/input.h"
#include "selfdrive/ui/qt/widgets/ssh_keys.h"
#include "selfdrive/ui/qt/widgets/toggle.h"
#include "selfdrive/ui/ui.h"
class WifiItem : public QWidget {
Q_OBJECT
@@ -45,6 +46,9 @@ private:
ListWidget *wifi_list_widget = nullptr;
std::vector<WifiItem*> wifi_items;
// FrogPilot widgets
void updateState(const UIState &s);
signals:
void connectToNetwork(const Network n);
@@ -59,7 +63,7 @@ public:
private:
LabelControl* ipLabel;
ToggleControl* tetheringToggle;
ButtonParamControl* tetheringToggle;
ToggleControl* roamingToggle;
ButtonControl* editApnButton;
ButtonControl* hiddenNetworkButton;
@@ -72,7 +76,7 @@ signals:
void requestWifiScreen();
public slots:
void toggleTethering(bool enabled);
void toggleTethering(int id);
void refresh();
};
+1 -1
View File
@@ -58,6 +58,7 @@ public:
void setTetheringEnabled(bool enabled);
bool isTetheringEnabled();
void changeTetheringPassword(const QString &newPassword);
QString getIp4Address();
QString getTetheringPassword();
private:
@@ -72,7 +73,6 @@ private:
QString getAdapter(const uint = NM_DEVICE_TYPE_WIFI);
uint getAdapterType(const QDBusObjectPath &path);
QString getIp4Address();
void deactivateConnectionBySsid(const QString &ssid);
void deactivateConnection(const QDBusObjectPath &path);
QVector<QDBusObjectPath> getActiveConnections();
+129 -18
View File
@@ -15,6 +15,8 @@
#include "selfdrive/ui/qt/widgets/scrollview.h"
#include "selfdrive/ui/qt/widgets/ssh_keys.h"
#include "selfdrive/frogpilot/ui/qt/offroad/frogpilot_settings.h"
TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) {
// param, title, desc, icon
std::vector<std::tuple<QString, QString, QString, QString>> toggle_defs{
@@ -114,6 +116,11 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) {
connect(toggles["ExperimentalLongitudinalEnabled"], &ToggleControl::toggleFlipped, [=]() {
updateToggles();
});
// FrogPilot signals
connect(toggles["IsMetric"], &ToggleControl::toggleFlipped, [=](bool metric) {
updateMetric(metric);
});
}
void TogglesPanel::updateState(const UIState &s) {
@@ -137,6 +144,16 @@ void TogglesPanel::showEvent(QShowEvent *event) {
}
void TogglesPanel::updateToggles() {
UIState *s = uiState();
UIScene &scene = s->scene;
auto disengage_on_accelerator_toggle = toggles["DisengageOnAccelerator"];
disengage_on_accelerator_toggle->setVisible(!scene.always_on_lateral);
auto driver_camera_toggle = toggles["RecordFront"];
driver_camera_toggle->setVisible(!(scene.no_logging && scene.no_uploads));
auto nav_settings_left_toggle = toggles["NavSettingLeftSide"];
nav_settings_left_toggle->setVisible(!scene.full_map);
auto experimental_mode_toggle = toggles["ExperimentalMode"];
auto op_long_toggle = toggles["ExperimentalLongitudinalEnabled"];
const QString e2e_description = QString("%1<br>"
@@ -152,17 +169,16 @@ void TogglesPanel::updateToggles() {
.arg(tr("New Driving Visualization"))
.arg(tr("The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner."));
const bool is_release = params.getBool("IsReleaseBranch");
auto cp_bytes = params.get("CarParamsPersistent");
if (!cp_bytes.empty()) {
AlignedBuffer aligned_buf;
capnp::FlatArrayMessageReader cmsg(aligned_buf.align(cp_bytes.data(), cp_bytes.size()));
cereal::CarParams::Reader CP = cmsg.getRoot<cereal::CarParams>();
if (!CP.getExperimentalLongitudinalAvailable() || is_release) {
if (!CP.getExperimentalLongitudinalAvailable()) {
params.remove("ExperimentalLongitudinalEnabled");
}
op_long_toggle->setVisible(CP.getExperimentalLongitudinalAvailable() && !is_release);
op_long_toggle->setVisible(CP.getExperimentalLongitudinalAvailable());
if (hasLongitudinalControl(CP)) {
// normal description and toggle
experimental_mode_toggle->setEnabled(true);
@@ -179,11 +195,7 @@ void TogglesPanel::updateToggles() {
QString long_desc = unavailable + " " + \
tr("openpilot longitudinal control may come in a future update.");
if (CP.getExperimentalLongitudinalAvailable()) {
if (is_release) {
long_desc = unavailable + " " + tr("An alpha version of openpilot longitudinal control can be tested, along with Experimental mode, on non-release branches.");
} else {
long_desc = tr("Enable the openpilot longitudinal control (alpha) toggle to allow Experimental mode.");
}
long_desc = tr("Enable the openpilot longitudinal control (alpha) toggle to allow Experimental mode.");
}
experimental_mode_toggle->setDescription("<b>" + long_desc + "</b><br><br>" + e2e_description);
}
@@ -221,6 +233,8 @@ DevicePanel::DevicePanel(SettingsWindow *parent) : ListWidget(parent) {
if (ConfirmationDialog::confirm(tr("Are you sure you want to reset calibration?"), tr("Reset"), this)) {
params.remove("CalibrationParams");
params.remove("LiveTorqueParameters");
params_storage.remove("CalibrationParams");
params_storage.remove("LiveTorqueParameters");
}
});
addItem(resetCalibBtn);
@@ -348,6 +362,19 @@ void DevicePanel::showEvent(QShowEvent *event) {
ListWidget::showEvent(event);
}
void SettingsWindow::hideEvent(QHideEvent *event) {
closeMapBoxInstructions();
closeMapSelection();
closePanel();
closeParentToggle();
mapboxInstructionsOpen = false;
mapSelectionOpen = false;
panelOpen = false;
parentToggleOpen = false;
subParentToggleOpen = false;
}
void SettingsWindow::showEvent(QShowEvent *event) {
setCurrentPanel(0);
}
@@ -368,23 +395,41 @@ SettingsWindow::SettingsWindow(QWidget *parent) : QFrame(parent) {
panel_widget = new QStackedWidget();
// close button
QPushButton *close_btn = new QPushButton(tr("×"));
QPushButton *close_btn = new QPushButton(tr("← Back"));
close_btn->setStyleSheet(R"(
QPushButton {
font-size: 140px;
padding-bottom: 20px;
border-radius: 100px;
font-size: 50px;
border-radius: 25px;
background-color: #292929;
font-weight: 400;
font-weight: 500;
}
QPushButton:pressed {
background-color: #3B3B3B;
background-color: #ADADAD;
}
)");
close_btn->setFixedSize(200, 200);
sidebar_layout->addSpacing(45);
sidebar_layout->addWidget(close_btn, 0, Qt::AlignCenter);
QObject::connect(close_btn, &QPushButton::clicked, this, &SettingsWindow::closeSettings);
close_btn->setFixedSize(300, 125);
sidebar_layout->addSpacing(10);
sidebar_layout->addWidget(close_btn, 0, Qt::AlignRight);
QObject::connect(close_btn, &QPushButton::clicked, [this]() {
if (mapboxInstructionsOpen) {
closeMapBoxInstructions();
mapboxInstructionsOpen = false;
} else if (mapSelectionOpen) {
closeMapSelection();
mapSelectionOpen = false;
} else if (subParentToggleOpen) {
closeSubParentToggle();
subParentToggleOpen = false;
} else if (parentToggleOpen) {
closeParentToggle();
parentToggleOpen = false;
} else if (panelOpen) {
closePanel();
panelOpen = false;
} else {
closeSettings();
}
});
// setup panels
DevicePanel *device = new DevicePanel(this);
@@ -394,11 +439,23 @@ SettingsWindow::SettingsWindow(QWidget *parent) : QFrame(parent) {
TogglesPanel *toggles = new TogglesPanel(this);
QObject::connect(this, &SettingsWindow::expandToggleDescription, toggles, &TogglesPanel::expandToggleDescription);
// FrogPilot panels
QObject::connect(toggles, &TogglesPanel::updateMetric, this, &SettingsWindow::updateMetric);
FrogPilotSettingsWindow *frogpilotSettingsWindow = new FrogPilotSettingsWindow(this);
QObject::connect(frogpilotSettingsWindow, &FrogPilotSettingsWindow::closeMapBoxInstructions, [this]() {mapboxInstructionsOpen=false;});
QObject::connect(frogpilotSettingsWindow, &FrogPilotSettingsWindow::openMapBoxInstructions, [this]() {mapboxInstructionsOpen=true;});
QObject::connect(frogpilotSettingsWindow, &FrogPilotSettingsWindow::openMapSelection, [this]() {mapSelectionOpen=true;});
QObject::connect(frogpilotSettingsWindow, &FrogPilotSettingsWindow::openPanel, [this]() {panelOpen=true;});
QObject::connect(frogpilotSettingsWindow, &FrogPilotSettingsWindow::openParentToggle, [this]() {parentToggleOpen=true;});
QObject::connect(frogpilotSettingsWindow, &FrogPilotSettingsWindow::openSubParentToggle, [this]() {subParentToggleOpen=true;});
QList<QPair<QString, QWidget *>> panels = {
{tr("Device"), device},
{tr("Network"), new Networking(this)},
{tr("Toggles"), toggles},
{tr("Software"), new SoftwarePanel(this)},
{tr("FrogPilot"), frogpilotSettingsWindow},
};
nav_btns = new QButtonGroup(this);
@@ -432,6 +489,60 @@ SettingsWindow::SettingsWindow(QWidget *parent) : QFrame(parent) {
panel_widget->addWidget(panel_frame);
QObject::connect(btn, &QPushButton::clicked, [=, w = panel_frame]() {
if (w->widget() == frogpilotSettingsWindow) {
bool tuningLevelConfirmed = params.getBool("TuningLevelConfirmed");
if (!tuningLevelConfirmed) {
int frogpilotHours = paramsTracking.getInt("FrogPilotMinutes") / 60;
int openpilotHours = params.getInt("openpilotMinutes") / 60;
if (frogpilotHours < 1 && openpilotHours < 100) {
if (FrogPilotConfirmationDialog::toggleAlert(tr("Welcome to FrogPilot! Since you're new to FrogPilot, the 'Minimal' toggle preset has been applied, but you can change this at any time via the 'Tuning Level' button!"), tr("Sounds good!"), this, true)) {
params.putBool("TuningLevelConfirmed", true);
params.putInt("TuningLevel", 0);
}
} else if (frogpilotHours < 50 && openpilotHours < 100) {
if (FrogPilotConfirmationDialog::toggleAlert(tr("Since you're fairly new to FrogPilot, the 'Minimal' toggle preset has been applied, but you can change this at any time via the 'Tuning Level' button!"), tr("Sounds good!"), this, true)) {
params.putBool("TuningLevelConfirmed", true);
params.putInt("TuningLevel", 0);
}
} else if (frogpilotHours < 100) {
if (openpilotHours >= 100) {
if (FrogPilotConfirmationDialog::toggleAlert(tr("Since you're experienced with openpilot, the 'Standard' toggle preset has been applied, but you can change this at any time via the 'Tuning Level' button!"), tr("Sounds good!"), this, true)) {
params.putBool("TuningLevelConfirmed", true);
params.putInt("TuningLevel", 1);
}
} else {
if (FrogPilotConfirmationDialog::toggleAlert(tr("Since you're experienced with FrogPilot, the 'Standard' toggle preset has been applied, but you can change this at any time via the 'Tuning Level' button!"), tr("Sounds good!"), this, true)) {
params.putBool("TuningLevelConfirmed", true);
params.putInt("TuningLevel", 1);
}
}
} else if (frogpilotHours >= 100) {
if (FrogPilotConfirmationDialog::toggleAlert(tr("Since you're very experienced with FrogPilot, the 'Advanced' toggle preset has been applied, but you can change this at any time via the 'Tuning Level' button!"), tr("Sounds good!"), this, true)) {
params.putBool("TuningLevelConfirmed", true);
params.putInt("TuningLevel", 2);
}
}
}
}
if (mapboxInstructionsOpen) {
closeMapBoxInstructions();
mapboxInstructionsOpen = false;
}
if (mapSelectionOpen) {
closeMapSelection();
mapSelectionOpen = false;
}
if (panelOpen) {
closePanel();
panelOpen = false;
}
if (parentToggleOpen) {
closeParentToggle();
parentToggleOpen = false;
}
btn->setChecked(true);
panel_widget->setCurrentWidget(w);
});
+31
View File
@@ -25,17 +25,38 @@ public:
protected:
void showEvent(QShowEvent *event) override;
// FrogPilot widgets
void hideEvent(QHideEvent *event) override;
signals:
void closeSettings();
void reviewTrainingGuide();
void showDriverView();
void expandToggleDescription(const QString &param);
// FrogPilot signals
void closeMapBoxInstructions();
void closeMapSelection();
void closePanel();
void closeParentToggle();
void closeSubParentToggle();
void updateMetric(bool metric, bool bootRun=false);
private:
QPushButton *sidebar_alert_widget;
QWidget *sidebar_widget;
QButtonGroup *nav_btns;
QStackedWidget *panel_widget;
// FrogPilot variables
Params params;
Params paramsTracking{"/persist/tracking"};
bool mapboxInstructionsOpen;
bool mapSelectionOpen;
bool panelOpen;
bool parentToggleOpen;
bool subParentToggleOpen;
};
class DevicePanel : public ListWidget {
@@ -56,6 +77,9 @@ private slots:
private:
Params params;
ButtonControl *pair_device;
// FrogPilot variables
Params params_storage{"/persist/params"};
};
class TogglesPanel : public ListWidget {
@@ -64,6 +88,10 @@ public:
explicit TogglesPanel(SettingsWindow *parent);
void showEvent(QShowEvent *event) override;
signals:
// FrogPilot signals
void updateMetric(bool metric, bool bootRun=false);
public slots:
void expandToggleDescription(const QString &param);
@@ -98,4 +126,7 @@ private:
Params params;
ParamWatcher *fs_watch;
// FrogPilot variables
Params params_memory{"/dev/shm/params"};
};
+40 -8
View File
@@ -21,7 +21,7 @@ void SoftwarePanel::checkForUpdates() {
}
SoftwarePanel::SoftwarePanel(QWidget* parent) : ListWidget(parent) {
onroadLbl = new QLabel(tr("Updates are only downloaded while the car is off."));
onroadLbl = new QLabel(tr("Updates are only downloaded while the car is off or in park."));
onroadLbl->setStyleSheet("font-size: 50px; font-weight: 400; text-align: left; padding-top: 30px; padding-bottom: 30px;");
addItem(onroadLbl);
@@ -29,6 +29,12 @@ SoftwarePanel::SoftwarePanel(QWidget* parent) : ListWidget(parent) {
versionLbl = new LabelControl(tr("Current Version"), "");
addItem(versionLbl);
// automatic updates toggle
ParamControl *automaticUpdatesToggle = new ParamControl("AutomaticUpdates", tr("Automatically Update FrogPilot"),
tr("FrogPilot will automatically update itself and it's assets when you're offroad and connected to Wi-Fi."), "");
connect(automaticUpdatesToggle, &ToggleControl::toggleFlipped, this, &updateFrogPilotToggles);
addItem(automaticUpdatesToggle);
// download update btn
downloadBtn = new ButtonControl(tr("Download"), tr("CHECK"));
connect(downloadBtn, &ButtonControl::clicked, [=]() {
@@ -38,6 +44,7 @@ SoftwarePanel::SoftwarePanel(QWidget* parent) : ListWidget(parent) {
} else {
std::system("pkill -SIGHUP -f system.updated.updated");
}
params_memory.putBool("ManualUpdateInitiated", true);
});
addItem(downloadBtn);
@@ -54,6 +61,12 @@ SoftwarePanel::SoftwarePanel(QWidget* parent) : ListWidget(parent) {
connect(targetBranchBtn, &ButtonControl::clicked, [=]() {
auto current = params.get("GitBranch");
QStringList branches = QString::fromStdString(params.get("UpdaterAvailableBranches")).split(",");
if (!uiState()->scene.frogs_go_moo) {
branches.removeAll("FrogPilot-Development");
branches.removeAll("FrogPilot-New");
branches.removeAll("FrogPilot-Test");
branches.removeAll("MAKE-PRS-HERE");
}
for (QString b : {current.c_str(), "devel-staging", "devel", "nightly", "master-ci", "master"}) {
auto i = branches.indexOf(b);
if (i >= 0) {
@@ -70,19 +83,30 @@ SoftwarePanel::SoftwarePanel(QWidget* parent) : ListWidget(parent) {
checkForUpdates();
}
});
if (!params.getBool("IsTestedBranch")) {
addItem(targetBranchBtn);
}
addItem(targetBranchBtn);
// uninstall button
auto uninstallBtn = new ButtonControl(tr("Uninstall %1").arg(getBrand()), tr("UNINSTALL"));
connect(uninstallBtn, &ButtonControl::clicked, [&]() {
if (ConfirmationDialog::confirm(tr("Are you sure you want to uninstall?"), tr("Uninstall"), this)) {
if (FrogPilotConfirmationDialog::yesorno(tr("Do you want to delete deep storage FrogPilot assets? This includes your toggle settings for quick reinstalls."), this)) {
if (FrogPilotConfirmationDialog::yesorno(tr("Are you sure? This is 100% unrecoverable and if you reinstall FrogPilot you'll lose all your previous settings!"), this)) {
std::system("rm -rf /persist/params");
}
}
params.putBool("DoUninstall", true);
}
});
addItem(uninstallBtn);
// error log button
auto errorLogBtn = new ButtonControl(tr("Error Log"), tr("VIEW"), tr("View the error log for openpilot crashes."));
connect(errorLogBtn, &ButtonControl::clicked, [=]() {
std::string txt = util::read_file("/data/crashes/error.txt");
ConfirmationDialog::rich(QString::fromStdString(txt), this);
});
addItem(errorLogBtn);
fs_watch = new ParamWatcher(this);
QObject::connect(fs_watch, &ParamWatcher::paramChanged, [=](const QString &param_name, const QString &param_value) {
updateLabels();
@@ -104,6 +128,9 @@ void SoftwarePanel::showEvent(QShowEvent *event) {
}
void SoftwarePanel::updateLabels() {
UIState *s = uiState();
UIScene &scene = s->scene;
// add these back in case the files got removed
fs_watch->addParam("LastUpdateTime");
fs_watch->addParam("UpdateFailedCount");
@@ -111,12 +138,15 @@ void SoftwarePanel::updateLabels() {
fs_watch->addParam("UpdateAvailable");
if (!isVisible()) {
scene.downloading_update = false;
return;
}
// updater only runs offroad
onroadLbl->setVisible(is_onroad);
downloadBtn->setVisible(!is_onroad);
// updater only runs offroad or when parked
bool parked = scene.parked || scene.frogs_go_moo;
onroadLbl->setVisible(is_onroad && !parked);
downloadBtn->setVisible(!is_onroad || parked);
// download update
QString updater_state = QString::fromStdString(params.get("UpdaterState"));
@@ -124,7 +154,9 @@ void SoftwarePanel::updateLabels() {
if (updater_state != "idle") {
downloadBtn->setEnabled(false);
downloadBtn->setValue(updater_state);
scene.downloading_update = true;
} else {
scene.downloading_update = false;
if (failed) {
downloadBtn->setText(tr("CHECK"));
downloadBtn->setValue(tr("failed to check for update"));
@@ -148,7 +180,7 @@ void SoftwarePanel::updateLabels() {
versionLbl->setText(QString::fromStdString(params.get("UpdaterCurrentDescription")));
versionLbl->setDescription(QString::fromStdString(params.get("UpdaterCurrentReleaseNotes")));
installBtn->setVisible(!is_onroad && params.getBool("UpdateAvailable"));
installBtn->setVisible((!is_onroad || parked) && params.getBool("UpdateAvailable"));
installBtn->setValue(QString::fromStdString(params.get("UpdaterNewDescription")));
installBtn->setDescription(QString::fromStdString(params.get("UpdaterNewReleaseNotes")));
+20 -4
View File
@@ -6,11 +6,17 @@
#include "selfdrive/ui/qt/util.h"
void OnroadAlerts::updateState(const UIState &s) {
Alert a = getAlert(*(s.sm), s.scene.started_frame);
Alert a = getAlert(*(s.sm), s.scene.started_frame, s.scene.force_onroad);
if (!alert.equal(a)) {
alert = a;
update();
}
// FrogPilot variables
const UIScene &scene = s.scene;
hide_alerts = scene.hide_alerts;
road_name_ui = scene.road_name_ui;
}
void OnroadAlerts::clear() {
@@ -18,7 +24,7 @@ void OnroadAlerts::clear() {
update();
}
OnroadAlerts::Alert OnroadAlerts::getAlert(const SubMaster &sm, uint64_t started_frame) {
OnroadAlerts::Alert OnroadAlerts::getAlert(const SubMaster &sm, uint64_t started_frame, bool force_onroad) {
const cereal::ControlsState::Reader &cs = sm["controlsState"].getControlsState();
const uint64_t controls_frame = sm.rcv_frame("controlsState");
@@ -28,7 +34,7 @@ OnroadAlerts::Alert OnroadAlerts::getAlert(const SubMaster &sm, uint64_t started
cs.getAlertType().cStr(), cs.getAlertSize(), cs.getAlertStatus()};
}
if (!sm.updated("controlsState") && (sm.frame - started_frame) > 5 * UI_FREQ) {
if (!sm.updated("controlsState") && (sm.frame - started_frame) > 5 * UI_FREQ && !force_onroad) {
const int CONTROLS_TIMEOUT = 5;
const int controls_missing = (nanos_since_boot() - sm.rcv_time("controlsState")) / 1e9;
@@ -56,8 +62,15 @@ OnroadAlerts::Alert OnroadAlerts::getAlert(const SubMaster &sm, uint64_t started
void OnroadAlerts::paintEvent(QPaintEvent *event) {
if (alert.size == cereal::ControlsState::AlertSize::NONE) {
alert_height = 0;
return;
}
if (hide_alerts && alert.status == cereal::ControlsState::AlertStatus::NORMAL) {
alert_height = 0;
return;
}
static std::map<cereal::ControlsState::AlertSize, const int> alert_heights = {
{cereal::ControlsState::AlertSize::SMALL, 271},
{cereal::ControlsState::AlertSize::MID, 420},
@@ -67,11 +80,14 @@ void OnroadAlerts::paintEvent(QPaintEvent *event) {
int margin = 40;
int radius = 30;
int offset = road_name_ui ? 25 : 0;
alert_height = h - margin + offset;
if (alert.size == cereal::ControlsState::AlertSize::FULL) {
margin = 0;
radius = 0;
offset = 0;
}
QRect r = QRect(0 + margin, height() - h + margin, width() - margin*2, h - margin*2);
QRect r = QRect(0 + margin, height() - h + margin - offset, width() - margin*2, h - margin*2);
QPainter p(this);
+11 -1
View File
@@ -12,6 +12,9 @@ public:
void updateState(const UIState &s);
void clear();
// FrogPilot variables
int alert_height;
protected:
struct Alert {
QString text1;
@@ -29,11 +32,18 @@ protected:
{cereal::ControlsState::AlertStatus::NORMAL, QColor(0x15, 0x15, 0x15, 0xf1)},
{cereal::ControlsState::AlertStatus::USER_PROMPT, QColor(0xDA, 0x6F, 0x25, 0xf1)},
{cereal::ControlsState::AlertStatus::CRITICAL, QColor(0xC9, 0x22, 0x31, 0xf1)},
// FrogPilot alert colors
{cereal::ControlsState::AlertStatus::FROGPILOT, QColor(0x17, 0x86, 0x44, 0xf1)},
};
void paintEvent(QPaintEvent*) override;
OnroadAlerts::Alert getAlert(const SubMaster &sm, uint64_t started_frame);
OnroadAlerts::Alert getAlert(const SubMaster &sm, uint64_t started_frame, bool force_onroad);
QColor bg;
Alert alert = {};
// FrogPilot variables
bool hide_alerts;
bool road_name_ui;
};
File diff suppressed because it is too large Load Diff
+146 -4
View File
@@ -6,17 +6,49 @@
#include "selfdrive/ui/qt/onroad/buttons.h"
#include "selfdrive/ui/qt/widgets/cameraview.h"
#include "selfdrive/frogpilot/screenrecorder/screenrecorder.h"
class PedalIcons : public QWidget {
Q_OBJECT
public:
explicit PedalIcons(QWidget *parent = 0);
void updateState(const UIScene &scene);
private:
void paintEvent(QPaintEvent *event) override;
QPixmap brake_pedal_img;
QPixmap gas_pedal_img;
bool accelerating;
bool brakeLightOn;
bool decelerating;
bool dynamicPedals;
bool standstill;
bool staticPedals;
float acceleration;
};
class AnnotatedCameraWidget : public CameraWidget {
Q_OBJECT
public:
explicit AnnotatedCameraWidget(VisionStreamType type, QWidget* parent = 0);
void updateState(const UIState &s);
void updateState(int alert_height, const UIState &s);
MapSettingsButton *map_settings_btn;
// FrogPilot variables
QRect newSpeedLimitRect;
QString accelerationUnit;
float accelerationConversion;
private:
void drawText(QPainter &p, int x, int y, const QString &text, int alpha = 255);
void drawText(QPainter &p, int x, int y, const QString &text, int alpha = 255, bool overridePen = false);
QVBoxLayout *main_layout;
ExperimentalButton *experimental_btn;
@@ -40,15 +72,125 @@ private:
int skip_frame_count = 0;
bool wide_cam_requested = false;
// FrogPilot widgets
void drawCEMStatus(QPainter &p);
void drawRoadName(QPainter &p);
void drawTurnSignals(QPainter &p);
void initializeFrogPilotWidgets();
void paintFrogPilotWidgets(QPainter &painter);
void updateFrogPilotVariables(int alert_height, const UIScene &scene);
void updateSignals();
// FrogPilot variables
Params params_memory{"/dev/shm/params"};
DistanceButton *distance_btn;
PedalIcons *pedal_icons;
ScreenRecorder *screenRecorder;
QPixmap chillModeIcon;
QPixmap curveIcon;
QPixmap curveSpeedLeftIcon;
QPixmap curveSpeedRightIcon;
QPixmap dashboardIcon;
QPixmap experimentalModeIcon;
QPixmap leadIcon;
QPixmap lightIcon;
QPixmap mapDataIcon;
QPixmap navigationIcon;
QPixmap speedIcon;
QPixmap stopSignImg;
QPixmap turnIcon;
QPixmap upcomingMapsIcon;
QPoint dmIconPosition;
QString leadDistanceUnit;
QString leadSpeedUnit;
QString signalStyle;
QTimer *animationTimer;
QVector<QPixmap> blindspotImages;
QVector<QPixmap> signalImages;
bool bigMapOpen;
bool blindSpotLeft;
bool blindSpotRight;
bool cemStatus;
bool compass;
bool experimentalMode;
bool hideCSCUI;
bool hideMapIcon;
bool hideMaxSpeed;
bool hideSpeed;
bool hideSpeedLimit;
bool leadInfo;
bool leftCurve;
bool mapOpen;
bool mtscEnabled;
bool onroadDistanceButton;
bool roadNameUI;
bool showSLCOffset;
bool slcOverridden;
bool speedLimitChanged;
bool speedLimitSources;
bool trafficModeActive;
bool turnSignalAnimation;
bool turnSignalLeft;
bool turnSignalRight;
bool useStockColors;
bool useSI;
bool useViennaSLCSign;
bool vtscControllingCurve;
bool vtscEnabled;
float dashboardSpeedLimit;
float distanceConversion;
float laneDetectionWidth;
float lead_x;
float lead_y;
float mapsSpeedLimit;
float mtscSpeed;
float navigationSpeedLimit;
float slcSpeedLimitOffset;
float speedConversion;
float speedConversionMetrics;
float unconfirmedSpeedLimit;
float upcomingSpeedLimit;
float vtscSpeed;
int alertHeight;
int animationFrameIndex;
int cameraView;
int conditionalStatus;
int desiredFollow;
int modelLength;
int signalAnimationLength;
int signalHeight;
int signalMovement;
int signalWidth;
int standstillDuration;
int totalFrames;
std::string speedLimitSource;
inline QColor blueColor(int alpha = 255) { return QColor(0, 0, 255, alpha); }
inline QColor greenColor(int alpha = 242) { return QColor(23, 134, 68, alpha); }
inline QColor orangeColor(int alpha = 255) { return QColor(255, 165, 0, alpha); }
inline QColor purpleColor(int alpha = 255) { return QColor(128, 0, 128, alpha); }
inline QColor yellowColor(int alpha = 255) { return QColor(255, 255, 0, alpha); }
protected:
void paintGL() override;
void initializeGL() override;
void showEvent(QShowEvent *event) override;
void updateFrameMat() override;
void drawLaneLines(QPainter &painter, const UIState *s);
void drawLead(QPainter &painter, const cereal::RadarState::LeadData::Reader &lead_data, const QPointF &vd);
void drawLaneLines(QPainter &painter, const UIState *s, float v_ego);
void drawLead(QPainter &painter, const cereal::RadarState::LeadData::Reader &lead_data, const QPointF &vd, float v_ego, const QColor &lead_marker_color, bool adjacent = false);
void drawHud(QPainter &p);
void drawDriverState(QPainter &painter, const UIState *s);
void paintEvent(QPaintEvent *event) override;
inline QColor redColor(int alpha = 255) { return QColor(201, 34, 49, alpha); }
inline QColor whiteColor(int alpha = 255) { return QColor(255, 255, 255, alpha); }
inline QColor blackColor(int alpha = 255) { return QColor(0, 0, 0, alpha); }
+231 -8
View File
@@ -4,53 +4,179 @@
#include "selfdrive/ui/qt/util.h"
void drawIcon(QPainter &p, const QPoint &center, const QPixmap &img, const QBrush &bg, float opacity) {
void drawIcon(QPainter &p, const QPoint &center, const QPixmap &img, const QBrush &bg, float opacity, const int angle) {
p.setRenderHint(QPainter::Antialiasing);
p.setOpacity(1.0); // bg dictates opacity of ellipse
p.setPen(Qt::NoPen);
p.setBrush(bg);
p.drawEllipse(center, btn_size / 2, btn_size / 2);
p.save();
p.translate(center);
p.rotate(angle);
p.setOpacity(opacity);
p.drawPixmap(center - QPoint(img.width() / 2, img.height() / 2), img);
p.drawPixmap(-QPoint(img.width() / 2, img.height() / 2), img);
p.setOpacity(1.0);
p.restore();
}
// ExperimentalButton
ExperimentalButton::ExperimentalButton(QWidget *parent) : experimental_mode(false), engageable(false), QPushButton(parent) {
setFixedSize(btn_size, btn_size);
setFixedSize(btn_size, btn_size + 10);
engage_img = loadPixmap("../assets/img_chffr_wheel.png", {img_size, img_size});
experimental_img = loadPixmap("../assets/img_experimental.svg", {img_size, img_size});
QObject::connect(this, &QPushButton::clicked, this, &ExperimentalButton::changeMode);
// FrogPilot variables
wheel_gif_path = "../frogpilot/assets/active_theme/steering_wheel/wheel.gif";
wheel_png_path = "../frogpilot/assets/active_theme/steering_wheel/wheel.png";
gif_label = new QLabel(this);
gif_label->setScaledContents(true);
}
ExperimentalButton::~ExperimentalButton() {
if (gif != nullptr) {
gif->stop();
delete gif;
gif = nullptr;
gif_label->hide();
}
}
void ExperimentalButton::changeMode() {
const auto cp = (*uiState()->sm)["carParams"].getCarParams();
bool can_change = hasLongitudinalControl(cp) && params.getBool("ExperimentalModeConfirmed");
if (can_change) {
params.putBool("ExperimentalMode", !experimental_mode);
if (conditional_experimental) {
int override_value = (conditional_status >= 1 && conditional_status <= 6) ? 0 : conditional_status >= 7 ? 5 : 6;
params_memory.putInt("CEStatus", override_value);
} else {
params.putBool("ExperimentalMode", !experimental_mode);
}
}
}
void ExperimentalButton::updateState(const UIState &s) {
const auto cs = (*s.sm)["controlsState"].getControlsState();
bool eng = cs.getEngageable() || cs.getEnabled();
bool eng = cs.getEngageable() || cs.getEnabled() || always_on_lateral_active;
if ((cs.getExperimentalMode() != experimental_mode) || (eng != engageable)) {
engageable = eng;
experimental_mode = cs.getExperimentalMode();
update();
}
// FrogPilot variables
const UIScene &scene = s.scene;
always_on_lateral_active = scene.always_on_lateral_active;
big_map = scene.big_map;
conditional_experimental = scene.conditional_experimental;
conditional_status = scene.conditional_status;
map_open = scene.map_open;
navigate_on_openpilot = scene.navigate_on_openpilot;
rotating_wheel = scene.rotating_wheel;
traffic_mode_active = scene.traffic_mode_active;
use_stock_wheel = scene.use_stock_wheel;
if (rotating_wheel && steering_angle_deg != scene.steering_angle_deg) {
steering_angle_deg = scene.steering_angle_deg;
update();
} else if (!rotating_wheel) {
steering_angle_deg = 0;
}
if (params_memory.getBool("UpdateWheelImage")) {
updateIcon();
params_memory.remove("UpdateWheelImage");
}
}
void ExperimentalButton::updateBackgroundColor() {
static const QMap<QString, QColor> status_color_map {
{"default", QColor(0, 0, 0, 166)},
{"always_on_lateral_active", bg_colors[STATUS_ALWAYS_ON_LATERAL_ACTIVE]},
{"conditional_overridden", bg_colors[STATUS_CONDITIONAL_OVERRIDDEN]},
{"experimental_mode_active", bg_colors[STATUS_EXPERIMENTAL_MODE_ACTIVE]},
{"navigation_active", bg_colors[STATUS_NAVIGATION_ACTIVE]},
{"traffic_mode_active", bg_colors[STATUS_TRAFFIC_MODE_ACTIVE]}
};
if (isDown() || !engageable || use_stock_wheel) {
background_color = status_color_map["default"];
return;
}
if (always_on_lateral_active) {
background_color = status_color_map["always_on_lateral_active"];
} else if (conditional_status == 1 || conditional_status == 3 || conditional_status == 5) {
background_color = status_color_map["conditional_overridden"];
} else if (experimental_mode) {
background_color = status_color_map["experimental_mode_active"];
} else if (navigate_on_openpilot) {
background_color = status_color_map["navigation_active"];
} else if (traffic_mode_active) {
background_color = status_color_map["traffic_mode_active"];
} else {
background_color = status_color_map["default"];
}
}
void ExperimentalButton::updateIcon() {
if (gif != nullptr) {
gif->stop();
delete gif;
gif = nullptr;
gif_label->hide();
}
if (QFile::exists(wheel_gif_path)) {
gif = new QMovie(wheel_gif_path);
if (!gif->isValid()) {
delete gif;
gif = nullptr;
return;
}
gif_label->setMovie(gif);
gif_label->resize(img_size, img_size);
gif_label->move((btn_size - img_size) / 2, (btn_size - img_size) / 2);
gif_label->show();
gif->start();
use_gif = true;
image_empty = false;
} else if (QFile::exists(wheel_png_path)) {
img = loadPixmap(wheel_png_path, {img_size, img_size});
image_empty = false;
use_gif = false;
} else {
image_empty = true;
use_gif = false;
}
update();
}
void ExperimentalButton::paintEvent(QPaintEvent *event) {
if ((big_map && map_open) || image_empty || use_gif) {
return;
}
QPainter p(this);
QPixmap img = experimental_mode ? experimental_img : engage_img;
drawIcon(p, QPoint(btn_size / 2, btn_size / 2), img, QColor(0, 0, 0, 166), (isDown() || !engageable) ? 0.6 : 1.0);
if (use_stock_wheel) {
img = experimental_mode ? experimental_img : engage_img;
}
updateBackgroundColor();
drawIcon(p, QPoint(btn_size / 2, btn_size / 2), img, background_color, (isDown() || !engageable) ? 0.6 : 1.0, steering_angle_deg);
}
// MapSettingsButton
MapSettingsButton::MapSettingsButton(QWidget *parent) : QPushButton(parent) {
setFixedSize(btn_size, btn_size);
setFixedSize(btn_size, btn_size + 20);
settings_img = loadPixmap("../assets/navigation/icon_directions_outlined.svg", {img_size, img_size});
// hidden by default, made visible if map is created (has prime or mapbox token)
@@ -62,3 +188,100 @@ void MapSettingsButton::paintEvent(QPaintEvent *event) {
QPainter p(this);
drawIcon(p, QPoint(btn_size / 2, btn_size / 2), settings_img, QColor(0, 0, 0, 166), isDown() ? 0.6 : 1.0);
}
// FrogPilot buttons
// DistanceButton
DistanceButton::DistanceButton(QWidget *parent) : QPushButton(parent) {
setFixedSize(btn_size * 1.5, btn_size * 1.5);
gif_label = new QLabel(this);
gif_label->setScaledContents(true);
connect(this, &QPushButton::pressed, [this] {params_memory.putBool("OnroadDistanceButtonPressed", true);});
connect(this, &QPushButton::released, [this] {params_memory.putBool("OnroadDistanceButtonPressed", false);});
}
DistanceButton::~DistanceButton() {
qDeleteAll(profile_data_gif);
profile_data_gif.clear();
profile_data_png.clear();
}
void DistanceButton::updateState(const UIScene &scene) {
bool state_changed = (traffic_mode_active != scene.traffic_mode_active) ||
(personality != static_cast<int>(scene.personality) + 1 && !traffic_mode_active);
if (!state_changed) {
return;
}
personality = static_cast<int>(scene.personality) + 1;
traffic_mode_active = scene.traffic_mode_active;
int profile_index = traffic_mode_active ? 0 : personality;
if (QMovie *gif = profile_data_gif.value(profile_index)) {
gif_label->setMovie(gif);
gif_label->resize(btn_size, btn_size);
gif_label->move(UI_BORDER_SIZE, btn_size / 2.5);
gif_label->show();
gif->start();
use_gif = true;
} else {
gif_label->hide();
profile_image = profile_data_png.value(profile_index);
use_gif = false;
}
update();
}
void DistanceButton::updateIcon() {
qDeleteAll(profile_data_gif);
profile_data_gif.clear();
profile_data_png.clear();
static const QVector<QString> file_names = {
"../frogpilot/assets/active_theme/distance_icons/traffic",
"../frogpilot/assets/active_theme/distance_icons/aggressive",
"../frogpilot/assets/active_theme/distance_icons/standard",
"../frogpilot/assets/active_theme/distance_icons/relaxed"
};
for (int i = 0; i < file_names.size(); ++i) {
const QString &file_name = file_names[i];
QString gif_file = file_name + ".gif";
QString png_file = file_name + ".png";
QString fallback_file = QString("../frogpilot/assets/stock_theme/distance_icons/%1.png").arg(QFileInfo(file_name).baseName().toLower());
if (QFile::exists(gif_file)) {
QMovie *movie = new QMovie(gif_file);
profile_data_gif.push_back(movie);
profile_data_png.push_back(QPixmap());
} else {
QPixmap pixmap = loadPixmap(QFile::exists(png_file) ? png_file : fallback_file, QSize(btn_size * 1.25, btn_size * 1.25));
profile_data_gif.push_back(nullptr);
profile_data_png.push_back(pixmap);
}
}
personality = 0;
}
void DistanceButton::paintEvent(QPaintEvent *event) {
if (use_gif) {
return;
}
QPainter p(this);
p.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
drawIcon(p, QPoint((btn_size / 2) + UI_BORDER_SIZE, btn_size - (UI_BORDER_SIZE * 1.5)), profile_image, Qt::transparent, 1.0);
}
+65 -1
View File
@@ -1,5 +1,7 @@
#pragma once
#include <QLabel>
#include <QMovie>
#include <QPushButton>
#include "selfdrive/ui/ui.h"
@@ -14,6 +16,10 @@ public:
explicit ExperimentalButton(QWidget *parent = 0);
void updateState(const UIState &s);
// FrogPilot widgets
~ExperimentalButton();
void updateIcon();
private:
void paintEvent(QPaintEvent *event) override;
void changeMode();
@@ -23,6 +29,37 @@ private:
QPixmap experimental_img;
bool experimental_mode;
bool engageable;
// FrogPilot widgets
void updateBackgroundColor();
// FrogPilot variables
Params params_memory{"/dev/shm/params"};
QColor background_color;
QLabel *gif_label;
QMovie *gif;
QPixmap img;
QString wheel_gif_path;
QString wheel_png_path;
bool always_on_lateral_active;
bool big_map;
bool conditional_experimental;
bool image_empty;
bool map_open;
bool navigate_on_openpilot;
bool rotating_wheel;
bool traffic_mode_active;
bool use_gif;
bool use_stock_wheel;
int conditional_status;
int steering_angle_deg;
};
@@ -38,4 +75,31 @@ private:
QPixmap settings_img;
};
void drawIcon(QPainter &p, const QPoint &center, const QPixmap &img, const QBrush &bg, float opacity);
void drawIcon(QPainter &p, const QPoint &center, const QPixmap &img, const QBrush &bg, float opacity, const int angle = 0);
// FrogPilot buttons
class DistanceButton : public QPushButton {
Q_OBJECT
public:
explicit DistanceButton(QWidget *parent = 0);
~DistanceButton();
void updateIcon();
void updateState(const UIScene &scene);
private:
void paintEvent(QPaintEvent *event) override;
Params params_memory{"/dev/shm/params"};
QLabel *gif_label;
QPixmap profile_image;
QVector<QPixmap> profile_data_png;
QVector<QMovie*> profile_data_gif;
bool traffic_mode_active;
bool use_gif;
int personality;
};
+274 -4
View File
@@ -1,5 +1,6 @@
#include "selfdrive/ui/qt/onroad/onroad_home.h"
#include <QApplication>
#include <QPainter>
#include <QStackedLayout>
@@ -48,6 +49,13 @@ OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent) {
QObject::connect(uiState(), &UIState::uiUpdate, this, &OnroadWindow::updateState);
QObject::connect(uiState(), &UIState::offroadTransition, this, &OnroadWindow::offroadTransition);
QObject::connect(uiState(), &UIState::primeChanged, this, &OnroadWindow::primeChanged);
// FrogPilot variables
QObject::connect(&clickTimer, &QTimer::timeout, [this]() {
clickTimer.stop();
QMouseEvent event(QEvent::MouseButtonPress, timeoutPoint, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QApplication::sendEvent(this, &event);
});
}
void OnroadWindow::updateState(const UIState &s) {
@@ -55,29 +63,97 @@ void OnroadWindow::updateState(const UIState &s) {
return;
}
if (s.scene.map_on_left) {
if (s.scene.map_on_left || s.scene.full_map) {
split->setDirection(QBoxLayout::LeftToRight);
} else {
split->setDirection(QBoxLayout::RightToLeft);
}
alerts->updateState(s);
nvg->updateState(s);
nvg->updateState(alerts->alert_height, s);
bool shouldUpdate = false;
QColor bgColor = bg_colors[s.status];
if (bg != bgColor) {
// repaint border
bg = bgColor;
shouldUpdate = true;
}
// FrogPilot variables
const UIScene &scene = s.scene;
acceleration = scene.acceleration;
accelerationJerk = scene.acceleration_jerk;
accelerationJerkDifference = scene.acceleration_jerk_difference;
blindSpotLeft = scene.blind_spot_left;
blindSpotRight = scene.blind_spot_right;
fps = scene.fps;
friction = scene.friction;
latAccel = scene.lat_accel;
liveValid = scene.live_valid;
showBlindspot = scene.show_blind_spot && (blindSpotLeft || blindSpotRight);
showFPS = scene.show_fps;
showJerk = scene.jerk_metrics;
showSignal = scene.signal_metrics && (turnSignalLeft || turnSignalRight);
showSteering = scene.steering_metrics;
showTuning = scene.lateral_tuning_metrics;
speedJerk = scene.speed_jerk;
speedJerkDifference = scene.speed_jerk_difference;
steer = scene.steer;
steeringAngleDeg = scene.steering_angle_deg;
turnSignalLeft = scene.turn_signal_left;
turnSignalRight = scene.turn_signal_right;
if (showBlindspot || showFPS || showJerk || showSignal || showSteering || showTuning) {
shouldUpdate = true;
}
if (shouldUpdate) {
update();
}
}
void OnroadWindow::mousePressEvent(QMouseEvent* e) {
// FrogPilot variables
UIState *s = uiState();
UIScene &scene = s->scene;
QPoint pos = e->pos();
if (scene.speed_limit_changed && nvg->newSpeedLimitRect.contains(pos)) {
params_memory.putBool("SpeedLimitAccepted", true);
return;
}
if (scene.experimental_mode_via_tap && pos != timeoutPoint) {
if (clickTimer.isActive()) {
clickTimer.stop();
if (scene.conditional_experimental) {
int override_value = scene.conditional_status != 0 && scene.conditional_status <= 6 ? 0 : scene.conditional_status >= 7 ? 5 : 6;
params_memory.putInt("CEStatus", override_value);
} else {
params.putBoolNonBlocking("ExperimentalMode", !params.getBool("ExperimentalMode"));
}
} else {
clickTimer.start(500);
}
return;
}
#ifdef ENABLE_MAPS
if (map != nullptr) {
// Switch between map and sidebar when using navigate on openpilot
bool sidebarVisible = geometry().x() > 0;
bool show_map = !sidebarVisible;
bool show_map = scene.navigate_on_openpilot ? sidebarVisible : !sidebarVisible;
map->setVisible(show_map && !map->isVisible());
if (scene.big_map) {
map->setFixedWidth(width());
} else {
map->setFixedWidth(topWidget(this)->width() / 2 - UI_BORDER_SIZE);
}
}
#endif
// propagation event to parent(HomeWindow)
@@ -125,5 +201,199 @@ void OnroadWindow::primeChanged(bool prime) {
void OnroadWindow::paintEvent(QPaintEvent *event) {
QPainter p(this);
p.fillRect(rect(), QColor(bg.red(), bg.green(), bg.blue(), 255));
// FrogPilot variables
UIState *s = uiState();
SubMaster &sm = *(s->sm);
QRect rect = this->rect();
QColor bgColor(bg.red(), bg.green(), bg.blue(), 255);
p.fillRect(rect, bgColor);
if (showSteering) {
static float smoothedSteer = 0.0;
smoothedSteer = 0.1 * std::abs(steer) + 0.9 * smoothedSteer;
if (std::abs(smoothedSteer - steer) < 0.01) {
smoothedSteer = steer;
}
QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
gradient.setColorAt(0.0, bg_colors[STATUS_TRAFFIC_MODE_ACTIVE]);
gradient.setColorAt(0.15, bg_colors[STATUS_EXPERIMENTAL_MODE_ACTIVE]);
gradient.setColorAt(0.5, bg_colors[STATUS_CONDITIONAL_OVERRIDDEN]);
gradient.setColorAt(0.85, bg_colors[STATUS_ENGAGED]);
gradient.setColorAt(1.0, bg_colors[STATUS_ENGAGED]);
QBrush brush(gradient);
if (steeringAngleDeg != 0) {
int visibleHeight = rect.height() * smoothedSteer;
QRect rectToFill, rectToHide;
if (steeringAngleDeg < 0) {
rectToFill = QRect(rect.x(), rect.y() + rect.height() - visibleHeight, UI_BORDER_SIZE, visibleHeight);
rectToHide = QRect(rect.x(), rect.y(), UI_BORDER_SIZE, rect.height() - visibleHeight);
} else {
rectToFill = QRect(rect.x() + rect.width() - UI_BORDER_SIZE, rect.y() + rect.height() - visibleHeight, UI_BORDER_SIZE, visibleHeight);
rectToHide = QRect(rect.x() + rect.width() - UI_BORDER_SIZE, rect.y(), UI_BORDER_SIZE, rect.height() - visibleHeight);
}
p.fillRect(rectToFill, brush);
p.fillRect(rectToHide, bgColor);
}
}
if (showBlindspot || showSignal) {
static bool leftFlickerActive = false;
static bool rightFlickerActive = false;
std::function<QColor(bool, bool, bool&)> getBorderColor = [&](bool blindSpot, bool turnSignal, bool &flickerActive) -> QColor {
if (showSignal && turnSignal) {
if (blindSpot) {
if (sm.frame % (UI_FREQ / 5) == 0) {
flickerActive = !flickerActive;
}
return flickerActive ? bg_colors[STATUS_TRAFFIC_MODE_ACTIVE] : bg_colors[STATUS_CONDITIONAL_OVERRIDDEN];
} else if (sm.frame % (UI_FREQ / 2) == 0) {
flickerActive = !flickerActive;
}
return flickerActive ? bg_colors[STATUS_CONDITIONAL_OVERRIDDEN] : bg;
} else if (showBlindspot && blindSpot) {
return bg_colors[STATUS_TRAFFIC_MODE_ACTIVE];
} else {
return bg;
}
};
QColor borderColorLeft = getBorderColor(blindSpotLeft, turnSignalLeft, leftFlickerActive);
QColor borderColorRight = getBorderColor(blindSpotRight, turnSignalRight, rightFlickerActive);
p.fillRect(rect.x(), rect.y(), rect.width() / 2, rect.height(), borderColorLeft);
p.fillRect(rect.x() + rect.width() / 2, rect.y(), rect.width() / 2, rect.height(), borderColorRight);
}
QString logicsDisplayString;
if (showJerk) {
if (bg == bg_colors[STATUS_ENGAGED] || bg == bg_colors[STATUS_TRAFFIC_MODE_ACTIVE]) {
maxAcceleration = std::max(maxAcceleration, acceleration);
}
maxAccelTimer = maxAcceleration == acceleration && maxAcceleration != 0 ? UI_FREQ * 5 : maxAccelTimer - 1;
logicsDisplayString += QString("Acceleration: %1 %2 - ").arg(acceleration, 0, 'f', 2).arg(nvg->accelerationUnit);
logicsDisplayString += QString("Max: %1 %2 | ").arg(maxAcceleration, 0, 'f', 2).arg(nvg->accelerationUnit);
logicsDisplayString += QString("Acceleration Jerk: %1 | ").arg(accelerationJerk, 0, 'f', 2);
logicsDisplayString += QString("Speed Jerk: %1").arg(speedJerk, 0, 'f', 2);
}
if (showTuning) {
if (!logicsDisplayString.isEmpty()) {
logicsDisplayString += " | ";
}
logicsDisplayString += QString("Friction: %1 | ").arg(liveValid ? QString::number(friction, 'f', 2) : "Calculating...");
logicsDisplayString += QString("Lateral Acceleration: %1").arg(liveValid ? QString::number(latAccel, 'f', 2) : "Calculating...");
}
if (!logicsDisplayString.isEmpty()) {
p.save();
p.setFont(InterFont(28, QFont::DemiBold));
p.setRenderHint(QPainter::TextAntialiasing);
QFontMetrics fontMetrics(p.font());
int x = (rect.width() - fontMetrics.horizontalAdvance(logicsDisplayString)) / 2 - UI_BORDER_SIZE;
int y = rect.top() + (fontMetrics.height() / 1.5);
QStringList parts = logicsDisplayString.split("|");
for (QString part : parts) {
if (part.contains("Max:") && maxAccelTimer > 0) {
QString baseText = QString("Acceleration: %1 %2 - ").arg(acceleration, 0, 'f', 2).arg(nvg->accelerationUnit);
p.setPen(whiteColor());
p.drawText(x, y, baseText);
x += fontMetrics.horizontalAdvance(baseText);
QString maxText = QString("Max: %1 %2 | ").arg(maxAcceleration, 0, 'f', 2).arg(nvg->accelerationUnit);
p.setPen(redColor());
p.drawText(x, y, maxText);
x += fontMetrics.horizontalAdvance(maxText);
} else if (part.contains("Acceleration Jerk") && accelerationJerkDifference != 0) {
QString baseText = QString("Acceleration Jerk: %1").arg(accelerationJerk, 0, 'f', 2);
p.setPen(whiteColor());
p.drawText(x, y, baseText);
x += fontMetrics.horizontalAdvance(baseText);
QString diffText = QString(" (%1) | ").arg(accelerationJerkDifference, 0, 'f', 2);
p.setPen(redColor());
p.drawText(x, y, diffText);
x += fontMetrics.horizontalAdvance(diffText);
} else if (part.contains("Speed Jerk") && speedJerkDifference != 0) {
QString baseText = QString("Speed Jerk: %1").arg(speedJerk, 0, 'f', 2);
p.setPen(whiteColor());
p.drawText(x, y, baseText);
x += fontMetrics.horizontalAdvance(baseText);
QString diffText = QString(" (%1)").arg(speedJerkDifference, 0, 'f', 2);
if (showTuning) {
diffText += " | ";
}
p.setPen(redColor());
p.drawText(x, y, diffText);
x += fontMetrics.horizontalAdvance(diffText);
} else if (part.contains("Speed Jerk") && !showTuning) {
p.setPen(whiteColor());
p.drawText(x, y, part);
x += fontMetrics.horizontalAdvance(part);
} else if (part.contains("Lateral Acceleration")) {
p.setPen(whiteColor());
p.drawText(x, y, part);
x += fontMetrics.horizontalAdvance(part);
} else {
part += " | ";
p.setPen(whiteColor());
p.drawText(x, y, part);
x += fontMetrics.horizontalAdvance(part);
}
}
p.restore();
}
if (showFPS) {
qint64 currentMillis = QDateTime::currentMSecsSinceEpoch();
static std::queue<std::pair<qint64, float>> fpsQueue;
static float avgFPS = 0.0;
static float maxFPS = 0.0;
static float minFPS = 99.9;
minFPS = std::min(minFPS, fps);
maxFPS = std::max(maxFPS, fps);
fpsQueue.push({currentMillis, fps});
while (!fpsQueue.empty() && currentMillis - fpsQueue.front().first > 60000) {
fpsQueue.pop();
}
if (!fpsQueue.empty()) {
float totalFPS = 0.0;
for (auto tempQueue = fpsQueue; !tempQueue.empty(); tempQueue.pop()) {
totalFPS += tempQueue.front().second;
}
avgFPS = totalFPS / fpsQueue.size();
}
QString fpsDisplayString = QString("FPS: %1 | Min: %3 | Max: %4 | Avg: %5")
.arg(qRound(fps))
.arg(qRound(minFPS))
.arg(qRound(maxFPS))
.arg(qRound(avgFPS));
p.setFont(InterFont(28, QFont::DemiBold));
p.setRenderHint(QPainter::TextAntialiasing);
p.setPen(whiteColor());
int textWidth = p.fontMetrics().horizontalAdvance(fpsDisplayString);
int xPos = (rect.width() - textWidth) / 2;
int yPos = rect.bottom() - 5;
p.drawText(xPos, yPos, fpsDisplayString);
}
}
+37
View File
@@ -24,6 +24,43 @@ private:
QWidget *map = nullptr;
QHBoxLayout* split;
// FrogPilot variables
bool blindSpotLeft;
bool blindSpotRight;
bool liveValid;
bool showBlindspot;
bool showFPS;
bool showJerk;
bool showSignal;
bool showSteering;
bool showTuning;
bool turnSignalLeft;
bool turnSignalRight;
float acceleration;
float accelerationJerk;
float accelerationJerkDifference;
float fps;
float friction;
float latAccel;
float maxAcceleration;
float speedJerk;
float speedJerkDifference;
float steer;
int maxAccelTimer;
int steeringAngleDeg;
QPoint timeoutPoint = QPoint(420, 69);
QTimer clickTimer;
inline QColor redColor(int alpha = 255) { return QColor(201, 34, 49, alpha); }
inline QColor whiteColor(int alpha = 255) { return QColor(255, 255, 255, alpha); }
Params params;
Params params_memory{"/dev/shm/params"};
private slots:
void offroadTransition(bool offroad);
void primeChanged(bool prime);
+265 -24
View File
@@ -25,10 +25,6 @@ void Sidebar::drawMetric(QPainter &p, const QPair<QString, QString> &label, QCol
}
Sidebar::Sidebar(QWidget *parent) : QFrame(parent), onroad(false), flag_pressed(false), settings_pressed(false) {
home_img = loadPixmap("../assets/images/button_home.png", home_btn.size());
flag_img = loadPixmap("../assets/images/button_flag.png", home_btn.size());
settings_img = loadPixmap("../assets/images/button_settings.png", settings_btn.size(), Qt::IgnoreAspectRatio);
connect(this, &Sidebar::valueChanged, [=] { update(); });
setAttribute(Qt::WA_OpaquePaintEvent);
@@ -38,15 +34,151 @@ Sidebar::Sidebar(QWidget *parent) : QFrame(parent), onroad(false), flag_pressed(
QObject::connect(uiState(), &UIState::uiUpdate, this, &Sidebar::updateState);
pm = std::make_unique<PubMaster, const std::initializer_list<const char *>>({"userFlag"});
// FrogPilot variables
home_label = new QLabel(this);
settings_label = new QLabel(this);
flagPngPath = "../frogpilot/assets/active_theme/icons/button_flag.png";
homeGifPath = "../frogpilot/assets/active_theme/icons/button_home.gif";
homePngPath = "../frogpilot/assets/active_theme/icons/button_home.png";
settingsGifPath = "../frogpilot/assets/active_theme/icons/button_settings.gif";
settingsPngPath = "../frogpilot/assets/active_theme/icons/button_settings.png";
randomEventGifPath = "../frogpilot/assets/random_events/icons/button_home.gif";
QObject::connect(uiState(), &UIState::themeUpdated, this, &Sidebar::updateIcons);
}
void Sidebar::showEvent(QShowEvent *event) {
updateIcons();
}
void Sidebar::updateIcons() {
updateIcon(home_label, home_gif, homeGifPath, home_btn, homePngPath, isHomeGif);
updateIcon(settings_label, settings_gif, settingsGifPath, settings_btn, settingsPngPath, isSettingsGif);
}
void Sidebar::updateIcon(QLabel *&label, QMovie *&gif, const QString &gifPath, const QRect &btnRect, const QString &pngPath, bool &isGif) {
QString selectedGifPath = gifPath;
if (util::random_int(1, 100) == 100 && btnRect == home_btn && isRandomEvents) {
selectedGifPath = randomEventGifPath;
}
if (gif != nullptr) {
gif->stop();
delete gif;
gif = nullptr;
if (label) {
label->hide();
}
}
if (QFile::exists(selectedGifPath)) {
gif = new QMovie(selectedGifPath);
if (gif->isValid()) {
gif->setScaledSize(btnRect.size());
if (label) {
label->setGeometry(btnRect);
label->setMovie(gif);
label->show();
}
gif->start();
isGif = true;
} else {
delete gif;
gif = nullptr;
isGif = false;
}
} else {
if (btnRect == home_btn) {
home_img = loadPixmap(homePngPath, btnRect.size());
flag_img = loadPixmap(flagPngPath, btnRect.size());
} else {
settings_img = loadPixmap(settingsPngPath, btnRect.size(), Qt::IgnoreAspectRatio);
}
isGif = false;
}
}
void Sidebar::mousePressEvent(QMouseEvent *event) {
if (onroad && home_btn.contains(event->pos())) {
UIState *s = uiState();
UIScene &scene = s->scene;
QPoint pos = event->pos();
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 (cpuRect.contains(pos) && isSidebarMetrics) {
showChip = (showChip + 1) % 3;
isCPU = (showChip == 1);
isGPU = (showChip == 2);
scene.cpu_metrics = isCPU;
scene.gpu_metrics = isGPU;
params.putBoolNonBlocking("ShowCPU", isCPU);
params.putBoolNonBlocking("ShowGPU", isGPU);
update();
return;
}
if (memoryRect.contains(pos) && isSidebarMetrics) {
showMemory = (showMemory + 1) % 4;
isMemoryUsage = (showMemory == 1);
isStorageLeft = (showMemory == 2);
isStorageUsed = (showMemory == 3);
scene.memory_metrics = isMemoryUsage;
scene.storage_left_metrics = isStorageLeft;
scene.storage_used_metrics = isStorageUsed;
params.putBoolNonBlocking("ShowMemoryUsage", isMemoryUsage);
params.putBoolNonBlocking("ShowStorageLeft", isStorageLeft);
params.putBoolNonBlocking("ShowStorageUsed", isStorageUsed);
update();
return;
}
if (tempRect.contains(pos) && isSidebarMetrics) {
showTemp = (showTemp + 1) % 3;
isFahrenheit = showTemp == 2;
scene.fahrenheit = isFahrenheit;
scene.numerical_temp = showTemp != 0;
params.putBoolNonBlocking("Fahrenheit", showTemp == 2);
params.putBoolNonBlocking("NumericalTemp", showTemp != 0);
update();
return;
}
if (onroad && home_btn.contains(pos)) {
flag_pressed = true;
update();
} else if (settings_btn.contains(event->pos())) {
return;
}
if (settings_btn.contains(pos)) {
settings_pressed = true;
update();
return;
}
}
@@ -70,7 +202,22 @@ void Sidebar::offroadTransition(bool offroad) {
}
void Sidebar::updateState(const UIState &s) {
if (!isVisible()) return;
if (!isVisible()) {
if (home_gif != nullptr) {
home_gif->stop();
delete home_gif;
home_gif = nullptr;
home_label->hide();
}
if (settings_gif != nullptr) {
settings_gif->stop();
delete settings_gif;
settings_gif = nullptr;
settings_label->hide();
}
return;
}
auto &sm = *(s.sm);
@@ -85,27 +232,95 @@ void Sidebar::updateState(const UIState &s) {
connectStatus = ItemStatus{{tr("CONNECT"), tr("OFFLINE")}, warning_color};
} else {
connectStatus = nanos_since_boot() - last_ping < 80e9
? ItemStatus{{tr("CONNECT"), tr("ONLINE")}, good_color}
? ItemStatus{{tr("CONNECT"), tr("ONLINE")}, sidebar_color3}
: ItemStatus{{tr("CONNECT"), tr("ERROR")}, danger_color};
}
setProperty("connectStatus", QVariant::fromValue(connectStatus));
ItemStatus tempStatus = {{tr("TEMP"), tr("HIGH")}, danger_color};
ItemStatus tempStatus = {{tr("TEMP"), isNumericalTemp ? max_temp : tr("HIGH")}, danger_color};
auto ts = deviceState.getThermalStatus();
if (ts == cereal::DeviceState::ThermalStatus::GREEN) {
tempStatus = {{tr("TEMP"), tr("GOOD")}, good_color};
tempStatus = {{tr("TEMP"), isNumericalTemp ? max_temp : tr("GOOD")}, sidebar_color1};
} else if (ts == cereal::DeviceState::ThermalStatus::YELLOW) {
tempStatus = {{tr("TEMP"), tr("OK")}, warning_color};
tempStatus = {{tr("TEMP"), isNumericalTemp ? max_temp : tr("OK")}, warning_color};
}
setProperty("tempStatus", QVariant::fromValue(tempStatus));
ItemStatus pandaStatus = {{tr("VEHICLE"), tr("ONLINE")}, good_color};
ItemStatus pandaStatus = {{tr("VEHICLE"), tr("ONLINE")}, sidebar_color2};
if (s.scene.pandaType == cereal::PandaState::PandaType::UNKNOWN) {
pandaStatus = {{tr("NO"), tr("PANDA")}, danger_color};
} else if (s.scene.started && !sm["liveLocationKalman"].getLiveLocationKalman().getGpsOK()) {
pandaStatus = {{tr("GPS"), tr("SEARCH")}, warning_color};
}
setProperty("pandaStatus", QVariant::fromValue(pandaStatus));
// FrogPilot variables
const UIScene &scene = s.scene;
isCPU = scene.cpu_metrics;
isFahrenheit = scene.fahrenheit;
isGPU = scene.gpu_metrics;
isIP = scene.ip_metrics;
isMemoryUsage = scene.memory_metrics;
isNumericalTemp = scene.numerical_temp;
isRandomEvents = scene.random_events;
isSidebarMetrics = scene.sidebar_metrics;
isStorageLeft = scene.storage_left_metrics;
isStorageUsed = scene.storage_used_metrics;
bool useStockColors = scene.use_stock_colors;
sidebar_color1 = useStockColors ? good_color : scene.sidebar_color1;
sidebar_color2 = useStockColors ? good_color : scene.sidebar_color2;
sidebar_color3 = useStockColors ? good_color : scene.sidebar_color3;
const cereal::FrogPilotDeviceState::Reader &frogpilotDeviceState = sm["frogpilotDeviceState"].getFrogpilotDeviceState();
int maxTempC = deviceState.getMaxTempC();
max_temp = isFahrenheit ? QString::number(maxTempC * 9 / 5 + 32) + "°F" : QString::number(maxTempC) + "°C";
if (isCPU || isGPU) {
auto cpu_loads = deviceState.getCpuUsagePercent();
int cpu_usage = cpu_loads.size() != 0 ? std::accumulate(cpu_loads.begin(), cpu_loads.end(), 0) / cpu_loads.size() : 0;
int gpu_usage = deviceState.getGpuUsagePercent();
int usage = isGPU ? gpu_usage : cpu_usage;
QString chip_usage = QString::number(usage) + "%";
ItemStatus cpuStatus = {{isGPU ? tr("GPU") : tr("CPU"), chip_usage}, sidebar_color2};
if (usage >= 85) {
cpuStatus = {{isGPU ? tr("GPU") : tr("CPU"), chip_usage}, danger_color};
} else if (usage >= 70) {
cpuStatus = {{isGPU ? tr("GPU") : tr("CPU"), chip_usage}, 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}, sidebar_color3};
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}, sidebar_color3};
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));
}
}
}
void Sidebar::paintEvent(QPaintEvent *event) {
@@ -116,28 +331,54 @@ void Sidebar::paintEvent(QPaintEvent *event) {
p.fillRect(rect(), QColor(57, 57, 57));
// buttons
p.setOpacity(settings_pressed ? 0.65 : 1.0);
p.drawPixmap(settings_btn.x(), settings_btn.y(), settings_img);
p.setOpacity(onroad && flag_pressed ? 0.65 : 1.0);
p.drawPixmap(home_btn.x(), home_btn.y(), onroad ? flag_img : home_img);
if (!isSettingsGif) {
p.setOpacity(settings_pressed ? 0.65 : 1.0);
p.drawPixmap(settings_btn.x(), settings_btn.y(), settings_img);
}
if (!isHomeGif) {
p.setOpacity(onroad && flag_pressed ? 0.65 : 1.0);
p.drawPixmap(home_btn.x(), home_btn.y(), onroad ? flag_img : home_img);
}
p.setOpacity(1.0);
// 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);
}
}
+48
View File
@@ -3,7 +3,9 @@
#include <memory>
#include <QFrame>
#include <QLabel>
#include <QMap>
#include <QMovie>
#include "selfdrive/ui/ui.h"
@@ -18,6 +20,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);
@@ -59,4 +66,45 @@ protected:
private:
std::unique_ptr<PubMaster> pm;
// FrogPilot widgets
void showEvent(QShowEvent *event);
void updateIcon(QLabel *&label, QMovie *&gif, const QString &gifPath, const QRect &btnRect, const QString &pngPath, bool &isGif);
void updateIcons();
// FrogPilot variables
Params params;
ItemStatus cpu_status, memory_status, storage_status;
bool isCPU;
bool isFahrenheit;
bool isGPU;
bool isHomeGif;
bool isIP;
bool isMemoryUsage;
bool isNumericalTemp;
bool isRandomEvents;
bool isSettingsGif;
bool isSidebarMetrics;
bool isStorageLeft;
bool isStorageUsed;
QColor sidebar_color1;
QColor sidebar_color2;
QColor sidebar_color3;
QLabel *home_label;
QLabel *settings_label;
QMovie *home_gif;
QMovie *settings_gif;
QString flagPngPath;
QString homeGifPath;
QString homePngPath;
QString max_temp;
QString randomEventGifPath;
QString settingsGifPath;
QString settingsPngPath;
};
+1 -1
View File
@@ -88,7 +88,7 @@ Spinner::Spinner(QWidget *parent) : QWidget(parent) {
}
QProgressBar::chunk {
border-radius: 10px;
background-color: white;
background-color: rgba(23, 134, 68, 255);
}
)");
+5 -4
View File
@@ -26,7 +26,7 @@ QString getVersion() {
}
QString getBrand() {
return QObject::tr("openpilot");
return QObject::tr("FrogPilot");
}
QString getUserAgent() {
@@ -247,9 +247,10 @@ QPixmap bootstrapPixmap(const QString &id) {
bool hasLongitudinalControl(const cereal::CarParams::Reader &car_params) {
// Using the experimental longitudinal toggle, returns whether longitudinal control
// will be active without needing a restart of openpilot
return car_params.getExperimentalLongitudinalAvailable()
? Params().getBool("ExperimentalLongitudinalEnabled")
: car_params.getOpenpilotLongitudinalControl();
Params params = Params();
return (car_params.getExperimentalLongitudinalAvailable()
? params.getBool("ExperimentalLongitudinalEnabled")
: car_params.getOpenpilotLongitudinalControl()) && !params.getBool("DisableOpenpilotLongitudinal");
}
// ParamWatcher
+27
View File
@@ -132,6 +132,10 @@ public:
toggle.update();
}
void refresh() {
toggle.togglePosition();
}
signals:
void toggleFlipped(bool state);
@@ -221,10 +225,12 @@ public:
button->setMinimumWidth(minimum_button_width);
hlayout->addWidget(button);
button_group->addButton(button, i);
button->installEventFilter(this);
}
QObject::connect(button_group, QOverload<int>::of(&QButtonGroup::buttonClicked), [=](int id) {
params.put(key, std::to_string(id));
emit buttonClicked(id);
});
}
@@ -234,6 +240,12 @@ public:
}
}
void setEnabledButtons(int id, bool enable) {
if (QAbstractButton *button = button_group->button(id)) {
button->setEnabled(enable);
}
}
void setCheckedButton(int id) {
button_group->button(id)->setChecked(true);
}
@@ -247,6 +259,21 @@ public:
refresh();
}
signals:
void buttonClicked(int id);
void disabledButtonClicked(int id);
protected:
bool eventFilter(QObject *obj, QEvent *event) override {
if (event->type() == QEvent::MouseButtonPress) {
QPushButton *button = qobject_cast<QPushButton *>(obj);
if (button && !button->isEnabled()) {
emit disabledButtonClicked(button_group->id(button));
}
}
return AbstractControl::eventFilter(obj, event);
}
private:
std::string key;
Params params;
+21 -4
View File
@@ -141,19 +141,25 @@ InputDialog::InputDialog(const QString &title, QWidget *parent, const QString &s
QObject::connect(k, &Keyboard::emitEnter, this, &InputDialog::handleEnter);
QObject::connect(k, &Keyboard::emitBackspace, this, [=]() {
line->backspace();
updateMaxLengthSublabel(line->text());
});
QObject::connect(k, &Keyboard::emitKey, this, [=](const QString &key) {
line->insert(key.left(1));
if (line->text().length() < maxLength || maxLength == DEFAULT_MAX_LENGTH) {
line->insert(key.left(1));
updateMaxLengthSublabel(line->text());
}
});
main_layout->addWidget(k, 2, Qt::AlignBottom);
}
QString InputDialog::getText(const QString &prompt, QWidget *parent, const QString &subtitle,
bool secret, int minLength, const QString &defaultText) {
bool secret, int minLength, const QString &defaultText, int maxLength) {
InputDialog d = InputDialog(prompt, parent, subtitle, secret);
d.line->setText(defaultText);
d.setMinLength(minLength);
d.setMaxLength(maxLength);
d.updateMaxLengthSublabel(defaultText);
const int ret = d.exec();
return ret ? d.text() : QString();
}
@@ -186,10 +192,21 @@ void InputDialog::setMinLength(int length) {
minLength = length;
}
// FrogPilot functions
void InputDialog::setMaxLength(int length) {
maxLength = length;
}
void InputDialog::updateMaxLengthSublabel(const QString &text) {
if (maxLength != DEFAULT_MAX_LENGTH) {
sublabel->setText(tr("Characters: %1/%2").arg(text.length()).arg(maxLength));
}
}
// ConfirmationDialog
ConfirmationDialog::ConfirmationDialog(const QString &prompt_text, const QString &confirm_text, const QString &cancel_text,
const bool rich, QWidget *parent) : DialogBase(parent) {
const bool rich, QWidget *parent, const bool is_long) : DialogBase(parent) {
QFrame *container = new QFrame(this);
container->setStyleSheet(R"(
QFrame { background-color: #1B1B1B; color: #C9C9C9; }
@@ -197,7 +214,7 @@ ConfirmationDialog::ConfirmationDialog(const QString &prompt_text, const QString
#confirm_btn:pressed { background-color: #3049F4; }
)");
QVBoxLayout *main_layout = new QVBoxLayout(container);
main_layout->setContentsMargins(32, rich ? 32 : 120, 32, 32);
main_layout->setContentsMargins(32, rich || is_long ? 32 : 120, 32, 32);
QLabel *prompt = new QLabel(prompt_text, this);
prompt->setWordWrap(true);
+12 -2
View File
@@ -9,6 +9,7 @@
#include "selfdrive/ui/qt/widgets/keyboard.h"
const int DEFAULT_MAX_LENGTH = 512;
class DialogBase : public QDialog {
Q_OBJECT
@@ -27,12 +28,15 @@ class InputDialog : public DialogBase {
public:
explicit InputDialog(const QString &title, QWidget *parent, const QString &subtitle = "", bool secret = false);
static QString getText(const QString &title, QWidget *parent, const QString &subtitle = "",
bool secret = false, int minLength = -1, const QString &defaultText = "");
bool secret = false, int minLength = -1, const QString &defaultText = "", int maxLength = DEFAULT_MAX_LENGTH);
QString text();
void setMessage(const QString &message, bool clearInputField = true);
void setMinLength(int length);
void show();
// FrogPilot widgets
void setMaxLength(int length);
private:
int minLength;
QLineEdit *line;
@@ -42,6 +46,12 @@ private:
QVBoxLayout *main_layout;
QPushButton *eye_btn;
// FrogPilot widgets
void updateMaxLengthSublabel(const QString &text);
// FrogPilot variables
int maxLength;
private slots:
void handleEnter();
@@ -55,7 +65,7 @@ class ConfirmationDialog : public DialogBase {
public:
explicit ConfirmationDialog(const QString &prompt_text, const QString &confirm_text,
const QString &cancel_text, const bool rich, QWidget* parent);
const QString &cancel_text, const bool rich, QWidget* parent, const bool is_long=false);
static bool alert(const QString &prompt_text, QWidget *parent);
static bool confirm(const QString &prompt_text, const QString &confirm_text, QWidget *parent);
static bool rich(const QString &prompt_text, QWidget *parent);
+12
View File
@@ -32,6 +32,17 @@ AbstractAlert::AbstractAlert(bool hasRebootBtn, QWidget *parent) : QFrame(parent
footer_layout->addWidget(dismiss_btn, 0, Qt::AlignBottom | Qt::AlignLeft);
QObject::connect(dismiss_btn, &QPushButton::clicked, this, &AbstractAlert::dismiss);
disable_check_btn = new QPushButton(tr("Disable Internet Check"));
disable_check_btn->setVisible(false);
disable_check_btn->setFixedSize(625, 125);
footer_layout->addWidget(disable_check_btn, 1, Qt::AlignBottom | Qt::AlignCenter);
QObject::connect(disable_check_btn, &QPushButton::clicked, [=]() {
params.putBool("DeviceManagement", true);
params.putBool("OfflineMode", true);
});
QObject::connect(disable_check_btn, &QPushButton::clicked, this, &AbstractAlert::dismiss);
disable_check_btn->setStyleSheet(R"(color: white; background-color: #4F4F4F;)");
snooze_btn = new QPushButton(tr("Snooze Update"));
snooze_btn->setVisible(false);
snooze_btn->setFixedSize(550, 125);
@@ -107,6 +118,7 @@ int OffroadAlert::refresh() {
label->setVisible(!text.isEmpty());
alertCount += !text.isEmpty();
}
disable_check_btn->setVisible(!alerts["Offroad_ConnectivityNeeded"]->text().isEmpty());
snooze_btn->setVisible(!alerts["Offroad_ConnectivityNeeded"]->text().isEmpty());
return alertCount;
}
+1
View File
@@ -15,6 +15,7 @@ class AbstractAlert : public QFrame {
protected:
AbstractAlert(bool hasRebootBtn, QWidget *parent = nullptr);
QPushButton *disable_check_btn;
QPushButton *snooze_btn;
QVBoxLayout *scrollable_layout;
Params params;
+2
View File
@@ -18,7 +18,9 @@ SshControl::SshControl() :
}
} else {
params.remove("GithubUsername");
params_storage.remove("GithubUsername");
params.remove("GithubSshKeys");
params_storage.remove("GithubSshKeys");
refresh();
}
});
+3
View File
@@ -29,4 +29,7 @@ private:
void refresh();
void getUserKeys(const QString &username);
// FrogPilot variables
Params params_storage{"/persist/params"};
};
+1 -1
View File
@@ -75,7 +75,7 @@ void Toggle::setEnabled(bool value) {
enabled = value;
if (value) {
circleColor.setRgb(0xfafafa);
green.setRgb(0x33ab4c);
green.setRgb(0x178644);
} else {
circleColor.setRgb(0x888888);
green.setRgb(0x227722);
+30 -1
View File
@@ -81,6 +81,35 @@ WiFiPromptWidget::WiFiPromptWidget(QWidget *parent) : QFrame(parent) {
}
stack->addWidget(uploading);
// not uploading data
QWidget *notUploading = new QWidget;
QVBoxLayout *not_uploading_layout = new QVBoxLayout(notUploading);
not_uploading_layout->setContentsMargins(64, 56, 64, 56);
not_uploading_layout->setSpacing(36);
{
QHBoxLayout *title_layout = new QHBoxLayout;
{
QLabel *title = new QLabel(tr("Uploading disabled"));
title->setStyleSheet("font-size: 64px; font-weight: 600;");
title->setWordWrap(true);
title->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
title_layout->addWidget(title);
title_layout->addStretch();
QLabel *icon = new QLabel;
QPixmap pixmap("../frogpilot/assets/other_images/icon_wifi_uploading_disabled.svg");
icon->setPixmap(pixmap.scaledToWidth(120, Qt::SmoothTransformation));
title_layout->addWidget(icon);
}
not_uploading_layout->addLayout(title_layout);
QLabel *desc = new QLabel(tr("Toggle off the 'Turn Off Data Uploads' toggle to re-enable uploads."));
desc->setStyleSheet("font-size: 48px; font-weight: 400;");
desc->setWordWrap(true);
not_uploading_layout->addWidget(desc);
}
stack->addWidget(notUploading);
setStyleSheet(R"(
WiFiPromptWidget {
background-color: #333333;
@@ -99,5 +128,5 @@ void WiFiPromptWidget::updateState(const UIState &s) {
auto network_type = sm["deviceState"].getDeviceState().getNetworkType();
auto uploading = network_type == cereal::DeviceState::NetworkType::WIFI ||
network_type == cereal::DeviceState::NetworkType::ETHERNET;
stack->setCurrentIndex(uploading ? 1 : 0);
stack->setCurrentIndex(s.scene.no_uploads ? 2 : uploading ? 1 : 0);
}
+4
View File
@@ -18,6 +18,10 @@ signals:
public slots:
void updateState(const UIState &s);
private:
// FrogPilot variables
Params params;
protected:
QStackedLayout *stack;
};
+8 -3
View File
@@ -74,7 +74,12 @@ void MainWindow::closeSettings() {
main_layout->setCurrentWidget(homeWindow);
if (uiState()->scene.started) {
homeWindow->showSidebar(false);
// Map is always shown when using navigate on openpilot
if (uiState()->scene.navigate_on_openpilot) {
homeWindow->showMapPanel(true);
} else {
homeWindow->showSidebar(params.getBool("Sidebar"));
}
}
}
@@ -87,8 +92,8 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
case QEvent::MouseButtonPress:
case QEvent::MouseMove: {
// ignore events when device is awakened by resetInteractiveTimeout
ignore = !device()->isAwake();
device()->resetInteractiveTimeout();
ignore = !device()->isAwake() || uiState()->scene.driver_camera_timer >= 10;
device()->resetInteractiveTimeout(uiState()->scene.screen_timeout, uiState()->scene.screen_timeout_onroad);
break;
}
default:
+3
View File
@@ -22,4 +22,7 @@ private:
HomeWindow *homeWindow;
SettingsWindow *settingsWindow;
OnboardingWindow *onboardingWindow;
// FrogPilot variables
Params params;
};