Offline maps

Co-Authored-By: Jacob Pfeifer <jacob@pfeifer.dev>
This commit is contained in:
James
2025-12-01 12:00:00 -07:00
parent 83d1156bb4
commit a8122c8f05
4 changed files with 190 additions and 2 deletions
+33 -1
View File
@@ -16,7 +16,7 @@ from openpilot.frogpilot.assets.theme_manager import ThemeManager
from openpilot.frogpilot.common.frogpilot_backups import backup_frogpilot
from openpilot.frogpilot.common.frogpilot_utilities import is_FrogsGoMoo, run_cmd, use_konik_server
from openpilot.frogpilot.common.frogpilot_variables import (
ERROR_LOGS_PATH, FROGS_GO_MOO_PATH, HD_LOGS_PATH, KONIK_LOGS_PATH, THEME_SAVE_PATH,
ERROR_LOGS_PATH, FROGS_GO_MOO_PATH, HD_LOGS_PATH, KONIK_LOGS_PATH, MAPD_PATH, MAPS_PATH, THEME_SAVE_PATH,
FrogPilotVariables, get_frogpilot_toggles
)
@@ -96,6 +96,38 @@ def update_boot_logo(frogpilot=False, stock=False):
run_cmd(["sudo", "mount", "-o", f"remount,{mount_options}", "/"], "Successfully restored / mount options", "Failed to restore / mount options")
def update_maps(now, params, params_memory):
while not MAPD_PATH.exists():
time.sleep(60)
maps_selected = params.get("MapsSelected")
if not maps_selected or not (maps_selected.get("nations") or maps_selected.get("states")):
return
day = now.day
is_first = day == 1
is_sunday = now.weekday() == 6
schedule = params.get("PreferredSchedule")
maps_downloaded = MAPS_PATH.exists()
if maps_downloaded and (schedule == 0 or (schedule == 1 and not is_sunday) or (schedule == 2 and not is_first)):
return
suffix = "th" if 11 <= day <= 13 else {1: "st", 2: "nd", 3: "rd"}.get(day % 10, "th")
todays_date = now.strftime(f"%B {day}{suffix}, %Y")
if maps_downloaded and params.get("LastMapsUpdate") == todays_date:
return
if params.get("OSMDownloadProgress") is None:
params_memory.put("OSMDownloadLocations", maps_selected)
while params.get("OSMDownloadProgress") is not None:
time.sleep(60)
params.put("LastMapsUpdate", todays_date)
def update_openpilot(thread_manager, params):
def update_available():
run_cmd(["pkill", "-SIGUSR1", "-f", "system.updated.updated"], "Checking for updates...", "Failed to check for update...", report=False)
+3 -1
View File
@@ -10,7 +10,7 @@ from openpilot.common.time_helpers import system_time_valid
from openpilot.frogpilot.assets.theme_manager import THEME_COMPONENT_PARAMS, ThemeManager
from openpilot.frogpilot.common.frogpilot_backups import backup_toggles
from openpilot.frogpilot.common.frogpilot_functions import update_openpilot
from openpilot.frogpilot.common.frogpilot_functions import update_maps, update_openpilot
from openpilot.frogpilot.common.frogpilot_utilities import ThreadManager, flash_panda, is_url_pingable, lock_doors
from openpilot.frogpilot.common.frogpilot_variables import ERROR_LOGS_PATH, FrogPilotVariables
from openpilot.frogpilot.controls.frogpilot_planner import FrogPilotPlanner
@@ -45,6 +45,8 @@ def update_checks(now, theme_manager, thread_manager, params, params_memory, fro
while not (is_url_pingable("https://github.com") or is_url_pingable("https://gitlab.com")):
time.sleep(60)
thread_manager.run_with_lock(update_maps, (now, params, params_memory))
theme_manager.update_themes(frogpilot_toggles, boot_run)
if frogpilot_toggles.automatic_updates:
+153
View File
@@ -0,0 +1,153 @@
#!/usr/bin/env python3
# PFEIFER - MAPD - Modified by FrogAi for FrogPilot
import json
import os
import shutil
import stat
import subprocess
import tempfile
import time
import urllib.request
from pathlib import Path
from openpilot.common.params import Params
from openpilot.frogpilot.common.frogpilot_utilities import is_url_pingable
from openpilot.frogpilot.common.frogpilot_variables import MAPD_PATH, RESOURCES_REPO
VERSION = "v2"
GITHUB_VERSION_URL = f"https://github.com/{RESOURCES_REPO}/raw/Versions/mapd_version_{VERSION}.json"
GITLAB_VERSION_URL = f"https://gitlab.com/{RESOURCES_REPO}/-/raw/Versions/mapd_version_{VERSION}.json"
VERSION_PATH = Path("/data/media/0/osm/mapd_version")
def cleanup_temp_files():
parent = MAPD_PATH.parent
try:
if not parent.exists() or not parent.is_dir():
return
except OSError as e:
print(f"Skipping cleanup; cannot access {parent}: {e}")
return
try:
for file in parent.glob("mapd*"):
if file == MAPD_PATH or file == VERSION_PATH:
continue
if file.is_file():
try:
file.unlink()
except Exception as exception:
print(f"Failed to delete leftover file {file}: {exception}")
except OSError as exception:
print(f"Skipping cleanup in {parent} due to I/O error: {exception}")
def download():
Path(MAPD_PATH).parent.mkdir(parents=True, exist_ok=True)
while not (is_url_pingable("https://github.com") or is_url_pingable("https://gitlab.com")):
time.sleep(60)
latest_version = get_latest_version()
urls = [
f"https://github.com/pfeiferj/openpilot-mapd/releases/download/{latest_version}/mapd",
f"https://gitlab.com/{RESOURCES_REPO}/-/raw/Mapd/{latest_version}"
]
for url in urls:
try:
with urllib.request.urlopen(url) as response:
with tempfile.NamedTemporaryFile("wb", delete=False, dir=MAPD_PATH.parent) as temp_file:
shutil.copyfileobj(response, temp_file)
temp_file_path = Path(temp_file.name)
os.fsync(temp_file.fileno())
os.chmod(temp_file_path, os.stat(temp_file_path).st_mode | stat.S_IEXEC)
os.rename(temp_file_path, MAPD_PATH)
with open(VERSION_PATH, "w") as version_file:
version_file.write(latest_version)
os.fsync(version_file.fileno())
return
except Exception as exception:
print(f"Failed to download mapd from {url}: {exception}")
if "temp_file_path" in locals() and temp_file_path.exists():
temp_file_path.unlink(missing_ok=True)
def get_latest_version():
while not (is_url_pingable("https://github.com") or is_url_pingable("https://gitlab.com")):
time.sleep(60)
for url in [GITHUB_VERSION_URL, GITLAB_VERSION_URL]:
try:
with urllib.request.urlopen(url, timeout=10) as response:
return json.loads(response.read().decode("utf-8"))["version"]
except Exception as exception:
print(f"Error fetching mapd version from {url}: {exception}")
return "v0"
def update_mapd():
if not MAPD_PATH.exists():
print(f"{MAPD_PATH} not found. Downloading...")
download()
return False
if not VERSION_PATH.exists():
print(f"{VERSION_PATH} not found. Downloading mapd...")
download()
return False
if is_url_pingable("https://github.com") or is_url_pingable("https://gitlab.com"):
try:
with open(VERSION_PATH) as version_file:
local_version = version_file.read().strip()
if local_version != get_latest_version():
print("New mapd version available. Updating...")
download()
return False
else:
return True
except Exception as exception:
print(f"Error checking version: {exception}")
return False
if not os.access(MAPD_PATH, os.X_OK):
print(f"{MAPD_PATH} is not executable. Fixing permissions...")
try:
os.chmod(MAPD_PATH, os.stat(MAPD_PATH).st_mode | stat.S_IEXEC)
except Exception as exception:
print(f"Failed to set executable permissions on {MAPD_PATH}: {exception}")
return False
return True
def mapd_thread():
params_memory = Params(memory=True)
params_memory.put("MapdLogLevel", "disabled")
while True:
try:
cleanup_temp_files()
except OSError as exception:
print(f"Cleanup errored: {exception}")
time.sleep(5)
continue
while not update_mapd():
time.sleep(60)
continue
try:
process = subprocess.Popen(str(MAPD_PATH))
process.wait()
except FileNotFoundError as error:
print(f"Subprocess failed: {error}")
download()
def main():
mapd_thread()
if __name__ == "__main__":
main()
+1
View File
@@ -130,6 +130,7 @@ elif TICI:
procs.append(NativeProcess("ui", "selfdrive/ui", ["./ui"], always_run, watchdog_max_dt=5)),
procs += [
PythonProcess("frogpilot_process", "frogpilot.frogpilot_process", always_run),
PythonProcess("mapd", "frogpilot.navigation.mapd", always_run),
]
managed_processes = {p.name: p for p in procs}