mirror of
https://github.com/MoreTore/openpilot.git
synced 2026-09-27 18:03:52 +08:00
September 10th, 2024 Patch
This commit is contained in:
@@ -21,7 +21,7 @@ FrogPilot is a fully open-sourced fork of openpilot, featuring clear and concise
|
||||
------
|
||||
FrogPilot was last updated on:
|
||||
|
||||
**September 5th, 2024**
|
||||
**September 10th, 2024**
|
||||
|
||||
Features
|
||||
------
|
||||
|
||||
@@ -43,34 +43,30 @@ def handle_error(destination, error_message, error, download_param, progress_par
|
||||
params_memory.put(progress_param, error_message)
|
||||
|
||||
def handle_request_error(error, destination, download_param, progress_param, params_memory):
|
||||
if isinstance(error, requests.HTTPError):
|
||||
if error.response.status_code == 404:
|
||||
return
|
||||
error_message = f"Server error ({error.response.status_code})" if error.response else "Server error."
|
||||
elif isinstance(error, requests.ConnectionError):
|
||||
error_message = "Connection dropped."
|
||||
elif isinstance(error, requests.Timeout):
|
||||
error_message = "Download timed out."
|
||||
elif isinstance(error, requests.RequestException):
|
||||
error_message = "Network request error. Check connection."
|
||||
else:
|
||||
error_message = "Unexpected error."
|
||||
error_map = {
|
||||
requests.HTTPError: lambda e: f"Server error ({e.response.status_code})" if e.response else "Server error.",
|
||||
requests.ConnectionError: "Connection dropped.",
|
||||
requests.Timeout: "Download timed out.",
|
||||
requests.RequestException: "Network request error. Check connection."
|
||||
}
|
||||
|
||||
error_message = error_map.get(type(error), "Unexpected error.")
|
||||
if isinstance(error, requests.HTTPError) and error.response and error.response.status_code == 404:
|
||||
return
|
||||
|
||||
handle_error(destination, f"Failed: {error_message}", error, download_param, progress_param, params_memory)
|
||||
|
||||
def get_remote_file_size(url):
|
||||
try:
|
||||
response = requests.head(url, headers={'Accept-Encoding': 'identity'}, timeout=5)
|
||||
if response.status_code == 404:
|
||||
print(f"URL not found: {url}")
|
||||
return None
|
||||
response.raise_for_status()
|
||||
return int(response.headers.get('Content-Length', 0))
|
||||
except requests.HTTPError as e:
|
||||
if e.response.status_code == 404:
|
||||
return 0
|
||||
else:
|
||||
handle_request_error(e, None, None, None, None)
|
||||
except Exception as e:
|
||||
except (requests.RequestException, ValueError) as e:
|
||||
handle_request_error(e, None, None, None, None)
|
||||
return 0
|
||||
return None
|
||||
|
||||
def get_repository_url():
|
||||
if is_url_pingable("https://github.com"):
|
||||
@@ -84,17 +80,25 @@ def link_valid(url):
|
||||
response = requests.head(url, allow_redirects=True, timeout=5)
|
||||
response.raise_for_status()
|
||||
return True
|
||||
except requests.HTTPError as e:
|
||||
if e.response.status_code != 404:
|
||||
handle_request_error(e, None, None, None, None)
|
||||
return False
|
||||
except Exception as e:
|
||||
handle_request_error(e, None, None, None, None)
|
||||
return False
|
||||
|
||||
def verify_download(file_path, url):
|
||||
if not os.path.exists(file_path):
|
||||
if not os.path.isfile(file_path):
|
||||
print(f"File not found: {file_path}")
|
||||
return False
|
||||
|
||||
remote_file_size = get_remote_file_size(url)
|
||||
if remote_file_size is None:
|
||||
print(f"Error fetching remote size for {file_path}")
|
||||
return None
|
||||
if remote_file_size != os.path.getsize(file_path):
|
||||
print(f"File size mismatch for {file_path}")
|
||||
return False
|
||||
|
||||
return remote_file_size == os.path.getsize(file_path)
|
||||
return True
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import requests
|
||||
import shutil
|
||||
import time
|
||||
import urllib.request
|
||||
@@ -46,16 +45,16 @@ class ModelManager:
|
||||
|
||||
def download_model(self, model_to_download):
|
||||
model_path = os.path.join(MODELS_PATH, f"{model_to_download}.thneed")
|
||||
if os.path.exists(model_path):
|
||||
if os.path.isfile(model_path):
|
||||
handle_error(model_path, "Model already exists...", "Model already exists...", self.download_param, self.download_progress_param, self.params_memory)
|
||||
return
|
||||
|
||||
self.repo_url = get_repository_url()
|
||||
if not self.repo_url:
|
||||
repo_url = get_repository_url()
|
||||
if not repo_url:
|
||||
handle_error(model_path, "GitHub and GitLab are offline...", "Repository unavailable", self.download_param, self.download_progress_param, self.params_memory)
|
||||
return
|
||||
|
||||
model_url = f"{self.repo_url}Models/{model_to_download}.thneed"
|
||||
model_url = f"{repo_url}Models/{model_to_download}.thneed"
|
||||
print(f"Downloading model: {model_to_download}")
|
||||
download_file(self.cancel_download_param, model_path, self.download_progress_param, model_url, self.download_param, self.params_memory)
|
||||
|
||||
@@ -74,7 +73,7 @@ class ModelManager:
|
||||
handle_request_error(error, None, None, None, None)
|
||||
return []
|
||||
|
||||
def update_model_params(self, model_info):
|
||||
def update_model_params(self, model_info, repo_url):
|
||||
available_models, available_model_names, experimental_models, navigation_models, radarless_models = [], [], [], [], []
|
||||
|
||||
for model in model_info:
|
||||
@@ -96,20 +95,23 @@ class ModelManager:
|
||||
print("Models list updated successfully.")
|
||||
|
||||
if available_models:
|
||||
models_downloaded = self.are_all_models_downloaded(available_models, available_model_names)
|
||||
models_downloaded = self.are_all_models_downloaded(available_models, available_model_names, repo_url)
|
||||
self.params.put_bool_nonblocking("ModelsDownloaded", models_downloaded)
|
||||
|
||||
def are_all_models_downloaded(self, available_models, available_model_names):
|
||||
def are_all_models_downloaded(self, available_models, available_model_names, repo_url):
|
||||
automatically_update_models = self.params.get_bool("AutomaticallyUpdateModels")
|
||||
all_models_downloaded = True
|
||||
|
||||
for model in available_models:
|
||||
model_path = os.path.join(MODELS_PATH, f"{model}.thneed")
|
||||
model_url = f"{self.repo_url}Models/{model}.thneed"
|
||||
model_url = f"{repo_url}Models/{model}.thneed"
|
||||
|
||||
if os.path.exists(model_path):
|
||||
if os.path.isfile(model_path):
|
||||
if automatically_update_models:
|
||||
if not verify_download(model_path, model_url):
|
||||
verify_result = verify_download(model_path, model_url)
|
||||
if verify_result is None:
|
||||
all_models_downloaded = False
|
||||
elif not verify_result:
|
||||
print(f"Model {model} is outdated. Re-downloading...")
|
||||
delete_file(model_path)
|
||||
self.remove_model_params(available_model_names, available_models, model)
|
||||
@@ -152,6 +154,11 @@ class ModelManager:
|
||||
if not available_models:
|
||||
return
|
||||
|
||||
current_model_path = os.path.join(MODELS_PATH, f"{current_model}.thneed")
|
||||
if not os.path.isfile(current_model_path):
|
||||
print(f"Model {current_model} is not downloaded. Downloading...")
|
||||
self.download_model(current_model)
|
||||
|
||||
for model_file in os.listdir(MODELS_PATH):
|
||||
if model_file.replace(".thneed", "") not in available_models.split(','):
|
||||
if model_file == current_model:
|
||||
@@ -163,35 +170,38 @@ class ModelManager:
|
||||
def copy_default_model(self):
|
||||
default_model_path = os.path.join(MODELS_PATH, f"{DEFAULT_MODEL}.thneed")
|
||||
|
||||
if not os.path.exists(default_model_path):
|
||||
if not os.path.isfile(default_model_path):
|
||||
source_path = os.path.join(BASEDIR, "selfdrive", "modeld", "models", "supercombo.thneed")
|
||||
|
||||
if os.path.exists(source_path):
|
||||
if os.path.isfile(source_path):
|
||||
shutil.copyfile(source_path, default_model_path)
|
||||
print(f"Copied default model from {source_path} to {default_model_path}")
|
||||
else:
|
||||
print(f"Source default model not found at {source_path}. Exiting...")
|
||||
|
||||
def update_models(self, boot_run=True):
|
||||
def update_models(self, boot_run=False):
|
||||
if boot_run:
|
||||
self.copy_default_model()
|
||||
|
||||
self.repo_url = get_repository_url()
|
||||
if self.repo_url is None:
|
||||
repo_url = get_repository_url()
|
||||
if repo_url is None:
|
||||
print("GitHub and GitLab are offline...")
|
||||
return
|
||||
|
||||
model_info = self.fetch_models(f"{self.repo_url}Versions/model_names_{VERSION}.json")
|
||||
model_info = self.fetch_models(f"{repo_url}Versions/model_names_{VERSION}.json")
|
||||
if model_info:
|
||||
self.update_model_params(model_info)
|
||||
self.update_model_params(model_info, repo_url)
|
||||
|
||||
if boot_run:
|
||||
self.validate_models()
|
||||
|
||||
def download_all_models(self):
|
||||
self.repo_url = get_repository_url()
|
||||
if not self.repo_url:
|
||||
repo_url = get_repository_url()
|
||||
if not repo_url:
|
||||
handle_error(None, "GitHub and GitLab are offline...", "Repository unavailable", self.download_param, self.download_progress_param, self.params_memory)
|
||||
return
|
||||
|
||||
model_info = self.fetch_models(f"{self.repo_url}Versions/model_names_{VERSION}.json")
|
||||
model_info = self.fetch_models(f"{repo_url}Versions/model_names_{VERSION}.json")
|
||||
if not model_info:
|
||||
handle_error(None, "Unable to update model list...", "Model list unavailable", self.download_param, self.download_progress_param, self.params_memory)
|
||||
return
|
||||
@@ -208,7 +218,7 @@ class ModelManager:
|
||||
if self.params_memory.get_bool(self.cancel_download_param):
|
||||
return
|
||||
|
||||
if not os.path.exists(os.path.join(MODELS_PATH, f"{model}.thneed")):
|
||||
if not os.path.isfile(os.path.join(MODELS_PATH, f"{model}.thneed")):
|
||||
model_index = available_models.index(model)
|
||||
model_name = available_model_names[model_index]
|
||||
|
||||
@@ -220,7 +230,7 @@ class ModelManager:
|
||||
while self.params_memory.get(self.download_param, encoding='utf-8'):
|
||||
time.sleep(1)
|
||||
|
||||
while not all(os.path.exists(os.path.join(MODELS_PATH, f"{model}.thneed")) for model in available_models):
|
||||
while not all(os.path.isfile(os.path.join(MODELS_PATH, f"{model}.thneed")) for model in available_models):
|
||||
time.sleep(1)
|
||||
|
||||
self.params_memory.put(self.download_progress_param, "All models downloaded!")
|
||||
|
||||
@@ -258,7 +258,7 @@ class ThemeManager:
|
||||
|
||||
for ext in extentions:
|
||||
theme_path = download_path + ext
|
||||
if os.path.exists(theme_path):
|
||||
if os.path.isfile(theme_path):
|
||||
handle_error(theme_path, "Theme already exists...", "Theme already exists...", theme_param, self.download_progress_param, self.params_memory)
|
||||
return
|
||||
|
||||
@@ -366,7 +366,7 @@ class ThemeManager:
|
||||
self.previous_assets = {}
|
||||
self.update_active_theme()
|
||||
|
||||
def update_themes(self):
|
||||
def update_themes(self, boot_run=False):
|
||||
if not os.path.exists(THEME_SAVE_PATH):
|
||||
return
|
||||
|
||||
@@ -375,6 +375,9 @@ class ThemeManager:
|
||||
print("GitHub and GitLab are offline...")
|
||||
return
|
||||
|
||||
if boot_run:
|
||||
self.validate_themes()
|
||||
|
||||
if repo_url == GITHUB_URL:
|
||||
base_url = "https://github.com/FrogAi/FrogPilot-Resources/blob/Themes/"
|
||||
distance_icons_files = self.fetch_files("https://github.com/FrogAi/FrogPilot-Resources/blob/Distance-Icons")
|
||||
|
||||
@@ -86,13 +86,13 @@ def time_checks(automatic_updates, deviceState, model_manager, now, started, the
|
||||
update_maps(now, params, params_memory)
|
||||
|
||||
with locks["update_models"]:
|
||||
model_manager.update_models(boot_run=False)
|
||||
model_manager.update_models()
|
||||
|
||||
with locks["update_themes"]:
|
||||
theme_manager.update_themes()
|
||||
|
||||
def toggle_updates(frogpilot_toggles, started, time_validated, params, params_storage):
|
||||
FrogPilotVariables.update_frogpilot_params(started, True)
|
||||
FrogPilotVariables.update_frogpilot_params(started)
|
||||
|
||||
if not frogpilot_toggles.model_manager:
|
||||
params.put_nonblocking("Model", DEFAULT_MODEL)
|
||||
@@ -195,8 +195,8 @@ def frogpilot_thread():
|
||||
if not time_validated:
|
||||
continue
|
||||
if deviceState.networkType == WIFI:
|
||||
run_thread_with_lock("update_models", model_manager.update_models)
|
||||
run_thread_with_lock("update_themes", theme_manager.update_themes)
|
||||
run_thread_with_lock("update_models", model_manager.update_models, (True,))
|
||||
run_thread_with_lock("update_themes", theme_manager.update_themes, (True,))
|
||||
|
||||
theme_manager.update_holiday()
|
||||
|
||||
|
||||
@@ -5,9 +5,6 @@ import stat
|
||||
import subprocess
|
||||
import time
|
||||
import urllib.request
|
||||
import http.client
|
||||
import socket
|
||||
import openpilot.system.sentry as sentry
|
||||
|
||||
from openpilot.common.realtime import Ratekeeper
|
||||
|
||||
@@ -26,9 +23,8 @@ def get_latest_version():
|
||||
try:
|
||||
with urllib.request.urlopen(url, timeout=5) as response:
|
||||
return json.loads(response.read().decode('utf-8'))['version']
|
||||
except (http.client.IncompleteRead, http.client.RemoteDisconnected, socket.gaierror, socket.timeout, urllib.error.HTTPError, urllib.error.URLError) as e:
|
||||
sentry.capture_exception(e)
|
||||
print(f"Failed to get latest version from {url}. Error: {e}")
|
||||
except Exception as e:
|
||||
print(f"Error fetching version from {url}: {e}")
|
||||
print("Failed to get the latest version from both sources.")
|
||||
return None
|
||||
|
||||
@@ -54,9 +50,8 @@ def download(current_version):
|
||||
|
||||
print(f"Successfully downloaded mapd from {url}")
|
||||
return True
|
||||
except (http.client.IncompleteRead, http.client.RemoteDisconnected, socket.gaierror, socket.timeout, urllib.error.HTTPError, urllib.error.URLError) as e:
|
||||
sentry.capture_exception(e)
|
||||
print(f"Failed to download from {url}. Error: {e}")
|
||||
except Exception as e:
|
||||
print(f"Failed to download from {url}: {e}")
|
||||
|
||||
print(f"Failed to download mapd for version {current_version} from both sources.")
|
||||
return False
|
||||
@@ -66,7 +61,6 @@ def ensure_mapd_is_running():
|
||||
try:
|
||||
subprocess.run([MAPD_PATH], check=True)
|
||||
except Exception as e:
|
||||
sentry.capture_exception(e)
|
||||
print(f"Error running mapd process: {e}")
|
||||
time.sleep(1)
|
||||
|
||||
@@ -89,7 +83,6 @@ def mapd_thread(sm=None, pm=None):
|
||||
continue
|
||||
ensure_mapd_is_running()
|
||||
except Exception as e:
|
||||
sentry.capture_exception(e)
|
||||
print(f"Exception in mapd_thread: {e}")
|
||||
time.sleep(1)
|
||||
|
||||
@@ -99,7 +92,6 @@ def main(sm=None, pm=None):
|
||||
try:
|
||||
mapd_thread(sm, pm)
|
||||
except Exception as e:
|
||||
sentry.capture_exception(e)
|
||||
print(f"Unhandled exception in main: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -14,31 +14,31 @@
|
||||
#include "selfdrive/ui/ui.h"
|
||||
|
||||
QMap<QString, QString> northeastMap = {
|
||||
{"CT", "Connecticut"}, {"DE", "Delaware"}, {"MA", "Massachusetts"},
|
||||
{"MD", "Maryland"}, {"ME", "Maine"}, {"NH", "New Hampshire"},
|
||||
{"CT", "Connecticut"}, {"DE", "Delaware"}, {"ME", "Maine"},
|
||||
{"MD", "Maryland"}, {"MA", "Massachusetts"}, {"NH", "New Hampshire"},
|
||||
{"NJ", "New Jersey"}, {"NY", "New York"}, {"PA", "Pennsylvania"},
|
||||
{"RI", "Rhode Island"}, {"VT", "Vermont"}
|
||||
};
|
||||
|
||||
QMap<QString, QString> midwestMap = {
|
||||
{"IA", "Iowa"}, {"IL", "Illinois"}, {"IN", "Indiana"},
|
||||
{"IL", "Illinois"}, {"IN", "Indiana"}, {"IA", "Iowa"},
|
||||
{"KS", "Kansas"}, {"MI", "Michigan"}, {"MN", "Minnesota"},
|
||||
{"MO", "Missouri"}, {"ND", "North Dakota"}, {"NE", "Nebraska"},
|
||||
{"MO", "Missouri"}, {"NE", "Nebraska"}, {"ND", "North Dakota"},
|
||||
{"OH", "Ohio"}, {"SD", "South Dakota"}, {"WI", "Wisconsin"}
|
||||
};
|
||||
|
||||
QMap<QString, QString> southMap = {
|
||||
{"AL", "Alabama"}, {"AR", "Arkansas"}, {"FL", "Florida"},
|
||||
{"GA", "Georgia"}, {"KY", "Kentucky"}, {"LA", "Louisiana"},
|
||||
{"MS", "Mississippi"}, {"NC", "North Carolina"}, {"OK", "Oklahoma"},
|
||||
{"SC", "South Carolina"}, {"TN", "Tennessee"}, {"TX", "Texas"},
|
||||
{"VA", "Virginia"}, {"WV", "West Virginia"}
|
||||
{"MD", "Maryland"}, {"MS", "Mississippi"}, {"NC", "North Carolina"},
|
||||
{"OK", "Oklahoma"}, {"SC", "South Carolina"}, {"TN", "Tennessee"},
|
||||
{"TX", "Texas"}, {"VA", "Virginia"}, {"WV", "West Virginia"}
|
||||
};
|
||||
|
||||
QMap<QString, QString> westMap = {
|
||||
{"AK", "Alaska"}, {"AZ", "Arizona"}, {"CA", "California"},
|
||||
{"CO", "Colorado"}, {"HI", "Hawaii"}, {"ID", "Idaho"},
|
||||
{"MT", "Montana"}, {"NM", "New Mexico"}, {"NV", "Nevada"},
|
||||
{"MT", "Montana"}, {"NV", "Nevada"}, {"NM", "New Mexico"},
|
||||
{"OR", "Oregon"}, {"UT", "Utah"}, {"WA", "Washington"},
|
||||
{"WY", "Wyoming"}
|
||||
};
|
||||
@@ -51,19 +51,23 @@ QMap<QString, QString> territoriesMap = {
|
||||
|
||||
QMap<QString, QString> africaMap = {
|
||||
{"DZ", "Algeria"}, {"AO", "Angola"}, {"BJ", "Benin"}, {"BW", "Botswana"},
|
||||
{"BF", "Burkina Faso"}, {"BI", "Burundi"}, {"CM", "Cameroon"}, {"CV", "Cape Verde"},
|
||||
{"CF", "Central African Republic"}, {"TD", "Chad"}, {"KM", "Comoros"}, {"CG", "Congo (Brazzaville)"},
|
||||
{"CD", "Congo (Kinshasa)"}, {"CI", "Ivory Coast"}, {"DJ", "Djibouti"}, {"EG", "Egypt"},
|
||||
{"GQ", "Equatorial Guinea"}, {"ER", "Eritrea"}, {"SZ", "Eswatini"}, {"ET", "Ethiopia"},
|
||||
{"GA", "Gabon"}, {"GM", "Gambia"}, {"GH", "Ghana"}, {"GN", "Guinea"},
|
||||
{"GW", "Guinea-Bissau"}, {"KE", "Kenya"}, {"LS", "Lesotho"}, {"LR", "Liberia"},
|
||||
{"LY", "Libya"}, {"MG", "Madagascar"}, {"MW", "Malawi"}, {"ML", "Mali"},
|
||||
{"MR", "Mauritania"}, {"MU", "Mauritius"}, {"MA", "Morocco"}, {"MZ", "Mozambique"},
|
||||
{"NA", "Namibia"}, {"NE", "Niger"}, {"NG", "Nigeria"}, {"RW", "Rwanda"},
|
||||
{"ST", "Sao Tome and Principe"}, {"SN", "Senegal"}, {"SC", "Seychelles"}, {"SL", "Sierra Leone"},
|
||||
{"SO", "Somalia"}, {"ZA", "South Africa"}, {"SS", "South Sudan"}, {"SD", "Sudan"},
|
||||
{"TZ", "Tanzania"}, {"TG", "Togo"}, {"TN", "Tunisia"}, {"UG", "Uganda"},
|
||||
{"EH", "Western Sahara"}, {"ZM", "Zambia"}, {"ZW", "Zimbabwe"}
|
||||
{"BF", "Burkina Faso"}, {"BI", "Burundi"}, {"CV", "Cape Verde"},
|
||||
{"CM", "Cameroon"}, {"CF", "Central African Republic"}, {"TD", "Chad"},
|
||||
{"KM", "Comoros"}, {"CG", "Congo (Brazzaville)"}, {"CD", "Congo (Kinshasa)"},
|
||||
{"CI", "Ivory Coast"}, {"DJ", "Djibouti"}, {"EG", "Egypt"},
|
||||
{"GQ", "Equatorial Guinea"}, {"ER", "Eritrea"}, {"SZ", "Eswatini"},
|
||||
{"ET", "Ethiopia"}, {"GA", "Gabon"}, {"GM", "Gambia"}, {"GH", "Ghana"},
|
||||
{"GN", "Guinea"}, {"GW", "Guinea-Bissau"}, {"KE", "Kenya"},
|
||||
{"LS", "Lesotho"}, {"LR", "Liberia"}, {"LY", "Libya"},
|
||||
{"MG", "Madagascar"}, {"MW", "Malawi"}, {"ML", "Mali"}, {"MR", "Mauritania"},
|
||||
{"MU", "Mauritius"}, {"MA", "Morocco"}, {"MZ", "Mozambique"},
|
||||
{"NA", "Namibia"}, {"NE", "Niger"}, {"NG", "Nigeria"},
|
||||
{"RW", "Rwanda"}, {"ST", "Sao Tome and Principe"},
|
||||
{"SN", "Senegal"}, {"SC", "Seychelles"}, {"SL", "Sierra Leone"},
|
||||
{"SO", "Somalia"}, {"ZA", "South Africa"}, {"SS", "South Sudan"},
|
||||
{"SD", "Sudan"}, {"TZ", "Tanzania"}, {"TG", "Togo"}, {"TN", "Tunisia"},
|
||||
{"UG", "Uganda"}, {"EH", "Western Sahara"}, {"ZM", "Zambia"},
|
||||
{"ZW", "Zimbabwe"}
|
||||
};
|
||||
|
||||
QMap<QString, QString> antarcticaMap = {
|
||||
@@ -71,57 +75,66 @@ QMap<QString, QString> antarcticaMap = {
|
||||
};
|
||||
|
||||
QMap<QString, QString> asiaMap = {
|
||||
{"AF", "Afghanistan"}, {"AM", "Armenia"}, {"AZ", "Azerbaijan"}, {"BH", "Bahrain"},
|
||||
{"BD", "Bangladesh"}, {"BT", "Bhutan"}, {"BN", "Brunei"}, {"KH", "Cambodia"},
|
||||
{"CN", "China"}, {"CY", "Cyprus"}, {"GE", "Georgia"}, {"IN", "India"},
|
||||
{"ID", "Indonesia"}, {"IR", "Iran"}, {"IQ", "Iraq"}, {"IL", "Israel"},
|
||||
{"JP", "Japan"}, {"JO", "Jordan"}, {"KZ", "Kazakhstan"}, {"KP", "North Korea"},
|
||||
{"KR", "South Korea"}, {"KW", "Kuwait"}, {"KG", "Kyrgyzstan"}, {"LA", "Laos"},
|
||||
{"LB", "Lebanon"}, {"MY", "Malaysia"}, {"MV", "Maldives"}, {"MN", "Mongolia"},
|
||||
{"MM", "Myanmar"}, {"NP", "Nepal"}, {"OM", "Oman"}, {"PK", "Pakistan"},
|
||||
{"PS", "Palestine"}, {"PH", "Philippines"}, {"QA", "Qatar"}, {"SA", "Saudi Arabia"},
|
||||
{"SG", "Singapore"}, {"LK", "Sri Lanka"}, {"SY", "Syria"}, {"TW", "Taiwan"},
|
||||
{"TJ", "Tajikistan"}, {"TH", "Thailand"}, {"TL", "Timor-Leste"}, {"TR", "Turkey"},
|
||||
{"TM", "Turkmenistan"}, {"AE", "United Arab Emirates"}, {"UZ", "Uzbekistan"}, {"VN", "Vietnam"},
|
||||
{"YE", "Yemen"}
|
||||
{"AF", "Afghanistan"}, {"AM", "Armenia"}, {"AZ", "Azerbaijan"},
|
||||
{"BH", "Bahrain"}, {"BD", "Bangladesh"}, {"BT", "Bhutan"},
|
||||
{"BN", "Brunei"}, {"MM", "Myanmar"}, {"KH", "Cambodia"}, {"CN", "China"},
|
||||
{"CY", "Cyprus"}, {"GE", "Georgia"}, {"IN", "India"}, {"ID", "Indonesia"},
|
||||
{"IR", "Iran"}, {"IQ", "Iraq"}, {"IL", "Israel"}, {"JP", "Japan"},
|
||||
{"JO", "Jordan"}, {"KZ", "Kazakhstan"}, {"KW", "Kuwait"}, {"KG", "Kyrgyzstan"},
|
||||
{"LA", "Laos"}, {"LB", "Lebanon"}, {"MV", "Maldives"}, {"MY", "Malaysia"},
|
||||
{"MN", "Mongolia"}, {"NP", "Nepal"}, {"OM", "Oman"}, {"PK", "Pakistan"},
|
||||
{"PH", "Philippines"}, {"QA", "Qatar"}, {"RU", "Russia"},
|
||||
{"SA", "Saudi Arabia"}, {"SG", "Singapore"}, {"KR", "South Korea"},
|
||||
{"LK", "Sri Lanka"}, {"SY", "Syria"}, {"TJ", "Tajikistan"},
|
||||
{"TH", "Thailand"}, {"TL", "Timor-Leste"}, {"TR", "Turkey"},
|
||||
{"TM", "Turkmenistan"}, {"AE", "United Arab Emirates"},
|
||||
{"UZ", "Uzbekistan"}, {"VN", "Vietnam"}, {"YE", "Yemen"}
|
||||
};
|
||||
|
||||
QMap<QString, QString> europeMap = {
|
||||
{"AL", "Albania"}, {"AD", "Andorra"}, {"AT", "Austria"}, {"BY", "Belarus"},
|
||||
{"BE", "Belgium"}, {"BA", "Bosnia and Herzegovina"}, {"BG", "Bulgaria"}, {"HR", "Croatia"},
|
||||
{"CY", "Cyprus"}, {"CZ", "Czech Republic"}, {"DK", "Denmark"}, {"EE", "Estonia"},
|
||||
{"FI", "Finland"}, {"FR", "France"}, {"DE", "Germany"}, {"GR", "Greece"},
|
||||
{"HU", "Hungary"}, {"IS", "Iceland"}, {"IE", "Ireland"}, {"IT", "Italy"},
|
||||
{"LV", "Latvia"}, {"LI", "Liechtenstein"}, {"LT", "Lithuania"}, {"LU", "Luxembourg"},
|
||||
{"MT", "Malta"}, {"MD", "Moldova"}, {"MC", "Monaco"}, {"ME", "Montenegro"},
|
||||
{"NL", "Netherlands"}, {"MK", "North Macedonia"}, {"NO", "Norway"}, {"PL", "Poland"},
|
||||
{"PT", "Portugal"}, {"RO", "Romania"}, {"RU", "Russia"}, {"SM", "San Marino"},
|
||||
{"RS", "Serbia"}, {"SK", "Slovakia"}, {"SI", "Slovenia"}, {"ES", "Spain"},
|
||||
{"SE", "Sweden"}, {"CH", "Switzerland"}, {"TR", "Turkey"}, {"UA", "Ukraine"},
|
||||
{"GB", "United Kingdom"}, {"VA", "Vatican City"}
|
||||
{"AL", "Albania"}, {"AD", "Andorra"}, {"AT", "Austria"},
|
||||
{"BY", "Belarus"}, {"BE", "Belgium"}, {"BA", "Bosnia and Herzegovina"},
|
||||
{"BG", "Bulgaria"}, {"HR", "Croatia"}, {"CY", "Cyprus"},
|
||||
{"CZ", "Czech Republic"}, {"DK", "Denmark"}, {"EE", "Estonia"},
|
||||
{"FI", "Finland"}, {"FR", "France"}, {"GE", "Georgia"},
|
||||
{"DE", "Germany"}, {"GR", "Greece"}, {"HU", "Hungary"},
|
||||
{"IS", "Iceland"}, {"IE", "Ireland"}, {"IT", "Italy"},
|
||||
{"LV", "Latvia"}, {"LI", "Liechtenstein"}, {"LT", "Lithuania"},
|
||||
{"LU", "Luxembourg"}, {"MT", "Malta"}, {"MD", "Moldova"},
|
||||
{"MC", "Monaco"}, {"ME", "Montenegro"}, {"NL", "Netherlands"},
|
||||
{"MK", "North Macedonia"}, {"NO", "Norway"}, {"PL", "Poland"},
|
||||
{"PT", "Portugal"}, {"RO", "Romania"}, {"RU", "Russia"},
|
||||
{"SM", "San Marino"}, {"RS", "Serbia"}, {"SK", "Slovakia"},
|
||||
{"SI", "Slovenia"}, {"ES", "Spain"}, {"SE", "Sweden"},
|
||||
{"CH", "Switzerland"}, {"UA", "Ukraine"}, {"GB", "United Kingdom"},
|
||||
{"VA", "Vatican City"}
|
||||
};
|
||||
|
||||
QMap<QString, QString> northAmericaMap = {
|
||||
{"AG", "Antigua and Barbuda"}, {"BS", "Bahamas"}, {"BB", "Barbados"}, {"BZ", "Belize"},
|
||||
{"CA", "Canada"}, {"CR", "Costa Rica"}, {"CU", "Cuba"}, {"DM", "Dominica"},
|
||||
{"DO", "Dominican Republic"}, {"SV", "El Salvador"}, {"GD", "Grenada"}, {"GT", "Guatemala"},
|
||||
{"HT", "Haiti"}, {"HN", "Honduras"}, {"JM", "Jamaica"}, {"MX", "Mexico"},
|
||||
{"NI", "Nicaragua"}, {"PA", "Panama"}, {"KN", "Saint Kitts and Nevis"}, {"LC", "Saint Lucia"},
|
||||
{"VC", "Saint Vincent and the Grenadines"}, {"TT", "Trinidad and Tobago"}, {"US", "United States"}
|
||||
{"AG", "Antigua and Barbuda"}, {"BS", "Bahamas"}, {"BB", "Barbados"},
|
||||
{"BZ", "Belize"}, {"CA", "Canada"}, {"CR", "Costa Rica"},
|
||||
{"CU", "Cuba"}, {"DM", "Dominica"}, {"DO", "Dominican Republic"},
|
||||
{"SV", "El Salvador"}, {"GD", "Grenada"}, {"GT", "Guatemala"},
|
||||
{"HT", "Haiti"}, {"HN", "Honduras"}, {"JM", "Jamaica"},
|
||||
{"MX", "Mexico"}, {"NI", "Nicaragua"}, {"PA", "Panama"},
|
||||
{"KN", "Saint Kitts and Nevis"}, {"LC", "Saint Lucia"},
|
||||
{"VC", "Saint Vincent and the Grenadines"}, {"TT", "Trinidad and Tobago"},
|
||||
{"US", "United States"}
|
||||
};
|
||||
|
||||
QMap<QString, QString> oceaniaMap = {
|
||||
{"AU", "Australia"}, {"FJ", "Fiji"}, {"KI", "Kiribati"}, {"MH", "Marshall Islands"},
|
||||
{"FM", "Micronesia"}, {"NR", "Nauru"}, {"NZ", "New Zealand"}, {"PW", "Palau"},
|
||||
{"PG", "Papua New Guinea"}, {"WS", "Samoa"}, {"SB", "Solomon Islands"}, {"TO", "Tonga"},
|
||||
{"AU", "Australia"}, {"FJ", "Fiji"}, {"FM", "Micronesia"},
|
||||
{"KI", "Kiribati"}, {"MH", "Marshall Islands"}, {"NR", "Nauru"},
|
||||
{"NZ", "New Zealand"}, {"PW", "Palau"}, {"PG", "Papua New Guinea"},
|
||||
{"WS", "Samoa"}, {"SB", "Solomon Islands"}, {"TO", "Tonga"},
|
||||
{"TV", "Tuvalu"}, {"VU", "Vanuatu"}
|
||||
};
|
||||
|
||||
QMap<QString, QString> southAmericaMap = {
|
||||
{"AR", "Argentina"}, {"BO", "Bolivia"}, {"BR", "Brazil"}, {"CL", "Chile"},
|
||||
{"CO", "Colombia"}, {"EC", "Ecuador"}, {"GY", "Guyana"}, {"PY", "Paraguay"},
|
||||
{"PE", "Peru"}, {"SR", "Suriname"}, {"TT", "Trinidad and Tobago"}, {"UY", "Uruguay"},
|
||||
{"VE", "Venezuela"}
|
||||
{"AR", "Argentina"}, {"BO", "Bolivia"}, {"BR", "Brazil"},
|
||||
{"CL", "Chile"}, {"CO", "Colombia"}, {"EC", "Ecuador"},
|
||||
{"GY", "Guyana"}, {"PY", "Paraguay"}, {"PE", "Peru"},
|
||||
{"SR", "Suriname"}, {"UY", "Uruguay"}, {"VE", "Venezuela"}
|
||||
};
|
||||
|
||||
class ButtonSelectionControl : public QWidget {
|
||||
@@ -145,7 +158,12 @@ public:
|
||||
|
||||
QJsonObject mapsSelected = QJsonDocument::fromJson(QString::fromStdString(Params().get("MapsSelected")).toUtf8()).object();
|
||||
|
||||
for (const QString &stateCode : map.keys()) {
|
||||
QList<QString> sortedKeys = map.keys();
|
||||
std::sort(sortedKeys.begin(), sortedKeys.end(), [&](const QString &a, const QString &b) {
|
||||
return map[a] < map[b];
|
||||
});
|
||||
|
||||
for (const QString &stateCode : sortedKeys) {
|
||||
if (count % max == 0 && count != 0) {
|
||||
buttonsLayout = new QHBoxLayout();
|
||||
buttonsLayout->setSpacing(10);
|
||||
|
||||
@@ -874,7 +874,7 @@ void AnnotatedCameraWidget::updateFrogPilotWidgets(int alert_height, const UISce
|
||||
unconfirmedSpeedLimit = speedLimitController ? scene.unconfirmed_speed_limit : 0;
|
||||
useViennaSLCSign = scene.use_vienna_slc_sign;
|
||||
|
||||
bool stoppedTimer = scene.stopped_timer && scene.standstill && scene.started_timer / UI_FREQ >= 10;
|
||||
bool stoppedTimer = scene.stopped_timer && scene.standstill && scene.started_timer / UI_FREQ >= 10 && !mapOpen;
|
||||
if (stoppedTimer) {
|
||||
if (!standstillTimer.isValid()) {
|
||||
standstillTimer.start();
|
||||
|
||||
@@ -161,6 +161,9 @@ void ExperimentalButton::paintEvent(QPaintEvent *event) {
|
||||
}
|
||||
|
||||
QPainter p(this);
|
||||
if (use_stock_wheel) {
|
||||
img = experimental_mode ? experimental_img : engage_img;
|
||||
}
|
||||
updateBackgroundColor();
|
||||
drawIcon(p, QPoint(btn_size / 2, btn_size / 2 + y_offset), img, background_color, (isDown() || !engageable) ? 0.6 : 1.0, steering_angle_deg);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user