Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ui: tap experimental mode icon to toggle #27064

Merged
merged 4 commits into from
Feb 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 59 additions & 13 deletions selfdrive/ui/qt/onroad.cc
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,62 @@ void OnroadAlerts::paintEvent(QPaintEvent *event) {
}


ExperimentalButton::ExperimentalButton(QWidget *parent) : QPushButton(parent) {
setVisible(false);
setFixedSize(btn_size, btn_size);
setCheckable(true);

params = Params();
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::toggled, [=](bool checked) {
params.putBool("ExperimentalMode", checked);
});
}

void ExperimentalButton::updateState(const UIState &s) {
const SubMaster &sm = *(s.sm);

// button is "visible" if engageable or enabled
const auto cs = sm["controlsState"].getControlsState();
setVisible(cs.getEngageable() || cs.getEnabled());

// button is "checked" if experimental mode is enabled
setChecked(sm["controlsState"].getControlsState().getExperimentalMode());

// disable button when experimental mode is not available, or has not been confirmed for the first time
const auto cp = sm["carParams"].getCarParams();
const bool experimental_mode_available = cp.getExperimentalLongitudinalAvailable() ? params.getBool("ExperimentalLongitudinalEnabled") : cp.getOpenpilotLongitudinalControl();
setEnabled(params.getBool("ExperimentalModeConfirmed") && experimental_mode_available);
}

void ExperimentalButton::paintEvent(QPaintEvent *event) {
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);

QPoint center(btn_size / 2, btn_size / 2);
QPixmap img = isChecked() ? experimental_img : engage_img;

p.setOpacity(1.0);
p.setPen(Qt::NoPen);
p.setBrush(QColor(0, 0, 0, 166));
p.drawEllipse(center, btn_size / 2, btn_size / 2);
p.setOpacity(isDown() ? 0.8 : 1.0);
p.drawPixmap((btn_size - img_size) / 2, (btn_size - img_size) / 2, img);
}


AnnotatedCameraWidget::AnnotatedCameraWidget(VisionStreamType type, QWidget* parent) : fps_filter(UI_FREQ, 3, 1. / UI_FREQ), CameraWidget("camerad", type, true, parent) {
pm = std::make_unique<PubMaster, const std::initializer_list<const char *>>({"uiDebug"});

engage_img = loadPixmap("../assets/img_chffr_wheel.png", {img_size, img_size});
experimental_img = loadPixmap("../assets/img_experimental.svg", {img_size - 5, img_size - 5});
QVBoxLayout *main_layout = new QVBoxLayout(this);
main_layout->setMargin(bdr_s);
main_layout->setSpacing(0);

experimental_btn = new ExperimentalButton(this);
main_layout->addWidget(experimental_btn, 0, Qt::AlignTop | Qt::AlignRight);

dm_img = loadPixmap("../assets/img_driver_face.png", {img_size, img_size});
}

Expand Down Expand Up @@ -227,9 +278,11 @@ void AnnotatedCameraWidget::updateState(const UIState &s) {
setProperty("hideDM", cs.getAlertSize() != cereal::ControlsState::AlertSize::NONE);
setProperty("status", s.status);

// update engageability and DM icons at 2Hz
// update engageability/experimental mode button
experimental_btn->updateState(s);

// update DM icons at 2Hz
if (sm.frame % (UI_FREQ / 2) == 0) {
setProperty("engageable", cs.getEngageable() || cs.getEnabled());
setProperty("dmActive", sm["driverMonitoringState"].getDriverMonitoringState().getIsActiveMode());
setProperty("rightHandDM", sm["driverMonitoringState"].getDriverMonitoringState().getIsRHD());
}
Expand Down Expand Up @@ -382,16 +435,9 @@ void AnnotatedCameraWidget::drawHud(QPainter &p) {
configFont(p, "Inter", 66, "Regular");
drawText(p, rect().center().x(), 290, speedUnit, 200);

// engage-ability icon
if (engageable) {
SubMaster &sm = *(uiState()->sm);
drawIcon(p, rect().right() - radius / 2 - bdr_s * 2, radius / 2 + int(bdr_s * 1.5),
sm["controlsState"].getControlsState().getExperimentalMode() ? experimental_img : engage_img, blackColor(166), 1.0);
}

// dm icon
if (!hideDM) {
int dm_icon_x = rightHandDM ? rect().right() - radius / 2 - (bdr_s * 2) : radius / 2 + (bdr_s * 2);
int dm_icon_x = rightHandDM ? rect().right() - btn_size / 2 - (bdr_s * 2) : btn_size / 2 + (bdr_s * 2);
drawIcon(p, dm_icon_x, rect().bottom() - footer_h / 2,
dm_img, blackColor(70), dmActive ? 1.0 : 0.2);
}
Expand All @@ -414,7 +460,7 @@ void AnnotatedCameraWidget::drawIcon(QPainter &p, int x, int y, QPixmap &img, QB
p.setOpacity(1.0); // bg dictates opacity of ellipse
p.setPen(Qt::NoPen);
p.setBrush(bg);
p.drawEllipse(x - radius / 2, y - radius / 2, radius, radius);
p.drawEllipse(x - btn_size / 2, y - btn_size / 2, btn_size, btn_size);
p.setOpacity(opacity);
p.drawPixmap(x - img.size().width() / 2, y - img.size().height() / 2, img);
}
Expand Down
29 changes: 22 additions & 7 deletions selfdrive/ui/qt/onroad.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
#pragma once

#include <QPushButton>
#include <QStackedLayout>
#include <QWidget>

#include "common/util.h"
#include "selfdrive/ui/qt/widgets/cameraview.h"
#include "selfdrive/ui/ui.h"
#include "selfdrive/ui/qt/widgets/cameraview.h"


const int btn_size = 192;
const int img_size = (btn_size / 4) * 3;


// ***** onroad widgets *****
Expand All @@ -24,6 +29,21 @@ class OnroadAlerts : public QWidget {
Alert alert = {};
};

class ExperimentalButton : public QPushButton {
Q_OBJECT

public:
explicit ExperimentalButton(QWidget *parent = 0);
void updateState(const UIState &s);

private:
void paintEvent(QPaintEvent *event) override;

Params params;
QPixmap engage_img;
QPixmap experimental_img;
};

// container window for the NVG UI
class AnnotatedCameraWidget : public CameraWidget {
Q_OBJECT
Expand All @@ -36,7 +56,6 @@ class AnnotatedCameraWidget : public CameraWidget {
Q_PROPERTY(bool has_us_speed_limit MEMBER has_us_speed_limit);
Q_PROPERTY(bool is_metric MEMBER is_metric);

Q_PROPERTY(bool engageable MEMBER engageable);
Q_PROPERTY(bool dmActive MEMBER dmActive);
Q_PROPERTY(bool hideDM MEMBER hideDM);
Q_PROPERTY(bool rightHandDM MEMBER rightHandDM);
Expand All @@ -50,18 +69,14 @@ class AnnotatedCameraWidget : public CameraWidget {
void drawIcon(QPainter &p, int x, int y, QPixmap &img, QBrush bg, float opacity);
void drawText(QPainter &p, int x, int y, const QString &text, int alpha = 255);

QPixmap engage_img;
QPixmap experimental_img;
ExperimentalButton *experimental_btn;
QPixmap dm_img;
const int radius = 192;
const int img_size = (radius / 2) * 1.5;
float speed;
QString speedUnit;
float setSpeed;
float speedLimit;
bool is_cruise_set = false;
bool is_metric = false;
bool engageable = false;
bool dmActive = false;
bool hideDM = false;
bool rightHandDM = false;
Expand Down