ui: refactor hud updating and rendering into HudRenderer class (#33458)

refactor hud updating and rendering into DriverMonitorRenderer class
pull/33631/head
Dean Lee 7 months ago committed by GitHub
parent 900c2c83bd
commit caa33c3193
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      selfdrive/ui/SConscript
  2. 92
      selfdrive/ui/qt/onroad/annotated_camera.cc
  3. 15
      selfdrive/ui/qt/onroad/annotated_camera.h
  4. 109
      selfdrive/ui/qt/onroad/hud.cc
  5. 23
      selfdrive/ui/qt/onroad/hud.h
  6. 30
      selfdrive/ui/translations/main_ar.ts
  7. 30
      selfdrive/ui/translations/main_de.ts
  8. 30
      selfdrive/ui/translations/main_es.ts
  9. 30
      selfdrive/ui/translations/main_fr.ts
  10. 30
      selfdrive/ui/translations/main_ja.ts
  11. 30
      selfdrive/ui/translations/main_ko.ts
  12. 30
      selfdrive/ui/translations/main_pt-BR.ts
  13. 30
      selfdrive/ui/translations/main_th.ts
  14. 30
      selfdrive/ui/translations/main_tr.ts
  15. 30
      selfdrive/ui/translations/main_zh-CHS.ts
  16. 30
      selfdrive/ui/translations/main_zh-CHT.ts

@ -31,7 +31,7 @@ qt_src = ["main.cc", "ui.cc", "qt/sidebar.cc", "qt/body.cc",
"qt/offroad/software_settings.cc", "qt/offroad/onboarding.cc",
"qt/offroad/driverview.cc", "qt/offroad/experimental_mode.cc",
"qt/onroad/onroad_home.cc", "qt/onroad/annotated_camera.cc",
"qt/onroad/buttons.cc", "qt/onroad/alerts.cc", "qt/onroad/driver_monitoring.cc"]
"qt/onroad/buttons.cc", "qt/onroad/alerts.cc", "qt/onroad/driver_monitoring.cc", "qt/onroad/hud.cc"]
# build translation files
with open(File("translations/languages.json").abspath) as f:

@ -6,7 +6,6 @@
#include <cmath>
#include "common/swaglog.h"
#include "selfdrive/ui/qt/onroad/buttons.h"
#include "selfdrive/ui/qt/util.h"
// Window that shows camera view and variety of info drawn on top
@ -23,98 +22,11 @@ AnnotatedCameraWidget::AnnotatedCameraWidget(VisionStreamType type, QWidget *par
}
void AnnotatedCameraWidget::updateState(const UIState &s) {
const int SET_SPEED_NA = 255;
const SubMaster &sm = *(s.sm);
const bool cs_alive = sm.alive("carState");
const auto cs = sm["controlsState"].getControlsState();
const auto car_state = sm["carState"].getCarState();
is_metric = s.scene.is_metric;
// Handle older routes where vCruise was in controlsState
float v_cruise = car_state.getVCruiseCluster() == 0.0 ? cs.getVCruiseDEPRECATED() : car_state.getVCruiseCluster();
setSpeed = cs_alive ? v_cruise : SET_SPEED_NA;
is_cruise_set = setSpeed > 0 && (int)setSpeed != SET_SPEED_NA;
if (is_cruise_set && !is_metric) {
setSpeed *= KM_TO_MILE;
}
// Handle older routes where vEgoCluster is not set
v_ego_cluster_seen = v_ego_cluster_seen || car_state.getVEgoCluster() != 0.0;
float v_ego = v_ego_cluster_seen ? car_state.getVEgoCluster() : car_state.getVEgo();
speed = cs_alive ? std::max<float>(0.0, v_ego) : 0.0;
speed *= is_metric ? MS_TO_KPH : MS_TO_MPH;
speedUnit = is_metric ? tr("km/h") : tr("mph");
status = s.status;
// update engageability/experimental mode button
experimental_btn->updateState(s);
// update DM icon
dmon.updateState(s);
}
void AnnotatedCameraWidget::drawHud(QPainter &p) {
p.save();
// Header gradient
QLinearGradient bg(0, UI_HEADER_HEIGHT - (UI_HEADER_HEIGHT / 2.5), 0, UI_HEADER_HEIGHT);
bg.setColorAt(0, QColor::fromRgbF(0, 0, 0, 0.45));
bg.setColorAt(1, QColor::fromRgbF(0, 0, 0, 0));
p.fillRect(0, 0, width(), UI_HEADER_HEIGHT, bg);
QString speedStr = QString::number(std::nearbyint(speed));
QString setSpeedStr = is_cruise_set ? QString::number(std::nearbyint(setSpeed)) : "";
// Draw outer box + border to contain set speed
const QSize default_size = {172, 204};
QSize set_speed_size = default_size;
if (is_metric) set_speed_size.rwidth() = 200;
QRect set_speed_rect(QPoint(60 + (default_size.width() - set_speed_size.width()) / 2, 45), set_speed_size);
p.setPen(QPen(whiteColor(75), 6));
p.setBrush(blackColor(166));
p.drawRoundedRect(set_speed_rect, 32, 32);
// Draw MAX
QColor max_color = QColor(0x80, 0xd8, 0xa6, 0xff);
QColor set_speed_color = whiteColor();
if (is_cruise_set) {
if (status == STATUS_DISENGAGED) {
max_color = whiteColor();
} else if (status == STATUS_OVERRIDE) {
max_color = QColor(0x91, 0x9b, 0x95, 0xff);
}
} else {
max_color = QColor(0xa6, 0xa6, 0xa6, 0xff);
set_speed_color = QColor(0x72, 0x72, 0x72, 0xff);
}
p.setFont(InterFont(40, QFont::DemiBold));
p.setPen(max_color);
p.drawText(set_speed_rect.adjusted(0, 27, 0, 0), Qt::AlignTop | Qt::AlignHCenter, tr("MAX"));
p.setFont(InterFont(90, QFont::Bold));
p.setPen(set_speed_color);
p.drawText(set_speed_rect.adjusted(0, 77, 0, 0), Qt::AlignTop | Qt::AlignHCenter, setSpeedStr);
// current speed
p.setFont(InterFont(176, QFont::Bold));
drawText(p, rect().center().x(), 210, speedStr);
p.setFont(InterFont(66));
drawText(p, rect().center().x(), 290, speedUnit, 200);
p.restore();
}
void AnnotatedCameraWidget::drawText(QPainter &p, int x, int y, const QString &text, int alpha) {
QRect real_rect = p.fontMetrics().boundingRect(text);
real_rect.moveCenter({x, y - real_rect.height() / 2});
p.setPen(QColor(0xff, 0xff, 0xff, alpha));
p.drawText(real_rect.x(), real_rect.bottom(), text);
}
void AnnotatedCameraWidget::initializeGL() {
CameraWidget::initializeGL();
qInfo() << "OpenGL version:" << QString((const char*)glGetString(GL_VERSION));
@ -333,8 +245,8 @@ void AnnotatedCameraWidget::paintGL() {
}
dmon.draw(painter, rect());
drawHud(painter);
hud.updateState(*s);
hud.draw(painter, rect());
double cur_draw_t = millis_since_boot();
double dt = cur_draw_t - prev_draw_t;

@ -2,7 +2,7 @@
#include <QVBoxLayout>
#include <memory>
#include "selfdrive/ui/qt/onroad/hud.h"
#include "selfdrive/ui/qt/onroad/buttons.h"
#include "selfdrive/ui/qt/onroad/driver_monitoring.h"
#include "selfdrive/ui/qt/widgets/cameraview.h"
@ -15,18 +15,10 @@ public:
void updateState(const UIState &s);
private:
void drawText(QPainter &p, int x, int y, const QString &text, int alpha = 255);
QVBoxLayout *main_layout;
ExperimentalButton *experimental_btn;
DriverMonitorRenderer dmon;
float speed;
QString speedUnit;
float setSpeed;
bool is_cruise_set = false;
bool is_metric = false;
bool v_ego_cluster_seen = false;
int status = STATUS_DISENGAGED;
HudRenderer hud;
std::unique_ptr<PubMaster> pm;
int skip_frame_count = 0;
@ -39,10 +31,7 @@ protected:
mat4 calcFrameMatrix() override;
void drawLaneLines(QPainter &painter, const UIState *s);
void drawLead(QPainter &painter, const cereal::RadarState::LeadData::Reader &lead_data, const QPointF &vd);
void drawHud(QPainter &p);
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); }
double prev_draw_t = 0;
FirstOrderFilter fps_filter;

@ -0,0 +1,109 @@
#include "selfdrive/ui/qt/onroad/hud.h"
#include <cmath>
#include "selfdrive/ui/qt/util.h"
constexpr int SET_SPEED_NA = 255;
HudRenderer::HudRenderer() {}
void HudRenderer::updateState(const UIState &s) {
is_metric = s.scene.is_metric;
status = s.status;
const SubMaster &sm = *(s.sm);
if (!sm.alive("carState")) {
is_cruise_set = false;
set_speed = SET_SPEED_NA;
speed = 0.0;
return;
}
const auto &controls_state = sm["controlsState"].getControlsState();
const auto &car_state = sm["carState"].getCarState();
// Handle older routes where vCruiseCluster is not set
set_speed = car_state.getVCruiseCluster() == 0.0 ? controls_state.getVCruiseDEPRECATED() : car_state.getVCruiseCluster();
is_cruise_set = set_speed > 0 && set_speed != SET_SPEED_NA;
if (is_cruise_set && !is_metric) {
set_speed *= KM_TO_MILE;
}
// Handle older routes where vEgoCluster is not set
v_ego_cluster_seen = v_ego_cluster_seen || car_state.getVEgoCluster() != 0.0;
float v_ego = v_ego_cluster_seen ? car_state.getVEgoCluster() : car_state.getVEgo();
speed = std::max<float>(0.0f, v_ego * (is_metric ? MS_TO_KPH : MS_TO_MPH));
}
void HudRenderer::draw(QPainter &p, const QRect &surface_rect) {
p.save();
// Draw header gradient
QLinearGradient bg(0, UI_HEADER_HEIGHT - (UI_HEADER_HEIGHT / 2.5), 0, UI_HEADER_HEIGHT);
bg.setColorAt(0, QColor::fromRgbF(0, 0, 0, 0.45));
bg.setColorAt(1, QColor::fromRgbF(0, 0, 0, 0));
p.fillRect(0, 0, surface_rect.width(), UI_HEADER_HEIGHT, bg);
drawSetSpeed(p, surface_rect);
drawCurrentSpeed(p, surface_rect);
p.restore();
}
void HudRenderer::drawSetSpeed(QPainter &p, const QRect &surface_rect) {
// Draw outer box + border to contain set speed
const QSize default_size = {172, 204};
QSize set_speed_size = is_metric ? QSize(200, 204) : default_size;
QRect set_speed_rect(QPoint(60 + (default_size.width() - set_speed_size.width()) / 2, 45), set_speed_size);
// Draw set speed box
p.setPen(QPen(QColor(255, 255, 255, 75), 6));
p.setBrush(QColor(0, 0, 0, 166));
p.drawRoundedRect(set_speed_rect, 32, 32);
// Colors based on status
QColor max_color = QColor(0xa6, 0xa6, 0xa6, 0xff);
QColor set_speed_color = QColor(0x72, 0x72, 0x72, 0xff);
if (is_cruise_set) {
if (status == STATUS_DISENGAGED) {
max_color = QColor(255, 255, 255);
} else if (status == STATUS_OVERRIDE) {
max_color = QColor(0x91, 0x9b, 0x95, 0xff);
} else {
max_color = QColor(0x80, 0xd8, 0xa6, 0xff);
set_speed_color = QColor(255, 255, 255);
}
}
// Draw "MAX" text
p.setFont(InterFont(40, QFont::DemiBold));
p.setPen(max_color);
p.drawText(set_speed_rect.adjusted(0, 27, 0, 0), Qt::AlignTop | Qt::AlignHCenter, tr("MAX"));
// Draw set speed
QString setSpeedStr = is_cruise_set ? QString::number(std::nearbyint(set_speed)) : "";
p.setFont(InterFont(90, QFont::Bold));
p.setPen(set_speed_color);
p.drawText(set_speed_rect.adjusted(0, 77, 0, 0), Qt::AlignTop | Qt::AlignHCenter, setSpeedStr);
}
void HudRenderer::drawCurrentSpeed(QPainter &p, const QRect &surface_rect) {
QString speedStr = QString::number(std::nearbyint(speed));
p.setFont(InterFont(176, QFont::Bold));
drawText(p, surface_rect.center().x(), 210, speedStr);
p.setFont(InterFont(66));
drawText(p, surface_rect.center().x(), 290, is_metric ? tr("km/h") : tr("mph"), 200);
}
void HudRenderer::drawText(QPainter &p, int x, int y, const QString &text, int alpha) {
QRect real_rect = p.fontMetrics().boundingRect(text);
real_rect.moveCenter({x, y - real_rect.height() / 2});
p.setPen(QColor(0xff, 0xff, 0xff, alpha));
p.drawText(real_rect.x(), real_rect.bottom(), text);
}

@ -0,0 +1,23 @@
#pragma once
#include <QPainter>
#include "selfdrive/ui/ui.h"
class HudRenderer : public QObject {
public:
HudRenderer();
void updateState(const UIState &s);
void draw(QPainter &p, const QRect &surface_rect);
private:
void drawSetSpeed(QPainter &p, const QRect &surface_rect);
void drawCurrentSpeed(QPainter &p, const QRect &surface_rect);
void drawText(QPainter &p, int x, int y, const QString &text, int alpha = 255);
float speed = 0;
float set_speed = 0;
bool is_cruise_set = false;
bool is_metric = false;
bool v_ego_cluster_seen = false;
int status = STATUS_DISENGAGED;
};

@ -87,21 +87,6 @@
<translation>من أجل &quot;%1&quot;</translation>
</message>
</context>
<context>
<name>AnnotatedCameraWidget</name>
<message>
<source>km/h</source>
<translation>كم/س</translation>
</message>
<message>
<source>mph</source>
<translation>ميل/س</translation>
</message>
<message>
<source>MAX</source>
<translation>MAX</translation>
</message>
</context>
<context>
<name>ConfirmationDialog</name>
<message>
@ -289,6 +274,21 @@
<translation>تشغيل وضع الراحة</translation>
</message>
</context>
<context>
<name>HudRenderer</name>
<message>
<source>km/h</source>
<translation>كم/س</translation>
</message>
<message>
<source>mph</source>
<translation>ميل/س</translation>
</message>
<message>
<source>MAX</source>
<translation>MAX</translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>

@ -87,21 +87,6 @@
<translation type="unfinished">für &quot;%1&quot;</translation>
</message>
</context>
<context>
<name>AnnotatedCameraWidget</name>
<message>
<source>km/h</source>
<translation>km/h</translation>
</message>
<message>
<source>mph</source>
<translation>mph</translation>
</message>
<message>
<source>MAX</source>
<translation>MAX</translation>
</message>
</context>
<context>
<name>ConfirmationDialog</name>
<message>
@ -289,6 +274,21 @@
<translation>ENTSPANNTER MODUS AN</translation>
</message>
</context>
<context>
<name>HudRenderer</name>
<message>
<source>km/h</source>
<translation>km/h</translation>
</message>
<message>
<source>mph</source>
<translation>mph</translation>
</message>
<message>
<source>MAX</source>
<translation>MAX</translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>

@ -87,21 +87,6 @@
<translation>para &quot;%1&quot;</translation>
</message>
</context>
<context>
<name>AnnotatedCameraWidget</name>
<message>
<source>km/h</source>
<translation>km/h</translation>
</message>
<message>
<source>mph</source>
<translation>mph</translation>
</message>
<message>
<source>MAX</source>
<translation>MAX</translation>
</message>
</context>
<context>
<name>ConfirmationDialog</name>
<message>
@ -289,6 +274,21 @@
<translation>MODO CHILL</translation>
</message>
</context>
<context>
<name>HudRenderer</name>
<message>
<source>km/h</source>
<translation>km/h</translation>
</message>
<message>
<source>mph</source>
<translation>mph</translation>
</message>
<message>
<source>MAX</source>
<translation>MAX</translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>

@ -87,21 +87,6 @@
<translation>pour &quot;%1&quot;</translation>
</message>
</context>
<context>
<name>AnnotatedCameraWidget</name>
<message>
<source>km/h</source>
<translation>km/h</translation>
</message>
<message>
<source>mph</source>
<translation>mi/h</translation>
</message>
<message>
<source>MAX</source>
<translation>MAX</translation>
</message>
</context>
<context>
<name>ConfirmationDialog</name>
<message>
@ -289,6 +274,21 @@
<translation>MODE DÉTENTE ACTIVÉ</translation>
</message>
</context>
<context>
<name>HudRenderer</name>
<message>
<source>km/h</source>
<translation>km/h</translation>
</message>
<message>
<source>mph</source>
<translation>mi/h</translation>
</message>
<message>
<source>MAX</source>
<translation>MAX</translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>

@ -87,21 +87,6 @@
<translation type="unfinished">%1</translation>
</message>
</context>
<context>
<name>AnnotatedCameraWidget</name>
<message>
<source>km/h</source>
<translation>km/h</translation>
</message>
<message>
<source>mph</source>
<translation>mph</translation>
</message>
<message>
<source>MAX</source>
<translation></translation>
</message>
</context>
<context>
<name>ConfirmationDialog</name>
<message>
@ -289,6 +274,21 @@
<translation></translation>
</message>
</context>
<context>
<name>HudRenderer</name>
<message>
<source>km/h</source>
<translation>km/h</translation>
</message>
<message>
<source>mph</source>
<translation>mph</translation>
</message>
<message>
<source>MAX</source>
<translation></translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>

@ -87,21 +87,6 @@
<translation>&quot;%1&quot; </translation>
</message>
</context>
<context>
<name>AnnotatedCameraWidget</name>
<message>
<source>km/h</source>
<translation>km/h</translation>
</message>
<message>
<source>mph</source>
<translation>mph</translation>
</message>
<message>
<source>MAX</source>
<translation>MAX</translation>
</message>
</context>
<context>
<name>ConfirmationDialog</name>
<message>
@ -289,6 +274,21 @@
<translation> </translation>
</message>
</context>
<context>
<name>HudRenderer</name>
<message>
<source>km/h</source>
<translation>km/h</translation>
</message>
<message>
<source>mph</source>
<translation>mph</translation>
</message>
<message>
<source>MAX</source>
<translation>MAX</translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>

@ -87,21 +87,6 @@
<translation>para &quot;%1&quot;</translation>
</message>
</context>
<context>
<name>AnnotatedCameraWidget</name>
<message>
<source>km/h</source>
<translation>km/h</translation>
</message>
<message>
<source>mph</source>
<translation>mph</translation>
</message>
<message>
<source>MAX</source>
<translation>LIMITE</translation>
</message>
</context>
<context>
<name>ConfirmationDialog</name>
<message>
@ -289,6 +274,21 @@
<translation>MODO CHILL ON</translation>
</message>
</context>
<context>
<name>HudRenderer</name>
<message>
<source>km/h</source>
<translation>km/h</translation>
</message>
<message>
<source>mph</source>
<translation>mph</translation>
</message>
<message>
<source>MAX</source>
<translation>LIMITE</translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>

@ -87,21 +87,6 @@
<translation> &quot;%1&quot;</translation>
</message>
</context>
<context>
<name>AnnotatedCameraWidget</name>
<message>
<source>km/h</source>
<translation>./.</translation>
</message>
<message>
<source>mph</source>
<translation>/.</translation>
</message>
<message>
<source>MAX</source>
<translation></translation>
</message>
</context>
<context>
<name>ConfirmationDialog</name>
<message>
@ -289,6 +274,21 @@
<translation></translation>
</message>
</context>
<context>
<name>HudRenderer</name>
<message>
<source>km/h</source>
<translation>./.</translation>
</message>
<message>
<source>mph</source>
<translation>/.</translation>
</message>
<message>
<source>MAX</source>
<translation></translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>

@ -87,21 +87,6 @@
<translation type="unfinished">için &quot;%1&quot;</translation>
</message>
</context>
<context>
<name>AnnotatedCameraWidget</name>
<message>
<source>km/h</source>
<translation type="unfinished">km/h</translation>
</message>
<message>
<source>mph</source>
<translation type="unfinished">mph</translation>
</message>
<message>
<source>MAX</source>
<translation type="unfinished">MAX</translation>
</message>
</context>
<context>
<name>ConfirmationDialog</name>
<message>
@ -289,6 +274,21 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>HudRenderer</name>
<message>
<source>km/h</source>
<translation>km/h</translation>
</message>
<message>
<source>mph</source>
<translation>mph</translation>
</message>
<message>
<source>MAX</source>
<translation>MAX</translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>

@ -87,21 +87,6 @@
<translation>&quot;%1&quot;</translation>
</message>
</context>
<context>
<name>AnnotatedCameraWidget</name>
<message>
<source>km/h</source>
<translation>km/h</translation>
</message>
<message>
<source>mph</source>
<translation>mph</translation>
</message>
<message>
<source>MAX</source>
<translation></translation>
</message>
</context>
<context>
<name>ConfirmationDialog</name>
<message>
@ -289,6 +274,21 @@
<translation></translation>
</message>
</context>
<context>
<name>HudRenderer</name>
<message>
<source>km/h</source>
<translation>km/h</translation>
</message>
<message>
<source>mph</source>
<translation>mph</translation>
</message>
<message>
<source>MAX</source>
<translation></translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>

@ -87,21 +87,6 @@
<translation> &quot;%1&quot;</translation>
</message>
</context>
<context>
<name>AnnotatedCameraWidget</name>
<message>
<source>km/h</source>
<translation>km/h</translation>
</message>
<message>
<source>mph</source>
<translation>mph</translation>
</message>
<message>
<source>MAX</source>
<translation></translation>
</message>
</context>
<context>
<name>ConfirmationDialog</name>
<message>
@ -289,6 +274,21 @@
<translation> ON</translation>
</message>
</context>
<context>
<name>HudRenderer</name>
<message>
<source>km/h</source>
<translation>km/h</translation>
</message>
<message>
<source>mph</source>
<translation>mph</translation>
</message>
<message>
<source>MAX</source>
<translation></translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>

Loading…
Cancel
Save