match nvg onroad alerts (#20854)

pull/20871/head
Adeeb Shihadeh 4 years ago committed by GitHub
parent 0a34900fec
commit e06f9828ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      selfdrive/ui/qt/home.cc
  2. 147
      selfdrive/ui/qt/onroad.cc
  3. 23
      selfdrive/ui/qt/onroad.h
  4. 16
      selfdrive/ui/qt/sidebar.cc
  5. 10
      selfdrive/ui/qt/util.h
  6. 2
      selfdrive/ui/ui.cc

@ -46,6 +46,7 @@ void HomeWindow::offroadTransition(bool offroad) {
slayout->setCurrentWidget(onroad);
}
sidebar->setVisible(offroad);
emit offroadTransitionSignal(offroad);
}
void HomeWindow::mousePressEvent(QMouseEvent* e) {

@ -5,7 +5,7 @@
#include "selfdrive/common/swaglog.h"
#include "selfdrive/common/timing.h"
#include "selfdrive/ui/paint.h"
#include "selfdrive/ui/qt/qt_window.h"
#include "selfdrive/ui/qt/util.h"
OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent) {
layout = new QStackedLayout();
@ -17,76 +17,44 @@ OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent) {
QObject::connect(this, &OnroadWindow::update, nvg, &NvgWindow::update);
alerts = new OnroadAlerts(this);
QObject::connect(this, &OnroadWindow::update, alerts, &OnroadAlerts::update);
QObject::connect(this, &OnroadWindow::update, alerts, &OnroadAlerts::updateState);
QObject::connect(this, &OnroadWindow::offroadTransition, alerts, &OnroadAlerts::offroadTransition);
layout->addWidget(alerts);
// hack to align the onroad alerts, better way to do this?
QVBoxLayout *alerts_container = new QVBoxLayout(this);
alerts_container->setMargin(0);
alerts_container->addStretch(1);
alerts_container->addWidget(alerts, 0, Qt::AlignBottom);
QWidget *w = new QWidget(this);
w->setLayout(alerts_container);
layout->addWidget(w);
// alerts on top
layout->setCurrentWidget(w);
// setup stacking order
alerts->raise();
setLayout(layout);
}
// ***** onroad widgets *****
OnroadAlerts::OnroadAlerts(QWidget *parent) : QFrame(parent) {
layout = new QVBoxLayout(this);
layout->setSpacing(40);
layout->setMargin(20);
title = new QLabel();
title->setWordWrap(true);
title->setAlignment(Qt::AlignCenter);
layout->addWidget(title);
msg = new QLabel();
msg->setWordWrap(true);
msg->setAlignment(Qt::AlignCenter);
layout->addWidget(msg);
layout->addStretch(1);
layout->insertStretch(0, 1);
setLayout(layout);
setStyleSheet("color: white;");
setVisible(false);
// setup sounds
OnroadAlerts::OnroadAlerts(QWidget *parent) : QWidget(parent) {
for (auto &kv : sound_map) {
auto path = QUrl::fromLocalFile(kv.second.first);
sounds[kv.first].setSource(path);
}
}
void OnroadAlerts::update(const UIState &s) {
void OnroadAlerts::updateState(const UIState &s) {
SubMaster &sm = *(s.sm);
if (sm.updated("carState")) {
// scale volume with speed
volume = util::map_val(sm["carState"].getCarState().getVEgo(), 0.f, 20.f,
Hardware::MIN_VOLUME, Hardware::MAX_VOLUME);
}
if (s.scene.deviceState.getStarted()) {
if (sm.updated("controlsState")) {
const cereal::ControlsState::Reader &cs = sm["controlsState"].getControlsState();
updateAlert(QString::fromStdString(cs.getAlertText1()), QString::fromStdString(cs.getAlertText2()),
cs.getAlertBlinkingRate(), cs.getAlertType(), cs.getAlertSize(), cs.getAlertSound());
} else {
} else if ((sm.frame - s.scene.started_frame) > 10 * UI_FREQ) {
// Handle controls timeout
if (s.scene.deviceState.getStarted() && (sm.frame - s.scene.started_frame) > 10 * UI_FREQ) {
const uint64_t cs_frame = sm.rcv_frame("controlsState");
if (cs_frame < s.scene.started_frame) {
if (sm.rcv_frame("controlsState") < s.scene.started_frame) {
// car is started, but controlsState hasn't been seen at all
updateAlert("openpilot Unavailable", "Waiting for controls to start", 0,
"controlsWaiting", cereal::ControlsState::AlertSize::MID, AudibleAlert::NONE);
} else if ((sm.frame - cs_frame) > 5 * UI_FREQ) {
} else if ((sm.frame - sm.rcv_frame("controlsState")) > 5 * UI_FREQ) {
// car is started, but controls is lagging or died
updateAlert("TAKE CONTROL IMMEDIATELY", "Controls Unresponsive", 0,
"controlsUnresponsive", cereal::ControlsState::AlertSize::FULL, AudibleAlert::CHIME_WARNING_REPEAT);
@ -97,23 +65,19 @@ void OnroadAlerts::update(const UIState &s) {
}
}
if (isVisible()) {
// TODO: add blinking back if performant
//float alpha = 0.375 * cos((millis_since_boot() / 1000) * 2 * M_PI * blinking_rate) + 0.625;
auto c = bg_colors[s.status];
float alpha = 0.375 * cos((millis_since_boot() / 1000) * 2 * M_PI * blinking_rate) + 0.625;
bg.setRgb(c.r*255, c.g*255, c.b*255, c.a*alpha*255);
}
bg.setRgbF(c.r, c.g, c.b, c.a);
}
void OnroadAlerts::offroadTransition(bool offroad) {
stopSounds();
setVisible(false);
alert_type = "";
updateAlert("", "", 0, "", cereal::ControlsState::AlertSize::NONE, AudibleAlert::NONE);
}
void OnroadAlerts::updateAlert(const QString &text1, const QString &text2, float blink_rate,
void OnroadAlerts::updateAlert(const QString &t1, const QString &t2, float blink_rate,
const std::string &type, cereal::ControlsState::AlertSize size, AudibleAlert sound) {
if (alert_type.compare(type) == 0) {
if (alert_type.compare(type) == 0 && text1.compare(t1) == 0) {
return;
}
@ -122,28 +86,13 @@ void OnroadAlerts::updateAlert(const QString &text1, const QString &text2, float
playSound(sound);
}
text1 = t1;
text2 = t2;
alert_type = type;
alert_size = size;
blinking_rate = blink_rate;
title->setText(text1);
msg->setText(text2);
msg->setVisible(!msg->text().isEmpty());
if (size == cereal::ControlsState::AlertSize::SMALL) {
setFixedHeight(241);
title->setStyleSheet("font-size: 70px; font-weight: 500;");
} else if (size == cereal::ControlsState::AlertSize::MID) {
setFixedHeight(390);
msg->setStyleSheet("font-size: 65px; font-weight: 400;");
title->setStyleSheet("font-size: 80px; font-weight: 500;");
} else if (size == cereal::ControlsState::AlertSize::FULL) {
setFixedHeight(vwp_h);
int title_size = (title->text().size() > 15) ? 130 : 110;
title->setStyleSheet(QString("font-size: %1px; font-weight: 500;").arg(title_size));
msg->setStyleSheet("font-size: 90px; font-weight: 400;");
}
setVisible(size != cereal::ControlsState::AlertSize::NONE);
repaint();
update();
}
void OnroadAlerts::playSound(AudibleAlert alert) {
@ -164,9 +113,57 @@ void OnroadAlerts::stopSounds() {
void OnroadAlerts::paintEvent(QPaintEvent *event) {
QPainter p(this);
p.setBrush(QBrush(bg));
static std::map<cereal::ControlsState::AlertSize, const int> alert_sizes = {
{cereal::ControlsState::AlertSize::NONE, 0},
{cereal::ControlsState::AlertSize::SMALL, 271},
{cereal::ControlsState::AlertSize::MID, 420},
{cereal::ControlsState::AlertSize::FULL, height()},
};
int h = alert_sizes[alert_size];
if (h == 0) {
return;
}
QRect r = QRect(0, height() - h, width(), h);
// draw background + gradient
p.setPen(Qt::NoPen);
p.drawRect(rect());
p.setCompositionMode(QPainter::CompositionMode_DestinationOver);
p.setBrush(QBrush(bg));
p.drawRect(r);
QLinearGradient g(0, r.y(), 0, r.bottom());
g.setColorAt(0, QColor::fromRgbF(0, 0, 0, 0.05));
g.setColorAt(1, QColor::fromRgbF(0, 0, 0, 0.35));
p.setBrush(QBrush(g));
p.fillRect(r, g);
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
// remove bottom border
r = QRect(0, height() - h, width(), h - 30);
// text
const QPoint c = r.center();
p.setPen(QColor(0xff, 0xff, 0xff));
p.setRenderHint(QPainter::TextAntialiasing);
if (alert_size == cereal::ControlsState::AlertSize::SMALL) {
configFont(p, "Open Sans", 74, "SemiBold");
p.drawText(r, Qt::AlignCenter, text1);
} else if (alert_size == cereal::ControlsState::AlertSize::MID) {
configFont(p, "Open Sans", 88, "Bold");
p.drawText(QRect(0, c.y() - 125, width(), 150), Qt::AlignHCenter | Qt::AlignTop, text1);
configFont(p, "Open Sans", 66, "Regular");
p.drawText(QRect(0, c.y() + 21, width(), 90), Qt::AlignHCenter, text2);
} else if (alert_size == cereal::ControlsState::AlertSize::FULL) {
// TODO: offset from center to match old NVG UI, but why was it this way?
bool l = text1.length() > 15;
configFont(p, "Open Sans", l ? 132 : 177, "Bold");
p.drawText(QRect(0, r.y() + (l ? 240 : 270), width() - 60, 350), Qt::AlignHCenter | Qt::TextWordWrap, text1);
configFont(p, "Open Sans", 88, "Regular");
p.drawText(QRect(0, r.height() - (l ? 361 : 420), width() - 60, 300), Qt::AlignHCenter | Qt::TextWordWrap, text2);
}
}
NvgWindow::~NvgWindow() {

@ -8,12 +8,13 @@
#include "cereal/gen/cpp/log.capnp.h"
#include "selfdrive/hardware/hw.h"
#include "selfdrive/ui/ui.h"
#include "selfdrive/ui/qt/qt_window.h"
typedef cereal::CarControl::HUDControl::AudibleAlert AudibleAlert;
// ***** onroad widgets *****
class OnroadAlerts : public QFrame {
class OnroadAlerts : public QWidget {
Q_OBJECT
public:
@ -23,14 +24,11 @@ protected:
void paintEvent(QPaintEvent*) override;
private:
QColor bg;
QLabel *title, *msg;
QVBoxLayout *layout;
void updateAlert(const QString &text1, const QString &text2, float blink_rate,
void stopSounds();
void playSound(AudibleAlert alert);
void updateAlert(const QString &t1, const QString &t2, float blink_rate,
const std::string &type, cereal::ControlsState::AlertSize size, AudibleAlert sound);
// sounds
std::map<AudibleAlert, std::pair<QString, bool>> sound_map {
// AudibleAlert, (file path, inf loop)
{AudibleAlert::CHIME_DISENGAGE, {"../assets/sounds/disengaged.wav", false}},
@ -42,16 +40,17 @@ private:
{AudibleAlert::CHIME_ERROR, {"../assets/sounds/error.wav", false}},
{AudibleAlert::CHIME_PROMPT, {"../assets/sounds/error.wav", false}}
};
QColor bg;
float volume = Hardware::MIN_VOLUME;
std::map<AudibleAlert, QSoundEffect> sounds;
float blinking_rate = 0;
QString text1, text2;
std::string alert_type;
std::map<AudibleAlert, QSoundEffect> sounds;
void playSound(AudibleAlert alert);
void stopSounds();
cereal::ControlsState::AlertSize alert_size;
public slots:
void update(const UIState &s);
void updateState(const UIState &s);
void offroadTransition(bool offroad);
};

@ -3,13 +3,7 @@
#include "selfdrive/ui/qt/qt_window.h"
#include "selfdrive/common/util.h"
#include "selfdrive/hardware/hw.h"
void configFont(QPainter &p, QString family, int size, int weight) {
QFont f(family);
f.setPixelSize(size);
f.setWeight(weight);
p.setFont(f);
}
#include "selfdrive/ui/qt/util.h"
void Sidebar::drawMetric(QPainter &p, const QString &label, const QString &val, QColor c, int y) {
const QRect rect = {30, y, 240, val.isEmpty() ? (label.contains("\n") ? 124 : 100) : 148};
@ -28,13 +22,13 @@ void Sidebar::drawMetric(QPainter &p, const QString &label, const QString &val,
p.setPen(QColor(0xff, 0xff, 0xff));
if (val.isEmpty()) {
configFont(p, "Open Sans", 35, 500);
configFont(p, "Open Sans", 35, "Bold");
const QRect r = QRect(rect.x() + 35, rect.y(), rect.width() - 50, rect.height());
p.drawText(r, Qt::AlignCenter, label);
} else {
configFont(p, "Open Sans", 58, 500);
configFont(p, "Open Sans", 58, "Bold");
p.drawText(rect.x() + 50, rect.y() + 71, val);
configFont(p, "Open Sans", 35, 400);
configFont(p, "Open Sans", 35, "Regular");
p.drawText(rect.x() + 50, rect.y() + 50 + 77, label);
}
}
@ -107,7 +101,7 @@ void Sidebar::paintEvent(QPaintEvent *event) {
// network
p.drawImage(58, 196, signal_imgs[strength]);
configFont(p, "Open Sans", 35, 400);
configFont(p, "Open Sans", 35, "Regular");
p.setPen(QColor(0xff, 0xff, 0xff));
const QRect r = QRect(50, 247, 100, 50);
p.drawText(r, Qt::AlignCenter, network_type[net_type]);

@ -0,0 +1,10 @@
#pragma once
#include <QtWidgets>
inline void configFont(QPainter &p, QString family, int size, const QString &style) {
QFont f(family);
f.setPixelSize(size);
f.setStyleName(style);
p.setFont(f);
}

@ -305,7 +305,7 @@ void QUIState::update() {
update_status(&ui_state);
update_vision(&ui_state);
if (ui_state.scene.started != started_prev) {
if (ui_state.scene.started != started_prev || ui_state.sm->frame == 1) {
started_prev = ui_state.scene.started;
emit offroadTransition(!ui_state.scene.started);

Loading…
Cancel
Save