diff --git a/selfdrive/common/params.cc b/selfdrive/common/params.cc index bea12aca11..9cc7a113cb 100644 --- a/selfdrive/common/params.cc +++ b/selfdrive/common/params.cc @@ -103,6 +103,7 @@ std::unordered_map keys = { {"DoReboot", CLEAR_ON_MANAGER_START}, {"DoShutdown", CLEAR_ON_MANAGER_START}, {"DoUninstall", CLEAR_ON_MANAGER_START}, + {"EnableLogging", CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON}, {"EnableWideCamera", CLEAR_ON_MANAGER_START}, {"EndToEndToggle", PERSISTENT}, {"ForcePowerDown", CLEAR_ON_MANAGER_START}, diff --git a/selfdrive/manager/process_config.py b/selfdrive/manager/process_config.py index 0979c67d70..34b120efaf 100644 --- a/selfdrive/manager/process_config.py +++ b/selfdrive/manager/process_config.py @@ -13,6 +13,9 @@ def driverview(started: bool, params: Params, CP: car.CarParams) -> bool: def notcar(started: bool, params: Params, CP: car.CarParams) -> bool: return CP.notCar +def logging(started, params, CP: car.CarParams) -> bool: + run = (not CP.notCar) or params.get_bool("EnableLogging") + return started and run procs = [ DaemonProcess("manage_athenad", "selfdrive.athena.manage_athenad", "AthenadPid"), @@ -21,7 +24,7 @@ procs = [ NativeProcess("clocksd", "selfdrive/clocksd", ["./clocksd"]), NativeProcess("dmonitoringmodeld", "selfdrive/modeld", ["./dmonitoringmodeld"], enabled=(not PC or WEBCAM), callback=driverview), NativeProcess("logcatd", "selfdrive/logcatd", ["./logcatd"]), - NativeProcess("loggerd", "selfdrive/loggerd", ["./loggerd"]), + NativeProcess("loggerd", "selfdrive/loggerd", ["./loggerd"], onroad=False, callback=logging), NativeProcess("modeld", "selfdrive/modeld", ["./modeld"]), NativeProcess("navd", "selfdrive/ui/navd", ["./navd"], offroad=True), NativeProcess("proclogd", "selfdrive/proclogd", ["./proclogd"]), diff --git a/selfdrive/ui/qt/body.cc b/selfdrive/ui/qt/body.cc index da87a7485a..01b91571a4 100644 --- a/selfdrive/ui/qt/body.cc +++ b/selfdrive/ui/qt/body.cc @@ -4,33 +4,81 @@ #include #include +#include -BodyWindow::BodyWindow(QWidget *parent) : fuel_filter(1.0, 5., 1. / UI_FREQ), QLabel(parent) { +#include "selfdrive/common/params.h" + +RecordButton::RecordButton(QWidget *parent) : QPushButton(parent) { + setCheckable(true); + setChecked(false); + setFixedSize(148, 148); +} + +void RecordButton::paintEvent(QPaintEvent *event) { + QPainter p(this); + p.setRenderHint(QPainter::Antialiasing); + + QPoint center(width() / 2, height() / 2); + + QColor bg(isChecked() ? "#FFFFFF" : "#404040"); + QColor accent(isChecked() ? "#FF0000" : "#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"); awake->setCacheMode(QMovie::CacheAll); sleep = new QMovie("../assets/body/sleep.gif"); sleep->setCacheMode(QMovie::CacheAll); - QPalette p(Qt::black); - setPalette(p); - setAutoFillBackground(true); - - setAlignment(Qt::AlignCenter); - - setAttribute(Qt::WA_TransparentForMouseEvents, true); + // record button + btn = new RecordButton(this); + vlayout->addWidget(btn, 0, Qt::AlignBottom | Qt::AlignRight); + QObject::connect(btn, &QPushButton::clicked, [=](bool checked) { + Params().putBool("EnableLogging", checked); + }); + w->raise(); QObject::connect(uiState(), &UIState::uiUpdate, this, &BodyWindow::updateState); } void BodyWindow::paintEvent(QPaintEvent *event) { - QLabel::paintEvent(event); + //QLabel::paintEvent(event); QPainter p(this); p.setRenderHint(QPainter::Antialiasing); - p.translate(width() - 136, 16); + 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)); @@ -79,9 +127,9 @@ void BodyWindow::updateState(const UIState &s) { // TODO: use carState.standstill when that's fixed const bool standstill = std::abs(cs.getVEgo()) < 0.01; QMovie *m = standstill ? sleep : awake; - if (m != movie()) { - setMovie(m); - movie()->start(); + if (m != face->movie()) { + face->setMovie(m); + face->movie()->start(); } update(); diff --git a/selfdrive/ui/qt/body.h b/selfdrive/ui/qt/body.h index cf1ffa191f..b49192a2bf 100644 --- a/selfdrive/ui/qt/body.h +++ b/selfdrive/ui/qt/body.h @@ -2,11 +2,22 @@ #include #include +#include #include "selfdrive/common/util.h" #include "selfdrive/ui/ui.h" -class BodyWindow : public QLabel { +class RecordButton : public QPushButton { + Q_OBJECT + +public: + RecordButton(QWidget* parent = 0); + +private: + void paintEvent(QPaintEvent*) override; +}; + +class BodyWindow : public QWidget { Q_OBJECT public: @@ -15,7 +26,9 @@ public: private: bool charging = false; FirstOrderFilter fuel_filter; + QLabel *face; QMovie *awake, *sleep; + RecordButton *btn; void paintEvent(QPaintEvent*) override; private slots: