openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

101 lines
3.6 KiB

#include "selfdrive/ui/qt/offroad/driverview.h"
#include <QPainter>
#include "selfdrive/ui/qt/qt_window.h"
#include "selfdrive/ui/qt/util.h"
const int FACE_IMG_SIZE = 130;
DriverViewWindow::DriverViewWindow(QWidget* parent) : QWidget(parent) {
setAttribute(Qt::WA_OpaquePaintEvent);
layout = new QStackedLayout(this);
layout->setStackingMode(QStackedLayout::StackAll);
cameraView = new CameraViewWidget(VISION_STREAM_RGB_FRONT, true, this);
layout->addWidget(cameraView);
scene = new DriverViewScene(this);
connect(cameraView, &CameraViewWidget::frameUpdated, scene, &DriverViewScene::frameUpdated);
layout->addWidget(scene);
layout->setCurrentWidget(scene);
}
void DriverViewWindow::mouseReleaseEvent(QMouseEvent* e) {
emit done();
}
DriverViewScene::DriverViewScene(QWidget* parent) : sm({"driverState"}), QWidget(parent) {
face_img = QImage("../assets/img_driver_face.png").scaled(FACE_IMG_SIZE, FACE_IMG_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
void DriverViewScene::showEvent(QShowEvent* event) {
frame_updated = false;
is_rhd = params.getBool("IsRHD");
params.putBool("IsDriverViewEnabled", true);
}
void DriverViewScene::hideEvent(QHideEvent* event) {
params.putBool("IsDriverViewEnabled", false);
}
void DriverViewScene::frameUpdated() {
frame_updated = true;
sm.update(0);
update();
}
void DriverViewScene::paintEvent(QPaintEvent* event) {
QPainter p(this);
// startup msg
if (!frame_updated) {
p.setPen(Qt::white);
p.setRenderHint(QPainter::TextAntialiasing);
configFont(p, "Inter", 100, "Bold");
p.drawText(geometry(), Qt::AlignCenter, "camera starting");
return;
}
const int width = 4 * height() / 3;
const QRect rect2 = {rect().center().x() - width / 2, rect().top(), width, rect().height()};
const QRect valid_rect = {is_rhd ? rect2.right() - rect2.height() / 2 : rect2.left(), rect2.top(), rect2.height() / 2, rect2.height()};
// blackout
const QColor bg(0, 0, 0, 140);
const QRect& blackout_rect = Hardware::TICI() ? rect() : rect2;
p.fillRect(blackout_rect.adjusted(0, 0, valid_rect.left() - blackout_rect.right(), 0), bg);
p.fillRect(blackout_rect.adjusted(valid_rect.right() - blackout_rect.left(), 0, 0, 0), bg);
if (Hardware::TICI()) {
p.fillRect(blackout_rect.adjusted(valid_rect.left()-blackout_rect.left()+1, 0, valid_rect.right()-blackout_rect.right()-1, -valid_rect.height()*7/10), bg); // top dz
}
// face bounding box
cereal::DriverState::Reader driver_state = sm["driverState"].getDriverState();
bool face_detected = driver_state.getFaceProb() > 0.5;
if (face_detected) {
auto fxy_list = driver_state.getFacePosition();
auto std_list = driver_state.getFaceOrientationStd();
float face_x = fxy_list[0];
float face_y = fxy_list[1];
float face_std = std::max(std_list[0], std_list[1]);
float alpha = 0.7;
if (face_std > 0.08) {
alpha = std::max(0.7 - (face_std-0.08)*7, 0.0);
}
const int box_size = 0.6 * rect2.height() / 2;
const float rhd_offset = 0.05; // lhd is shifted, so rhd is not mirrored
int fbox_x = valid_rect.center().x() + (is_rhd ? (face_x + rhd_offset) : -face_x) * valid_rect.width();
int fbox_y = valid_rect.center().y() + face_y * valid_rect.height();
p.setPen(QPen(QColor(255, 255, 255, alpha * 255), 10));
p.drawRoundedRect(fbox_x - box_size / 2, fbox_y - box_size / 2, box_size, box_size, 35.0, 35.0);
}
// icon
const int img_offset = 30;
const int img_x = is_rhd ? rect2.right() - FACE_IMG_SIZE - img_offset : rect2.left() + img_offset;
const int img_y = rect2.bottom() - FACE_IMG_SIZE - img_offset;
p.setOpacity(face_detected ? 1.0 : 0.3);
p.drawImage(img_x, img_y, face_img);
}