From 436ff5aa427f3d1e289188f1cf00271a44d2329c Mon Sep 17 00:00:00 2001 From: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Thu, 11 Dec 2025 23:40:33 -0800 Subject: [PATCH] ui: OSM panel (#1515) * param to control stock vs sp ui * init styles * SP Toggles * Lint * optimizations * sp raylib preview * fix callback * fix ui preview * dialog txt * compare vs what used to be done before InputDialog * merge origin raylib toggles * tree dialog * less trees for the planet * the heck * save the trees we got icons * Update process.py * Remove 'sunnypilot_ui' Removed 'sunnypilot_ui' parameter from params_keys.h * Update raylib_screenshots.py Removed the parameter setting for 'sunnypilot_ui' in the test. * ui: fuzzy search helper * better tree. fully dynamic and stuff * rm * more indent * Squashed commit of the following: commit 6b5b686fa5f1b6c8ba05cb98606bcb5e22fdcfd9 Author: discountchubbs Date: Mon Nov 24 17:16:17 2025 -0800 more indent commit 76bc538ac74898e026ee67502ddcb2a2a78eb429 Merge: 53eb821dc4 c53e2134e2 Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Mon Nov 24 17:15:48 2025 -0800 Merge branch 'master' into rl-tree-dialog commit 53eb821dc41a09f0bbe5ddbc6957ddfb6023c979 Merge: 82e1ebe97e 844f4cbc74 Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Mon Nov 24 11:54:55 2025 -0800 Merge branch 'master' into rl-tree-dialog commit 82e1ebe97ecae94f14adadcf77ac7a68d55cc0fe Author: discountchubbs Date: Mon Nov 24 10:23:35 2025 -0800 rm commit da3ff45bb6efe5f0bbd06eb6e4f61a7a3dd844b0 Merge: 41da513fca a829a1b972 Author: discountchubbs Date: Mon Nov 24 10:19:08 2025 -0800 Merge remote-tracking branch 'origin/rl-tree-dialog' into rl-tree-dialog commit 41da513fcaf5a5ff302427734813b005b6385f0b Author: discountchubbs Date: Mon Nov 24 10:18:43 2025 -0800 better tree. fully dynamic and stuff commit b2950149fbafda7d58bb5ed2b316f59ccc8a47eb Merge: 4fb8e4beed 924e5a3211 Author: discountchubbs Date: Mon Nov 24 10:17:51 2025 -0800 Merge remote-tracking branch 'origin/input-dialog' into rl-tree-dialog commit a829a1b97269de24dc707188808ad5b623968dfa Merge: 848290d07e 9edc36ca66 Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Mon Nov 24 10:16:28 2025 -0800 Merge branch 'master' into rl-tree-dialog commit 4fb8e4beede0e6771c25aaac7c8b8f90b2f21c03 Merge: 848290d07e af4f0f8372 Author: discountchubbs Date: Mon Nov 24 10:16:20 2025 -0800 Merge remote-tracking branch 'origin/fuzzy-dialog' into rl-tree-dialog commit af4f0f8372a63fdaeb94fe3b64703fbcca057b9c Merge: 1d5f0ab282 3cd55260d9 Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Mon Nov 24 06:39:29 2025 -0800 Merge branch 'master' into fuzzy-dialog commit 1d5f0ab282a01419d03e856b4a5a205f3bfb02aa Author: discountchubbs Date: Sun Nov 23 11:28:59 2025 -0800 ui: fuzzy search helper commit 848290d07eaab2ed5ba948bc8dd63338dc070ac1 Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Fri Nov 21 21:08:07 2025 -0800 Update raylib_screenshots.py Removed the parameter setting for 'sunnypilot_ui' in the test. commit 6694928a467641d500bf7b81ad82308ff1652eb7 Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Fri Nov 21 21:06:57 2025 -0800 Remove 'sunnypilot_ui' Removed 'sunnypilot_ui' parameter from params_keys.h commit b3c90ef7b2bdd0328442cdbeff7b13bcb260744e Merge: 0d3bc959c8 457b6634fd Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Fri Nov 21 21:06:04 2025 -0800 Merge branch 'master' into rl-tree-dialog commit 924e5a3211b3db71d785cd578ee2bdc31de5f495 Merge: a4ee4ba76d d92d2cb683 Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Fri Nov 21 19:33:18 2025 -0800 Merge branch 'master' into input-dialog commit a4ee4ba76d238fbb8da5261056da649e1dfbaab9 Merge: e911de5968 4f13a0f775 Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Fri Nov 21 16:24:31 2025 -0800 Merge branch 'master' into input-dialog commit e911de59684c44e02784ca98937cbdeb76401e05 Merge: cea6e00819 0ba5cbea91 Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Fri Nov 21 13:50:33 2025 -0800 Merge branch 'master' into input-dialog commit cea6e00819af66f3b46b9d72282a4e550c325798 Merge: d7b8ce86ed 8184cd8a6a Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Fri Nov 21 12:01:45 2025 -0800 Merge branch 'master' into input-dialog commit 0d3bc959c8547d97b14503cec73a67f5760ffb99 Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Wed Nov 19 20:29:30 2025 -0800 Update process.py commit 4f3c19ffb54db603528280e9aa941f719c764185 Author: James Vecellio Date: Wed Nov 19 20:28:59 2025 -0800 save the trees we got icons commit ae5c44355db6a625f9e257db2f62b2a5691a827f Author: discountchubbs Date: Wed Nov 19 13:38:04 2025 -0800 the heck commit 066438ad107ce9a3e9b4b2a1c0de062c523bc747 Merge: 9532675814 e74460f3a8 Author: discountchubbs Date: Wed Nov 19 12:18:17 2025 -0800 Merge remote-tracking branch 'origin/rl-tree-dialog' into rl-tree-dialog commit 95326758146bfe690b826d319c40f3bc7140392c Author: discountchubbs Date: Wed Nov 19 12:17:52 2025 -0800 less trees for the planet commit e74460f3a82d1338edb667bdf3423560270cbeab Merge: c347db376a 423a7d2ed0 Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Wed Nov 19 09:37:44 2025 -0800 Merge branch 'rl-sp-toggles' into rl-tree-dialog commit c347db376a08d3f3ee6d5cd66176bc12ec842582 Author: discountchubbs Date: Wed Nov 19 09:36:33 2025 -0800 tree dialog commit c9bd67b26121fce0637aeec924b777ef73a66575 Author: discountchubbs Date: Wed Nov 19 09:34:08 2025 -0800 merge origin raylib toggles commit d7b8ce86edaccb89452db51f4f69cf67643a0824 Author: discountchubbs Date: Mon Nov 17 20:21:33 2025 -0800 compare vs what used to be done before InputDialog commit 2d3d104658d660e8f9f7c12e312544c419a5d406 Merge: ded02895f4 f1025f6ee9 Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Mon Nov 17 19:24:20 2025 -0800 Merge branch 'master' into input-dialog commit ded02895f44a241afd3c9857760a18ec5e1406c4 Author: discountchubbs Date: Mon Nov 17 19:22:01 2025 -0800 dialog txt commit 9778a925b09438c7eb9618dfb0fc38eb13d53a39 Merge: cb03d08397 08e85808c5 Author: Jason Wen Date: Sun Nov 16 03:16:58 2025 -0500 input dialog commit 423a7d2ed0249e12743c2b36e1053d5a446f8d33 Author: nayan Date: Sun Nov 16 11:15:28 2025 -0500 fix ui preview commit e4e10d4b87d0bdf4fe2e766122935e5ee3706a5b Author: nayan Date: Sun Nov 16 11:15:22 2025 -0500 fix callback commit 362e9ce04becc1ef1d16d2f23daa01cb2d5303c4 Author: nayan Date: Sun Nov 16 09:53:28 2025 -0500 sp raylib preview commit 3946e643f68fdb5784a2b42839162903a5f4a592 Author: nayan Date: Sat Nov 15 20:24:20 2025 -0500 optimizations commit 0c37a385967c201d7db6e23ca3506bc21a22d698 Author: nayan Date: Sat Nov 15 09:42:12 2025 -0500 Lint commit 9c5acf61c047c81fd17bd02e9354225aabf5f7e8 Author: nayan Date: Sat Nov 15 09:29:07 2025 -0500 SP Toggles commit 121b304fe0dcd8bfad02a05aaba6d3e0c9d3029e Author: nayan Date: Sat Nov 15 09:28:58 2025 -0500 init styles commit 47d848293b54a6adf83c964120ed74dfbdf58359 Author: nayan Date: Sat Nov 15 09:28:43 2025 -0500 param to control stock vs sp ui * Squashed commit of the following: commit 70ad001add04810c6d30fd27e44299245b2b5c86 Merge: 142663c490 844f4cbc74 Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Mon Nov 24 11:54:58 2025 -0800 Merge branch 'master' into rl-progress-bar commit 142663c490b8ec88770fc0d8bc16cfcfff3f7a62 Author: discountchubbs Date: Sat Nov 22 20:12:44 2025 -0800 smoother updating commit 4476e418dd5cbd84e7ef1c65bc85c21a7806c6c7 Author: discountchubbs Date: Sat Nov 22 09:55:17 2025 -0800 easier to see commit ad66c22e88569c86f64095fab56a3c79310b63a3 Merge: 0c46ef5948 457b6634fd Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Sat Nov 22 07:45:05 2025 -0800 Merge branch 'master' into rl-progress-bar commit 0c46ef59482f678ec944ce772ac4202d257d29fd Author: discountchubbs Date: Sat Nov 22 07:42:59 2025 -0800 freaking test dir commit 11c19aad246b1e0bba02f49347517cf9af41a9d8 Merge: 7785238d54 8184cd8a6a Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Fri Nov 21 12:01:36 2025 -0800 Merge branch 'master' into rl-progress-bar commit 7785238d54e60f537418aea319e449ebccccbeac Author: discountchubbs Date: Wed Nov 19 07:47:10 2025 -0800 raylib: progress bar * OSM panel * fetching * only show if fav_param is used in the call * flattened and custom search query * conditional for mypy * sunny's new x,y makes this even easier! * download all * add back the rough estimate * not sure i like the 'Download' * simplify the path * actual size as of today * format * more simple * only show on download or delete * loathing loathing, unadulterated loathing, i loathe it all * loathing loathing, unadulterated loathing, i loathe it all * # Conflicts: # system/ui/sunnypilot/lib/styles.py # system/ui/sunnypilot/widgets/tree_dialog.py * search * st * Update osm.py * one second updates: its heavy process, which isnt really noticeable during downloads ayways. the once a second ensures responsiveness on the ui, while also maintaining 20fps on device for country/state downloads. * efficient? i hope * big boi texts * big boi texts * use our own classes * need to clear all params when delete all * more * collateral lol * do not behave as selected if canceled during US->States dialog * more * instead of timestamp, let's just show formatted time * disable button when downloading dbs * should be the buttons being disabled * well gotta re-enable them too * empty country * might be bigger now * fixes for mapd manager * should stay as a json * sanitize it a bit * revert * only nuke if the cancel button is called * always try to update the labels * Revert "always try to update the labels" This reverts commit ba0988fc06734234598f8235fdfe10270e1a3025. * re-enable button after download is complete * disable all while downloading (till we could cancel and re-download) * fix progress bar not filling up as intended for smaller total counts * revert * use new --------- Co-authored-by: nayan Co-authored-by: Jason Wen --- .../ui/sunnypilot/layouts/settings/osm.py | 222 +++++++++++++++++- sunnypilot/mapd/mapd_manager.py | 9 +- 2 files changed, 213 insertions(+), 18 deletions(-) diff --git a/selfdrive/ui/sunnypilot/layouts/settings/osm.py b/selfdrive/ui/sunnypilot/layouts/settings/osm.py index d57a0de9d..3726a820f 100644 --- a/selfdrive/ui/sunnypilot/layouts/settings/osm.py +++ b/selfdrive/ui/sunnypilot/layouts/settings/osm.py @@ -4,27 +4,229 @@ Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. This file is part of sunnypilot and is licensed under the MIT License. See the LICENSE.md file in the root directory for more details. """ +import datetime +import os +import platform +import requests +import shutil +import threading +from pathlib import Path +from time import monotonic + from openpilot.common.params import Params +from openpilot.selfdrive.ui.ui_state import device, ui_state +from openpilot.selfdrive.ui.layouts.settings.software import time_ago +from openpilot.system.hardware.hw import Paths +from openpilot.system.ui.lib.application import gui_app +from openpilot.system.ui.lib.multilang import tr +from openpilot.system.ui.widgets import DialogResult, Widget +from openpilot.system.ui.widgets.confirm_dialog import ConfirmDialog +from openpilot.system.ui.widgets.list_view import text_item from openpilot.system.ui.widgets.scroller_tici import Scroller -from openpilot.system.ui.widgets import Widget + +from openpilot.system.ui.sunnypilot.lib.utils import NoElideButtonAction +from openpilot.system.ui.sunnypilot.widgets.list_view import ListItemSP +from openpilot.system.ui.sunnypilot.widgets.tree_dialog import TreeFolder, TreeNode, TreeOptionDialog +from openpilot.system.ui.sunnypilot.widgets.progress_bar import progress_item + +MAP_PATH = Path(Paths.mapd_root()) / "offline" class OSMLayout(Widget): def __init__(self): super().__init__() - - self._params = Params() - items = self._initialize_items() - self._scroller = Scroller(items, line_separator=True, spacing=0) + self._current_percent = 0 + self._last_map_size_update = 0 + self._mem_params = Params("/dev/shm/params") if platform.system() != "Darwin" else ui_state.params + self._initialize_items() + self._update_map_size() + self._progress.set_visible(False) + self._state_btn.set_visible(False) + self._mapd_version.action_item.set_text(ui_state.params.get("MapdVersion") or "Loading...") + self._scroller = Scroller(self.items, line_separator=True, spacing=0) def _initialize_items(self): - items = [ + self._mapd_version = text_item(tr("Mapd Version"), lambda: ui_state.params.get("MapdVersion") or "Loading...") + self._delete_maps_btn = ListItemSP(tr("Downloaded Maps"), action_item=NoElideButtonAction(tr("DELETE"), enabled=True), callback=self._delete_maps) + self._progress = progress_item(tr("Downloading Map")) + self._update_btn = ListItemSP(tr("Database Update"), action_item=NoElideButtonAction(tr("CHECK"), enabled=True), callback=self._update_db) + self._country_btn = ListItemSP(tr("Country"), action_item=NoElideButtonAction(tr("SELECT"), enabled=True), callback=lambda: self._select_region("Country")) + self._state_btn = ListItemSP(tr("State"), action_item=NoElideButtonAction(tr("SELECT"), enabled=True), callback=lambda: self._select_region("State")) - ] - return items + self.items = [self._mapd_version, self._delete_maps_btn, self._progress, self._update_btn, self._country_btn, self._state_btn] - def _render(self, rect): - self._scroller.render(rect) + def _show_confirm(self, msg, confirm_text, func): + gui_app.set_modal_overlay(ConfirmDialog(msg, confirm_text), lambda res: func() if res == DialogResult.CONFIRM else None) + + def calculate_size(self): + total_size = 0 + directories_to_scan = [MAP_PATH] if MAP_PATH.exists() else [] + while directories_to_scan: + try: + for entry in os.scandir(directories_to_scan.pop()): + if entry.is_file(): + total_size += entry.stat().st_size + elif entry.is_dir(): + directories_to_scan.append(entry.path) + except OSError: + pass + self._delete_maps_btn.action_item.set_value(f"{total_size / 1024 ** 2:.2f} MB" if total_size < 1024 ** 3 else f"{total_size / 1024 ** 3:.2f} GB") + + def _update_map_size(self): + threading.Thread(target=self.calculate_size, daemon=True).start() + + def _do_delete_maps(self): + if MAP_PATH.exists(): + shutil.rmtree(MAP_PATH) + + for param in ("OsmDownloadedDate", "OsmLocal", "OsmLocationName", "OsmLocationTitle", "OsmStateName", "OsmStateTitle"): + ui_state.params.remove(param) + + self._delete_maps_btn.action_item.set_enabled(True) + self._delete_maps_btn.action_item.set_text(tr("DELETE")) + self._update_map_size() + + def _on_confirm_delete_maps(self): + self._delete_maps_btn.action_item.set_enabled(False) + self._delete_maps_btn.action_item.set_text("DELETING...") + threading.Thread(target=self._do_delete_maps).start() + + def _delete_maps(self): + self._show_confirm(tr("This will delete ALL downloaded maps\n\nAre you sure you want to delete all maps?"), + tr("Yes, delete all maps"), self._on_confirm_delete_maps) + + def _update_db(self): + self._show_confirm(tr("This will start the download process and it might take a while to complete."), tr("Start Download"), + lambda: ui_state.params.put_bool("OsmDbUpdatesCheck", True)) + + def _select_region(self, region_type): + is_country = region_type == "Country" + btn = self._country_btn if is_country else self._state_btn + btn.action_item.set_enabled(False) + btn.action_item.set_text(tr("FETCHING...")) + threading.Thread(target=self._do_select_region, args=(region_type, btn)).start() + + def _handle_region_selection(self, region_type, locations, key, res, ref): + if res != DialogResult.CONFIRM or not ref: + if region_type == "State" and res == DialogResult.CANCEL: + if ui_state.params.get("OsmLocationName") == "US" and not ui_state.params.get("OsmStateName"): + ui_state.params.remove("OsmLocationName") + ui_state.params.remove("OsmLocationTitle") + ui_state.params.remove("OsmLocal") + self._update_labels() + return + + if region_type == "Country": + ui_state.params.put_bool("OsmLocal", True) + ui_state.params.remove("OsmStateName") + ui_state.params.remove("OsmStateTitle") + + ui_state.params.put(f"{key}Name", ref) + name = next((n.data['display_name'] for n in locations if n.ref == ref), ref) + ui_state.params.put(f"{key}Title", name) + + if ref == "US" and region_type == "Country": + self._select_region("State") + else: + self._update_db() + + def _do_select_region(self, region_type, btn): + base_url = "https://raw.githubusercontent.com/pfeiferj/openpilot-mapd/main/" + url = base_url + ("nation_bounding_boxes.json" if region_type == "Country" else "us_states_bounding_boxes.json") + try: + data = requests.get(url, timeout=10).json() + locations = sorted([TreeNode(ref=k, data={'display_name': v['full_name']}) for k, v in data.items()], key=lambda n: n.data['display_name']) + except Exception: + locations = [] + + if region_type == "State": + locations.insert(0, TreeNode(ref="All", data={'display_name': tr("All states (~6.0 GB)")})) + + btn.action_item.set_enabled(True) + btn.action_item.set_text(tr("SELECT")) + + key = "OsmLocation" if region_type == "Country" else "OsmState" + current = ui_state.params.get(f"{key}Name") or "" + + dialog = TreeOptionDialog(tr(f"Select {region_type}"), [TreeFolder(folder="", nodes=locations)], current_ref=current, search_prompt="Perform a search") + dialog.on_exit = lambda res: self._handle_region_selection(region_type, locations, key, res, dialog.selection_ref) + gui_app.set_modal_overlay(dialog, callback=lambda res: self._handle_region_selection(region_type, locations, key, res, dialog.selection_ref)) + + def _update_labels(self): + downloading = bool(self._mem_params.get("OSMDownloadLocations")) + self._country_btn.set_enabled(not downloading) + self._state_btn.set_enabled(not downloading) + self._state_btn.set_visible(ui_state.params.get("OsmLocationName") == "US") + self._update_btn.set_visible(bool(ui_state.params.get("OsmLocationName"))) + + self._country_btn.action_item.set_value(ui_state.params.get("OsmLocationTitle") or "") + self._state_btn.action_item.set_value(ui_state.params.get("OsmStateTitle") or "") + + pending = ui_state.params.get_bool("OsmDbUpdatesCheck") + if downloading or pending: + if downloading: + device.reset_interactive_timeout() + self._update_map_size() + self._progress.set_visible(True) + progress = ui_state.params.get("OSMDownloadProgress") + total = progress.get('total_files', 0) if progress else 0 + done = progress.get('downloaded_files', 0) if progress else 0 + failed = total > 0 and not downloading and done < total + + if total > 0: + progress_perc = max(0.0, min(100.0, (done / total) * 100.0)) + else: + progress_perc = 0.0 + + if failed: + text = "0% - Downloading Maps" + btn_text = tr("Error: Invalid download. Retry.") + self._current_percent = 0.0 + elif total > 0 and downloading: + self._current_percent = progress_perc + perc_int = int(progress_perc) + text = f"{perc_int}% - Downloading Maps" + btn_text = f"{done}/{total} ({perc_int}%)" + else: + self._current_percent = 0.0 + text = "0% - Downloading Maps" + btn_text = tr("Downloading Maps...") + + self._progress.action_item.update(self._current_percent, text, show_progress=total > 0 and downloading and not failed) + self._update_btn.action_item.set_enabled(not downloading) # TODO-SP: introduce CANCEL database download with mapd + self._update_btn.action_item.set_value(btn_text) + self._country_btn.action_item.set_enabled(not downloading) + self._state_btn.action_item.set_enabled(not downloading) + self._delete_maps_btn.action_item.set_enabled(not downloading) + else: + self._progress.set_visible(False) + self._update_btn.action_item.set_enabled(True) + self._country_btn.action_item.set_enabled(True) + self._state_btn.action_item.set_enabled(True) + self._delete_maps_btn.action_item.set_enabled(True) + + ts = ui_state.params.get("OsmDownloadedDate") + dt: datetime.datetime | None = None + + if ts: + try: + ts_f = float(ts) + if ts_f > 0: + dt = datetime.datetime.fromtimestamp(ts_f, tz=datetime.UTC) + except (ValueError, TypeError): + dt = None + + formatted = time_ago(dt) + self._update_btn.action_item.set_value(tr("Last checked {}").format(formatted)) def show_event(self): self._scroller.show_event() + + def _update_state(self): + now = monotonic() + if now - self._last_map_size_update >= 1.0: + self._last_map_size_update = now + self._update_labels() + + def _render(self, rect): + self._scroller.render(rect) diff --git a/sunnypilot/mapd/mapd_manager.py b/sunnypilot/mapd/mapd_manager.py index 1211c1ecc..9304f8f0b 100755 --- a/sunnypilot/mapd/mapd_manager.py +++ b/sunnypilot/mapd/mapd_manager.py @@ -64,12 +64,7 @@ def request_refresh_osm_location_data(nations: list[str], states: list[str] = No "states": states or [] } - osm_download_locations_dump = json.dumps({ - "nations": nations, - "states": states or [] - }) - - print(f"Downloading maps for {osm_download_locations_dump}") + print(f"Downloading maps for {json.dumps(osm_download_locations)}") mem_params.put("OSMDownloadLocations", osm_download_locations) @@ -103,8 +98,6 @@ def filter_nations_and_states(nations: list[str], states: list[str] = None) -> t def update_osm_db() -> None: - # last_downloaded_date = params.get("OsmDownloadedDate", return_default=True) - # if params.get_bool("OsmDbUpdatesCheck") or time.monotonic() - last_downloaded_date >= 604800: # 7 days * 24 hours/day * 60 if params.get_bool("OsmDbUpdatesCheck"): cleanup_old_osm_data(get_files_for_cleanup()) country = params.get("OsmLocationName", return_default=True)