Skip to content

Commit a1e201e

Browse files
authored
MUI should be a status bar (commaai#23287)
1 parent f2c17bb commit a1e201e

File tree

1 file changed

+91
-4
lines changed

1 file changed

+91
-4
lines changed

selfdrive/ui/mui.cc

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,83 @@
11
#include <QApplication>
22
#include <QtWidgets>
33
#include <QTimer>
4+
#include <QGraphicsScene>
45

56
#include "cereal/messaging/messaging.h"
67
#include "selfdrive/ui/ui.h"
78
#include "selfdrive/ui/qt/qt_window.h"
89

10+
class StatusBar : public QGraphicsRectItem {
11+
private:
12+
QLinearGradient linear_gradient;
13+
QRadialGradient radial_gradient;
14+
QTimer animation_timer;
15+
const int animation_length = 10;
16+
int animation_index = 0;
17+
18+
public:
19+
StatusBar(double x, double y, double width, double height) : QGraphicsRectItem {x, y, width, height} {
20+
linear_gradient = QLinearGradient(0, 0, 0, height/2);
21+
linear_gradient.setSpread(QGradient::ReflectSpread);
22+
23+
radial_gradient = QRadialGradient(width/2, height/2, width/8);
24+
QObject::connect(&animation_timer, &QTimer::timeout, [=]() {
25+
animation_index++;
26+
animation_index %= animation_length;
27+
});
28+
animation_timer.start(50);
29+
}
30+
31+
void solidColor(QColor color) {
32+
QColor dark_color = QColor(color);
33+
dark_color.setAlphaF(0.5);
34+
35+
linear_gradient.setColorAt(0, dark_color);
36+
linear_gradient.setColorAt(1, color);
37+
setBrush(QBrush(linear_gradient));
38+
}
39+
40+
// these need to be called continuously for the animations to work.
41+
// can probably clean that up with some more abstractions
42+
void blinkingColor(QColor color) {
43+
QColor dark_color = QColor(color);
44+
dark_color.setAlphaF(0.1);
45+
46+
int radius = (rect().width() / animation_length) * animation_index;
47+
QPoint center = QPoint(rect().width()/2, rect().height()/2);
48+
radial_gradient.setCenter(center);
49+
radial_gradient.setFocalPoint(center);
50+
radial_gradient.setRadius(radius);
51+
52+
radial_gradient.setColorAt(1, dark_color);
53+
radial_gradient.setColorAt(0, color);
54+
setBrush(QBrush(radial_gradient));
55+
}
56+
57+
void laneChange(cereal::LateralPlan::LaneChangeDirection direction) {
58+
QColor dark_color = QColor(bg_colors[STATUS_ENGAGED]);
59+
dark_color.setAlphaF(0.1);
60+
61+
int x = (rect().width() / animation_length) * animation_index;
62+
QPoint center = QPoint(((direction == cereal::LateralPlan::LaneChangeDirection::RIGHT) ? x : (rect().width() - x)), rect().height()/2);
63+
radial_gradient.setCenter(center);
64+
radial_gradient.setFocalPoint(center);
65+
radial_gradient.setRadius(rect().width()/5);
66+
67+
radial_gradient.setColorAt(1, dark_color);
68+
radial_gradient.setColorAt(0, bg_colors[STATUS_ENGAGED]);
69+
setBrush(QBrush(radial_gradient));
70+
}
71+
72+
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override {
73+
painter->setPen(QPen());
74+
painter->setBrush(brush());
75+
76+
double rounding_radius = rect().height()/2;
77+
painter->drawRoundedRect(rect(), rounding_radius, rounding_radius);
78+
}
79+
};
80+
981
int main(int argc, char *argv[]) {
1082
QApplication a(argc, argv);
1183
QWidget w;
@@ -15,12 +87,18 @@ int main(int argc, char *argv[]) {
1587

1688
// our beautiful UI
1789
QVBoxLayout *layout = new QVBoxLayout(&w);
18-
QLabel *label = new QLabel("");
19-
layout->addWidget(label, 0, Qt::AlignCenter);
90+
91+
QGraphicsScene *scene = new QGraphicsScene();
92+
StatusBar *status_bar = new StatusBar(0, 0, 1000, 50);
93+
scene->addItem(status_bar);
94+
95+
QGraphicsView *graphics_view = new QGraphicsView(scene);
96+
layout->insertSpacing(0, 400);
97+
layout->addWidget(graphics_view, 0, Qt::AlignCenter);
2098

2199
QTimer timer;
22100
QObject::connect(&timer, &QTimer::timeout, [=]() {
23-
static SubMaster sm({"deviceState", "controlsState"});
101+
static SubMaster sm({"deviceState", "controlsState", "lateralPlan"});
24102

25103
bool onroad_prev = sm.allAliveAndValid({"deviceState"}) &&
26104
sm["deviceState"].getDeviceState().getStarted();
@@ -37,7 +115,16 @@ int main(int argc, char *argv[]) {
37115
} else if (cs.getAlertStatus() == cereal::ControlsState::AlertStatus::CRITICAL) {
38116
status = STATUS_ALERT;
39117
}
40-
label->setStyleSheet(QString("color: %1; font-size: 250px;").arg(bg_colors[status].name()));
118+
119+
auto lp = sm["lateralPlan"].getLateralPlan();
120+
if (lp.getLaneChangeState() == cereal::LateralPlan::LaneChangeState::PRE_LANE_CHANGE || status == STATUS_ALERT) {
121+
status_bar->blinkingColor(bg_colors[status]);
122+
} else if (lp.getLaneChangeState() == cereal::LateralPlan::LaneChangeState::LANE_CHANGE_STARTING ||
123+
lp.getLaneChangeState() == cereal::LateralPlan::LaneChangeState::LANE_CHANGE_FINISHING) {
124+
status_bar->laneChange(lp.getLaneChangeDirection());
125+
} else {
126+
status_bar->solidColor(bg_colors[status]);
127+
}
41128
}
42129

43130
if ((onroad != onroad_prev) || sm.frame < 2) {

0 commit comments

Comments
 (0)