diff --git a/common/params.cc b/common/params.cc index 08c728c9ed49ba..60f2baf41e49b6 100644 --- a/common/params.cc +++ b/common/params.cc @@ -214,6 +214,7 @@ std::unordered_map keys = { {"LQR", PERSISTENT}, {"ScreenOffTimer", PERSISTENT}, {"CruiseSpeedRewrite", PERSISTENT}, + {"DriverCamera", PERSISTENT}, }; } // namespace diff --git a/selfdrive/ui/qt/offroad/settings.cc b/selfdrive/ui/qt/offroad/settings.cc index 053f3db8ae1349..d5efa66f9e21ba 100644 --- a/selfdrive/ui/qt/offroad/settings.cc +++ b/selfdrive/ui/qt/offroad/settings.cc @@ -88,6 +88,13 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) { "openpilot will set its maximum speed to the vehicle's current speed."), "../assets/offroad/icon_cruise_speed_rewrite.png", }, + // DriverCamera, stolen from FrogPilot + { + "DriverCamera", + tr("Driver Camera On Reverse"), + tr("Displays the driver camera when in reverse."), + "../assets/img_driver_face_static.png", + }, { "IsMetric", tr("Use Metric System"), diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index 141bdc82d176cf..b5984300b4119a 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -189,7 +189,7 @@ void OnroadAlerts::updateAlert(const Alert &a) { } void OnroadAlerts::paintEvent(QPaintEvent *event) { - if (alert.size == cereal::ControlsState::AlertSize::NONE) { + if (alert.size == cereal::ControlsState::AlertSize::NONE || scene.show_driver_camera) { return; } static std::map alert_heights = { @@ -275,8 +275,10 @@ void ExperimentalButton::updateState(const UIState &s) { void ExperimentalButton::paintEvent(QPaintEvent *event) { QPainter p(this); QPixmap img = experimental_mode ? experimental_img : engage_img; - drawIcon(p, QPoint(btn_size / 2, btn_size / 2), img, QColor(0, 0, 0, 166), (isDown() || !engageable) ? 0.6 : 1.0); -} + if (!scene.show_driver_camera) { + drawIcon(p, QPoint(btn_size / 2, btn_size / 2), img, QColor(0, 0, 0, 166), (isDown() || !engageable) ? 0.6 : 1.0); + } +} scene.show_driver_camera // MapSettingsButton @@ -351,7 +353,7 @@ void AnnotatedCameraWidget::updateState(const UIState &s) { has_eu_speed_limit = (nav_alive && speed_limit_sign == cereal::NavInstruction::SpeedLimitSign::VIENNA); is_metric = s.scene.is_metric; speedUnit = s.scene.is_metric ? tr("km/h") : tr("mph"); - hideBottomIcons = (cs.getAlertSize() != cereal::ControlsState::AlertSize::NONE); + hideBottomIcons = (cs.getAlertSize() != cereal::ControlsState::AlertSize::NONE || showDriverCamera); status = s.status; // update engageability/experimental mode button @@ -363,7 +365,10 @@ void AnnotatedCameraWidget::updateState(const UIState &s) { rightHandDM = dm_state.getIsRHD(); // DM icon transition dm_fade_state = std::clamp(dm_fade_state+0.2*(0.5-dmActive), 0.0, 1.0); - + + // FrogPilot variables + showDriverCamera = scene.show_driver_camera; + // FrogPilot properties setProperty("drivingPersonalitiesUIWheel", s.scene.driving_personalities_ui_wheel); setProperty("personalityProfile", s.scene.personality_profile); @@ -688,7 +693,7 @@ void AnnotatedCameraWidget::paintGL() { // for replay of old routes, never go to widecam wide_cam_requested = wide_cam_requested && s->scene.calibration_wide_valid; } - CameraWidget::setStreamType(wide_cam_requested ? VISION_STREAM_WIDE_ROAD : VISION_STREAM_ROAD); + CameraWidget::setStreamType(showDriverCamera ? VISION_STREAM_DRIVER : wide_cam_requested ? VISION_STREAM_WIDE_ROAD : VISION_STREAM_ROAD); s->scene.wide_cam = CameraWidget::getStreamType() == VISION_STREAM_WIDE_ROAD; if (s->scene.calibration_valid) { @@ -705,36 +710,37 @@ void AnnotatedCameraWidget::paintGL() { painter.setRenderHint(QPainter::Antialiasing); painter.setPen(Qt::NoPen); - if (s->worldObjectsVisible()) { - if (sm.rcv_frame("modelV2") > s->scene.started_frame) { - update_model(s, model, sm["uiPlan"].getUiPlan()); - if (sm.rcv_frame("radarState") > s->scene.started_frame) { - update_leads(s, radar_state, model.getPosition()); + if (!showDriverCamera) { + if (s->worldObjectsVisible()) { + if (sm.rcv_frame("modelV2") > s->scene.started_frame) { + update_model(s, model, sm["uiPlan"].getUiPlan()); + if (sm.rcv_frame("radarState") > s->scene.started_frame) { + update_leads(s, radar_state, model.getPosition()); + } } - } - drawLaneLines(painter, s); - - if (s->scene.longitudinal_control) { - auto lead_one = radar_state.getLeadOne(); - auto lead_two = radar_state.getLeadTwo(); - if (lead_one.getStatus()) { - drawLead(painter, lead_one, s->scene.lead_vertices[0]); - } - if (lead_two.getStatus() && (std::abs(lead_one.getDRel() - lead_two.getDRel()) > 3.0)) { - drawLead(painter, lead_two, s->scene.lead_vertices[1]); + drawLaneLines(painter, s); + + if (s->scene.longitudinal_control) { + auto lead_one = radar_state.getLeadOne(); + auto lead_two = radar_state.getLeadTwo(); + if (lead_one.getStatus()) { + drawLead(painter, lead_one, s->scene.lead_vertices[0]); + } + if (lead_two.getStatus() && (std::abs(lead_one.getDRel() - lead_two.getDRel()) > 3.0)) { + drawLead(painter, lead_two, s->scene.lead_vertices[1]); + } } + + // DMoji + if (!hideBottomIcons && (sm.rcv_frame("driverStateV2") > s->scene.started_frame)) { + update_dmonitoring(s, sm["driverStateV2"].getDriverStateV2(), dm_fade_state, rightHandDM); + drawDriverState(painter, s); } - } - // DMoji - if (!hideBottomIcons && (sm.rcv_frame("driverStateV2") > s->scene.started_frame)) { - update_dmonitoring(s, sm["driverStateV2"].getDriverStateV2(), dm_fade_state, rightHandDM); - drawDriverState(painter, s); + drawHud(painter); } - 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); diff --git a/selfdrive/ui/qt/onroad.h b/selfdrive/ui/qt/onroad.h index bf2f562235bb05..dedf6bc8d42e85 100644 --- a/selfdrive/ui/qt/onroad.h +++ b/selfdrive/ui/qt/onroad.h @@ -108,6 +108,7 @@ class AnnotatedCameraWidget : public CameraWidget { // FrogPilot variables bool drivingPersonalitiesUIWheel; int personalityProfile; + bool showDriverCamera; QVector> profile_data; protected: diff --git a/selfdrive/ui/qt/widgets/cameraview.cc b/selfdrive/ui/qt/widgets/cameraview.cc index 6a5064e8ca2561..5243849f52b306 100644 --- a/selfdrive/ui/qt/widgets/cameraview.cc +++ b/selfdrive/ui/qt/widgets/cameraview.cc @@ -207,6 +207,7 @@ void CameraWidget::updateFrameMat() { if (active_stream_type == VISION_STREAM_DRIVER) { if (stream_width > 0 && stream_height > 0) { frame_mat = get_driver_view_transform(w, h, stream_width, stream_height); + frame_mat.v[0] *= -1.0; } } else { // Project point at "infinity" to compute x and y offsets diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index f23ce6f826880f..e5f996f0bde149 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -201,6 +201,12 @@ static void update_state(UIState *s) { if (sm.updated("carParams")) { scene.longitudinal_control = sm["carParams"].getCarParams().getOpenpilotLongitudinalControl(); } + if (sm.updated("carState")) { + const auto carState = sm["carState"].getCarState(); + if (scene.driver_camera) { + scene.show_driver_camera = carState.getGearShifter() == cereal::CarState::GearShifter::REVERSE; + } + } if (sm.updated("wideRoadCameraState")) { auto cam_state = sm["wideRoadCameraState"].getWideRoadCameraState(); float scale = (cam_state.getSensor() == cereal::FrameData::ImageSensor::AR0231) ? 6.0f : 1.0f; @@ -218,6 +224,7 @@ void ui_update_params(UIState *s) { // FrogPilot variables UIScene &scene = s->scene; scene.driving_personalities_ui_wheel = params.getBool("DrivingPersonalitiesUIWheel"); + scene.driver_camera = params.getBool("DriverCamera"); } void ui_live_update_params(UIState *s) { diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index da23c9b1a9b2a4..49707f713e7ff7 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -155,6 +155,8 @@ typedef struct UIScene { // FrogPilot variables int personality_profile; bool driving_personalities_ui_wheel; + bool driver_camera; + bool show_driver_camera; } UIScene;