mui.cc 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include <QApplication>
  2. #include <QtWidgets>
  3. #include <QTimer>
  4. #include <QGraphicsScene>
  5. #include "cereal/messaging/messaging.h"
  6. #include "selfdrive/ui/ui.h"
  7. #include "selfdrive/ui/qt/qt_window.h"
  8. class StatusBar : public QGraphicsRectItem {
  9. private:
  10. QLinearGradient linear_gradient;
  11. QRadialGradient radial_gradient;
  12. QTimer animation_timer;
  13. const int animation_length = 10;
  14. int animation_index = 0;
  15. public:
  16. StatusBar(double x, double y, double width, double height) : QGraphicsRectItem {x, y, width, height} {
  17. linear_gradient = QLinearGradient(0, 0, 0, height/2);
  18. linear_gradient.setSpread(QGradient::ReflectSpread);
  19. radial_gradient = QRadialGradient(width/2, height/2, width/8);
  20. QObject::connect(&animation_timer, &QTimer::timeout, [=]() {
  21. animation_index++;
  22. animation_index %= animation_length;
  23. });
  24. animation_timer.start(50);
  25. }
  26. void solidColor(QColor color) {
  27. QColor dark_color = QColor(color);
  28. dark_color.setAlphaF(0.5);
  29. linear_gradient.setColorAt(0, dark_color);
  30. linear_gradient.setColorAt(1, color);
  31. setBrush(QBrush(linear_gradient));
  32. }
  33. // these need to be called continuously for the animations to work.
  34. // can probably clean that up with some more abstractions
  35. void blinkingColor(QColor color) {
  36. QColor dark_color = QColor(color);
  37. dark_color.setAlphaF(0.1);
  38. int radius = (rect().width() / animation_length) * animation_index;
  39. QPoint center = QPoint(rect().width()/2, rect().height()/2);
  40. radial_gradient.setCenter(center);
  41. radial_gradient.setFocalPoint(center);
  42. radial_gradient.setRadius(radius);
  43. radial_gradient.setColorAt(1, dark_color);
  44. radial_gradient.setColorAt(0, color);
  45. setBrush(QBrush(radial_gradient));
  46. }
  47. void laneChange(cereal::LateralPlan::LaneChangeDirection direction) {
  48. QColor dark_color = QColor(bg_colors[STATUS_ENGAGED]);
  49. dark_color.setAlphaF(0.1);
  50. int x = (rect().width() / animation_length) * animation_index;
  51. QPoint center = QPoint(((direction == cereal::LateralPlan::LaneChangeDirection::RIGHT) ? x : (rect().width() - x)), rect().height()/2);
  52. radial_gradient.setCenter(center);
  53. radial_gradient.setFocalPoint(center);
  54. radial_gradient.setRadius(rect().width()/5);
  55. radial_gradient.setColorAt(1, dark_color);
  56. radial_gradient.setColorAt(0, bg_colors[STATUS_ENGAGED]);
  57. setBrush(QBrush(radial_gradient));
  58. }
  59. void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override {
  60. painter->setPen(QPen());
  61. painter->setBrush(brush());
  62. double rounding_radius = rect().height()/2;
  63. painter->drawRoundedRect(rect(), rounding_radius, rounding_radius);
  64. }
  65. };
  66. int main(int argc, char *argv[]) {
  67. QApplication a(argc, argv);
  68. QWidget w;
  69. setMainWindow(&w);
  70. w.setStyleSheet("background-color: black;");
  71. // our beautiful UI
  72. QVBoxLayout *layout = new QVBoxLayout(&w);
  73. QGraphicsScene *scene = new QGraphicsScene();
  74. StatusBar *status_bar = new StatusBar(0, 0, 1000, 50);
  75. scene->addItem(status_bar);
  76. QGraphicsView *graphics_view = new QGraphicsView(scene);
  77. layout->insertSpacing(0, 400);
  78. layout->addWidget(graphics_view, 0, Qt::AlignCenter);
  79. QTimer timer;
  80. QObject::connect(&timer, &QTimer::timeout, [=]() {
  81. static SubMaster sm({"deviceState", "controlsState", "lateralPlan"});
  82. bool onroad_prev = sm.allAliveAndValid({"deviceState"}) &&
  83. sm["deviceState"].getDeviceState().getStarted();
  84. sm.update(0);
  85. bool onroad = sm.allAliveAndValid({"deviceState"}) &&
  86. sm["deviceState"].getDeviceState().getStarted();
  87. if (onroad) {
  88. auto cs = sm["controlsState"].getControlsState();
  89. UIStatus status = cs.getEnabled() ? STATUS_ENGAGED : STATUS_DISENGAGED;
  90. if (cs.getAlertStatus() == cereal::ControlsState::AlertStatus::USER_PROMPT) {
  91. status = STATUS_WARNING;
  92. } else if (cs.getAlertStatus() == cereal::ControlsState::AlertStatus::CRITICAL) {
  93. status = STATUS_ALERT;
  94. }
  95. auto lp = sm["lateralPlan"].getLateralPlan();
  96. if (lp.getLaneChangeState() == cereal::LateralPlan::LaneChangeState::PRE_LANE_CHANGE || status == STATUS_ALERT) {
  97. status_bar->blinkingColor(bg_colors[status]);
  98. } else if (lp.getLaneChangeState() == cereal::LateralPlan::LaneChangeState::LANE_CHANGE_STARTING ||
  99. lp.getLaneChangeState() == cereal::LateralPlan::LaneChangeState::LANE_CHANGE_FINISHING) {
  100. status_bar->laneChange(lp.getLaneChangeDirection());
  101. } else {
  102. status_bar->solidColor(bg_colors[status]);
  103. }
  104. }
  105. if ((onroad != onroad_prev) || sm.frame < 2) {
  106. Hardware::set_brightness(50);
  107. Hardware::set_display_power(onroad);
  108. }
  109. });
  110. timer.start(50);
  111. return a.exec();
  112. }