diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc
index e19760f2e..ca58282a3 100644
--- a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc
+++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc
@@ -25,21 +25,28 @@ VisualsPanel::VisualsPanel(QWidget *parent) : QWidget(parent) {
"BlindSpot",
tr("Show Blind Spot Warnings"),
tr("Enabling this will display warnings when a vehicle is detected in your blind spot as long as your car has BSM supported."),
- "../assets/offroad/icon_monitoring.png",
+ "",
false,
},
{
"RainbowMode",
tr("Enable Tesla Rainbow Mode"),
RainbowizeWords(tr("A beautiful rainbow effect on the path the model wants to take.")) + "
" + tr("It")+ " " + tr("does not") + " " + tr("affect driving in any way.") + "",
- "../assets/offroad/icon_monitoring.png",
+ "",
false,
},
{
"StandstillTimer",
tr("Enable Standstill Timer"),
tr("Show a timer on the HUD when the car is at a standstill."),
- "../assets/offroad/icon_monitoring.png",
+ "",
+ false,
+ },
+ {
+ "RoadName",
+ tr("Display Road Name"),
+ tr("Displays the name of the road the car is traveling on. The OpenStreetMap database of the location must be downloaded from the OSM panel to fetch the road name."),
+ "",
false,
},
};
diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc
index 71bdd92ca..991710bbf 100644
--- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc
+++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc
@@ -32,7 +32,9 @@ void HudRendererSP::updateState(const UIState &s) {
speedLimit = lp_sp.getSpeedLimit().getResolver().getSpeedLimit() * speedConv;
speedLimitOffset = lp_sp.getSpeedLimit().getResolver().getSpeedLimitOffset() * speedConv;
speedLimitMode = static_cast(s.scene.speed_limit_mode);
+ roadName = s.scene.road_name;
if (sm.updated("liveMapDataSP")) {
+ roadNameStr = QString::fromStdString(lmd.getRoadName());
speedLimitAheadValid = lmd.getSpeedLimitAheadValid();
speedLimitAhead = lmd.getSpeedLimitAhead() * speedConv;
speedLimitAheadDistance = lmd.getSpeedLimitAheadDistance();
@@ -138,6 +140,9 @@ void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) {
drawSpeedLimitSigns(p);
drawUpcomingSpeedLimit(p);
}
+
+ // Road Name
+ drawRoadName(p, surface_rect);
}
}
@@ -516,3 +521,33 @@ void HudRendererSP::drawUpcomingSpeedLimit(QPainter &p) {
p.setPen(QColor(180, 180, 180, 255));
p.drawText(ahead_rect.adjusted(0, 110, 0, 0), Qt::AlignTop | Qt::AlignHCenter, distanceStr);
}
+
+void HudRendererSP::drawRoadName(QPainter &p, const QRect &surface_rect) {
+ if (!roadName || roadNameStr.isEmpty()) return;
+
+ // Measure text to size container
+ p.setFont(InterFont(40, QFont::Normal));
+ QFontMetrics fm(p.font());
+
+ int text_width = fm.horizontalAdvance(roadNameStr);
+ int padding = 40;
+ int rect_width = text_width + padding;
+
+ // Constrain to reasonable bounds
+ int min_width = 200;
+ int max_width = surface_rect.width() - 40;
+ rect_width = std::max(min_width, std::min(rect_width, max_width));
+
+ // Center at top of screen
+ QRect road_rect(surface_rect.width() / 2 - rect_width / 2, -6, rect_width, 60);
+
+ p.setPen(Qt::NoPen);
+ p.setBrush(QColor(0, 0, 0, 120));
+ p.drawRoundedRect(road_rect, 12, 12);
+
+ p.setPen(QColor(255, 255, 255, 200));
+
+ // Truncate if still too long
+ QString truncated = fm.elidedText(roadNameStr, Qt::ElideRight, road_rect.width() - 20);
+ p.drawText(road_rect, Qt::AlignCenter, truncated);
+}
diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.h b/selfdrive/ui/sunnypilot/qt/onroad/hud.h
index d76eb0606..073780bc1 100644
--- a/selfdrive/ui/sunnypilot/qt/onroad/hud.h
+++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.h
@@ -31,6 +31,7 @@ private:
void drawSmartCruiseControlOnroadIcon(QPainter &p, const QRect &surface_rect, int x_offset, int y_offset, std::string name);
void drawSpeedLimitSigns(QPainter &p);
void drawUpcomingSpeedLimit(QPainter &p);
+ void drawRoadName(QPainter &p, const QRect &surface_rect);
bool lead_status;
float lead_d_rel;
@@ -74,4 +75,6 @@ private:
float speedLimitAheadDistancePrev;
int speedLimitAheadValidFrame;
SpeedLimitMode speedLimitMode = SpeedLimitMode::OFF;
+ bool roadName;
+ QString roadNameStr;
};
diff --git a/selfdrive/ui/sunnypilot/ui.cc b/selfdrive/ui/sunnypilot/ui.cc
index 7b582a834..9acf84408 100644
--- a/selfdrive/ui/sunnypilot/ui.cc
+++ b/selfdrive/ui/sunnypilot/ui.cc
@@ -54,6 +54,7 @@ void ui_update_params_sp(UIStateSP *s) {
s->scene.dev_ui_info = std::atoi(params.get("DevUIInfo").c_str());
s->scene.standstill_timer = params.getBool("StandstillTimer");
s->scene.speed_limit_mode = std::atoi(params.get("SpeedLimitMode").c_str());
+ s->scene.road_name = params.getBool("RoadName");
}
DeviceSP::DeviceSP(QObject *parent) : Device(parent) {
diff --git a/selfdrive/ui/sunnypilot/ui_scene.h b/selfdrive/ui/sunnypilot/ui_scene.h
index 69cebd6d7..768cc5d7a 100644
--- a/selfdrive/ui/sunnypilot/ui_scene.h
+++ b/selfdrive/ui/sunnypilot/ui_scene.h
@@ -11,4 +11,5 @@ typedef struct UISceneSP : UIScene {
int dev_ui_info = 0;
bool standstill_timer = false;
int speed_limit_mode = 0;
+ bool road_name = false;
} UISceneSP;