Skip to content

Commit ae34afa

Browse files
sshaneAragon7777
authored andcommitted
onroad ui: dynamic follow button (commaai#441)
* start to work on onroad ui * saInit * button test * fix * test * test * test * ButtonsWindow will hold all onroad buttons! * circle button * two button demo * tune the buttons * closer to before * closer to before * ml colors * button colors * fix * initialize df button with param data and send cereal message * fix stacking * margin * match order * can go in main stylesheet
1 parent 7893d7c commit ae34afa

File tree

5 files changed

+110
-2
lines changed

5 files changed

+110
-2
lines changed

common/op_params.py

-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ def __init__(self):
120120
'auto will reboot the device when an update is seen', static=True),
121121
'dynamic_gas': Param(False, bool, 'Whether to use dynamic gas if your car is supported'),
122122
'hide_auto_df_alerts': Param(False, bool, 'Hides the alert that shows what profile the model has chosen'),
123-
'model_laneless': Param(False, bool, 'Ignore lane lines, only path is used for planning (e2e). Experimental', static=True),
124123
'log_auto_df': Param(False, bool, 'Logs dynamic follow data for auto-df', static=True),
125124
# 'dynamic_camera_offset': Param(False, bool, 'Whether to automatically keep away from oncoming traffic.\n'
126125
# 'Works from 35 to ~60 mph (requires radar)'),

selfdrive/ui/qt/onroad.cc

+63
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent) {
2828
split->setSpacing(0);
2929
split->addWidget(nvg);
3030

31+
buttons = new ButtonsWindow(this);
32+
stacked_layout->addWidget(buttons);
33+
3134
stacked_layout->addWidget(split_wrapper);
3235

3336
alerts = new OnroadAlerts(this);
@@ -43,6 +46,8 @@ OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent) {
4346
}
4447

4548
void OnroadWindow::updateState(const UIState &s) {
49+
buttons->updateState(s);
50+
4651
SubMaster &sm = *(s.sm);
4752
QColor bgColor = bg_colors[s.status];
4853
if (sm.updated("controlsState")) {
@@ -100,6 +105,64 @@ void OnroadWindow::paintEvent(QPaintEvent *event) {
100105

101106
// ***** onroad widgets *****
102107

108+
ButtonsWindow::ButtonsWindow(QWidget *parent) : QWidget(parent) {
109+
QVBoxLayout *main_layout = new QVBoxLayout(this);
110+
111+
QWidget *btns_wrapper = new QWidget;
112+
QHBoxLayout *btns_layout = new QHBoxLayout(btns_wrapper);
113+
btns_layout->setSpacing(0);
114+
btns_layout->setContentsMargins(0, 0, 15, 15);
115+
116+
main_layout->addWidget(btns_wrapper, 0, Qt::AlignBottom);
117+
118+
// mlButton = new QPushButton("Toggle Model Long");
119+
// mlButton->setStyleSheet("font-size: 50px; border-radius: 25px; border-color: #b83737;");
120+
// QObject::connect(mlButton, &QPushButton::clicked, [=]() {
121+
// mlButton->setStyleSheet("font-size: 50px; border-radius: 25px; border-color: #37b868;");
122+
// });
123+
// mlButton->setFixedWidth(525);
124+
// mlButton->setFixedHeight(150);
125+
// btns_layout->addStretch();
126+
// btns_layout->addWidget(mlButton, 0, Qt::AlignCenter);
127+
128+
dfButton = new QPushButton("DF\nprofile");
129+
QObject::connect(dfButton, &QPushButton::clicked, [=]() {
130+
QUIState::ui_state.scene.dfButtonStatus = dfStatus < 3 ? dfStatus + 1 : 0; // wrap back around
131+
});
132+
dfButton->setFixedWidth(200);
133+
dfButton->setFixedHeight(200);
134+
// btns_layout->addStretch();
135+
btns_layout->addWidget(dfButton, 0, Qt::AlignRight);
136+
137+
setStyleSheet(R"(
138+
QPushButton {
139+
color: white;
140+
text-align: center;
141+
padding: 0px;
142+
border-width: 12px;
143+
border-style: solid;
144+
background-color: transparent;
145+
}
146+
)");
147+
}
148+
149+
void ButtonsWindow::updateState(const UIState &s) {
150+
updateDfButton(s.scene.dfButtonStatus); // update dynamic follow profile button
151+
// updateMlButton(s.scene.dfButtonStatus); // update model longitudinal button // TODO: add model long back first
152+
}
153+
154+
void ButtonsWindow::updateDfButton(int status) {
155+
if (dfStatus != status) { // updates (resets) on car start, or on button press
156+
dfStatus = status;
157+
dfButton->setStyleSheet(QString("font-size: 45px; border-radius: 100px; border-color: %1").arg(dfButtonColors.at(dfStatus)));
158+
159+
MessageBuilder msg;
160+
auto dfButtonStatus = msg.initEvent().initDynamicFollowButton();
161+
dfButtonStatus.setStatus(dfStatus);
162+
QUIState::ui_state.pm->send("dynamicFollowButton", msg);
163+
}
164+
}
165+
103166
void OnroadAlerts::updateAlert(const Alert &a, const QColor &color) {
104167
if (!alert.equal(a) || color != bg) {
105168
alert = a;

selfdrive/ui/qt/onroad.h

+18
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <QOpenGLWidget>
55
#include <QStackedLayout>
66
#include <QWidget>
7+
#include <QPushButton>
78

89
#include "cereal/gen/cpp/log.capnp.h"
910
#include "selfdrive/ui/qt/qt_window.h"
@@ -12,6 +13,22 @@
1213

1314
// ***** onroad widgets *****
1415

16+
class ButtonsWindow : public QWidget {
17+
Q_OBJECT
18+
19+
public:
20+
ButtonsWindow(QWidget* parent = 0);
21+
void updateState(const UIState &s);
22+
23+
private:
24+
QPushButton *dfButton;
25+
// QPushButton *mlButton;
26+
27+
int dfStatus = -1; // always initialize style sheet and send msg
28+
const QStringList dfButtonColors = {"#044389", "#24a8bc", "#fcff4b", "#37b868"};
29+
void updateDfButton(int status);
30+
};
31+
1532
class OnroadAlerts : public QWidget {
1633
Q_OBJECT
1734

@@ -61,6 +78,7 @@ class OnroadWindow : public QWidget {
6178

6279
OnroadAlerts *alerts;
6380
NvgWindow *nvg;
81+
ButtonsWindow *buttons;
6482
QColor bg = bg_colors[STATUS_DISENGAGED];
6583
QHBoxLayout* split;
6684

selfdrive/ui/ui.cc

+22
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <cassert>
66
#include <cmath>
77
#include <cstdio>
8+
#include <QDebug>
89

910
#include "selfdrive/common/swaglog.h"
1011
#include "selfdrive/common/util.h"
@@ -18,6 +19,25 @@
1819
#define BACKLIGHT_TS 10.00
1920
#define BACKLIGHT_OFFROAD 75
2021

22+
std::map<std::string, int> LS_TO_IDX = {{"off", 0}, {"audible", 1}, {"silent", 2}};
23+
std::map<std::string, int> DF_TO_IDX = {{"traffic", 0}, {"relaxed", 1}, {"stock", 2}, {"auto", 3}};
24+
25+
void saInit(UIState *s) {
26+
s->scene.mlButtonEnabled = false; // reset on ignition
27+
28+
std::string dynamic_follow = util::read_file("/data/community/params/dynamic_follow");
29+
if (dynamic_follow != "") {
30+
dynamic_follow = dynamic_follow.substr(1, dynamic_follow.find_last_of('"') - 1);
31+
qDebug() << "set dfButtonStatus to" << QString::fromStdString(dynamic_follow);
32+
s->scene.dfButtonStatus = DF_TO_IDX[dynamic_follow];
33+
}
34+
// std::string lane_speed_alerts = util::read_file("/data/community/params/lane_speed_alerts");
35+
// if (lane_speed_alerts != "") {
36+
// lane_speed_alerts = lane_speed_alerts.substr(1, lane_speed_alerts.find_last_of('"') - 1);
37+
// qDebug() << "Set lsButtonStatus to " << lane_speed_alerts;
38+
// s->scene.lsButtonStatus = DF_TO_IDX[lane_speed_alerts];
39+
// }
40+
}
2141

2242
// Projects a point in car to space to the corresponding point in full frame
2343
// image space.
@@ -246,6 +266,7 @@ static void update_status(UIState *s) {
246266
static bool started_prev = false;
247267
if (s->scene.started != started_prev) {
248268
if (s->scene.started) {
269+
saInit(s);
249270
s->status = STATUS_DISENGAGED;
250271
s->scene.started_frame = s->sm->frame;
251272

@@ -276,6 +297,7 @@ QUIState::QUIState(QObject *parent) : QObject(parent) {
276297
"modelV2", "controlsState", "liveCalibration", "radarState", "deviceState", "roadCameraState",
277298
"pandaState", "carParams", "driverMonitoringState", "sensorEvents", "carState", "liveLocationKalman",
278299
});
300+
ui_state.pm = std::make_unique<PubMaster, const std::initializer_list<const char *>>({"laneSpeedButton", "dynamicFollowButton", "modelLongButton"});
279301

280302
ui_state.fb_w = vwp_w;
281303
ui_state.fb_h = vwp_h;

selfdrive/ui/ui.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ typedef struct Alert {
6060
}
6161
} Alert;
6262

63-
const Alert CONTROLS_WAITING_ALERT = {"openpilot Unavailable", "Waiting for controls to start",
63+
const Alert CONTROLS_WAITING_ALERT = {"openpilot Unavailable", "Waiting for controls to start",
6464
"controlsWaiting", cereal::ControlsState::AlertSize::MID,
6565
AudibleAlert::NONE};
6666

@@ -100,6 +100,10 @@ typedef struct {
100100

101101
typedef struct UIScene {
102102

103+
int dfButtonStatus = 0;
104+
int lsButtonStatus = 0;
105+
bool mlButtonEnabled;
106+
103107
mat3 view_from_calib;
104108
bool world_objects_visible;
105109

@@ -138,6 +142,7 @@ typedef struct UIState {
138142
std::map<std::string, int> images;
139143

140144
std::unique_ptr<SubMaster> sm;
145+
std::unique_ptr<PubMaster> pm;
141146

142147
UIStatus status;
143148
UIScene scene;
@@ -175,6 +180,7 @@ private slots:
175180
private:
176181
QTimer *timer;
177182
bool started_prev = true;
183+
void saInit(const UIState &s);
178184
};
179185

180186

0 commit comments

Comments
 (0)