diff --git a/common/params.cc b/common/params.cc index 2a4374e..50a3c07 100644 --- a/common/params.cc +++ b/common/params.cc @@ -245,6 +245,7 @@ std::unordered_map keys = { {"CustomTheme", PERSISTENT}, {"DeviceShutdown", PERSISTENT}, {"DisableOnroadUploads", PERSISTENT}, + {"DriverCamera", PERSISTENT}, {"FrogPilotTogglesUpdated", PERSISTENT}, {"GasRegenCmd", PERSISTENT}, {"GoatScream", PERSISTENT}, diff --git a/selfdrive/frogpilot/ui/visual_settings.cc b/selfdrive/frogpilot/ui/visual_settings.cc index c530c53..8cbe770 100644 --- a/selfdrive/frogpilot/ui/visual_settings.cc +++ b/selfdrive/frogpilot/ui/visual_settings.cc @@ -17,6 +17,8 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot {"ShowFPS", "FPS Counter", "Display the Frames Per Second (FPS) of your onroad UI for monitoring system performance.", ""}, {"LeadInfo", "Lead Info and Logics", "Get detailed information about the vehicle ahead, including speed and distance, and the logic behind your following distance.", ""}, + {"DriverCamera", "Driver Camera On Reverse", "Show the driver's camera feed when you shift to reverse.", "../assets/img_driver_face_static.png"}, + {"ModelUI", "Model UI", "Personalize how the model's visualizations appear on your screen.", "../assets/offroad/icon_calibration.png"}, {"AccelerationPath", "Acceleration Path", "Visualize the car's intended acceleration or deceleration with a color-coded path.", ""}, {"LaneLinesWidth", "Lane Lines", "Adjust the visual thickness of lane lines on your display.\n\nDefault matches the MUTCD average of 4 inches.", ""}, diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index f446b65..9db7f58 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -221,7 +221,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 = { @@ -337,7 +337,9 @@ void ExperimentalButton::paintEvent(QPaintEvent *event) { (scene.always_on_lateral_active ? QColor(10, 186, 181, 255) : QColor(0, 0, 0, 166)); - drawIcon(p, QPoint(btn_size / 2, btn_size / 2 + y_offset), img, background_color, (isDown() || (!engageable && !scene.always_on_lateral_active)) ? 0.6 : 1.0); + if (!scene.show_driver_camera) { + drawIcon(p, QPoint(btn_size / 2, btn_size / 2 + y_offset), img, background_color, (isDown() || (!engageable && !scene.always_on_lateral_active)) ? 0.6 : 1.0); + } } @@ -409,7 +411,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 || customSignals && (turnSignalLeft || turnSignalRight)); + hideBottomIcons = (cs.getAlertSize() != cereal::ControlsState::AlertSize::NONE || customSignals && (turnSignalLeft || turnSignalRight)) || showDriverCamera; status = s.status; // update engageability/experimental mode button @@ -904,7 +906,7 @@ void AnnotatedCameraWidget::paintGL() { wide_cam_requested = wide_cam_requested && s->scene.calibration_wide_valid; } paramsMemory.putBoolNonBlocking("WideCamera", wide_cam_requested); - CameraWidget::setStreamType(cameraView == 3 ? VISION_STREAM_DRIVER : + CameraWidget::setStreamType(showDriverCamera || cameraView == 3 ? VISION_STREAM_DRIVER : wide_cam_requested && cameraView != 1 ? VISION_STREAM_WIDE_ROAD : VISION_STREAM_ROAD); s->scene.wide_cam = CameraWidget::getStreamType() == VISION_STREAM_WIDE_ROAD; @@ -922,7 +924,7 @@ void AnnotatedCameraWidget::paintGL() { painter.setRenderHint(QPainter::Antialiasing); painter.setPen(Qt::NoPen); - if (s->scene.world_objects_visible) { + if (s->scene.world_objects_visible && !showDriverCamera) { update_model(s, model, sm["uiPlan"].getUiPlan()); drawLaneLines(painter, s); @@ -1027,26 +1029,29 @@ void AnnotatedCameraWidget::updateFrogPilotWidgets(QPainter &p) { mapOpen = scene.map_open; obstacleDistance = scene.obstacle_distance; obstacleDistanceStock = scene.obstacle_distance_stock; + showDriverCamera = scene.show_driver_camera; stoppedEquivalence = scene.stopped_equivalence; turnSignalLeft = scene.turn_signal_left; turnSignalRight = scene.turn_signal_right; useSI = scene.use_si; - if (leadInfo) { - drawLeadInfo(p); - } - - if (alwaysOnLateral || conditionalExperimental) { - drawStatusBar(p); - } - - if (customSignals && (turnSignalLeft || turnSignalRight)) { - if (!animationTimer->isActive()) { - animationTimer->start(totalFrames * 11); // 440 milliseconds per loop; syncs up perfectly with my 2019 Lexus ES 350 turn signal clicks + if (!showDriverCamera) { + if (leadInfo) { + drawLeadInfo(p); + } + + if (alwaysOnLateral || conditionalExperimental) { + drawStatusBar(p); + } + + if (customSignals && (turnSignalLeft || turnSignalRight)) { + if (!animationTimer->isActive()) { + animationTimer->start(totalFrames * 11); // 440 milliseconds per loop; syncs up perfectly with my 2019 Lexus ES 350 turn signal clicks + } + drawTurnSignals(p); + } else if (animationTimer->isActive()) { + animationTimer->stop(); } - drawTurnSignals(p); - } else if (animationTimer->isActive()) { - animationTimer->stop(); } map_settings_btn_bottom->setEnabled(map_settings_btn->isEnabled()); diff --git a/selfdrive/ui/qt/onroad.h b/selfdrive/ui/qt/onroad.h index c4f956f..0d14af0 100644 --- a/selfdrive/ui/qt/onroad.h +++ b/selfdrive/ui/qt/onroad.h @@ -135,6 +135,7 @@ private: bool experimentalMode; bool leadInfo; bool mapOpen; + bool showDriverCamera; bool turnSignalLeft; bool turnSignalRight; bool useSI; diff --git a/selfdrive/ui/qt/widgets/cameraview.cc b/selfdrive/ui/qt/widgets/cameraview.cc index 7b1f2f1..d7d52f9 100644 --- a/selfdrive/ui/qt/widgets/cameraview.cc +++ b/selfdrive/ui/qt/widgets/cameraview.cc @@ -217,6 +217,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 92b8687..e8f547c 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -222,6 +222,9 @@ static void update_state(UIState *s) { scene.turn_signal_left = carState.getLeftBlinker(); scene.turn_signal_right = carState.getRightBlinker(); } + if (scene.driver_camera) { + scene.show_driver_camera = carState.getGearShifter() == cereal::CarState::GearShifter::REVERSE; + } } if (sm.updated("controlsState")) { auto controlsState = sm["controlsState"].getControlsState(); @@ -301,6 +304,7 @@ void ui_update_params(UIState *s) { scene.road_edge_width = params.getInt("RoadEdgesWidth") * (scene.is_metric ? 1 : INCH_TO_CM) / 200; scene.unlimited_road_ui_length = scene.model_ui && params.getBool("UnlimitedLength"); + scene.driver_camera = params.getBool("DriverCamera"); scene.screen_brightness = params.getInt("ScreenBrightness"); scene.wheel_icon = params.getInt("WheelIcon"); } diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index e485636..4744829 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -179,11 +179,13 @@ typedef struct UIScene { bool conditional_experimental; bool custom_onroad_ui; bool custom_theme; + bool driver_camera; bool enabled; bool experimental_mode; bool lead_info; bool map_open; bool model_ui; + bool show_driver_camera; bool show_fps; bool turn_signal_left; bool turn_signal_right;