Stylistic map UIs and MapBox styles

Fancied up the map in the onroad UI and added toggles to use a custom MapBox style when using "Navigate on openpilot",

Co-Authored-By: mike8643 <98910897+mike8643@users.noreply.github.com>
Co-Authored-By: pencilpusher <83676301+jakethesnake420@users.noreply.github.com>
Co-Authored-By: multikyd <72329880+multikyd@users.noreply.github.com>
This commit is contained in:
FrogAi
2024-02-27 16:34:47 -07:00
parent 61e9b1cd45
commit c250a933be
8 changed files with 141 additions and 13 deletions

View File

@@ -313,6 +313,7 @@ std::unordered_map<std::string, uint32_t> keys = {
{"MapsSelected", PERSISTENT}, {"MapsSelected", PERSISTENT},
{"MapSpeedLimit", PERSISTENT}, {"MapSpeedLimit", PERSISTENT},
{"MapSpeedLimitControl", PERSISTENT}, {"MapSpeedLimitControl", PERSISTENT},
{"MapStyle", PERSISTENT},
{"MapTargetLatA", PERSISTENT}, {"MapTargetLatA", PERSISTENT},
{"MapTargetVelocities", PERSISTENT}, {"MapTargetVelocities", PERSISTENT},
{"Model", PERSISTENT}, {"Model", PERSISTENT},

View File

@@ -53,6 +53,7 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot
{"DriveStats", "Drive Stats In Home Screen", "Display your device's drive stats in the home screen.", ""}, {"DriveStats", "Drive Stats In Home Screen", "Display your device's drive stats in the home screen.", ""},
{"FullMap", "Full Sized Map", "Maximize the size of the map in the onroad UI.", ""}, {"FullMap", "Full Sized Map", "Maximize the size of the map in the onroad UI.", ""},
{"HideSpeed", "Hide Speed", "Hide the speed indicator in the onroad UI. Additional toggle allows it to be hidden/shown via tapping the speed itself.", ""}, {"HideSpeed", "Hide Speed", "Hide the speed indicator in the onroad UI. Additional toggle allows it to be hidden/shown via tapping the speed itself.", ""},
{"MapStyle", "Map Style", "Use a custom map style to be used for 'Navigate on openpilot'.", ""},
{"ScreenManagement", "Screen Management", "Manage your screen's brightness, timeout settings, and hide specific onroad UI elements.", "../frogpilot/assets/toggle_icons/icon_light.png"}, {"ScreenManagement", "Screen Management", "Manage your screen's brightness, timeout settings, and hide specific onroad UI elements.", "../frogpilot/assets/toggle_icons/icon_light.png"},
{"HideUIElements", "Hide UI Elements", "Hide the selected UI elements from the onroad screen.", ""}, {"HideUIElements", "Hide UI Elements", "Hide the selected UI elements from the onroad screen.", ""},
@@ -172,12 +173,46 @@ FrogPilotVisualsPanel::FrogPilotVisualsPanel(SettingsWindow *parent) : FrogPilot
for (auto &[key, toggle] : toggles) { for (auto &[key, toggle] : toggles) {
toggle->setVisible(qolKeys.find(key.c_str()) != qolKeys.end()); toggle->setVisible(qolKeys.find(key.c_str()) != qolKeys.end());
} }
mapStyleButton->setVisible(true);
}); });
toggle = qolToggle; toggle = qolToggle;
} else if (param == "HideSpeed") { } else if (param == "HideSpeed") {
std::vector<QString> hideSpeedToggles{"HideSpeedUI"}; std::vector<QString> hideSpeedToggles{"HideSpeedUI"};
std::vector<QString> hideSpeedToggleNames{tr("Control Via UI")}; std::vector<QString> hideSpeedToggleNames{tr("Control Via UI")};
toggle = new FrogPilotParamToggleControl(param, title, desc, icon, hideSpeedToggles, hideSpeedToggleNames); toggle = new FrogPilotParamToggleControl(param, title, desc, icon, hideSpeedToggles, hideSpeedToggleNames);
} else if (param == "MapStyle") {
QMap<int, QString> styleMap = {
{0, tr("Stock openpilot")},
{1, tr("Mapbox Streets")},
{2, tr("Mapbox Outdoors")},
{3, tr("Mapbox Light")},
{4, tr("Mapbox Dark")},
{5, tr("Mapbox Satellite")},
{6, tr("Mapbox Satellite Streets")},
{7, tr("Mapbox Navigation Day")},
{8, tr("Mapbox Navigation Night")},
{9, tr("Mapbox Traffic Night")},
{10, tr("mike854's (Satellite hybrid)")},
};
QStringList styles = styleMap.values();
mapStyleButton = new ButtonControl(title, tr("SELECT"), desc);
QObject::connect(mapStyleButton, &ButtonControl::clicked, this, [this, styleMap]() {
QStringList styles = styleMap.values();
QString selection = MultiOptionDialog::getSelection(tr("Select a map style"), styles, "", this);
if (!selection.isEmpty()) {
int selectedStyle = styleMap.key(selection);
params.putInt("MapStyle", selectedStyle);
mapStyleButton->setValue(selection);
updateToggles();
}
});
int currentStyle = params.getInt("MapStyle");
mapStyleButton->setValue(styleMap[currentStyle]);
addItem(mapStyleButton);
} else if (param == "ScreenManagement") { } else if (param == "ScreenManagement") {
FrogPilotParamManageControl *screenToggle = new FrogPilotParamManageControl(param, title, desc, icon, this); FrogPilotParamManageControl *screenToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
@@ -307,14 +342,20 @@ void FrogPilotVisualsPanel::updateMetric() {
} }
void FrogPilotVisualsPanel::parentToggleClicked() { void FrogPilotVisualsPanel::parentToggleClicked() {
mapStyleButton->setVisible(false);
openParentToggle(); openParentToggle();
} }
void FrogPilotVisualsPanel::subParentToggleClicked() { void FrogPilotVisualsPanel::subParentToggleClicked() {
mapStyleButton->setVisible(false);
openSubParentToggle(); openSubParentToggle();
} }
void FrogPilotVisualsPanel::hideSubToggles() { void FrogPilotVisualsPanel::hideSubToggles() {
mapStyleButton->setVisible(false);
for (auto &[key, toggle] : toggles) { for (auto &[key, toggle] : toggles) {
bool subToggles = alertVolumeControlKeys.find(key.c_str()) != alertVolumeControlKeys.end() || bool subToggles = alertVolumeControlKeys.find(key.c_str()) != alertVolumeControlKeys.end() ||
customAlertsKeys.find(key.c_str()) != customAlertsKeys.end() || customAlertsKeys.find(key.c_str()) != customAlertsKeys.end() ||

View File

@@ -28,12 +28,14 @@ private:
void updateState(const UIState &s); void updateState(const UIState &s);
void updateToggles(); void updateToggles();
ButtonControl *mapStyleButton;
std::set<QString> alertVolumeControlKeys = {"EngageVolume", "DisengageVolume", "RefuseVolume", "PromptVolume", "PromptDistractedVolume", "WarningSoftVolume", "WarningImmediateVolume"}; std::set<QString> alertVolumeControlKeys = {"EngageVolume", "DisengageVolume", "RefuseVolume", "PromptVolume", "PromptDistractedVolume", "WarningSoftVolume", "WarningImmediateVolume"};
std::set<QString> customAlertsKeys = {"GreenLightAlert", "LeadDepartingAlert", "LoudBlindspotAlert", "SpeedLimitChangedAlert"}; std::set<QString> customAlertsKeys = {"GreenLightAlert", "LeadDepartingAlert", "LoudBlindspotAlert", "SpeedLimitChangedAlert"};
std::set<QString> customOnroadUIKeys = {"AccelerationPath", "AdjacentPath", "BlindSpotPath", "FPSCounter", "LeadInfo", "PedalsOnUI", "RoadNameUI"}; std::set<QString> customOnroadUIKeys = {"AccelerationPath", "AdjacentPath", "BlindSpotPath", "FPSCounter", "LeadInfo", "PedalsOnUI", "RoadNameUI"};
std::set<QString> customThemeKeys = {"HolidayThemes", "CustomColors", "CustomIcons", "CustomSignals", "CustomSounds"}; std::set<QString> customThemeKeys = {"HolidayThemes", "CustomColors", "CustomIcons", "CustomSignals", "CustomSounds"};
std::set<QString> modelUIKeys = {"DynamicPathWidth", "HideLeadMarker", "LaneLinesWidth", "PathEdgeWidth", "PathWidth", "RoadEdgesWidth", "UnlimitedLength"}; std::set<QString> modelUIKeys = {"DynamicPathWidth", "HideLeadMarker", "LaneLinesWidth", "PathEdgeWidth", "PathWidth", "RoadEdgesWidth", "UnlimitedLength"};
std::set<QString> qolKeys = {"DriveStats", "FullMap", "HideSpeed"}; std::set<QString> qolKeys = {"DriveStats", "FullMap", "HideSpeed", "MapStyle"};
std::set<QString> screenKeys = {"HideUIElements", "ScreenBrightness", "ScreenBrightnessOnroad", "ScreenRecorder", "ScreenTimeout", "ScreenTimeoutOnroad", "StandbyMode"}; std::set<QString> screenKeys = {"HideUIElements", "ScreenBrightness", "ScreenBrightnessOnroad", "ScreenRecorder", "ScreenTimeout", "ScreenTimeoutOnroad", "StandbyMode"};
std::map<std::string, ParamControl*> toggles; std::map<std::string, ParamControl*> toggles;

0
selfdrive/manager/manager.py Executable file → Normal file
View File

View File

@@ -54,17 +54,6 @@ MapWindow::~MapWindow() {
void MapWindow::initLayers() { void MapWindow::initLayers() {
// This doesn't work from initializeGL // This doesn't work from initializeGL
if (!m_map->layerExists("modelPathLayer")) {
qDebug() << "Initializing modelPathLayer";
QVariantMap modelPath;
//modelPath["id"] = "modelPathLayer";
modelPath["type"] = "line";
modelPath["source"] = "modelPathSource";
m_map->addLayer("modelPathLayer", modelPath);
m_map->setPaintProperty("modelPathLayer", "line-color", QColor("red"));
m_map->setPaintProperty("modelPathLayer", "line-width", 5.0);
m_map->setLayoutProperty("modelPathLayer", "line-cap", "round");
}
if (!m_map->layerExists("navLayer")) { if (!m_map->layerExists("navLayer")) {
qDebug() << "Initializing navLayer"; qDebug() << "Initializing navLayer";
QVariantMap nav; QVariantMap nav;
@@ -79,6 +68,17 @@ void MapWindow::initLayers() {
m_map->setPaintProperty("navLayer", "line-width", 7.5); m_map->setPaintProperty("navLayer", "line-width", 7.5);
m_map->setLayoutProperty("navLayer", "line-cap", "round"); m_map->setLayoutProperty("navLayer", "line-cap", "round");
} }
if (!m_map->layerExists("modelPathLayer")) {
qDebug() << "Initializing modelPathLayer";
QVariantMap modelPath;
//modelPath["id"] = "modelPathLayer";
modelPath["type"] = "line";
modelPath["source"] = "modelPathSource";
m_map->addLayer("modelPathLayer", modelPath);
m_map->setPaintProperty("modelPathLayer", "line-color", QColor("red"));
m_map->setPaintProperty("modelPathLayer", "line-width", 5.0);
m_map->setLayoutProperty("modelPathLayer", "line-cap", "round");
}
if (!m_map->layerExists("pinLayer")) { if (!m_map->layerExists("pinLayer")) {
qDebug() << "Initializing pinLayer"; qDebug() << "Initializing pinLayer";
m_map->addImage("default_marker", QImage("../assets/navigation/default_marker.svg")); m_map->addImage("default_marker", QImage("../assets/navigation/default_marker.svg"));
@@ -109,6 +109,50 @@ void MapWindow::initLayers() {
// TODO: remove, symbol-sort-key does not seem to matter outside of each layer // TODO: remove, symbol-sort-key does not seem to matter outside of each layer
m_map->setLayoutProperty("carPosLayer", "symbol-sort-key", 0); m_map->setLayoutProperty("carPosLayer", "symbol-sort-key", 0);
} }
if (!m_map->layerExists("buildingsLayer")) {
qDebug() << "Initializing buildingsLayer";
QVariantMap buildings;
buildings["id"] = "buildingsLayer";
buildings["source"] = "composite";
buildings["source-layer"] = "building";
buildings["type"] = "fill-extrusion";
buildings["minzoom"] = 15;
m_map->addLayer("buildingsLayer", buildings);
m_map->setFilter("buildingsLayer", QVariantList({"==", "extrude", "true"}));
QVariantList fillExtrusionHight = {
"interpolate",
QVariantList{"linear"},
QVariantList{"zoom"},
15, 0,
15.05, QVariantList{"get", "height"}
};
QVariantList fillExtrusionBase = {
"interpolate",
QVariantList{"linear"},
QVariantList{"zoom"},
15, 0,
15.05, QVariantList{"get", "min_height"}
};
QVariantList fillExtrusionOpacity = {
"interpolate",
QVariantList{"linear"},
QVariantList{"zoom"},
15, 0,
15.5, .6,
17, .6,
20, 0
};
m_map->setPaintProperty("buildingsLayer", "fill-extrusion-color", QColor("grey"));
m_map->setPaintProperty("buildingsLayer", "fill-extrusion-opacity", fillExtrusionOpacity);
m_map->setPaintProperty("buildingsLayer", "fill-extrusion-height", fillExtrusionHight);
m_map->setPaintProperty("buildingsLayer", "fill-extrusion-base", fillExtrusionBase);
m_map->setLayoutProperty("buildingsLayer", "visibility", "visible");
}
} }
void MapWindow::updateState(const UIState &s) { void MapWindow::updateState(const UIState &s) {
@@ -151,6 +195,17 @@ void MapWindow::updateState(const UIState &s) {
velocity_filter.update(std::max(10.0, locationd_velocity.getValue()[0])); velocity_filter.update(std::max(10.0, locationd_velocity.getValue()[0]));
} }
} }
// Credit to jakethesnake420
if (loaded_once && (sm.rcv_frame("uiPlan") != model_rcv_frame)) {
auto locationd_location = sm["liveLocationKalman"].getLiveLocationKalman();
auto model_path = model_to_collection(locationd_location.getCalibratedOrientationECEF(), locationd_location.getPositionECEF(), sm["uiPlan"].getUiPlan().getPosition());
QMapLibre::Feature model_path_feature(QMapLibre::Feature::LineStringType, model_path, {}, {});
QVariantMap modelV2Path;
modelV2Path["type"] = "geojson";
modelV2Path["data"] = QVariant::fromValue<QMapLibre::Feature>(model_path_feature);
m_map->updateSource("modelPathSource", modelV2Path);
model_rcv_frame = sm.rcv_frame("uiPlan");
}
if (sm.updated("navRoute") && sm["navRoute"].getNavRoute().getCoordinates().size()) { if (sm.updated("navRoute") && sm["navRoute"].getNavRoute().getCoordinates().size()) {
auto nav_dest = coordinate_from_param("NavDestination"); auto nav_dest = coordinate_from_param("NavDestination");
@@ -237,6 +292,30 @@ void MapWindow::updateState(const UIState &s) {
route_rcv_frame = sm.rcv_frame("navRoute"); route_rcv_frame = sm.rcv_frame("navRoute");
updateDestinationMarker(); updateDestinationMarker();
} }
// Map Styling - Credit goes to OPKR!
int map_style = uiState()->scene.map_style;
if (map_style != previous_map_style) {
std::unordered_map<int, std::string> styleUrls = {
{0, "mapbox://styles/commaai/clkqztk0f00ou01qyhsa5bzpj"}, // Stock openpilot
{1, "mapbox://styles/mapbox/streets-v11"}, // Mapbox Streets
{2, "mapbox://styles/mapbox/outdoors-v11"}, // Mapbox Outdoors
{3, "mapbox://styles/mapbox/light-v10"}, // Mapbox Light
{4, "mapbox://styles/mapbox/dark-v10"}, // Mapbox Dark
{5, "mapbox://styles/mapbox/satellite-v9"}, // Mapbox Satellite
{6, "mapbox://styles/mapbox/satellite-streets-v11"}, // Mapbox Satellite Streets
{7, "mapbox://styles/mapbox/navigation-day-v1"}, // Mapbox Navigation Day
{8, "mapbox://styles/mapbox/navigation-night-v1"}, // Mapbox Navigation Night
{9, "mapbox://styles/mapbox/traffic-night-v2"}, // Mapbox Traffic Night
{10, "mapbox://styles/mike854/clt0hm8mw01ok01p4blkr27jp"}, // mike854's (Satellite hybrid)
};
std::unordered_map<int, std::string>::iterator it = styleUrls.find(map_style);
m_map->setStyleUrl(QString::fromStdString(it->second));
}
previous_map_style = map_style;
} }
void MapWindow::setError(const QString &err_str) { void MapWindow::setError(const QString &err_str) {

View File

@@ -77,10 +77,13 @@ private:
void clearRoute(); void clearRoute();
void updateDestinationMarker(); void updateDestinationMarker();
uint64_t route_rcv_frame = 0; uint64_t route_rcv_frame = 0;
uint64_t model_rcv_frame = 0;
// FrogPilot variables // FrogPilot variables
Params params; Params params;
int previous_map_style;
private slots: private slots:
void updateState(const UIState &s); void updateState(const UIState &s);

View File

@@ -368,6 +368,7 @@ void ui_update_frogpilot_params(UIState *s) {
scene.full_map = quality_of_life_visuals && params.getBool("FullMap"); scene.full_map = quality_of_life_visuals && params.getBool("FullMap");
scene.hide_speed = quality_of_life_visuals && params.getBool("HideSpeed"); scene.hide_speed = quality_of_life_visuals && params.getBool("HideSpeed");
scene.hide_speed_ui = scene.hide_speed && params.getBool("HideSpeedUI"); scene.hide_speed_ui = scene.hide_speed && params.getBool("HideSpeedUI");
scene.map_style = quality_of_life_visuals ? params.getInt("MapStyle") : 0;
scene.rotating_wheel = params.getBool("RotatingWheel"); scene.rotating_wheel = params.getBool("RotatingWheel");

View File

@@ -255,6 +255,7 @@ typedef struct UIScene {
int custom_icons; int custom_icons;
int custom_signals; int custom_signals;
int desired_follow; int desired_follow;
int map_style;
int obstacle_distance; int obstacle_distance;
int obstacle_distance_stock; int obstacle_distance_stock;
int screen_brightness; int screen_brightness;