ui: New ButtomParamControl design

This commit is contained in:
Jason Wen
2023-10-04 16:59:33 +00:00
parent 2c43f3b15b
commit fb6acf9ff1
12 changed files with 132 additions and 185 deletions

View File

@@ -236,7 +236,6 @@ std::unordered_map<std::string, uint32_t> keys = {
{"DynamicExperimentalControl", PERSISTENT},
{"DynamicExperimentalControlToggle", PERSISTENT},
{"DynamicLaneProfile", PERSISTENT},
{"DynamicLaneProfileToggle", PERSISTENT},
{"EnableAmap", PERSISTENT},
{"EnableDebugSnapshot", PERSISTENT},
{"EnableGmap", PERSISTENT},
@@ -283,7 +282,6 @@ std::unordered_map<std::string, uint32_t> keys = {
{"ReverseDmCam", PERSISTENT},
{"ScreenRecorder", PERSISTENT},
{"ShowDebugUI", PERSISTENT},
{"SidebarTemperature", PERSISTENT},
{"SidebarTemperatureOptions", PERSISTENT},
{"SpeedLimitControl", PERSISTENT},
{"SpeedLimitPercOffset", PERSISTENT},

View File

@@ -57,7 +57,6 @@ class LateralPlanner:
self.reset_mpc(np.zeros(4))
self.param_s = Params()
self.dynamic_lane_profile_enabled = self.param_s.get_bool("DynamicLaneProfileToggle")
self.dynamic_lane_profile = int(self.param_s.get("DynamicLaneProfile", encoding="utf8"))
self.dynamic_lane_profile_status = True
self.dynamic_lane_profile_status_buffer = False
@@ -73,7 +72,6 @@ class LateralPlanner:
def read_param(self):
self.dynamic_lane_profile = int(self.param_s.get("DynamicLaneProfile", encoding='utf8'))
if self.param_read_counter % 50 == 0:
self.dynamic_lane_profile_enabled = self.param_s.get_bool("DynamicLaneProfileToggle")
self.vision_curve_laneless = self.param_s.get_bool("VisionCurveLaneless")
self.param_read_counter += 1
@@ -163,9 +161,7 @@ class LateralPlanner:
self.solution_invalid_cnt = 0
def get_dynamic_lane_profile(self, longitudinal_plan_sp):
if not self.dynamic_lane_profile_enabled:
return True
elif self.dynamic_lane_profile == 1:
if self.dynamic_lane_profile == 1:
return True
elif self.dynamic_lane_profile == 0:
return False

View File

@@ -70,7 +70,6 @@ def manager_init() -> None:
("DisableOnroadUploads", "0"),
("DisengageLateralOnBrake", "0"),
("DynamicLaneProfile", "1"),
("DynamicLaneProfileToggle", "0"),
("EnableMads", "1"),
("EnhancedScc", "0"),
("GpxDeleteAfterUpload", "1"),

View File

@@ -280,15 +280,11 @@ SPControlsPanel::SPControlsPanel(QWidget *parent) : ListWidget(parent) {
},
};
// Controls: Dynamic Lane Profile group
auto dynamic_lane_profile = new DynamicLaneProfile(this);
// toggle names to trigger updateToggles() when toggleFlipped
std::vector<std::string> updateTogglesNames{
"EnableMads", "CustomOffsets", "EnforceTorqueLateral", "SpeedLimitPercOffset", "SpeedLimitControl",
"CustomTorqueLateral", "LiveTorque", "TorquedOverride"
};
connect(dynamic_lane_profile, &DynamicLaneProfile::updateExternalToggles, this, &SPControlsPanel::updateToggles);
// toggle for offroadTransition when going onroad/offroad
std::vector<std::string> toggleOffroad{
@@ -328,6 +324,13 @@ SPControlsPanel::SPControlsPanel(QWidget *parent) : ListWidget(parent) {
lat_accel_factor = new TorqueMaxLatAccel();
connect(lat_accel_factor, &SPOptionControl::updateLabels, lat_accel_factor, &TorqueMaxLatAccel::refresh);
std::vector<QString> dlp_settings_texts{tr("Laneful"), tr("Laneless"), tr("Auto")};
dlp_settings = new ButtonParamControl(
"DynamicLaneProfile", "Dynamic Lane Profile", "Default is Laneless. In Auto mode, sunnnypilot dynamically chooses between Laneline or Laneless model based on lane recognition confidence level on road and certain conditions.",
"../assets/offroad/icon_blank.png",
dlp_settings_texts
);
for (auto &[param, title, desc, icon] : toggle_defs) {
auto toggle = new ParamControl(param, title, desc, icon, this);
@@ -336,7 +339,7 @@ SPControlsPanel::SPControlsPanel(QWidget *parent) : ListWidget(parent) {
if (param == "RoadEdge") {
// Controls: Dynamic Lane Profile group
addItem(dynamic_lane_profile);
addItem(dlp_settings);
}
if (param == "CustomOffsets") {
@@ -410,10 +413,18 @@ SPControlsPanel::SPControlsPanel(QWidget *parent) : ListWidget(parent) {
friction->refresh();
lat_accel_factor->refresh();
});
param_watcher = new ParamWatcher(this);
QObject::connect(param_watcher, &ParamWatcher::paramChanged, [=](const QString &param_name, const QString &param_value) {
updateToggles();
updateButtons();
});
}
void SPControlsPanel::showEvent(QShowEvent *event) {
updateToggles();
updateButtons();
}
void SPControlsPanel::updateToggles() {
@@ -425,8 +436,8 @@ void SPControlsPanel::updateToggles() {
}
}
// toggle names to update when DynamicLaneProfileToggle is flipped
toggles["VisionCurveLaneless"]->setVisible(params.getBool("DynamicLaneProfileToggle"));
// toggle VisionCurveLaneless when DynamicLaneProfile == 2/Auto
toggles["VisionCurveLaneless"]->setEnabled(QString::fromStdString(params.get("DynamicLaneProfile")) == "2");
// toggle names to update when CustomOffsets is flipped
std::vector<AbstractControl*> customOffsetsGroup{camera_offset, path_offset};
@@ -508,6 +519,14 @@ void SPControlsPanel::updateToggles() {
}
}
void SPControlsPanel::updateButtons() {
param_watcher->addParam("DynamicLaneProfile");
if (!isVisible()) return;
dlp_settings->setButton("DynamicLaneProfile");
}
SPVehiclesPanel::SPVehiclesPanel(QWidget *parent) : QWidget(parent) {
main_layout = new QStackedLayout(this);
home = new QWidget(this);
@@ -724,8 +743,14 @@ SPVisualsPanel::SPVisualsPanel(QWidget *parent) : ListWidget(parent) {
}
}
auto sidebar_temp = new SidebarTemp(this);
addItem(sidebar_temp);
std::vector<QString> sidebar_temp_texts{tr("Off"), tr("Ambient"), tr("RAM"), tr("CPU"), tr("GPU"), tr("Max")};
sidebar_temp_setting = new ButtonParamControl(
"SidebarTemperatureOptions", "Display Temperature on Sidebar", "",
"../assets/offroad/icon_blank.png",
sidebar_temp_texts,
255
);
addItem(sidebar_temp_setting);
// trigger updateToggles() when toggleFlipped
connect(toggles["DevUI"], &ToggleControl::toggleFlipped, [=](bool state) {
@@ -1034,96 +1059,3 @@ void ChevronInfo::refresh() {
setLabel(tr("Speed"));
}
}
SidebarTemp::SidebarTemp(QWidget *parent) : QWidget(parent), outer_layout(this) {
outer_layout.setMargin(0);
outer_layout.setSpacing(0);
outer_layout.addLayout(&inner_layout);
inner_layout.setMargin(0);
//inner_layout.setSpacing(25); // default spacing is 25
outer_layout.addStretch();
sidebarTemperature = new ParamControl(
"SidebarTemperature",
tr("Display Temperature on Sidebar"),
tr("Display Ambient temperature, memory temperature, CPU core with the highest temperature, GPU temperature, or max of Memory/CPU/GPU on the sidebar."),
"../assets/offroad/icon_calibration.png"
);
std::vector<QString> sidebar_temp_texts{tr("Ambient"), tr("Memory"), tr("CPU"), tr("GPU"), tr("Max")};
sidebar_temp_setting = new ButtonParamControl(
"SidebarTemperatureOptions", "", "",
"../assets/offroad/icon_blank.png",
sidebar_temp_texts
);
connect(sidebarTemperature, &ToggleControl::toggleFlipped, [=](bool state) {
updateToggles();
});
addItem(sidebarTemperature);
addItem(sidebar_temp_setting);
}
void SidebarTemp::showEvent(QShowEvent *event) {
updateToggles();
}
void SidebarTemp::updateToggles() {
sidebar_temp_setting->setVisible(sidebarTemperature->isToggled());
}
DynamicLaneProfile::DynamicLaneProfile(QWidget *parent) : QWidget(parent), outer_layout(this) {
outer_layout.setMargin(0);
outer_layout.setSpacing(0);
outer_layout.addLayout(&inner_layout);
inner_layout.setMargin(0);
//inner_layout.setSpacing(25); // default spacing is 25
outer_layout.addStretch();
dynamicLaneProfile = new ParamControl(
"DynamicLaneProfileToggle",
tr("Enable Dynamic Lane Profile"),
tr("Enable toggle to use Dynamic Lane Profile. Disable toggle to use Laneless only."),
"../assets/offroad/icon_road.png"
);
std::vector<QString> dlp_settings_texts{tr("Laneful"), tr("Laneless"), tr("Auto")};
dlp_settings = new ButtonParamControl(
"DynamicLaneProfile", "", "",
"../assets/offroad/icon_blank.png",
dlp_settings_texts
);
connect(dynamicLaneProfile, &ToggleControl::toggleFlipped, [=]() {
updateToggles();
emit updateExternalToggles();
});
addItem(dynamicLaneProfile);
addItem(dlp_settings);
param_watcher = new ParamWatcher(this);
QObject::connect(param_watcher, &ParamWatcher::paramChanged, [=](const QString &param_name, const QString &param_value) {
updateButtons();
});
}
void DynamicLaneProfile::showEvent(QShowEvent *event) {
updateToggles();
updateButtons();
}
void DynamicLaneProfile::updateToggles() {
// toggle names to update when DynamicLaneProfile is flipped
dlp_settings->setVisible(dynamicLaneProfile->isToggled());
}
void DynamicLaneProfile::updateButtons() {
param_watcher->addParam("DynamicLaneProfile");
if (!isVisible()) return;
dlp_settings->setButton("DynamicLaneProfile");
}

View File

@@ -258,56 +258,6 @@ private:
Params params;
};
class SidebarTemp : public QWidget {
Q_OBJECT
public:
explicit SidebarTemp(QWidget *parent = nullptr);
void showEvent(QShowEvent *event) override;
public slots:
void updateToggles();
private:
inline void addItem(QWidget *w) { inner_layout.addWidget(w); }
inline void addItem(QLayout *layout) { inner_layout.addLayout(layout); }
inline void setSpacing(int spacing) { inner_layout.setSpacing(spacing); }
QVBoxLayout outer_layout;
QVBoxLayout inner_layout;
Params params;
ParamControl *sidebarTemperature;
ButtonParamControl *sidebar_temp_setting;
};
class DynamicLaneProfile : public QWidget {
Q_OBJECT
public:
explicit DynamicLaneProfile(QWidget *parent = nullptr);
void showEvent(QShowEvent *event) override;
signals:
void updateExternalToggles();
public slots:
void updateToggles();
private:
inline void addItem(QWidget *w) { inner_layout.addWidget(w); }
inline void addItem(QLayout *layout) { inner_layout.addLayout(layout); }
inline void setSpacing(int spacing) { inner_layout.setSpacing(spacing); }
QVBoxLayout outer_layout;
QVBoxLayout inner_layout;
Params params;
ParamControl *dynamicLaneProfile;
ButtonParamControl *dlp_settings;
ParamWatcher *param_watcher;
void updateButtons();
};
class SPGeneralPanel : public ListWidget {
Q_OBJECT
@@ -339,6 +289,7 @@ public slots:
private:
Params params;
std::map<std::string, ParamControl*> toggles;
ParamWatcher *param_watcher;
CameraOffset *camera_offset;
PathOffset *path_offset;
@@ -347,6 +298,9 @@ private:
SpeedLimitValueOffset *slvo;
TorqueFriction *friction;
TorqueMaxLatAccel *lat_accel_factor;
ButtonParamControl *dlp_settings;
void updateButtons();
};
class SPVehiclesPanel : public QWidget {
@@ -388,6 +342,7 @@ private:
DevUiInfo *dev_ui_info;
ChevronInfo *chevron_info;
ButtonParamControl *sidebar_temp_setting;
void updateToggles();
};

View File

@@ -426,7 +426,7 @@ void OnroadSettingsButton::paintEvent(QPaintEvent *event) {
void OnroadSettingsButton::updateState(const UIState &s) {
const auto cp = (*s.sm)["carParams"].getCarParams();
auto dlp_enabled = s.scene.dynamic_lane_profile_toggle;
auto dlp_enabled = true;
auto dec_enabled = s.scene.dynamic_experimental_control_toggle;
bool allow_btn = dlp_enabled || hasLongitudinalControl(cp) || dec_enabled || !cp.getPcmCruiseSpeed();
@@ -1587,9 +1587,7 @@ void AnnotatedCameraWidget::drawFeatureStatusText(QPainter &p, int x, int y) {
}
// Dynamic Lane Profile
if (uiState()->scene.dynamic_lane_profile_toggle) {
drawFeatureStatusElement(dynamicLaneProfile, feature_text.dlp_list_text, feature_color.dlp_list_color, uiState()->scene.dynamic_lane_profile_toggle, "OFF", "DLP");
}
drawFeatureStatusElement(dynamicLaneProfile, feature_text.dlp_list_text, feature_color.dlp_list_color, true, "OFF", "DLP");
if (uiState()->scene.dynamic_experimental_control_toggle) {
bool cruise_enabled = (*uiState()->sm)["carState"].getCarState().getCruiseState().getEnabled();

View File

@@ -110,7 +110,7 @@ OnroadSettings::OnroadSettings(bool closeable, QWidget *parent) : QFrame(parent)
void OnroadSettings::changeDynamicLaneProfile() {
UIScene &scene = uiState()->scene;
bool can_change = scene.dynamic_lane_profile_toggle;
bool can_change = true;
if (can_change) {
scene.dynamic_lane_profile++;
scene.dynamic_lane_profile = scene.dynamic_lane_profile > 2 ? 0 : scene.dynamic_lane_profile;
@@ -158,7 +158,6 @@ void OnroadSettings::showEvent(QShowEvent *event) {
void OnroadSettings::refresh() {
param_watcher->addParam("DynamicLaneProfile");
param_watcher->addParam("DynamicLaneProfileToggle");
param_watcher->addParam("LongitudinalPersonality");
param_watcher->addParam("DynamicExperimentalControl");
param_watcher->addParam("DynamicExperimentalControlToggle");
@@ -179,7 +178,7 @@ void OnroadSettings::refresh() {
// Dynamic Lane Profile
dlp_widget->updateDynamicLaneProfile("DynamicLaneProfile");
dlp_widget->setVisible(params.getBool("DynamicLaneProfileToggle"));
dlp_widget->setVisible(true);
// Gap Adjust Cruise
gac_widget->updateGapAdjustCruise("LongitudinalPersonality");

View File

@@ -95,12 +95,14 @@ void Sidebar::updateState(const UIState &s) {
if (sm.frame % UI_FREQ == 0) { // Update every 1 Hz
switch (s.scene.sidebar_temp_options) {
case 0:
sidebar_temp = QString::number((int)deviceState.getAmbientTempC());
break;
case 1:
sidebar_temp = QString::number((int)deviceState.getAmbientTempC());
break;
case 2:
sidebar_temp = QString::number((int)deviceState.getMemoryTempC());
break;
case 2: {
case 3: {
const auto& cpu_temp_list = deviceState.getCpuTempC();
float max_cpu_temp = std::numeric_limits<float>::lowest();
@@ -113,7 +115,7 @@ void Sidebar::updateState(const UIState &s) {
}
break;
}
case 3: {
case 4: {
const auto& gpu_temp_list = deviceState.getGpuTempC();
float max_gpu_temp = std::numeric_limits<float>::lowest();
@@ -126,7 +128,7 @@ void Sidebar::updateState(const UIState &s) {
}
break;
}
case 4:
case 5:
sidebar_temp = QString::number((int)deviceState.getMaxTempC());
break;
default:
@@ -136,12 +138,13 @@ void Sidebar::updateState(const UIState &s) {
setProperty("sidebarTemp", sidebar_temp + "°C");
}
ItemStatus tempStatus = {{tr("TEMP"), s.scene.sidebar_temp ? sidebar_temp_str : tr("HIGH")}, danger_color};
bool show_sidebar_temp = s.scene.sidebar_temp_options != 0;
ItemStatus tempStatus = {{tr("TEMP"), show_sidebar_temp ? sidebar_temp_str : tr("HIGH")}, danger_color};
auto ts = deviceState.getThermalStatus();
if (ts == cereal::DeviceState::ThermalStatus::GREEN) {
tempStatus = {{tr("TEMP"), s.scene.sidebar_temp ? sidebar_temp_str : tr("GOOD")}, good_color};
tempStatus = {{tr("TEMP"), show_sidebar_temp ? sidebar_temp_str : tr("GOOD")}, good_color};
} else if (ts == cereal::DeviceState::ThermalStatus::YELLOW) {
tempStatus = {{tr("TEMP"), s.scene.sidebar_temp ? sidebar_temp_str : tr("OK")}, warning_color};
tempStatus = {{tr("TEMP"), show_sidebar_temp ? sidebar_temp_str : tr("OK")}, warning_color};
}
setProperty("tempStatus", QVariant::fromValue(tempStatus));

View File

@@ -61,6 +61,36 @@ void AbstractControl::hideEvent(QHideEvent *e) {
}
}
SPAbstractControl::SPAbstractControl(const QString &title, const QString &desc, const QString &icon, QWidget *parent) : QFrame(parent) {
QVBoxLayout *main_layout = new QVBoxLayout(this);
main_layout->setMargin(0);
hlayout = new QHBoxLayout;
hlayout->setMargin(0);
hlayout->setSpacing(0);
// title
title_label = new QPushButton(title);
title_label->setFixedHeight(120);
title_label->setStyleSheet("font-size: 50px; font-weight: 400; text-align: left; border: none;");
main_layout->addWidget(title_label, 1);
main_layout->addLayout(hlayout);
// description
description = new QLabel(desc);
description->setContentsMargins(0, 20, 40, 20);
description->setStyleSheet("font-size: 40px; color: grey");
description->setWordWrap(true);
description->setVisible(true);
main_layout->addWidget(description);
main_layout->addStretch();
}
void SPAbstractControl::hideEvent(QHideEvent *e) {
}
// controls
ButtonControl::ButtonControl(const QString &title, const QString &text, const QString &desc, QWidget *parent) : AbstractControl(title, desc, "", parent) {

View File

@@ -201,17 +201,53 @@ private:
bool store_confirm = false;
};
class ButtonParamControl : public AbstractControl {
class SPAbstractControl : public QFrame {
Q_OBJECT
public:
void setDescription(const QString &desc) {
if (description) description->setText(desc);
}
void setTitle(const QString &title) {
title_label->setText(title);
}
const QString getDescription() {
return description->text();
}
public slots:
void showDescription() {
description->setVisible(true);
}
signals:
void showDescriptionEvent();
protected:
SPAbstractControl(const QString &title, const QString &desc = "", const QString &icon = "", QWidget *parent = nullptr);
void hideEvent(QHideEvent *e) override;
QHBoxLayout *hlayout;
QPushButton *title_label;
private:
QLabel *description = nullptr;
};
class ButtonParamControl : public SPAbstractControl {
Q_OBJECT
public:
ButtonParamControl(const QString &param, const QString &title, const QString &desc, const QString &icon,
const std::vector<QString> &button_texts, const int minimum_button_width = 225) : AbstractControl(title, desc, icon) {
const std::vector<QString> &button_texts, const int minimum_button_width = 300) : SPAbstractControl(title, desc, icon) {
const QString style = R"(
QPushButton {
border-radius: 50px;
font-size: 40px;
font-weight: 500;
height:100px;
border: 0px;
border-radius: 0px;
font-size: 50px;
font-weight: 450;
height:125px;
padding: 0 25 0 25;
color: #E4E4E4;
background-color: #393939;
@@ -220,7 +256,7 @@ public:
background-color: #4a4a4a;
}
QPushButton:checked:enabled {
background-color: #1e79e8;
background-color: #696868;
}
QPushButton:disabled {
color: #33E4E4E4;
@@ -239,8 +275,13 @@ public:
button->setMinimumWidth(minimum_button_width);
hlayout->addWidget(button);
button_group->addButton(button, i);
if (i == 0) button->setStyleSheet(style + "QPushButton { border-top-left-radius: 15px; border-bottom-left-radius: 15px; }");
else if (i == button_texts.size() - 1) button->setStyleSheet(style + "QPushButton { border-top-right-radius: 15px; border-bottom-right-radius: 15px; }");
}
hlayout->setAlignment(Qt::AlignLeft);
QObject::connect(button_group, QOverload<int, bool>::of(&QButtonGroup::buttonToggled), [=](int id, bool checked) {
if (checked) {
params.put(key, std::to_string(id));

View File

@@ -232,7 +232,6 @@ void ui_update_params(UIState *s) {
s->scene.is_metric = params.getBool("IsMetric");
s->scene.map_on_left = params.getBool("NavSettingLeftSide");
s->scene.dynamic_lane_profile_toggle = params.getBool("DynamicLaneProfileToggle");
s->scene.visual_brake_lights = params.getBool("BrakeLights");
s->scene.onroadScreenOff = std::atoi(params.get("OnroadScreenOff").c_str());
s->scene.onroadScreenOffBrightness = std::atoi(params.get("OnroadScreenOffBrightness").c_str());
@@ -367,7 +366,6 @@ void UIState::updateStatus() {
}
if (sm->frame % UI_FREQ == 0) { // Update every 1 Hz
scene.sidebar_temp = params.getBool("SidebarTemperature");
scene.sidebar_temp_options = std::atoi(params.get("SidebarTemperatureOptions").c_str());
}
}

View File

@@ -194,7 +194,6 @@ typedef struct UIScene {
int dynamic_lane_profile;
bool dynamic_lane_profile_status = true;
bool dynamic_lane_profile_toggle;
bool visual_brake_lights;
@@ -229,7 +228,6 @@ typedef struct UIScene {
bool e2e_long_alert_light, e2e_long_alert_lead, e2e_long_alert_ui;
float e2eX[13] = {0};
bool sidebar_temp;
int sidebar_temp_options;
float mads_path_scale = DRIVING_PATH_WIDE - DRIVING_PATH_NARROW;