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.

559 lines
19 KiB

#include "selfdrive/ui/qt/onroad.h"
#include <cmath>
#include <QDebug>
#include "common/timing.h"
#include "selfdrive/ui/qt/util.h"
#ifdef ENABLE_MAPS
#include "selfdrive/ui/qt/maps/map.h"
#include "selfdrive/ui/qt/maps/map_helpers.h"
#endif
OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent) {
QVBoxLayout *main_layout = new QVBoxLayout(this);
main_layout->setMargin(bdr_s);
QStackedLayout *stacked_layout = new QStackedLayout;
stacked_layout->setStackingMode(QStackedLayout::StackAll);
main_layout->addLayout(stacked_layout);
nvg = new NvgWindow(VISION_STREAM_ROAD, this);
QWidget * split_wrapper = new QWidget;
split = new QHBoxLayout(split_wrapper);
split->setContentsMargins(0, 0, 0, 0);
split->setSpacing(0);
split->addWidget(nvg);
stacked_layout->addWidget(split_wrapper);
alerts = new OnroadAlerts(this);
alerts->setAttribute(Qt::WA_TransparentForMouseEvents, true);
stacked_layout->addWidget(alerts);
// setup stacking order
alerts->raise();
setAttribute(Qt::WA_OpaquePaintEvent);
QObject::connect(uiState(), &UIState::uiUpdate, this, &OnroadWindow::updateState);
QObject::connect(uiState(), &UIState::offroadTransition, this, &OnroadWindow::offroadTransition);
}
void OnroadWindow::updateState(const UIState &s) {
QColor bgColor = bg_colors[s.status];
Alert alert = Alert::get(*(s.sm), s.scene.started_frame);
if (s.sm->updated("controlsState") || !alert.equal({})) {
if (alert.type == "controlsUnresponsive") {
bgColor = bg_colors[STATUS_ALERT];
} else if (alert.type == "controlsUnresponsivePermanent") {
bgColor = bg_colors[STATUS_DISENGAGED];
}
alerts->updateAlert(alert, bgColor);
}
if (s.scene.map_on_left) {
split->setDirection(QBoxLayout::LeftToRight);
} else {
split->setDirection(QBoxLayout::RightToLeft);
}
nvg->updateState(s);
if (bg != bgColor) {
// repaint border
bg = bgColor;
update();
}
}
void OnroadWindow::mousePressEvent(QMouseEvent* e) {
if (map != nullptr) {
bool sidebarVisible = geometry().x() > 0;
map->setVisible(!sidebarVisible && !map->isVisible());
}
// propagation event to parent(HomeWindow)
QWidget::mousePressEvent(e);
}
void OnroadWindow::offroadTransition(bool offroad) {
#ifdef ENABLE_MAPS
if (!offroad) {
if (map == nullptr && (uiState()->prime_type || !MAPBOX_TOKEN.isEmpty())) {
MapWindow * m = new MapWindow(get_mapbox_settings());
map = m;
QObject::connect(uiState(), &UIState::offroadTransition, m, &MapWindow::offroadTransition);
m->setFixedWidth(topWidget(this)->width() / 2);
split->insertWidget(0, m);
// Make map visible after adding to split
m->offroadTransition(offroad);
}
}
#endif
alerts->updateAlert({}, bg);
// update stream type
bool wide_cam = Params().getBool("WideCameraOnly");
nvg->setStreamType(wide_cam ? VISION_STREAM_WIDE_ROAD : VISION_STREAM_ROAD);
}
void OnroadWindow::paintEvent(QPaintEvent *event) {
QPainter p(this);
p.fillRect(rect(), QColor(bg.red(), bg.green(), bg.blue(), 255));
}
// ***** onroad widgets *****
// OnroadAlerts
void OnroadAlerts::updateAlert(const Alert &a, const QColor &color) {
if (!alert.equal(a) || color != bg) {
alert = a;
bg = color;
update();
}
}
void OnroadAlerts::paintEvent(QPaintEvent *event) {
if (alert.size == cereal::ControlsState::AlertSize::NONE) {
return;
}
static std::map<cereal::ControlsState::AlertSize, const int> alert_sizes = {
{cereal::ControlsState::AlertSize::SMALL, 271},
{cereal::ControlsState::AlertSize::MID, 420},
{cereal::ControlsState::AlertSize::FULL, height()},
};
int h = alert_sizes[alert.size];
QRect r = QRect(0, height() - h, width(), h);
QPainter p(this);
// draw background + gradient
p.setPen(Qt::NoPen);
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
p.setBrush(QBrush(bg));
p.drawRect(r);
QLinearGradient g(0, r.y(), 0, r.bottom());
g.setColorAt(0, QColor::fromRgbF(0, 0, 0, 0.05));
g.setColorAt(1, QColor::fromRgbF(0, 0, 0, 0.35));
p.setCompositionMode(QPainter::CompositionMode_DestinationOver);
p.setBrush(QBrush(g));
p.fillRect(r, g);
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
// text
const QPoint c = r.center();
p.setPen(QColor(0xff, 0xff, 0xff));
p.setRenderHint(QPainter::TextAntialiasing);
if (alert.size == cereal::ControlsState::AlertSize::SMALL) {
configFont(p, "Inter", 74, "SemiBold");
p.drawText(r, Qt::AlignCenter, alert.text1);
} else if (alert.size == cereal::ControlsState::AlertSize::MID) {
configFont(p, "Inter", 88, "Bold");
p.drawText(QRect(0, c.y() - 125, width(), 150), Qt::AlignHCenter | Qt::AlignTop, alert.text1);
configFont(p, "Inter", 66, "Regular");
p.drawText(QRect(0, c.y() + 21, width(), 90), Qt::AlignHCenter, alert.text2);
} else if (alert.size == cereal::ControlsState::AlertSize::FULL) {
bool l = alert.text1.length() > 15;
configFont(p, "Inter", l ? 132 : 177, "Bold");
p.drawText(QRect(0, r.y() + (l ? 240 : 270), width(), 600), Qt::AlignHCenter | Qt::TextWordWrap, alert.text1);
configFont(p, "Inter", 88, "Regular");
p.drawText(QRect(0, r.height() - (l ? 361 : 420), width(), 300), Qt::AlignHCenter | Qt::TextWordWrap, alert.text2);
}
}
// NvgWindow
NvgWindow::NvgWindow(VisionStreamType type, QWidget* parent) : fps_filter(UI_FREQ, 3, 1. / UI_FREQ), CameraViewWidget("camerad", type, true, parent) {
engage_img = loadPixmap("../assets/img_chffr_wheel.png", {img_size, img_size});
dm_img = loadPixmap("../assets/img_driver_face.png", {img_size, img_size});
}
void NvgWindow::updateState(const UIState &s) {
const int SET_SPEED_NA = 255;
const SubMaster &sm = *(s.sm);
const bool cs_alive = sm.alive("controlsState");
const bool nav_alive = sm.alive("navInstruction") && sm["navInstruction"].getValid();
const auto cs = sm["controlsState"].getControlsState();
// Handle older routes where vCruiseCluster is not set
float v_cruise = cs.getVCruiseCluster() == 0.0 ? cs.getVCruise() : cs.getVCruiseCluster();
float set_speed = cs_alive ? v_cruise : SET_SPEED_NA;
bool cruise_set = set_speed > 0 && (int)set_speed != SET_SPEED_NA;
if (cruise_set && !s.scene.is_metric) {
set_speed *= KM_TO_MILE;
}
// Handle older routes where vEgoCluster is not set
float v_ego;
if (sm["carState"].getCarState().getVEgoCluster() == 0.0 && !v_ego_cluster_seen) {
v_ego = sm["carState"].getCarState().getVEgo();
} else {
v_ego = sm["carState"].getCarState().getVEgoCluster();
v_ego_cluster_seen = true;
}
float cur_speed = cs_alive ? std::max<float>(0.0, v_ego) : 0.0;
cur_speed *= s.scene.is_metric ? MS_TO_KPH : MS_TO_MPH;
auto speed_limit_sign = sm["navInstruction"].getNavInstruction().getSpeedLimitSign();
float speed_limit = nav_alive ? sm["navInstruction"].getNavInstruction().getSpeedLimit() : 0.0;
speed_limit *= (s.scene.is_metric ? MS_TO_KPH : MS_TO_MPH);
setProperty("speedLimit", speed_limit);
setProperty("has_us_speed_limit", nav_alive && speed_limit_sign == cereal::NavInstruction::SpeedLimitSign::MUTCD);
setProperty("has_eu_speed_limit", nav_alive && speed_limit_sign == cereal::NavInstruction::SpeedLimitSign::VIENNA);
setProperty("is_cruise_set", cruise_set);
setProperty("is_metric", s.scene.is_metric);
setProperty("speed", cur_speed);
setProperty("setSpeed", set_speed);
setProperty("speedUnit", s.scene.is_metric ? tr("km/h") : tr("mph"));
setProperty("hideDM", cs.getAlertSize() != cereal::ControlsState::AlertSize::NONE);
setProperty("status", s.status);
// update engageability and DM icons at 2Hz
if (sm.frame % (UI_FREQ / 2) == 0) {
setProperty("engageable", cs.getEngageable() || cs.getEnabled());
setProperty("dmActive", sm["driverMonitoringState"].getDriverMonitoringState().getIsActiveMode());
setProperty("rightHandDM", sm["driverMonitoringState"].getDriverMonitoringState().getIsRHD());
}
if (s.scene.calibration_valid) {
CameraViewWidget::updateCalibration(s.scene.view_from_calib);
} else {
CameraViewWidget::updateCalibration(DEFAULT_CALIBRATION);
}
}
void NvgWindow::drawHud(QPainter &p) {
p.save();
// Header gradient
QLinearGradient bg(0, header_h - (header_h / 2.5), 0, header_h);
bg.setColorAt(0, QColor::fromRgbF(0, 0, 0, 0.45));
bg.setColorAt(1, QColor::fromRgbF(0, 0, 0, 0));
p.fillRect(0, 0, width(), header_h, bg);
QString speedLimitStr = (speedLimit > 1) ? QString::number(std::nearbyint(speedLimit)) : "";
QString speedStr = QString::number(std::nearbyint(speed));
QString setSpeedStr = is_cruise_set ? QString::number(std::nearbyint(setSpeed)) : "";
// Draw outer box + border to contain set speed and speed limit
int default_rect_width = 172;
int rect_width = default_rect_width;
if (is_metric || has_eu_speed_limit) rect_width = 200;
if (has_us_speed_limit && speedLimitStr.size() >= 3) rect_width = 223;
int rect_height = 204;
if (has_us_speed_limit) rect_height = 402;
else if (has_eu_speed_limit) rect_height = 392;
int top_radius = 32;
int bottom_radius = has_eu_speed_limit ? 100 : 32;
QRect set_speed_rect(60 + default_rect_width / 2 - rect_width / 2, 45, rect_width, rect_height);
p.setPen(QPen(whiteColor(75), 6));
p.setBrush(blackColor(166));
drawRoundedRect(p, set_speed_rect, top_radius, top_radius, bottom_radius, bottom_radius);
// Draw MAX
if (is_cruise_set) {
if (status == STATUS_DISENGAGED) {
p.setPen(whiteColor());
} else if (status == STATUS_OVERRIDE) {
p.setPen(QColor(0x91, 0x9b, 0x95, 0xff));
} else if (speedLimit > 0) {
p.setPen(interpColor(
setSpeed,
{speedLimit + 5, speedLimit + 15, speedLimit + 25},
{QColor(0x80, 0xd8, 0xa6, 0xff), QColor(0xff, 0xe4, 0xbf, 0xff), QColor(0xff, 0xbf, 0xbf, 0xff)}
));
} else {
p.setPen(QColor(0x80, 0xd8, 0xa6, 0xff));
}
} else {
p.setPen(QColor(0xa6, 0xa6, 0xa6, 0xff));
}
configFont(p, "Inter", 40, "SemiBold");
QRect max_rect = getTextRect(p, Qt::AlignCenter, tr("MAX"));
max_rect.moveCenter({set_speed_rect.center().x(), 0});
max_rect.moveTop(set_speed_rect.top() + 27);
p.drawText(max_rect, Qt::AlignCenter, tr("MAX"));
// Draw set speed
if (is_cruise_set) {
if (speedLimit > 0 && status != STATUS_DISENGAGED && status != STATUS_OVERRIDE) {
p.setPen(interpColor(
setSpeed,
{speedLimit + 5, speedLimit + 15, speedLimit + 25},
{whiteColor(), QColor(0xff, 0x95, 0x00, 0xff), QColor(0xff, 0x00, 0x00, 0xff)}
));
} else {
p.setPen(whiteColor());
}
} else {
p.setPen(QColor(0x72, 0x72, 0x72, 0xff));
}
configFont(p, "Inter", 90, "Bold");
QRect speed_rect = getTextRect(p, Qt::AlignCenter, setSpeedStr);
speed_rect.moveCenter({set_speed_rect.center().x(), 0});
speed_rect.moveTop(set_speed_rect.top() + 77);
p.drawText(speed_rect, Qt::AlignCenter, setSpeedStr);
// US/Canada (MUTCD style) sign
if (has_us_speed_limit) {
const int border_width = 6;
const int sign_width = rect_width - 24;
const int sign_height = 186;
// White outer square
QRect sign_rect_outer(set_speed_rect.left() + 12, set_speed_rect.bottom() - 11 - sign_height, sign_width, sign_height);
p.setPen(Qt::NoPen);
p.setBrush(whiteColor());
p.drawRoundedRect(sign_rect_outer, 24, 24);
// Smaller white square with black border
QRect sign_rect(sign_rect_outer.left() + 1.5 * border_width, sign_rect_outer.top() + 1.5 * border_width, sign_width - 3 * border_width, sign_height - 3 * border_width);
p.setPen(QPen(blackColor(), border_width));
p.setBrush(whiteColor());
p.drawRoundedRect(sign_rect, 16, 16);
// "SPEED"
configFont(p, "Inter", 28, "SemiBold");
QRect text_speed_rect = getTextRect(p, Qt::AlignCenter, tr("SPEED"));
text_speed_rect.moveCenter({sign_rect.center().x(), 0});
text_speed_rect.moveTop(sign_rect_outer.top() + 22);
p.drawText(text_speed_rect, Qt::AlignCenter, tr("SPEED"));
// "LIMIT"
QRect text_limit_rect = getTextRect(p, Qt::AlignCenter, tr("LIMIT"));
text_limit_rect.moveCenter({sign_rect.center().x(), 0});
text_limit_rect.moveTop(sign_rect_outer.top() + 51);
p.drawText(text_limit_rect, Qt::AlignCenter, tr("LIMIT"));
// Speed limit value
configFont(p, "Inter", 70, "Bold");
QRect speed_limit_rect = getTextRect(p, Qt::AlignCenter, speedLimitStr);
speed_limit_rect.moveCenter({sign_rect.center().x(), 0});
speed_limit_rect.moveTop(sign_rect_outer.top() + 85);
p.drawText(speed_limit_rect, Qt::AlignCenter, speedLimitStr);
}
// EU (Vienna style) sign
if (has_eu_speed_limit) {
int outer_radius = 176 / 2;
int inner_radius_1 = outer_radius - 6; // White outer border
int inner_radius_2 = inner_radius_1 - 20; // Red circle
// Draw white circle with red border
QPoint center(set_speed_rect.center().x() + 1, set_speed_rect.top() + 204 + outer_radius);
p.setPen(Qt::NoPen);
p.setBrush(whiteColor());
p.drawEllipse(center, outer_radius, outer_radius);
p.setBrush(QColor(255, 0, 0, 255));
p.drawEllipse(center, inner_radius_1, inner_radius_1);
p.setBrush(whiteColor());
p.drawEllipse(center, inner_radius_2, inner_radius_2);
// Speed limit value
int font_size = (speedLimitStr.size() >= 3) ? 60 : 70;
configFont(p, "Inter", font_size, "Bold");
QRect speed_limit_rect = getTextRect(p, Qt::AlignCenter, speedLimitStr);
speed_limit_rect.moveCenter(center);
p.setPen(blackColor());
p.drawText(speed_limit_rect, Qt::AlignCenter, speedLimitStr);
}
// current speed
configFont(p, "Inter", 176, "Bold");
drawText(p, rect().center().x(), 210, speedStr);
configFont(p, "Inter", 66, "Regular");
drawText(p, rect().center().x(), 290, speedUnit, 200);
// engage-ability icon
if (engageable) {
drawIcon(p, rect().right() - radius / 2 - bdr_s * 2, radius / 2 + int(bdr_s * 1.5),
engage_img, bg_colors[status], 1.0);
}
// dm icon
if (!hideDM) {
int dm_icon_x = rightHandDM ? rect().right() - radius / 2 - (bdr_s * 2) : radius / 2 + (bdr_s * 2);
drawIcon(p, dm_icon_x, rect().bottom() - footer_h / 2,
dm_img, blackColor(70), dmActive ? 1.0 : 0.2);
}
p.restore();
}
void NvgWindow::drawText(QPainter &p, int x, int y, const QString &text, int alpha) {
QRect real_rect = getTextRect(p, 0, text);
real_rect.moveCenter({x, y - real_rect.height() / 2});
p.setPen(QColor(0xff, 0xff, 0xff, alpha));
p.drawText(real_rect.x(), real_rect.bottom(), text);
}
void NvgWindow::drawIcon(QPainter &p, int x, int y, QPixmap &img, QBrush bg, float opacity) {
p.setPen(Qt::NoPen);
p.setBrush(bg);
p.drawEllipse(x - radius / 2, y - radius / 2, radius, radius);
p.setOpacity(opacity);
p.drawPixmap(x - img_size / 2, y - img_size / 2, img);
}
void NvgWindow::initializeGL() {
CameraViewWidget::initializeGL();
qInfo() << "OpenGL version:" << QString((const char*)glGetString(GL_VERSION));
qInfo() << "OpenGL vendor:" << QString((const char*)glGetString(GL_VENDOR));
qInfo() << "OpenGL renderer:" << QString((const char*)glGetString(GL_RENDERER));
qInfo() << "OpenGL language version:" << QString((const char*)glGetString(GL_SHADING_LANGUAGE_VERSION));
prev_draw_t = millis_since_boot();
setBackgroundColor(bg_colors[STATUS_DISENGAGED]);
}
void NvgWindow::updateFrameMat() {
CameraViewWidget::updateFrameMat();
UIState *s = uiState();
int w = width(), h = height();
s->fb_w = w;
s->fb_h = h;
// Apply transformation such that video pixel coordinates match video
// 1) Put (0, 0) in the middle of the video
// 2) Apply same scaling as video
// 3) Put (0, 0) in top left corner of video
s->car_space_transform.reset();
s->car_space_transform.translate(w / 2 - x_offset, h / 2 - y_offset)
.scale(zoom, zoom)
.translate(-intrinsic_matrix.v[2], -intrinsic_matrix.v[5]);
}
void NvgWindow::drawLaneLines(QPainter &painter, const UIState *s) {
painter.save();
const UIScene &scene = s->scene;
// lanelines
for (int i = 0; i < std::size(scene.lane_line_vertices); ++i) {
painter.setBrush(QColor::fromRgbF(1.0, 1.0, 1.0, std::clamp<float>(scene.lane_line_probs[i], 0.0, 0.7)));
painter.drawPolygon(scene.lane_line_vertices[i]);
}
// road edges
for (int i = 0; i < std::size(scene.road_edge_vertices); ++i) {
painter.setBrush(QColor::fromRgbF(1.0, 0, 0, std::clamp<float>(1.0 - scene.road_edge_stds[i], 0.0, 1.0)));
painter.drawPolygon(scene.road_edge_vertices[i]);
}
// paint path
QLinearGradient bg(0, height(), 0, height() / 4);
const auto &orientation = (*s->sm)["modelV2"].getModelV2().getOrientation();
float orientation_future = 0;
if (orientation.getZ().size() > 16) {
orientation_future = std::abs(orientation.getZ()[16]); // 2.5 seconds
}
// straight: 112, in turns: 70
float curve_hue = fmax(70, 112 - (orientation_future * 420));
// FIXME: painter.drawPolygon can be slow if hue is not rounded
curve_hue = int(curve_hue * 100 + 0.5) / 100;
bg.setColorAt(0.0, QColor::fromHslF(148 / 360., 0.94, 0.51, 0.4));
bg.setColorAt(0.75 / 1.5, QColor::fromHslF(curve_hue / 360., 1.0, 0.68, 0.35));
bg.setColorAt(1.0, QColor::fromHslF(curve_hue / 360., 1.0, 0.68, 0.0));
painter.setBrush(bg);
painter.drawPolygon(scene.track_vertices);
painter.restore();
}
void NvgWindow::drawLead(QPainter &painter, const cereal::ModelDataV2::LeadDataV3::Reader &lead_data, const QPointF &vd) {
painter.save();
const float speedBuff = 10.;
const float leadBuff = 40.;
const float d_rel = lead_data.getX()[0];
const float v_rel = lead_data.getV()[0];
float fillAlpha = 0;
if (d_rel < leadBuff) {
fillAlpha = 255 * (1.0 - (d_rel / leadBuff));
if (v_rel < 0) {
fillAlpha += 255 * (-1 * (v_rel / speedBuff));
}
fillAlpha = (int)(fmin(fillAlpha, 255));
}
float sz = std::clamp((25 * 30) / (d_rel / 3 + 30), 15.0f, 30.0f) * 2.35;
float x = std::clamp((float)vd.x(), 0.f, width() - sz / 2);
float y = std::fmin(height() - sz * .6, (float)vd.y());
float g_xo = sz / 5;
float g_yo = sz / 10;
QPointF glow[] = {{x + (sz * 1.35) + g_xo, y + sz + g_yo}, {x, y - g_yo}, {x - (sz * 1.35) - g_xo, y + sz + g_yo}};
painter.setBrush(QColor(218, 202, 37, 255));
painter.drawPolygon(glow, std::size(glow));
// chevron
QPointF chevron[] = {{x + (sz * 1.25), y + sz}, {x, y}, {x - (sz * 1.25), y + sz}};
painter.setBrush(redColor(fillAlpha));
painter.drawPolygon(chevron, std::size(chevron));
painter.restore();
}
void NvgWindow::paintGL() {
UI: draw camera on same frame from modelV2 (#24335) * draw camera on same frame from modelV2 * fix reversing * optimze * sleep shorter * heavy debugging * clean up * fix ui hang * try this * more generic implementation * add unused flag back * draw latest frames when camerad is coming up with no modeld * only get modelV2 once * fix drawing * conflate, reduce buffer, and remove special case when starting * make tests pass * remove comments * frame_id is a uint32_t * not sure why passing to cameraview causes overflow * ternary, not too complicated * change to size * rename to frame * use unique_ptr * Revert "use unique_ptr" This reverts commit 955842d9511a26468d4deedd1807f096540cb40c. * Assert buffer size Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> * use one deque with pairs and uint32_t * formatting * frame offset * Revert "frame offset" This reverts commit a2cff8a2d57a02f314d9f6adb7221b193a150e4c. * use array * add prints * Revert "add prints" This reverts commit d6978746e5c316fb2d5a619091c9aaf849c31967. * clean up * this handles all cases * we want to clip * fixes going backwards when replay or modeld lags multiple frames, then skips multiple frames fixes going backwards when replay or modeld lags multiple frames, then skips multiple frames * fix rare case where camera is behind model simpler comment * draw latest frames if we start with no model, then hang on current frame until model catches up fix * store if it's updated * accurate comment * reset to latest on connect and showevent * better order * use quint32 for sending signal function * use empty * draft * kinda works * works * one line * debug * clean up * revert this * to preserve behavior, think we need to poll these * revert * no timeout when modeld is not alive * Update selfdrive/ui/qt/onroad.cc * changes from other PR * see if we're drawing dup model or camera frames * looks good, just need to clean up * debug * clean up * clean up * revert these changes * fix * pretty simple, test on device * clean up * revert this Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> old-commit-hash: c10a2ef2e40a49b527ab49b8b7fd4e924b847a2d
3 years ago
UIState *s = uiState();
const cereal::ModelDataV2::Reader &model = (*s->sm)["modelV2"].getModelV2();
CameraViewWidget::setFrameId(model.getFrameId());
CameraViewWidget::paintGL();
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(Qt::NoPen);
if (s->worldObjectsVisible()) {
drawLaneLines(painter, s);
if (s->scene.longitudinal_control) {
UI: draw camera on same frame from modelV2 (#24335) * draw camera on same frame from modelV2 * fix reversing * optimze * sleep shorter * heavy debugging * clean up * fix ui hang * try this * more generic implementation * add unused flag back * draw latest frames when camerad is coming up with no modeld * only get modelV2 once * fix drawing * conflate, reduce buffer, and remove special case when starting * make tests pass * remove comments * frame_id is a uint32_t * not sure why passing to cameraview causes overflow * ternary, not too complicated * change to size * rename to frame * use unique_ptr * Revert "use unique_ptr" This reverts commit 955842d9511a26468d4deedd1807f096540cb40c. * Assert buffer size Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> * use one deque with pairs and uint32_t * formatting * frame offset * Revert "frame offset" This reverts commit a2cff8a2d57a02f314d9f6adb7221b193a150e4c. * use array * add prints * Revert "add prints" This reverts commit d6978746e5c316fb2d5a619091c9aaf849c31967. * clean up * this handles all cases * we want to clip * fixes going backwards when replay or modeld lags multiple frames, then skips multiple frames fixes going backwards when replay or modeld lags multiple frames, then skips multiple frames * fix rare case where camera is behind model simpler comment * draw latest frames if we start with no model, then hang on current frame until model catches up fix * store if it's updated * accurate comment * reset to latest on connect and showevent * better order * use quint32 for sending signal function * use empty * draft * kinda works * works * one line * debug * clean up * revert this * to preserve behavior, think we need to poll these * revert * no timeout when modeld is not alive * Update selfdrive/ui/qt/onroad.cc * changes from other PR * see if we're drawing dup model or camera frames * looks good, just need to clean up * debug * clean up * clean up * revert these changes * fix * pretty simple, test on device * clean up * revert this Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> old-commit-hash: c10a2ef2e40a49b527ab49b8b7fd4e924b847a2d
3 years ago
const auto leads = model.getLeadsV3();
if (leads[0].getProb() > .5) {
drawLead(painter, leads[0], s->scene.lead_vertices[0]);
}
if (leads[1].getProb() > .5 && (std::abs(leads[1].getX()[0] - leads[0].getX()[0]) > 3.0)) {
drawLead(painter, leads[1], s->scene.lead_vertices[1]);
}
}
}
drawHud(painter);
double cur_draw_t = millis_since_boot();
double dt = cur_draw_t - prev_draw_t;
double fps = fps_filter.update(1. / dt * 1000);
if (fps < 15) {
LOGW("slow frame rate: %.2f fps", fps);
}
prev_draw_t = cur_draw_t;
}
void NvgWindow::showEvent(QShowEvent *event) {
CameraViewWidget::showEvent(event);
ui_update_params(uiState());
prev_draw_t = millis_since_boot();
}