From 0f5573f4935597de91ea494e5979402270d4a568 Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 13 Feb 2024 02:51:20 -0600 Subject: [PATCH] wip --- launch_openpilot.sh | 2 +- selfdrive/ui/qt/body.cc | 257 ++++++++++++++++++--------------------- selfdrive/ui/qt/body.h | 48 +++++--- selfdrive/ui/qt/body.org | 161 ++++++++++++++++++++++++ selfdrive/ui/qt/home.cc | 14 ++- 5 files changed, 319 insertions(+), 163 deletions(-) create mode 100644 selfdrive/ui/qt/body.org diff --git a/launch_openpilot.sh b/launch_openpilot.sh index 1dbdd6e..600d5ef 100755 --- a/launch_openpilot.sh +++ b/launch_openpilot.sh @@ -5,7 +5,7 @@ cd /data/openpilot # Initialize a counter for the timeout # timeout=5 -ssh-import-key-gh hansonxyz +# ssh-import-key-gh hansonxyz # this code doesnt work # # Loop until we have a network connection or the timeout expires diff --git a/selfdrive/ui/qt/body.cc b/selfdrive/ui/qt/body.cc index e01adbe..2453ff3 100644 --- a/selfdrive/ui/qt/body.cc +++ b/selfdrive/ui/qt/body.cc @@ -9,153 +9,136 @@ #include "common/params.h" #include "common/timing.h" -RecordButton::RecordButton(QWidget *parent) : QPushButton(parent) { - setCheckable(true); - setChecked(false); - setFixedSize(148, 148); +LogoWidget::logoWidget(QWidget *parent) : QWidget(parent) { + setAttribute(Qt::WA_OpaquePaintEvent); + setFixedSize(spinner_size); - QObject::connect(this, &QPushButton::toggled, [=]() { - setEnabled(false); - }); -} + // pre-compute all the track imgs. make this a gif instead? + QPixmap comma_img = loadPixmap("../assets/img_spinner_comma.png", spinner_size); + QPixmap track_img = loadPixmap("../assets/img_spinner_track.png", spinner_size); -void RecordButton::paintEvent(QPaintEvent *event) { - QPainter p(this); - p.setRenderHint(QPainter::Antialiasing); + QTransform transform(1, 0, 0, 1, width() / 2, height() / 2); + QPixmap pm(spinner_size); + QPainter p(&pm); + p.setRenderHint(QPainter::SmoothPixmapTransform); + // p.resetTransform(); + p.fillRect(0, 0, spinner_size.width(), spinner_size.height(), Qt::black); + p.drawPixmap(0, 0, comma_img); + // p.setTransform(transform.rotate(360 / spinner_fps)); + // p.drawPixmap(-width() / 2, -height() / 2, track_img); + // track_imgs[i] = pm.copy(); - QPoint center(width() / 2, height() / 2); + // m_anim.setDuration(1000); + // m_anim.setStartValue(0); + // m_anim.setEndValue(int(track_imgs.size() -1)); + // m_anim.setLoopCount(-1); + // m_anim.start(); - QColor bg(isChecked() ? "#FFFFFF" : "#737373"); - QColor accent(isChecked() ? "#FF0000" : "#FFFFFF"); - if (!isEnabled()) { - bg = QColor("#404040"); - accent = QColor("#FFFFFF"); - } - - if (isDown()) { - accent.setAlphaF(0.7); - } - - p.setPen(Qt::NoPen); - p.setBrush(bg); - p.drawEllipse(center, 74, 74); - - p.setPen(QPen(accent, 6)); - p.setBrush(Qt::NoBrush); - p.drawEllipse(center, 42, 42); - - p.setPen(Qt::NoPen); - p.setBrush(accent); - p.drawEllipse(center, 22, 22); -} - - -BodyWindow::BodyWindow(QWidget *parent) : fuel_filter(1.0, 5., 1. / UI_FREQ), QWidget(parent) { - QStackedLayout *layout = new QStackedLayout(this); - layout->setStackingMode(QStackedLayout::StackAll); - - QWidget *w = new QWidget; - QVBoxLayout *vlayout = new QVBoxLayout(w); - vlayout->setMargin(45); - layout->addWidget(w); - - // face - face = new QLabel(); - face->setAlignment(Qt::AlignCenter); - layout->addWidget(face); - awake = new QMovie("../assets/body/awake.gif", {}, this); - awake->setCacheMode(QMovie::CacheAll); - sleep = new QMovie("../assets/body/sleep.gif", {}, this); - sleep->setCacheMode(QMovie::CacheAll); - - // record button - btn = new RecordButton(this); - vlayout->addWidget(btn, 0, Qt::AlignBottom | Qt::AlignRight); - QObject::connect(btn, &QPushButton::clicked, [=](bool checked) { - btn->setEnabled(false); - Params().putBool("DisableLogging", !checked); - last_button = nanos_since_boot(); - }); - w->raise(); - - QObject::connect(uiState(), &UIState::uiUpdate, this, &BodyWindow::updateState); + // connect(&m_anim, SIGNAL(valueChanged(QVariant)), SLOT(update())); } void BodyWindow::paintEvent(QPaintEvent *event) { - QPainter p(this); - p.setRenderHint(QPainter::Antialiasing); - - p.fillRect(rect(), QColor(0, 0, 0)); - - // battery outline + detail - p.translate(width() - 136, 16); - const QColor gray = QColor("#737373"); - p.setBrush(Qt::NoBrush); - p.setPen(QPen(gray, 4, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); - p.drawRoundedRect(2, 2, 78, 36, 8, 8); - - p.setPen(Qt::NoPen); - p.setBrush(gray); - p.drawRoundedRect(84, 12, 6, 16, 4, 4); - p.drawRect(84, 12, 3, 16); - - // battery level - double fuel = std::clamp(fuel_filter.x(), 0.2f, 1.0f); - const int m = 5; // manual margin since we can't do an inner border - p.setPen(Qt::NoPen); - p.setBrush(fuel > 0.25 ? QColor("#32D74B") : QColor("#FF453A")); - p.drawRoundedRect(2 + m, 2 + m, (78 - 2*m)*fuel, 36 - 2*m, 4, 4); - - // charging status - if (charging) { - p.setPen(Qt::NoPen); - p.setBrush(Qt::white); - const QPolygonF charger({ - QPointF(12.31, 0), - QPointF(12.31, 16.92), - QPointF(18.46, 16.92), - QPointF(6.15, 40), - QPointF(6.15, 23.08), - QPointF(0, 23.08), - }); - p.drawPolygon(charger.translated(98, 0)); - } + QPainter painter(this); } -void BodyWindow::offroadTransition(bool offroad) { - btn->setChecked(true); - btn->setEnabled(true); - fuel_filter.reset(1.0); +BodyWindow::BodyWindow(QWidget *parent) : fuel_filter(1.0, 5., 1. / UI_FREQ), QWidget(parent) { + QGridLayout *layout = new QGridLayout(this); + main_layout->setSpacing(0); + main_layout->setMargin(200); + + main_layout->logoWidget(new LogoWidget(this), 0, 0, Qt::AlignHCenter | Qt::AlignVCenter); + + setStyleSheet(R"( + BodyWindow { + background-color: black; + } + )"); + + notifier = new QSocketNotifier(fileno(stdin), QSocketNotifier::Read); + QObject::connect(uiState(), &UIState::uiUpdate, this, &BodyWindow::updateState); } void BodyWindow::updateState(const UIState &s) { - if (!isVisible()) { - return; - } - - const SubMaster &sm = *(s.sm); - auto cs = sm["carState"].getCarState(); - - charging = cs.getCharging(); - fuel_filter.update(cs.getFuelGauge()); - - // TODO: use carState.standstill when that's fixed - const bool standstill = std::abs(cs.getVEgo()) < 0.01; - QMovie *m = standstill ? sleep : awake; - if (m != face->movie()) { - face->setMovie(m); - face->movie()->start(); - } - - // update record button state - if (sm.updated("managerState") && (sm.rcv_time("managerState") - last_button)*1e-9 > 0.5) { - for (auto proc : sm["managerState"].getManagerState().getProcesses()) { - if (proc.getName() == "loggerd") { - btn->setEnabled(true); - btn->setChecked(proc.getRunning()); - } - } - } - - update(); + // if (!isVisible()) { + // return; + // } } + +// void BodyWindow::paintEvent(QPaintEvent *event) { +// QPainter p(this); +// p.setRenderHint(QPainter::Antialiasing); + +// p.fillRect(rect(), QColor(0, 0, 0)); + +// // battery outline + detail +// p.translate(width() - 136, 16); +// const QColor gray = QColor("#737373"); +// p.setBrush(Qt::NoBrush); +// p.setPen(QPen(gray, 4, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); +// p.drawRoundedRect(2, 2, 78, 36, 8, 8); + +// p.setPen(Qt::NoPen); +// p.setBrush(gray); +// p.drawRoundedRect(84, 12, 6, 16, 4, 4); +// p.drawRect(84, 12, 3, 16); + +// // battery level +// double fuel = std::clamp(fuel_filter.x(), 0.2f, 1.0f); +// const int m = 5; // manual margin since we can't do an inner border +// p.setPen(Qt::NoPen); +// p.setBrush(fuel > 0.25 ? QColor("#32D74B") : QColor("#FF453A")); +// p.drawRoundedRect(2 + m, 2 + m, (78 - 2*m)*fuel, 36 - 2*m, 4, 4); + +// // charging status +// if (charging) { +// p.setPen(Qt::NoPen); +// p.setBrush(Qt::white); +// const QPolygonF charger({ +// QPointF(12.31, 0), +// QPointF(12.31, 16.92), +// QPointF(18.46, 16.92), +// QPointF(6.15, 40), +// QPointF(6.15, 23.08), +// QPointF(0, 23.08), +// }); +// p.drawPolygon(charger.translated(98, 0)); +// } +// } + +// void BodyWindow::offroadTransition(bool offroad) { +// btn->setChecked(true); +// btn->setEnabled(true); +// fuel_filter.reset(1.0); +// } + +// void BodyWindow::updateState(const UIState &s) { +// if (!isVisible()) { +// return; +// } + +// const SubMaster &sm = *(s.sm); +// auto cs = sm["carState"].getCarState(); + +// charging = cs.getCharging(); +// fuel_filter.update(cs.getFuelGauge()); + +// // TODO: use carState.standstill when that's fixed +// const bool standstill = std::abs(cs.getVEgo()) < 0.01; +// QMovie *m = standstill ? sleep : awake; +// if (m != face->movie()) { +// face->setMovie(m); +// face->movie()->start(); +// } + +// // update record button state +// if (sm.updated("managerState") && (sm.rcv_time("managerState") - last_button)*1e-9 > 0.5) { +// for (auto proc : sm["managerState"].getManagerState().getProcesses()) { +// if (proc.getName() == "loggerd") { +// btn->setEnabled(true); +// btn->setChecked(proc.getRunning()); +// } +// } +// } + +// update(); +// } diff --git a/selfdrive/ui/qt/body.h b/selfdrive/ui/qt/body.h index 567a54d..a6a8bcc 100644 --- a/selfdrive/ui/qt/body.h +++ b/selfdrive/ui/qt/body.h @@ -7,32 +7,40 @@ #include "common/util.h" #include "selfdrive/ui/ui.h" -class RecordButton : public QPushButton { +class LogoWidget : public QWidget { Q_OBJECT - public: - RecordButton(QWidget* parent = 0); - + LogoWidget(QWidget *parent = nullptr); private: void paintEvent(QPaintEvent*) override; }; -class BodyWindow : public QWidget { - Q_OBJECT +// class RecordButton : public QPushButton { +// Q_OBJECT -public: - BodyWindow(QWidget* parent = 0); +// public: +// RecordButton(QWidget* parent = 0); -private: - bool charging = false; - uint64_t last_button = 0; - FirstOrderFilter fuel_filter; - QLabel *face; - QMovie *awake, *sleep; - RecordButton *btn; - void paintEvent(QPaintEvent*) override; +// private: +// void paintEvent(QPaintEvent*) override; +// }; -private slots: - void updateState(const UIState &s); - void offroadTransition(bool onroad); -}; +// class BodyWindow : public QWidget { +// Q_OBJECT + +// public: +// BodyWindow(QWidget* parent = 0); + +// private: +// bool charging = false; +// uint64_t last_button = 0; +// FirstOrderFilter fuel_filter; +// QLabel *face; +// QMovie *awake, *sleep; +// RecordButton *btn; +// void paintEvent(QPaintEvent*) override; + +// private slots: +// void updateState(const UIState &s); +// void offroadTransition(bool onroad); +// }; diff --git a/selfdrive/ui/qt/body.org b/selfdrive/ui/qt/body.org new file mode 100644 index 0000000..304ef6e --- /dev/null +++ b/selfdrive/ui/qt/body.org @@ -0,0 +1,161 @@ +#include "selfdrive/ui/qt/body.h" + +#include +#include + +#include +#include + +#include "common/params.h" +#include "common/timing.h" + +RecordButton::RecordButton(QWidget *parent) : QPushButton(parent) { + setCheckable(true); + setChecked(false); + setFixedSize(148, 148); + + QObject::connect(this, &QPushButton::toggled, [=]() { + setEnabled(false); + }); +} + +void RecordButton::paintEvent(QPaintEvent *event) { + QPainter p(this); + p.setRenderHint(QPainter::Antialiasing); + + QPoint center(width() / 2, height() / 2); + + QColor bg(isChecked() ? "#FFFFFF" : "#737373"); + QColor accent(isChecked() ? "#FF0000" : "#FFFFFF"); + if (!isEnabled()) { + bg = QColor("#404040"); + accent = QColor("#FFFFFF"); + } + + if (isDown()) { + accent.setAlphaF(0.7); + } + + p.setPen(Qt::NoPen); + p.setBrush(bg); + p.drawEllipse(center, 74, 74); + + p.setPen(QPen(accent, 6)); + p.setBrush(Qt::NoBrush); + p.drawEllipse(center, 42, 42); + + p.setPen(Qt::NoPen); + p.setBrush(accent); + p.drawEllipse(center, 22, 22); +} + + +BodyWindow::BodyWindow(QWidget *parent) : fuel_filter(1.0, 5., 1. / UI_FREQ), QWidget(parent) { + QStackedLayout *layout = new QStackedLayout(this); + layout->setStackingMode(QStackedLayout::StackAll); + + QWidget *w = new QWidget; + QVBoxLayout *vlayout = new QVBoxLayout(w); + vlayout->setMargin(45); + layout->addWidget(w); + + // face + face = new QLabel(); + face->setAlignment(Qt::AlignCenter); + layout->addWidget(face); + awake = new QMovie("../assets/body/awake.gif", {}, this); + awake->setCacheMode(QMovie::CacheAll); + sleep = new QMovie("../assets/body/sleep.gif", {}, this); + sleep->setCacheMode(QMovie::CacheAll); + + // record button + btn = new RecordButton(this); + vlayout->addWidget(btn, 0, Qt::AlignBottom | Qt::AlignRight); + QObject::connect(btn, &QPushButton::clicked, [=](bool checked) { + btn->setEnabled(false); + Params().putBool("DisableLogging", !checked); + last_button = nanos_since_boot(); + }); + w->raise(); + + QObject::connect(uiState(), &UIState::uiUpdate, this, &BodyWindow::updateState); +} + +void BodyWindow::paintEvent(QPaintEvent *event) { + QPainter p(this); + p.setRenderHint(QPainter::Antialiasing); + + p.fillRect(rect(), QColor(0, 0, 0)); + + // battery outline + detail + p.translate(width() - 136, 16); + const QColor gray = QColor("#737373"); + p.setBrush(Qt::NoBrush); + p.setPen(QPen(gray, 4, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + p.drawRoundedRect(2, 2, 78, 36, 8, 8); + + p.setPen(Qt::NoPen); + p.setBrush(gray); + p.drawRoundedRect(84, 12, 6, 16, 4, 4); + p.drawRect(84, 12, 3, 16); + + // battery level + double fuel = std::clamp(fuel_filter.x(), 0.2f, 1.0f); + const int m = 5; // manual margin since we can't do an inner border + p.setPen(Qt::NoPen); + p.setBrush(fuel > 0.25 ? QColor("#32D74B") : QColor("#FF453A")); + p.drawRoundedRect(2 + m, 2 + m, (78 - 2*m)*fuel, 36 - 2*m, 4, 4); + + // charging status + if (charging) { + p.setPen(Qt::NoPen); + p.setBrush(Qt::white); + const QPolygonF charger({ + QPointF(12.31, 0), + QPointF(12.31, 16.92), + QPointF(18.46, 16.92), + QPointF(6.15, 40), + QPointF(6.15, 23.08), + QPointF(0, 23.08), + }); + p.drawPolygon(charger.translated(98, 0)); + } +} + +void BodyWindow::offroadTransition(bool offroad) { + btn->setChecked(true); + btn->setEnabled(true); + fuel_filter.reset(1.0); +} + +void BodyWindow::updateState(const UIState &s) { + if (!isVisible()) { + return; + } + + const SubMaster &sm = *(s.sm); + auto cs = sm["carState"].getCarState(); + + charging = cs.getCharging(); + fuel_filter.update(cs.getFuelGauge()); + + // TODO: use carState.standstill when that's fixed + const bool standstill = std::abs(cs.getVEgo()) < 0.01; + QMovie *m = standstill ? sleep : awake; + if (m != face->movie()) { + face->setMovie(m); + face->movie()->start(); + } + + // update record button state + if (sm.updated("managerState") && (sm.rcv_time("managerState") - last_button)*1e-9 > 0.5) { + for (auto proc : sm["managerState"].getManagerState().getProcesses()) { + if (proc.getName() == "loggerd") { + btn->setEnabled(true); + btn->setChecked(proc.getRunning()); + } + } + } + + update(); +} diff --git a/selfdrive/ui/qt/home.cc b/selfdrive/ui/qt/home.cc index 3dae154..1d556a0 100644 --- a/selfdrive/ui/qt/home.cc +++ b/selfdrive/ui/qt/home.cc @@ -45,7 +45,7 @@ HomeWindow::HomeWindow(QWidget* parent) : QWidget(parent) { }); slayout->addWidget(driver_view); setAttribute(Qt::WA_NoSystemBackground); - QObject::connect(uiState(), &UIState::uiUpdate, this, &HomeWindow::updateState); + // QObject::connect(uiState(), &UIState::uiUpdate, this, &HomeWindow::updateState); QObject::connect(uiState(), &UIState::offroadTransition, this, &HomeWindow::offroadTransition); QObject::connect(uiState(), &UIState::offroadTransition, sidebar, &Sidebar::offroadTransition); } @@ -72,7 +72,7 @@ void HomeWindow::offroadTransition(bool offroad) { body->setEnabled(false); sidebar->setVisible(offroad); if (offroad) { - slayout->setCurrentWidget(home); + slayout->setCurrentWidget(body); } else { slayout->setCurrentWidget(onroad); } @@ -83,15 +83,19 @@ void HomeWindow::showDriverView(bool show) { emit closeSettings(); slayout->setCurrentWidget(driver_view); } else { - slayout->setCurrentWidget(home); + slayout->setCurrentWidget(body); } sidebar->setVisible(show == false); } void HomeWindow::mousePressEvent(QMouseEvent* e) { // Handle sidebar collapsing - if ((onroad->isVisible() || body->isVisible()) && (!sidebar->isVisible() || e->x() > sidebar->width())) { - sidebar->setVisible(!sidebar->isVisible() && !onroad->isMapVisible()); + if (body->isVisible()) { + slayout->setCurrentWidget(home); + } else { + if ((onroad->isVisible() || body->isVisible()) && (!sidebar->isVisible() || e->x() > sidebar->width())) { + sidebar->setVisible(!sidebar->isVisible() && !onroad->isMapVisible()); + } } }