From 995250ae4967943ee33a3699a1d89a7a770d95e9 Mon Sep 17 00:00:00 2001 From: Cameron Clough Date: Sun, 25 Feb 2024 00:41:23 +0000 Subject: [PATCH 01/41] use pyupgrade to update to new typing syntax (#31580) * add pyupgrade hook * run pyupgrade (pre-commit run -a) * ruff --fix * Revert "add pyupgrade hook" This reverts commit 56ec18bb6b8602a0b612f3803d96cdad14b52066. * revert changes to third_party/ * manual type fixes * explicit Optional wrapping capnp objects --- common/file_helpers.py | 3 +- common/gpio.py | 7 +- common/mock/__init__.py | 5 +- common/prefix.py | 3 +- common/realtime.py | 7 +- common/transformations/orientation.py | 2 +- openpilot/__init__.py | 3 - selfdrive/athena/athenad.py | 57 ++++++------ selfdrive/athena/registration.py | 9 +- selfdrive/athena/tests/test_athenad.py | 3 +- selfdrive/athena/tests/test_athenad_ping.py | 6 +- selfdrive/boardd/pandad.py | 4 +- selfdrive/car/__init__.py | 19 ++-- selfdrive/car/car_helpers.py | 6 +- selfdrive/car/chrysler/values.py | 3 +- selfdrive/car/docs.py | 15 ++-- selfdrive/car/docs_definitions.py | 33 ++++--- selfdrive/car/ecu_addrs.py | 13 ++- selfdrive/car/ford/tests/test_ford.py | 4 +- selfdrive/car/ford/values.py | 5 +- selfdrive/car/fw_query_definitions.py | 26 +++--- selfdrive/car/fw_versions.py | 27 +++--- selfdrive/car/gm/values.py | 5 +- selfdrive/car/honda/values.py | 3 +- selfdrive/car/hyundai/values.py | 9 +- selfdrive/car/interfaces.py | 23 ++--- selfdrive/car/mazda/values.py | 3 +- selfdrive/car/mock/values.py | 3 +- selfdrive/car/nissan/values.py | 3 +- selfdrive/car/subaru/values.py | 3 +- selfdrive/car/tesla/values.py | 3 +- selfdrive/car/tests/routes.py | 6 +- selfdrive/car/tests/test_docs.py | 4 +- selfdrive/car/tests/test_fingerprints.py | 3 +- selfdrive/car/tests/test_lateral_limits.py | 3 +- selfdrive/car/tests/test_models.py | 15 ++-- selfdrive/car/toyota/values.py | 7 +- selfdrive/car/volkswagen/values.py | 5 +- selfdrive/controls/lib/alertmanager.py | 11 ++- selfdrive/controls/lib/events.py | 18 ++-- selfdrive/controls/lib/vehicle_model.py | 3 +- selfdrive/controls/radard.py | 12 +-- selfdrive/debug/can_print_changes.py | 5 +- selfdrive/debug/check_freq.py | 6 +- selfdrive/debug/check_lag.py | 3 +- selfdrive/debug/check_timings.py | 4 +- selfdrive/debug/count_events.py | 6 +- selfdrive/debug/cpu_usage_stat.py | 4 +- selfdrive/debug/format_fingerprints.py | 2 +- .../internal/measure_modeld_packet_drop.py | 3 +- selfdrive/debug/live_cpu_and_temp.py | 7 +- selfdrive/locationd/calibrationd.py | 18 ++-- selfdrive/locationd/helpers.py | 10 +-- selfdrive/locationd/models/car_kf.py | 4 +- selfdrive/manager/build.py | 3 +- selfdrive/manager/manager.py | 7 +- selfdrive/manager/process.py | 12 +-- selfdrive/modeld/dmonitoringmodeld.py | 5 +- selfdrive/modeld/fill_model_msg.py | 5 +- selfdrive/modeld/get_model_metadata.py | 3 +- selfdrive/modeld/modeld.py | 9 +- selfdrive/modeld/navmodeld.py | 5 +- selfdrive/modeld/parse_model_outputs.py | 3 +- selfdrive/modeld/runners/onnxmodel.py | 4 +- selfdrive/navd/helpers.py | 16 ++-- selfdrive/statsd.py | 6 +- selfdrive/test/ciui.py | 4 +- selfdrive/test/fuzzy_generation.py | 17 ++-- selfdrive/test/helpers.py | 2 +- selfdrive/test/process_replay/capture.py | 4 +- selfdrive/test/process_replay/compare_logs.py | 3 +- .../test/process_replay/process_replay.py | 87 ++++++++++--------- selfdrive/test/process_replay/regen.py | 11 +-- selfdrive/test/process_replay/test_debayer.py | 2 +- .../test/process_replay/test_processes.py | 6 +- selfdrive/test/update_ci_routes.py | 6 +- selfdrive/thermald/power_monitoring.py | 5 +- selfdrive/thermald/thermald.py | 19 ++-- selfdrive/ui/soundd.py | 5 +- selfdrive/ui/tests/test_translations.py | 6 +- selfdrive/ui/translations/create_badges.py | 4 +- selfdrive/ui/update_translations.py | 2 +- selfdrive/updated.py | 11 ++- system/hardware/base.py | 3 +- system/hardware/tici/agnos.py | 6 +- system/hardware/tici/amplifier.py | 5 +- system/hardware/tici/casync.py | 18 ++-- system/hardware/tici/power_monitor.py | 3 +- system/hardware/tici/precise_power_measure.py | 2 +- .../tici/tests/compare_casync_manifest.py | 3 +- system/hardware/tici/tests/test_power_draw.py | 7 +- system/loggerd/deleter.py | 3 +- system/loggerd/tests/loggerd_tests_common.py | 5 +- system/loggerd/tests/test_deleter.py | 2 +- system/loggerd/tests/test_loggerd.py | 3 +- system/loggerd/tests/test_uploader.py | 5 +- system/loggerd/uploader.py | 15 ++-- system/loggerd/xattr_cache.py | 5 +- system/qcomgpsd/nmeaport.py | 2 +- system/qcomgpsd/qcomgpsd.py | 6 +- system/sensord/pigeond.py | 7 +- system/ubloxd/tests/ubloxd.py | 2 +- system/version.py | 7 +- system/webrtc/device/audio.py | 7 +- system/webrtc/device/video.py | 3 +- system/webrtc/schema.py | 8 +- system/webrtc/tests/test_webrtcd.py | 2 +- system/webrtc/webrtcd.py | 16 ++-- tools/bodyteleop/web.py | 4 +- tools/car_porting/auto_fingerprint.py | 3 +- tools/car_porting/test_car_model.py | 3 +- tools/latencylogger/latency_logger.py | 2 +- tools/lib/auth.py | 4 +- tools/lib/azure_container.py | 6 +- tools/lib/bootlog.py | 5 +- tools/lib/helpers.py | 14 +-- tools/lib/live_logreader.py | 5 +- tools/lib/logreader.py | 16 ++-- tools/lib/route.py | 4 +- tools/lib/tests/test_comma_car_segments.py | 2 - tools/lib/vidindex.py | 7 +- tools/replay/lib/ui_helpers.py | 4 +- tools/sim/bridge/common.py | 3 +- .../sim/bridge/metadrive/metadrive_bridge.py | 6 +- tools/sim/lib/manual_ctrl.py | 10 +-- 125 files changed, 464 insertions(+), 525 deletions(-) diff --git a/common/file_helpers.py b/common/file_helpers.py index dea298a529547a..417776b87ca345 100644 --- a/common/file_helpers.py +++ b/common/file_helpers.py @@ -1,7 +1,6 @@ import os import tempfile import contextlib -from typing import Optional class CallbackReader: @@ -24,7 +23,7 @@ def read(self, *args, **kwargs): @contextlib.contextmanager -def atomic_write_in_dir(path: str, mode: str = 'w', buffering: int = -1, encoding: Optional[str] = None, newline: Optional[str] = None, +def atomic_write_in_dir(path: str, mode: str = 'w', buffering: int = -1, encoding: str | None = None, newline: str | None = None, overwrite: bool = False): """Write to a file atomically using a temporary file in the same directory as the destination file.""" dir_name = os.path.dirname(path) diff --git a/common/gpio.py b/common/gpio.py index 88a9479a6081b5..68932cb87a2cb9 100644 --- a/common/gpio.py +++ b/common/gpio.py @@ -1,6 +1,5 @@ import os from functools import lru_cache -from typing import Optional, List def gpio_init(pin: int, output: bool) -> None: try: @@ -16,7 +15,7 @@ def gpio_set(pin: int, high: bool) -> None: except Exception as e: print(f"Failed to set gpio {pin} value: {e}") -def gpio_read(pin: int) -> Optional[bool]: +def gpio_read(pin: int) -> bool | None: val = None try: with open(f"/sys/class/gpio/gpio{pin}/value", 'rb') as f: @@ -37,7 +36,7 @@ def gpio_export(pin: int) -> None: print(f"Failed to export gpio {pin}") @lru_cache(maxsize=None) -def get_irq_action(irq: int) -> List[str]: +def get_irq_action(irq: int) -> list[str]: try: with open(f"/sys/kernel/irq/{irq}/actions") as f: actions = f.read().strip().split(',') @@ -45,7 +44,7 @@ def get_irq_action(irq: int) -> List[str]: except FileNotFoundError: return [] -def get_irqs_for_action(action: str) -> List[str]: +def get_irqs_for_action(action: str) -> list[str]: ret = [] with open("/proc/interrupts") as f: for l in f.readlines(): diff --git a/common/mock/__init__.py b/common/mock/__init__.py index e0dbf45c7423e9..8c86bbd394caee 100644 --- a/common/mock/__init__.py +++ b/common/mock/__init__.py @@ -6,7 +6,6 @@ import functools import threading -from typing import List, Union from cereal.messaging import PubMaster from cereal.services import SERVICE_LIST from openpilot.common.mock.generators import generate_liveLocationKalman @@ -18,7 +17,7 @@ } -def generate_messages_loop(services: List[str], done: threading.Event): +def generate_messages_loop(services: list[str], done: threading.Event): pm = PubMaster(services) rk = Ratekeeper(100) i = 0 @@ -32,7 +31,7 @@ def generate_messages_loop(services: List[str], done: threading.Event): rk.keep_time() -def mock_messages(services: Union[List[str], str]): +def mock_messages(services: list[str] | str): if isinstance(services, str): services = [services] diff --git a/common/prefix.py b/common/prefix.py index d027e3e5a13285..40f2f34b74f0ec 100644 --- a/common/prefix.py +++ b/common/prefix.py @@ -2,14 +2,13 @@ import shutil import uuid -from typing import Optional from openpilot.common.params import Params from openpilot.system.hardware.hw import Paths from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT class OpenpilotPrefix: - def __init__(self, prefix: Optional[str] = None, clean_dirs_on_exit: bool = True, shared_download_cache: bool = False): + def __init__(self, prefix: str | None = None, clean_dirs_on_exit: bool = True, shared_download_cache: bool = False): self.prefix = prefix if prefix else str(uuid.uuid4().hex[0:15]) self.msgq_path = os.path.join('/dev/shm', self.prefix) self.clean_dirs_on_exit = clean_dirs_on_exit diff --git a/common/realtime.py b/common/realtime.py index a398146166723e..6b8587ff068e95 100644 --- a/common/realtime.py +++ b/common/realtime.py @@ -3,7 +3,6 @@ import os import time from collections import deque -from typing import Optional, List, Union from setproctitle import getproctitle @@ -33,12 +32,12 @@ def set_realtime_priority(level: int) -> None: os.sched_setscheduler(0, os.SCHED_FIFO, os.sched_param(level)) -def set_core_affinity(cores: List[int]) -> None: +def set_core_affinity(cores: list[int]) -> None: if not PC: os.sched_setaffinity(0, cores) -def config_realtime_process(cores: Union[int, List[int]], priority: int) -> None: +def config_realtime_process(cores: int | list[int], priority: int) -> None: gc.disable() set_realtime_priority(priority) c = cores if isinstance(cores, list) else [cores, ] @@ -46,7 +45,7 @@ def config_realtime_process(cores: Union[int, List[int]], priority: int) -> None class Ratekeeper: - def __init__(self, rate: float, print_delay_threshold: Optional[float] = 0.0) -> None: + def __init__(self, rate: float, print_delay_threshold: float | None = 0.0) -> None: """Rate in Hz for ratekeeping. print_delay_threshold must be nonnegative.""" self._interval = 1. / rate self._next_frame_time = time.monotonic() + self._interval diff --git a/common/transformations/orientation.py b/common/transformations/orientation.py index ce4378738de6ea..86e6a6c34723be 100644 --- a/common/transformations/orientation.py +++ b/common/transformations/orientation.py @@ -1,5 +1,5 @@ import numpy as np -from typing import Callable +from collections.abc import Callable from openpilot.common.transformations.transformations import (ecef_euler_from_ned_single, euler2quat_single, diff --git a/openpilot/__init__.py b/openpilot/__init__.py index b28b04f643122b..e69de29bb2d1d6 100644 --- a/openpilot/__init__.py +++ b/openpilot/__init__.py @@ -1,3 +0,0 @@ - - - diff --git a/selfdrive/athena/athenad.py b/selfdrive/athena/athenad.py index cc3ab5e95b7e5a..9480d2b8ece750 100755 --- a/selfdrive/athena/athenad.py +++ b/selfdrive/athena/athenad.py @@ -19,7 +19,8 @@ from datetime import datetime from functools import partial from queue import Queue -from typing import Callable, Dict, List, Optional, Set, Union, cast +from typing import cast +from collections.abc import Callable import requests from jsonrpc import JSONRPCResponseManager, dispatcher @@ -55,17 +56,17 @@ NetworkType = log.DeviceState.NetworkType -UploadFileDict = Dict[str, Union[str, int, float, bool]] -UploadItemDict = Dict[str, Union[str, bool, int, float, Dict[str, str]]] +UploadFileDict = dict[str, str | int | float | bool] +UploadItemDict = dict[str, str | bool | int | float | dict[str, str]] -UploadFilesToUrlResponse = Dict[str, Union[int, List[UploadItemDict], List[str]]] +UploadFilesToUrlResponse = dict[str, int | list[UploadItemDict] | list[str]] @dataclass class UploadFile: fn: str url: str - headers: Dict[str, str] + headers: dict[str, str] allow_cellular: bool @classmethod @@ -77,9 +78,9 @@ def from_dict(cls, d: dict) -> UploadFile: class UploadItem: path: str url: str - headers: Dict[str, str] + headers: dict[str, str] created_at: int - id: Optional[str] + id: str | None retry_count: int = 0 current: bool = False progress: float = 0 @@ -97,9 +98,9 @@ def from_dict(cls, d: dict) -> UploadItem: upload_queue: Queue[UploadItem] = queue.Queue() low_priority_send_queue: Queue[str] = queue.Queue() log_recv_queue: Queue[str] = queue.Queue() -cancelled_uploads: Set[str] = set() +cancelled_uploads: set[str] = set() -cur_upload_items: Dict[int, Optional[UploadItem]] = {} +cur_upload_items: dict[int, UploadItem | None] = {} def strip_bz2_extension(fn: str) -> str: @@ -127,14 +128,14 @@ def initialize(upload_queue: Queue[UploadItem]) -> None: @staticmethod def cache(upload_queue: Queue[UploadItem]) -> None: try: - queue: List[Optional[UploadItem]] = list(upload_queue.queue) + queue: list[UploadItem | None] = list(upload_queue.queue) items = [asdict(i) for i in queue if i is not None and (i.id not in cancelled_uploads)] Params().put("AthenadUploadQueue", json.dumps(items)) except Exception: cloudlog.exception("athena.UploadQueueCache.cache.exception") -def handle_long_poll(ws: WebSocket, exit_event: Optional[threading.Event]) -> None: +def handle_long_poll(ws: WebSocket, exit_event: threading.Event | None) -> None: end_event = threading.Event() threads = [ @@ -278,7 +279,7 @@ def upload_handler(end_event: threading.Event) -> None: cloudlog.exception("athena.upload_handler.exception") -def _do_upload(upload_item: UploadItem, callback: Optional[Callable] = None) -> requests.Response: +def _do_upload(upload_item: UploadItem, callback: Callable | None = None) -> requests.Response: path = upload_item.path compress = False @@ -317,7 +318,7 @@ def getMessage(service: str, timeout: int = 1000) -> dict: @dispatcher.add_method -def getVersion() -> Dict[str, str]: +def getVersion() -> dict[str, str]: return { "version": get_version(), "remote": get_normalized_origin(), @@ -327,7 +328,7 @@ def getVersion() -> Dict[str, str]: @dispatcher.add_method -def setNavDestination(latitude: int = 0, longitude: int = 0, place_name: Optional[str] = None, place_details: Optional[str] = None) -> Dict[str, int]: +def setNavDestination(latitude: int = 0, longitude: int = 0, place_name: str | None = None, place_details: str | None = None) -> dict[str, int]: destination = { "latitude": latitude, "longitude": longitude, @@ -339,7 +340,7 @@ def setNavDestination(latitude: int = 0, longitude: int = 0, place_name: Optiona return {"success": 1} -def scan_dir(path: str, prefix: str) -> List[str]: +def scan_dir(path: str, prefix: str) -> list[str]: files = [] # only walk directories that match the prefix # (glob and friends traverse entire dir tree) @@ -359,12 +360,12 @@ def scan_dir(path: str, prefix: str) -> List[str]: return files @dispatcher.add_method -def listDataDirectory(prefix='') -> List[str]: +def listDataDirectory(prefix='') -> list[str]: return scan_dir(Paths.log_root(), prefix) @dispatcher.add_method -def uploadFileToUrl(fn: str, url: str, headers: Dict[str, str]) -> UploadFilesToUrlResponse: +def uploadFileToUrl(fn: str, url: str, headers: dict[str, str]) -> UploadFilesToUrlResponse: # this is because mypy doesn't understand that the decorator doesn't change the return type response: UploadFilesToUrlResponse = uploadFilesToUrls([{ "fn": fn, @@ -375,11 +376,11 @@ def uploadFileToUrl(fn: str, url: str, headers: Dict[str, str]) -> UploadFilesTo @dispatcher.add_method -def uploadFilesToUrls(files_data: List[UploadFileDict]) -> UploadFilesToUrlResponse: +def uploadFilesToUrls(files_data: list[UploadFileDict]) -> UploadFilesToUrlResponse: files = map(UploadFile.from_dict, files_data) - items: List[UploadItemDict] = [] - failed: List[str] = [] + items: list[UploadItemDict] = [] + failed: list[str] = [] for file in files: if len(file.fn) == 0 or file.fn[0] == '/' or '..' in file.fn or len(file.url) == 0: failed.append(file.fn) @@ -418,13 +419,13 @@ def uploadFilesToUrls(files_data: List[UploadFileDict]) -> UploadFilesToUrlRespo @dispatcher.add_method -def listUploadQueue() -> List[UploadItemDict]: +def listUploadQueue() -> list[UploadItemDict]: items = list(upload_queue.queue) + list(cur_upload_items.values()) return [asdict(i) for i in items if (i is not None) and (i.id not in cancelled_uploads)] @dispatcher.add_method -def cancelUpload(upload_id: Union[str, List[str]]) -> Dict[str, Union[int, str]]: +def cancelUpload(upload_id: str | list[str]) -> dict[str, int | str]: if not isinstance(upload_id, list): upload_id = [upload_id] @@ -437,7 +438,7 @@ def cancelUpload(upload_id: Union[str, List[str]]) -> Dict[str, Union[int, str]] return {"success": 1} @dispatcher.add_method -def setRouteViewed(route: str) -> Dict[str, Union[int, str]]: +def setRouteViewed(route: str) -> dict[str, int | str]: # maintain a list of the last 10 routes viewed in connect params = Params() @@ -452,7 +453,7 @@ def setRouteViewed(route: str) -> Dict[str, Union[int, str]]: return {"success": 1} -def startLocalProxy(global_end_event: threading.Event, remote_ws_uri: str, local_port: int) -> Dict[str, int]: +def startLocalProxy(global_end_event: threading.Event, remote_ws_uri: str, local_port: int) -> dict[str, int]: try: if local_port not in LOCAL_PORT_WHITELIST: raise Exception("Requested local port not whitelisted") @@ -486,7 +487,7 @@ def startLocalProxy(global_end_event: threading.Event, remote_ws_uri: str, local @dispatcher.add_method -def getPublicKey() -> Optional[str]: +def getPublicKey() -> str | None: if not os.path.isfile(Paths.persist_root() + '/comma/id_rsa.pub'): return None @@ -526,7 +527,7 @@ def getNetworks(): @dispatcher.add_method -def takeSnapshot() -> Optional[Union[str, Dict[str, str]]]: +def takeSnapshot() -> str | dict[str, str] | None: from openpilot.system.camerad.snapshot.snapshot import jpeg_write, snapshot ret = snapshot() if ret is not None: @@ -543,7 +544,7 @@ def b64jpeg(x): raise Exception("not available while camerad is started") -def get_logs_to_send_sorted() -> List[str]: +def get_logs_to_send_sorted() -> list[str]: # TODO: scan once then use inotify to detect file creation/deletion curr_time = int(time.time()) logs = [] @@ -766,7 +767,7 @@ def backoff(retries: int) -> int: return random.randrange(0, min(128, int(2 ** retries))) -def main(exit_event: Optional[threading.Event] = None): +def main(exit_event: threading.Event | None = None): try: set_core_affinity([0, 1, 2, 3]) except Exception: diff --git a/selfdrive/athena/registration.py b/selfdrive/athena/registration.py index 7db94c28c80874..6574d9ac202df3 100755 --- a/selfdrive/athena/registration.py +++ b/selfdrive/athena/registration.py @@ -3,7 +3,6 @@ import json import jwt from pathlib import Path -from typing import Optional from datetime import datetime, timedelta from openpilot.common.api import api_get @@ -23,12 +22,12 @@ def is_registered_device() -> bool: return dongle not in (None, UNREGISTERED_DONGLE_ID) -def register(show_spinner=False) -> Optional[str]: +def register(show_spinner=False) -> str | None: params = Params() IMEI = params.get("IMEI", encoding='utf8') HardwareSerial = params.get("HardwareSerial", encoding='utf8') - dongle_id: Optional[str] = params.get("DongleId", encoding='utf8') + dongle_id: str | None = params.get("DongleId", encoding='utf8') needs_registration = None in (IMEI, HardwareSerial, dongle_id) pubkey = Path(Paths.persist_root()+"/comma/id_rsa.pub") @@ -48,8 +47,8 @@ def register(show_spinner=False) -> Optional[str]: # Block until we get the imei serial = HARDWARE.get_serial() start_time = time.monotonic() - imei1: Optional[str] = None - imei2: Optional[str] = None + imei1: str | None = None + imei2: str | None = None while imei1 is None and imei2 is None: try: imei1, imei2 = HARDWARE.get_imei(0), HARDWARE.get_imei(1) diff --git a/selfdrive/athena/tests/test_athenad.py b/selfdrive/athena/tests/test_athenad.py index d59058d7e29b34..8d09661f010363 100755 --- a/selfdrive/athena/tests/test_athenad.py +++ b/selfdrive/athena/tests/test_athenad.py @@ -12,7 +12,6 @@ from dataclasses import asdict, replace from datetime import datetime, timedelta from parameterized import parameterized -from typing import Optional from unittest import mock from websocket import ABNF @@ -97,7 +96,7 @@ def _wait_for_upload(): break @staticmethod - def _create_file(file: str, parent: Optional[str] = None, data: bytes = b'') -> str: + def _create_file(file: str, parent: str | None = None, data: bytes = b'') -> str: fn = os.path.join(Paths.log_root() if parent is None else parent, file) os.makedirs(os.path.dirname(fn), exist_ok=True) with open(fn, 'wb') as f: diff --git a/selfdrive/athena/tests/test_athenad_ping.py b/selfdrive/athena/tests/test_athenad_ping.py index 7f32f60cb444d6..f56fcac8b58453 100755 --- a/selfdrive/athena/tests/test_athenad_ping.py +++ b/selfdrive/athena/tests/test_athenad_ping.py @@ -3,7 +3,7 @@ import threading import time import unittest -from typing import cast, Optional +from typing import cast from unittest import mock from openpilot.common.params import Params @@ -29,8 +29,8 @@ class TestAthenadPing(unittest.TestCase): athenad: threading.Thread exit_event: threading.Event - def _get_ping_time(self) -> Optional[str]: - return cast(Optional[str], self.params.get("LastAthenaPingTime", encoding="utf-8")) + def _get_ping_time(self) -> str | None: + return cast(str | None, self.params.get("LastAthenaPingTime", encoding="utf-8")) def _clear_ping_time(self) -> None: self.params.remove("LastAthenaPingTime") diff --git a/selfdrive/boardd/pandad.py b/selfdrive/boardd/pandad.py index a87613c8034b51..988d1a24095da9 100755 --- a/selfdrive/boardd/pandad.py +++ b/selfdrive/boardd/pandad.py @@ -4,7 +4,7 @@ import usb1 import time import subprocess -from typing import List, NoReturn +from typing import NoReturn from functools import cmp_to_key from panda import Panda, PandaDFU, PandaProtocolMismatch, FW_PATH @@ -124,7 +124,7 @@ def main() -> NoReturn: cloudlog.info(f"{len(panda_serials)} panda(s) found, connecting - {panda_serials}") # Flash pandas - pandas: List[Panda] = [] + pandas: list[Panda] = [] for serial in panda_serials: pandas.append(flash_panda(serial)) diff --git a/selfdrive/car/__init__.py b/selfdrive/car/__init__.py index 8f2c8bd451872b..7544796b930533 100644 --- a/selfdrive/car/__init__.py +++ b/selfdrive/car/__init__.py @@ -2,7 +2,6 @@ from collections import namedtuple from dataclasses import dataclass from enum import ReprEnum -from typing import Dict, List, Optional, Union import capnp @@ -27,9 +26,9 @@ def apply_hysteresis(val: float, val_steady: float, hyst_gap: float) -> float: return val_steady -def create_button_events(cur_btn: int, prev_btn: int, buttons_dict: Dict[int, capnp.lib.capnp._EnumModule], - unpressed_btn: int = 0) -> List[capnp.lib.capnp._DynamicStructBuilder]: - events: List[capnp.lib.capnp._DynamicStructBuilder] = [] +def create_button_events(cur_btn: int, prev_btn: int, buttons_dict: dict[int, capnp.lib.capnp._EnumModule], + unpressed_btn: int = 0) -> list[capnp.lib.capnp._DynamicStructBuilder]: + events: list[capnp.lib.capnp._DynamicStructBuilder] = [] if cur_btn == prev_btn: return events @@ -76,7 +75,7 @@ def scale_tire_stiffness(mass, wheelbase, center_to_front, tire_stiffness_factor return tire_stiffness_front, tire_stiffness_rear -DbcDict = Dict[str, str] +DbcDict = dict[str, str] def dbc_dict(pt_dbc, radar_dbc, chassis_dbc=None, body_dbc=None) -> DbcDict: @@ -214,7 +213,7 @@ def get_safety_config(safety_model, safety_param = None): class CanBusBase: offset: int - def __init__(self, CP, fingerprint: Optional[Dict[int, Dict[int, int]]]) -> None: + def __init__(self, CP, fingerprint: dict[int, dict[int, int]] | None) -> None: if CP is None: assert fingerprint is not None num = max([k for k, v in fingerprint.items() if len(v)], default=0) // 4 + 1 @@ -244,7 +243,7 @@ def update(self, current_value, current_counter): return self.rate -CarInfos = Union[CarInfo, List[CarInfo]] +CarInfos = CarInfo | list[CarInfo] @dataclass @@ -260,7 +259,7 @@ class PlatformConfig: car_info: CarInfos dbc_dict: DbcDict - specs: Optional[CarSpecs] = None + specs: CarSpecs | None = None def __hash__(self) -> int: return hash(self.platform_str) @@ -276,9 +275,9 @@ def __new__(cls, platform_config: PlatformConfig): return member @classmethod - def create_dbc_map(cls) -> Dict[str, DbcDict]: + def create_dbc_map(cls) -> dict[str, DbcDict]: return {p: p.config.dbc_dict for p in cls} @classmethod - def create_carinfo_map(cls) -> Dict[str, CarInfos]: + def create_carinfo_map(cls) -> dict[str, CarInfos]: return {p: p.config.car_info for p in cls} diff --git a/selfdrive/car/car_helpers.py b/selfdrive/car/car_helpers.py index 95028e10c5d06c..fe4c0e885ca652 100644 --- a/selfdrive/car/car_helpers.py +++ b/selfdrive/car/car_helpers.py @@ -1,6 +1,6 @@ import os import time -from typing import Callable, Dict, List, Optional, Tuple +from collections.abc import Callable from cereal import car from openpilot.common.params import Params @@ -63,7 +63,7 @@ def load_interfaces(brand_names): return ret -def _get_interface_names() -> Dict[str, List[str]]: +def _get_interface_names() -> dict[str, list[str]]: # returns a dict of brand name and its respective models brand_names = {} for brand_name, brand_models in get_interface_attr("CAR").items(): @@ -77,7 +77,7 @@ def _get_interface_names() -> Dict[str, List[str]]: interfaces = load_interfaces(interface_names) -def can_fingerprint(next_can: Callable) -> Tuple[Optional[str], Dict[int, dict]]: +def can_fingerprint(next_can: Callable) -> tuple[str | None, dict[int, dict]]: finger = gen_empty_fingerprint() candidate_cars = {i: all_legacy_fingerprint_cars() for i in [0, 1]} # attempt fingerprint on both bus 0 and 1 frame = 0 diff --git a/selfdrive/car/chrysler/values.py b/selfdrive/car/chrysler/values.py index 94ff1f1d0f3d39..a7eec8fe5ae0be 100644 --- a/selfdrive/car/chrysler/values.py +++ b/selfdrive/car/chrysler/values.py @@ -1,6 +1,5 @@ from enum import IntFlag, StrEnum from dataclasses import dataclass, field -from typing import Dict, List, Optional, Union from cereal import car from panda.python import uds @@ -66,7 +65,7 @@ class ChryslerCarInfo(CarInfo): car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.fca])) -CAR_INFO: Dict[str, Optional[Union[ChryslerCarInfo, List[ChryslerCarInfo]]]] = { +CAR_INFO: dict[str, ChryslerCarInfo | list[ChryslerCarInfo] | None] = { CAR.PACIFICA_2017_HYBRID: ChryslerCarInfo("Chrysler Pacifica Hybrid 2017"), CAR.PACIFICA_2018_HYBRID: ChryslerCarInfo("Chrysler Pacifica Hybrid 2018"), CAR.PACIFICA_2019_HYBRID: ChryslerCarInfo("Chrysler Pacifica Hybrid 2019-23"), diff --git a/selfdrive/car/docs.py b/selfdrive/car/docs.py index 8475a69d8a084d..caa79a8f87505f 100755 --- a/selfdrive/car/docs.py +++ b/selfdrive/car/docs.py @@ -5,7 +5,6 @@ import os from enum import Enum from natsort import natsorted -from typing import Dict, List from cereal import car from openpilot.common.basedir import BASEDIR @@ -14,7 +13,7 @@ from openpilot.selfdrive.car.car_helpers import interfaces, get_interface_attr -def get_all_footnotes() -> Dict[Enum, int]: +def get_all_footnotes() -> dict[Enum, int]: all_footnotes = list(CommonFootnote) for footnotes in get_interface_attr("Footnote", ignore_none=True).values(): all_footnotes.extend(footnotes) @@ -25,8 +24,8 @@ def get_all_footnotes() -> Dict[Enum, int]: CARS_MD_TEMPLATE = os.path.join(BASEDIR, "selfdrive", "car", "CARS_template.md") -def get_all_car_info() -> List[CarInfo]: - all_car_info: List[CarInfo] = [] +def get_all_car_info() -> list[CarInfo]: + all_car_info: list[CarInfo] = [] footnotes = get_all_footnotes() for model, car_info in get_interface_attr("CAR_INFO", combine_brands=True).items(): # If available, uses experimental longitudinal limits for the docs @@ -47,19 +46,19 @@ def get_all_car_info() -> List[CarInfo]: all_car_info.append(_car_info) # Sort cars by make and model + year - sorted_cars: List[CarInfo] = natsorted(all_car_info, key=lambda car: car.name.lower()) + sorted_cars: list[CarInfo] = natsorted(all_car_info, key=lambda car: car.name.lower()) return sorted_cars -def group_by_make(all_car_info: List[CarInfo]) -> Dict[str, List[CarInfo]]: +def group_by_make(all_car_info: list[CarInfo]) -> dict[str, list[CarInfo]]: sorted_car_info = defaultdict(list) for car_info in all_car_info: sorted_car_info[car_info.make].append(car_info) return dict(sorted_car_info) -def generate_cars_md(all_car_info: List[CarInfo], template_fn: str) -> str: - with open(template_fn, "r") as f: +def generate_cars_md(all_car_info: list[CarInfo], template_fn: str) -> str: + with open(template_fn) as f: template = jinja2.Template(f.read(), trim_blocks=True, lstrip_blocks=True) footnotes = [fn.value.text for fn in get_all_footnotes()] diff --git a/selfdrive/car/docs_definitions.py b/selfdrive/car/docs_definitions.py index f2ce743607b27d..03ed1f32cb5d26 100644 --- a/selfdrive/car/docs_definitions.py +++ b/selfdrive/car/docs_definitions.py @@ -3,7 +3,6 @@ import copy from dataclasses import dataclass, field from enum import Enum -from typing import Dict, List, Optional, Tuple, Union from cereal import car from openpilot.common.conversions import Conversions as CV @@ -35,7 +34,7 @@ class Star(Enum): @dataclass class BasePart: name: str - parts: List[Enum] = field(default_factory=list) + parts: list[Enum] = field(default_factory=list) def all_parts(self): # Recursively get all parts @@ -76,7 +75,7 @@ class Accessory(EnumBase): @dataclass class BaseCarHarness(BasePart): - parts: List[Enum] = field(default_factory=lambda: [Accessory.harness_box, Accessory.comma_power_v2, Cable.rj45_cable_7ft]) + parts: list[Enum] = field(default_factory=lambda: [Accessory.harness_box, Accessory.comma_power_v2, Cable.rj45_cable_7ft]) has_connector: bool = True # without are hidden on the harness connector page @@ -149,18 +148,18 @@ class PartType(Enum): tool = Tool -DEFAULT_CAR_PARTS: List[EnumBase] = [Device.threex] +DEFAULT_CAR_PARTS: list[EnumBase] = [Device.threex] @dataclass class CarParts: - parts: List[EnumBase] = field(default_factory=list) + parts: list[EnumBase] = field(default_factory=list) def __call__(self): return copy.deepcopy(self) @classmethod - def common(cls, add: Optional[List[EnumBase]] = None, remove: Optional[List[EnumBase]] = None): + def common(cls, add: list[EnumBase] | None = None, remove: list[EnumBase] | None = None): p = [part for part in (add or []) + DEFAULT_CAR_PARTS if part not in (remove or [])] return cls(p) @@ -186,7 +185,7 @@ class CommonFootnote(Enum): Column.LONGITUDINAL) -def get_footnotes(footnotes: List[Enum], column: Column) -> List[Enum]: +def get_footnotes(footnotes: list[Enum], column: Column) -> list[Enum]: # Returns applicable footnotes given current column return [fn for fn in footnotes if fn.value.column == column] @@ -209,7 +208,7 @@ def get_year_list(years): return years_list -def split_name(name: str) -> Tuple[str, str, str]: +def split_name(name: str) -> tuple[str, str, str]: make, model = name.split(" ", 1) years = "" match = re.search(MODEL_YEARS_RE, model) @@ -233,13 +232,13 @@ class CarInfo: # the minimum compatibility requirements for this model, regardless # of market. can be a package, trim, or list of features - requirements: Optional[str] = None + requirements: str | None = None - video_link: Optional[str] = None - footnotes: List[Enum] = field(default_factory=list) - min_steer_speed: Optional[float] = None - min_enable_speed: Optional[float] = None - auto_resume: Optional[bool] = None + video_link: str | None = None + footnotes: list[Enum] = field(default_factory=list) + min_steer_speed: float | None = None + min_enable_speed: float | None = None + auto_resume: bool | None = None # all the parts needed for the supported car car_parts: CarParts = field(default_factory=CarParts) @@ -248,7 +247,7 @@ def __post_init__(self): self.make, self.model, self.years = split_name(self.name) self.year_list = get_year_list(self.years) - def init(self, CP: car.CarParams, all_footnotes: Dict[Enum, int]): + def init(self, CP: car.CarParams, all_footnotes: dict[Enum, int]): self.car_name = CP.carName self.car_fingerprint = CP.carFingerprint @@ -293,7 +292,7 @@ def display_func(parts): if len(tools_docs): hardware_col += f'
Tools{display_func(tools_docs)}
' - self.row: Dict[Enum, Union[str, Star]] = { + self.row: dict[Enum, str | Star] = { Column.MAKE: self.make, Column.MODEL: self.model, Column.PACKAGE: self.package, @@ -352,7 +351,7 @@ def get_detail_sentence(self, CP): raise Exception(f"This notCar does not have a detail sentence: {CP.carFingerprint}") def get_column(self, column: Column, star_icon: str, video_icon: str, footnote_tag: str) -> str: - item: Union[str, Star] = self.row[column] + item: str | Star = self.row[column] if isinstance(item, Star): item = star_icon.format(item.value) elif column == Column.MODEL and len(self.years): diff --git a/selfdrive/car/ecu_addrs.py b/selfdrive/car/ecu_addrs.py index 13f7926defd6ec..6d6fa333a55b6f 100755 --- a/selfdrive/car/ecu_addrs.py +++ b/selfdrive/car/ecu_addrs.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 import capnp import time -from typing import Optional, Set import cereal.messaging as messaging from panda.python.uds import SERVICE_TYPE @@ -20,7 +19,7 @@ def make_tester_present_msg(addr, bus, subaddr=None): return make_can_msg(addr, bytes(dat), bus) -def is_tester_present_response(msg: capnp.lib.capnp._DynamicStructReader, subaddr: Optional[int] = None) -> bool: +def is_tester_present_response(msg: capnp.lib.capnp._DynamicStructReader, subaddr: int | None = None) -> bool: # ISO-TP messages are always padded to 8 bytes # tester present response is always a single frame dat_offset = 1 if subaddr is not None else 0 @@ -34,16 +33,16 @@ def is_tester_present_response(msg: capnp.lib.capnp._DynamicStructReader, subadd return False -def get_all_ecu_addrs(logcan: messaging.SubSocket, sendcan: messaging.PubSocket, bus: int, timeout: float = 1, debug: bool = True) -> Set[EcuAddrBusType]: +def get_all_ecu_addrs(logcan: messaging.SubSocket, sendcan: messaging.PubSocket, bus: int, timeout: float = 1, debug: bool = True) -> set[EcuAddrBusType]: addr_list = [0x700 + i for i in range(256)] + [0x18da00f1 + (i << 8) for i in range(256)] - queries: Set[EcuAddrBusType] = {(addr, None, bus) for addr in addr_list} + queries: set[EcuAddrBusType] = {(addr, None, bus) for addr in addr_list} responses = queries return get_ecu_addrs(logcan, sendcan, queries, responses, timeout=timeout, debug=debug) -def get_ecu_addrs(logcan: messaging.SubSocket, sendcan: messaging.PubSocket, queries: Set[EcuAddrBusType], - responses: Set[EcuAddrBusType], timeout: float = 1, debug: bool = False) -> Set[EcuAddrBusType]: - ecu_responses: Set[EcuAddrBusType] = set() # set((addr, subaddr, bus),) +def get_ecu_addrs(logcan: messaging.SubSocket, sendcan: messaging.PubSocket, queries: set[EcuAddrBusType], + responses: set[EcuAddrBusType], timeout: float = 1, debug: bool = False) -> set[EcuAddrBusType]: + ecu_responses: set[EcuAddrBusType] = set() # set((addr, subaddr, bus),) try: msgs = [make_tester_present_msg(addr, bus, subaddr) for addr, subaddr, bus in queries] diff --git a/selfdrive/car/ford/tests/test_ford.py b/selfdrive/car/ford/tests/test_ford.py index dff29629f6726c..fb5d07f4bfd44f 100755 --- a/selfdrive/car/ford/tests/test_ford.py +++ b/selfdrive/car/ford/tests/test_ford.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 import unittest from parameterized import parameterized -from typing import Dict, Iterable, Optional, Tuple +from collections.abc import Iterable import capnp @@ -50,7 +50,7 @@ def test_fw_query_config(self): self.assertIsNone(subaddr, "Unexpected ECU subaddress") @parameterized.expand(FW_VERSIONS.items()) - def test_fw_versions(self, car_model: str, fw_versions: Dict[Tuple[capnp.lib.capnp._EnumModule, int, Optional[int]], Iterable[bytes]]): + def test_fw_versions(self, car_model: str, fw_versions: dict[tuple[capnp.lib.capnp._EnumModule, int, int | None], Iterable[bytes]]): for (ecu, addr, subaddr), fws in fw_versions.items(): self.assertIn(ecu, ECU_FW_CORE, "Unexpected ECU") self.assertEqual(addr, ECU_ADDRESSES[ecu], "ECU address mismatch") diff --git a/selfdrive/car/ford/values.py b/selfdrive/car/ford/values.py index 8704a7b72487ce..3ad39d715ffc8d 100644 --- a/selfdrive/car/ford/values.py +++ b/selfdrive/car/ford/values.py @@ -1,7 +1,6 @@ from collections import defaultdict from dataclasses import dataclass from enum import Enum, StrEnum -from typing import Dict, List, Union from cereal import car from openpilot.selfdrive.car import AngleRateLimit, dbc_dict @@ -59,7 +58,7 @@ class RADAR: DELPHI_MRR = 'FORD_CADS' -DBC: Dict[str, Dict[str, str]] = defaultdict(lambda: dbc_dict("ford_lincoln_base_pt", RADAR.DELPHI_MRR)) +DBC: dict[str, dict[str, str]] = defaultdict(lambda: dbc_dict("ford_lincoln_base_pt", RADAR.DELPHI_MRR)) # F-150 radar is not yet supported DBC[CAR.F_150_MK14] = dbc_dict("ford_lincoln_base_pt", None) @@ -87,7 +86,7 @@ def init_make(self, CP: car.CarParams): self.car_parts = CarParts([Device.threex, harness]) -CAR_INFO: Dict[str, Union[CarInfo, List[CarInfo]]] = { +CAR_INFO: dict[str, CarInfo | list[CarInfo]] = { CAR.BRONCO_SPORT_MK1: FordCarInfo("Ford Bronco Sport 2021-22"), CAR.ESCAPE_MK4: [ FordCarInfo("Ford Escape 2020-22"), diff --git a/selfdrive/car/fw_query_definitions.py b/selfdrive/car/fw_query_definitions.py index 36e6794d2c1a50..80492b4177d5e7 100755 --- a/selfdrive/car/fw_query_definitions.py +++ b/selfdrive/car/fw_query_definitions.py @@ -3,16 +3,16 @@ import copy from dataclasses import dataclass, field import struct -from typing import Callable, Dict, List, Optional, Set, Tuple +from collections.abc import Callable import panda.python.uds as uds -AddrType = Tuple[int, Optional[int]] -EcuAddrBusType = Tuple[int, Optional[int], int] -EcuAddrSubAddr = Tuple[int, int, Optional[int]] +AddrType = tuple[int, int | None] +EcuAddrBusType = tuple[int, int | None, int] +EcuAddrSubAddr = tuple[int, int, int | None] -LiveFwVersions = Dict[AddrType, Set[bytes]] -OfflineFwVersions = Dict[str, Dict[EcuAddrSubAddr, List[bytes]]] +LiveFwVersions = dict[AddrType, set[bytes]] +OfflineFwVersions = dict[str, dict[EcuAddrSubAddr, list[bytes]]] # A global list of addresses we will only ever consider for VIN responses # engine, hybrid controller, Ford abs, Hyundai CAN FD cluster, 29-bit engine, PGM-FI @@ -71,9 +71,9 @@ class StdQueries: @dataclass class Request: - request: List[bytes] - response: List[bytes] - whitelist_ecus: List[int] = field(default_factory=list) + request: list[bytes] + response: list[bytes] + whitelist_ecus: list[int] = field(default_factory=list) rx_offset: int = 0x8 bus: int = 1 # Whether this query should be run on the first auxiliary panda (CAN FD cars for example) @@ -86,15 +86,15 @@ class Request: @dataclass class FwQueryConfig: - requests: List[Request] + requests: list[Request] # TODO: make this automatic and remove hardcoded lists, or do fingerprinting with ecus # Overrides and removes from essential ecus for specific models and ecus (exact matching) - non_essential_ecus: Dict[capnp.lib.capnp._EnumModule, List[str]] = field(default_factory=dict) + non_essential_ecus: dict[capnp.lib.capnp._EnumModule, list[str]] = field(default_factory=dict) # Ecus added for data collection, not to be fingerprinted on - extra_ecus: List[Tuple[capnp.lib.capnp._EnumModule, int, Optional[int]]] = field(default_factory=list) + extra_ecus: list[tuple[capnp.lib.capnp._EnumModule, int, int | None]] = field(default_factory=list) # Function a brand can implement to provide better fuzzy matching. Takes in FW versions, # returns set of candidates. Only will match if one candidate is returned - match_fw_to_car_fuzzy: Optional[Callable[[LiveFwVersions, OfflineFwVersions], Set[str]]] = None + match_fw_to_car_fuzzy: Callable[[LiveFwVersions, OfflineFwVersions], set[str]] | None = None def __post_init__(self): for i in range(len(self.requests)): diff --git a/selfdrive/car/fw_versions.py b/selfdrive/car/fw_versions.py index 6c02e69503f3c1..1cf4cecd3e22f4 100755 --- a/selfdrive/car/fw_versions.py +++ b/selfdrive/car/fw_versions.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 from collections import defaultdict -from typing import Any, DefaultDict, Dict, Iterator, List, Optional, Set, TypeVar +from typing import Any, TypeVar +from collections.abc import Iterator from tqdm import tqdm import capnp @@ -27,19 +28,19 @@ T = TypeVar('T') -def chunks(l: List[T], n: int = 128) -> Iterator[List[T]]: +def chunks(l: list[T], n: int = 128) -> Iterator[list[T]]: for i in range(0, len(l), n): yield l[i:i + n] -def is_brand(brand: str, filter_brand: Optional[str]) -> bool: +def is_brand(brand: str, filter_brand: str | None) -> bool: """Returns if brand matches filter_brand or no brand filter is specified""" return filter_brand is None or brand == filter_brand -def build_fw_dict(fw_versions: List[capnp.lib.capnp._DynamicStructBuilder], - filter_brand: Optional[str] = None) -> Dict[AddrType, Set[bytes]]: - fw_versions_dict: DefaultDict[AddrType, Set[bytes]] = defaultdict(set) +def build_fw_dict(fw_versions: list[capnp.lib.capnp._DynamicStructBuilder], + filter_brand: str | None = None) -> dict[AddrType, set[bytes]]: + fw_versions_dict: defaultdict[AddrType, set[bytes]] = defaultdict(set) for fw in fw_versions: if is_brand(fw.brand, filter_brand) and not fw.logging: sub_addr = fw.subAddress if fw.subAddress != 0 else None @@ -97,7 +98,7 @@ def match_fw_to_car_fuzzy(live_fw_versions, match_brand=None, log=True, exclude= return set() -def match_fw_to_car_exact(live_fw_versions, match_brand=None, log=True, extra_fw_versions=None) -> Set[str]: +def match_fw_to_car_exact(live_fw_versions, match_brand=None, log=True, extra_fw_versions=None) -> set[str]: """Do an exact FW match. Returns all cars that match the given FW versions for a list of "essential" ECUs. If an ECU is not considered essential the FW version can be missing to get a fingerprint, but if it's present it @@ -164,11 +165,11 @@ def match_fw_to_car(fw_versions, allow_exact=True, allow_fuzzy=True, log=True): return True, set() -def get_present_ecus(logcan, sendcan, num_pandas=1) -> Set[EcuAddrBusType]: +def get_present_ecus(logcan, sendcan, num_pandas=1) -> set[EcuAddrBusType]: params = Params() # queries are split by OBD multiplexing mode - queries: Dict[bool, List[List[EcuAddrBusType]]] = {True: [], False: []} - parallel_queries: Dict[bool, List[EcuAddrBusType]] = {True: [], False: []} + queries: dict[bool, list[list[EcuAddrBusType]]] = {True: [], False: []} + parallel_queries: dict[bool, list[EcuAddrBusType]] = {True: [], False: []} responses = set() for brand, config, r in REQUESTS: @@ -203,7 +204,7 @@ def get_present_ecus(logcan, sendcan, num_pandas=1) -> Set[EcuAddrBusType]: return ecu_responses -def get_brand_ecu_matches(ecu_rx_addrs: Set[EcuAddrBusType]) -> dict[str, set[AddrType]]: +def get_brand_ecu_matches(ecu_rx_addrs: set[EcuAddrBusType]) -> dict[str, set[AddrType]]: """Returns dictionary of brands and matches with ECUs in their FW versions""" brand_addrs = {brand: {(addr, subaddr) for _, addr, subaddr in config.get_all_ecus(VERSIONS[brand])} for @@ -231,7 +232,7 @@ def set_obd_multiplexing(params: Params, obd_multiplexing: bool): def get_fw_versions_ordered(logcan, sendcan, ecu_rx_addrs, timeout=0.1, num_pandas=1, debug=False, progress=False) -> \ - List[capnp.lib.capnp._DynamicStructBuilder]: + list[capnp.lib.capnp._DynamicStructBuilder]: """Queries for FW versions ordering brands by likelihood, breaks when exact match is found""" all_car_fw = [] @@ -254,7 +255,7 @@ def get_fw_versions_ordered(logcan, sendcan, ecu_rx_addrs, timeout=0.1, num_pand def get_fw_versions(logcan, sendcan, query_brand=None, extra=None, timeout=0.1, num_pandas=1, debug=False, progress=False) -> \ - List[capnp.lib.capnp._DynamicStructBuilder]: + list[capnp.lib.capnp._DynamicStructBuilder]: versions = VERSIONS.copy() params = Params() diff --git a/selfdrive/car/gm/values.py b/selfdrive/car/gm/values.py index 8188ad4e6e78b0..5c4d572fdb9233 100644 --- a/selfdrive/car/gm/values.py +++ b/selfdrive/car/gm/values.py @@ -1,7 +1,6 @@ from collections import defaultdict from dataclasses import dataclass from enum import Enum, StrEnum -from typing import Dict, List, Union from cereal import car from openpilot.selfdrive.car import dbc_dict @@ -98,7 +97,7 @@ def init_make(self, CP: car.CarParams): self.footnotes.append(Footnote.OBD_II) -CAR_INFO: Dict[str, Union[GMCarInfo, List[GMCarInfo]]] = { +CAR_INFO: dict[str, GMCarInfo | list[GMCarInfo]] = { CAR.HOLDEN_ASTRA: GMCarInfo("Holden Astra 2017"), CAR.VOLT: GMCarInfo("Chevrolet Volt 2017-18", min_enable_speed=0, video_link="https://youtu.be/QeMCN_4TFfQ"), CAR.CADILLAC_ATS: GMCarInfo("Cadillac ATS Premium Performance 2018"), @@ -181,7 +180,7 @@ class CanBus: extra_ecus=[(Ecu.fwdCamera, 0x24b, None)], ) -DBC: Dict[str, Dict[str, str]] = defaultdict(lambda: dbc_dict('gm_global_a_powertrain_generated', 'gm_global_a_object', chassis_dbc='gm_global_a_chassis')) +DBC: dict[str, dict[str, str]] = defaultdict(lambda: dbc_dict('gm_global_a_powertrain_generated', 'gm_global_a_object', chassis_dbc='gm_global_a_chassis')) EV_CAR = {CAR.VOLT, CAR.BOLT_EUV} diff --git a/selfdrive/car/honda/values.py b/selfdrive/car/honda/values.py index 517d2550a4a144..a2ef757d150d2b 100644 --- a/selfdrive/car/honda/values.py +++ b/selfdrive/car/honda/values.py @@ -1,6 +1,5 @@ from dataclasses import dataclass from enum import Enum, IntFlag, StrEnum -from typing import Dict, List, Optional, Union from cereal import car from openpilot.common.conversions import Conversions as CV @@ -116,7 +115,7 @@ def init_make(self, CP: car.CarParams): self.car_parts = CarParts.common([CarHarness.nidec]) -CAR_INFO: Dict[str, Optional[Union[HondaCarInfo, List[HondaCarInfo]]]] = { +CAR_INFO: dict[str, HondaCarInfo | list[HondaCarInfo] | None] = { CAR.ACCORD: [ HondaCarInfo("Honda Accord 2018-22", "All", video_link="https://www.youtube.com/watch?v=mrUwlj3Mi58", min_steer_speed=3. * CV.MPH_TO_MS), HondaCarInfo("Honda Inspire 2018", "All", min_steer_speed=3. * CV.MPH_TO_MS), diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index 20fc29897ddfe7..76ff0b39ceba7d 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -1,7 +1,6 @@ import re from dataclasses import dataclass from enum import Enum, IntFlag, StrEnum -from typing import Dict, List, Optional, Set, Tuple, Union from cereal import car from panda.python import uds @@ -157,7 +156,7 @@ def init_make(self, CP: car.CarParams): self.footnotes.insert(0, Footnote.CANFD) -CAR_INFO: Dict[str, Optional[Union[HyundaiCarInfo, List[HyundaiCarInfo]]]] = { +CAR_INFO: dict[str, HyundaiCarInfo | list[HyundaiCarInfo] | None] = { CAR.AZERA_6TH_GEN: HyundaiCarInfo("Hyundai Azera 2022", "All", car_parts=CarParts.common([CarHarness.hyundai_k])), CAR.AZERA_HEV_6TH_GEN: [ HyundaiCarInfo("Hyundai Azera Hybrid 2019", "All", car_parts=CarParts.common([CarHarness.hyundai_c])), @@ -316,7 +315,7 @@ class Buttons: CANCEL = 4 # on newer models, this is a pause/resume button -def get_platform_codes(fw_versions: List[bytes]) -> Set[Tuple[bytes, Optional[bytes]]]: +def get_platform_codes(fw_versions: list[bytes]) -> set[tuple[bytes, bytes | None]]: # Returns unique, platform-specific identification codes for a set of versions codes = set() # (code-Optional[part], date) for fw in fw_versions: @@ -335,12 +334,12 @@ def get_platform_codes(fw_versions: List[bytes]) -> Set[Tuple[bytes, Optional[by return codes -def match_fw_to_car_fuzzy(live_fw_versions, offline_fw_versions) -> Set[str]: +def match_fw_to_car_fuzzy(live_fw_versions, offline_fw_versions) -> set[str]: # Non-electric CAN FD platforms often do not have platform code specifiers needed # to distinguish between hybrid and ICE. All EVs so far are either exclusively # electric or specify electric in the platform code. fuzzy_platform_blacklist = {str(c) for c in (CANFD_CAR - EV_CAR - CANFD_FUZZY_WHITELIST)} - candidates: Set[str] = set() + candidates: set[str] = set() for candidate, fws in offline_fw_versions.items(): # Keep track of ECUs which pass all checks (platform codes, within date range) diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index 2b0b148ccfe287..05610a6dd6df6d 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -4,7 +4,8 @@ import tomllib from abc import abstractmethod, ABC from enum import StrEnum -from typing import Any, Dict, Optional, Tuple, List, Callable, NamedTuple, cast +from typing import Any, NamedTuple, cast +from collections.abc import Callable from cereal import car from openpilot.common.basedir import BASEDIR @@ -107,7 +108,7 @@ def get_non_essential_params(cls, candidate: str): return cls.get_params(candidate, gen_empty_fingerprint(), list(), False, False) @classmethod - def get_params(cls, candidate: str, fingerprint: Dict[int, Dict[int, int]], car_fw: List[car.CarParams.CarFw], experimental_long: bool, docs: bool): + def get_params(cls, candidate: str, fingerprint: dict[int, dict[int, int]], car_fw: list[car.CarParams.CarFw], experimental_long: bool, docs: bool): ret = CarInterfaceBase.get_std_params(candidate) if hasattr(candidate, "config"): @@ -131,8 +132,8 @@ def get_params(cls, candidate: str, fingerprint: Dict[int, Dict[int, int]], car_ @staticmethod @abstractmethod - def _get_params(ret: car.CarParams, candidate: str, fingerprint: Dict[int, Dict[int, int]], - car_fw: List[car.CarParams.CarFw], experimental_long: bool, docs: bool): + def _get_params(ret: car.CarParams, candidate: str, fingerprint: dict[int, dict[int, int]], + car_fw: list[car.CarParams.CarFw], experimental_long: bool, docs: bool): raise NotImplementedError @staticmethod @@ -212,7 +213,7 @@ def configure_torque_tune(candidate, tune, steering_angle_deadzone_deg=0.0, use_ def _update(self, c: car.CarControl) -> car.CarState: pass - def update(self, c: car.CarControl, can_strings: List[bytes]) -> car.CarState: + def update(self, c: car.CarControl, can_strings: list[bytes]) -> car.CarState: # parse can for cp in self.can_parsers: if cp is not None: @@ -246,7 +247,7 @@ def update(self, c: car.CarControl, can_strings: List[bytes]) -> car.CarState: return reader @abstractmethod - def apply(self, c: car.CarControl, now_nanos: int) -> Tuple[car.CarControl.Actuators, List[bytes]]: + def apply(self, c: car.CarControl, now_nanos: int) -> tuple[car.CarControl.Actuators, list[bytes]]: pass def create_common_events(self, cs_out, extra_gears=None, pcm_enable=True, allow_enable=True, @@ -417,11 +418,11 @@ def update_blinker_from_stalk(self, blinker_time: int, left_blinker_stalk: bool, return bool(left_blinker_stalk or self.left_blinker_cnt > 0), bool(right_blinker_stalk or self.right_blinker_cnt > 0) @staticmethod - def parse_gear_shifter(gear: Optional[str]) -> car.CarState.GearShifter: + def parse_gear_shifter(gear: str | None) -> car.CarState.GearShifter: if gear is None: return GearShifter.unknown - d: Dict[str, car.CarState.GearShifter] = { + d: dict[str, car.CarState.GearShifter] = { 'P': GearShifter.park, 'PARK': GearShifter.park, 'R': GearShifter.reverse, 'REVERSE': GearShifter.reverse, 'N': GearShifter.neutral, 'NEUTRAL': GearShifter.neutral, @@ -458,7 +459,7 @@ def get_loopback_can_parser(CP): # interface-specific helpers -def get_interface_attr(attr: str, combine_brands: bool = False, ignore_none: bool = False) -> Dict[str | StrEnum, Any]: +def get_interface_attr(attr: str, combine_brands: bool = False, ignore_none: bool = False) -> dict[str | StrEnum, Any]: # read all the folders in selfdrive/car and return a dict where: # - keys are all the car models or brand names # - values are attr values from all car folders @@ -491,7 +492,7 @@ def __init__(self, weights_loc: str, platform: str): self.load_weights(platform) def load_weights(self, platform: str): - with open(self.weights_loc, 'r') as fob: + with open(self.weights_loc) as fob: self.weights = {k: np.array(v) for k, v in json.load(fob)[platform].items()} def relu(self, x: np.ndarray): @@ -506,7 +507,7 @@ def forward(self, x: np.ndarray): x = np.dot(x, self.weights['w_4']) + self.weights['b_4'] return x - def predict(self, x: List[float], do_sample: bool = False): + def predict(self, x: list[float], do_sample: bool = False): x = self.forward(np.array(x)) if do_sample: pred = np.random.laplace(x[0], np.exp(x[1]) / self.weights['temperature']) diff --git a/selfdrive/car/mazda/values.py b/selfdrive/car/mazda/values.py index b43ab3df66bb52..eaf76d6a723d3b 100644 --- a/selfdrive/car/mazda/values.py +++ b/selfdrive/car/mazda/values.py @@ -1,6 +1,5 @@ from dataclasses import dataclass, field from enum import StrEnum -from typing import Dict, List, Union from cereal import car from openpilot.selfdrive.car import dbc_dict @@ -41,7 +40,7 @@ class MazdaCarInfo(CarInfo): car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.mazda])) -CAR_INFO: Dict[str, Union[MazdaCarInfo, List[MazdaCarInfo]]] = { +CAR_INFO: dict[str, MazdaCarInfo | list[MazdaCarInfo]] = { CAR.CX5: MazdaCarInfo("Mazda CX-5 2017-21"), CAR.CX9: MazdaCarInfo("Mazda CX-9 2016-20"), CAR.MAZDA3: MazdaCarInfo("Mazda 3 2017-18"), diff --git a/selfdrive/car/mock/values.py b/selfdrive/car/mock/values.py index c6c96579b48b54..e75665c98f276e 100644 --- a/selfdrive/car/mock/values.py +++ b/selfdrive/car/mock/values.py @@ -1,5 +1,4 @@ from enum import StrEnum -from typing import Dict, List, Optional, Union from openpilot.selfdrive.car.docs_definitions import CarInfo @@ -8,6 +7,6 @@ class CAR(StrEnum): MOCK = 'mock' -CAR_INFO: Dict[str, Optional[Union[CarInfo, List[CarInfo]]]] = { +CAR_INFO: dict[str, CarInfo | list[CarInfo] | None] = { CAR.MOCK: None, } diff --git a/selfdrive/car/nissan/values.py b/selfdrive/car/nissan/values.py index d064ce894d7526..c0308f9e0db49c 100644 --- a/selfdrive/car/nissan/values.py +++ b/selfdrive/car/nissan/values.py @@ -1,6 +1,5 @@ from dataclasses import dataclass, field from enum import StrEnum -from typing import Dict, List, Optional, Union from cereal import car from panda.python import uds @@ -37,7 +36,7 @@ class NissanCarInfo(CarInfo): car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.nissan_a])) -CAR_INFO: Dict[str, Optional[Union[NissanCarInfo, List[NissanCarInfo]]]] = { +CAR_INFO: dict[str, NissanCarInfo | list[NissanCarInfo] | None] = { CAR.XTRAIL: NissanCarInfo("Nissan X-Trail 2017"), CAR.LEAF: NissanCarInfo("Nissan Leaf 2018-23", video_link="https://youtu.be/vaMbtAh_0cY"), CAR.LEAF_IC: None, # same platforms diff --git a/selfdrive/car/subaru/values.py b/selfdrive/car/subaru/values.py index b871a919e34904..e496f43628c0ca 100644 --- a/selfdrive/car/subaru/values.py +++ b/selfdrive/car/subaru/values.py @@ -1,6 +1,5 @@ from dataclasses import dataclass, field from enum import Enum, IntFlag -from typing import List from cereal import car from panda.python import uds @@ -81,7 +80,7 @@ class Footnote(Enum): class SubaruCarInfo(CarInfo): package: str = "EyeSight Driver Assistance" car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.subaru_a])) - footnotes: List[Enum] = field(default_factory=lambda: [Footnote.GLOBAL]) + footnotes: list[Enum] = field(default_factory=lambda: [Footnote.GLOBAL]) def init_make(self, CP: car.CarParams): self.car_parts.parts.extend([Tool.socket_8mm_deep, Tool.pry_tool]) diff --git a/selfdrive/car/tesla/values.py b/selfdrive/car/tesla/values.py index 12877f1344eca1..2a51d15da89cf2 100644 --- a/selfdrive/car/tesla/values.py +++ b/selfdrive/car/tesla/values.py @@ -1,6 +1,5 @@ from collections import namedtuple from enum import StrEnum -from typing import Dict, List, Union from cereal import car from openpilot.selfdrive.car import AngleRateLimit, dbc_dict @@ -17,7 +16,7 @@ class CAR(StrEnum): AP2_MODELS = 'TESLA AP2 MODEL S' -CAR_INFO: Dict[str, Union[CarInfo, List[CarInfo]]] = { +CAR_INFO: dict[str, CarInfo | list[CarInfo]] = { CAR.AP1_MODELS: CarInfo("Tesla AP1 Model S", "All"), CAR.AP2_MODELS: CarInfo("Tesla AP2 Model S", "All"), } diff --git a/selfdrive/car/tests/routes.py b/selfdrive/car/tests/routes.py index f7ae4e038e7df5..9c14c0d25279c7 100755 --- a/selfdrive/car/tests/routes.py +++ b/selfdrive/car/tests/routes.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -from typing import NamedTuple, Optional +from typing import NamedTuple from openpilot.selfdrive.car.chrysler.values import CAR as CHRYSLER from openpilot.selfdrive.car.gm.values import CAR as GM @@ -29,8 +29,8 @@ class CarTestRoute(NamedTuple): route: str - car_model: Optional[str] - segment: Optional[int] = None + car_model: str | None + segment: int | None = None routes = [ diff --git a/selfdrive/car/tests/test_docs.py b/selfdrive/car/tests/test_docs.py index d9d67fe87d9cea..0cafb508f7e608 100755 --- a/selfdrive/car/tests/test_docs.py +++ b/selfdrive/car/tests/test_docs.py @@ -20,7 +20,7 @@ def setUpClass(cls): def test_generator(self): generated_cars_md = generate_cars_md(self.all_cars, CARS_MD_TEMPLATE) - with open(CARS_MD_OUT, "r") as f: + with open(CARS_MD_OUT) as f: current_cars_md = f.read() self.assertEqual(generated_cars_md, current_cars_md, @@ -45,7 +45,7 @@ def test_missing_car_info(self): all_car_info_platforms = get_interface_attr("CAR_INFO", combine_brands=True).keys() for platform in sorted(interfaces.keys()): with self.subTest(platform=platform): - self.assertTrue(platform in all_car_info_platforms, "Platform: {} doesn't exist in CarInfo".format(platform)) + self.assertTrue(platform in all_car_info_platforms, f"Platform: {platform} doesn't exist in CarInfo") def test_naming_conventions(self): # Asserts market-standard car naming conventions by brand diff --git a/selfdrive/car/tests/test_fingerprints.py b/selfdrive/car/tests/test_fingerprints.py index 61e9a4d165204f..34f30bc70385df 100755 --- a/selfdrive/car/tests/test_fingerprints.py +++ b/selfdrive/car/tests/test_fingerprints.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 import os import sys -from typing import Dict, List from openpilot.common.basedir import BASEDIR @@ -64,7 +63,7 @@ def check_can_ignition_conflicts(fingerprints, brands): if __name__ == "__main__": fingerprints = _get_fingerprints() - fingerprints_flat: List[Dict] = [] + fingerprints_flat: list[dict] = [] car_names = [] brand_names = [] for brand in fingerprints: diff --git a/selfdrive/car/tests/test_lateral_limits.py b/selfdrive/car/tests/test_lateral_limits.py index 10e24ff4c5a66b..083cdd5a5ea22f 100755 --- a/selfdrive/car/tests/test_lateral_limits.py +++ b/selfdrive/car/tests/test_lateral_limits.py @@ -3,7 +3,6 @@ import importlib from parameterized import parameterized_class import sys -from typing import DefaultDict, Dict import unittest from openpilot.common.realtime import DT_CTRL @@ -29,7 +28,7 @@ SUBARU.OUTBACK, ] -car_model_jerks: DefaultDict[str, Dict[str, float]] = defaultdict(dict) +car_model_jerks: defaultdict[str, dict[str, float]] = defaultdict(dict) @parameterized_class('car_model', [(c,) for c in sorted(CAR_MODELS)]) diff --git a/selfdrive/car/tests/test_models.py b/selfdrive/car/tests/test_models.py index ec7527713d4a79..2b29c14f7281da 100755 --- a/selfdrive/car/tests/test_models.py +++ b/selfdrive/car/tests/test_models.py @@ -8,7 +8,6 @@ from collections import defaultdict, Counter import hypothesis.strategies as st from hypothesis import Phase, given, settings -from typing import List, Optional, Tuple from parameterized import parameterized_class from cereal import messaging, log, car @@ -40,7 +39,7 @@ CI = os.environ.get("CI", None) is not None -def get_test_cases() -> List[Tuple[str, Optional[CarTestRoute]]]: +def get_test_cases() -> list[tuple[str, CarTestRoute | None]]: # build list of test cases test_cases = [] if not len(INTERNAL_SEG_LIST): @@ -65,14 +64,14 @@ def get_test_cases() -> List[Tuple[str, Optional[CarTestRoute]]]: @pytest.mark.slow @pytest.mark.shared_download_cache class TestCarModelBase(unittest.TestCase): - car_model: Optional[str] = None - test_route: Optional[CarTestRoute] = None + car_model: str | None = None + test_route: CarTestRoute | None = None test_route_on_bucket: bool = True # whether the route is on the preserved CI bucket - can_msgs: List[capnp.lib.capnp._DynamicStructReader] + can_msgs: list[capnp.lib.capnp._DynamicStructReader] fingerprint: dict[int, dict[int, int]] - elm_frame: Optional[int] - car_safety_mode_frame: Optional[int] + elm_frame: int | None + car_safety_mode_frame: int | None @classmethod def get_testing_data_from_logreader(cls, lr): @@ -408,7 +407,7 @@ def test_panda_safety_carstate(self): controls_allowed_prev = False CS_prev = car.CarState.new_message() - checks = defaultdict(lambda: 0) + checks = defaultdict(int) controlsd = Controls(CI=self.CI) controlsd.initialized = True for idx, can in enumerate(self.can_msgs): diff --git a/selfdrive/car/toyota/values.py b/selfdrive/car/toyota/values.py index ed2b022f43fdc7..011d153f70adae 100644 --- a/selfdrive/car/toyota/values.py +++ b/selfdrive/car/toyota/values.py @@ -2,7 +2,6 @@ from collections import defaultdict from dataclasses import dataclass, field from enum import Enum, IntFlag, StrEnum -from typing import Dict, List, Set, Union from cereal import car from openpilot.common.conversions import Conversions as CV @@ -100,7 +99,7 @@ class ToyotaCarInfo(CarInfo): car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.toyota_a])) -CAR_INFO: Dict[str, Union[ToyotaCarInfo, List[ToyotaCarInfo]]] = { +CAR_INFO: dict[str, ToyotaCarInfo | list[ToyotaCarInfo]] = { # Toyota CAR.ALPHARD_TSS2: [ ToyotaCarInfo("Toyota Alphard 2019-20"), @@ -253,7 +252,7 @@ class ToyotaCarInfo(CarInfo): ] -def get_platform_codes(fw_versions: List[bytes]) -> Dict[bytes, Set[bytes]]: +def get_platform_codes(fw_versions: list[bytes]) -> dict[bytes, set[bytes]]: # Returns sub versions in a dict so comparisons can be made within part-platform-major_version combos codes = defaultdict(set) # Optional[part]-platform-major_version: set of sub_version for fw in fw_versions: @@ -297,7 +296,7 @@ def get_platform_codes(fw_versions: List[bytes]) -> Dict[bytes, Set[bytes]]: return dict(codes) -def match_fw_to_car_fuzzy(live_fw_versions, offline_fw_versions) -> Set[str]: +def match_fw_to_car_fuzzy(live_fw_versions, offline_fw_versions) -> set[str]: candidates = set() for candidate, fws in offline_fw_versions.items(): diff --git a/selfdrive/car/volkswagen/values.py b/selfdrive/car/volkswagen/values.py index b09cbc5d8a231a..e49b9850bea4ef 100644 --- a/selfdrive/car/volkswagen/values.py +++ b/selfdrive/car/volkswagen/values.py @@ -1,7 +1,6 @@ from collections import defaultdict, namedtuple from dataclasses import dataclass, field from enum import Enum, IntFlag, StrEnum -from typing import Dict, List, Union from cereal import car from panda.python import uds @@ -151,7 +150,7 @@ class CAR(StrEnum): PQ_CARS = {CAR.PASSAT_NMS, CAR.SHARAN_MK2} -DBC: Dict[str, Dict[str, str]] = defaultdict(lambda: dbc_dict("vw_mqb_2010", None)) +DBC: dict[str, dict[str, str]] = defaultdict(lambda: dbc_dict("vw_mqb_2010", None)) for car_type in PQ_CARS: DBC[car_type] = dbc_dict("vw_golf_mk4", None) @@ -191,7 +190,7 @@ def init_make(self, CP: car.CarParams): self.car_parts = CarParts([Device.threex_angled_mount, CarHarness.j533]) -CAR_INFO: Dict[str, Union[VWCarInfo, List[VWCarInfo]]] = { +CAR_INFO: dict[str, VWCarInfo | list[VWCarInfo]] = { CAR.ARTEON_MK1: [ VWCarInfo("Volkswagen Arteon 2018-23", video_link="https://youtu.be/FAomFKPFlDA"), VWCarInfo("Volkswagen Arteon R 2020-23", video_link="https://youtu.be/FAomFKPFlDA"), diff --git a/selfdrive/controls/lib/alertmanager.py b/selfdrive/controls/lib/alertmanager.py index 6abcf4cbba73fb..8034c8ebbcec98 100644 --- a/selfdrive/controls/lib/alertmanager.py +++ b/selfdrive/controls/lib/alertmanager.py @@ -3,7 +3,6 @@ import json from collections import defaultdict from dataclasses import dataclass -from typing import List, Dict, Optional from openpilot.common.basedir import BASEDIR from openpilot.common.params import Params @@ -14,7 +13,7 @@ OFFROAD_ALERTS = json.load(f) -def set_offroad_alert(alert: str, show_alert: bool, extra_text: Optional[str] = None) -> None: +def set_offroad_alert(alert: str, show_alert: bool, extra_text: str | None = None) -> None: if show_alert: a = copy.copy(OFFROAD_ALERTS[alert]) a['extra'] = extra_text or '' @@ -25,7 +24,7 @@ def set_offroad_alert(alert: str, show_alert: bool, extra_text: Optional[str] = @dataclass class AlertEntry: - alert: Optional[Alert] = None + alert: Alert | None = None start_frame: int = -1 end_frame: int = -1 @@ -34,9 +33,9 @@ def active(self, frame: int) -> bool: class AlertManager: def __init__(self): - self.alerts: Dict[str, AlertEntry] = defaultdict(AlertEntry) + self.alerts: dict[str, AlertEntry] = defaultdict(AlertEntry) - def add_many(self, frame: int, alerts: List[Alert]) -> None: + def add_many(self, frame: int, alerts: list[Alert]) -> None: for alert in alerts: entry = self.alerts[alert.alert_type] entry.alert = alert @@ -45,7 +44,7 @@ def add_many(self, frame: int, alerts: List[Alert]) -> None: min_end_frame = entry.start_frame + alert.duration entry.end_frame = max(frame + 1, min_end_frame) - def process_alerts(self, frame: int, clear_event_types: set) -> Optional[Alert]: + def process_alerts(self, frame: int, clear_event_types: set) -> Alert | None: current_alert = AlertEntry() for v in self.alerts.values(): if not v.alert: diff --git a/selfdrive/controls/lib/events.py b/selfdrive/controls/lib/events.py index d68c95bcf50d81..c5228ef7f29796 100755 --- a/selfdrive/controls/lib/events.py +++ b/selfdrive/controls/lib/events.py @@ -2,7 +2,7 @@ import math import os from enum import IntEnum -from typing import Dict, Union, Callable, List, Optional +from collections.abc import Callable from cereal import log, car import cereal.messaging as messaging @@ -48,12 +48,12 @@ class ET: class Events: def __init__(self): - self.events: List[int] = [] - self.static_events: List[int] = [] + self.events: list[int] = [] + self.static_events: list[int] = [] self.events_prev = dict.fromkeys(EVENTS.keys(), 0) @property - def names(self) -> List[int]: + def names(self) -> list[int]: return self.events def __len__(self) -> int: @@ -71,7 +71,7 @@ def clear(self) -> None: def contains(self, event_type: str) -> bool: return any(event_type in EVENTS.get(e, {}) for e in self.events) - def create_alerts(self, event_types: List[str], callback_args=None): + def create_alerts(self, event_types: list[str], callback_args=None): if callback_args is None: callback_args = [] @@ -132,7 +132,7 @@ def __init__(self, self.creation_delay = creation_delay self.alert_type = "" - self.event_type: Optional[str] = None + self.event_type: str | None = None def __str__(self) -> str: return f"{self.alert_text_1}/{self.alert_text_2} {self.priority} {self.visual_alert} {self.audible_alert}" @@ -333,7 +333,7 @@ def joystick_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, -EVENTS: Dict[int, Dict[str, Union[Alert, AlertCallbackType]]] = { +EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { # ********** events with no alerts ********** EventName.stockFcw: {}, @@ -965,7 +965,7 @@ def joystick_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, from collections import defaultdict event_names = {v: k for k, v in EventName.schema.enumerants.items()} - alerts_by_type: Dict[str, Dict[Priority, List[str]]] = defaultdict(lambda: defaultdict(list)) + alerts_by_type: dict[str, dict[Priority, list[str]]] = defaultdict(lambda: defaultdict(list)) CP = car.CarParams.new_message() CS = car.CarState.new_message() @@ -977,7 +977,7 @@ def joystick_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, alert = alert(CP, CS, sm, False, 1) alerts_by_type[et][alert.priority].append(event_names[i]) - all_alerts: Dict[str, List[tuple[Priority, List[str]]]] = {} + all_alerts: dict[str, list[tuple[Priority, list[str]]]] = {} for et, priority_alerts in alerts_by_type.items(): all_alerts[et] = sorted(priority_alerts.items(), key=lambda x: x[0], reverse=True) diff --git a/selfdrive/controls/lib/vehicle_model.py b/selfdrive/controls/lib/vehicle_model.py index 0750384918dc31..b6f50b4ba80886 100755 --- a/selfdrive/controls/lib/vehicle_model.py +++ b/selfdrive/controls/lib/vehicle_model.py @@ -12,7 +12,6 @@ A depends on longitudinal speed, u [m/s], and vehicle parameters CP """ -from typing import Tuple import numpy as np from numpy.linalg import solve @@ -169,7 +168,7 @@ def kin_ss_sol(sa: float, u: float, VM: VehicleModel) -> np.ndarray: return K * sa -def create_dyn_state_matrices(u: float, VM: VehicleModel) -> Tuple[np.ndarray, np.ndarray]: +def create_dyn_state_matrices(u: float, VM: VehicleModel) -> tuple[np.ndarray, np.ndarray]: """Returns the A and B matrix for the dynamics system Args: diff --git a/selfdrive/controls/radard.py b/selfdrive/controls/radard.py index b0b9350dec0c43..4de4208e9d2916 100755 --- a/selfdrive/controls/radard.py +++ b/selfdrive/controls/radard.py @@ -2,7 +2,7 @@ import importlib import math from collections import deque -from typing import Optional, Dict, Any +from typing import Any, Optional import capnp from cereal import messaging, log, car @@ -125,7 +125,7 @@ def laplacian_pdf(x: float, mu: float, b: float): return math.exp(-abs(x-mu)/b) -def match_vision_to_track(v_ego: float, lead: capnp._DynamicStructReader, tracks: Dict[int, Track]): +def match_vision_to_track(v_ego: float, lead: capnp._DynamicStructReader, tracks: dict[int, Track]): offset_vision_dist = lead.x[0] - RADAR_TO_CAMERA def prob(c): @@ -166,8 +166,8 @@ def get_RadarState_from_vision(lead_msg: capnp._DynamicStructReader, v_ego: floa } -def get_lead(v_ego: float, ready: bool, tracks: Dict[int, Track], lead_msg: capnp._DynamicStructReader, - model_v_ego: float, low_speed_override: bool = True) -> Dict[str, Any]: +def get_lead(v_ego: float, ready: bool, tracks: dict[int, Track], lead_msg: capnp._DynamicStructReader, + model_v_ego: float, low_speed_override: bool = True) -> dict[str, Any]: # Determine leads, this is where the essential logic happens if len(tracks) > 0 and ready and lead_msg.prob > .5: track = match_vision_to_track(v_ego, lead_msg, tracks) @@ -196,14 +196,14 @@ class RadarD: def __init__(self, radar_ts: float, delay: int = 0): self.current_time = 0.0 - self.tracks: Dict[int, Track] = {} + self.tracks: dict[int, Track] = {} self.kalman_params = KalmanParams(radar_ts) self.v_ego = 0.0 self.v_ego_hist = deque([0.0], maxlen=delay+1) self.last_v_ego_frame = -1 - self.radar_state: Optional[capnp._DynamicStructBuilder] = None + self.radar_state: capnp._DynamicStructBuilder | None = None self.radar_state_valid = False self.ready = False diff --git a/selfdrive/debug/can_print_changes.py b/selfdrive/debug/can_print_changes.py index 810e45cfc607d4..97d60b2b05ed9f 100755 --- a/selfdrive/debug/can_print_changes.py +++ b/selfdrive/debug/can_print_changes.py @@ -3,7 +3,6 @@ import binascii import time from collections import defaultdict -from typing import Optional import cereal.messaging as messaging from openpilot.selfdrive.debug.can_table import can_table @@ -96,8 +95,8 @@ def can_printer(bus=0, init_msgs=None, new_msgs=None, table=False): args = parser.parse_args() - init_lr: Optional[LogIterable] = None - new_lr: Optional[LogIterable] = None + init_lr: LogIterable | None = None + new_lr: LogIterable | None = None if args.init: if args.init == '': diff --git a/selfdrive/debug/check_freq.py b/selfdrive/debug/check_freq.py index 7e7b05e950bfbe..1765aeb86b6752 100755 --- a/selfdrive/debug/check_freq.py +++ b/selfdrive/debug/check_freq.py @@ -3,7 +3,7 @@ import numpy as np import time from collections import defaultdict, deque -from typing import DefaultDict, Deque, MutableSequence +from collections.abc import MutableSequence import cereal.messaging as messaging @@ -19,8 +19,8 @@ socket_names = args.socket sockets = {} - rcv_times: DefaultDict[str, MutableSequence[float]] = defaultdict(lambda: deque(maxlen=100)) - valids: DefaultDict[str, Deque[bool]] = defaultdict(lambda: deque(maxlen=100)) + rcv_times: defaultdict[str, MutableSequence[float]] = defaultdict(lambda: deque(maxlen=100)) + valids: defaultdict[str, deque[bool]] = defaultdict(lambda: deque(maxlen=100)) t = time.monotonic() for name in socket_names: diff --git a/selfdrive/debug/check_lag.py b/selfdrive/debug/check_lag.py index 72d11d6eda5e1d..341ae79c8b5138 100755 --- a/selfdrive/debug/check_lag.py +++ b/selfdrive/debug/check_lag.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -from typing import Dict import cereal.messaging as messaging from cereal.services import SERVICE_LIST @@ -10,7 +9,7 @@ if __name__ == "__main__": sm = messaging.SubMaster(TO_CHECK) - prev_t: Dict[str, float] = {} + prev_t: dict[str, float] = {} while True: sm.update() diff --git a/selfdrive/debug/check_timings.py b/selfdrive/debug/check_timings.py index fb8467a3c4c68f..3de6b8eb669b28 100755 --- a/selfdrive/debug/check_timings.py +++ b/selfdrive/debug/check_timings.py @@ -3,13 +3,13 @@ import sys import time import numpy as np -from typing import DefaultDict, MutableSequence +from collections.abc import MutableSequence from collections import defaultdict, deque import cereal.messaging as messaging socks = {s: messaging.sub_sock(s, conflate=False) for s in sys.argv[1:]} -ts: DefaultDict[str, MutableSequence[float]] = defaultdict(lambda: deque(maxlen=100)) +ts: defaultdict[str, MutableSequence[float]] = defaultdict(lambda: deque(maxlen=100)) if __name__ == "__main__": while True: diff --git a/selfdrive/debug/count_events.py b/selfdrive/debug/count_events.py index 30e9bf8ec5ba75..59420547570b0e 100755 --- a/selfdrive/debug/count_events.py +++ b/selfdrive/debug/count_events.py @@ -4,7 +4,7 @@ import datetime from collections import Counter from pprint import pprint -from typing import List, Tuple, cast +from typing import cast from cereal.services import SERVICE_LIST from openpilot.tools.lib.logreader import LogReader, ReadMode @@ -15,8 +15,8 @@ cams = [s for s in SERVICE_LIST if s.endswith('CameraState')] cnt_cameras = dict.fromkeys(cams, 0) - events: List[Tuple[float, set[str]]] = [] - alerts: List[Tuple[float, str]] = [] + events: list[tuple[float, set[str]]] = [] + alerts: list[tuple[float, str]] = [] start_time = math.inf end_time = -math.inf ignition_off = None diff --git a/selfdrive/debug/cpu_usage_stat.py b/selfdrive/debug/cpu_usage_stat.py index 9050fbb064615d..ec9d02e8f49d4f 100755 --- a/selfdrive/debug/cpu_usage_stat.py +++ b/selfdrive/debug/cpu_usage_stat.py @@ -66,12 +66,12 @@ def get_arg_parser(): for p in psutil.process_iter(): if p == psutil.Process(): continue - matched = any(l for l in p.cmdline() if any(pn for pn in monitored_proc_names if re.match(r'.*{}.*'.format(pn), l, re.M | re.I))) + matched = any(l for l in p.cmdline() if any(pn for pn in monitored_proc_names if re.match(fr'.*{pn}.*', l, re.M | re.I))) if matched: k = ' '.join(p.cmdline()) print('Add monitored proc:', k) stats[k] = {'cpu_samples': defaultdict(list), 'min': defaultdict(lambda: None), 'max': defaultdict(lambda: None), - 'avg': defaultdict(lambda: 0.0), 'last_cpu_times': None, 'last_sys_time': None} + 'avg': defaultdict(float), 'last_cpu_times': None, 'last_sys_time': None} stats[k]['last_sys_time'] = timer() stats[k]['last_cpu_times'] = p.cpu_times() monitored_procs.append(p) diff --git a/selfdrive/debug/format_fingerprints.py b/selfdrive/debug/format_fingerprints.py index bd5822729af4b7..2a5e4e60802e5a 100755 --- a/selfdrive/debug/format_fingerprints.py +++ b/selfdrive/debug/format_fingerprints.py @@ -67,7 +67,7 @@ def format_brand_fw_versions(brand, extra_fw_versions: None | dict[str, dict[tup extra_fw_versions = extra_fw_versions or {} fingerprints_file = os.path.join(BASEDIR, f"selfdrive/car/{brand}/fingerprints.py") - with open(fingerprints_file, "r") as f: + with open(fingerprints_file) as f: comments = [line for line in f.readlines() if line.startswith("#") and "noqa" not in line] with open(fingerprints_file, "w") as f: diff --git a/selfdrive/debug/internal/measure_modeld_packet_drop.py b/selfdrive/debug/internal/measure_modeld_packet_drop.py index 6b7f7dbd13f8ac..9814942ce27fc6 100755 --- a/selfdrive/debug/internal/measure_modeld_packet_drop.py +++ b/selfdrive/debug/internal/measure_modeld_packet_drop.py @@ -1,12 +1,11 @@ #!/usr/bin/env python3 import cereal.messaging as messaging -from typing import Optional if __name__ == "__main__": modeld_sock = messaging.sub_sock("modelV2") last_frame_id = None - start_t: Optional[int] = None + start_t: int | None = None frame_cnt = 0 dropped = 0 diff --git a/selfdrive/debug/live_cpu_and_temp.py b/selfdrive/debug/live_cpu_and_temp.py index 06f1be0b00890d..8549b92665e6a1 100755 --- a/selfdrive/debug/live_cpu_and_temp.py +++ b/selfdrive/debug/live_cpu_and_temp.py @@ -5,7 +5,6 @@ from cereal.messaging import SubMaster from openpilot.common.numpy_fast import mean -from typing import Optional, Dict def cputime_total(ct): return ct.user + ct.nice + ct.system + ct.idle + ct.iowait + ct.irq + ct.softirq @@ -42,8 +41,8 @@ def proc_name(proc): total_times = [0.]*8 busy_times = [0.]*8 - prev_proclog: Optional[capnp._DynamicStructReader] = None - prev_proclog_t: Optional[int] = None + prev_proclog: capnp._DynamicStructReader | None = None + prev_proclog_t: int | None = None while True: sm.update() @@ -76,7 +75,7 @@ def proc_name(proc): print(f"CPU {100.0 * mean(cores):.2f}% - RAM: {last_mem:.2f}% - Temp {last_temp:.2f}C") if args.cpu and prev_proclog is not None and prev_proclog_t is not None: - procs: Dict[str, float] = defaultdict(float) + procs: dict[str, float] = defaultdict(float) dt = (sm.logMonoTime['procLog'] - prev_proclog_t) / 1e9 for proc in m.procs: try: diff --git a/selfdrive/locationd/calibrationd.py b/selfdrive/locationd/calibrationd.py index da1c4ec37b1a9b..1456bf16f58048 100755 --- a/selfdrive/locationd/calibrationd.py +++ b/selfdrive/locationd/calibrationd.py @@ -10,7 +10,7 @@ import os import capnp import numpy as np -from typing import List, NoReturn, Optional +from typing import NoReturn from cereal import log import cereal.messaging as messaging @@ -89,7 +89,7 @@ def reset(self, rpy_init: np.ndarray = RPY_INIT, valid_blocks: int = 0, wide_from_device_euler_init: np.ndarray = WIDE_FROM_DEVICE_EULER_INIT, height_init: np.ndarray = HEIGHT_INIT, - smooth_from: Optional[np.ndarray] = None) -> None: + smooth_from: np.ndarray | None = None) -> None: if not np.isfinite(rpy_init).all(): self.rpy = RPY_INIT.copy() else: @@ -125,7 +125,7 @@ def reset(self, rpy_init: np.ndarray = RPY_INIT, self.old_rpy = smooth_from self.old_rpy_weight = 1.0 - def get_valid_idxs(self) -> List[int]: + def get_valid_idxs(self) -> list[int]: # exclude current block_idx from validity window before_current = list(range(self.block_idx)) after_current = list(range(min(self.valid_blocks, self.block_idx + 1), self.valid_blocks)) @@ -175,12 +175,12 @@ def get_smooth_rpy(self) -> np.ndarray: else: return self.rpy - def handle_cam_odom(self, trans: List[float], - rot: List[float], - wide_from_device_euler: List[float], - trans_std: List[float], - road_transform_trans: List[float], - road_transform_trans_std: List[float]) -> Optional[np.ndarray]: + def handle_cam_odom(self, trans: list[float], + rot: list[float], + wide_from_device_euler: list[float], + trans_std: list[float], + road_transform_trans: list[float], + road_transform_trans_std: list[float]) -> np.ndarray | None: self.old_rpy_weight = max(0.0, self.old_rpy_weight - 1/SMOOTH_CYCLES) straight_and_fast = ((self.v_ego > MIN_SPEED_FILTER) and (trans[0] > MIN_SPEED_FILTER) and (abs(rot[2]) < MAX_YAW_RATE_FILTER)) diff --git a/selfdrive/locationd/helpers.py b/selfdrive/locationd/helpers.py index c292e9886c7e37..c273ba87b3578b 100644 --- a/selfdrive/locationd/helpers.py +++ b/selfdrive/locationd/helpers.py @@ -1,5 +1,5 @@ import numpy as np -from typing import List, Optional, Tuple, Any +from typing import Any from cereal import log @@ -12,7 +12,7 @@ def __init__(self, maxlen: int, rowsize: int) -> None: def __len__(self) -> int: return len(self.arr) - def append(self, pt: List[float]) -> None: + def append(self, pt: list[float]) -> None: if len(self.arr) < self.maxlen: self.arr = np.append(self.arr, [pt], axis=0) else: @@ -21,7 +21,7 @@ def append(self, pt: List[float]) -> None: class PointBuckets: - def __init__(self, x_bounds: List[Tuple[float, float]], min_points: List[float], min_points_total: int, points_per_bucket: int, rowsize: int) -> None: + def __init__(self, x_bounds: list[tuple[float, float]], min_points: list[float], min_points_total: int, points_per_bucket: int, rowsize: int) -> None: self.x_bounds = x_bounds self.buckets = {bounds: NPQueue(maxlen=points_per_bucket, rowsize=rowsize) for bounds in x_bounds} self.buckets_min_points = dict(zip(x_bounds, min_points, strict=True)) @@ -41,13 +41,13 @@ def is_calculable(self) -> bool: def add_point(self, x: float, y: float, bucket_val: float) -> None: raise NotImplementedError - def get_points(self, num_points: Optional[int] = None) -> Any: + def get_points(self, num_points: int | None = None) -> Any: points = np.vstack([x.arr for x in self.buckets.values()]) if num_points is None: return points return points[np.random.choice(np.arange(len(points)), min(len(points), num_points), replace=False)] - def load_points(self, points: List[List[float]]) -> None: + def load_points(self, points: list[list[float]]) -> None: for point in points: self.add_point(*point) diff --git a/selfdrive/locationd/models/car_kf.py b/selfdrive/locationd/models/car_kf.py index 9230cb48f0b21a..1f3e447a199a3a 100755 --- a/selfdrive/locationd/models/car_kf.py +++ b/selfdrive/locationd/models/car_kf.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 import math import sys -from typing import Any, Dict +from typing import Any import numpy as np @@ -70,7 +70,7 @@ class CarKalman(KalmanFilter): ]) P_initial = Q.copy() - obs_noise: Dict[int, Any] = { + obs_noise: dict[int, Any] = { ObservationKind.STEER_ANGLE: np.atleast_2d(math.radians(0.05)**2), ObservationKind.ANGLE_OFFSET_FAST: np.atleast_2d(math.radians(10.0)**2), ObservationKind.ROAD_ROLL: np.atleast_2d(math.radians(1.0)**2), diff --git a/selfdrive/manager/build.py b/selfdrive/manager/build.py index f2758cf32b2d08..067e1b5a1e873e 100755 --- a/selfdrive/manager/build.py +++ b/selfdrive/manager/build.py @@ -2,7 +2,6 @@ import os import subprocess from pathlib import Path -from typing import List # NOTE: Do NOT import anything here that needs be built (e.g. params) from openpilot.common.basedir import BASEDIR @@ -29,7 +28,7 @@ def build(spinner: Spinner, dirty: bool = False, minimal: bool = False) -> None: # building with all cores can result in using too # much memory, so retry with less parallelism - compile_output: List[bytes] = [] + compile_output: list[bytes] = [] for n in (nproc, nproc/2, 1): compile_output.clear() scons: subprocess.Popen = subprocess.Popen(["scons", f"-j{int(n)}", "--cache-populate", *extra_args], cwd=BASEDIR, env=env, stderr=subprocess.PIPE) diff --git a/selfdrive/manager/manager.py b/selfdrive/manager/manager.py index bf1eeb8fd09817..24dceaaf08c5f2 100755 --- a/selfdrive/manager/manager.py +++ b/selfdrive/manager/manager.py @@ -4,7 +4,6 @@ import signal import sys import traceback -from typing import List, Tuple, Union from cereal import log import cereal.messaging as messaging @@ -33,7 +32,7 @@ def manager_init() -> None: if is_release_branch(): params.clear_all(ParamKeyType.DEVELOPMENT_ONLY) - default_params: List[Tuple[str, Union[str, bytes]]] = [ + default_params: list[tuple[str, str | bytes]] = [ ("CompletedTrainingVersion", "0"), ("DisengageOnAccelerator", "0"), ("GsmMetered", "1"), @@ -121,7 +120,7 @@ def manager_thread() -> None: params = Params() - ignore: List[str] = [] + ignore: list[str] = [] if params.get("DongleId", encoding='utf8') in (None, UNREGISTERED_DONGLE_ID): ignore += ["manage_athenad", "uploader"] if os.getenv("NOBOARD") is not None: @@ -154,7 +153,7 @@ def manager_thread() -> None: ensure_running(managed_processes.values(), started, params=params, CP=sm['carParams'], not_run=ignore) - running = ' '.join("%s%s\u001b[0m" % ("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name) + running = ' '.join("{}{}\u001b[0m".format("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name) for p in managed_processes.values() if p.proc) print(running) cloudlog.debug(running) diff --git a/selfdrive/manager/process.py b/selfdrive/manager/process.py index ac1b4ac68c522f..46fb68f89cac3c 100644 --- a/selfdrive/manager/process.py +++ b/selfdrive/manager/process.py @@ -4,7 +4,7 @@ import struct import time import subprocess -from typing import Optional, Callable, List, ValuesView +from collections.abc import Callable, ValuesView from abc import ABC, abstractmethod from multiprocessing import Process @@ -47,7 +47,7 @@ def launcher(proc: str, name: str) -> None: raise -def nativelauncher(pargs: List[str], cwd: str, name: str) -> None: +def nativelauncher(pargs: list[str], cwd: str, name: str) -> None: os.environ['MANAGER_DAEMON'] = name # exec the process @@ -67,12 +67,12 @@ class ManagerProcess(ABC): daemon = False sigkill = False should_run: Callable[[bool, Params, car.CarParams], bool] - proc: Optional[Process] = None + proc: Process | None = None enabled = True name = "" last_watchdog_time = 0 - watchdog_max_dt: Optional[int] = None + watchdog_max_dt: int | None = None watchdog_seen = False shutting_down = False @@ -109,7 +109,7 @@ def check_watchdog(self, started: bool) -> None: else: self.watchdog_seen = True - def stop(self, retry: bool = True, block: bool = True, sig: Optional[signal.Signals] = None) -> Optional[int]: + def stop(self, retry: bool = True, block: bool = True, sig: signal.Signals | None = None) -> int | None: if self.proc is None: return None @@ -274,7 +274,7 @@ def stop(self, retry=True, block=True, sig=None) -> None: def ensure_running(procs: ValuesView[ManagerProcess], started: bool, params=None, CP: car.CarParams=None, - not_run: Optional[List[str]]=None) -> List[ManagerProcess]: + not_run: list[str] | None=None) -> list[ManagerProcess]: if not_run is None: not_run = [] diff --git a/selfdrive/modeld/dmonitoringmodeld.py b/selfdrive/modeld/dmonitoringmodeld.py index 1e259647023209..ef403b44fc648f 100755 --- a/selfdrive/modeld/dmonitoringmodeld.py +++ b/selfdrive/modeld/dmonitoringmodeld.py @@ -6,7 +6,6 @@ import ctypes import numpy as np from pathlib import Path -from typing import Tuple, Dict from cereal import messaging from cereal.messaging import PubMaster, SubMaster @@ -53,7 +52,7 @@ class DMonitoringModelResult(ctypes.Structure): ("wheel_on_right_prob", ctypes.c_float)] class ModelState: - inputs: Dict[str, np.ndarray] + inputs: dict[str, np.ndarray] output: np.ndarray model: ModelRunner @@ -68,7 +67,7 @@ def __init__(self): self.model.addInput("input_img", None) self.model.addInput("calib", self.inputs['calib']) - def run(self, buf:VisionBuf, calib:np.ndarray) -> Tuple[np.ndarray, float]: + def run(self, buf:VisionBuf, calib:np.ndarray) -> tuple[np.ndarray, float]: self.inputs['calib'][:] = calib v_offset = buf.height - MODEL_HEIGHT diff --git a/selfdrive/modeld/fill_model_msg.py b/selfdrive/modeld/fill_model_msg.py index c76966867ae871..c39ec2da3d25bf 100644 --- a/selfdrive/modeld/fill_model_msg.py +++ b/selfdrive/modeld/fill_model_msg.py @@ -1,7 +1,6 @@ import os import capnp import numpy as np -from typing import Dict from cereal import log from openpilot.selfdrive.modeld.constants import ModelConstants, Plan, Meta @@ -42,7 +41,7 @@ def fill_xyvat(builder, t, x, y, v, a, x_std=None, y_std=None, v_std=None, a_std if a_std is not None: builder.aStd = a_std.tolist() -def fill_model_msg(msg: capnp._DynamicStructBuilder, net_output_data: Dict[str, np.ndarray], publish_state: PublishState, +def fill_model_msg(msg: capnp._DynamicStructBuilder, net_output_data: dict[str, np.ndarray], publish_state: PublishState, vipc_frame_id: int, vipc_frame_id_extra: int, frame_id: int, frame_drop: float, timestamp_eof: int, timestamp_llk: int, model_execution_time: float, nav_enabled: bool, valid: bool) -> None: @@ -174,7 +173,7 @@ def fill_model_msg(msg: capnp._DynamicStructBuilder, net_output_data: Dict[str, if SEND_RAW_PRED: modelV2.rawPredictions = net_output_data['raw_pred'].tobytes() -def fill_pose_msg(msg: capnp._DynamicStructBuilder, net_output_data: Dict[str, np.ndarray], +def fill_pose_msg(msg: capnp._DynamicStructBuilder, net_output_data: dict[str, np.ndarray], vipc_frame_id: int, vipc_dropped_frames: int, timestamp_eof: int, live_calib_seen: bool) -> None: msg.valid = live_calib_seen & (vipc_dropped_frames < 1) cameraOdometry = msg.cameraOdometry diff --git a/selfdrive/modeld/get_model_metadata.py b/selfdrive/modeld/get_model_metadata.py index 187f83399b9740..144860204fd79c 100755 --- a/selfdrive/modeld/get_model_metadata.py +++ b/selfdrive/modeld/get_model_metadata.py @@ -4,9 +4,8 @@ import onnx import codecs import pickle -from typing import Tuple -def get_name_and_shape(value_info:onnx.ValueInfoProto) -> Tuple[str, Tuple[int,...]]: +def get_name_and_shape(value_info:onnx.ValueInfoProto) -> tuple[str, tuple[int,...]]: shape = tuple([int(dim.dim_value) for dim in value_info.type.tensor_type.shape.dim]) name = value_info.name return name, shape diff --git a/selfdrive/modeld/modeld.py b/selfdrive/modeld/modeld.py index f2842d94b70634..e086b8aaf88058 100755 --- a/selfdrive/modeld/modeld.py +++ b/selfdrive/modeld/modeld.py @@ -6,7 +6,6 @@ import cereal.messaging as messaging from cereal import car, log from pathlib import Path -from typing import Dict, Optional from setproctitle import setproctitle from cereal.messaging import PubMaster, SubMaster from cereal.visionipc import VisionIpcClient, VisionStreamType, VisionBuf @@ -45,7 +44,7 @@ def __init__(self, vipc=None): class ModelState: frame: ModelFrame wide_frame: ModelFrame - inputs: Dict[str, np.ndarray] + inputs: dict[str, np.ndarray] output: np.ndarray prev_desire: np.ndarray # for tracking the rising edge of the pulse model: ModelRunner @@ -78,14 +77,14 @@ def __init__(self, context: CLContext): for k,v in self.inputs.items(): self.model.addInput(k, v) - def slice_outputs(self, model_outputs: np.ndarray) -> Dict[str, np.ndarray]: + def slice_outputs(self, model_outputs: np.ndarray) -> dict[str, np.ndarray]: parsed_model_outputs = {k: model_outputs[np.newaxis, v] for k,v in self.output_slices.items()} if SEND_RAW_PRED: parsed_model_outputs['raw_pred'] = model_outputs.copy() return parsed_model_outputs def run(self, buf: VisionBuf, wbuf: VisionBuf, transform: np.ndarray, transform_wide: np.ndarray, - inputs: Dict[str, np.ndarray], prepare_only: bool) -> Optional[Dict[str, np.ndarray]]: + inputs: dict[str, np.ndarray], prepare_only: bool) -> dict[str, np.ndarray] | None: # Model decides when action is completed, so desire input is just a pulse triggered on rising edge inputs['desire'][0] = 0 self.inputs['desire'][:-ModelConstants.DESIRE_LEN] = self.inputs['desire'][ModelConstants.DESIRE_LEN:] @@ -276,7 +275,7 @@ def main(demo=False): if prepare_only: cloudlog.error(f"skipping model eval. Dropped {vipc_dropped_frames} frames") - inputs:Dict[str, np.ndarray] = { + inputs:dict[str, np.ndarray] = { 'desire': vec_desire, 'traffic_convention': traffic_convention, 'lateral_control_params': lateral_control_params, diff --git a/selfdrive/modeld/navmodeld.py b/selfdrive/modeld/navmodeld.py index ed0b597dfeb6d3..4672734681504c 100755 --- a/selfdrive/modeld/navmodeld.py +++ b/selfdrive/modeld/navmodeld.py @@ -5,7 +5,6 @@ import ctypes import numpy as np from pathlib import Path -from typing import Tuple, Dict from cereal import messaging from cereal.messaging import PubMaster, SubMaster @@ -41,7 +40,7 @@ class NavModelResult(ctypes.Structure): ("features", ctypes.c_float*NAV_FEATURE_LEN)] class ModelState: - inputs: Dict[str, np.ndarray] + inputs: dict[str, np.ndarray] output: np.ndarray model: ModelRunner @@ -52,7 +51,7 @@ def __init__(self): self.model = ModelRunner(MODEL_PATHS, self.output, Runtime.DSP, True, None) self.model.addInput("input_img", None) - def run(self, buf:np.ndarray) -> Tuple[np.ndarray, float]: + def run(self, buf:np.ndarray) -> tuple[np.ndarray, float]: self.inputs['input_img'][:] = buf t1 = time.perf_counter() diff --git a/selfdrive/modeld/parse_model_outputs.py b/selfdrive/modeld/parse_model_outputs.py index 01cba29d1ce059..af57e11d03c7a9 100644 --- a/selfdrive/modeld/parse_model_outputs.py +++ b/selfdrive/modeld/parse_model_outputs.py @@ -1,5 +1,4 @@ import numpy as np -from typing import Dict from openpilot.selfdrive.modeld.constants import ModelConstants def sigmoid(x): @@ -82,7 +81,7 @@ def parse_mdn(self, name, outs, in_N=0, out_N=1, out_shape=None): outs[name] = pred_mu_final.reshape(final_shape) outs[name + '_stds'] = pred_std_final.reshape(final_shape) - def parse_outputs(self, outs: Dict[str, np.ndarray]) -> Dict[str, np.ndarray]: + def parse_outputs(self, outs: dict[str, np.ndarray]) -> dict[str, np.ndarray]: self.parse_mdn('plan', outs, in_N=ModelConstants.PLAN_MHP_N, out_N=ModelConstants.PLAN_MHP_SELECTION, out_shape=(ModelConstants.IDX_N,ModelConstants.PLAN_WIDTH)) self.parse_mdn('lane_lines', outs, in_N=0, out_N=0, out_shape=(ModelConstants.NUM_LANE_LINES,ModelConstants.IDX_N,ModelConstants.LANE_LINES_WIDTH)) diff --git a/selfdrive/modeld/runners/onnxmodel.py b/selfdrive/modeld/runners/onnxmodel.py index f86bee387808f1..69b44a5a97116a 100644 --- a/selfdrive/modeld/runners/onnxmodel.py +++ b/selfdrive/modeld/runners/onnxmodel.py @@ -3,7 +3,7 @@ import os import sys import numpy as np -from typing import Tuple, Dict, Union, Any +from typing import Any from openpilot.selfdrive.modeld.runners.runmodel_pyx import RunModel @@ -38,7 +38,7 @@ def create_ort_session(path, fp16_to_fp32): options = ort.SessionOptions() options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_DISABLE_ALL - provider: Union[str, Tuple[str, Dict[Any, Any]]] + provider: str | tuple[str, dict[Any, Any]] if 'OpenVINOExecutionProvider' in ort.get_available_providers() and 'ONNXCPU' not in os.environ: provider = 'OpenVINOExecutionProvider' elif 'CUDAExecutionProvider' in ort.get_available_providers() and 'ONNXCPU' not in os.environ: diff --git a/selfdrive/navd/helpers.py b/selfdrive/navd/helpers.py index 55c3f88a9aec1a..5b0f5b7e853f3a 100644 --- a/selfdrive/navd/helpers.py +++ b/selfdrive/navd/helpers.py @@ -2,7 +2,7 @@ import json import math -from typing import Any, Dict, List, Optional, Tuple, Union, cast +from typing import Any, cast from openpilot.common.conversions import Conversions from openpilot.common.numpy_fast import clip @@ -22,13 +22,13 @@ class Coordinate: def __init__(self, latitude: float, longitude: float) -> None: self.latitude = latitude self.longitude = longitude - self.annotations: Dict[str, float] = {} + self.annotations: dict[str, float] = {} @classmethod - def from_mapbox_tuple(cls, t: Tuple[float, float]) -> Coordinate: + def from_mapbox_tuple(cls, t: tuple[float, float]) -> Coordinate: return cls(t[1], t[0]) - def as_dict(self) -> Dict[str, float]: + def as_dict(self) -> dict[str, float]: return {'latitude': self.latitude, 'longitude': self.longitude} def __str__(self) -> str: @@ -83,7 +83,7 @@ def minimum_distance(a: Coordinate, b: Coordinate, p: Coordinate): return projection.distance_to(p) -def distance_along_geometry(geometry: List[Coordinate], pos: Coordinate) -> float: +def distance_along_geometry(geometry: list[Coordinate], pos: Coordinate) -> float: if len(geometry) <= 2: return geometry[0].distance_to(pos) @@ -106,7 +106,7 @@ def distance_along_geometry(geometry: List[Coordinate], pos: Coordinate) -> floa return total_distance_closest -def coordinate_from_param(param: str, params: Optional[Params] = None) -> Optional[Coordinate]: +def coordinate_from_param(param: str, params: Params | None = None) -> Coordinate | None: if params is None: params = Params() @@ -130,7 +130,7 @@ def string_to_direction(direction: str) -> str: return 'none' -def maxspeed_to_ms(maxspeed: Dict[str, Union[str, float]]) -> float: +def maxspeed_to_ms(maxspeed: dict[str, str | float]) -> float: unit = cast(str, maxspeed['unit']) speed = cast(float, maxspeed['speed']) return SPEED_CONVERSIONS[unit] * speed @@ -140,7 +140,7 @@ def field_valid(dat: dict, field: str) -> bool: return field in dat and dat[field] is not None -def parse_banner_instructions(banners: Any, distance_to_maneuver: float = 0.0) -> Optional[Dict[str, Any]]: +def parse_banner_instructions(banners: Any, distance_to_maneuver: float = 0.0) -> dict[str, Any] | None: if not len(banners): return None diff --git a/selfdrive/statsd.py b/selfdrive/statsd.py index 94572b82c7af70..299aa295d7ea63 100755 --- a/selfdrive/statsd.py +++ b/selfdrive/statsd.py @@ -5,7 +5,7 @@ from pathlib import Path from collections import defaultdict from datetime import datetime, timezone -from typing import NoReturn, Union, List, Dict +from typing import NoReturn from openpilot.common.params import Params from cereal.messaging import SubMaster @@ -61,7 +61,7 @@ def sample(self, name: str, value: float): def main() -> NoReturn: dongle_id = Params().get("DongleId", encoding='utf-8') - def get_influxdb_line(measurement: str, value: Union[float, Dict[str, float]], timestamp: datetime, tags: dict) -> str: + def get_influxdb_line(measurement: str, value: float | dict[str, float], timestamp: datetime, tags: dict) -> str: res = f"{measurement}" for k, v in tags.items(): res += f",{k}={str(v)}" @@ -102,7 +102,7 @@ def get_influxdb_line(measurement: str, value: Union[float, Dict[str, float]], idx = 0 last_flush_time = time.monotonic() gauges = {} - samples: Dict[str, List[float]] = defaultdict(list) + samples: dict[str, list[float]] = defaultdict(list) try: while True: started_prev = sm['deviceState'].started diff --git a/selfdrive/test/ciui.py b/selfdrive/test/ciui.py index 3f33847b2975a6..f3b0c1a98f357f 100755 --- a/selfdrive/test/ciui.py +++ b/selfdrive/test/ciui.py @@ -11,7 +11,7 @@ class Window(QWidget): def __init__(self, parent=None): - super(Window, self).__init__(parent) + super().__init__(parent) layout = QVBoxLayout() self.setLayout(layout) @@ -47,7 +47,7 @@ def __init__(self, parent=None): def update(self): for cmd, label in self.labels.items(): - out = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + out = subprocess.run(cmd, capture_output=True, shell=True, check=False, encoding='utf8').stdout label.setText(out.strip()) diff --git a/selfdrive/test/fuzzy_generation.py b/selfdrive/test/fuzzy_generation.py index 28c70a0ff44b7e..00e98fadc1e3f2 100644 --- a/selfdrive/test/fuzzy_generation.py +++ b/selfdrive/test/fuzzy_generation.py @@ -1,6 +1,7 @@ import capnp import hypothesis.strategies as st -from typing import Any, Callable, Dict, List, Optional, Union +from typing import Any +from collections.abc import Callable from cereal import log @@ -12,7 +13,7 @@ def __init__(self, draw: DrawType, real_floats: bool): self.draw = draw self.real_floats = real_floats - def generate_native_type(self, field: str) -> st.SearchStrategy[Union[bool, int, float, str, bytes]]: + def generate_native_type(self, field: str) -> st.SearchStrategy[bool | int | float | str | bytes]: def floats(**kwargs) -> st.SearchStrategy[float]: allow_nan = not self.real_floats allow_infinity = not self.real_floats @@ -67,18 +68,18 @@ def rec(field_type: capnp.lib.capnp._DynamicStructReader) -> st.SearchStrategy: else: return self.generate_struct(field.schema) - def generate_struct(self, schema: capnp.lib.capnp._StructSchema, event: Optional[str] = None) -> st.SearchStrategy[Dict[str, Any]]: - full_fill: List[str] = list(schema.non_union_fields) - single_fill: List[str] = [event] if event else [self.draw(st.sampled_from(schema.union_fields))] if schema.union_fields else [] + def generate_struct(self, schema: capnp.lib.capnp._StructSchema, event: str | None = None) -> st.SearchStrategy[dict[str, Any]]: + full_fill: list[str] = list(schema.non_union_fields) + single_fill: list[str] = [event] if event else [self.draw(st.sampled_from(schema.union_fields))] if schema.union_fields else [] return st.fixed_dictionaries({field: self.generate_field(schema.fields[field]) for field in full_fill + single_fill}) @classmethod - def get_random_msg(cls, draw: DrawType, struct: capnp.lib.capnp._StructModule, real_floats: bool = False) -> Dict[str, Any]: + def get_random_msg(cls, draw: DrawType, struct: capnp.lib.capnp._StructModule, real_floats: bool = False) -> dict[str, Any]: fg = cls(draw, real_floats=real_floats) - data: Dict[str, Any] = draw(fg.generate_struct(struct.schema)) + data: dict[str, Any] = draw(fg.generate_struct(struct.schema)) return data @classmethod - def get_random_event_msg(cls, draw: DrawType, events: List[str], real_floats: bool = False) -> List[Dict[str, Any]]: + def get_random_event_msg(cls, draw: DrawType, events: list[str], real_floats: bool = False) -> list[dict[str, Any]]: fg = cls(draw, real_floats=real_floats) return [draw(fg.generate_struct(log.Event.schema, e)) for e in sorted(events)] diff --git a/selfdrive/test/helpers.py b/selfdrive/test/helpers.py index 0e7912a989ace2..a62f7ede852585 100644 --- a/selfdrive/test/helpers.py +++ b/selfdrive/test/helpers.py @@ -72,7 +72,7 @@ def noop(*args, **kwargs): def read_segment_list(segment_list_path): - with open(segment_list_path, "r") as f: + with open(segment_list_path) as f: seg_list = f.read().splitlines() return [(platform[2:], segment) for platform, segment in zip(seg_list[::2], seg_list[1::2], strict=True)] diff --git a/selfdrive/test/process_replay/capture.py b/selfdrive/test/process_replay/capture.py index 28206c6b91cfcb..90c279ef35b1e7 100644 --- a/selfdrive/test/process_replay/capture.py +++ b/selfdrive/test/process_replay/capture.py @@ -1,7 +1,7 @@ import os import sys -from typing import Tuple, no_type_check +from typing import no_type_check class FdRedirect: def __init__(self, file_prefix: str, fd: int): @@ -53,7 +53,7 @@ def link_with_current_proc(self) -> None: self.stdout_redirect.link() self.stderr_redirect.link() - def read_outerr(self) -> Tuple[str, str]: + def read_outerr(self) -> tuple[str, str]: out_str = self.stdout_redirect.read().decode() err_str = self.stderr_redirect.read().decode() return out_str, err_str diff --git a/selfdrive/test/process_replay/compare_logs.py b/selfdrive/test/process_replay/compare_logs.py index dbb7c223f57ff5..673f3b484c740e 100755 --- a/selfdrive/test/process_replay/compare_logs.py +++ b/selfdrive/test/process_replay/compare_logs.py @@ -5,7 +5,6 @@ import numbers import dictdiffer from collections import Counter -from typing import Dict from openpilot.tools.lib.logreader import LogReader @@ -97,7 +96,7 @@ def format_process_diff(diff): diff_short += f" {diff}\n" diff_long += f"\t{diff}\n" else: - cnt: Dict[str, int] = {} + cnt: dict[str, int] = {} for d in diff: diff_long += f"\t{str(d)}\n" diff --git a/selfdrive/test/process_replay/process_replay.py b/selfdrive/test/process_replay/process_replay.py index 77ac3f551e4e9e..b760548fd79a16 100755 --- a/selfdrive/test/process_replay/process_replay.py +++ b/selfdrive/test/process_replay/process_replay.py @@ -8,7 +8,8 @@ import platform from collections import OrderedDict from dataclasses import dataclass, field -from typing import Dict, List, Optional, Callable, Union, Any, Iterable, Tuple +from typing import Any +from collections.abc import Callable, Iterable from tqdm import tqdm import capnp @@ -36,9 +37,9 @@ class DummySocket: def __init__(self): - self.data: List[bytes] = [] + self.data: list[bytes] = [] - def receive(self, non_blocking: bool = False) -> Optional[bytes]: + def receive(self, non_blocking: bool = False) -> bytes | None: if non_blocking: return None @@ -128,21 +129,21 @@ def wait_for_next_recv(self, trigger_empty_recv): @dataclass class ProcessConfig: proc_name: str - pubs: List[str] - subs: List[str] - ignore: List[str] - config_callback: Optional[Callable] = None - init_callback: Optional[Callable] = None - should_recv_callback: Optional[Callable] = None - tolerance: Optional[float] = None + pubs: list[str] + subs: list[str] + ignore: list[str] + config_callback: Callable | None = None + init_callback: Callable | None = None + should_recv_callback: Callable | None = None + tolerance: float | None = None processing_time: float = 0.001 timeout: int = 30 simulation: bool = True - main_pub: Optional[str] = None + main_pub: str | None = None main_pub_drained: bool = True - vision_pubs: List[str] = field(default_factory=list) - ignore_alive_pubs: List[str] = field(default_factory=list) - unlocked_pubs: List[str] = field(default_factory=list) + vision_pubs: list[str] = field(default_factory=list) + ignore_alive_pubs: list[str] = field(default_factory=list) + unlocked_pubs: list[str] = field(default_factory=list) class ProcessContainer: @@ -150,25 +151,25 @@ def __init__(self, cfg: ProcessConfig): self.prefix = OpenpilotPrefix(clean_dirs_on_exit=False) self.cfg = copy.deepcopy(cfg) self.process = copy.deepcopy(managed_processes[cfg.proc_name]) - self.msg_queue: List[capnp._DynamicStructReader] = [] + self.msg_queue: list[capnp._DynamicStructReader] = [] self.cnt = 0 - self.pm: Optional[messaging.PubMaster] = None - self.sockets: Optional[List[messaging.SubSocket]] = None - self.rc: Optional[ReplayContext] = None - self.vipc_server: Optional[VisionIpcServer] = None - self.environ_config: Optional[Dict[str, Any]] = None - self.capture: Optional[ProcessOutputCapture] = None + self.pm: messaging.PubMaster | None = None + self.sockets: list[messaging.SubSocket] | None = None + self.rc: ReplayContext | None = None + self.vipc_server: VisionIpcServer | None = None + self.environ_config: dict[str, Any] | None = None + self.capture: ProcessOutputCapture | None = None @property def has_empty_queue(self) -> bool: return len(self.msg_queue) == 0 @property - def pubs(self) -> List[str]: + def pubs(self) -> list[str]: return self.cfg.pubs @property - def subs(self) -> List[str]: + def subs(self) -> list[str]: return self.cfg.subs def _clean_env(self): @@ -180,7 +181,7 @@ def _clean_env(self): if k in os.environ: del os.environ[k] - def _setup_env(self, params_config: Dict[str, Any], environ_config: Dict[str, Any]): + def _setup_env(self, params_config: dict[str, Any], environ_config: dict[str, Any]): for k, v in environ_config.items(): if len(v) != 0: os.environ[k] = v @@ -202,7 +203,7 @@ def _setup_env(self, params_config: Dict[str, Any], environ_config: Dict[str, An self.environ_config = environ_config - def _setup_vision_ipc(self, all_msgs: LogIterable, frs: Dict[str, Any]): + def _setup_vision_ipc(self, all_msgs: LogIterable, frs: dict[str, Any]): assert len(self.cfg.vision_pubs) != 0 vipc_server = VisionIpcServer("camerad") @@ -223,9 +224,9 @@ def _start_process(self): self.process.start() def start( - self, params_config: Dict[str, Any], environ_config: Dict[str, Any], - all_msgs: LogIterable, frs: Optional[Dict[str, BaseFrameReader]], - fingerprint: Optional[str], capture_output: bool + self, params_config: dict[str, Any], environ_config: dict[str, Any], + all_msgs: LogIterable, frs: dict[str, BaseFrameReader] | None, + fingerprint: str | None, capture_output: bool ): with self.prefix as p: self._setup_env(params_config, environ_config) @@ -266,7 +267,7 @@ def stop(self): self.prefix.clean_dirs() self._clean_env() - def run_step(self, msg: capnp._DynamicStructReader, frs: Optional[Dict[str, BaseFrameReader]]) -> List[capnp._DynamicStructReader]: + def run_step(self, msg: capnp._DynamicStructReader, frs: dict[str, BaseFrameReader] | None) -> list[capnp._DynamicStructReader]: assert self.rc and self.pm and self.sockets and self.process.proc output_msgs = [] @@ -580,7 +581,7 @@ def get_process_config(name: str) -> ProcessConfig: raise Exception(f"Cannot find process config with name: {name}") from ex -def get_custom_params_from_lr(lr: LogIterable, initial_state: str = "first") -> Dict[str, Any]: +def get_custom_params_from_lr(lr: LogIterable, initial_state: str = "first") -> dict[str, Any]: """ Use this to get custom params dict based on provided logs. Useful when replaying following processes: calibrationd, paramsd, torqued @@ -614,7 +615,7 @@ def get_custom_params_from_lr(lr: LogIterable, initial_state: str = "first") -> return custom_params -def replay_process_with_name(name: Union[str, Iterable[str]], lr: LogIterable, *args, **kwargs) -> List[capnp._DynamicStructReader]: +def replay_process_with_name(name: str | Iterable[str], lr: LogIterable, *args, **kwargs) -> list[capnp._DynamicStructReader]: if isinstance(name, str): cfgs = [get_process_config(name)] elif isinstance(name, Iterable): @@ -626,10 +627,10 @@ def replay_process_with_name(name: Union[str, Iterable[str]], lr: LogIterable, * def replay_process( - cfg: Union[ProcessConfig, Iterable[ProcessConfig]], lr: LogIterable, frs: Optional[Dict[str, BaseFrameReader]] = None, - fingerprint: Optional[str] = None, return_all_logs: bool = False, custom_params: Optional[Dict[str, Any]] = None, - captured_output_store: Optional[Dict[str, Dict[str, str]]] = None, disable_progress: bool = False -) -> List[capnp._DynamicStructReader]: + cfg: ProcessConfig | Iterable[ProcessConfig], lr: LogIterable, frs: dict[str, BaseFrameReader] | None = None, + fingerprint: str | None = None, return_all_logs: bool = False, custom_params: dict[str, Any] | None = None, + captured_output_store: dict[str, dict[str, str]] | None = None, disable_progress: bool = False +) -> list[capnp._DynamicStructReader]: if isinstance(cfg, Iterable): cfgs = list(cfg) else: @@ -654,9 +655,9 @@ def replay_process( def _replay_multi_process( - cfgs: List[ProcessConfig], lr: LogIterable, frs: Optional[Dict[str, BaseFrameReader]], fingerprint: Optional[str], - custom_params: Optional[Dict[str, Any]], captured_output_store: Optional[Dict[str, Dict[str, str]]], disable_progress: bool -) -> List[capnp._DynamicStructReader]: + cfgs: list[ProcessConfig], lr: LogIterable, frs: dict[str, BaseFrameReader] | None, fingerprint: str | None, + custom_params: dict[str, Any] | None, captured_output_store: dict[str, dict[str, str]] | None, disable_progress: bool +) -> list[capnp._DynamicStructReader]: if fingerprint is not None: params_config = generate_params_config(lr=lr, fingerprint=fingerprint, custom_params=custom_params) env_config = generate_environ_config(fingerprint=fingerprint) @@ -690,10 +691,10 @@ def _replay_multi_process( pub_msgs = [msg for msg in all_msgs if msg.which() in lr_pubs] # external queue for messages taken from logs; internal queue for messages generated by processes, which will be republished - external_pub_queue: List[capnp._DynamicStructReader] = pub_msgs.copy() - internal_pub_queue: List[capnp._DynamicStructReader] = [] + external_pub_queue: list[capnp._DynamicStructReader] = pub_msgs.copy() + internal_pub_queue: list[capnp._DynamicStructReader] = [] # heap for maintaining the order of messages generated by processes, where each element: (logMonoTime, index in internal_pub_queue) - internal_pub_index_heap: List[Tuple[int, int]] = [] + internal_pub_index_heap: list[tuple[int, int]] = [] pbar = tqdm(total=len(external_pub_queue), disable=disable_progress) while len(external_pub_queue) != 0 or (len(internal_pub_index_heap) != 0 and not all(c.has_empty_queue for c in containers)): @@ -723,7 +724,7 @@ def _replay_multi_process( return log_msgs -def generate_params_config(lr=None, CP=None, fingerprint=None, custom_params=None) -> Dict[str, Any]: +def generate_params_config(lr=None, CP=None, fingerprint=None, custom_params=None) -> dict[str, Any]: params_dict = { "OpenpilotEnabledToggle": True, "DisengageOnAccelerator": True, @@ -755,7 +756,7 @@ def generate_params_config(lr=None, CP=None, fingerprint=None, custom_params=Non return params_dict -def generate_environ_config(CP=None, fingerprint=None, log_dir=None) -> Dict[str, Any]: +def generate_environ_config(CP=None, fingerprint=None, log_dir=None) -> dict[str, Any]: environ_dict = {} if platform.system() != "Darwin": environ_dict["PARAMS_ROOT"] = "/dev/shm/params" diff --git a/selfdrive/test/process_replay/regen.py b/selfdrive/test/process_replay/regen.py index 245b5b2709e14a..3bb51d0b65ba38 100755 --- a/selfdrive/test/process_replay/regen.py +++ b/selfdrive/test/process_replay/regen.py @@ -5,7 +5,8 @@ import capnp import numpy as np -from typing import Union, Iterable, Optional, List, Any, Dict, Tuple +from typing import Any +from collections.abc import Iterable from openpilot.selfdrive.test.process_replay.process_replay import CONFIGS, FAKEDATA, ProcessConfig, replay_process, get_process_config, \ check_openpilot_enabled, get_custom_params_from_lr @@ -40,9 +41,9 @@ def zero_dcamera(): def regen_segment( - lr: LogIterable, frs: Optional[Dict[str, Any]] = None, + lr: LogIterable, frs: dict[str, Any] | None = None, processes: Iterable[ProcessConfig] = CONFIGS, disable_tqdm: bool = False -) -> List[capnp._DynamicStructReader]: +) -> list[capnp._DynamicStructReader]: all_msgs = sorted(lr, key=lambda m: m.logMonoTime) custom_params = get_custom_params_from_lr(all_msgs) @@ -57,7 +58,7 @@ def regen_segment( def setup_data_readers( route: str, sidx: int, use_route_meta: bool, needs_driver_cam: bool = True, needs_road_cam: bool = True, dummy_driver_cam: bool = False -) -> Tuple[LogReader, Dict[str, Any]]: +) -> tuple[LogReader, dict[str, Any]]: if use_route_meta: r = Route(route) lr = LogReader(r.log_paths()[sidx]) @@ -92,7 +93,7 @@ def setup_data_readers( def regen_and_save( - route: str, sidx: int, processes: Union[str, Iterable[str]] = "all", outdir: str = FAKEDATA, + route: str, sidx: int, processes: str | Iterable[str] = "all", outdir: str = FAKEDATA, upload: bool = False, use_route_meta: bool = False, disable_tqdm: bool = False, dummy_driver_cam: bool = False ) -> str: if not isinstance(processes, str) and not hasattr(processes, "__iter__"): diff --git a/selfdrive/test/process_replay/test_debayer.py b/selfdrive/test/process_replay/test_debayer.py index bea1b1fb00d47f..edf2cbd4690c24 100755 --- a/selfdrive/test/process_replay/test_debayer.py +++ b/selfdrive/test/process_replay/test_debayer.py @@ -30,7 +30,7 @@ def get_frame_fn(ref_commit, test_route, tici=True): def bzip_frames(frames): - data = bytes() + data = b'' for y, u, v in frames: data += y.tobytes() data += u.tobytes() diff --git a/selfdrive/test/process_replay/test_processes.py b/selfdrive/test/process_replay/test_processes.py index 5323a5280f10e4..2b917b0f616ba2 100755 --- a/selfdrive/test/process_replay/test_processes.py +++ b/selfdrive/test/process_replay/test_processes.py @@ -5,7 +5,7 @@ import sys from collections import defaultdict from tqdm import tqdm -from typing import Any, DefaultDict, Dict +from typing import Any from openpilot.selfdrive.car.car_helpers import interface_names from openpilot.tools.lib.openpilotci import get_url, upload_file @@ -172,11 +172,11 @@ def test_process(cfg, lr, segment, ref_log_path, new_log_path, ignore_fields=Non untested = (set(interface_names) - set(excluded_interfaces)) - {c.lower() for c in tested_cars} assert len(untested) == 0, f"Cars missing routes: {str(untested)}" - log_paths: DefaultDict[str, Dict[str, Dict[str, str]]] = defaultdict(lambda: defaultdict(dict)) + log_paths: defaultdict[str, dict[str, dict[str, str]]] = defaultdict(lambda: defaultdict(dict)) with concurrent.futures.ProcessPoolExecutor(max_workers=args.jobs) as pool: if not args.upload_only: download_segments = [seg for car, seg in segments if car in tested_cars] - log_data: Dict[str, LogReader] = {} + log_data: dict[str, LogReader] = {} p1 = pool.map(get_log_data, download_segments) for segment, lr in tqdm(p1, desc="Getting Logs", total=len(download_segments)): log_data[segment] = lr diff --git a/selfdrive/test/update_ci_routes.py b/selfdrive/test/update_ci_routes.py index 5ab5042b2b89de..bdfefb78d1b4c8 100755 --- a/selfdrive/test/update_ci_routes.py +++ b/selfdrive/test/update_ci_routes.py @@ -3,7 +3,7 @@ import re import subprocess import sys -from typing import Iterable, List, Optional +from collections.abc import Iterable from tqdm import tqdm @@ -12,14 +12,14 @@ from openpilot.tools.lib.azure_container import AzureContainer from openpilot.tools.lib.openpilotcontainers import DataCIContainer, DataProdContainer, OpenpilotCIContainer -SOURCES: List[AzureContainer] = [ +SOURCES: list[AzureContainer] = [ DataProdContainer, DataCIContainer ] DEST = OpenpilotCIContainer -def upload_route(path: str, exclude_patterns: Optional[Iterable[str]] = None) -> None: +def upload_route(path: str, exclude_patterns: Iterable[str] | None = None) -> None: if exclude_patterns is None: exclude_patterns = [r'dcamera\.hevc'] diff --git a/selfdrive/thermald/power_monitoring.py b/selfdrive/thermald/power_monitoring.py index f74118b5686818..073589edb72bc0 100644 --- a/selfdrive/thermald/power_monitoring.py +++ b/selfdrive/thermald/power_monitoring.py @@ -1,6 +1,5 @@ import time import threading -from typing import Optional from openpilot.common.params import Params from openpilot.system.hardware import HARDWARE @@ -38,7 +37,7 @@ def __init__(self): self.car_battery_capacity_uWh = max((CAR_BATTERY_CAPACITY_uWh / 10), int(car_battery_capacity_uWh)) # Calculation tick - def calculate(self, voltage: Optional[int], ignition: bool): + def calculate(self, voltage: int | None, ignition: bool): try: now = time.monotonic() @@ -108,7 +107,7 @@ def get_car_battery_capacity(self) -> int: return int(self.car_battery_capacity_uWh) # See if we need to shutdown - def should_shutdown(self, ignition: bool, in_car: bool, offroad_timestamp: Optional[float], started_seen: bool): + def should_shutdown(self, ignition: bool, in_car: bool, offroad_timestamp: float | None, started_seen: bool): if offroad_timestamp is None: return False diff --git a/selfdrive/thermald/thermald.py b/selfdrive/thermald/thermald.py index e868f2ffdd05a7..93ebd3ab87848d 100755 --- a/selfdrive/thermald/thermald.py +++ b/selfdrive/thermald/thermald.py @@ -6,7 +6,6 @@ import time from collections import OrderedDict, namedtuple from pathlib import Path -from typing import Dict, Optional, Tuple import psutil @@ -50,9 +49,9 @@ # Override to highest thermal band when offroad and above this temp OFFROAD_DANGER_TEMP = 75 -prev_offroad_states: Dict[str, Tuple[bool, Optional[str]]] = {} +prev_offroad_states: dict[str, tuple[bool, str | None]] = {} -tz_by_type: Optional[Dict[str, int]] = None +tz_by_type: dict[str, int] | None = None def populate_tz_by_type(): global tz_by_type tz_by_type = {} @@ -87,7 +86,7 @@ def read_thermal(thermal_config): return dat -def set_offroad_alert_if_changed(offroad_alert: str, show_alert: bool, extra_text: Optional[str]=None): +def set_offroad_alert_if_changed(offroad_alert: str, show_alert: bool, extra_text: str | None=None): if prev_offroad_states.get(offroad_alert, None) == (show_alert, extra_text): return prev_offroad_states[offroad_alert] = (show_alert, extra_text) @@ -169,16 +168,16 @@ def thermald_thread(end_event, hw_queue) -> None: count = 0 - onroad_conditions: Dict[str, bool] = { + onroad_conditions: dict[str, bool] = { "ignition": False, } - startup_conditions: Dict[str, bool] = {} - startup_conditions_prev: Dict[str, bool] = {} + startup_conditions: dict[str, bool] = {} + startup_conditions_prev: dict[str, bool] = {} - off_ts: Optional[float] = None - started_ts: Optional[float] = None + off_ts: float | None = None + started_ts: float | None = None started_seen = False - startup_blocked_ts: Optional[float] = None + startup_blocked_ts: float | None = None thermal_status = ThermalStatus.yellow last_hw_state = HardwareState( diff --git a/selfdrive/ui/soundd.py b/selfdrive/ui/soundd.py index 11caf809d115d7..0550a7db9ec01e 100644 --- a/selfdrive/ui/soundd.py +++ b/selfdrive/ui/soundd.py @@ -3,7 +3,6 @@ import time import wave -from typing import Dict, Optional, Tuple from cereal import car, messaging from openpilot.common.basedir import BASEDIR @@ -27,7 +26,7 @@ AudibleAlert = car.CarControl.HUDControl.AudibleAlert -sound_list: Dict[int, Tuple[str, Optional[int], float]] = { +sound_list: dict[int, tuple[str, int | None, float]] = { # AudibleAlert, file name, play count (none for infinite) AudibleAlert.engage: ("engage.wav", 1, MAX_VOLUME), AudibleAlert.disengage: ("disengage.wav", 1, MAX_VOLUME), @@ -64,7 +63,7 @@ def __init__(self): self.spl_filter_weighted = FirstOrderFilter(0, 2.5, FILTER_DT, initialized=False) def load_sounds(self): - self.loaded_sounds: Dict[int, np.ndarray] = {} + self.loaded_sounds: dict[int, np.ndarray] = {} # Load all sounds for sound in sound_list: diff --git a/selfdrive/ui/tests/test_translations.py b/selfdrive/ui/tests/test_translations.py index 9ba9054ea199fa..8e50695e7083a5 100755 --- a/selfdrive/ui/tests/test_translations.py +++ b/selfdrive/ui/tests/test_translations.py @@ -12,7 +12,7 @@ from openpilot.selfdrive.ui.update_translations import TRANSLATIONS_DIR, LANGUAGES_FILE, update_translations -with open(LANGUAGES_FILE, "r") as f: +with open(LANGUAGES_FILE) as f: translation_files = json.load(f) UNFINISHED_TRANSLATION_TAG = " None: t = datetime.datetime.utcnow() params.put(param, t.isoformat().encode('utf8')) -def read_time_from_param(params, param) -> Optional[datetime.datetime]: +def read_time_from_param(params, param) -> datetime.datetime | None: t = params.get(param, encoding='utf8') try: return datetime.datetime.fromisoformat(t) @@ -72,7 +71,7 @@ def read_time_from_param(params, param) -> Optional[datetime.datetime]: pass return None -def run(cmd: List[str], cwd: Optional[str] = None) -> str: +def run(cmd: list[str], cwd: str | None = None) -> str: return subprocess.check_output(cmd, cwd=cwd, stderr=subprocess.STDOUT, encoding='utf8') @@ -234,7 +233,7 @@ def handle_agnos_update() -> None: class Updater: def __init__(self): self.params = Params() - self.branches = defaultdict(lambda: '') + self.branches = defaultdict(str) self._has_internet: bool = False @property @@ -243,7 +242,7 @@ def has_internet(self) -> bool: @property def target_branch(self) -> str: - b: Union[str, None] = self.params.get("UpdaterTargetBranch", encoding='utf-8') + b: str | None = self.params.get("UpdaterTargetBranch", encoding='utf-8') if b is None: b = self.get_branch(BASEDIR) return b @@ -272,7 +271,7 @@ def get_branch(self, path: str) -> str: def get_commit_hash(self, path: str = OVERLAY_MERGED) -> str: return run(["git", "rev-parse", "HEAD"], path).rstrip() - def set_params(self, update_success: bool, failed_count: int, exception: Optional[str]) -> None: + def set_params(self, update_success: bool, failed_count: int, exception: str | None) -> None: self.params.put("UpdateFailedCount", str(failed_count)) self.params.put("UpdaterTargetBranch", self.target_branch) diff --git a/system/hardware/base.py b/system/hardware/base.py index 7434bb61e8cafa..6cdb4a4d64e676 100644 --- a/system/hardware/base.py +++ b/system/hardware/base.py @@ -1,6 +1,5 @@ from abc import abstractmethod, ABC from collections import namedtuple -from typing import Dict from cereal import log @@ -10,7 +9,7 @@ class HardwareBase(ABC): @staticmethod - def get_cmdline() -> Dict[str, str]: + def get_cmdline() -> dict[str, str]: with open('/proc/cmdline') as f: cmdline = f.read() return {kv[0]: kv[1] for kv in [s.split('=') for s in cmdline.split(' ')] if len(kv) == 2} diff --git a/system/hardware/tici/agnos.py b/system/hardware/tici/agnos.py index 342281b0f87a0e..502295be075389 100755 --- a/system/hardware/tici/agnos.py +++ b/system/hardware/tici/agnos.py @@ -6,7 +6,7 @@ import struct import subprocess import time -from typing import Dict, Generator, List, Tuple, Union +from collections.abc import Generator import requests @@ -117,7 +117,7 @@ def get_raw_hash(path: str, partition_size: int) -> str: return raw_hash.hexdigest().lower() -def verify_partition(target_slot_number: int, partition: Dict[str, Union[str, int]], force_full_check: bool = False) -> bool: +def verify_partition(target_slot_number: int, partition: dict[str, str | int], force_full_check: bool = False) -> bool: full_check = partition['full_check'] or force_full_check path = get_partition_path(target_slot_number, partition) @@ -184,7 +184,7 @@ def extract_casync_image(target_slot_number: int, partition: dict, cloudlog): target = casync.parse_caibx(partition['casync_caibx']) - sources: List[Tuple[str, casync.ChunkReader, casync.ChunkDict]] = [] + sources: list[tuple[str, casync.ChunkReader, casync.ChunkDict]] = [] # First source is the current partition. try: diff --git a/system/hardware/tici/amplifier.py b/system/hardware/tici/amplifier.py index e003f131ccd41e..af82067467eaf1 100755 --- a/system/hardware/tici/amplifier.py +++ b/system/hardware/tici/amplifier.py @@ -2,7 +2,6 @@ import time from smbus2 import SMBus from collections import namedtuple -from typing import List # https://datasheets.maximintegrated.com/en/ds/MAX98089.pdf @@ -110,7 +109,7 @@ def __init__(self, debug=False): def _get_shutdown_config(self, amp_disabled: bool) -> AmpConfig: return AmpConfig("Global shutdown", 0b0 if amp_disabled else 0b1, 0x51, 7, 0b10000000) - def _set_configs(self, configs: List[AmpConfig]) -> None: + def _set_configs(self, configs: list[AmpConfig]) -> None: with SMBus(self.AMP_I2C_BUS) as bus: for config in configs: if self.debug: @@ -123,7 +122,7 @@ def _set_configs(self, configs: List[AmpConfig]) -> None: if self.debug: print(f" Changed {hex(config.register)}: {hex(old_value)} -> {hex(new_value)}") - def set_configs(self, configs: List[AmpConfig]) -> bool: + def set_configs(self, configs: list[AmpConfig]) -> bool: # retry in case panda is using the amp tries = 15 for i in range(15): diff --git a/system/hardware/tici/casync.py b/system/hardware/tici/casync.py index 993336616ddbf7..68ca37d38d646d 100755 --- a/system/hardware/tici/casync.py +++ b/system/hardware/tici/casync.py @@ -7,7 +7,7 @@ import time from abc import ABC, abstractmethod from collections import defaultdict, namedtuple -from typing import Callable, Dict, List, Optional, Tuple +from collections.abc import Callable import requests from Crypto.Hash import SHA512 @@ -28,7 +28,7 @@ CAIBX_DOWNLOAD_TIMEOUT = 120 Chunk = namedtuple('Chunk', ['sha', 'offset', 'length']) -ChunkDict = Dict[bytes, Chunk] +ChunkDict = dict[bytes, Chunk] class ChunkReader(ABC): @@ -83,7 +83,7 @@ def read(self, chunk: Chunk) -> bytes: return decompressor.decompress(contents) -def parse_caibx(caibx_path: str) -> List[Chunk]: +def parse_caibx(caibx_path: str) -> list[Chunk]: """Parses the chunks from a caibx file. Can handle both local and remote files. Returns a list of chunks with hash, offset and length""" caibx: io.BufferedIOBase @@ -132,7 +132,7 @@ def parse_caibx(caibx_path: str) -> List[Chunk]: return chunks -def build_chunk_dict(chunks: List[Chunk]) -> ChunkDict: +def build_chunk_dict(chunks: list[Chunk]) -> ChunkDict: """Turn a list of chunks into a dict for faster lookups based on hash. Keep first chunk since it's more likely to be already downloaded.""" r = {} @@ -142,11 +142,11 @@ def build_chunk_dict(chunks: List[Chunk]) -> ChunkDict: return r -def extract(target: List[Chunk], - sources: List[Tuple[str, ChunkReader, ChunkDict]], +def extract(target: list[Chunk], + sources: list[tuple[str, ChunkReader, ChunkDict]], out_path: str, - progress: Optional[Callable[[int], None]] = None): - stats: Dict[str, int] = defaultdict(int) + progress: Callable[[int], None] | None = None): + stats: dict[str, int] = defaultdict(int) mode = 'rb+' if os.path.exists(out_path) else 'wb' with open(out_path, mode) as out: @@ -181,7 +181,7 @@ def extract(target: List[Chunk], return stats -def print_stats(stats: Dict[str, int]): +def print_stats(stats: dict[str, int]): total_bytes = sum(stats.values()) print(f"Total size: {total_bytes / 1024 / 1024:.2f} MB") for name, total in stats.items(): diff --git a/system/hardware/tici/power_monitor.py b/system/hardware/tici/power_monitor.py index ef3055ac47d569..296290dae84da5 100755 --- a/system/hardware/tici/power_monitor.py +++ b/system/hardware/tici/power_monitor.py @@ -3,7 +3,6 @@ import time import datetime import numpy as np -from typing import List from collections import deque from openpilot.common.realtime import Ratekeeper @@ -14,7 +13,7 @@ def read_power(): with open("/sys/bus/i2c/devices/0-0040/hwmon/hwmon1/power1_input") as f: return int(f.read()) / 1e6 -def sample_power(seconds=5) -> List[float]: +def sample_power(seconds=5) -> list[float]: rate = 123 rk = Ratekeeper(rate, print_delay_threshold=None) diff --git a/system/hardware/tici/precise_power_measure.py b/system/hardware/tici/precise_power_measure.py index e186ba4aeabd52..52fe0850ab3e15 100755 --- a/system/hardware/tici/precise_power_measure.py +++ b/system/hardware/tici/precise_power_measure.py @@ -6,4 +6,4 @@ print("measuring for 5 seconds") for _ in range(3): pwrs = sample_power() - print("mean %.2f std %.2f" % (np.mean(pwrs), np.std(pwrs))) + print(f"mean {np.mean(pwrs):.2f} std {np.std(pwrs):.2f}") diff --git a/system/hardware/tici/tests/compare_casync_manifest.py b/system/hardware/tici/tests/compare_casync_manifest.py index 835985b0b5f179..7de66d91d0cdd9 100755 --- a/system/hardware/tici/tests/compare_casync_manifest.py +++ b/system/hardware/tici/tests/compare_casync_manifest.py @@ -3,7 +3,6 @@ import collections import multiprocessing import os -from typing import Dict, List import requests from tqdm import tqdm @@ -42,7 +41,7 @@ def get_chunk_download_size(chunk): szs = list(tqdm(pool.imap(get_chunk_download_size, to), total=len(to))) chunk_sizes = {t.sha: sz for (t, sz) in zip(to, szs, strict=True)} - sources: Dict[str, List[int]] = { + sources: dict[str, list[int]] = { 'seed': [], 'remote_uncompressed': [], 'remote_compressed': [], diff --git a/system/hardware/tici/tests/test_power_draw.py b/system/hardware/tici/tests/test_power_draw.py index f6c0cf21a49c5e..352fcdf18a8b10 100755 --- a/system/hardware/tici/tests/test_power_draw.py +++ b/system/hardware/tici/tests/test_power_draw.py @@ -7,7 +7,6 @@ import numpy as np from dataclasses import dataclass from tabulate import tabulate -from typing import List import cereal.messaging as messaging from cereal.services import SERVICE_LIST @@ -22,9 +21,9 @@ @dataclass class Proc: - procs: List[str] + procs: list[str] power: float - msgs: List[str] + msgs: list[str] rtol: float = 0.05 atol: float = 0.12 @@ -66,7 +65,7 @@ def valid_power_draw(self, proc, used): return np.core.numeric.isclose(used, proc.power, rtol=proc.rtol, atol=proc.atol) def tabulate_msg_counts(self, msgs_and_power): - msg_counts = defaultdict(lambda: 0) + msg_counts = defaultdict(int) for _, counts in msgs_and_power: for msg, count in counts.items(): msg_counts[msg] += count diff --git a/system/loggerd/deleter.py b/system/loggerd/deleter.py index 868340150a400c..2f0b96c90e02b9 100755 --- a/system/loggerd/deleter.py +++ b/system/loggerd/deleter.py @@ -2,7 +2,6 @@ import os import shutil import threading -from typing import List from openpilot.system.hardware.hw import Paths from openpilot.common.swaglog import cloudlog from openpilot.system.loggerd.config import get_available_bytes, get_available_percent @@ -23,7 +22,7 @@ def has_preserve_xattr(d: str) -> bool: return getxattr(os.path.join(Paths.log_root(), d), PRESERVE_ATTR_NAME) == PRESERVE_ATTR_VALUE -def get_preserved_segments(dirs_by_creation: List[str]) -> List[str]: +def get_preserved_segments(dirs_by_creation: list[str]) -> list[str]: preserved = [] for n, d in enumerate(filter(has_preserve_xattr, reversed(dirs_by_creation))): if n == PRESERVE_COUNT: diff --git a/system/loggerd/tests/loggerd_tests_common.py b/system/loggerd/tests/loggerd_tests_common.py index 3aa9e40531a038..0532fe1a8993e5 100644 --- a/system/loggerd/tests/loggerd_tests_common.py +++ b/system/loggerd/tests/loggerd_tests_common.py @@ -2,7 +2,6 @@ import random import unittest from pathlib import Path -from typing import Optional import openpilot.system.loggerd.deleter as deleter @@ -12,7 +11,7 @@ from openpilot.system.loggerd.xattr_cache import setxattr -def create_random_file(file_path: Path, size_mb: float, lock: bool = False, upload_xattr: Optional[bytes] = None) -> None: +def create_random_file(file_path: Path, size_mb: float, lock: bool = False, upload_xattr: bytes | None = None) -> None: file_path.parent.mkdir(parents=True, exist_ok=True) if lock: @@ -82,7 +81,7 @@ def setUp(self): self.params.put("DongleId", "0000000000000000") def make_file_with_data(self, f_dir: str, fn: str, size_mb: float = .1, lock: bool = False, - upload_xattr: Optional[bytes] = None, preserve_xattr: Optional[bytes] = None) -> Path: + upload_xattr: bytes | None = None, preserve_xattr: bytes | None = None) -> Path: file_path = Path(Paths.log_root()) / f_dir / fn create_random_file(file_path, size_mb, lock, upload_xattr) diff --git a/system/loggerd/tests/test_deleter.py b/system/loggerd/tests/test_deleter.py index e4112b7b4e9f1d..37d25507e0d2b5 100755 --- a/system/loggerd/tests/test_deleter.py +++ b/system/loggerd/tests/test_deleter.py @@ -4,7 +4,7 @@ import unittest from collections import namedtuple from pathlib import Path -from typing import Sequence +from collections.abc import Sequence import openpilot.system.loggerd.deleter as deleter from openpilot.common.timeout import Timeout, TimeoutException diff --git a/system/loggerd/tests/test_loggerd.py b/system/loggerd/tests/test_loggerd.py index 963978926d4d92..c80dc19fce75fd 100755 --- a/system/loggerd/tests/test_loggerd.py +++ b/system/loggerd/tests/test_loggerd.py @@ -8,7 +8,6 @@ import time from collections import defaultdict from pathlib import Path -from typing import Dict, List from flaky import flaky import cereal.messaging as messaging @@ -76,7 +75,7 @@ def _check_sentinel(self, msgs, route): end_type = SentinelType.endOfRoute if route else SentinelType.endOfSegment assert msgs[-1].sentinel.type == end_type - def _publish_random_messages(self, services: List[str]) -> Dict[str, list]: + def _publish_random_messages(self, services: list[str]) -> dict[str, list]: pm = messaging.PubMaster(services) managed_processes["loggerd"].start() diff --git a/system/loggerd/tests/test_uploader.py b/system/loggerd/tests/test_uploader.py index b674de5438d486..b807bd6b98568d 100755 --- a/system/loggerd/tests/test_uploader.py +++ b/system/loggerd/tests/test_uploader.py @@ -6,7 +6,6 @@ import logging import json from pathlib import Path -from typing import List, Optional from openpilot.system.hardware.hw import Paths from openpilot.common.swaglog import cloudlog @@ -53,7 +52,7 @@ def join_thread(self): self.end_event.set() self.up_thread.join() - def gen_files(self, lock=False, xattr: Optional[bytes] = None, boot=True) -> List[Path]: + def gen_files(self, lock=False, xattr: bytes | None = None, boot=True) -> list[Path]: f_paths = [] for t in ["qlog", "rlog", "dcamera.hevc", "fcamera.hevc"]: f_paths.append(self.make_file_with_data(self.seg_dir, t, 1, lock=lock, upload_xattr=xattr)) @@ -62,7 +61,7 @@ def gen_files(self, lock=False, xattr: Optional[bytes] = None, boot=True) -> Lis f_paths.append(self.make_file_with_data("boot", f"{self.seg_dir}", 1, lock=lock, upload_xattr=xattr)) return f_paths - def gen_order(self, seg1: List[int], seg2: List[int], boot=True) -> List[str]: + def gen_order(self, seg1: list[int], seg2: list[int], boot=True) -> list[str]: keys = [] if boot: keys += [f"boot/{self.seg_format.format(i)}.bz2" for i in seg1] diff --git a/system/loggerd/uploader.py b/system/loggerd/uploader.py index 5c8f25368c6d96..5ccf0ff69afab4 100755 --- a/system/loggerd/uploader.py +++ b/system/loggerd/uploader.py @@ -9,7 +9,8 @@ import time import traceback import datetime -from typing import BinaryIO, Iterator, List, Optional, Tuple +from typing import BinaryIO +from collections.abc import Iterator from cereal import log import cereal.messaging as messaging @@ -42,10 +43,10 @@ def __init__(self): self.request = FakeRequest() -def get_directory_sort(d: str) -> List[str]: +def get_directory_sort(d: str) -> list[str]: return [s.rjust(10, '0') for s in d.rsplit('--', 1)] -def listdir_by_creation(d: str) -> List[str]: +def listdir_by_creation(d: str) -> list[str]: if not os.path.isdir(d): return [] @@ -82,7 +83,7 @@ def __init__(self, dongle_id: str, root: str): self.immediate_folders = ["crash/", "boot/"] self.immediate_priority = {"qlog": 0, "qlog.bz2": 0, "qcamera.ts": 1} - def list_upload_files(self, metered: bool) -> Iterator[Tuple[str, str, str]]: + def list_upload_files(self, metered: bool) -> Iterator[tuple[str, str, str]]: r = self.params.get("AthenadRecentlyViewedRoutes", encoding="utf8") requested_routes = [] if r is None else r.split(",") @@ -121,7 +122,7 @@ def list_upload_files(self, metered: bool) -> Iterator[Tuple[str, str, str]]: yield name, key, fn - def next_file_to_upload(self, metered: bool) -> Optional[Tuple[str, str, str]]: + def next_file_to_upload(self, metered: bool) -> tuple[str, str, str] | None: upload_files = list(self.list_upload_files(metered)) for name, key, fn in upload_files: @@ -207,7 +208,7 @@ def upload(self, name: str, key: str, fn: str, network_type: int, metered: bool) return success - def step(self, network_type: int, metered: bool) -> Optional[bool]: + def step(self, network_type: int, metered: bool) -> bool | None: d = self.next_file_to_upload(metered) if d is None: return None @@ -221,7 +222,7 @@ def step(self, network_type: int, metered: bool) -> Optional[bool]: return self.upload(name, key, fn, network_type, metered) -def main(exit_event: Optional[threading.Event] = None) -> None: +def main(exit_event: threading.Event | None = None) -> None: if exit_event is None: exit_event = threading.Event() diff --git a/system/loggerd/xattr_cache.py b/system/loggerd/xattr_cache.py index 5feeff34d2a464..d3220118ac6bca 100644 --- a/system/loggerd/xattr_cache.py +++ b/system/loggerd/xattr_cache.py @@ -1,10 +1,9 @@ import os import errno -from typing import Dict, Optional, Tuple -_cached_attributes: Dict[Tuple, Optional[bytes]] = {} +_cached_attributes: dict[tuple, bytes | None] = {} -def getxattr(path: str, attr_name: str) -> Optional[bytes]: +def getxattr(path: str, attr_name: str) -> bytes | None: key = (path, attr_name) if key not in _cached_attributes: try: diff --git a/system/qcomgpsd/nmeaport.py b/system/qcomgpsd/nmeaport.py index 231096fc5da813..caff7af6467c03 100644 --- a/system/qcomgpsd/nmeaport.py +++ b/system/qcomgpsd/nmeaport.py @@ -93,7 +93,7 @@ def nmea_checksum_ok(s): def process_nmea_port_messages(device:str="/dev/ttyUSB1") -> NoReturn: while True: try: - with open(device, "r") as nmeaport: + with open(device) as nmeaport: for line in nmeaport: line = line.strip() if DEBUG: diff --git a/system/qcomgpsd/qcomgpsd.py b/system/qcomgpsd/qcomgpsd.py index e2a180df863415..e8c407a6274374 100755 --- a/system/qcomgpsd/qcomgpsd.py +++ b/system/qcomgpsd/qcomgpsd.py @@ -10,7 +10,7 @@ import subprocess import datetime from multiprocessing import Process, Event -from typing import NoReturn, Optional +from typing import NoReturn from struct import unpack_from, calcsize, pack from cereal import log @@ -90,7 +90,7 @@ def try_setup_logs(diag, logs): return setup_logs(diag, logs) @retry(attempts=3, delay=1.0) -def at_cmd(cmd: str) -> Optional[str]: +def at_cmd(cmd: str) -> str | None: return subprocess.check_output(f"mmcli -m any --timeout 30 --command='{cmd}'", shell=True, encoding='utf8') def gps_enabled() -> bool: @@ -342,7 +342,7 @@ def cleanup(sig, frame): gps.bearingDeg = report["q_FltHeadingRad"] * 180/math.pi # TODO needs update if there is another leap second, after june 2024? - dt_timestamp = (datetime.datetime(1980, 1, 6, 0, 0, 0, 0, datetime.timezone.utc) + + dt_timestamp = (datetime.datetime(1980, 1, 6, 0, 0, 0, 0, datetime.UTC) + datetime.timedelta(weeks=report['w_GpsWeekNumber']) + datetime.timedelta(seconds=(1e-3*report['q_GpsFixTimeMs'] - 18))) gps.unixTimestampMillis = dt_timestamp.timestamp()*1e3 diff --git a/system/sensord/pigeond.py b/system/sensord/pigeond.py index 78b3b074981c16..21b3a86f970981 100755 --- a/system/sensord/pigeond.py +++ b/system/sensord/pigeond.py @@ -7,7 +7,6 @@ import requests import urllib.parse from datetime import datetime -from typing import List, Optional, Tuple from cereal import messaging from openpilot.common.params import Params @@ -41,7 +40,7 @@ def add_ubx_checksum(msg: bytes) -> bytes: B = (B + A) % 256 return msg + bytes([A, B]) -def get_assistnow_messages(token: bytes) -> List[bytes]: +def get_assistnow_messages(token: bytes) -> list[bytes]: # make request # TODO: implement adding the last known location r = requests.get("https://online-live2.services.u-blox.com/GetOnlineData.ashx", params=urllib.parse.urlencode({ @@ -238,7 +237,7 @@ def initialize_pigeon(pigeon: TTYPigeon) -> bool: return False return True -def deinitialize_and_exit(pigeon: Optional[TTYPigeon]): +def deinitialize_and_exit(pigeon: TTYPigeon | None): cloudlog.warning("Storing almanac in ublox flash") if pigeon is not None: @@ -259,7 +258,7 @@ def deinitialize_and_exit(pigeon: Optional[TTYPigeon]): set_power(False) sys.exit(0) -def create_pigeon() -> Tuple[TTYPigeon, messaging.PubMaster]: +def create_pigeon() -> tuple[TTYPigeon, messaging.PubMaster]: pigeon = None # register exit handler diff --git a/system/ubloxd/tests/ubloxd.py b/system/ubloxd/tests/ubloxd.py index 4ee99dc28aaf31..c17387114fd32e 100755 --- a/system/ubloxd/tests/ubloxd.py +++ b/system/ubloxd/tests/ubloxd.py @@ -82,7 +82,7 @@ def configure_ublox(dev): if __name__ == "__main__": class Device: def write(self, s): - d = '"{}"s'.format(''.join('\\x{:02X}'.format(b) for b in s)) + d = '"{}"s'.format(''.join(f'\\x{b:02X}' for b in s)) print(f" if (!send_with_ack({d})) continue;") dev = ublox.UBlox(Device(), baudrate=baudrate) diff --git a/system/version.py b/system/version.py index e34458f16f964a..4319ef2140a3da 100755 --- a/system/version.py +++ b/system/version.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 import os import subprocess -from typing import List, Callable, TypeVar +from typing import TypeVar +from collections.abc import Callable from functools import lru_cache from openpilot.common.basedir import BASEDIR @@ -18,11 +19,11 @@ def cache(user_function: Callable[..., _RT], /) -> Callable[..., _RT]: return lru_cache(maxsize=None)(user_function) -def run_cmd(cmd: List[str]) -> str: +def run_cmd(cmd: list[str]) -> str: return subprocess.check_output(cmd, encoding='utf8').strip() -def run_cmd_default(cmd: List[str], default: str = "") -> str: +def run_cmd_default(cmd: list[str], default: str = "") -> str: try: return run_cmd(cmd) except subprocess.CalledProcessError: diff --git a/system/webrtc/device/audio.py b/system/webrtc/device/audio.py index 3c78be6752653b..b1859518a17b37 100644 --- a/system/webrtc/device/audio.py +++ b/system/webrtc/device/audio.py @@ -1,6 +1,5 @@ import asyncio import io -from typing import Optional, List, Tuple import aiortc import av @@ -17,7 +16,7 @@ class AudioInputStreamTrack(aiortc.mediastreams.AudioStreamTrack): pyaudio.paFloat32: 'flt', } - def __init__(self, audio_format: int = pyaudio.paInt16, rate: int = 16000, channels: int = 1, packet_time: float = 0.020, device_index: Optional[int] = None): + def __init__(self, audio_format: int = pyaudio.paInt16, rate: int = 16000, channels: int = 1, packet_time: float = 0.020, device_index: int | None = None): super().__init__() self.p = pyaudio.PyAudio() @@ -49,7 +48,7 @@ async def recv(self): class AudioOutputSpeaker: - def __init__(self, audio_format: int = pyaudio.paInt16, rate: int = 48000, channels: int = 2, packet_time: float = 0.2, device_index: Optional[int] = None): + def __init__(self, audio_format: int = pyaudio.paInt16, rate: int = 48000, channels: int = 2, packet_time: float = 0.2, device_index: int | None = None): chunk_size = int(packet_time * rate) self.p = pyaudio.PyAudio() @@ -62,7 +61,7 @@ def __init__(self, audio_format: int = pyaudio.paInt16, rate: int = 48000, chann output=True, output_device_index=device_index, stream_callback=self.__pyaudio_callback) - self.tracks_and_tasks: List[Tuple[aiortc.MediaStreamTrack, Optional[asyncio.Task]]] = [] + self.tracks_and_tasks: list[tuple[aiortc.MediaStreamTrack, asyncio.Task | None]] = [] def __pyaudio_callback(self, in_data, frame_count, time_info, status): if self.buffer.getbuffer().nbytes < frame_count * self.channels * 2: diff --git a/system/webrtc/device/video.py b/system/webrtc/device/video.py index 314f8128349721..1bca909294504a 100644 --- a/system/webrtc/device/video.py +++ b/system/webrtc/device/video.py @@ -1,5 +1,4 @@ import asyncio -from typing import Optional import av from teleoprtc.tracks import TiciVideoStreamTrack @@ -40,5 +39,5 @@ async def recv(self): return packet - def codec_preference(self) -> Optional[str]: + def codec_preference(self) -> str | None: return "H264" diff --git a/system/webrtc/schema.py b/system/webrtc/schema.py index f659b34293fbc2..d80986ebf2599e 100644 --- a/system/webrtc/schema.py +++ b/system/webrtc/schema.py @@ -1,8 +1,8 @@ import capnp -from typing import Union, List, Dict, Any +from typing import Any -def generate_type(type_walker, schema_walker) -> Union[str, List[Any], Dict[str, Any]]: +def generate_type(type_walker, schema_walker) -> str | list[Any] | dict[str, Any]: data_type = next(type_walker) if data_type.which() == 'struct': return generate_struct(next(schema_walker)) @@ -15,11 +15,11 @@ def generate_type(type_walker, schema_walker) -> Union[str, List[Any], Dict[str, return str(data_type.which()) -def generate_struct(schema: capnp.lib.capnp._StructSchema) -> Dict[str, Any]: +def generate_struct(schema: capnp.lib.capnp._StructSchema) -> dict[str, Any]: return {field: generate_field(schema.fields[field]) for field in schema.fields if not field.endswith("DEPRECATED")} -def generate_field(field: capnp.lib.capnp._StructSchemaField) -> Union[str, List[Any], Dict[str, Any]]: +def generate_field(field: capnp.lib.capnp._StructSchemaField) -> str | list[Any] | dict[str, Any]: def schema_walker(field): yield field.schema diff --git a/system/webrtc/tests/test_webrtcd.py b/system/webrtc/tests/test_webrtcd.py index e92958cc9283a1..c31b63d02bf573 100755 --- a/system/webrtc/tests/test_webrtcd.py +++ b/system/webrtc/tests/test_webrtcd.py @@ -18,7 +18,7 @@ async def assertCompletesWithTimeout(self, awaitable, timeout=1): try: async with asyncio.timeout(timeout): await awaitable - except asyncio.TimeoutError: + except TimeoutError: self.fail("Timeout while waiting for awaitable to complete") async def test_webrtcd(self): diff --git a/system/webrtc/webrtcd.py b/system/webrtc/webrtcd.py index cc26d50daf5cae..6c1370eae9440a 100755 --- a/system/webrtc/webrtcd.py +++ b/system/webrtc/webrtcd.py @@ -6,7 +6,7 @@ import uuid import logging from dataclasses import dataclass, field -from typing import Any, List, Optional, Union, TYPE_CHECKING +from typing import Any, TYPE_CHECKING # aiortc and its dependencies have lots of internal warnings :( import warnings @@ -24,7 +24,7 @@ class CerealOutgoingMessageProxy: def __init__(self, sm: messaging.SubMaster): self.sm = sm - self.channels: List['RTCDataChannel'] = [] + self.channels: list['RTCDataChannel'] = [] def add_channel(self, channel: 'RTCDataChannel'): self.channels.append(channel) @@ -103,7 +103,7 @@ async def run(self): class StreamSession: - def __init__(self, sdp: str, cameras: List[str], incoming_services: List[str], outgoing_services: List[str], debug_mode: bool = False): + def __init__(self, sdp: str, cameras: list[str], incoming_services: list[str], outgoing_services: list[str], debug_mode: bool = False): from aiortc.mediastreams import VideoStreamTrack, AudioStreamTrack from aiortc.contrib.media import MediaBlackhole from openpilot.system.webrtc.device.video import LiveStreamVideoStreamTrack @@ -132,8 +132,8 @@ def __init__(self, sdp: str, cameras: List[str], incoming_services: List[str], o self.incoming_bridge = CerealIncomingMessageProxy(messaging.PubMaster(incoming_services)) self.outgoing_bridge_runner = CerealProxyRunner(self.outgoing_bridge) - self.audio_output: Optional[Union[AudioOutputSpeaker, MediaBlackhole]] = None - self.run_task: Optional[asyncio.Task] = None + self.audio_output: AudioOutputSpeaker | MediaBlackhole | None = None + self.run_task: asyncio.Task | None = None self.logger = logging.getLogger("webrtcd") self.logger.info("New stream session (%s), cameras %s, audio in %s out %s, incoming services %s, outgoing services %s", self.identifier, cameras, config.incoming_audio_track, config.expected_audio_track, incoming_services, outgoing_services) @@ -189,9 +189,9 @@ async def post_run_cleanup(self): @dataclass class StreamRequestBody: sdp: str - cameras: List[str] - bridge_services_in: List[str] = field(default_factory=list) - bridge_services_out: List[str] = field(default_factory=list) + cameras: list[str] + bridge_services_in: list[str] = field(default_factory=list) + bridge_services_out: list[str] = field(default_factory=list) async def get_stream(request: 'web.Request'): diff --git a/tools/bodyteleop/web.py b/tools/bodyteleop/web.py index b1fb9525db92ad..fd8f691d199ee8 100644 --- a/tools/bodyteleop/web.py +++ b/tools/bodyteleop/web.py @@ -56,7 +56,7 @@ def create_ssl_cert(cert_path: str, key_path: str): try: proc = subprocess.run(f'openssl req -x509 -newkey rsa:4096 -nodes -out {cert_path} -keyout {key_path} \ -days 365 -subj "/C=US/ST=California/O=commaai/OU=comma body"', - stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + capture_output=True, shell=True) proc.check_returncode() except subprocess.CalledProcessError as ex: raise ValueError(f"Error creating SSL certificate:\n[stdout]\n{proc.stdout.decode()}\n[stderr]\n{proc.stderr.decode()}") from ex @@ -77,7 +77,7 @@ def create_ssl_context(): ## ENDPOINTS async def index(request: 'web.Request'): - with open(os.path.join(TELEOPDIR, "static", "index.html"), "r") as f: + with open(os.path.join(TELEOPDIR, "static", "index.html")) as f: content = f.read() return web.Response(content_type="text/html", text=content) diff --git a/tools/car_porting/auto_fingerprint.py b/tools/car_porting/auto_fingerprint.py index 7dae9ce0481ecd..f122c2774e54d4 100755 --- a/tools/car_porting/auto_fingerprint.py +++ b/tools/car_porting/auto_fingerprint.py @@ -2,7 +2,6 @@ import argparse from collections import defaultdict -from typing import Optional from openpilot.selfdrive.debug.format_fingerprints import format_brand_fw_versions from openpilot.selfdrive.car.fw_versions import match_fw_to_car @@ -30,7 +29,7 @@ carVin = None carPlatform = None - platform: Optional[str] = None + platform: str | None = None CP = lr.first("carParams") diff --git a/tools/car_porting/test_car_model.py b/tools/car_porting/test_car_model.py index 66fe2ea65fdb81..86980b054b529b 100755 --- a/tools/car_porting/test_car_model.py +++ b/tools/car_porting/test_car_model.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 import argparse import sys -from typing import List import unittest from openpilot.selfdrive.car.tests.routes import CarTestRoute @@ -9,7 +8,7 @@ from openpilot.tools.lib.route import SegmentName -def create_test_models_suite(routes: List[CarTestRoute], ci=False) -> unittest.TestSuite: +def create_test_models_suite(routes: list[CarTestRoute], ci=False) -> unittest.TestSuite: test_suite = unittest.TestSuite() for test_route in routes: # create new test case and discover tests diff --git a/tools/latencylogger/latency_logger.py b/tools/latencylogger/latency_logger.py index 19c0a86bf4a835..8c6af56b6e4de4 100755 --- a/tools/latencylogger/latency_logger.py +++ b/tools/latencylogger/latency_logger.py @@ -90,7 +90,7 @@ def read_logs(lr): return (data, frame_mismatches) # This is not needed in 3.10 as a "key" parameter is added to bisect -class KeyifyList(object): +class KeyifyList: def __init__(self, inner, key): self.inner = inner self.key = key diff --git a/tools/lib/auth.py b/tools/lib/auth.py index 997d1f860dc5f5..5988397d0a94e2 100755 --- a/tools/lib/auth.py +++ b/tools/lib/auth.py @@ -26,7 +26,7 @@ import pprint import webbrowser from http.server import BaseHTTPRequestHandler, HTTPServer -from typing import Any, Dict +from typing import Any from urllib.parse import parse_qs, urlencode from openpilot.tools.lib.api import APIError, CommaApi, UnauthorizedError @@ -36,7 +36,7 @@ class ClientRedirectServer(HTTPServer): - query_params: Dict[str, Any] = {} + query_params: dict[str, Any] = {} class ClientRedirectHandler(BaseHTTPRequestHandler): diff --git a/tools/lib/azure_container.py b/tools/lib/azure_container.py index 7d9550266d0e54..52b2f37dbfb748 100644 --- a/tools/lib/azure_container.py +++ b/tools/lib/azure_container.py @@ -2,7 +2,7 @@ from datetime import datetime, timedelta from functools import lru_cache from pathlib import Path -from typing import IO, Union +from typing import IO TOKEN_PATH = Path("/data/azure_token") @@ -57,7 +57,7 @@ def get_url(self, route_name: str, segment_num, log_type="rlog") -> str: ext = "hevc" if log_type.endswith('camera') else "bz2" return self.BASE_URL + f"{route_name.replace('|', '/')}/{segment_num}/{log_type}.{ext}" - def upload_bytes(self, data: Union[bytes, IO], blob_name: str) -> str: + def upload_bytes(self, data: bytes | IO, blob_name: str) -> str: from azure.storage.blob import BlobClient blob = BlobClient( account_url=self.ACCOUNT_URL, @@ -69,6 +69,6 @@ def upload_bytes(self, data: Union[bytes, IO], blob_name: str) -> str: blob.upload_blob(data) return self.BASE_URL + blob_name - def upload_file(self, path: Union[str, os.PathLike], blob_name: str) -> str: + def upload_file(self, path: str | os.PathLike, blob_name: str) -> str: with open(path, "rb") as f: return self.upload_bytes(f, blob_name) diff --git a/tools/lib/bootlog.py b/tools/lib/bootlog.py index 827ef1eefc83ae..208ddc19c228fb 100644 --- a/tools/lib/bootlog.py +++ b/tools/lib/bootlog.py @@ -1,6 +1,5 @@ import functools import re -from typing import List, Optional from openpilot.tools.lib.auth_config import get_token from openpilot.tools.lib.api import CommaApi @@ -44,7 +43,7 @@ def __lt__(self, b) -> bool: return False return self.id < b.id -def get_bootlog_from_id(bootlog_id: str) -> Optional[Bootlog]: +def get_bootlog_from_id(bootlog_id: str) -> Bootlog | None: # TODO: implement an API endpoint for this bl = Bootlog(bootlog_id) for b in get_bootlogs(bl.dongle_id): @@ -52,7 +51,7 @@ def get_bootlog_from_id(bootlog_id: str) -> Optional[Bootlog]: return b return None -def get_bootlogs(dongle_id: str) -> List[Bootlog]: +def get_bootlogs(dongle_id: str) -> list[Bootlog]: api = CommaApi(get_token()) r = api.get(f'v1/devices/{dongle_id}/bootlogs') return [Bootlog(b) for b in r] diff --git a/tools/lib/helpers.py b/tools/lib/helpers.py index f0af3d03c5d9ca..653eb3d7e08cde 100644 --- a/tools/lib/helpers.py +++ b/tools/lib/helpers.py @@ -9,18 +9,18 @@ class RE: DONGLE_ID = r'(?P[a-f0-9]{16})' TIMESTAMP = r'(?P[0-9]{4}-[0-9]{2}-[0-9]{2}--[0-9]{2}-[0-9]{2}-[0-9]{2})' LOG_ID_V2 = r'(?P[a-f0-9]{8})--(?P[a-z0-9]{10})' - LOG_ID = r'(?P(?:{}|{}))'.format(TIMESTAMP, LOG_ID_V2) - ROUTE_NAME = r'(?P{}[|_/]{})'.format(DONGLE_ID, LOG_ID) - SEGMENT_NAME = r'{}(?:--|/)(?P[0-9]+)'.format(ROUTE_NAME) + LOG_ID = fr'(?P(?:{TIMESTAMP}|{LOG_ID_V2}))' + ROUTE_NAME = fr'(?P{DONGLE_ID}[|_/]{LOG_ID})' + SEGMENT_NAME = fr'{ROUTE_NAME}(?:--|/)(?P[0-9]+)' INDEX = r'-?[0-9]+' - SLICE = r'(?P{})?:?(?P{})?:?(?P{})?'.format(INDEX, INDEX, INDEX) - SEGMENT_RANGE = r'{}(?:(--|/)(?P({})))?(?:/(?P([qras])))?'.format(ROUTE_NAME, SLICE) + SLICE = fr'(?P{INDEX})?:?(?P{INDEX})?:?(?P{INDEX})?' + SEGMENT_RANGE = fr'{ROUTE_NAME}(?:(--|/)(?P({SLICE})))?(?:/(?P([qras])))?' BOOTLOG_NAME = ROUTE_NAME - EXPLORER_FILE = r'^(?P{})--(?P[a-z]+\.[a-z0-9]+)$'.format(SEGMENT_NAME) - OP_SEGMENT_DIR = r'^(?P{})$'.format(SEGMENT_NAME) + EXPLORER_FILE = fr'^(?P{SEGMENT_NAME})--(?P[a-z]+\.[a-z0-9]+)$' + OP_SEGMENT_DIR = fr'^(?P{SEGMENT_NAME})$' def timestamp_to_datetime(t: str) -> datetime.datetime: diff --git a/tools/lib/live_logreader.py b/tools/lib/live_logreader.py index 0678fd1d00d111..6a7ecee6fd0dad 100644 --- a/tools/lib/live_logreader.py +++ b/tools/lib/live_logreader.py @@ -1,5 +1,4 @@ import os -from typing import List from cereal import log as capnp_log, messaging from cereal.services import SERVICE_LIST @@ -8,7 +7,7 @@ ALL_SERVICES = list(SERVICE_LIST.keys()) -def raw_live_logreader(services: List[str] = ALL_SERVICES, addr: str = '127.0.0.1') -> RawLogIterable: +def raw_live_logreader(services: list[str] = ALL_SERVICES, addr: str = '127.0.0.1') -> RawLogIterable: if addr != "127.0.0.1": os.environ["ZMQ"] = "1" messaging.context = messaging.Context() @@ -25,7 +24,7 @@ def raw_live_logreader(services: List[str] = ALL_SERVICES, addr: str = '127.0.0. yield msg -def live_logreader(services: List[str] = ALL_SERVICES, addr: str = '127.0.0.1') -> LogIterable: +def live_logreader(services: list[str] = ALL_SERVICES, addr: str = '127.0.0.1') -> LogIterable: for m in raw_live_logreader(services, addr): with capnp_log.Event.from_bytes(m) as evt: yield evt diff --git a/tools/lib/logreader.py b/tools/lib/logreader.py index 7957712aff6602..6247bbc9db3304 100755 --- a/tools/lib/logreader.py +++ b/tools/lib/logreader.py @@ -11,7 +11,7 @@ import urllib.parse import warnings -from typing import Callable, Dict, Iterable, Iterator, List, Optional, Type +from collections.abc import Callable, Iterable, Iterator from urllib.parse import parse_qs, urlparse from cereal import log as capnp_log @@ -21,7 +21,7 @@ from openpilot.tools.lib.filereader import FileReader, file_exists, internal_source_available from openpilot.tools.lib.route import Route, SegmentRange -LogMessage = Type[capnp._DynamicStructReader] +LogMessage = type[capnp._DynamicStructReader] LogIterable = Iterable[LogMessage] RawLogIterable = Iterable[bytes] @@ -76,8 +76,8 @@ class ReadMode(enum.StrEnum): AUTO_INTERACTIVE = "i" # default to rlogs, fallback to qlogs with a prompt from the user -LogPath = Optional[str] -LogPaths = List[LogPath] +LogPath = str | None +LogPaths = list[LogPath] ValidFileCallable = Callable[[LogPath], bool] Source = Callable[[SegmentRange, ReadMode], LogPaths] @@ -170,7 +170,7 @@ def auto_source(sr: SegmentRange, mode=ReadMode.RLOG) -> LogPaths: if mode == ReadMode.SANITIZED: return comma_car_segments_source(sr, mode) - SOURCES: List[Source] = [internal_source, openpilotci_source, comma_api_source, comma_car_segments_source,] + SOURCES: list[Source] = [internal_source, openpilotci_source, comma_api_source, comma_car_segments_source,] exceptions = [] # Automatically determine viable source for source in SOURCES: @@ -212,7 +212,7 @@ def parse_indirect(identifier: str): class LogReader: - def _parse_identifiers(self, identifier: str | List[str]): + def _parse_identifiers(self, identifier: str | list[str]): if isinstance(identifier, list): return [i for j in identifier for i in self._parse_identifiers(j)] @@ -234,7 +234,7 @@ def _parse_identifiers(self, identifier: str | List[str]): are uploaded or auto fallback to qlogs with '/a' selector at the end of the route name." return identifiers - def __init__(self, identifier: str | List[str], default_mode: ReadMode = ReadMode.RLOG, + def __init__(self, identifier: str | list[str], default_mode: ReadMode = ReadMode.RLOG, default_source=auto_source, sort_by_time=False, only_union_types=False): self.default_mode = default_mode self.default_source = default_source @@ -243,7 +243,7 @@ def __init__(self, identifier: str | List[str], default_mode: ReadMode = ReadMod self.sort_by_time = sort_by_time self.only_union_types = only_union_types - self.__lrs: Dict[int, _LogFileReader] = {} + self.__lrs: dict[int, _LogFileReader] = {} self.reset() def _get_lr(self, i): diff --git a/tools/lib/route.py b/tools/lib/route.py index 47ebdc7a514109..bd0ccc1fc333be 100644 --- a/tools/lib/route.py +++ b/tools/lib/route.py @@ -4,7 +4,7 @@ from urllib.parse import urlparse from collections import defaultdict from itertools import chain -from typing import Optional, cast +from typing import cast from openpilot.tools.lib.auth_config import get_token from openpilot.tools.lib.api import CommaApi @@ -231,7 +231,7 @@ def segment_num(self) -> int: return self._num def route_name(self) -> RouteName: return self._route_name @property - def data_dir(self) -> Optional[str]: return self._data_dir + def data_dir(self) -> str | None: return self._data_dir def __str__(self) -> str: return self._canonical_name diff --git a/tools/lib/tests/test_comma_car_segments.py b/tools/lib/tests/test_comma_car_segments.py index b355b0fe60dfe6..50d4200b4fab9d 100644 --- a/tools/lib/tests/test_comma_car_segments.py +++ b/tools/lib/tests/test_comma_car_segments.py @@ -1,5 +1,3 @@ - - import unittest import requests diff --git a/tools/lib/vidindex.py b/tools/lib/vidindex.py index 8156faba6b08f6..f2e4e9ca45e3e9 100755 --- a/tools/lib/vidindex.py +++ b/tools/lib/vidindex.py @@ -3,7 +3,6 @@ import os import struct from enum import IntEnum -from typing import Tuple from openpilot.tools.lib.filereader import FileReader @@ -120,7 +119,7 @@ class HevcNalUnitType(IntEnum): class VideoFileInvalid(Exception): pass -def get_ue(dat: bytes, start_idx: int, skip_bits: int) -> Tuple[int, int]: +def get_ue(dat: bytes, start_idx: int, skip_bits: int) -> tuple[int, int]: prefix_val = 0 prefix_len = 0 suffix_val = 0 @@ -184,7 +183,7 @@ def get_hevc_nal_unit_type(dat: bytes, nal_unit_start: int) -> HevcNalUnitType: print(" nal_unit_type:", nal_unit_type.name, f"({nal_unit_type.value})") return nal_unit_type -def get_hevc_slice_type(dat: bytes, nal_unit_start: int, nal_unit_type: HevcNalUnitType) -> Tuple[int, bool]: +def get_hevc_slice_type(dat: bytes, nal_unit_start: int, nal_unit_type: HevcNalUnitType) -> tuple[int, bool]: # 7.3.2.9 Slice segment layer RBSP syntax # slice_segment_layer_rbsp( ) { # slice_segment_header( ) @@ -259,7 +258,7 @@ def get_hevc_slice_type(dat: bytes, nal_unit_start: int, nal_unit_type: HevcNalU raise VideoFileInvalid("slice_type must be 0, 1, or 2") return slice_type, is_first_slice -def hevc_index(hevc_file_name: str, allow_corrupt: bool=False) -> Tuple[list, int, bytes]: +def hevc_index(hevc_file_name: str, allow_corrupt: bool=False) -> tuple[list, int, bytes]: with FileReader(hevc_file_name) as f: dat = f.read() diff --git a/tools/replay/lib/ui_helpers.py b/tools/replay/lib/ui_helpers.py index e350b89bac7974..23f356308454e3 100644 --- a/tools/replay/lib/ui_helpers.py +++ b/tools/replay/lib/ui_helpers.py @@ -1,5 +1,5 @@ import itertools -from typing import Any, Dict, Tuple +from typing import Any import matplotlib.pyplot as plt import numpy as np @@ -84,7 +84,7 @@ def car_space_to_bb(self, x, y, z): return pts / self.zoom -_COLOR_CACHE : Dict[Tuple[int, int, int], Any] = {} +_COLOR_CACHE : dict[tuple[int, int, int], Any] = {} def find_color(lidar_surface, color): if color in _COLOR_CACHE: return _COLOR_CACHE[color] diff --git a/tools/sim/bridge/common.py b/tools/sim/bridge/common.py index 91ab0b6f0760ba..10e2a055a395d6 100644 --- a/tools/sim/bridge/common.py +++ b/tools/sim/bridge/common.py @@ -4,7 +4,6 @@ from multiprocessing import Process, Queue, Value from abc import ABC, abstractmethod -from typing import Optional from openpilot.common.params import Params from openpilot.common.numpy_fast import clip @@ -44,7 +43,7 @@ def __init__(self, dual_camera, high_quality): self._exit = threading.Event() self.simulator_state = SimulatorState() - self.world: Optional[World] = None + self.world: World | None = None self.past_startup_engaged = False diff --git a/tools/sim/bridge/metadrive/metadrive_bridge.py b/tools/sim/bridge/metadrive/metadrive_bridge.py index 1b1e5ffea644c9..c94fca2b959b80 100644 --- a/tools/sim/bridge/metadrive/metadrive_bridge.py +++ b/tools/sim/bridge/metadrive/metadrive_bridge.py @@ -30,14 +30,14 @@ def get_rgb_array_cpu(self): class RGBCameraWide(CopyRamRGBCamera): def __init__(self, *args, **kwargs): - super(RGBCameraWide, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) lens = self.get_lens() lens.setFov(120) lens.setNear(0.1) class RGBCameraRoad(CopyRamRGBCamera): def __init__(self, *args, **kwargs): - super(RGBCameraRoad, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) lens = self.get_lens() lens.setFov(40) lens.setNear(0.1) @@ -85,7 +85,7 @@ class MetaDriveBridge(SimulatorBridge): def __init__(self, dual_camera, high_quality): self.should_render = False - super(MetaDriveBridge, self).__init__(dual_camera, high_quality) + super().__init__(dual_camera, high_quality) def spawn_world(self): sensors = { diff --git a/tools/sim/lib/manual_ctrl.py b/tools/sim/lib/manual_ctrl.py index 5e826e7baae6cf..8a72296538246b 100755 --- a/tools/sim/lib/manual_ctrl.py +++ b/tools/sim/lib/manual_ctrl.py @@ -4,7 +4,7 @@ import os import struct from fcntl import ioctl -from typing import NoReturn, Dict, List +from typing import NoReturn # Iterate over the joystick devices. print('Available devices:') @@ -13,8 +13,8 @@ print(f' /dev/input/{fn}') # We'll store the states here. -axis_states: Dict[str, float] = {} -button_states: Dict[str, float] = {} +axis_states: dict[str, float] = {} +button_states: dict[str, float] = {} # These constants were borrowed from linux/input.h axis_names = { @@ -88,8 +88,8 @@ 0x2c3 : 'dpad_down', } -axis_name_list: List[str] = [] -button_name_list: List[str] = [] +axis_name_list: list[str] = [] +button_name_list: list[str] = [] def wheel_poll_thread(q: 'Queue[str]') -> NoReturn: # Open the joystick device. From 96ce470b7356a5dc3ca2e02aa6fc8d08646faf78 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Sat, 24 Feb 2024 20:54:04 -0800 Subject: [PATCH 02/41] VSCode settings (#31582) * base config * add launch.json * little more * cleanup * fix --------- Co-authored-by: Justin Newberry --- .gitignore | 1 - .pre-commit-config.yaml | 2 +- .vscode/extensions.json | 7 ++++++ .vscode/launch.json | 47 +++++++++++++++++++++++++++++++++++++++++ .vscode/settings.json | 16 ++++++++++++++ 5 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index 3e91531d0881bc..3da75aaea4a126 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,6 @@ venv/ .overlay_init .overlay_consistent .sconsign.dblite -.vscode* model2.png a.out .hypothesis diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 335ccae456c7f8..09fded7f773b45 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,7 +10,7 @@ repos: - id: check-ast exclude: '^(third_party)/' - id: check-json - exclude: '.devcontainer/devcontainer.json' # this supports JSON with comments + exclude: '.devcontainer/devcontainer.json|.vscode/' # these support JSON with comments - id: check-toml - id: check-xml - id: check-yaml diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000000000..3799b93e79b1c0 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "ms-python.python", + "ms-vscode.cpptools", + "elagil.pre-commit-helper", + ] +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000000000..3b3953c3f4bf56 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,47 @@ +{ + "version": "0.2.0", + "inputs": [ + { + "id": "python_process", + "type": "pickString", + "description": "Select the process to debug", + "options": [ + "selfdrive/controls/controlsd.py", + "selfdrive/navd/navd.py", + "system/timed/timed.py", + "tools/sim/run_bridge.py" + ] + }, + { + "id": "cpp_process", + "type": "pickString", + "description": "Select the process to debug", + "options": [ + "selfdrive/ui/ui" + ] + }, + { + "id": "args", + "description": "Arguments to pass to the process", + "type": "promptString" + } + ], + "configurations": [ + { + "name": "Python: openpilot Process", + "type": "debugpy", + "request": "launch", + "program": "${input:python_process}", + "console": "integratedTerminal", + "justMyCode": true, + "args": "${input:args}" + }, + { + "name": "C++: openpilot Process", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/${input:cpp_process}", + "cwd": "${workspaceFolder}", + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000000000..daf74ca7776b8c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,16 @@ +{ + "editor.tabSize": 2, + "editor.insertSpaces": true, + "editor.renderWhitespace": "trailing", + "files.trimTrailingWhitespace": true, + "search.exclude": { + "**/.git": true, + "**/.venv": true, + "**/__pycache__": true + }, + "files.exclude": { + "**/.git": true, + "**/.venv": true, + "**/__pycache__": true + } +} \ No newline at end of file From e6009d80e9323f0cbb41f058164b63eef4a9c55c Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Sun, 25 Feb 2024 01:18:13 -0500 Subject: [PATCH 03/41] cars: introduce "Platform" union type for all car enums (#31558) * Hmm * release * hmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm * unrelated * forgot * cleaner * Platform * new syntax * Fix * clean * Fix --- release/files_common | 1 + selfdrive/car/car_helpers.py | 6 +++++- selfdrive/car/interfaces.py | 7 ++++--- selfdrive/car/subaru/interface.py | 3 ++- selfdrive/car/values.py | 18 ++++++++++++++++++ 5 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 selfdrive/car/values.py diff --git a/release/files_common b/release/files_common index 1158d2c552e5d9..00a6abe6e6389b 100644 --- a/release/files_common +++ b/release/files_common @@ -87,6 +87,7 @@ selfdrive/car/docs_definitions.py selfdrive/car/car_helpers.py selfdrive/car/fingerprints.py selfdrive/car/interfaces.py +selfdrive/car/values.py selfdrive/car/vin.py selfdrive/car/disable_ecu.py selfdrive/car/fw_versions.py diff --git a/selfdrive/car/car_helpers.py b/selfdrive/car/car_helpers.py index fe4c0e885ca652..339be1912cb61d 100644 --- a/selfdrive/car/car_helpers.py +++ b/selfdrive/car/car_helpers.py @@ -5,6 +5,7 @@ from cereal import car from openpilot.common.params import Params from openpilot.common.basedir import BASEDIR +from openpilot.selfdrive.car.values import PLATFORMS from openpilot.system.version import is_comma_remote, is_tested_branch from openpilot.selfdrive.car.interfaces import get_interface_attr from openpilot.selfdrive.car.fingerprints import eliminate_incompatible_cars, all_legacy_fingerprint_cars @@ -189,7 +190,10 @@ def fingerprint(logcan, sendcan, num_pandas): cloudlog.event("fingerprinted", car_fingerprint=car_fingerprint, source=source, fuzzy=not exact_match, cached=cached, fw_count=len(car_fw), ecu_responses=list(ecu_rx_addrs), vin_rx_addr=vin_rx_addr, vin_rx_bus=vin_rx_bus, fingerprints=repr(finger), fw_query_time=fw_query_time, error=True) - return car_fingerprint, finger, vin, car_fw, source, exact_match + + car_platform = PLATFORMS.get(car_fingerprint, car_fingerprint) + + return car_platform, finger, vin, car_fw, source, exact_match def get_car(logcan, sendcan, experimental_long_allowed, num_pandas=1): diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index 05610a6dd6df6d..4516ff3a9a777f 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -14,6 +14,7 @@ from openpilot.common.numpy_fast import clip from openpilot.common.realtime import DT_CTRL from openpilot.selfdrive.car import PlatformConfig, apply_hysteresis, gen_empty_fingerprint, scale_rot_inertia, scale_tire_stiffness, STD_CARGO_KG +from openpilot.selfdrive.car.values import Platform from openpilot.selfdrive.controls.lib.drive_helpers import V_CRUISE_MAX, get_friction from openpilot.selfdrive.controls.lib.events import Events from openpilot.selfdrive.controls.lib.vehicle_model import VehicleModel @@ -101,14 +102,14 @@ def get_pid_accel_limits(CP, current_speed, cruise_speed): return ACCEL_MIN, ACCEL_MAX @classmethod - def get_non_essential_params(cls, candidate: str): + def get_non_essential_params(cls, candidate: Platform): """ Parameters essential to controlling the car may be incomplete or wrong without FW versions or fingerprints. """ return cls.get_params(candidate, gen_empty_fingerprint(), list(), False, False) @classmethod - def get_params(cls, candidate: str, fingerprint: dict[int, dict[int, int]], car_fw: list[car.CarParams.CarFw], experimental_long: bool, docs: bool): + def get_params(cls, candidate: Platform, fingerprint: dict[int, dict[int, int]], car_fw: list[car.CarParams.CarFw], experimental_long: bool, docs: bool): ret = CarInterfaceBase.get_std_params(candidate) if hasattr(candidate, "config"): @@ -132,7 +133,7 @@ def get_params(cls, candidate: str, fingerprint: dict[int, dict[int, int]], car_ @staticmethod @abstractmethod - def _get_params(ret: car.CarParams, candidate: str, fingerprint: dict[int, dict[int, int]], + def _get_params(ret: car.CarParams, candidate: Platform, fingerprint: dict[int, dict[int, int]], car_fw: list[car.CarParams.CarFw], experimental_long: bool, docs: bool): raise NotImplementedError diff --git a/selfdrive/car/subaru/interface.py b/selfdrive/car/subaru/interface.py index edf07ac2efc85a..1358adb69cdfa5 100644 --- a/selfdrive/car/subaru/interface.py +++ b/selfdrive/car/subaru/interface.py @@ -1,6 +1,7 @@ from cereal import car from panda import Panda from openpilot.selfdrive.car import get_safety_config +from openpilot.selfdrive.car.values import Platform from openpilot.selfdrive.car.disable_ecu import disable_ecu from openpilot.selfdrive.car.interfaces import CarInterfaceBase from openpilot.selfdrive.car.subaru.values import CAR, GLOBAL_ES_ADDR, LKAS_ANGLE, GLOBAL_GEN2, PREGLOBAL_CARS, HYBRID_CARS, SubaruFlags @@ -9,7 +10,7 @@ class CarInterface(CarInterfaceBase): @staticmethod - def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): + def _get_params(ret, candidate: Platform, fingerprint, car_fw, experimental_long, docs): ret.carName = "subaru" ret.radarUnavailable = True # for HYBRID CARS to be upstreamed, we need: diff --git a/selfdrive/car/values.py b/selfdrive/car/values.py new file mode 100644 index 00000000000000..7a824d25c32af0 --- /dev/null +++ b/selfdrive/car/values.py @@ -0,0 +1,18 @@ +from typing import List, cast, Dict +from openpilot.selfdrive.car.body.values import CAR as BODY +from openpilot.selfdrive.car.chrysler.values import CAR as CHRYSLER +from openpilot.selfdrive.car.ford.values import CAR as FORD +from openpilot.selfdrive.car.gm.values import CAR as GM +from openpilot.selfdrive.car.honda.values import CAR as HONDA +from openpilot.selfdrive.car.hyundai.values import CAR as HYUNDAI +from openpilot.selfdrive.car.mazda.values import CAR as MAZDA +from openpilot.selfdrive.car.nissan.values import CAR as NISSAN +from openpilot.selfdrive.car.subaru.values import CAR as SUBARU +from openpilot.selfdrive.car.tesla.values import CAR as TESLA +from openpilot.selfdrive.car.toyota.values import CAR as TOYOTA +from openpilot.selfdrive.car.volkswagen.values import CAR as VOLKSWAGEN + +Platform = BODY | CHRYSLER | FORD | GM | HONDA | HYUNDAI | MAZDA | NISSAN | SUBARU | TESLA | TOYOTA | VOLKSWAGEN +BRANDS = [BODY, CHRYSLER, FORD, GM, HONDA, HYUNDAI, MAZDA, NISSAN, SUBARU, TESLA, TOYOTA, VOLKSWAGEN] + +PLATFORMS: Dict[str, Platform] = {str(platform): platform for brand in BRANDS for platform in cast(List[Platform], brand)} From cdd4d418aaa1516d110e03199f070b3168cb55c6 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Sun, 25 Feb 2024 02:15:16 -0500 Subject: [PATCH 04/41] Subaru: fix forester weight (#31585) fix weight --- selfdrive/car/subaru/values.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/car/subaru/values.py b/selfdrive/car/subaru/values.py index e496f43628c0ca..0fd7ab9c1357bb 100644 --- a/selfdrive/car/subaru/values.py +++ b/selfdrive/car/subaru/values.py @@ -139,7 +139,7 @@ class CAR(Platforms): FORESTER = SubaruPlatformConfig( "SUBARU FORESTER 2019", SubaruCarInfo("Subaru Forester 2019-21", "All"), - specs=CarSpecs(mass=1668, wheelbase=2.67, steerRatio=17), + specs=CarSpecs(mass=1568, wheelbase=2.67, steerRatio=17), ) FORESTER_HYBRID = SubaruPlatformConfig( "SUBARU FORESTER HYBRID 2020", From be8e503a7da7b686ffa944902d58bb62925e34a9 Mon Sep 17 00:00:00 2001 From: Cameron Clough Date: Sun, 25 Feb 2024 16:24:33 +0000 Subject: [PATCH 05/41] cars: update platforms typing syntax (#31586) --- selfdrive/car/values.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/selfdrive/car/values.py b/selfdrive/car/values.py index 7a824d25c32af0..3e2787091575bc 100644 --- a/selfdrive/car/values.py +++ b/selfdrive/car/values.py @@ -1,4 +1,4 @@ -from typing import List, cast, Dict +from typing import cast from openpilot.selfdrive.car.body.values import CAR as BODY from openpilot.selfdrive.car.chrysler.values import CAR as CHRYSLER from openpilot.selfdrive.car.ford.values import CAR as FORD @@ -15,4 +15,4 @@ Platform = BODY | CHRYSLER | FORD | GM | HONDA | HYUNDAI | MAZDA | NISSAN | SUBARU | TESLA | TOYOTA | VOLKSWAGEN BRANDS = [BODY, CHRYSLER, FORD, GM, HONDA, HYUNDAI, MAZDA, NISSAN, SUBARU, TESLA, TOYOTA, VOLKSWAGEN] -PLATFORMS: Dict[str, Platform] = {str(platform): platform for brand in BRANDS for platform in cast(List[Platform], brand)} +PLATFORMS: dict[str, Platform] = {str(platform): platform for brand in BRANDS for platform in cast(list[Platform], brand)} From 30afe2c231d18bbbf71c1e26d0458bf0acacdd2f Mon Sep 17 00:00:00 2001 From: Cameron Clough Date: Sun, 25 Feb 2024 17:26:11 +0000 Subject: [PATCH 06/41] scripts: install and run pyupgrade (#31587) --- scripts/pyupgrade.sh | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100755 scripts/pyupgrade.sh diff --git a/scripts/pyupgrade.sh b/scripts/pyupgrade.sh new file mode 100755 index 00000000000000..19aac4b5e23d5c --- /dev/null +++ b/scripts/pyupgrade.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -e + +pip install --upgrade pyupgrade + +git ls-files '*.py' | grep -v 'third_party/' | xargs pyupgrade --py311-plus From 854e78eaffbdf66daccb53aa326276fb51723ee1 Mon Sep 17 00:00:00 2001 From: Robbe Derks Date: Sun, 25 Feb 2024 18:18:43 +0000 Subject: [PATCH 07/41] linux-aarch64 also works for plotjuggler --- tools/plotjuggler/juggle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/plotjuggler/juggle.py b/tools/plotjuggler/juggle.py index dc940628016c6e..0caf5a18ff6cb6 100755 --- a/tools/plotjuggler/juggle.py +++ b/tools/plotjuggler/juggle.py @@ -26,7 +26,7 @@ def install(): m = f"{platform.system()}-{platform.machine()}" - supported = ("Linux-x86_64", "Darwin-arm64", "Darwin-x86_64") + supported = ("Linux-x86_64", "Linux-aarch64", "Darwin-arm64", "Darwin-x86_64") if m not in supported: raise Exception(f"Unsupported platform: '{m}'. Supported platforms: {supported}") From 3520d479557dad78b85ce2fd1f51d656c7ea6bd2 Mon Sep 17 00:00:00 2001 From: Cameron Clough Date: Sun, 25 Feb 2024 19:41:27 +0000 Subject: [PATCH 08/41] vscode: add ruff extension (#31589) --- .vscode/extensions.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 3799b93e79b1c0..458312fc88af81 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -3,5 +3,6 @@ "ms-python.python", "ms-vscode.cpptools", "elagil.pre-commit-helper", + "charliermarsh.ruff", ] -} \ No newline at end of file +} From 80da3aee147867e46f566b63a96f4fe199e0628d Mon Sep 17 00:00:00 2001 From: Cameron Clough Date: Sun, 25 Feb 2024 21:29:18 +0000 Subject: [PATCH 09/41] mypy: use implicit-optional (#31590) * mypy: set implicit-optional = true * find and replace '| None = None' -> '= None' in function args --- common/file_helpers.py | 2 +- common/prefix.py | 2 +- pyproject.toml | 3 +++ selfdrive/athena/athenad.py | 6 +++--- selfdrive/athena/tests/test_athenad.py | 2 +- selfdrive/car/docs_definitions.py | 2 +- selfdrive/car/ecu_addrs.py | 2 +- selfdrive/car/fw_versions.py | 2 +- selfdrive/car/isotp_parallel_query.py | 2 +- selfdrive/controls/lib/alertmanager.py | 2 +- selfdrive/locationd/calibrationd.py | 2 +- selfdrive/locationd/helpers.py | 2 +- selfdrive/manager/process.py | 2 +- selfdrive/navd/helpers.py | 2 +- selfdrive/test/fuzzy_generation.py | 2 +- selfdrive/test/process_replay/process_replay.py | 6 +++--- selfdrive/test/process_replay/regen.py | 2 +- selfdrive/test/update_ci_routes.py | 2 +- selfdrive/ui/translations/auto_translate.py | 2 +- selfdrive/updated.py | 2 +- system/hardware/tici/casync.py | 2 +- system/loggerd/tests/loggerd_tests_common.py | 4 ++-- system/loggerd/tests/test_uploader.py | 2 +- system/loggerd/uploader.py | 2 +- system/webrtc/device/audio.py | 4 ++-- 25 files changed, 33 insertions(+), 30 deletions(-) diff --git a/common/file_helpers.py b/common/file_helpers.py index 417776b87ca345..29ad219c076600 100644 --- a/common/file_helpers.py +++ b/common/file_helpers.py @@ -23,7 +23,7 @@ def read(self, *args, **kwargs): @contextlib.contextmanager -def atomic_write_in_dir(path: str, mode: str = 'w', buffering: int = -1, encoding: str | None = None, newline: str | None = None, +def atomic_write_in_dir(path: str, mode: str = 'w', buffering: int = -1, encoding: str = None, newline: str = None, overwrite: bool = False): """Write to a file atomically using a temporary file in the same directory as the destination file.""" dir_name = os.path.dirname(path) diff --git a/common/prefix.py b/common/prefix.py index 40f2f34b74f0ec..4059ac09e2e409 100644 --- a/common/prefix.py +++ b/common/prefix.py @@ -8,7 +8,7 @@ from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT class OpenpilotPrefix: - def __init__(self, prefix: str | None = None, clean_dirs_on_exit: bool = True, shared_download_cache: bool = False): + def __init__(self, prefix: str = None, clean_dirs_on_exit: bool = True, shared_download_cache: bool = False): self.prefix = prefix if prefix else str(uuid.uuid4().hex[0:15]) self.msgq_path = os.path.join('/dev/shm', self.prefix) self.clean_dirs_on_exit = clean_dirs_on_exit diff --git a/pyproject.toml b/pyproject.toml index 51396ca39bb7f3..ac5bb0922ccb5b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,6 +63,9 @@ warn_unused_ignores=true # restrict dynamic typing warn_return_any=true +# allow implicit optionals for default args +implicit_optional = true + [tool.poetry] name = "openpilot" diff --git a/selfdrive/athena/athenad.py b/selfdrive/athena/athenad.py index 9480d2b8ece750..9f901498b74cbf 100755 --- a/selfdrive/athena/athenad.py +++ b/selfdrive/athena/athenad.py @@ -279,7 +279,7 @@ def upload_handler(end_event: threading.Event) -> None: cloudlog.exception("athena.upload_handler.exception") -def _do_upload(upload_item: UploadItem, callback: Callable | None = None) -> requests.Response: +def _do_upload(upload_item: UploadItem, callback: Callable = None) -> requests.Response: path = upload_item.path compress = False @@ -328,7 +328,7 @@ def getVersion() -> dict[str, str]: @dispatcher.add_method -def setNavDestination(latitude: int = 0, longitude: int = 0, place_name: str | None = None, place_details: str | None = None) -> dict[str, int]: +def setNavDestination(latitude: int = 0, longitude: int = 0, place_name: str = None, place_details: str = None) -> dict[str, int]: destination = { "latitude": latitude, "longitude": longitude, @@ -767,7 +767,7 @@ def backoff(retries: int) -> int: return random.randrange(0, min(128, int(2 ** retries))) -def main(exit_event: threading.Event | None = None): +def main(exit_event: threading.Event = None): try: set_core_affinity([0, 1, 2, 3]) except Exception: diff --git a/selfdrive/athena/tests/test_athenad.py b/selfdrive/athena/tests/test_athenad.py index 8d09661f010363..780bef345e863e 100755 --- a/selfdrive/athena/tests/test_athenad.py +++ b/selfdrive/athena/tests/test_athenad.py @@ -96,7 +96,7 @@ def _wait_for_upload(): break @staticmethod - def _create_file(file: str, parent: str | None = None, data: bytes = b'') -> str: + def _create_file(file: str, parent: str = None, data: bytes = b'') -> str: fn = os.path.join(Paths.log_root() if parent is None else parent, file) os.makedirs(os.path.dirname(fn), exist_ok=True) with open(fn, 'wb') as f: diff --git a/selfdrive/car/docs_definitions.py b/selfdrive/car/docs_definitions.py index 03ed1f32cb5d26..841cc3af2f9c55 100644 --- a/selfdrive/car/docs_definitions.py +++ b/selfdrive/car/docs_definitions.py @@ -159,7 +159,7 @@ def __call__(self): return copy.deepcopy(self) @classmethod - def common(cls, add: list[EnumBase] | None = None, remove: list[EnumBase] | None = None): + def common(cls, add: list[EnumBase] = None, remove: list[EnumBase] = None): p = [part for part in (add or []) + DEFAULT_CAR_PARTS if part not in (remove or [])] return cls(p) diff --git a/selfdrive/car/ecu_addrs.py b/selfdrive/car/ecu_addrs.py index 6d6fa333a55b6f..da5e7b46125cda 100755 --- a/selfdrive/car/ecu_addrs.py +++ b/selfdrive/car/ecu_addrs.py @@ -19,7 +19,7 @@ def make_tester_present_msg(addr, bus, subaddr=None): return make_can_msg(addr, bytes(dat), bus) -def is_tester_present_response(msg: capnp.lib.capnp._DynamicStructReader, subaddr: int | None = None) -> bool: +def is_tester_present_response(msg: capnp.lib.capnp._DynamicStructReader, subaddr: int = None) -> bool: # ISO-TP messages are always padded to 8 bytes # tester present response is always a single frame dat_offset = 1 if subaddr is not None else 0 diff --git a/selfdrive/car/fw_versions.py b/selfdrive/car/fw_versions.py index 1cf4cecd3e22f4..76738141954d79 100755 --- a/selfdrive/car/fw_versions.py +++ b/selfdrive/car/fw_versions.py @@ -39,7 +39,7 @@ def is_brand(brand: str, filter_brand: str | None) -> bool: def build_fw_dict(fw_versions: list[capnp.lib.capnp._DynamicStructBuilder], - filter_brand: str | None = None) -> dict[AddrType, set[bytes]]: + filter_brand: str = None) -> dict[AddrType, set[bytes]]: fw_versions_dict: defaultdict[AddrType, set[bytes]] = defaultdict(set) for fw in fw_versions: if is_brand(fw.brand, filter_brand) and not fw.logging: diff --git a/selfdrive/car/isotp_parallel_query.py b/selfdrive/car/isotp_parallel_query.py index 678fe9ea46e521..8fdc747e9ebcd4 100644 --- a/selfdrive/car/isotp_parallel_query.py +++ b/selfdrive/car/isotp_parallel_query.py @@ -12,7 +12,7 @@ class IsoTpParallelQuery: def __init__(self, sendcan: messaging.PubSocket, logcan: messaging.SubSocket, bus: int, addrs: list[int] | list[AddrType], request: list[bytes], response: list[bytes], response_offset: int = 0x8, - functional_addrs: list[int] | None = None, debug: bool = False, response_pending_timeout: float = 10) -> None: + functional_addrs: list[int] = None, debug: bool = False, response_pending_timeout: float = 10) -> None: self.sendcan = sendcan self.logcan = logcan self.bus = bus diff --git a/selfdrive/controls/lib/alertmanager.py b/selfdrive/controls/lib/alertmanager.py index 8034c8ebbcec98..f67e269fa97854 100644 --- a/selfdrive/controls/lib/alertmanager.py +++ b/selfdrive/controls/lib/alertmanager.py @@ -13,7 +13,7 @@ OFFROAD_ALERTS = json.load(f) -def set_offroad_alert(alert: str, show_alert: bool, extra_text: str | None = None) -> None: +def set_offroad_alert(alert: str, show_alert: bool, extra_text: str = None) -> None: if show_alert: a = copy.copy(OFFROAD_ALERTS[alert]) a['extra'] = extra_text or '' diff --git a/selfdrive/locationd/calibrationd.py b/selfdrive/locationd/calibrationd.py index 1456bf16f58048..6e154bf07cf83e 100755 --- a/selfdrive/locationd/calibrationd.py +++ b/selfdrive/locationd/calibrationd.py @@ -89,7 +89,7 @@ def reset(self, rpy_init: np.ndarray = RPY_INIT, valid_blocks: int = 0, wide_from_device_euler_init: np.ndarray = WIDE_FROM_DEVICE_EULER_INIT, height_init: np.ndarray = HEIGHT_INIT, - smooth_from: np.ndarray | None = None) -> None: + smooth_from: np.ndarray = None) -> None: if not np.isfinite(rpy_init).all(): self.rpy = RPY_INIT.copy() else: diff --git a/selfdrive/locationd/helpers.py b/selfdrive/locationd/helpers.py index c273ba87b3578b..786bdbbfec804f 100644 --- a/selfdrive/locationd/helpers.py +++ b/selfdrive/locationd/helpers.py @@ -41,7 +41,7 @@ def is_calculable(self) -> bool: def add_point(self, x: float, y: float, bucket_val: float) -> None: raise NotImplementedError - def get_points(self, num_points: int | None = None) -> Any: + def get_points(self, num_points: int = None) -> Any: points = np.vstack([x.arr for x in self.buckets.values()]) if num_points is None: return points diff --git a/selfdrive/manager/process.py b/selfdrive/manager/process.py index 46fb68f89cac3c..7964f5229daf80 100644 --- a/selfdrive/manager/process.py +++ b/selfdrive/manager/process.py @@ -109,7 +109,7 @@ def check_watchdog(self, started: bool) -> None: else: self.watchdog_seen = True - def stop(self, retry: bool = True, block: bool = True, sig: signal.Signals | None = None) -> int | None: + def stop(self, retry: bool = True, block: bool = True, sig: signal.Signals = None) -> int | None: if self.proc is None: return None diff --git a/selfdrive/navd/helpers.py b/selfdrive/navd/helpers.py index 5b0f5b7e853f3a..0f0410c2c7ccda 100644 --- a/selfdrive/navd/helpers.py +++ b/selfdrive/navd/helpers.py @@ -106,7 +106,7 @@ def distance_along_geometry(geometry: list[Coordinate], pos: Coordinate) -> floa return total_distance_closest -def coordinate_from_param(param: str, params: Params | None = None) -> Coordinate | None: +def coordinate_from_param(param: str, params: Params = None) -> Coordinate | None: if params is None: params = Params() diff --git a/selfdrive/test/fuzzy_generation.py b/selfdrive/test/fuzzy_generation.py index 00e98fadc1e3f2..26c35c0c1820d2 100644 --- a/selfdrive/test/fuzzy_generation.py +++ b/selfdrive/test/fuzzy_generation.py @@ -68,7 +68,7 @@ def rec(field_type: capnp.lib.capnp._DynamicStructReader) -> st.SearchStrategy: else: return self.generate_struct(field.schema) - def generate_struct(self, schema: capnp.lib.capnp._StructSchema, event: str | None = None) -> st.SearchStrategy[dict[str, Any]]: + def generate_struct(self, schema: capnp.lib.capnp._StructSchema, event: str = None) -> st.SearchStrategy[dict[str, Any]]: full_fill: list[str] = list(schema.non_union_fields) single_fill: list[str] = [event] if event else [self.draw(st.sampled_from(schema.union_fields))] if schema.union_fields else [] return st.fixed_dictionaries({field: self.generate_field(schema.fields[field]) for field in full_fill + single_fill}) diff --git a/selfdrive/test/process_replay/process_replay.py b/selfdrive/test/process_replay/process_replay.py index b760548fd79a16..4fb3e3c4de0116 100755 --- a/selfdrive/test/process_replay/process_replay.py +++ b/selfdrive/test/process_replay/process_replay.py @@ -627,9 +627,9 @@ def replay_process_with_name(name: str | Iterable[str], lr: LogIterable, *args, def replay_process( - cfg: ProcessConfig | Iterable[ProcessConfig], lr: LogIterable, frs: dict[str, BaseFrameReader] | None = None, - fingerprint: str | None = None, return_all_logs: bool = False, custom_params: dict[str, Any] | None = None, - captured_output_store: dict[str, dict[str, str]] | None = None, disable_progress: bool = False + cfg: ProcessConfig | Iterable[ProcessConfig], lr: LogIterable, frs: dict[str, BaseFrameReader] = None, + fingerprint: str = None, return_all_logs: bool = False, custom_params: dict[str, Any] = None, + captured_output_store: dict[str, dict[str, str]] = None, disable_progress: bool = False ) -> list[capnp._DynamicStructReader]: if isinstance(cfg, Iterable): cfgs = list(cfg) diff --git a/selfdrive/test/process_replay/regen.py b/selfdrive/test/process_replay/regen.py index 3bb51d0b65ba38..8e882207b54a8e 100755 --- a/selfdrive/test/process_replay/regen.py +++ b/selfdrive/test/process_replay/regen.py @@ -41,7 +41,7 @@ def zero_dcamera(): def regen_segment( - lr: LogIterable, frs: dict[str, Any] | None = None, + lr: LogIterable, frs: dict[str, Any] = None, processes: Iterable[ProcessConfig] = CONFIGS, disable_tqdm: bool = False ) -> list[capnp._DynamicStructReader]: all_msgs = sorted(lr, key=lambda m: m.logMonoTime) diff --git a/selfdrive/test/update_ci_routes.py b/selfdrive/test/update_ci_routes.py index bdfefb78d1b4c8..a9f4494ffd9aa6 100755 --- a/selfdrive/test/update_ci_routes.py +++ b/selfdrive/test/update_ci_routes.py @@ -19,7 +19,7 @@ DEST = OpenpilotCIContainer -def upload_route(path: str, exclude_patterns: Iterable[str] | None = None) -> None: +def upload_route(path: str, exclude_patterns: Iterable[str] = None) -> None: if exclude_patterns is None: exclude_patterns = [r'dcamera\.hevc'] diff --git a/selfdrive/ui/translations/auto_translate.py b/selfdrive/ui/translations/auto_translate.py index 8613feb245a206..c2e4bbc5527b6a 100755 --- a/selfdrive/ui/translations/auto_translate.py +++ b/selfdrive/ui/translations/auto_translate.py @@ -18,7 +18,7 @@ "The following sentence or word is in the GUI of a software called openpilot, translate it accordingly." -def get_language_files(languages: list[str] | None = None) -> dict[str, pathlib.Path]: +def get_language_files(languages: list[str] = None) -> dict[str, pathlib.Path]: files = {} with open(TRANSLATIONS_LANGUAGES) as fp: diff --git a/selfdrive/updated.py b/selfdrive/updated.py index ba4260ae3d3211..b6b395f2543828 100755 --- a/selfdrive/updated.py +++ b/selfdrive/updated.py @@ -71,7 +71,7 @@ def read_time_from_param(params, param) -> datetime.datetime | None: pass return None -def run(cmd: list[str], cwd: str | None = None) -> str: +def run(cmd: list[str], cwd: str = None) -> str: return subprocess.check_output(cmd, cwd=cwd, stderr=subprocess.STDOUT, encoding='utf8') diff --git a/system/hardware/tici/casync.py b/system/hardware/tici/casync.py index 68ca37d38d646d..986228c1cdca34 100755 --- a/system/hardware/tici/casync.py +++ b/system/hardware/tici/casync.py @@ -145,7 +145,7 @@ def build_chunk_dict(chunks: list[Chunk]) -> ChunkDict: def extract(target: list[Chunk], sources: list[tuple[str, ChunkReader, ChunkDict]], out_path: str, - progress: Callable[[int], None] | None = None): + progress: Callable[[int], None] = None): stats: dict[str, int] = defaultdict(int) mode = 'rb+' if os.path.exists(out_path) else 'wb' diff --git a/system/loggerd/tests/loggerd_tests_common.py b/system/loggerd/tests/loggerd_tests_common.py index 0532fe1a8993e5..42eec2a0f4fa36 100644 --- a/system/loggerd/tests/loggerd_tests_common.py +++ b/system/loggerd/tests/loggerd_tests_common.py @@ -11,7 +11,7 @@ from openpilot.system.loggerd.xattr_cache import setxattr -def create_random_file(file_path: Path, size_mb: float, lock: bool = False, upload_xattr: bytes | None = None) -> None: +def create_random_file(file_path: Path, size_mb: float, lock: bool = False, upload_xattr: bytes = None) -> None: file_path.parent.mkdir(parents=True, exist_ok=True) if lock: @@ -81,7 +81,7 @@ def setUp(self): self.params.put("DongleId", "0000000000000000") def make_file_with_data(self, f_dir: str, fn: str, size_mb: float = .1, lock: bool = False, - upload_xattr: bytes | None = None, preserve_xattr: bytes | None = None) -> Path: + upload_xattr: bytes = None, preserve_xattr: bytes = None) -> Path: file_path = Path(Paths.log_root()) / f_dir / fn create_random_file(file_path, size_mb, lock, upload_xattr) diff --git a/system/loggerd/tests/test_uploader.py b/system/loggerd/tests/test_uploader.py index b807bd6b98568d..73917a30cf128e 100755 --- a/system/loggerd/tests/test_uploader.py +++ b/system/loggerd/tests/test_uploader.py @@ -52,7 +52,7 @@ def join_thread(self): self.end_event.set() self.up_thread.join() - def gen_files(self, lock=False, xattr: bytes | None = None, boot=True) -> list[Path]: + def gen_files(self, lock=False, xattr: bytes = None, boot=True) -> list[Path]: f_paths = [] for t in ["qlog", "rlog", "dcamera.hevc", "fcamera.hevc"]: f_paths.append(self.make_file_with_data(self.seg_dir, t, 1, lock=lock, upload_xattr=xattr)) diff --git a/system/loggerd/uploader.py b/system/loggerd/uploader.py index 5ccf0ff69afab4..33ee8c1850caac 100755 --- a/system/loggerd/uploader.py +++ b/system/loggerd/uploader.py @@ -222,7 +222,7 @@ def step(self, network_type: int, metered: bool) -> bool | None: return self.upload(name, key, fn, network_type, metered) -def main(exit_event: threading.Event | None = None) -> None: +def main(exit_event: threading.Event = None) -> None: if exit_event is None: exit_event = threading.Event() diff --git a/system/webrtc/device/audio.py b/system/webrtc/device/audio.py index b1859518a17b37..4b22033e03e639 100644 --- a/system/webrtc/device/audio.py +++ b/system/webrtc/device/audio.py @@ -16,7 +16,7 @@ class AudioInputStreamTrack(aiortc.mediastreams.AudioStreamTrack): pyaudio.paFloat32: 'flt', } - def __init__(self, audio_format: int = pyaudio.paInt16, rate: int = 16000, channels: int = 1, packet_time: float = 0.020, device_index: int | None = None): + def __init__(self, audio_format: int = pyaudio.paInt16, rate: int = 16000, channels: int = 1, packet_time: float = 0.020, device_index: int = None): super().__init__() self.p = pyaudio.PyAudio() @@ -48,7 +48,7 @@ async def recv(self): class AudioOutputSpeaker: - def __init__(self, audio_format: int = pyaudio.paInt16, rate: int = 48000, channels: int = 2, packet_time: float = 0.2, device_index: int | None = None): + def __init__(self, audio_format: int = pyaudio.paInt16, rate: int = 48000, channels: int = 2, packet_time: float = 0.2, device_index: int = None): chunk_size = int(packet_time * rate) self.p = pyaudio.PyAudio() From da540eac1346d0d28bf7cbb2499d6193af541798 Mon Sep 17 00:00:00 2001 From: Jason Young <46612682+jyoung8607@users.noreply.github.com> Date: Sun, 25 Feb 2024 19:38:17 -0600 Subject: [PATCH 10/41] VW: Move car specs to PlatformConfig (#31567) * subaru platform config * forester wrong dbc * spacing * subaru car specs * someday! * more red diff * all brands can be done like this * but this should be done first and thats subaru specific * that seems very low but we shouldn't change it here * as long as it subclasses str its fine * well that sucked * cleanup and follow refactor * diff reduction * oops * fix * force fingerprint * Revert "force fingerprint" This reverts commit 600fbcd7d559703601a06c8876a640de417e5b6c. * space * Fix specs * this one too --------- Co-authored-by: Justin Newberry --- selfdrive/car/__init__.py | 6 +- selfdrive/car/interfaces.py | 2 + selfdrive/car/volkswagen/interface.py | 120 +-------- selfdrive/car/volkswagen/values.py | 336 ++++++++++++++++---------- 4 files changed, 217 insertions(+), 247 deletions(-) diff --git a/selfdrive/car/__init__.py b/selfdrive/car/__init__.py index 7544796b930533..ca77dce1cfe74f 100644 --- a/selfdrive/car/__init__.py +++ b/selfdrive/car/__init__.py @@ -1,6 +1,6 @@ # functions common among cars from collections import namedtuple -from dataclasses import dataclass +from dataclasses import dataclass, field from enum import ReprEnum import capnp @@ -246,11 +246,13 @@ def update(self, current_value, current_counter): CarInfos = CarInfo | list[CarInfo] -@dataclass +@dataclass(kw_only=True) class CarSpecs: mass: float wheelbase: float steerRatio: float + minSteerSpeed: float = field(default=0.) + minEnableSpeed: float = field(default=-1.) @dataclass(order=True) diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index 4516ff3a9a777f..e0db1b56d8f78e 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -118,6 +118,8 @@ def get_params(cls, candidate: Platform, fingerprint: dict[int, dict[int, int]], ret.mass = platform_config.specs.mass ret.wheelbase = platform_config.specs.wheelbase ret.steerRatio = platform_config.specs.steerRatio + ret.minEnableSpeed = platform_config.specs.minEnableSpeed + ret.minSteerSpeed = platform_config.specs.minSteerSpeed ret = cls._get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs) diff --git a/selfdrive/car/volkswagen/interface.py b/selfdrive/car/volkswagen/interface.py index 544d104d338b17..fa68e81d0d20aa 100644 --- a/selfdrive/car/volkswagen/interface.py +++ b/selfdrive/car/volkswagen/interface.py @@ -1,9 +1,8 @@ from cereal import car from panda import Panda -from openpilot.common.conversions import Conversions as CV from openpilot.selfdrive.car import get_safety_config from openpilot.selfdrive.car.interfaces import CarInterfaceBase -from openpilot.selfdrive.car.volkswagen.values import CAR, PQ_CARS, CANBUS, NetworkLocation, TransmissionType, GearShifter, VolkswagenFlags +from openpilot.selfdrive.car.volkswagen.values import PQ_CARS, CANBUS, NetworkLocation, TransmissionType, GearShifter, VolkswagenFlags ButtonType = car.CarState.ButtonEvent.Type EventName = car.CarEvent.EventName @@ -72,7 +71,6 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): # Global lateral tuning defaults, can be overridden per-vehicle - ret.steerRatio = 15.6 # Let the params learner figure this out ret.steerLimitTimer = 0.4 if candidate in PQ_CARS: ret.steerActuatorDelay = 0.2 @@ -105,122 +103,6 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): # Per-chassis tuning values, override tuning defaults here if desired - if candidate == CAR.ARTEON_MK1: - ret.mass = 1733 - ret.wheelbase = 2.84 - - elif candidate == CAR.ATLAS_MK1: - ret.mass = 2011 - ret.wheelbase = 2.98 - - elif candidate == CAR.CRAFTER_MK2: - ret.mass = 2100 - ret.wheelbase = 3.64 # SWB, LWB is 4.49, TBD how to detect difference - ret.minSteerSpeed = 50 * CV.KPH_TO_MS - - elif candidate == CAR.GOLF_MK7: - ret.mass = 1397 - ret.wheelbase = 2.62 - - elif candidate == CAR.JETTA_MK7: - ret.mass = 1328 - ret.wheelbase = 2.71 - - elif candidate == CAR.PASSAT_MK8: - ret.mass = 1551 - ret.wheelbase = 2.79 - - elif candidate == CAR.PASSAT_NMS: - ret.mass = 1503 - ret.wheelbase = 2.80 - ret.minEnableSpeed = 20 * CV.KPH_TO_MS # ACC "basic", no FtS - ret.minSteerSpeed = 50 * CV.KPH_TO_MS - - elif candidate == CAR.POLO_MK6: - ret.mass = 1230 - ret.wheelbase = 2.55 - - elif candidate == CAR.SHARAN_MK2: - ret.mass = 1639 - ret.wheelbase = 2.92 - ret.minSteerSpeed = 50 * CV.KPH_TO_MS - - elif candidate == CAR.TAOS_MK1: - ret.mass = 1498 - ret.wheelbase = 2.69 - - elif candidate == CAR.TCROSS_MK1: - ret.mass = 1150 - ret.wheelbase = 2.60 - - elif candidate == CAR.TIGUAN_MK2: - ret.mass = 1715 - ret.wheelbase = 2.74 - - elif candidate == CAR.TOURAN_MK2: - ret.mass = 1516 - ret.wheelbase = 2.79 - - elif candidate == CAR.TRANSPORTER_T61: - ret.mass = 1926 - ret.wheelbase = 3.00 # SWB, LWB is 3.40, TBD how to detect difference - ret.minSteerSpeed = 14.0 - - elif candidate == CAR.TROC_MK1: - ret.mass = 1413 - ret.wheelbase = 2.63 - - elif candidate == CAR.AUDI_A3_MK3: - ret.mass = 1335 - ret.wheelbase = 2.61 - - elif candidate == CAR.AUDI_Q2_MK1: - ret.mass = 1205 - ret.wheelbase = 2.61 - - elif candidate == CAR.AUDI_Q3_MK2: - ret.mass = 1623 - ret.wheelbase = 2.68 - - elif candidate == CAR.SEAT_ATECA_MK1: - ret.mass = 1900 - ret.wheelbase = 2.64 - - elif candidate == CAR.SEAT_LEON_MK3: - ret.mass = 1227 - ret.wheelbase = 2.64 - - elif candidate == CAR.SKODA_FABIA_MK4: - ret.mass = 1266 - ret.wheelbase = 2.56 - - elif candidate == CAR.SKODA_KAMIQ_MK1: - ret.mass = 1265 - ret.wheelbase = 2.66 - - elif candidate == CAR.SKODA_KAROQ_MK1: - ret.mass = 1278 - ret.wheelbase = 2.66 - - elif candidate == CAR.SKODA_KODIAQ_MK1: - ret.mass = 1569 - ret.wheelbase = 2.79 - - elif candidate == CAR.SKODA_OCTAVIA_MK3: - ret.mass = 1388 - ret.wheelbase = 2.68 - - elif candidate == CAR.SKODA_SCALA_MK1: - ret.mass = 1192 - ret.wheelbase = 2.65 - - elif candidate == CAR.SKODA_SUPERB_MK3: - ret.mass = 1505 - ret.wheelbase = 2.84 - - else: - raise ValueError(f"unsupported car {candidate}") - ret.autoResumeSng = ret.minEnableSpeed == -1 ret.centerToFront = ret.wheelbase * 0.45 return ret diff --git a/selfdrive/car/volkswagen/values.py b/selfdrive/car/volkswagen/values.py index e49b9850bea4ef..f0297402840c11 100644 --- a/selfdrive/car/volkswagen/values.py +++ b/selfdrive/car/volkswagen/values.py @@ -1,11 +1,12 @@ -from collections import defaultdict, namedtuple +from collections import namedtuple from dataclasses import dataclass, field -from enum import Enum, IntFlag, StrEnum +from enum import Enum, IntFlag from cereal import car from panda.python import uds from opendbc.can.can_define import CANDefine -from openpilot.selfdrive.car import dbc_dict +from openpilot.common.conversions import Conversions as CV +from openpilot.selfdrive.car import dbc_dict, CarSpecs, DbcDict, PlatformConfig, Platforms from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarHarness, CarInfo, CarParts, Column, \ Device from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, p16 @@ -111,49 +112,17 @@ class CANBUS: class VolkswagenFlags(IntFlag): STOCK_HCA_PRESENT = 1 +@dataclass +class VolkswagenMQBPlatformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('vw_mqb_2010', None)) -# Check the 7th and 8th characters of the VIN before adding a new CAR. If the -# chassis code is already listed below, don't add a new CAR, just add to the -# FW_VERSIONS for that existing CAR. -# Exception: SEAT Leon and SEAT Ateca share a chassis code - -class CAR(StrEnum): - ARTEON_MK1 = "VOLKSWAGEN ARTEON 1ST GEN" # Chassis AN, Mk1 VW Arteon and variants - ATLAS_MK1 = "VOLKSWAGEN ATLAS 1ST GEN" # Chassis CA, Mk1 VW Atlas and Atlas Cross Sport - CRAFTER_MK2 = "VOLKSWAGEN CRAFTER 2ND GEN" # Chassis SY/SZ, Mk2 VW Crafter, VW Grand California, MAN TGE - GOLF_MK7 = "VOLKSWAGEN GOLF 7TH GEN" # Chassis 5G/AU/BA/BE, Mk7 VW Golf and variants - JETTA_MK7 = "VOLKSWAGEN JETTA 7TH GEN" # Chassis BU, Mk7 VW Jetta - PASSAT_MK8 = "VOLKSWAGEN PASSAT 8TH GEN" # Chassis 3G, Mk8 VW Passat and variants - PASSAT_NMS = "VOLKSWAGEN PASSAT NMS" # Chassis A3, North America/China/Mideast NMS Passat, incl. facelift - POLO_MK6 = "VOLKSWAGEN POLO 6TH GEN" # Chassis AW, Mk6 VW Polo - SHARAN_MK2 = "VOLKSWAGEN SHARAN 2ND GEN" # Chassis 7N, Mk2 Volkswagen Sharan and SEAT Alhambra - TAOS_MK1 = "VOLKSWAGEN TAOS 1ST GEN" # Chassis B2, Mk1 VW Taos and Tharu - TCROSS_MK1 = "VOLKSWAGEN T-CROSS 1ST GEN" # Chassis C1, Mk1 VW T-Cross SWB and LWB variants - TIGUAN_MK2 = "VOLKSWAGEN TIGUAN 2ND GEN" # Chassis AD/BW, Mk2 VW Tiguan and variants - TOURAN_MK2 = "VOLKSWAGEN TOURAN 2ND GEN" # Chassis 1T, Mk2 VW Touran and variants - TRANSPORTER_T61 = "VOLKSWAGEN TRANSPORTER T6.1" # Chassis 7H/7L, T6-facelift Transporter/Multivan/Caravelle/California - TROC_MK1 = "VOLKSWAGEN T-ROC 1ST GEN" # Chassis A1, Mk1 VW T-Roc and variants - AUDI_A3_MK3 = "AUDI A3 3RD GEN" # Chassis 8V/FF, Mk3 Audi A3 and variants - AUDI_Q2_MK1 = "AUDI Q2 1ST GEN" # Chassis GA, Mk1 Audi Q2 (RoW) and Q2L (China only) - AUDI_Q3_MK2 = "AUDI Q3 2ND GEN" # Chassis 8U/F3/FS, Mk2 Audi Q3 and variants - SEAT_ATECA_MK1 = "SEAT ATECA 1ST GEN" # Chassis 5F, Mk1 SEAT Ateca and CUPRA Ateca - SEAT_LEON_MK3 = "SEAT LEON 3RD GEN" # Chassis 5F, Mk3 SEAT Leon and variants - SKODA_FABIA_MK4 = "SKODA FABIA 4TH GEN" # Chassis PJ, Mk4 Skoda Fabia - SKODA_KAMIQ_MK1 = "SKODA KAMIQ 1ST GEN" # Chassis NW, Mk1 Skoda Kamiq - SKODA_KAROQ_MK1 = "SKODA KAROQ 1ST GEN" # Chassis NU, Mk1 Skoda Karoq - SKODA_KODIAQ_MK1 = "SKODA KODIAQ 1ST GEN" # Chassis NS, Mk1 Skoda Kodiaq - SKODA_SCALA_MK1 = "SKODA SCALA 1ST GEN" # Chassis NW, Mk1 Skoda Scala and Skoda Kamiq - SKODA_SUPERB_MK3 = "SKODA SUPERB 3RD GEN" # Chassis 3V/NP, Mk3 Skoda Superb and variants - SKODA_OCTAVIA_MK3 = "SKODA OCTAVIA 3RD GEN" # Chassis NE, Mk3 Skoda Octavia and variants - - -PQ_CARS = {CAR.PASSAT_NMS, CAR.SHARAN_MK2} - - -DBC: dict[str, dict[str, str]] = defaultdict(lambda: dbc_dict("vw_mqb_2010", None)) -for car_type in PQ_CARS: - DBC[car_type] = dbc_dict("vw_golf_mk4", None) +@dataclass +class VolkswagenPQPlatformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('vw_golf_mk4', None)) +@dataclass(kw_only=True) +class VolkswagenCarSpecs(CarSpecs): + steerRatio: float = field(default=15.6) class Footnote(Enum): KAMIQ = CarFootnote( @@ -189,90 +158,202 @@ def init_make(self, CP: car.CarParams): if CP.carFingerprint in (CAR.CRAFTER_MK2, CAR.TRANSPORTER_T61): self.car_parts = CarParts([Device.threex_angled_mount, CarHarness.j533]) +# Check the 7th and 8th characters of the VIN before adding a new CAR. If the +# chassis code is already listed below, don't add a new CAR, just add to the +# FW_VERSIONS for that existing CAR. +# Exception: SEAT Leon and SEAT Ateca share a chassis code -CAR_INFO: dict[str, VWCarInfo | list[VWCarInfo]] = { - CAR.ARTEON_MK1: [ - VWCarInfo("Volkswagen Arteon 2018-23", video_link="https://youtu.be/FAomFKPFlDA"), - VWCarInfo("Volkswagen Arteon R 2020-23", video_link="https://youtu.be/FAomFKPFlDA"), - VWCarInfo("Volkswagen Arteon eHybrid 2020-23", video_link="https://youtu.be/FAomFKPFlDA"), - VWCarInfo("Volkswagen CC 2018-22", video_link="https://youtu.be/FAomFKPFlDA"), - ], - CAR.ATLAS_MK1: [ - VWCarInfo("Volkswagen Atlas 2018-23"), - VWCarInfo("Volkswagen Atlas Cross Sport 2020-22"), - VWCarInfo("Volkswagen Teramont 2018-22"), - VWCarInfo("Volkswagen Teramont Cross Sport 2021-22"), - VWCarInfo("Volkswagen Teramont X 2021-22"), - ], - CAR.CRAFTER_MK2: [ - VWCarInfo("Volkswagen Crafter 2017-23", video_link="https://youtu.be/4100gLeabmo"), - VWCarInfo("Volkswagen e-Crafter 2018-23", video_link="https://youtu.be/4100gLeabmo"), - VWCarInfo("Volkswagen Grand California 2019-23", video_link="https://youtu.be/4100gLeabmo"), - VWCarInfo("MAN TGE 2017-23", video_link="https://youtu.be/4100gLeabmo"), - VWCarInfo("MAN eTGE 2020-23", video_link="https://youtu.be/4100gLeabmo"), - ], - CAR.GOLF_MK7: [ - VWCarInfo("Volkswagen e-Golf 2014-20"), - VWCarInfo("Volkswagen Golf 2015-20", auto_resume=False), - VWCarInfo("Volkswagen Golf Alltrack 2015-19", auto_resume=False), - VWCarInfo("Volkswagen Golf GTD 2015-20"), - VWCarInfo("Volkswagen Golf GTE 2015-20"), - VWCarInfo("Volkswagen Golf GTI 2015-21", auto_resume=False), - VWCarInfo("Volkswagen Golf R 2015-19"), - VWCarInfo("Volkswagen Golf SportsVan 2015-20"), - ], - CAR.JETTA_MK7: [ - VWCarInfo("Volkswagen Jetta 2018-24"), - VWCarInfo("Volkswagen Jetta GLI 2021-24"), - ], - CAR.PASSAT_MK8: [ - VWCarInfo("Volkswagen Passat 2015-22", footnotes=[Footnote.PASSAT]), - VWCarInfo("Volkswagen Passat Alltrack 2015-22"), - VWCarInfo("Volkswagen Passat GTE 2015-22"), - ], - CAR.PASSAT_NMS: VWCarInfo("Volkswagen Passat NMS 2017-22"), - CAR.POLO_MK6: [ - VWCarInfo("Volkswagen Polo 2018-23", footnotes=[Footnote.VW_MQB_A0]), - VWCarInfo("Volkswagen Polo GTI 2018-23", footnotes=[Footnote.VW_MQB_A0]), - ], - CAR.SHARAN_MK2: [ - VWCarInfo("Volkswagen Sharan 2018-22"), - VWCarInfo("SEAT Alhambra 2018-20"), - ], - CAR.TAOS_MK1: VWCarInfo("Volkswagen Taos 2022-23"), - CAR.TCROSS_MK1: VWCarInfo("Volkswagen T-Cross 2021", footnotes=[Footnote.VW_MQB_A0]), - CAR.TIGUAN_MK2: [ - VWCarInfo("Volkswagen Tiguan 2018-24"), - VWCarInfo("Volkswagen Tiguan eHybrid 2021-23"), - ], - CAR.TOURAN_MK2: VWCarInfo("Volkswagen Touran 2016-23"), - CAR.TRANSPORTER_T61: [ - VWCarInfo("Volkswagen Caravelle 2020"), - VWCarInfo("Volkswagen California 2021-23"), - ], - CAR.TROC_MK1: VWCarInfo("Volkswagen T-Roc 2018-22", footnotes=[Footnote.VW_MQB_A0]), - CAR.AUDI_A3_MK3: [ - VWCarInfo("Audi A3 2014-19"), - VWCarInfo("Audi A3 Sportback e-tron 2017-18"), - VWCarInfo("Audi RS3 2018"), - VWCarInfo("Audi S3 2015-17"), - ], - CAR.AUDI_Q2_MK1: VWCarInfo("Audi Q2 2018"), - CAR.AUDI_Q3_MK2: VWCarInfo("Audi Q3 2019-23"), - CAR.SEAT_ATECA_MK1: VWCarInfo("SEAT Ateca 2018"), - CAR.SEAT_LEON_MK3: VWCarInfo("SEAT Leon 2014-20"), - CAR.SKODA_FABIA_MK4: VWCarInfo("Å koda Fabia 2022-23", footnotes=[Footnote.VW_MQB_A0]), - CAR.SKODA_KAMIQ_MK1: VWCarInfo("Å koda Kamiq 2021-23", footnotes=[Footnote.VW_MQB_A0, Footnote.KAMIQ]), - CAR.SKODA_KAROQ_MK1: VWCarInfo("Å koda Karoq 2019-23"), - CAR.SKODA_KODIAQ_MK1: VWCarInfo("Å koda Kodiaq 2017-23"), - CAR.SKODA_SCALA_MK1: VWCarInfo("Å koda Scala 2020-23", footnotes=[Footnote.VW_MQB_A0]), - CAR.SKODA_SUPERB_MK3: VWCarInfo("Å koda Superb 2015-22"), - CAR.SKODA_OCTAVIA_MK3: [ - VWCarInfo("Å koda Octavia 2015-19"), - VWCarInfo("Å koda Octavia RS 2016"), - ], -} +class CAR(Platforms): + ARTEON_MK1 = VolkswagenMQBPlatformConfig( + "VOLKSWAGEN ARTEON 1ST GEN", # Chassis AN + [ + VWCarInfo("Volkswagen Arteon 2018-23", video_link="https://youtu.be/FAomFKPFlDA"), + VWCarInfo("Volkswagen Arteon R 2020-23", video_link="https://youtu.be/FAomFKPFlDA"), + VWCarInfo("Volkswagen Arteon eHybrid 2020-23", video_link="https://youtu.be/FAomFKPFlDA"), + VWCarInfo("Volkswagen CC 2018-22", video_link="https://youtu.be/FAomFKPFlDA"), + ], + specs=VolkswagenCarSpecs(mass=1733, wheelbase=2.84), + ) + ATLAS_MK1 = VolkswagenMQBPlatformConfig( + "VOLKSWAGEN ATLAS 1ST GEN", # Chassis CA + [ + VWCarInfo("Volkswagen Atlas 2018-23"), + VWCarInfo("Volkswagen Atlas Cross Sport 2020-22"), + VWCarInfo("Volkswagen Teramont 2018-22"), + VWCarInfo("Volkswagen Teramont Cross Sport 2021-22"), + VWCarInfo("Volkswagen Teramont X 2021-22"), + ], + specs=VolkswagenCarSpecs(mass=2011, wheelbase=2.98), + ) + CRAFTER_MK2 = VolkswagenMQBPlatformConfig( + "VOLKSWAGEN CRAFTER 2ND GEN", # Chassis SY/SZ + [ + VWCarInfo("Volkswagen Crafter 2017-23", video_link="https://youtu.be/4100gLeabmo"), + VWCarInfo("Volkswagen e-Crafter 2018-23", video_link="https://youtu.be/4100gLeabmo"), + VWCarInfo("Volkswagen Grand California 2019-23", video_link="https://youtu.be/4100gLeabmo"), + VWCarInfo("MAN TGE 2017-23", video_link="https://youtu.be/4100gLeabmo"), + VWCarInfo("MAN eTGE 2020-23", video_link="https://youtu.be/4100gLeabmo"), + ], + specs=VolkswagenCarSpecs(mass=2100, wheelbase=3.64, minSteerSpeed=50 * CV.KPH_TO_MS), + ) + GOLF_MK7 = VolkswagenMQBPlatformConfig( + "VOLKSWAGEN GOLF 7TH GEN", # Chassis 5G/AU/BA/BE + [ + VWCarInfo("Volkswagen e-Golf 2014-20"), + VWCarInfo("Volkswagen Golf 2015-20", auto_resume=False), + VWCarInfo("Volkswagen Golf Alltrack 2015-19", auto_resume=False), + VWCarInfo("Volkswagen Golf GTD 2015-20"), + VWCarInfo("Volkswagen Golf GTE 2015-20"), + VWCarInfo("Volkswagen Golf GTI 2015-21", auto_resume=False), + VWCarInfo("Volkswagen Golf R 2015-19"), + VWCarInfo("Volkswagen Golf SportsVan 2015-20"), + ], + specs=VolkswagenCarSpecs(mass=1397, wheelbase=2.62), + ) + JETTA_MK7 = VolkswagenMQBPlatformConfig( + "VOLKSWAGEN JETTA 7TH GEN", # Chassis BU + [ + VWCarInfo("Volkswagen Jetta 2018-24"), + VWCarInfo("Volkswagen Jetta GLI 2021-24"), + ], + specs=VolkswagenCarSpecs(mass=1328, wheelbase=2.71), + ) + PASSAT_MK8 = VolkswagenMQBPlatformConfig( + "VOLKSWAGEN PASSAT 8TH GEN", # Chassis 3G + [ + VWCarInfo("Volkswagen Passat 2015-22", footnotes=[Footnote.PASSAT]), + VWCarInfo("Volkswagen Passat Alltrack 2015-22"), + VWCarInfo("Volkswagen Passat GTE 2015-22"), + ], + specs=VolkswagenCarSpecs(mass=1551, wheelbase=2.79), + ) + PASSAT_NMS = VolkswagenPQPlatformConfig( + "VOLKSWAGEN PASSAT NMS", # Chassis A3 + VWCarInfo("Volkswagen Passat NMS 2017-22"), + specs=VolkswagenCarSpecs(mass=1503, wheelbase=2.80, minSteerSpeed=50*CV.KPH_TO_MS, minEnableSpeed=20*CV.KPH_TO_MS), + ) + POLO_MK6 = VolkswagenMQBPlatformConfig( + "VOLKSWAGEN POLO 6TH GEN", # Chassis AW + [ + VWCarInfo("Volkswagen Polo 2018-23", footnotes=[Footnote.VW_MQB_A0]), + VWCarInfo("Volkswagen Polo GTI 2018-23", footnotes=[Footnote.VW_MQB_A0]), + ], + specs=VolkswagenCarSpecs(mass=1230, wheelbase=2.55), + ) + SHARAN_MK2 = VolkswagenPQPlatformConfig( + "VOLKSWAGEN SHARAN 2ND GEN", # Chassis 7N + [ + VWCarInfo("Volkswagen Sharan 2018-22"), + VWCarInfo("SEAT Alhambra 2018-20"), + ], + specs=VolkswagenCarSpecs(mass=1639, wheelbase=2.92, minSteerSpeed=50*CV.KPH_TO_MS), + ) + TAOS_MK1 = VolkswagenMQBPlatformConfig( + "VOLKSWAGEN TAOS 1ST GEN", # Chassis B2 + VWCarInfo("Volkswagen Taos 2022-23"), + specs=VolkswagenCarSpecs(mass=1498, wheelbase=2.69), + ) + TCROSS_MK1 = VolkswagenMQBPlatformConfig( + "VOLKSWAGEN T-CROSS 1ST GEN", # Chassis C1 + car_info=VWCarInfo("Volkswagen T-Cross 2021", footnotes=[Footnote.VW_MQB_A0]), + specs=VolkswagenCarSpecs(mass=1150, wheelbase=2.60), + ) + TIGUAN_MK2 = VolkswagenMQBPlatformConfig( + "VOLKSWAGEN TIGUAN 2ND GEN", # Chassis AD/BW + [ + VWCarInfo("Volkswagen Tiguan 2018-24"), + VWCarInfo("Volkswagen Tiguan eHybrid 2021-23"), + ], + specs=VolkswagenCarSpecs(mass=1715, wheelbase=2.74), + ) + TOURAN_MK2 = VolkswagenMQBPlatformConfig( + "VOLKSWAGEN TOURAN 2ND GEN", # Chassis 1T + VWCarInfo("Volkswagen Touran 2016-23"), + specs=VolkswagenCarSpecs(mass=1516, wheelbase=2.79), + ) + TRANSPORTER_T61 = VolkswagenMQBPlatformConfig( + "VOLKSWAGEN TRANSPORTER T6.1", # Chassis 7H/7L + [ + VWCarInfo("Volkswagen Caravelle 2020"), + VWCarInfo("Volkswagen California 2021-23"), + ], + specs=VolkswagenCarSpecs(mass=1926, wheelbase=3.00, minSteerSpeed=14.0), + ) + TROC_MK1 = VolkswagenMQBPlatformConfig( + "VOLKSWAGEN T-ROC 1ST GEN", # Chassis A1 + VWCarInfo("Volkswagen T-Roc 2018-22", footnotes=[Footnote.VW_MQB_A0]), + specs=VolkswagenCarSpecs(mass=1413, wheelbase=2.63), + ) + AUDI_A3_MK3 = VolkswagenMQBPlatformConfig( + "AUDI A3 3RD GEN", # Chassis 8V/FF + [ + VWCarInfo("Audi A3 2014-19"), + VWCarInfo("Audi A3 Sportback e-tron 2017-18"), + VWCarInfo("Audi RS3 2018"), + VWCarInfo("Audi S3 2015-17"), + ], + specs=VolkswagenCarSpecs(mass=1335, wheelbase=2.61), + ) + AUDI_Q2_MK1 = VolkswagenMQBPlatformConfig( + "AUDI Q2 1ST GEN", # Chassis GA + VWCarInfo("Audi Q2 2018"), + specs=VolkswagenCarSpecs(mass=1205, wheelbase=2.61), + ) + AUDI_Q3_MK2 = VolkswagenMQBPlatformConfig( + "AUDI Q3 2ND GEN", # Chassis 8U/F3/FS + VWCarInfo("Audi Q3 2019-23"), + specs=VolkswagenCarSpecs(mass=1623, wheelbase=2.68), + ) + SEAT_ATECA_MK1 = VolkswagenMQBPlatformConfig( + "SEAT ATECA 1ST GEN", # Chassis 5F + VWCarInfo("SEAT Ateca 2018"), + specs=VolkswagenCarSpecs(mass=1900, wheelbase=2.64), + ) + SEAT_LEON_MK3 = VolkswagenMQBPlatformConfig( + "SEAT LEON 3RD GEN", # Chassis 5F + VWCarInfo("SEAT Leon 2014-20"), + specs=VolkswagenCarSpecs(mass=1227, wheelbase=2.64), + ) + SKODA_FABIA_MK4 = VolkswagenMQBPlatformConfig( + "SKODA FABIA 4TH GEN", # Chassis PJ + VWCarInfo("Å koda Fabia 2022-23", footnotes=[Footnote.VW_MQB_A0]), + specs=VolkswagenCarSpecs(mass=1266, wheelbase=2.56), + ) + SKODA_KAMIQ_MK1 = VolkswagenMQBPlatformConfig( + "SKODA KAMIQ 1ST GEN", # Chassis NW + VWCarInfo("Å koda Kamiq 2021-23", footnotes=[Footnote.VW_MQB_A0, Footnote.KAMIQ]), + specs=VolkswagenCarSpecs(mass=1265, wheelbase=2.66), + ) + SKODA_KAROQ_MK1 = VolkswagenMQBPlatformConfig( + "SKODA KAROQ 1ST GEN", # Chassis NU + VWCarInfo("Å koda Karoq 2019-23"), + specs=VolkswagenCarSpecs(mass=1278, wheelbase=2.66), + ) + SKODA_KODIAQ_MK1 = VolkswagenMQBPlatformConfig( + "SKODA KODIAQ 1ST GEN", # Chassis NS + VWCarInfo("Å koda Kodiaq 2017-23"), + specs=VolkswagenCarSpecs(mass=1569, wheelbase=2.79), + ) + SKODA_OCTAVIA_MK3 = VolkswagenMQBPlatformConfig( + "SKODA OCTAVIA 3RD GEN", # Chassis NE + [ + VWCarInfo("Å koda Octavia 2015-19"), + VWCarInfo("Å koda Octavia RS 2016"), + ], + specs=VolkswagenCarSpecs(mass=1388, wheelbase=2.68), + ) + SKODA_SCALA_MK1 = VolkswagenMQBPlatformConfig( + "SKODA SCALA 1ST GEN", # Chassis NW + VWCarInfo("Å koda Scala 2020-23", footnotes=[Footnote.VW_MQB_A0]), + specs=VolkswagenCarSpecs(mass=1192, wheelbase=2.65), + ) + SKODA_SUPERB_MK3 = VolkswagenMQBPlatformConfig( + "SKODA SUPERB 3RD GEN", # Chassis 3V/NP + VWCarInfo("Å koda Superb 2015-22"), + specs=VolkswagenCarSpecs(mass=1505, wheelbase=2.84), + ) +PQ_CARS = {CAR.PASSAT_NMS, CAR.SHARAN_MK2} # All supported cars should return FW from the engine, srs, eps, and fwdRadar. Cars # with a manual trans won't return transmission firmware, but all other cars will. @@ -313,3 +394,6 @@ def init_make(self, CP: car.CarParams): ), ]], ) + +CAR_INFO = CAR.create_carinfo_map() +DBC = CAR.create_dbc_map() From 5012e15aa65f4ee82ce19c856a52909b3a879016 Mon Sep 17 00:00:00 2001 From: Eric Brown Date: Sun, 25 Feb 2024 18:53:26 -0700 Subject: [PATCH 11/41] GM: move to platform config (#31553) * subaru platform config * forester wrong dbc * spacing * subaru car specs * someday! * more red diff * Move GM to platform config * Implement CarSpecs * Simplify centerToFront * Accidentally had subaru DBC * Fix typo in DBC name * done above * two spaces * that is moved up * fix hardcoded fingerprints * whitespace * values * better? * fix * bump * fix * fix --------- Co-authored-by: Justin Newberry --- selfdrive/car/__init__.py | 1 + selfdrive/car/gm/interface.py | 61 -------------- selfdrive/car/gm/values.py | 133 ++++++++++++++++++++---------- selfdrive/car/interfaces.py | 1 + selfdrive/car/subaru/interface.py | 3 - 5 files changed, 90 insertions(+), 109 deletions(-) diff --git a/selfdrive/car/__init__.py b/selfdrive/car/__init__.py index ca77dce1cfe74f..75b85cab2fb4ea 100644 --- a/selfdrive/car/__init__.py +++ b/selfdrive/car/__init__.py @@ -251,6 +251,7 @@ class CarSpecs: mass: float wheelbase: float steerRatio: float + centerToFrontRatio: float = field(default=0.5) minSteerSpeed: float = field(default=0.) minEnableSpeed: float = field(default=-1.) diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py index 05caa28510290c..e0dde4d0e9e332 100755 --- a/selfdrive/car/gm/interface.py +++ b/selfdrive/car/gm/interface.py @@ -152,11 +152,7 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): ret.longitudinalActuatorDelayUpperBound = 0.5 # large delay to initially start braking if candidate == CAR.VOLT: - ret.mass = 1607. - ret.wheelbase = 2.69 - ret.steerRatio = 17.7 # Stock 15.7, LiveParameters ret.tireStiffnessFactor = 0.469 # Stock Michelin Energy Saver A/S, LiveParameters - ret.centerToFront = ret.wheelbase * 0.45 # Volt Gen 1, TODO corner weigh ret.lateralTuning.pid.kpBP = [0., 40.] ret.lateralTuning.pid.kpV = [0., 0.17] @@ -165,61 +161,20 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): ret.lateralTuning.pid.kf = 1. # get_steer_feedforward_volt() ret.steerActuatorDelay = 0.2 - elif candidate == CAR.MALIBU: - ret.mass = 1496. - ret.wheelbase = 2.83 - ret.steerRatio = 15.8 - ret.centerToFront = ret.wheelbase * 0.4 # wild guess - - elif candidate == CAR.HOLDEN_ASTRA: - ret.mass = 1363. - ret.wheelbase = 2.662 - # Remaining parameters copied from Volt for now - ret.centerToFront = ret.wheelbase * 0.4 - ret.steerRatio = 15.7 - elif candidate == CAR.ACADIA: ret.minEnableSpeed = -1. # engage speed is decided by pcm - ret.mass = 4353. * CV.LB_TO_KG - ret.wheelbase = 2.86 - ret.steerRatio = 14.4 # end to end is 13.46 - ret.centerToFront = ret.wheelbase * 0.4 ret.steerActuatorDelay = 0.2 CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) elif candidate == CAR.BUICK_LACROSSE: - ret.mass = 1712. - ret.wheelbase = 2.91 - ret.steerRatio = 15.8 - ret.centerToFront = ret.wheelbase * 0.4 # wild guess CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) - elif candidate == CAR.BUICK_REGAL: - ret.mass = 3779. * CV.LB_TO_KG # (3849+3708)/2 - ret.wheelbase = 2.83 # 111.4 inches in meters - ret.steerRatio = 14.4 # guess for tourx - ret.centerToFront = ret.wheelbase * 0.4 # guess for tourx - - elif candidate == CAR.CADILLAC_ATS: - ret.mass = 1601. - ret.wheelbase = 2.78 - ret.steerRatio = 15.3 - ret.centerToFront = ret.wheelbase * 0.5 - elif candidate == CAR.ESCALADE: ret.minEnableSpeed = -1. # engage speed is decided by pcm - ret.mass = 5653. * CV.LB_TO_KG # (5552+5815)/2 - ret.wheelbase = 2.95 # 116 inches in meters - ret.steerRatio = 17.3 - ret.centerToFront = ret.wheelbase * 0.5 CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) elif candidate in (CAR.ESCALADE_ESV, CAR.ESCALADE_ESV_2019): ret.minEnableSpeed = -1. # engage speed is decided by pcm - ret.mass = 2739. - ret.wheelbase = 3.302 - ret.steerRatio = 17.3 - ret.centerToFront = ret.wheelbase * 0.5 ret.tireStiffnessFactor = 1.0 if candidate == CAR.ESCALADE_ESV: @@ -231,19 +186,11 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) elif candidate == CAR.BOLT_EUV: - ret.mass = 1669. - ret.wheelbase = 2.63779 - ret.steerRatio = 16.8 - ret.centerToFront = ret.wheelbase * 0.4 ret.tireStiffnessFactor = 1.0 ret.steerActuatorDelay = 0.2 CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) elif candidate == CAR.SILVERADO: - ret.mass = 2450. - ret.wheelbase = 3.75 - ret.steerRatio = 16.3 - ret.centerToFront = ret.wheelbase * 0.5 ret.tireStiffnessFactor = 1.0 # On the Bolt, the ECM and camera independently check that you are either above 5 kph or at a stop # with foot on brake to allow engagement, but this platform only has that check in the camera. @@ -253,17 +200,9 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) elif candidate == CAR.EQUINOX: - ret.mass = 3500. * CV.LB_TO_KG - ret.wheelbase = 2.72 - ret.steerRatio = 14.4 - ret.centerToFront = ret.wheelbase * 0.4 CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) elif candidate == CAR.TRAILBLAZER: - ret.mass = 1345. - ret.wheelbase = 2.64 - ret.steerRatio = 16.8 - ret.centerToFront = ret.wheelbase * 0.4 ret.tireStiffnessFactor = 1.0 ret.steerActuatorDelay = 0.2 CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) diff --git a/selfdrive/car/gm/values.py b/selfdrive/car/gm/values.py index 5c4d572fdb9233..53dbde87f44f86 100644 --- a/selfdrive/car/gm/values.py +++ b/selfdrive/car/gm/values.py @@ -1,9 +1,8 @@ -from collections import defaultdict -from dataclasses import dataclass -from enum import Enum, StrEnum +from dataclasses import dataclass, field +from enum import Enum from cereal import car -from openpilot.selfdrive.car import dbc_dict +from openpilot.selfdrive.car import dbc_dict, PlatformConfig, DbcDict, Platforms, CarSpecs from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarHarness, CarInfo, CarParts, Column from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries @@ -61,23 +60,6 @@ def __init__(self, CP): self.BRAKE_LOOKUP_V = [self.MAX_BRAKE, 0.] -class CAR(StrEnum): - HOLDEN_ASTRA = "HOLDEN ASTRA RS-V BK 2017" - VOLT = "CHEVROLET VOLT PREMIER 2017" - CADILLAC_ATS = "CADILLAC ATS Premium Performance 2018" - MALIBU = "CHEVROLET MALIBU PREMIER 2017" - ACADIA = "GMC ACADIA DENALI 2018" - BUICK_LACROSSE = "BUICK LACROSSE 2017" - BUICK_REGAL = "BUICK REGAL ESSENCE 2018" - ESCALADE = "CADILLAC ESCALADE 2017" - ESCALADE_ESV = "CADILLAC ESCALADE ESV 2016" - ESCALADE_ESV_2019 = "CADILLAC ESCALADE ESV 2019" - BOLT_EUV = "CHEVROLET BOLT EUV 2022" - SILVERADO = "CHEVROLET SILVERADO 1500 2020" - EQUINOX = "CHEVROLET EQUINOX 2019" - TRAILBLAZER = "CHEVROLET TRAILBLAZER 2021" - - class Footnote(Enum): OBD_II = CarFootnote( 'Requires a community built ASCM harness. ' + @@ -97,28 +79,88 @@ def init_make(self, CP: car.CarParams): self.footnotes.append(Footnote.OBD_II) -CAR_INFO: dict[str, GMCarInfo | list[GMCarInfo]] = { - CAR.HOLDEN_ASTRA: GMCarInfo("Holden Astra 2017"), - CAR.VOLT: GMCarInfo("Chevrolet Volt 2017-18", min_enable_speed=0, video_link="https://youtu.be/QeMCN_4TFfQ"), - CAR.CADILLAC_ATS: GMCarInfo("Cadillac ATS Premium Performance 2018"), - CAR.MALIBU: GMCarInfo("Chevrolet Malibu Premier 2017"), - CAR.ACADIA: GMCarInfo("GMC Acadia 2018", video_link="https://www.youtube.com/watch?v=0ZN6DdsBUZo"), - CAR.BUICK_LACROSSE: GMCarInfo("Buick LaCrosse 2017-19", "Driver Confidence Package 2"), - CAR.BUICK_REGAL: GMCarInfo("Buick Regal Essence 2018"), - CAR.ESCALADE: GMCarInfo("Cadillac Escalade 2017", "Driver Assist Package"), - CAR.ESCALADE_ESV: GMCarInfo("Cadillac Escalade ESV 2016", "Adaptive Cruise Control (ACC) & LKAS"), - CAR.ESCALADE_ESV_2019: GMCarInfo("Cadillac Escalade ESV 2019", "Adaptive Cruise Control (ACC) & LKAS"), - CAR.BOLT_EUV: [ - GMCarInfo("Chevrolet Bolt EUV 2022-23", "Premier or Premier Redline Trim without Super Cruise Package", video_link="https://youtu.be/xvwzGMUA210"), - GMCarInfo("Chevrolet Bolt EV 2022-23", "2LT Trim with Adaptive Cruise Control Package"), - ], - CAR.SILVERADO: [ - GMCarInfo("Chevrolet Silverado 1500 2020-21", "Safety Package II"), - GMCarInfo("GMC Sierra 1500 2020-21", "Driver Alert Package II", video_link="https://youtu.be/5HbNoBLzRwE"), - ], - CAR.EQUINOX: GMCarInfo("Chevrolet Equinox 2019-22"), - CAR.TRAILBLAZER: GMCarInfo("Chevrolet Trailblazer 2021-22"), -} +@dataclass +class GMPlatformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('gm_global_a_powertrain_generated', 'gm_global_a_object', chassis_dbc='gm_global_a_chassis')) + + +class CAR(Platforms): + HOLDEN_ASTRA = GMPlatformConfig( + "HOLDEN ASTRA RS-V BK 2017", + GMCarInfo("Holden Astra 2017"), + specs=CarSpecs(mass=1363, wheelbase=2.662, steerRatio=15.7, centerToFrontRatio=0.4), + ) + VOLT = GMPlatformConfig( + "CHEVROLET VOLT PREMIER 2017", + GMCarInfo("Chevrolet Volt 2017-18", min_enable_speed=0, video_link="https://youtu.be/QeMCN_4TFfQ"), + specs=CarSpecs(mass=1607, wheelbase=2.69, steerRatio=17.7, centerToFrontRatio=0.45), + ) + CADILLAC_ATS = GMPlatformConfig( + "CADILLAC ATS Premium Performance 2018", + GMCarInfo("Cadillac ATS Premium Performance 2018"), + specs=CarSpecs(mass=1601, wheelbase=2.78, steerRatio=15.3), + ) + MALIBU = GMPlatformConfig( + "CHEVROLET MALIBU PREMIER 2017", + GMCarInfo("Chevrolet Malibu Premier 2017"), + specs=CarSpecs(mass=1496, wheelbase=2.83, steerRatio=15.8, centerToFrontRatio=0.4), + ) + ACADIA = GMPlatformConfig( + "GMC ACADIA DENALI 2018", + GMCarInfo("GMC Acadia 2018", video_link="https://www.youtube.com/watch?v=0ZN6DdsBUZo"), + specs=CarSpecs(mass=1975, wheelbase=2.86, steerRatio=14.4, centerToFrontRatio=0.4), + ) + BUICK_LACROSSE = GMPlatformConfig( + "BUICK LACROSSE 2017", + GMCarInfo("Buick LaCrosse 2017-19", "Driver Confidence Package 2"), + specs=CarSpecs(mass=1712, wheelbase=2.91, steerRatio=15.8, centerToFrontRatio=0.4), + ) + BUICK_REGAL = GMPlatformConfig( + "BUICK REGAL ESSENCE 2018", + GMCarInfo("Buick Regal Essence 2018"), + specs=CarSpecs(mass=1714, wheelbase=2.83, steerRatio=14.4, centerToFrontRatio=0.4), + ) + ESCALADE = GMPlatformConfig( + "CADILLAC ESCALADE 2017", + GMCarInfo("Cadillac Escalade 2017", "Driver Assist Package"), + specs=CarSpecs(mass=2564, wheelbase=2.95, steerRatio=17.3), + ) + ESCALADE_ESV = GMPlatformConfig( + "CADILLAC ESCALADE ESV 2016", + GMCarInfo("Cadillac Escalade ESV 2016", "Adaptive Cruise Control (ACC) & LKAS"), + specs=CarSpecs(mass=2739, wheelbase=3.302, steerRatio=17.3), + ) + ESCALADE_ESV_2019 = GMPlatformConfig( + "CADILLAC ESCALADE ESV 2019", + GMCarInfo("Cadillac Escalade ESV 2019", "Adaptive Cruise Control (ACC) & LKAS"), + specs=ESCALADE_ESV.specs, + ) + BOLT_EUV = GMPlatformConfig( + "CHEVROLET BOLT EUV 2022", + [ + GMCarInfo("Chevrolet Bolt EUV 2022-23", "Premier or Premier Redline Trim without Super Cruise Package", video_link="https://youtu.be/xvwzGMUA210"), + GMCarInfo("Chevrolet Bolt EV 2022-23", "2LT Trim with Adaptive Cruise Control Package"), + ], + specs=CarSpecs(mass=1669, wheelbase=2.63779, steerRatio=16.8, centerToFrontRatio=0.4), + ) + SILVERADO = GMPlatformConfig( + "CHEVROLET SILVERADO 1500 2020", + [ + GMCarInfo("Chevrolet Silverado 1500 2020-21", "Safety Package II"), + GMCarInfo("GMC Sierra 1500 2020-21", "Driver Alert Package II", video_link="https://youtu.be/5HbNoBLzRwE"), + ], + specs=CarSpecs(mass=2450, wheelbase=3.75, steerRatio=16.3), + ) + EQUINOX = GMPlatformConfig( + "CHEVROLET EQUINOX 2019", + GMCarInfo("Chevrolet Equinox 2019-22"), + specs=CarSpecs(mass=1588, wheelbase=2.72, steerRatio=14.4, centerToFrontRatio=0.4), + ) + TRAILBLAZER = GMPlatformConfig( + "CHEVROLET TRAILBLAZER 2021", + GMCarInfo("Chevrolet Trailblazer 2021-22"), + specs=CarSpecs(mass=1345, wheelbase=2.64, steerRatio=16.8, centerToFrontRatio=0.4), + ) class CruiseButtons: @@ -180,11 +222,12 @@ class CanBus: extra_ecus=[(Ecu.fwdCamera, 0x24b, None)], ) -DBC: dict[str, dict[str, str]] = defaultdict(lambda: dbc_dict('gm_global_a_powertrain_generated', 'gm_global_a_object', chassis_dbc='gm_global_a_chassis')) - EV_CAR = {CAR.VOLT, CAR.BOLT_EUV} # We're integrated at the camera with VOACC on these cars (instead of ASCM w/ OBD-II harness) CAMERA_ACC_CAR = {CAR.BOLT_EUV, CAR.SILVERADO, CAR.EQUINOX, CAR.TRAILBLAZER} STEER_THRESHOLD = 1.0 + +CAR_INFO = CAR.create_carinfo_map() +DBC = CAR.create_dbc_map() diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index e0db1b56d8f78e..0a2d978004ddf6 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -118,6 +118,7 @@ def get_params(cls, candidate: Platform, fingerprint: dict[int, dict[int, int]], ret.mass = platform_config.specs.mass ret.wheelbase = platform_config.specs.wheelbase ret.steerRatio = platform_config.specs.steerRatio + ret.centerToFront = ret.wheelbase * platform_config.specs.centerToFrontRatio ret.minEnableSpeed = platform_config.specs.minEnableSpeed ret.minSteerSpeed = platform_config.specs.minSteerSpeed diff --git a/selfdrive/car/subaru/interface.py b/selfdrive/car/subaru/interface.py index 1358adb69cdfa5..2dfb4f9565c75e 100644 --- a/selfdrive/car/subaru/interface.py +++ b/selfdrive/car/subaru/interface.py @@ -41,9 +41,6 @@ def _get_params(ret, candidate: Platform, fingerprint, car_fw, experimental_long else: CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) - - ret.centerToFront = ret.wheelbase * 0.5 - if candidate in (CAR.ASCENT, CAR.ASCENT_2023): ret.steerActuatorDelay = 0.3 # end-to-end angle controller ret.lateralTuning.init('pid') From 8e03cdfc2ae72ea09208ce41ddc8f7a118c3b973 Mon Sep 17 00:00:00 2001 From: Cameron Clough Date: Mon, 26 Feb 2024 01:55:42 +0000 Subject: [PATCH 12/41] Ford: move to PlatformConfig (#31554) * Ford: move to PlatformConfig * Align Aviator model years with Explorer * Add CarSpecs to PlatformConfig --------- Co-authored-by: justin --- selfdrive/car/ford/interface.py | 47 +---------- selfdrive/car/ford/values.py | 141 +++++++++++++++++++------------- 2 files changed, 83 insertions(+), 105 deletions(-) diff --git a/selfdrive/car/ford/interface.py b/selfdrive/car/ford/interface.py index 685a2a27ad5c04..fd4c381f889995 100644 --- a/selfdrive/car/ford/interface.py +++ b/selfdrive/car/ford/interface.py @@ -3,7 +3,7 @@ from openpilot.common.conversions import Conversions as CV from openpilot.selfdrive.car import get_safety_config from openpilot.selfdrive.car.ford.fordcan import CanBus -from openpilot.selfdrive.car.ford.values import CANFD_CAR, CAR, Ecu +from openpilot.selfdrive.car.ford.values import CANFD_CAR, Ecu from openpilot.selfdrive.car.interfaces import CarInterfaceBase TransmissionType = car.CarParams.TransmissionType @@ -39,51 +39,6 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): if candidate in CANFD_CAR: ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_FORD_CANFD - if candidate == CAR.BRONCO_SPORT_MK1: - ret.wheelbase = 2.67 - ret.steerRatio = 17.7 - ret.mass = 1625 - - elif candidate == CAR.ESCAPE_MK4: - ret.wheelbase = 2.71 - ret.steerRatio = 16.7 - ret.mass = 1750 - - elif candidate == CAR.EXPLORER_MK6: - ret.wheelbase = 3.025 - ret.steerRatio = 16.8 - ret.mass = 2050 - - elif candidate == CAR.F_150_MK14: - # required trim only on SuperCrew - ret.wheelbase = 3.69 - ret.steerRatio = 17.0 - ret.mass = 2000 - - elif candidate == CAR.F_150_LIGHTNING_MK1: - # required trim only on SuperCrew - ret.wheelbase = 3.70 - ret.steerRatio = 16.9 - ret.mass = 2948 - - elif candidate == CAR.MUSTANG_MACH_E_MK1: - ret.wheelbase = 2.984 - ret.steerRatio = 17.0 # guess - ret.mass = 2200 - - elif candidate == CAR.FOCUS_MK4: - ret.wheelbase = 2.7 - ret.steerRatio = 15.0 - ret.mass = 1350 - - elif candidate == CAR.MAVERICK_MK1: - ret.wheelbase = 3.076 - ret.steerRatio = 17.0 - ret.mass = 1650 - - else: - raise ValueError(f"Unsupported car: {candidate}") - # Auto Transmission: 0x732 ECU or Gear_Shift_by_Wire_FD1 found_ecus = [fw.ecu for fw in car_fw] if Ecu.shiftByWire in found_ecus or 0x5A in fingerprint[CAN.main] or docs: diff --git a/selfdrive/car/ford/values.py b/selfdrive/car/ford/values.py index 3ad39d715ffc8d..ef99cf5f340f1e 100644 --- a/selfdrive/car/ford/values.py +++ b/selfdrive/car/ford/values.py @@ -1,9 +1,8 @@ -from collections import defaultdict -from dataclasses import dataclass -from enum import Enum, StrEnum +from dataclasses import dataclass, field +from enum import Enum from cereal import car -from openpilot.selfdrive.car import AngleRateLimit, dbc_dict +from openpilot.selfdrive.car import AngleRateLimit, CarSpecs, dbc_dict, DbcDict, PlatformConfig, Platforms from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarHarness, CarInfo, CarParts, Column, \ Device from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries @@ -39,33 +38,11 @@ def __init__(self, CP): pass -class CAR(StrEnum): - BRONCO_SPORT_MK1 = "FORD BRONCO SPORT 1ST GEN" - ESCAPE_MK4 = "FORD ESCAPE 4TH GEN" - EXPLORER_MK6 = "FORD EXPLORER 6TH GEN" - F_150_MK14 = "FORD F-150 14TH GEN" - FOCUS_MK4 = "FORD FOCUS 4TH GEN" - MAVERICK_MK1 = "FORD MAVERICK 1ST GEN" - F_150_LIGHTNING_MK1 = "FORD F-150 LIGHTNING 1ST GEN" - MUSTANG_MACH_E_MK1 = "FORD MUSTANG MACH-E 1ST GEN" - - -CANFD_CAR = {CAR.F_150_MK14, CAR.F_150_LIGHTNING_MK1, CAR.MUSTANG_MACH_E_MK1} - - class RADAR: DELPHI_ESR = 'ford_fusion_2018_adas' DELPHI_MRR = 'FORD_CADS' -DBC: dict[str, dict[str, str]] = defaultdict(lambda: dbc_dict("ford_lincoln_base_pt", RADAR.DELPHI_MRR)) - -# F-150 radar is not yet supported -DBC[CAR.F_150_MK14] = dbc_dict("ford_lincoln_base_pt", None) -DBC[CAR.F_150_LIGHTNING_MK1] = dbc_dict("ford_lincoln_base_pt", None) -DBC[CAR.MUSTANG_MACH_E_MK1] = dbc_dict("ford_lincoln_base_pt", None) - - class Footnote(Enum): FOCUS = CarFootnote( "Refers only to the Focus Mk4 (C519) available in Europe/China/Taiwan/Australasia, not the Focus Mk3 (C346) in " + @@ -86,39 +63,82 @@ def init_make(self, CP: car.CarParams): self.car_parts = CarParts([Device.threex, harness]) -CAR_INFO: dict[str, CarInfo | list[CarInfo]] = { - CAR.BRONCO_SPORT_MK1: FordCarInfo("Ford Bronco Sport 2021-22"), - CAR.ESCAPE_MK4: [ - FordCarInfo("Ford Escape 2020-22"), - FordCarInfo("Ford Escape Hybrid 2020-22"), - FordCarInfo("Ford Escape Plug-in Hybrid 2020-22"), - FordCarInfo("Ford Kuga 2020-22", "Adaptive Cruise Control with Lane Centering"), - FordCarInfo("Ford Kuga Hybrid 2020-22", "Adaptive Cruise Control with Lane Centering"), - FordCarInfo("Ford Kuga Plug-in Hybrid 2020-22", "Adaptive Cruise Control with Lane Centering"), - ], - CAR.EXPLORER_MK6: [ - FordCarInfo("Ford Explorer 2020-23"), - FordCarInfo("Ford Explorer Hybrid 2020-23"), # Limited and Platinum only - FordCarInfo("Lincoln Aviator 2020-23", "Co-Pilot360 Plus"), - FordCarInfo("Lincoln Aviator Plug-in Hybrid 2020-23", "Co-Pilot360 Plus"), # Grand Touring only - ], - CAR.F_150_MK14: [ - FordCarInfo("Ford F-150 2023", "Co-Pilot360 Active 2.0"), - FordCarInfo("Ford F-150 Hybrid 2023", "Co-Pilot360 Active 2.0"), - ], - CAR.F_150_LIGHTNING_MK1: FordCarInfo("Ford F-150 Lightning 2021-23", "Co-Pilot360 Active 2.0"), - CAR.MUSTANG_MACH_E_MK1: FordCarInfo("Ford Mustang Mach-E 2021-23", "Co-Pilot360 Active 2.0"), - CAR.FOCUS_MK4: [ - FordCarInfo("Ford Focus 2018", "Adaptive Cruise Control with Lane Centering", footnotes=[Footnote.FOCUS]), - FordCarInfo("Ford Focus Hybrid 2018", "Adaptive Cruise Control with Lane Centering", footnotes=[Footnote.FOCUS]), # mHEV only - ], - CAR.MAVERICK_MK1: [ - FordCarInfo("Ford Maverick 2022", "LARIAT Luxury"), - FordCarInfo("Ford Maverick Hybrid 2022", "LARIAT Luxury"), - FordCarInfo("Ford Maverick 2023", "Co-Pilot360 Assist"), - FordCarInfo("Ford Maverick Hybrid 2023", "Co-Pilot360 Assist"), - ], -} +@dataclass +class FordPlatformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('ford_lincoln_base_pt', RADAR.DELPHI_MRR)) + + +class CAR(Platforms): + BRONCO_SPORT_MK1 = FordPlatformConfig( + "FORD BRONCO SPORT 1ST GEN", + FordCarInfo("Ford Bronco Sport 2021-22"), + specs=CarSpecs(mass=1625, wheelbase=2.67, steerRatio=17.7), + ) + ESCAPE_MK4 = FordPlatformConfig( + "FORD ESCAPE 4TH GEN", + [ + FordCarInfo("Ford Escape 2020-22"), + FordCarInfo("Ford Escape Hybrid 2020-22"), + FordCarInfo("Ford Escape Plug-in Hybrid 2020-22"), + FordCarInfo("Ford Kuga 2020-22", "Adaptive Cruise Control with Lane Centering"), + FordCarInfo("Ford Kuga Hybrid 2020-22", "Adaptive Cruise Control with Lane Centering"), + FordCarInfo("Ford Kuga Plug-in Hybrid 2020-22", "Adaptive Cruise Control with Lane Centering"), + ], + specs=CarSpecs(mass=1750, wheelbase=2.71, steerRatio=16.7), + ) + EXPLORER_MK6 = FordPlatformConfig( + "FORD EXPLORER 6TH GEN", + [ + FordCarInfo("Ford Explorer 2020-23"), + FordCarInfo("Ford Explorer Hybrid 2020-23"), # Limited and Platinum only + FordCarInfo("Lincoln Aviator 2020-23", "Co-Pilot360 Plus"), + FordCarInfo("Lincoln Aviator Plug-in Hybrid 2020-23", "Co-Pilot360 Plus"), # Grand Touring only + ], + specs=CarSpecs(mass=2050, wheelbase=3.025, steerRatio=16.8), + ) + F_150_MK14 = FordPlatformConfig( + "FORD F-150 14TH GEN", + [ + FordCarInfo("Ford F-150 2023", "Co-Pilot360 Active 2.0"), + FordCarInfo("Ford F-150 Hybrid 2023", "Co-Pilot360 Active 2.0"), + ], + dbc_dict=dbc_dict('ford_lincoln_base_pt', None), + specs=CarSpecs(mass=2000, wheelbase=3.69, steerRatio=17.0), + ) + F_150_LIGHTNING_MK1 = FordPlatformConfig( + "FORD F-150 LIGHTNING 1ST GEN", + FordCarInfo("Ford F-150 Lightning 2021-23", "Co-Pilot360 Active 2.0"), + dbc_dict=dbc_dict('ford_lincoln_base_pt', None), + specs=CarSpecs(mass=2948, wheelbase=3.70, steerRatio=16.9), + ) + FOCUS_MK4 = FordPlatformConfig( + "FORD FOCUS 4TH GEN", + [ + FordCarInfo("Ford Focus 2018", "Adaptive Cruise Control with Lane Centering", footnotes=[Footnote.FOCUS]), + FordCarInfo("Ford Focus Hybrid 2018", "Adaptive Cruise Control with Lane Centering", footnotes=[Footnote.FOCUS]), # mHEV only + ], + specs=CarSpecs(mass=1350, wheelbase=2.7, steerRatio=15.0), + ) + MAVERICK_MK1 = FordPlatformConfig( + "FORD MAVERICK 1ST GEN", + [ + FordCarInfo("Ford Maverick 2022", "LARIAT Luxury"), + FordCarInfo("Ford Maverick Hybrid 2022", "LARIAT Luxury"), + FordCarInfo("Ford Maverick 2023", "Co-Pilot360 Assist"), + FordCarInfo("Ford Maverick Hybrid 2023", "Co-Pilot360 Assist"), + ], + specs=CarSpecs(mass=1650, wheelbase=3.076, steerRatio=17.0), + ) + MUSTANG_MACH_E_MK1 = FordPlatformConfig( + "FORD MUSTANG MACH-E 1ST GEN", + FordCarInfo("Ford Mustang Mach-E 2021-23", "Co-Pilot360 Active 2.0"), + dbc_dict=dbc_dict('ford_lincoln_base_pt', None), + specs=CarSpecs(mass=2200, wheelbase=2.984, steerRatio=17.0), # TODO: check steer ratio + ) + + +CANFD_CAR = {CAR.F_150_MK14, CAR.F_150_LIGHTNING_MK1, CAR.MUSTANG_MACH_E_MK1} + FW_QUERY_CONFIG = FwQueryConfig( requests=[ @@ -142,3 +162,6 @@ def init_make(self, CP: car.CarParams): (Ecu.shiftByWire, 0x732, None), ], ) + +CAR_INFO = CAR.create_carinfo_map() +DBC = CAR.create_dbc_map() From a1fefabbca852923dee83b5ee58c748ce861cdad Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Mon, 26 Feb 2024 09:08:24 -0800 Subject: [PATCH 13/41] [bot] Update Python packages and pre-commit hooks (#31595) Update Python packages and pre-commit hooks Co-authored-by: jnewb1 --- .pre-commit-config.yaml | 2 +- poetry.lock | 351 ++++++++++++++++++++-------------------- 2 files changed, 177 insertions(+), 176 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 09fded7f773b45..6db68e55bc125b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -91,7 +91,7 @@ repos: pass_filenames: false files: 'selfdrive/ui/translations/*' - repo: https://github.com/python-poetry/poetry - rev: '1.7.0' + rev: '1.8.0' hooks: - id: poetry-check name: validate poetry lock diff --git a/poetry.lock b/poetry.lock index 9972cd77322f63..588186d1384d8f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -751,63 +751,63 @@ test = ["pytest", "pytest-timeout"] [[package]] name = "coverage" -version = "7.4.1" +version = "7.4.3" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:077d366e724f24fc02dbfe9d946534357fda71af9764ff99d73c3c596001bbd7"}, - {file = "coverage-7.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0193657651f5399d433c92f8ae264aff31fc1d066deee4b831549526433f3f61"}, - {file = "coverage-7.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d17bbc946f52ca67adf72a5ee783cd7cd3477f8f8796f59b4974a9b59cacc9ee"}, - {file = "coverage-7.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3277f5fa7483c927fe3a7b017b39351610265308f5267ac6d4c2b64cc1d8d25"}, - {file = "coverage-7.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dceb61d40cbfcf45f51e59933c784a50846dc03211054bd76b421a713dcdf19"}, - {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6008adeca04a445ea6ef31b2cbaf1d01d02986047606f7da266629afee982630"}, - {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c61f66d93d712f6e03369b6a7769233bfda880b12f417eefdd4f16d1deb2fc4c"}, - {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b9bb62fac84d5f2ff523304e59e5c439955fb3b7f44e3d7b2085184db74d733b"}, - {file = "coverage-7.4.1-cp310-cp310-win32.whl", hash = "sha256:f86f368e1c7ce897bf2457b9eb61169a44e2ef797099fb5728482b8d69f3f016"}, - {file = "coverage-7.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:869b5046d41abfea3e381dd143407b0d29b8282a904a19cb908fa24d090cc018"}, - {file = "coverage-7.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b8ffb498a83d7e0305968289441914154fb0ef5d8b3157df02a90c6695978295"}, - {file = "coverage-7.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3cacfaefe6089d477264001f90f55b7881ba615953414999c46cc9713ff93c8c"}, - {file = "coverage-7.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d6850e6e36e332d5511a48a251790ddc545e16e8beaf046c03985c69ccb2676"}, - {file = "coverage-7.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18e961aa13b6d47f758cc5879383d27b5b3f3dcd9ce8cdbfdc2571fe86feb4dd"}, - {file = "coverage-7.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfd1e1b9f0898817babf840b77ce9fe655ecbe8b1b327983df485b30df8cc011"}, - {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6b00e21f86598b6330f0019b40fb397e705135040dbedc2ca9a93c7441178e74"}, - {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:536d609c6963c50055bab766d9951b6c394759190d03311f3e9fcf194ca909e1"}, - {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7ac8f8eb153724f84885a1374999b7e45734bf93a87d8df1e7ce2146860edef6"}, - {file = "coverage-7.4.1-cp311-cp311-win32.whl", hash = "sha256:f3771b23bb3675a06f5d885c3630b1d01ea6cac9e84a01aaf5508706dba546c5"}, - {file = "coverage-7.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:9d2f9d4cc2a53b38cabc2d6d80f7f9b7e3da26b2f53d48f05876fef7956b6968"}, - {file = "coverage-7.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f68ef3660677e6624c8cace943e4765545f8191313a07288a53d3da188bd8581"}, - {file = "coverage-7.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:23b27b8a698e749b61809fb637eb98ebf0e505710ec46a8aa6f1be7dc0dc43a6"}, - {file = "coverage-7.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e3424c554391dc9ef4a92ad28665756566a28fecf47308f91841f6c49288e66"}, - {file = "coverage-7.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0860a348bf7004c812c8368d1fc7f77fe8e4c095d661a579196a9533778e156"}, - {file = "coverage-7.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe558371c1bdf3b8fa03e097c523fb9645b8730399c14fe7721ee9c9e2a545d3"}, - {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3468cc8720402af37b6c6e7e2a9cdb9f6c16c728638a2ebc768ba1ef6f26c3a1"}, - {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:02f2edb575d62172aa28fe00efe821ae31f25dc3d589055b3fb64d51e52e4ab1"}, - {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ca6e61dc52f601d1d224526360cdeab0d0712ec104a2ce6cc5ccef6ed9a233bc"}, - {file = "coverage-7.4.1-cp312-cp312-win32.whl", hash = "sha256:ca7b26a5e456a843b9b6683eada193fc1f65c761b3a473941efe5a291f604c74"}, - {file = "coverage-7.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:85ccc5fa54c2ed64bd91ed3b4a627b9cce04646a659512a051fa82a92c04a448"}, - {file = "coverage-7.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8bdb0285a0202888d19ec6b6d23d5990410decb932b709f2b0dfe216d031d218"}, - {file = "coverage-7.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:918440dea04521f499721c039863ef95433314b1db00ff826a02580c1f503e45"}, - {file = "coverage-7.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:379d4c7abad5afbe9d88cc31ea8ca262296480a86af945b08214eb1a556a3e4d"}, - {file = "coverage-7.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b094116f0b6155e36a304ff912f89bbb5067157aff5f94060ff20bbabdc8da06"}, - {file = "coverage-7.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2f5968608b1fe2a1d00d01ad1017ee27efd99b3437e08b83ded9b7af3f6f766"}, - {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:10e88e7f41e6197ea0429ae18f21ff521d4f4490aa33048f6c6f94c6045a6a75"}, - {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a4a3907011d39dbc3e37bdc5df0a8c93853c369039b59efa33a7b6669de04c60"}, - {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6d224f0c4c9c98290a6990259073f496fcec1b5cc613eecbd22786d398ded3ad"}, - {file = "coverage-7.4.1-cp38-cp38-win32.whl", hash = "sha256:23f5881362dcb0e1a92b84b3c2809bdc90db892332daab81ad8f642d8ed55042"}, - {file = "coverage-7.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:a07f61fc452c43cd5328b392e52555f7d1952400a1ad09086c4a8addccbd138d"}, - {file = "coverage-7.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8e738a492b6221f8dcf281b67129510835461132b03024830ac0e554311a5c54"}, - {file = "coverage-7.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46342fed0fff72efcda77040b14728049200cbba1279e0bf1188f1f2078c1d70"}, - {file = "coverage-7.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9641e21670c68c7e57d2053ddf6c443e4f0a6e18e547e86af3fad0795414a628"}, - {file = "coverage-7.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aeb2c2688ed93b027eb0d26aa188ada34acb22dceea256d76390eea135083950"}, - {file = "coverage-7.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d12c923757de24e4e2110cf8832d83a886a4cf215c6e61ed506006872b43a6d1"}, - {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0491275c3b9971cdbd28a4595c2cb5838f08036bca31765bad5e17edf900b2c7"}, - {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8dfc5e195bbef80aabd81596ef52a1277ee7143fe419efc3c4d8ba2754671756"}, - {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1a78b656a4d12b0490ca72651fe4d9f5e07e3c6461063a9b6265ee45eb2bdd35"}, - {file = "coverage-7.4.1-cp39-cp39-win32.whl", hash = "sha256:f90515974b39f4dea2f27c0959688621b46d96d5a626cf9c53dbc653a895c05c"}, - {file = "coverage-7.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:64e723ca82a84053dd7bfcc986bdb34af8d9da83c521c19d6b472bc6880e191a"}, - {file = "coverage-7.4.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:32a8d985462e37cfdab611a6f95b09d7c091d07668fdc26e47a725ee575fe166"}, - {file = "coverage-7.4.1.tar.gz", hash = "sha256:1ed4b95480952b1a26d863e546fa5094564aa0065e1e5f0d4d0041f293251d04"}, + {file = "coverage-7.4.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8580b827d4746d47294c0e0b92854c85a92c2227927433998f0d3320ae8a71b6"}, + {file = "coverage-7.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:718187eeb9849fc6cc23e0d9b092bc2348821c5e1a901c9f8975df0bc785bfd4"}, + {file = "coverage-7.4.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:767b35c3a246bcb55b8044fd3a43b8cd553dd1f9f2c1eeb87a302b1f8daa0524"}, + {file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae7f19afe0cce50039e2c782bff379c7e347cba335429678450b8fe81c4ef96d"}, + {file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba3a8aaed13770e970b3df46980cb068d1c24af1a1968b7818b69af8c4347efb"}, + {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ee866acc0861caebb4f2ab79f0b94dbfbdbfadc19f82e6e9c93930f74e11d7a0"}, + {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:506edb1dd49e13a2d4cac6a5173317b82a23c9d6e8df63efb4f0380de0fbccbc"}, + {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd6545d97c98a192c5ac995d21c894b581f1fd14cf389be90724d21808b657e2"}, + {file = "coverage-7.4.3-cp310-cp310-win32.whl", hash = "sha256:f6a09b360d67e589236a44f0c39218a8efba2593b6abdccc300a8862cffc2f94"}, + {file = "coverage-7.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:18d90523ce7553dd0b7e23cbb28865db23cddfd683a38fb224115f7826de78d0"}, + {file = "coverage-7.4.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cbbe5e739d45a52f3200a771c6d2c7acf89eb2524890a4a3aa1a7fa0695d2a47"}, + {file = "coverage-7.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:489763b2d037b164846ebac0cbd368b8a4ca56385c4090807ff9fad817de4113"}, + {file = "coverage-7.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:451f433ad901b3bb00184d83fd83d135fb682d780b38af7944c9faeecb1e0bfe"}, + {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fcc66e222cf4c719fe7722a403888b1f5e1682d1679bd780e2b26c18bb648cdc"}, + {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3ec74cfef2d985e145baae90d9b1b32f85e1741b04cd967aaf9cfa84c1334f3"}, + {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:abbbd8093c5229c72d4c2926afaee0e6e3140de69d5dcd918b2921f2f0c8baba"}, + {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:35eb581efdacf7b7422af677b92170da4ef34500467381e805944a3201df2079"}, + {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8249b1c7334be8f8c3abcaaa996e1e4927b0e5a23b65f5bf6cfe3180d8ca7840"}, + {file = "coverage-7.4.3-cp311-cp311-win32.whl", hash = "sha256:cf30900aa1ba595312ae41978b95e256e419d8a823af79ce670835409fc02ad3"}, + {file = "coverage-7.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:18c7320695c949de11a351742ee001849912fd57e62a706d83dfc1581897fa2e"}, + {file = "coverage-7.4.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b51bfc348925e92a9bd9b2e48dad13431b57011fd1038f08316e6bf1df107d10"}, + {file = "coverage-7.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d6cdecaedea1ea9e033d8adf6a0ab11107b49571bbb9737175444cea6eb72328"}, + {file = "coverage-7.4.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b2eccb883368f9e972e216c7b4c7c06cabda925b5f06dde0650281cb7666a30"}, + {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c00cdc8fa4e50e1cc1f941a7f2e3e0f26cb2a1233c9696f26963ff58445bac7"}, + {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9a4a8dd3dcf4cbd3165737358e4d7dfbd9d59902ad11e3b15eebb6393b0446e"}, + {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:062b0a75d9261e2f9c6d071753f7eef0fc9caf3a2c82d36d76667ba7b6470003"}, + {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ebe7c9e67a2d15fa97b77ea6571ce5e1e1f6b0db71d1d5e96f8d2bf134303c1d"}, + {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c0a120238dd71c68484f02562f6d446d736adcc6ca0993712289b102705a9a3a"}, + {file = "coverage-7.4.3-cp312-cp312-win32.whl", hash = "sha256:37389611ba54fd6d278fde86eb2c013c8e50232e38f5c68235d09d0a3f8aa352"}, + {file = "coverage-7.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:d25b937a5d9ffa857d41be042b4238dd61db888533b53bc76dc082cb5a15e914"}, + {file = "coverage-7.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:28ca2098939eabab044ad68850aac8f8db6bf0b29bc7f2887d05889b17346454"}, + {file = "coverage-7.4.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:280459f0a03cecbe8800786cdc23067a8fc64c0bd51dc614008d9c36e1659d7e"}, + {file = "coverage-7.4.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c0cdedd3500e0511eac1517bf560149764b7d8e65cb800d8bf1c63ebf39edd2"}, + {file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a9babb9466fe1da12417a4aed923e90124a534736de6201794a3aea9d98484e"}, + {file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dec9de46a33cf2dd87a5254af095a409ea3bf952d85ad339751e7de6d962cde6"}, + {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:16bae383a9cc5abab9bb05c10a3e5a52e0a788325dc9ba8499e821885928968c"}, + {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2c854ce44e1ee31bda4e318af1dbcfc929026d12c5ed030095ad98197eeeaed0"}, + {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ce8c50520f57ec57aa21a63ea4f325c7b657386b3f02ccaedeccf9ebe27686e1"}, + {file = "coverage-7.4.3-cp38-cp38-win32.whl", hash = "sha256:708a3369dcf055c00ddeeaa2b20f0dd1ce664eeabde6623e516c5228b753654f"}, + {file = "coverage-7.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:1bf25fbca0c8d121a3e92a2a0555c7e5bc981aee5c3fdaf4bb7809f410f696b9"}, + {file = "coverage-7.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3b253094dbe1b431d3a4ac2f053b6d7ede2664ac559705a704f621742e034f1f"}, + {file = "coverage-7.4.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77fbfc5720cceac9c200054b9fab50cb2a7d79660609200ab83f5db96162d20c"}, + {file = "coverage-7.4.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6679060424faa9c11808598504c3ab472de4531c571ab2befa32f4971835788e"}, + {file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4af154d617c875b52651dd8dd17a31270c495082f3d55f6128e7629658d63765"}, + {file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8640f1fde5e1b8e3439fe482cdc2b0bb6c329f4bb161927c28d2e8879c6029ee"}, + {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:69b9f6f66c0af29642e73a520b6fed25ff9fd69a25975ebe6acb297234eda501"}, + {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0842571634f39016a6c03e9d4aba502be652a6e4455fadb73cd3a3a49173e38f"}, + {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a78ed23b08e8ab524551f52953a8a05d61c3a760781762aac49f8de6eede8c45"}, + {file = "coverage-7.4.3-cp39-cp39-win32.whl", hash = "sha256:c0524de3ff096e15fcbfe8f056fdb4ea0bf497d584454f344d59fce069d3e6e9"}, + {file = "coverage-7.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:0209a6369ccce576b43bb227dc8322d8ef9e323d089c6f3f26a597b09cb4d2aa"}, + {file = "coverage-7.4.3-pp38.pp39.pp310-none-any.whl", hash = "sha256:7cbde573904625509a3f37b6fecea974e363460b556a627c60dc2f47e2fffa51"}, + {file = "coverage-7.4.3.tar.gz", hash = "sha256:276f6077a5c61447a48d133ed13e759c09e62aff0dc84274a68dc18660104d52"}, ] [package.extras] @@ -825,43 +825,43 @@ files = [ [[package]] name = "cryptography" -version = "42.0.3" +version = "42.0.5" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-42.0.3-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:de5086cd475d67113ccb6f9fae6d8fe3ac54a4f9238fd08bfdb07b03d791ff0a"}, - {file = "cryptography-42.0.3-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:935cca25d35dda9e7bd46a24831dfd255307c55a07ff38fd1a92119cffc34857"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20100c22b298c9eaebe4f0b9032ea97186ac2555f426c3e70670f2517989543b"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2eb6368d5327d6455f20327fb6159b97538820355ec00f8cc9464d617caecead"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:39d5c93e95bcbc4c06313fc6a500cee414ee39b616b55320c1904760ad686938"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3d96ea47ce6d0055d5b97e761d37b4e84195485cb5a38401be341fabf23bc32a"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:d1998e545081da0ab276bcb4b33cce85f775adb86a516e8f55b3dac87f469548"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93fbee08c48e63d5d1b39ab56fd3fdd02e6c2431c3da0f4edaf54954744c718f"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:90147dad8c22d64b2ff7331f8d4cddfdc3ee93e4879796f837bdbb2a0b141e0c"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4dcab7c25e48fc09a73c3e463d09ac902a932a0f8d0c568238b3696d06bf377b"}, - {file = "cryptography-42.0.3-cp37-abi3-win32.whl", hash = "sha256:1e935c2900fb53d31f491c0de04f41110351377be19d83d908c1fd502ae8daa5"}, - {file = "cryptography-42.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:762f3771ae40e111d78d77cbe9c1035e886ac04a234d3ee0856bf4ecb3749d54"}, - {file = "cryptography-42.0.3-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:0d3ec384058b642f7fb7e7bff9664030011ed1af8f852540c76a1317a9dd0d20"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35772a6cffd1f59b85cb670f12faba05513446f80352fe811689b4e439b5d89e"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04859aa7f12c2b5f7e22d25198ddd537391f1695df7057c8700f71f26f47a129"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c3d1f5a1d403a8e640fa0887e9f7087331abb3f33b0f2207d2cc7f213e4a864c"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:df34312149b495d9d03492ce97471234fd9037aa5ba217c2a6ea890e9166f151"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:de4ae486041878dc46e571a4c70ba337ed5233a1344c14a0790c4c4be4bbb8b4"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:0fab2a5c479b360e5e0ea9f654bcebb535e3aa1e493a715b13244f4e07ea8eec"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25b09b73db78facdfd7dd0fa77a3f19e94896197c86e9f6dc16bce7b37a96504"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d5cf11bc7f0b71fb71af26af396c83dfd3f6eed56d4b6ef95d57867bf1e4ba65"}, - {file = "cryptography-42.0.3-cp39-abi3-win32.whl", hash = "sha256:0fea01527d4fb22ffe38cd98951c9044400f6eff4788cf52ae116e27d30a1ba3"}, - {file = "cryptography-42.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:2619487f37da18d6826e27854a7f9d4d013c51eafb066c80d09c63cf24505306"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ead69ba488f806fe1b1b4050febafdbf206b81fa476126f3e16110c818bac396"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:20180da1b508f4aefc101cebc14c57043a02b355d1a652b6e8e537967f1e1b46"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5fbf0f3f0fac7c089308bd771d2c6c7b7d53ae909dce1db52d8e921f6c19bb3a"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c23f03cfd7d9826cdcbad7850de67e18b4654179e01fe9bc623d37c2638eb4ef"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:db0480ffbfb1193ac4e1e88239f31314fe4c6cdcf9c0b8712b55414afbf80db4"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:6c25e1e9c2ce682d01fc5e2dde6598f7313027343bd14f4049b82ad0402e52cd"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9541c69c62d7446539f2c1c06d7046aef822940d248fa4b8962ff0302862cc1f"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1b797099d221df7cce5ff2a1d272761d1554ddf9a987d3e11f6459b38cd300fd"}, - {file = "cryptography-42.0.3.tar.gz", hash = "sha256:069d2ce9be5526a44093a0991c450fe9906cdf069e0e7cd67d9dee49a62b9ebe"}, + {file = "cryptography-42.0.5-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a30596bae9403a342c978fb47d9b0ee277699fa53bbafad14706af51fe543d16"}, + {file = "cryptography-42.0.5-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:b7ffe927ee6531c78f81aa17e684e2ff617daeba7f189f911065b2ea2d526dec"}, + {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2424ff4c4ac7f6b8177b53c17ed5d8fa74ae5955656867f5a8affaca36a27abb"}, + {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:329906dcc7b20ff3cad13c069a78124ed8247adcac44b10bea1130e36caae0b4"}, + {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:b03c2ae5d2f0fc05f9a2c0c997e1bc18c8229f392234e8a0194f202169ccd278"}, + {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f8837fe1d6ac4a8052a9a8ddab256bc006242696f03368a4009be7ee3075cdb7"}, + {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:0270572b8bd2c833c3981724b8ee9747b3ec96f699a9665470018594301439ee"}, + {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:b8cac287fafc4ad485b8a9b67d0ee80c66bf3574f655d3b97ef2e1082360faf1"}, + {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:16a48c23a62a2f4a285699dba2e4ff2d1cff3115b9df052cdd976a18856d8e3d"}, + {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2bce03af1ce5a5567ab89bd90d11e7bbdff56b8af3acbbec1faded8f44cb06da"}, + {file = "cryptography-42.0.5-cp37-abi3-win32.whl", hash = "sha256:b6cd2203306b63e41acdf39aa93b86fb566049aeb6dc489b70e34bcd07adca74"}, + {file = "cryptography-42.0.5-cp37-abi3-win_amd64.whl", hash = "sha256:98d8dc6d012b82287f2c3d26ce1d2dd130ec200c8679b6213b3c73c08b2b7940"}, + {file = "cryptography-42.0.5-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:5e6275c09d2badf57aea3afa80d975444f4be8d3bc58f7f80d2a484c6f9485c8"}, + {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4985a790f921508f36f81831817cbc03b102d643b5fcb81cd33df3fa291a1a1"}, + {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cde5f38e614f55e28d831754e8a3bacf9ace5d1566235e39d91b35502d6936e"}, + {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7367d7b2eca6513681127ebad53b2582911d1736dc2ffc19f2c3ae49997496bc"}, + {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cd2030f6650c089aeb304cf093f3244d34745ce0cfcc39f20c6fbfe030102e2a"}, + {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a2913c5375154b6ef2e91c10b5720ea6e21007412f6437504ffea2109b5a33d7"}, + {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:c41fb5e6a5fe9ebcd58ca3abfeb51dffb5d83d6775405305bfa8715b76521922"}, + {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3eaafe47ec0d0ffcc9349e1708be2aaea4c6dd4978d76bf6eb0cb2c13636c6fc"}, + {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1b95b98b0d2af784078fa69f637135e3c317091b615cd0905f8b8a087e86fa30"}, + {file = "cryptography-42.0.5-cp39-abi3-win32.whl", hash = "sha256:1f71c10d1e88467126f0efd484bd44bca5e14c664ec2ede64c32f20875c0d413"}, + {file = "cryptography-42.0.5-cp39-abi3-win_amd64.whl", hash = "sha256:a011a644f6d7d03736214d38832e030d8268bcff4a41f728e6030325fea3e400"}, + {file = "cryptography-42.0.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9481ffe3cf013b71b2428b905c4f7a9a4f76ec03065b05ff499bb5682a8d9ad8"}, + {file = "cryptography-42.0.5-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:ba334e6e4b1d92442b75ddacc615c5476d4ad55cc29b15d590cc6b86efa487e2"}, + {file = "cryptography-42.0.5-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ba3e4a42397c25b7ff88cdec6e2a16c2be18720f317506ee25210f6d31925f9c"}, + {file = "cryptography-42.0.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:111a0d8553afcf8eb02a4fea6ca4f59d48ddb34497aa8706a6cf536f1a5ec576"}, + {file = "cryptography-42.0.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cd65d75953847815962c84a4654a84850b2bb4aed3f26fadcc1c13892e1e29f6"}, + {file = "cryptography-42.0.5-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e807b3188f9eb0eaa7bbb579b462c5ace579f1cedb28107ce8b48a9f7ad3679e"}, + {file = "cryptography-42.0.5-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f12764b8fffc7a123f641d7d049d382b73f96a34117e0b637b80643169cec8ac"}, + {file = "cryptography-42.0.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:37dd623507659e08be98eec89323469e8c7b4c1407c85112634ae3dbdb926fdd"}, + {file = "cryptography-42.0.5.tar.gz", hash = "sha256:6fe07eec95dfd477eb9530aef5bead34fec819b3aaf6c5bd6d20565da607bfe1"}, ] [package.dependencies] @@ -2281,22 +2281,22 @@ tests = ["pytest (>=4.6)"] [[package]] name = "msal" -version = "1.26.0" +version = "1.27.0" description = "The Microsoft Authentication Library (MSAL) for Python library enables your app to access the Microsoft Cloud by supporting authentication of users with Microsoft Azure Active Directory accounts (AAD) and Microsoft Accounts (MSA) using industry standard OAuth2 and OpenID Connect." optional = false python-versions = ">=2.7" files = [ - {file = "msal-1.26.0-py2.py3-none-any.whl", hash = "sha256:be77ba6a8f49c9ff598bbcdc5dfcf1c9842f3044300109af738e8c3e371065b5"}, - {file = "msal-1.26.0.tar.gz", hash = "sha256:224756079fe338be838737682b49f8ebc20a87c1c5eeaf590daae4532b83de15"}, + {file = "msal-1.27.0-py2.py3-none-any.whl", hash = "sha256:572d07149b83e7343a85a3bcef8e581167b4ac76befcbbb6eef0c0e19643cdc0"}, + {file = "msal-1.27.0.tar.gz", hash = "sha256:3109503c038ba6b307152b0e8d34f98113f2e7a78986e28d0baf5b5303afda52"}, ] [package.dependencies] -cryptography = ">=0.6,<44" +cryptography = ">=0.6,<45" PyJWT = {version = ">=1.0.0,<3", extras = ["crypto"]} requests = ">=2.0.0,<3" [package.extras] -broker = ["pymsalruntime (>=0.13.2,<0.14)"] +broker = ["pymsalruntime (>=0.13.2,<0.15)"] [[package]] name = "msal-extensions" @@ -2608,36 +2608,36 @@ reference = ["Pillow", "google-re2"] [[package]] name = "onnxruntime" -version = "1.17.0" +version = "1.17.1" description = "ONNX Runtime is a runtime accelerator for Machine Learning models" optional = false python-versions = "*" files = [ - {file = "onnxruntime-1.17.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:d2b22a25a94109cc983443116da8d9805ced0256eb215c5e6bc6dcbabefeab96"}, - {file = "onnxruntime-1.17.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4c87d83c6f58d1af2675fc99e3dc810f2dbdb844bcefd0c1b7573632661f6fc"}, - {file = "onnxruntime-1.17.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dba55723bf9b835e358f48c98a814b41692c393eb11f51e02ece0625c756b797"}, - {file = "onnxruntime-1.17.0-cp310-cp310-win32.whl", hash = "sha256:ee48422349cc500273beea7607e33c2237909f58468ae1d6cccfc4aecd158565"}, - {file = "onnxruntime-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:f34cc46553359293854e38bdae2ab1be59543aad78a6317e7746d30e311110c3"}, - {file = "onnxruntime-1.17.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:16d26badd092c8c257fa57c458bb600d96dc15282c647ccad0ed7b2732e6c03b"}, - {file = "onnxruntime-1.17.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6f1273bebcdb47ed932d076c85eb9488bc4768fcea16d5f2747ca692fad4f9d3"}, - {file = "onnxruntime-1.17.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cb60fd3c2c1acd684752eb9680e89ae223e9801a9b0e0dc7b28adabe45a2e380"}, - {file = "onnxruntime-1.17.0-cp311-cp311-win32.whl", hash = "sha256:4b038324586bc905299e435f7c00007e6242389c856b82fe9357fdc3b1ef2bdc"}, - {file = "onnxruntime-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:93d39b3fa1ee01f034f098e1c7769a811a21365b4883f05f96c14a2b60c6028b"}, - {file = "onnxruntime-1.17.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:90c0890e36f880281c6c698d9bc3de2afbeee2f76512725ec043665c25c67d21"}, - {file = "onnxruntime-1.17.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7466724e809a40e986b1637cba156ad9fc0d1952468bc00f79ef340bc0199552"}, - {file = "onnxruntime-1.17.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d47bee7557a8b99c8681b6882657a515a4199778d6d5e24e924d2aafcef55b0a"}, - {file = "onnxruntime-1.17.0-cp312-cp312-win32.whl", hash = "sha256:bb1bf1ee575c665b8bbc3813ab906e091a645a24ccc210be7932154b8260eca1"}, - {file = "onnxruntime-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:ac2f286da3494b29b4186ca193c7d4e6a2c1f770c4184c7192c5da142c3dec28"}, - {file = "onnxruntime-1.17.0-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:1ec485643b93e0a3896c655eb2426decd63e18a278bb7ccebc133b340723624f"}, - {file = "onnxruntime-1.17.0-cp38-cp38-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:83c35809cda898c5a11911c69ceac8a2ac3925911854c526f73bad884582f911"}, - {file = "onnxruntime-1.17.0-cp38-cp38-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fa464aa4d81df818375239e481887b656e261377d5b6b9a4692466f5f3261edc"}, - {file = "onnxruntime-1.17.0-cp38-cp38-win32.whl", hash = "sha256:b7b337cd0586f7836601623cbd30a443df9528ef23965860d11c753ceeb009f2"}, - {file = "onnxruntime-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:fbb9faaf51d01aa2c147ef52524d9326744c852116d8005b9041809a71838878"}, - {file = "onnxruntime-1.17.0-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:5a06ab84eaa350bf64b1d747b33ccf10da64221ed1f38f7287f15eccbec81603"}, - {file = "onnxruntime-1.17.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d3d11db2c8242766212a68d0b139745157da7ce53bd96ba349a5c65e5a02357"}, - {file = "onnxruntime-1.17.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5632077c3ab8b0cd4f74b0af9c4e924be012b1a7bcd7daa845763c6c6bf14b7d"}, - {file = "onnxruntime-1.17.0-cp39-cp39-win32.whl", hash = "sha256:61a12732cba869b3ad2d4e29ab6cb62c7a96f61b8c213f7fcb961ba412b70b37"}, - {file = "onnxruntime-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:461fa0fc7d9c392c352b6cccdedf44d818430f3d6eacd924bb804fdea2dcfd02"}, + {file = "onnxruntime-1.17.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:d43ac17ac4fa3c9096ad3c0e5255bb41fd134560212dc124e7f52c3159af5d21"}, + {file = "onnxruntime-1.17.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55b5e92a4c76a23981c998078b9bf6145e4fb0b016321a8274b1607bd3c6bd35"}, + {file = "onnxruntime-1.17.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ebbcd2bc3a066cf54e6f18c75708eb4d309ef42be54606d22e5bdd78afc5b0d7"}, + {file = "onnxruntime-1.17.1-cp310-cp310-win32.whl", hash = "sha256:5e3716b5eec9092e29a8d17aab55e737480487deabfca7eac3cd3ed952b6ada9"}, + {file = "onnxruntime-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:fbb98cced6782ae1bb799cc74ddcbbeeae8819f3ad1d942a74d88e72b6511337"}, + {file = "onnxruntime-1.17.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:36fd6f87a1ecad87e9c652e42407a50fb305374f9a31d71293eb231caae18784"}, + {file = "onnxruntime-1.17.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:99a8bddeb538edabc524d468edb60ad4722cff8a49d66f4e280c39eace70500b"}, + {file = "onnxruntime-1.17.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd7fddb4311deb5a7d3390cd8e9b3912d4d963efbe4dfe075edbaf18d01c024e"}, + {file = "onnxruntime-1.17.1-cp311-cp311-win32.whl", hash = "sha256:606a7cbfb6680202b0e4f1890881041ffc3ac6e41760a25763bd9fe146f0b335"}, + {file = "onnxruntime-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:53e4e06c0a541696ebdf96085fd9390304b7b04b748a19e02cf3b35c869a1e76"}, + {file = "onnxruntime-1.17.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:40f08e378e0f85929712a2b2c9b9a9cc400a90c8a8ca741d1d92c00abec60843"}, + {file = "onnxruntime-1.17.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ac79da6d3e1bb4590f1dad4bb3c2979d7228555f92bb39820889af8b8e6bd472"}, + {file = "onnxruntime-1.17.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ae9ba47dc099004e3781f2d0814ad710a13c868c739ab086fc697524061695ea"}, + {file = "onnxruntime-1.17.1-cp312-cp312-win32.whl", hash = "sha256:2dff1a24354220ac30e4a4ce2fb1df38cb1ea59f7dac2c116238d63fe7f4c5ff"}, + {file = "onnxruntime-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:6226a5201ab8cafb15e12e72ff2a4fc8f50654e8fa5737c6f0bd57c5ff66827e"}, + {file = "onnxruntime-1.17.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:cd0c07c0d1dfb8629e820b05fda5739e4835b3b82faf43753d2998edf2cf00aa"}, + {file = "onnxruntime-1.17.1-cp38-cp38-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:617ebdf49184efa1ba6e4467e602fbfa029ed52c92f13ce3c9f417d303006381"}, + {file = "onnxruntime-1.17.1-cp38-cp38-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9dae9071e3facdf2920769dceee03b71c684b6439021defa45b830d05e148924"}, + {file = "onnxruntime-1.17.1-cp38-cp38-win32.whl", hash = "sha256:835d38fa1064841679433b1aa8138b5e1218ddf0cfa7a3ae0d056d8fd9cec713"}, + {file = "onnxruntime-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:96621e0c555c2453bf607606d08af3f70fbf6f315230c28ddea91754e17ad4e6"}, + {file = "onnxruntime-1.17.1-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:7a9539935fb2d78ebf2cf2693cad02d9930b0fb23cdd5cf37a7df813e977674d"}, + {file = "onnxruntime-1.17.1-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:45c6a384e9d9a29c78afff62032a46a993c477b280247a7e335df09372aedbe9"}, + {file = "onnxruntime-1.17.1-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4e19f966450f16863a1d6182a685ca33ae04d7772a76132303852d05b95411ea"}, + {file = "onnxruntime-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e2ae712d64a42aac29ed7a40a426cb1e624a08cfe9273dcfe681614aa65b07dc"}, + {file = "onnxruntime-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:f7e9f7fb049825cdddf4a923cfc7c649d84d63c0134315f8e0aa9e0c3004672c"}, ] [package.dependencies] @@ -2650,21 +2650,21 @@ sympy = "*" [[package]] name = "onnxruntime-gpu" -version = "1.17.0" +version = "1.17.1" description = "ONNX Runtime is a runtime accelerator for Machine Learning models" optional = false python-versions = "*" files = [ - {file = "onnxruntime_gpu-1.17.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:1f2a4e0468ac0bd8246996c3d5dbba92cbbaca874bcd7f9cee4e99ce6eb27f5b"}, - {file = "onnxruntime_gpu-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:0721b7930d7abed3730b2335e639e60d94ec411bb4d35a0347cc9c8b52c34540"}, - {file = "onnxruntime_gpu-1.17.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:be0314afe399943904de7c1ca797cbcc63e6fad60eb85d3df6422f81dd94e79e"}, - {file = "onnxruntime_gpu-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:52125c24b21406d1431e43de1c98cea29c21e0cceba80db530b7e4c9216d86ea"}, - {file = "onnxruntime_gpu-1.17.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:bb802d8033885c412269f8bc8877d8779b0dc874df6fb9df8b796cba7276ad66"}, - {file = "onnxruntime_gpu-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:8c43533e3e5335eaa78059fb86b849a4faded513a00c1feaaa205ca5af51c40f"}, - {file = "onnxruntime_gpu-1.17.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:1d461455bba160836d6c11c648c8fd4e4500d5c17096a13e6c2c9d22a4abd436"}, - {file = "onnxruntime_gpu-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4398f2175a92f4b35d95279a6294a89c462f24de058a2736ee1d498bab5a16"}, - {file = "onnxruntime_gpu-1.17.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:1d0e3805cd1c024aba7f4ae576fd08545fc27530a2aaad2b3c8ac0ee889fbd05"}, - {file = "onnxruntime_gpu-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc1da5b93363ee600b5b220b04eeec51ad2c2b3e96f0b7615b16b8a173c88001"}, + {file = "onnxruntime_gpu-1.17.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a55fe84ee11a59ea069c6a790ee960f1c7da0d7d6c74822b2a8b357027c93646"}, + {file = "onnxruntime_gpu-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:a9abefceb32879cbee9f57977d6bb8d58cbac501f8a64bf96bca2f4fdff157fe"}, + {file = "onnxruntime_gpu-1.17.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:b2cd54f2b0a05e6bc9ab30182b859364d30115a19c31be24aa2edef40be00277"}, + {file = "onnxruntime_gpu-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:bdffcced8a5f6275c0df202220e9232138b336f868cd671c9d2c571e834d2a80"}, + {file = "onnxruntime_gpu-1.17.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:a1c871e8d0ae4121ea6528fc9410a5a7cbc5e43714b30521d5514fd10b987c83"}, + {file = "onnxruntime_gpu-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:9a0a94eda080e9f4a8e5035fdf0b3c24f5533e7861d88833a94493e63fca0812"}, + {file = "onnxruntime_gpu-1.17.1-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:624fdb65a632833f13de36854855818680be4f77942d8114524491d58f60d3ab"}, + {file = "onnxruntime_gpu-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:29fa78d232bbb5a5be3a3e0a022148a7b3df2ca66b4c21a11eef56e6f22859e9"}, + {file = "onnxruntime_gpu-1.17.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b0f8c70f2f9aeae825f3a397cc0c5f45124f9ae7c173263cf13c495982b0b99a"}, + {file = "onnxruntime_gpu-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:b1a27a104334461b690e4fc62775e1e71c68936399874932225d7fea21a0c261"}, ] [package.dependencies] @@ -2844,40 +2844,40 @@ test = ["pylint (>=3.0.0,<3.1.0)", "pytest", "pytest-pylint"] [[package]] name = "pandas" -version = "2.2.0" +version = "2.2.1" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.9" files = [ - {file = "pandas-2.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8108ee1712bb4fa2c16981fba7e68b3f6ea330277f5ca34fa8d557e986a11670"}, - {file = "pandas-2.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:736da9ad4033aeab51d067fc3bd69a0ba36f5a60f66a527b3d72e2030e63280a"}, - {file = "pandas-2.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38e0b4fc3ddceb56ec8a287313bc22abe17ab0eb184069f08fc6a9352a769b18"}, - {file = "pandas-2.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20404d2adefe92aed3b38da41d0847a143a09be982a31b85bc7dd565bdba0f4e"}, - {file = "pandas-2.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7ea3ee3f125032bfcade3a4cf85131ed064b4f8dd23e5ce6fa16473e48ebcaf5"}, - {file = "pandas-2.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f9670b3ac00a387620489dfc1bca66db47a787f4e55911f1293063a78b108df1"}, - {file = "pandas-2.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:5a946f210383c7e6d16312d30b238fd508d80d927014f3b33fb5b15c2f895430"}, - {file = "pandas-2.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a1b438fa26b208005c997e78672f1aa8138f67002e833312e6230f3e57fa87d5"}, - {file = "pandas-2.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8ce2fbc8d9bf303ce54a476116165220a1fedf15985b09656b4b4275300e920b"}, - {file = "pandas-2.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2707514a7bec41a4ab81f2ccce8b382961a29fbe9492eab1305bb075b2b1ff4f"}, - {file = "pandas-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85793cbdc2d5bc32620dc8ffa715423f0c680dacacf55056ba13454a5be5de88"}, - {file = "pandas-2.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cfd6c2491dc821b10c716ad6776e7ab311f7df5d16038d0b7458bc0b67dc10f3"}, - {file = "pandas-2.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a146b9dcacc3123aa2b399df1a284de5f46287a4ab4fbfc237eac98a92ebcb71"}, - {file = "pandas-2.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbc1b53c0e1fdf16388c33c3cca160f798d38aea2978004dd3f4d3dec56454c9"}, - {file = "pandas-2.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a41d06f308a024981dcaa6c41f2f2be46a6b186b902c94c2674e8cb5c42985bc"}, - {file = "pandas-2.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:159205c99d7a5ce89ecfc37cb08ed179de7783737cea403b295b5eda8e9c56d1"}, - {file = "pandas-2.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb1e1f3861ea9132b32f2133788f3b14911b68102d562715d71bd0013bc45440"}, - {file = "pandas-2.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:761cb99b42a69005dec2b08854fb1d4888fdf7b05db23a8c5a099e4b886a2106"}, - {file = "pandas-2.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a20628faaf444da122b2a64b1e5360cde100ee6283ae8effa0d8745153809a2e"}, - {file = "pandas-2.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f5be5d03ea2073627e7111f61b9f1f0d9625dc3c4d8dda72cc827b0c58a1d042"}, - {file = "pandas-2.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:a626795722d893ed6aacb64d2401d017ddc8a2341b49e0384ab9bf7112bdec30"}, - {file = "pandas-2.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9f66419d4a41132eb7e9a73dcec9486cf5019f52d90dd35547af11bc58f8637d"}, - {file = "pandas-2.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:57abcaeda83fb80d447f28ab0cc7b32b13978f6f733875ebd1ed14f8fbc0f4ab"}, - {file = "pandas-2.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e60f1f7dba3c2d5ca159e18c46a34e7ca7247a73b5dd1a22b6d59707ed6b899a"}, - {file = "pandas-2.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb61dc8567b798b969bcc1fc964788f5a68214d333cade8319c7ab33e2b5d88a"}, - {file = "pandas-2.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:52826b5f4ed658fa2b729264d63f6732b8b29949c7fd234510d57c61dbeadfcd"}, - {file = "pandas-2.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bde2bc699dbd80d7bc7f9cab1e23a95c4375de615860ca089f34e7c64f4a8de7"}, - {file = "pandas-2.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:3de918a754bbf2da2381e8a3dcc45eede8cd7775b047b923f9006d5f876802ae"}, - {file = "pandas-2.2.0.tar.gz", hash = "sha256:30b83f7c3eb217fb4d1b494a57a2fda5444f17834f5df2de6b2ffff68dc3c8e2"}, + {file = "pandas-2.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8df8612be9cd1c7797c93e1c5df861b2ddda0b48b08f2c3eaa0702cf88fb5f88"}, + {file = "pandas-2.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0f573ab277252ed9aaf38240f3b54cfc90fff8e5cab70411ee1d03f5d51f3944"}, + {file = "pandas-2.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f02a3a6c83df4026e55b63c1f06476c9aa3ed6af3d89b4f04ea656ccdaaaa359"}, + {file = "pandas-2.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c38ce92cb22a4bea4e3929429aa1067a454dcc9c335799af93ba9be21b6beb51"}, + {file = "pandas-2.2.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c2ce852e1cf2509a69e98358e8458775f89599566ac3775e70419b98615f4b06"}, + {file = "pandas-2.2.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:53680dc9b2519cbf609c62db3ed7c0b499077c7fefda564e330286e619ff0dd9"}, + {file = "pandas-2.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:94e714a1cca63e4f5939cdce5f29ba8d415d85166be3441165edd427dc9f6bc0"}, + {file = "pandas-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f821213d48f4ab353d20ebc24e4faf94ba40d76680642fb7ce2ea31a3ad94f9b"}, + {file = "pandas-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c70e00c2d894cb230e5c15e4b1e1e6b2b478e09cf27cc593a11ef955b9ecc81a"}, + {file = "pandas-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e97fbb5387c69209f134893abc788a6486dbf2f9e511070ca05eed4b930b1b02"}, + {file = "pandas-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101d0eb9c5361aa0146f500773395a03839a5e6ecde4d4b6ced88b7e5a1a6403"}, + {file = "pandas-2.2.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7d2ed41c319c9fb4fd454fe25372028dfa417aacb9790f68171b2e3f06eae8cd"}, + {file = "pandas-2.2.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:af5d3c00557d657c8773ef9ee702c61dd13b9d7426794c9dfeb1dc4a0bf0ebc7"}, + {file = "pandas-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:06cf591dbaefb6da9de8472535b185cba556d0ce2e6ed28e21d919704fef1a9e"}, + {file = "pandas-2.2.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:88ecb5c01bb9ca927ebc4098136038519aa5d66b44671861ffab754cae75102c"}, + {file = "pandas-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:04f6ec3baec203c13e3f8b139fb0f9f86cd8c0b94603ae3ae8ce9a422e9f5bee"}, + {file = "pandas-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a935a90a76c44fe170d01e90a3594beef9e9a6220021acfb26053d01426f7dc2"}, + {file = "pandas-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c391f594aae2fd9f679d419e9a4d5ba4bce5bb13f6a989195656e7dc4b95c8f0"}, + {file = "pandas-2.2.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9d1265545f579edf3f8f0cb6f89f234f5e44ba725a34d86535b1a1d38decbccc"}, + {file = "pandas-2.2.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:11940e9e3056576ac3244baef2fedade891977bcc1cb7e5cc8f8cc7d603edc89"}, + {file = "pandas-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:4acf681325ee1c7f950d058b05a820441075b0dd9a2adf5c4835b9bc056bf4fb"}, + {file = "pandas-2.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9bd8a40f47080825af4317d0340c656744f2bfdb6819f818e6ba3cd24c0e1397"}, + {file = "pandas-2.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:df0c37ebd19e11d089ceba66eba59a168242fc6b7155cba4ffffa6eccdfb8f16"}, + {file = "pandas-2.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:739cc70eaf17d57608639e74d63387b0d8594ce02f69e7a0b046f117974b3019"}, + {file = "pandas-2.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9d3558d263073ed95e46f4650becff0c5e1ffe0fc3a015de3c79283dfbdb3df"}, + {file = "pandas-2.2.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4aa1d8707812a658debf03824016bf5ea0d516afdea29b7dc14cf687bc4d4ec6"}, + {file = "pandas-2.2.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:76f27a809cda87e07f192f001d11adc2b930e93a2b0c4a236fde5429527423be"}, + {file = "pandas-2.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:1ba21b1d5c0e43416218db63037dbe1a01fc101dc6e6024bcad08123e48004ab"}, + {file = "pandas-2.2.1.tar.gz", hash = "sha256:0ab90f87093c13f3e8fa45b48ba9f39181046e8f3317d3aadb2fffbb1b978572"}, ] [package.dependencies] @@ -2905,6 +2905,7 @@ parquet = ["pyarrow (>=10.0.1)"] performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] plot = ["matplotlib (>=3.6.3)"] postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] +pyarrow = ["pyarrow (>=10.0.1)"] spss = ["pyreadstat (>=1.2.0)"] sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] @@ -6468,13 +6469,13 @@ cp2110 = ["hidapi"] [[package]] name = "pytest" -version = "8.0.1" +version = "8.0.2" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.0.1-py3-none-any.whl", hash = "sha256:3e4f16fe1c0a9dc9d9389161c127c3edc5d810c38d6793042fb81d9f48a59fca"}, - {file = "pytest-8.0.1.tar.gz", hash = "sha256:267f6563751877d772019b13aacbe4e860d73fe8f651f28112e9ac37de7513ae"}, + {file = "pytest-8.0.2-py3-none-any.whl", hash = "sha256:edfaaef32ce5172d5466b5127b42e0d6d35ebbe4453f0e3505d96afd93f6b096"}, + {file = "pytest-8.0.2.tar.gz", hash = "sha256:d4051d623a2e0b7e51960ba963193b09ce6daeb9759a451844a21e4ddedfc1bd"}, ] [package.dependencies] @@ -6639,12 +6640,12 @@ numpy = ["numpy (>=1.6.0)"] [[package]] name = "pytweening" -version = "1.1.0" -description = "A collection of tweening / easing functions." +version = "1.2.0" +description = "A collection of tweening (aka easing) functions." optional = false python-versions = "*" files = [ - {file = "pytweening-1.1.0.tar.gz", hash = "sha256:0d8e14af529dd816ad4aa4a86757dfb5fe2fc2897e06f5db60183706a9370828"}, + {file = "pytweening-1.2.0.tar.gz", hash = "sha256:243318b7736698066c5f362ec5c2b6434ecf4297c3c8e7caa8abfe6af4cac71b"}, ] [[package]] @@ -7172,19 +7173,19 @@ test = ["pytest"] [[package]] name = "setuptools" -version = "69.1.0" +version = "69.1.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.1.0-py3-none-any.whl", hash = "sha256:c054629b81b946d63a9c6e732bc8b2513a7c3ea645f11d0139a2191d735c60c6"}, - {file = "setuptools-69.1.0.tar.gz", hash = "sha256:850894c4195f09c4ed30dba56213bf7c3f21d86ed6bdaafb5df5972593bfc401"}, + {file = "setuptools-69.1.1-py3-none-any.whl", hash = "sha256:02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56"}, + {file = "setuptools-69.1.1.tar.gz", hash = "sha256:5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "shapely" @@ -7619,13 +7620,13 @@ files = [ [[package]] name = "typing-extensions" -version = "4.9.0" +version = "4.10.0" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, - {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, + {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, + {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, ] [[package]] @@ -7658,13 +7659,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.25.0" +version = "20.25.1" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.25.0-py3-none-any.whl", hash = "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3"}, - {file = "virtualenv-20.25.0.tar.gz", hash = "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b"}, + {file = "virtualenv-20.25.1-py3-none-any.whl", hash = "sha256:961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a"}, + {file = "virtualenv-20.25.1.tar.gz", hash = "sha256:e08e13ecdca7a0bd53798f356d5831434afa5b07b93f0abdf0797b7a06ffe197"}, ] [package.dependencies] From 5c0bbc7dda74f4e354b5e670185abf29d2d49488 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Mon, 26 Feb 2024 11:20:42 -0800 Subject: [PATCH 14/41] [bot] Bump submodules (#31594) * bump submodules * bump opendbc --------- Co-authored-by: jnewb1 Co-authored-by: Justin Newberry --- cereal | 2 +- opendbc | 2 +- panda | 2 +- rednose_repo | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cereal b/cereal index 2fba1381f40df2..a4255106b7255e 160000 --- a/cereal +++ b/cereal @@ -1 +1 @@ -Subproject commit 2fba1381f40df2654f42a2e4bed869f2b7d01a52 +Subproject commit a4255106b7255e00ae04162f7aa14aa3cae339c3 diff --git a/opendbc b/opendbc index 951ab07fdcbce0..0ac21652f2e643 160000 --- a/opendbc +++ b/opendbc @@ -1 +1 @@ -Subproject commit 951ab07fdcbce023a5c927f56bbf94e0f2322366 +Subproject commit 0ac21652f2e643e29aa471ad6b238bf74b22e356 diff --git a/panda b/panda index 6aa4b550336136..0c7d5f11d71879 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit 6aa4b550336136bc20a6abb307cf310e876eba28 +Subproject commit 0c7d5f11d7187904022ea49b6a76b54d7b280345 diff --git a/rednose_repo b/rednose_repo index 18b91458fd3965..c5762e8bc6f733 160000 --- a/rednose_repo +++ b/rednose_repo @@ -1 +1 @@ -Subproject commit 18b91458fd396530d43e1a2fe9a3ac9055fa9109 +Subproject commit c5762e8bc6f7338c7a30d2cd1cba8cc64e81ba19 From 86090a1e150f6d6df5283725ff1fb03605ecfef5 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Mon, 26 Feb 2024 14:20:51 -0500 Subject: [PATCH 15/41] add common/mock to release (#31596) * add mock * fix * fix2 --- release/files_common | 1 + 1 file changed, 1 insertion(+) diff --git a/release/files_common b/release/files_common index 00a6abe6e6389b..d62ef8d1bb6dd9 100644 --- a/release/files_common +++ b/release/files_common @@ -23,6 +23,7 @@ common/.gitignore common/__init__.py common/*.py common/*.pyx +common/mock/* common/transformations/__init__.py common/transformations/camera.py From 9d1cafd0fccc0406a91309a2f9aa1053b498601d Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Mon, 26 Feb 2024 15:53:17 -0500 Subject: [PATCH 16/41] move with_http_server to selfdrive/test/helpers (#31597) * move * fix --- selfdrive/athena/tests/helpers.py | 24 ------------------------ selfdrive/athena/tests/test_athenad.py | 4 ++-- selfdrive/test/helpers.py | 24 ++++++++++++++++++++++++ tools/lib/tests/test_caching.py | 2 +- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/selfdrive/athena/tests/helpers.py b/selfdrive/athena/tests/helpers.py index 87202665aa8c94..3dd98f02c91d29 100644 --- a/selfdrive/athena/tests/helpers.py +++ b/selfdrive/athena/tests/helpers.py @@ -1,7 +1,5 @@ import http.server -import threading import socket -from functools import wraps class MockResponse: @@ -65,25 +63,3 @@ def do_PUT(self): self.rfile.read(length) self.send_response(201, "Created") self.end_headers() - - -def with_http_server(func, handler=http.server.BaseHTTPRequestHandler, setup=None): - @wraps(func) - def inner(*args, **kwargs): - host = '127.0.0.1' - server = http.server.HTTPServer((host, 0), handler) - port = server.server_port - t = threading.Thread(target=server.serve_forever) - t.start() - - if setup is not None: - setup(host, port) - - try: - return func(*args, f'http://{host}:{port}', **kwargs) - finally: - server.shutdown() - server.server_close() - t.join() - - return inner diff --git a/selfdrive/athena/tests/test_athenad.py b/selfdrive/athena/tests/test_athenad.py index 780bef345e863e..4850ab9a3fc167 100755 --- a/selfdrive/athena/tests/test_athenad.py +++ b/selfdrive/athena/tests/test_athenad.py @@ -23,9 +23,9 @@ from openpilot.common.timeout import Timeout from openpilot.selfdrive.athena import athenad from openpilot.selfdrive.athena.athenad import MAX_RETRY_COUNT, dispatcher -from openpilot.selfdrive.athena.tests.helpers import MockWebsocket, MockApi, EchoSocket, with_http_server +from openpilot.selfdrive.athena.tests.helpers import HTTPRequestHandler, MockWebsocket, MockApi, EchoSocket +from openpilot.selfdrive.test.helpers import with_http_server from openpilot.system.hardware.hw import Paths -from openpilot.selfdrive.athena.tests.helpers import HTTPRequestHandler def seed_athena_server(host, port): diff --git a/selfdrive/test/helpers.py b/selfdrive/test/helpers.py index a62f7ede852585..210a283699f8cb 100644 --- a/selfdrive/test/helpers.py +++ b/selfdrive/test/helpers.py @@ -1,4 +1,6 @@ +import http.server import os +import threading import time from functools import wraps @@ -76,3 +78,25 @@ def read_segment_list(segment_list_path): seg_list = f.read().splitlines() return [(platform[2:], segment) for platform, segment in zip(seg_list[::2], seg_list[1::2], strict=True)] + + +def with_http_server(func, handler=http.server.BaseHTTPRequestHandler, setup=None): + @wraps(func) + def inner(*args, **kwargs): + host = '127.0.0.1' + server = http.server.HTTPServer((host, 0), handler) + port = server.server_port + t = threading.Thread(target=server.serve_forever) + t.start() + + if setup is not None: + setup(host, port) + + try: + return func(*args, f'http://{host}:{port}', **kwargs) + finally: + server.shutdown() + server.server_close() + t.join() + + return inner diff --git a/tools/lib/tests/test_caching.py b/tools/lib/tests/test_caching.py index bc92b013576891..5d3dfeba426c35 100755 --- a/tools/lib/tests/test_caching.py +++ b/tools/lib/tests/test_caching.py @@ -7,7 +7,7 @@ import unittest from parameterized import parameterized -from openpilot.selfdrive.athena.tests.helpers import with_http_server +from openpilot.selfdrive.test.helpers import with_http_server from openpilot.system.hardware.hw import Paths from openpilot.tools.lib.url_file import URLFile From edd26acdc324ad8d4b3ccd7406be545545f4cb6f Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Mon, 26 Feb 2024 19:26:01 -0500 Subject: [PATCH 17/41] can_replay: add type hint (#31601) type hint --- tools/replay/can_replay.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tools/replay/can_replay.py b/tools/replay/can_replay.py index c597df1f662c8a..bf6b1e9ae2cc55 100755 --- a/tools/replay/can_replay.py +++ b/tools/replay/can_replay.py @@ -21,41 +21,41 @@ ENABLE_PWR = PWR_ON > 0 and PWR_OFF > 0 -def send_thread(s, flock): +def send_thread(j: PandaJungle, flock): if "FLASH" in os.environ: with flock: - s.flash() + j.flash() for i in [0, 1, 2, 3, 0xFFFF]: - s.can_clear(i) - s.set_can_speed_kbps(i, 500) - s.set_can_data_speed_kbps(i, 500) - s.set_ignition(False) + j.can_clear(i) + j.set_can_speed_kbps(i, 500) + j.set_can_data_speed_kbps(i, 500) + j.set_ignition(False) time.sleep(5) - s.set_ignition(True) - s.set_panda_power(True) - s.set_can_loopback(False) + j.set_ignition(True) + j.set_panda_power(True) + j.set_can_loopback(False) rk = Ratekeeper(1 / DT_CTRL, print_delay_threshold=None) while True: # handle cycling if ENABLE_PWR: i = (rk.frame*DT_CTRL) % (PWR_ON + PWR_OFF) < PWR_ON - s.set_panda_power(i) + j.set_panda_power(i) if ENABLE_IGN: i = (rk.frame*DT_CTRL) % (IGN_ON + IGN_OFF) < IGN_ON - s.set_ignition(i) + j.set_ignition(i) snd = CAN_MSGS[rk.frame % len(CAN_MSGS)] snd = list(filter(lambda x: x[-1] <= 2, snd)) try: - s.can_send_many(snd) + j.can_send_many(snd) except usb1.USBErrorTimeout: # timeout is fine, just means the CAN TX buffer is full pass # Drain panda message buffer - s.can_recv() + j.can_recv() rk.keep_time() From 3c4e82f14a3569cec615fe602886271fee1566c7 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Mon, 26 Feb 2024 20:21:44 -0800 Subject: [PATCH 18/41] get name from kernel (#31602) * get name from kernel * revert that --------- Co-authored-by: Comma Device --- system/hardware/tici/hardware.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system/hardware/tici/hardware.h b/system/hardware/tici/hardware.h index e553a665a8a71e..f1d1f1e717ed88 100644 --- a/system/hardware/tici/hardware.h +++ b/system/hardware/tici/hardware.h @@ -20,12 +20,12 @@ class HardwareTici : public HardwareNone { } static std::string get_name() { - std::string devicetree_model = util::read_file("/sys/firmware/devicetree/base/model"); - return (devicetree_model.find("tizi") != std::string::npos) ? "tizi" : "tici"; + std::string model = util::read_file("/sys/firmware/devicetree/base/model"); + return model.substr(std::string("comma ").size()); } static cereal::InitData::DeviceType get_device_type() { - return (get_name() == "tizi") ? cereal::InitData::DeviceType::TIZI : cereal::InitData::DeviceType::TICI; + return (get_name() == "tizi") ? cereal::InitData::DeviceType::TIZI : (get_name() == "mici" ? cereal::InitData::DeviceType::MICI : cereal::InitData::DeviceType::TICI); } static int get_voltage() { return std::atoi(util::read_file("/sys/class/hwmon/hwmon1/in1_input").c_str()); } From 14ea615ae4acc644026b66342edc76edd9178afc Mon Sep 17 00:00:00 2001 From: Comma Device Date: Mon, 26 Feb 2024 20:39:41 -0800 Subject: [PATCH 19/41] no amp config --- system/hardware/tici/amplifier.py | 1 + 1 file changed, 1 insertion(+) diff --git a/system/hardware/tici/amplifier.py b/system/hardware/tici/amplifier.py index af82067467eaf1..5725cb8170187d 100755 --- a/system/hardware/tici/amplifier.py +++ b/system/hardware/tici/amplifier.py @@ -97,6 +97,7 @@ def configs_from_eq_params(base, eq_params): AmpConfig("Right DAC input mixer: DAI2 right", 0b1, 0x22, 0, 0b00000001), AmpConfig("Volume adjustment smoothing disabled", 0b1, 0x49, 6, 0b01000000), ], + "mici": [], } class Amplifier: From 6d0027342ab00486e9cfbed1ffbd098642f2abd7 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Tue, 27 Feb 2024 00:01:41 -0500 Subject: [PATCH 20/41] remove cast for platformconfig (#31604) * this isnt required * Cleaner --- selfdrive/car/interfaces.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index 0a2d978004ddf6..0a5ec94aa00db5 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -4,7 +4,7 @@ import tomllib from abc import abstractmethod, ABC from enum import StrEnum -from typing import Any, NamedTuple, cast +from typing import Any, NamedTuple from collections.abc import Callable from cereal import car @@ -13,7 +13,7 @@ from openpilot.common.simple_kalman import KF1D, get_kalman_gain from openpilot.common.numpy_fast import clip from openpilot.common.realtime import DT_CTRL -from openpilot.selfdrive.car import PlatformConfig, apply_hysteresis, gen_empty_fingerprint, scale_rot_inertia, scale_tire_stiffness, STD_CARGO_KG +from openpilot.selfdrive.car import apply_hysteresis, gen_empty_fingerprint, scale_rot_inertia, scale_tire_stiffness, STD_CARGO_KG from openpilot.selfdrive.car.values import Platform from openpilot.selfdrive.controls.lib.drive_helpers import V_CRUISE_MAX, get_friction from openpilot.selfdrive.controls.lib.events import Events @@ -113,14 +113,13 @@ def get_params(cls, candidate: Platform, fingerprint: dict[int, dict[int, int]], ret = CarInterfaceBase.get_std_params(candidate) if hasattr(candidate, "config"): - platform_config = cast(PlatformConfig, candidate.config) - if platform_config.specs is not None: - ret.mass = platform_config.specs.mass - ret.wheelbase = platform_config.specs.wheelbase - ret.steerRatio = platform_config.specs.steerRatio - ret.centerToFront = ret.wheelbase * platform_config.specs.centerToFrontRatio - ret.minEnableSpeed = platform_config.specs.minEnableSpeed - ret.minSteerSpeed = platform_config.specs.minSteerSpeed + if candidate.config.specs is not None: + ret.mass = candidate.config.specs.mass + ret.wheelbase = candidate.config.specs.wheelbase + ret.steerRatio = candidate.config.specs.steerRatio + ret.centerToFront = ret.wheelbase * candidate.config.specs.centerToFrontRatio + ret.minEnableSpeed = candidate.config.specs.minEnableSpeed + ret.minSteerSpeed = candidate.config.specs.minSteerSpeed ret = cls._get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs) From 9ecff49118a053917b462aac9dd20cadcf56dd1a Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Tue, 27 Feb 2024 00:16:05 -0500 Subject: [PATCH 21/41] platformconfig: freeze all dataclasses (#31605) * frozen * frozen --- selfdrive/car/__init__.py | 4 ++-- selfdrive/car/ford/values.py | 2 +- selfdrive/car/gm/values.py | 2 +- selfdrive/car/subaru/values.py | 2 +- selfdrive/car/volkswagen/values.py | 6 +++--- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/selfdrive/car/__init__.py b/selfdrive/car/__init__.py index 75b85cab2fb4ea..3b749101c9d29a 100644 --- a/selfdrive/car/__init__.py +++ b/selfdrive/car/__init__.py @@ -246,7 +246,7 @@ def update(self, current_value, current_counter): CarInfos = CarInfo | list[CarInfo] -@dataclass(kw_only=True) +@dataclass(frozen=True, kw_only=True) class CarSpecs: mass: float wheelbase: float @@ -256,7 +256,7 @@ class CarSpecs: minEnableSpeed: float = field(default=-1.) -@dataclass(order=True) +@dataclass(frozen=True, order=True) class PlatformConfig: platform_str: str car_info: CarInfos diff --git a/selfdrive/car/ford/values.py b/selfdrive/car/ford/values.py index ef99cf5f340f1e..caa3eb0d379899 100644 --- a/selfdrive/car/ford/values.py +++ b/selfdrive/car/ford/values.py @@ -63,7 +63,7 @@ def init_make(self, CP: car.CarParams): self.car_parts = CarParts([Device.threex, harness]) -@dataclass +@dataclass(frozen=True) class FordPlatformConfig(PlatformConfig): dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('ford_lincoln_base_pt', RADAR.DELPHI_MRR)) diff --git a/selfdrive/car/gm/values.py b/selfdrive/car/gm/values.py index 53dbde87f44f86..35fdf3fb92ee6b 100644 --- a/selfdrive/car/gm/values.py +++ b/selfdrive/car/gm/values.py @@ -79,7 +79,7 @@ def init_make(self, CP: car.CarParams): self.footnotes.append(Footnote.OBD_II) -@dataclass +@dataclass(frozen=True) class GMPlatformConfig(PlatformConfig): dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('gm_global_a_powertrain_generated', 'gm_global_a_object', chassis_dbc='gm_global_a_chassis')) diff --git a/selfdrive/car/subaru/values.py b/selfdrive/car/subaru/values.py index 0fd7ab9c1357bb..a296550b12f6ac 100644 --- a/selfdrive/car/subaru/values.py +++ b/selfdrive/car/subaru/values.py @@ -89,7 +89,7 @@ def init_make(self, CP: car.CarParams): self.footnotes.append(Footnote.EXP_LONG) -@dataclass +@dataclass(frozen=True) class SubaruPlatformConfig(PlatformConfig): dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('subaru_global_2017_generated', None)) diff --git a/selfdrive/car/volkswagen/values.py b/selfdrive/car/volkswagen/values.py index f0297402840c11..4dff9205d64736 100644 --- a/selfdrive/car/volkswagen/values.py +++ b/selfdrive/car/volkswagen/values.py @@ -112,15 +112,15 @@ class CANBUS: class VolkswagenFlags(IntFlag): STOCK_HCA_PRESENT = 1 -@dataclass +@dataclass(frozen=True) class VolkswagenMQBPlatformConfig(PlatformConfig): dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('vw_mqb_2010', None)) -@dataclass +@dataclass(frozen=True) class VolkswagenPQPlatformConfig(PlatformConfig): dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('vw_golf_mk4', None)) -@dataclass(kw_only=True) +@dataclass(frozen=True, kw_only=True) class VolkswagenCarSpecs(CarSpecs): steerRatio: float = field(default=15.6) From c724d1c86ce4044bfc03f1e7941871466f51a708 Mon Sep 17 00:00:00 2001 From: Cameron Clough Date: Tue, 27 Feb 2024 12:22:10 +0000 Subject: [PATCH 22/41] Ford: log interesting module configuration data (#31569) * Ford: log interesting module configuration data Ford ECUs have what is called "As-Built Data" which is configured at the factory/workshop to set what packages/features are enabled on the car. But they also contain vehicle specific information (VIN, make, model, weight, wheel base...), DTC information and driver preferences. I dumped the CAN traffic for the FORScan diagnostic tool to see how it requests this information from the ECUs.
FORScan communication with IPMA (camera)
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': '0200'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'TESTER_PRESENT', 'hex': '00'}
{'addr': 1806, 'type': 'positive_response', 'service': 'TESTER_PRESENT', 'hex': '00'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f190'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de00'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de00020799dbaa10296516a440000000000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f113'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1\x13JX7T-19H406-CH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1134a5837542d3139483430362d434800000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f188'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1\x88JX7T-14F397-AH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1884a5837542d3134463339372d414800000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f120'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1 JX7T-14F397-BF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1204a5837542d3134463339372d424600000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f121'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f124'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1$JX7T-14F398-AG\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1244a5837542d3134463339382d414700000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f125'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1%JX7T-14F398-BF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1254a5837542d3134463339382d424600000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f126'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f10a'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f111'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1\x11JX7T-14F403-CA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1114a5837542d3134463430332d434100000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f18c'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1\x8c182762191\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f18c31383237363231393100000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f162'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f110'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1\x10DS-JX7T-19H406-AD\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f11044532d4a5837542d3139483430362d414400000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': '0202'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'd100'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'd10001'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'd700'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'd70001010101'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'd701'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'd70101020000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'dd01'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'dd010102f8'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f113'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1\x13JX7T-19H406-CH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1134a5837542d3139483430362d434800000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'fd08'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'fd0800000500500100300000000000000000000000300000000000000000200100400300100200001200f00300500000000000000300c00b00400200000000000000000000000000000000200f01201e01501400a00200200400700d02501d01700700e06405005e05503401100a000000002002002001000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'fd09'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'fd09ffec0001fef60002'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de00'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de00020799dbaa10296516a440000000000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DTC_INFORMATION', 'hex': '028f'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DTC_INFORMATION', 'hex': '02ff50019768c253002cc401862cc418862c'}
... skip DTC requests ...
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de00'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de00020799dbaa10296516a440000000000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de01'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de01fd5616db5fffff557fe1f842080000000800000008000000080000000819bfe00f7c00000000000000000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de02'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de02800000008000000080000000800000008337fc00800000008000000080000000800000008337fc0000000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de03'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de03fffc26c3800000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de04'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de04546a8c0000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de05'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de06'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de07'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de08'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de09'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de0a'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de0b'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de0c'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de0d'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de0e'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
Using UDS service `READ_DATA_BY_IDENTIFIER`, we can read the As-Built blocks from `0xDExx` with no diagnostic session/security access necessary. I used [Online As-Built databases](https://cyanlabs.net/asbuilt-db/) and various coding spreadsheets shared online to find values we might be interested in using for fingerprinting (both vehicle parameters and identifying the platform). ABS: - Payload tier (Base, Mid Payload Upgrade, Heavy Duty Payload Upgrade...) - Wheelbase - Steering ratio - Cruise Control Mode (Normal, Adaptive) - Enable Stop and Go PSCM: - Enable Lane Keeping Aid - Enable Traffic Jam Assist - Enable Lane Centering Assist IPMA (Q4): - Steering ratio - Wheelbase APIM (Sync 3 and Sync 4): - Steering ratio - Vehicle weight - Wheelbase There are more potentially useful signals which I haven't included although they might not be necessary: - Vehicle (Ford platform code, like "C344" or "C519" - although the source of the mapping from index to code is FORScan and not Ford themselves unless we can find a better source). - Fuel type - Vehicle length/height/front track/rear track - Tire circumference (could be useful for converting wheel speed rad/s to m/s) - Steering angle source (Pinion, Wheel) - Country code (letters, e.g. US, CA or UK) - Transmission type - CAN network architecture - More feature flags (the APIM also stores settings for ACC, LCA, BLIS) The full list of settings I have found is [here](https://github.com/incognitojam/op-notebooks/blob/main/ford/settings.py). * FwQueryConfig: add data_requests * add car_data to CarInterface get_params * Revert "add car_data to CarInterface get_params" This reverts commit aa161a6b82082705db97bea2c4317e1888a74845. * test_ford: add APIM ecu address * Revert "FwQueryConfig: add data_requests" This reverts commit dc5484a9b80be5bc61a7fdf55560b8813bc43ef7. * fix block numbers and add extra queries * bump test_fw_query_timing * add missing query whitelists * simplify asbuilt requests * use forscan block ids * formatting --------- Co-authored-by: Shane Smiskol --- selfdrive/car/ford/tests/test_ford.py | 1 + selfdrive/car/ford/values.py | 46 ++++++++++++++++++++-- selfdrive/car/tests/test_fw_fingerprint.py | 6 +-- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/selfdrive/car/ford/tests/test_ford.py b/selfdrive/car/ford/tests/test_ford.py index fb5d07f4bfd44f..2ad3f5db1b9374 100755 --- a/selfdrive/car/ford/tests/test_ford.py +++ b/selfdrive/car/ford/tests/test_ford.py @@ -19,6 +19,7 @@ Ecu.fwdCamera: 0x706, # Image Processing Module A (IPMA) Ecu.engine: 0x7E0, # Powertrain Control Module (PCM) Ecu.shiftByWire: 0x732, # Gear Shift Module (GSM) + Ecu.debug: 0x7D0, # Accessory Protocol Interface Module (APIM) } diff --git a/selfdrive/car/ford/values.py b/selfdrive/car/ford/values.py index caa3eb0d379899..df3201c85354d8 100644 --- a/selfdrive/car/ford/values.py +++ b/selfdrive/car/ford/values.py @@ -1,11 +1,12 @@ from dataclasses import dataclass, field from enum import Enum +import panda.python.uds as uds from cereal import car from openpilot.selfdrive.car import AngleRateLimit, CarSpecs, dbc_dict, DbcDict, PlatformConfig, Platforms from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarHarness, CarInfo, CarParts, Column, \ Device -from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries +from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries, p16 Ecu = car.CarParams.Ecu @@ -140,6 +141,33 @@ class CAR(Platforms): CANFD_CAR = {CAR.F_150_MK14, CAR.F_150_LIGHTNING_MK1, CAR.MUSTANG_MACH_E_MK1} +DATA_IDENTIFIER_FORD_ASBUILT = 0xDE + +ASBUILT_BLOCKS: list[tuple[int, list]] = [ + (1, [Ecu.debug, Ecu.fwdCamera, Ecu.eps]), + (2, [Ecu.abs, Ecu.debug, Ecu.eps]), + (3, [Ecu.abs, Ecu.debug, Ecu.eps]), + (4, [Ecu.debug, Ecu.fwdCamera]), + (5, [Ecu.debug]), + (6, [Ecu.debug]), + (7, [Ecu.debug]), + (8, [Ecu.debug]), + (9, [Ecu.debug]), + (16, [Ecu.debug, Ecu.fwdCamera]), + (18, [Ecu.fwdCamera]), + (20, [Ecu.fwdCamera]), + (21, [Ecu.fwdCamera]), +] + + +def ford_asbuilt_block_request(block_id: int): + return bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + p16(DATA_IDENTIFIER_FORD_ASBUILT + block_id - 1) + + +def ford_asbuilt_block_response(block_id: int): + return bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + p16(DATA_IDENTIFIER_FORD_ASBUILT + block_id - 1) + + FW_QUERY_CONFIG = FwQueryConfig( requests=[ # CAN and CAN FD queries are combined. @@ -147,19 +175,29 @@ class CAR(Platforms): Request( [StdQueries.TESTER_PRESENT_REQUEST, StdQueries.MANUFACTURER_SOFTWARE_VERSION_REQUEST], [StdQueries.TESTER_PRESENT_RESPONSE, StdQueries.MANUFACTURER_SOFTWARE_VERSION_RESPONSE], + whitelist_ecus=[Ecu.abs, Ecu.debug, Ecu.engine, Ecu.eps, Ecu.fwdCamera, Ecu.fwdRadar, Ecu.shiftByWire], logging=True, ), Request( [StdQueries.TESTER_PRESENT_REQUEST, StdQueries.MANUFACTURER_SOFTWARE_VERSION_REQUEST], [StdQueries.TESTER_PRESENT_RESPONSE, StdQueries.MANUFACTURER_SOFTWARE_VERSION_RESPONSE], + whitelist_ecus=[Ecu.abs, Ecu.debug, Ecu.engine, Ecu.eps, Ecu.fwdCamera, Ecu.fwdRadar, Ecu.shiftByWire], bus=0, auxiliary=True, ), + *[Request( + [StdQueries.TESTER_PRESENT_REQUEST, ford_asbuilt_block_request(block_id)], + [StdQueries.TESTER_PRESENT_RESPONSE, ford_asbuilt_block_response(block_id)], + whitelist_ecus=ecus, + bus=0, + logging=True, + ) for block_id, ecus in ASBUILT_BLOCKS], ], extra_ecus=[ - # We are unlikely to get a response from the PCM from behind the gateway - (Ecu.engine, 0x7e0, None), - (Ecu.shiftByWire, 0x732, None), + (Ecu.engine, 0x7e0, None), # Powertrain Control Module + # Note: We are unlikely to get a response from behind the gateway + (Ecu.shiftByWire, 0x732, None), # Gear Shift Module + (Ecu.debug, 0x7d0, None), # Accessory Protocol Interface Module ], ) diff --git a/selfdrive/car/tests/test_fw_fingerprint.py b/selfdrive/car/tests/test_fw_fingerprint.py index 1a745b4447eef4..88c7225f2258ea 100755 --- a/selfdrive/car/tests/test_fw_fingerprint.py +++ b/selfdrive/car/tests/test_fw_fingerprint.py @@ -263,13 +263,13 @@ def fake_get_ecu_addrs(*_, timeout): print(f'get_vin {name} case, query time={self.total_time / self.N} seconds') def test_fw_query_timing(self): - total_ref_time = {1: 6.5, 2: 7.4} + total_ref_time = {1: 7.8, 2: 8.7} brand_ref_times = { 1: { 'gm': 0.5, 'body': 0.1, 'chrysler': 0.3, - 'ford': 0.2, + 'ford': 1.5, 'honda': 0.55, 'hyundai': 1.05, 'mazda': 0.1, @@ -280,7 +280,7 @@ def test_fw_query_timing(self): 'volkswagen': 0.65, }, 2: { - 'ford': 0.3, + 'ford': 1.6, 'hyundai': 1.85, } } From 3978e7e98caef295ea60277bc7994e77b38823f3 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 27 Feb 2024 06:40:46 -0600 Subject: [PATCH 23/41] [bot] Fingerprints: add missing FW versions from new users (#31572) * Export fingerprints * get these FP in --- selfdrive/car/toyota/fingerprints.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/selfdrive/car/toyota/fingerprints.py b/selfdrive/car/toyota/fingerprints.py index 12a1d46aaf540d..6b48408a108b0d 100644 --- a/selfdrive/car/toyota/fingerprints.py +++ b/selfdrive/car/toyota/fingerprints.py @@ -573,6 +573,7 @@ b'\x018821F6201400\x00\x00\x00\x00', ], (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F12010C0\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', b'\x028646F12010D0\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', b'\x028646F1201100\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', b'\x028646F1201200\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', @@ -843,6 +844,7 @@ b'8965B47023\x00\x00\x00\x00\x00\x00', b'8965B47050\x00\x00\x00\x00\x00\x00', b'8965B47060\x00\x00\x00\x00\x00\x00', + b'8965B47070\x00\x00\x00\x00\x00\x00', ], (Ecu.abs, 0x7b0, None): [ b'F152647290\x00\x00\x00\x00\x00\x00', @@ -1024,6 +1026,7 @@ b'\x02896634A13000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'\x02896634A13001\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', b'\x02896634A13101\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', + b'\x02896634A13201\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', b'\x02896634A14001\x00\x00\x00\x00897CF1203001\x00\x00\x00\x00', b'\x02896634A14001\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', b'\x02896634A14101\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', From d3f0f76a7e33832bb7312597f85b802b50f2d757 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Tue, 27 Feb 2024 13:16:06 -0500 Subject: [PATCH 24/41] Nissan: move to platform config (#31599) * do nissan * cleanup + fix --- selfdrive/car/__init__.py | 5 ++- selfdrive/car/nissan/interface.py | 14 +------ selfdrive/car/nissan/values.py | 68 +++++++++++++++++++------------ 3 files changed, 46 insertions(+), 41 deletions(-) diff --git a/selfdrive/car/__init__.py b/selfdrive/car/__init__.py index 3b749101c9d29a..297dc582f7cf1a 100644 --- a/selfdrive/car/__init__.py +++ b/selfdrive/car/__init__.py @@ -1,6 +1,6 @@ # functions common among cars from collections import namedtuple -from dataclasses import dataclass, field +from dataclasses import dataclass, field, replace from enum import ReprEnum import capnp @@ -267,6 +267,9 @@ class PlatformConfig: def __hash__(self) -> int: return hash(self.platform_str) + def override(self, **kwargs): + return replace(self, **kwargs) + class Platforms(str, ReprEnum): config: PlatformConfig diff --git a/selfdrive/car/nissan/interface.py b/selfdrive/car/nissan/interface.py index aedcaa18876e27..a94b97de200c3e 100644 --- a/selfdrive/car/nissan/interface.py +++ b/selfdrive/car/nissan/interface.py @@ -16,25 +16,13 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): ret.steerLimitTimer = 1.0 ret.steerActuatorDelay = 0.1 - ret.steerRatio = 17 ret.steerControlType = car.CarParams.SteerControlType.angle ret.radarUnavailable = True - if candidate in (CAR.ROGUE, CAR.XTRAIL): - ret.mass = 1610 - ret.wheelbase = 2.705 - ret.centerToFront = ret.wheelbase * 0.44 - elif candidate in (CAR.LEAF, CAR.LEAF_IC): - ret.mass = 1610 - ret.wheelbase = 2.705 - ret.centerToFront = ret.wheelbase * 0.44 - elif candidate == CAR.ALTIMA: + if candidate == CAR.ALTIMA: # Altima has EPS on C-CAN unlike the others that have it on V-CAN ret.safetyConfigs[0].safetyParam |= Panda.FLAG_NISSAN_ALT_EPS_BUS - ret.mass = 1492 - ret.wheelbase = 2.824 - ret.centerToFront = ret.wheelbase * 0.44 return ret diff --git a/selfdrive/car/nissan/values.py b/selfdrive/car/nissan/values.py index c0308f9e0db49c..58e4eb051a4431 100644 --- a/selfdrive/car/nissan/values.py +++ b/selfdrive/car/nissan/values.py @@ -1,9 +1,8 @@ from dataclasses import dataclass, field -from enum import StrEnum from cereal import car from panda.python import uds -from openpilot.selfdrive.car import AngleRateLimit, dbc_dict +from openpilot.selfdrive.car import AngleRateLimit, CarSpecs, DbcDict, PlatformConfig, Platforms, dbc_dict from openpilot.selfdrive.car.docs_definitions import CarInfo, CarHarness, CarParts from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries @@ -20,29 +19,52 @@ def __init__(self, CP): pass -class CAR(StrEnum): - XTRAIL = "NISSAN X-TRAIL 2017" - LEAF = "NISSAN LEAF 2018" - # Leaf with ADAS ECU found behind instrument cluster instead of glovebox - # Currently the only known difference between them is the inverted seatbelt signal. - LEAF_IC = "NISSAN LEAF 2018 Instrument Cluster" - ROGUE = "NISSAN ROGUE 2019" - ALTIMA = "NISSAN ALTIMA 2020" - - @dataclass class NissanCarInfo(CarInfo): package: str = "ProPILOT Assist" car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.nissan_a])) -CAR_INFO: dict[str, NissanCarInfo | list[NissanCarInfo] | None] = { - CAR.XTRAIL: NissanCarInfo("Nissan X-Trail 2017"), - CAR.LEAF: NissanCarInfo("Nissan Leaf 2018-23", video_link="https://youtu.be/vaMbtAh_0cY"), - CAR.LEAF_IC: None, # same platforms - CAR.ROGUE: NissanCarInfo("Nissan Rogue 2018-20"), - CAR.ALTIMA: NissanCarInfo("Nissan Altima 2019-20", car_parts=CarParts.common([CarHarness.nissan_b])), -} +@dataclass(frozen=True) +class NissanCarSpecs(CarSpecs): + centerToFrontRatio: float = 0.44 + steerRatio: float = 17. + + +@dataclass(frozen=True) +class NissanPlaformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('nissan_x_trail_2017_generated', None)) + + +class CAR(Platforms): + XTRAIL = NissanPlaformConfig( + "NISSAN X-TRAIL 2017", + NissanCarInfo("Nissan X-Trail 2017"), + specs=NissanCarSpecs(mass=1610, wheelbase=2.705) + ) + LEAF = NissanPlaformConfig( + "NISSAN LEAF 2018", + NissanCarInfo("Nissan Leaf 2018-23", video_link="https://youtu.be/vaMbtAh_0cY"), + dbc_dict=dbc_dict('nissan_leaf_2018_generated', None), + specs=NissanCarSpecs(mass=1610, wheelbase=2.705) + ) + # Leaf with ADAS ECU found behind instrument cluster instead of glovebox + # Currently the only known difference between them is the inverted seatbelt signal. + LEAF_IC = LEAF.override(platform_str="NISSAN LEAF 2018 Instrument Cluster", car_info=None) + ROGUE = NissanPlaformConfig( + "NISSAN ROGUE 2019", + NissanCarInfo("Nissan Rogue 2018-20"), + specs=NissanCarSpecs(mass=1610, wheelbase=2.705) + ) + ALTIMA = NissanPlaformConfig( + "NISSAN ALTIMA 2020", + NissanCarInfo("Nissan Altima 2019-20", car_parts=CarParts.common([CarHarness.nissan_b])), + specs=NissanCarSpecs(mass=1492, wheelbase=2.824) + ) + + +CAR_INFO = CAR.create_carinfo_map() +DBC = CAR.create_dbc_map() # Default diagnostic session NISSAN_DIAGNOSTIC_REQUEST_KWP = bytes([uds.SERVICE_TYPE.DIAGNOSTIC_SESSION_CONTROL, 0x81]) @@ -88,11 +110,3 @@ class NissanCarInfo(CarInfo): ), ]], ) - -DBC = { - CAR.XTRAIL: dbc_dict('nissan_x_trail_2017_generated', None), - CAR.LEAF: dbc_dict('nissan_leaf_2018_generated', None), - CAR.LEAF_IC: dbc_dict('nissan_leaf_2018_generated', None), - CAR.ROGUE: dbc_dict('nissan_x_trail_2017_generated', None), - CAR.ALTIMA: dbc_dict('nissan_x_trail_2017_generated', None), -} From 666c41d96923b1826f34a971b568f7d7754b4070 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Tue, 27 Feb 2024 13:16:22 -0500 Subject: [PATCH 25/41] Chrylser: move to platform config (#31600) * do chrysler * chrysler specs * cleanup Co-authored-by: Shane Smiskol --------- Co-authored-by: Shane Smiskol --- selfdrive/car/chrysler/interface.py | 12 --- selfdrive/car/chrysler/values.py | 131 +++++++++++++++++----------- 2 files changed, 79 insertions(+), 64 deletions(-) diff --git a/selfdrive/car/chrysler/interface.py b/selfdrive/car/chrysler/interface.py index 32a4f5dfcfdcc0..34df32762dfdf4 100755 --- a/selfdrive/car/chrysler/interface.py +++ b/selfdrive/car/chrysler/interface.py @@ -24,7 +24,6 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): elif candidate in RAM_DT: ret.safetyConfigs[0].safetyParam |= Panda.FLAG_CHRYSLER_RAM_DT - ret.minSteerSpeed = 3.8 # m/s CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) if candidate not in RAM_CARS: # Newer FW versions standard on the following platforms, or flashed by a dealer onto older platforms have a higher minimum steering speed. @@ -35,10 +34,6 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): # Chrysler if candidate in (CAR.PACIFICA_2017_HYBRID, CAR.PACIFICA_2018, CAR.PACIFICA_2018_HYBRID, CAR.PACIFICA_2019_HYBRID, CAR.PACIFICA_2020, CAR.DODGE_DURANGO): - ret.mass = 2242. - ret.wheelbase = 3.089 - ret.steerRatio = 16.2 # Pacifica Hybrid 2017 - ret.lateralTuning.init('pid') ret.lateralTuning.pid.kpBP, ret.lateralTuning.pid.kiBP = [[9., 20.], [9., 20.]] ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.15, 0.30], [0.03, 0.05]] @@ -46,9 +41,6 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): # Jeep elif candidate in (CAR.JEEP_GRAND_CHEROKEE, CAR.JEEP_GRAND_CHEROKEE_2019): - ret.mass = 1778 - ret.wheelbase = 2.71 - ret.steerRatio = 16.7 ret.steerActuatorDelay = 0.2 ret.lateralTuning.init('pid') @@ -60,9 +52,6 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): elif candidate == CAR.RAM_1500: ret.steerActuatorDelay = 0.2 ret.wheelbase = 3.88 - ret.steerRatio = 16.3 - ret.mass = 2493. - ret.minSteerSpeed = 14.5 # Older EPS FW allow steer to zero if any(fw.ecu == 'eps' and b"68" < fw.fwVersion[:4] <= b"6831" for fw in car_fw): ret.minSteerSpeed = 0. @@ -72,7 +61,6 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): ret.wheelbase = 3.785 ret.steerRatio = 15.61 ret.mass = 3405. - ret.minSteerSpeed = 16 CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning, 1.0, False) else: diff --git a/selfdrive/car/chrysler/values.py b/selfdrive/car/chrysler/values.py index a7eec8fe5ae0be..a94512608a7eaf 100644 --- a/selfdrive/car/chrysler/values.py +++ b/selfdrive/car/chrysler/values.py @@ -1,9 +1,9 @@ -from enum import IntFlag, StrEnum +from enum import IntFlag from dataclasses import dataclass, field from cereal import car from panda.python import uds -from openpilot.selfdrive.car import dbc_dict +from openpilot.selfdrive.car import CarSpecs, DbcDict, PlatformConfig, Platforms, dbc_dict from openpilot.selfdrive.car.docs_definitions import CarHarness, CarInfo, CarParts from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, p16 @@ -13,25 +13,89 @@ class ChryslerFlags(IntFlag): HIGHER_MIN_STEERING_SPEED = 1 +@dataclass +class ChryslerCarInfo(CarInfo): + package: str = "Adaptive Cruise Control (ACC)" + car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.fca])) + + +@dataclass +class ChryslerPlatformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('chrysler_pacifica_2017_hybrid_generated', None)) + + +@dataclass +class ChryslerCarSpecs(CarSpecs): + minSteerSpeed: float = 3.8 # m/s + -class CAR(StrEnum): +class CAR(Platforms): # Chrysler - PACIFICA_2017_HYBRID = "CHRYSLER PACIFICA HYBRID 2017" - PACIFICA_2018_HYBRID = "CHRYSLER PACIFICA HYBRID 2018" - PACIFICA_2019_HYBRID = "CHRYSLER PACIFICA HYBRID 2019" - PACIFICA_2018 = "CHRYSLER PACIFICA 2018" - PACIFICA_2020 = "CHRYSLER PACIFICA 2020" + PACIFICA_2017_HYBRID = ChryslerPlatformConfig( + "CHRYSLER PACIFICA HYBRID 2017", + ChryslerCarInfo("Chrysler Pacifica Hybrid 2017"), + specs=ChryslerCarSpecs(mass=2242., wheelbase=3.089, steerRatio=16.2), + ) + PACIFICA_2018_HYBRID = ChryslerPlatformConfig( + "CHRYSLER PACIFICA HYBRID 2018", + ChryslerCarInfo("Chrysler Pacifica Hybrid 2018"), + specs=PACIFICA_2017_HYBRID.specs, + ) + PACIFICA_2019_HYBRID = ChryslerPlatformConfig( + "CHRYSLER PACIFICA HYBRID 2019", + ChryslerCarInfo("Chrysler Pacifica Hybrid 2019-23"), + specs=PACIFICA_2017_HYBRID.specs, + ) + PACIFICA_2018 = ChryslerPlatformConfig( + "CHRYSLER PACIFICA 2018", + ChryslerCarInfo("Chrysler Pacifica 2017-18"), + specs=PACIFICA_2017_HYBRID.specs, + ) + PACIFICA_2020 = ChryslerPlatformConfig( + "CHRYSLER PACIFICA 2020", + [ + ChryslerCarInfo("Chrysler Pacifica 2019-20"), + ChryslerCarInfo("Chrysler Pacifica 2021-23", package="All"), + ], + specs=PACIFICA_2017_HYBRID.specs, + ) # Dodge - DODGE_DURANGO = "DODGE DURANGO 2021" + DODGE_DURANGO = ChryslerPlatformConfig( + "DODGE DURANGO 2021", + ChryslerCarInfo("Dodge Durango 2020-21"), + specs=PACIFICA_2017_HYBRID.specs, + ) # Jeep - JEEP_GRAND_CHEROKEE = "JEEP GRAND CHEROKEE V6 2018" # includes 2017 Trailhawk - JEEP_GRAND_CHEROKEE_2019 = "JEEP GRAND CHEROKEE 2019" # includes 2020 Trailhawk + JEEP_GRAND_CHEROKEE = ChryslerPlatformConfig( # includes 2017 Trailhawk + "JEEP GRAND CHEROKEE V6 2018", + ChryslerCarInfo("Jeep Grand Cherokee 2016-18", video_link="https://www.youtube.com/watch?v=eLR9o2JkuRk"), + specs=ChryslerCarSpecs(mass=1778., wheelbase=2.71, steerRatio=16.7), + ) + + JEEP_GRAND_CHEROKEE_2019 = ChryslerPlatformConfig( # includes 2020 Trailhawk + "JEEP GRAND CHEROKEE 2019", + ChryslerCarInfo("Jeep Grand Cherokee 2019-21", video_link="https://www.youtube.com/watch?v=jBe4lWnRSu4"), + specs=JEEP_GRAND_CHEROKEE.specs, + ) # Ram - RAM_1500 = "RAM 1500 5TH GEN" - RAM_HD = "RAM HD 5TH GEN" + RAM_1500 = ChryslerPlatformConfig( + "RAM 1500 5TH GEN", + ChryslerCarInfo("Ram 1500 2019-24", car_parts=CarParts.common([CarHarness.ram])), + dbc_dict('chrysler_ram_dt_generated', None), + specs=ChryslerCarSpecs(mass=2493., wheelbase=3.88, steerRatio=16.3, minSteerSpeed=14.5), + ) + RAM_HD = ChryslerPlatformConfig( + "RAM HD 5TH GEN", + [ + ChryslerCarInfo("Ram 2500 2020-24", car_parts=CarParts.common([CarHarness.ram])), + ChryslerCarInfo("Ram 3500 2019-22", car_parts=CarParts.common([CarHarness.ram])), + ], + dbc_dict('chrysler_ram_hd_generated', None), + specs=ChryslerCarSpecs(mass=3405., wheelbase=3.785, steerRatio=15.61, minSteerSpeed=16.), + ) class CarControllerParams: @@ -59,32 +123,6 @@ def __init__(self, CP): RAM_CARS = RAM_DT | RAM_HD -@dataclass -class ChryslerCarInfo(CarInfo): - package: str = "Adaptive Cruise Control (ACC)" - car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.fca])) - - -CAR_INFO: dict[str, ChryslerCarInfo | list[ChryslerCarInfo] | None] = { - CAR.PACIFICA_2017_HYBRID: ChryslerCarInfo("Chrysler Pacifica Hybrid 2017"), - CAR.PACIFICA_2018_HYBRID: ChryslerCarInfo("Chrysler Pacifica Hybrid 2018"), - CAR.PACIFICA_2019_HYBRID: ChryslerCarInfo("Chrysler Pacifica Hybrid 2019-23"), - CAR.PACIFICA_2018: ChryslerCarInfo("Chrysler Pacifica 2017-18"), - CAR.PACIFICA_2020: [ - ChryslerCarInfo("Chrysler Pacifica 2019-20"), - ChryslerCarInfo("Chrysler Pacifica 2021-23", package="All"), - ], - CAR.JEEP_GRAND_CHEROKEE: ChryslerCarInfo("Jeep Grand Cherokee 2016-18", video_link="https://www.youtube.com/watch?v=eLR9o2JkuRk"), - CAR.JEEP_GRAND_CHEROKEE_2019: ChryslerCarInfo("Jeep Grand Cherokee 2019-21", video_link="https://www.youtube.com/watch?v=jBe4lWnRSu4"), - CAR.DODGE_DURANGO: ChryslerCarInfo("Dodge Durango 2020-21"), - CAR.RAM_1500: ChryslerCarInfo("Ram 1500 2019-24", car_parts=CarParts.common([CarHarness.ram])), - CAR.RAM_HD: [ - ChryslerCarInfo("Ram 2500 2020-24", car_parts=CarParts.common([CarHarness.ram])), - ChryslerCarInfo("Ram 3500 2019-22", car_parts=CarParts.common([CarHarness.ram])), - ], -} - - CHRYSLER_VERSION_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ p16(0xf132) CHRYSLER_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + \ @@ -124,16 +162,5 @@ class ChryslerCarInfo(CarInfo): ], ) - -DBC = { - CAR.PACIFICA_2017_HYBRID: dbc_dict('chrysler_pacifica_2017_hybrid_generated', 'chrysler_pacifica_2017_hybrid_private_fusion'), - CAR.PACIFICA_2018: dbc_dict('chrysler_pacifica_2017_hybrid_generated', 'chrysler_pacifica_2017_hybrid_private_fusion'), - CAR.PACIFICA_2020: dbc_dict('chrysler_pacifica_2017_hybrid_generated', 'chrysler_pacifica_2017_hybrid_private_fusion'), - CAR.PACIFICA_2018_HYBRID: dbc_dict('chrysler_pacifica_2017_hybrid_generated', 'chrysler_pacifica_2017_hybrid_private_fusion'), - CAR.PACIFICA_2019_HYBRID: dbc_dict('chrysler_pacifica_2017_hybrid_generated', 'chrysler_pacifica_2017_hybrid_private_fusion'), - CAR.DODGE_DURANGO: dbc_dict('chrysler_pacifica_2017_hybrid_generated', 'chrysler_pacifica_2017_hybrid_private_fusion'), - CAR.JEEP_GRAND_CHEROKEE: dbc_dict('chrysler_pacifica_2017_hybrid_generated', 'chrysler_pacifica_2017_hybrid_private_fusion'), - CAR.JEEP_GRAND_CHEROKEE_2019: dbc_dict('chrysler_pacifica_2017_hybrid_generated', 'chrysler_pacifica_2017_hybrid_private_fusion'), - CAR.RAM_1500: dbc_dict('chrysler_ram_dt_generated', None), - CAR.RAM_HD: dbc_dict('chrysler_ram_hd_generated', None), -} +CAR_INFO = CAR.create_carinfo_map() +DBC = CAR.create_dbc_map() From d457ed9d50801905b762c870c4799e734dea05b1 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Tue, 27 Feb 2024 13:23:13 -0500 Subject: [PATCH 26/41] chrysler: freeze dataclass + remove more from interface (#31613) * fix * fix --- selfdrive/car/chrysler/interface.py | 3 --- selfdrive/car/chrysler/values.py | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/selfdrive/car/chrysler/interface.py b/selfdrive/car/chrysler/interface.py index 34df32762dfdf4..eb40bc6f6ef0a3 100755 --- a/selfdrive/car/chrysler/interface.py +++ b/selfdrive/car/chrysler/interface.py @@ -58,9 +58,6 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): elif candidate == CAR.RAM_HD: ret.steerActuatorDelay = 0.2 - ret.wheelbase = 3.785 - ret.steerRatio = 15.61 - ret.mass = 3405. CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning, 1.0, False) else: diff --git a/selfdrive/car/chrysler/values.py b/selfdrive/car/chrysler/values.py index a94512608a7eaf..1cc51753d4d319 100644 --- a/selfdrive/car/chrysler/values.py +++ b/selfdrive/car/chrysler/values.py @@ -19,12 +19,12 @@ class ChryslerCarInfo(CarInfo): car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.fca])) -@dataclass +@dataclass(frozen=True) class ChryslerPlatformConfig(PlatformConfig): dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('chrysler_pacifica_2017_hybrid_generated', None)) -@dataclass +@dataclass(frozen=True) class ChryslerCarSpecs(CarSpecs): minSteerSpeed: float = 3.8 # m/s From 0e41bf34746854869ad0d319fbb6bb765288ce50 Mon Sep 17 00:00:00 2001 From: Cameron Clough Date: Tue, 27 Feb 2024 18:59:27 +0000 Subject: [PATCH 27/41] Ford: fix As-Built request identifier (#31609) Should be 0xDE00 not 0xDE --- selfdrive/car/ford/values.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/car/ford/values.py b/selfdrive/car/ford/values.py index df3201c85354d8..1008d68b986152 100644 --- a/selfdrive/car/ford/values.py +++ b/selfdrive/car/ford/values.py @@ -141,7 +141,7 @@ class CAR(Platforms): CANFD_CAR = {CAR.F_150_MK14, CAR.F_150_LIGHTNING_MK1, CAR.MUSTANG_MACH_E_MK1} -DATA_IDENTIFIER_FORD_ASBUILT = 0xDE +DATA_IDENTIFIER_FORD_ASBUILT = 0xDE00 ASBUILT_BLOCKS: list[tuple[int, list]] = [ (1, [Ecu.debug, Ecu.fwdCamera, Ecu.eps]), From 402ac424d90f7b66dfe100b4073a43bf13570081 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Tue, 27 Feb 2024 11:09:48 -0800 Subject: [PATCH 28/41] auto PR comments (#30675) * auto PR comments * little more * test * update action * cleanup --- .github/workflows/auto_pr_review.yaml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/auto_pr_review.yaml b/.github/workflows/auto_pr_review.yaml index abb6c38d6be010..de07ed118ffb1a 100644 --- a/.github/workflows/auto_pr_review.yaml +++ b/.github/workflows/auto_pr_review.yaml @@ -34,6 +34,23 @@ jobs: already-exists-action: close_this already-exists-comment: "Your PR should be made against the `master` branch" + comment: + runs-on: ubuntu-latest + steps: + - name: comment + uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 + with: + message: | + Thanks for contributing to openpilot! In order for us to review your PR as quickly as possible, check the following: + * Convert your PR to a draft unless it's ready to review + * Read the [contributing docs](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md) + * Before marking as "ready for review", ensure: + * the goal is clearly stated in the description + * all the tests are passing + * the change is [something we merge](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md#what-gets-merged) + * include a route or your device' dongle ID if relevant + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + check-pr-template: runs-on: ubuntu-latest permissions: @@ -41,7 +58,7 @@ jobs: issues: write pull-requests: write actions: read - if: github.event.pull_request.head.repo.full_name != 'commaai/openpilot' + if: false && github.event.pull_request.head.repo.full_name != 'commaai/openpilot' steps: - uses: actions/github-script@v7 with: From dc3728134055bd422abac4f005e1ecbae46e6167 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Tue, 27 Feb 2024 14:55:19 -0500 Subject: [PATCH 29/41] typo (#31618) dataset --- docs/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 30f4e0dfd39e36..755ca82220fad3 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -62,4 +62,4 @@ A good pull request has all of the following: * Consider opting into driver camera uploads to improve the driver monitoring model. * Connect your device to Wi-Fi regularly, so that we can pull data for training better driving models. * Run the `nightly` branch and report issues. This branch is like `master` but it's built just like a release. -* Annotate images in the [comma10k dateset](https://github.com/commaai/comma10k). +* Annotate images in the [comma10k dataset](https://github.com/commaai/comma10k). From 47013fd0a4a322da39cbbdf6bd8129d49abb295d Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Tue, 27 Feb 2024 12:06:53 -0800 Subject: [PATCH 30/41] Revert "auto PR comments (#30675)" This reverts commit 402ac424d90f7b66dfe100b4073a43bf13570081. --- .github/workflows/auto_pr_review.yaml | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/.github/workflows/auto_pr_review.yaml b/.github/workflows/auto_pr_review.yaml index de07ed118ffb1a..abb6c38d6be010 100644 --- a/.github/workflows/auto_pr_review.yaml +++ b/.github/workflows/auto_pr_review.yaml @@ -34,23 +34,6 @@ jobs: already-exists-action: close_this already-exists-comment: "Your PR should be made against the `master` branch" - comment: - runs-on: ubuntu-latest - steps: - - name: comment - uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 - with: - message: | - Thanks for contributing to openpilot! In order for us to review your PR as quickly as possible, check the following: - * Convert your PR to a draft unless it's ready to review - * Read the [contributing docs](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md) - * Before marking as "ready for review", ensure: - * the goal is clearly stated in the description - * all the tests are passing - * the change is [something we merge](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md#what-gets-merged) - * include a route or your device' dongle ID if relevant - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - check-pr-template: runs-on: ubuntu-latest permissions: @@ -58,7 +41,7 @@ jobs: issues: write pull-requests: write actions: read - if: false && github.event.pull_request.head.repo.full_name != 'commaai/openpilot' + if: github.event.pull_request.head.repo.full_name != 'commaai/openpilot' steps: - uses: actions/github-script@v7 with: From f293f7bad4d6675b70a97d303f1321fb6cfc9182 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Tue, 27 Feb 2024 16:17:56 -0500 Subject: [PATCH 31/41] scons: move cereal library exports to cereal submodule (#31617) * cleanup-cereal * bump --- SConstruct | 9 --------- cereal | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/SConstruct b/SConstruct index b04e3903ed7648..4d4f9ad4fe2eb7 100644 --- a/SConstruct +++ b/SConstruct @@ -96,8 +96,6 @@ lenv = { rpath = lenv["LD_LIBRARY_PATH"].copy() if arch == "larch64": - lenv["LD_LIBRARY_PATH"] += ['/data/data/com.termux/files/usr/lib'] - cpppath = [ "#third_party/opencl/include", ] @@ -360,13 +358,6 @@ Export('common', 'gpucommon') # Build cereal and messaging SConscript(['cereal/SConscript']) -cereal = [File('#cereal/libcereal.a')] -messaging = [File('#cereal/libmessaging.a')] -visionipc = [File('#cereal/libvisionipc.a')] -messaging_python = [File('#cereal/messaging/messaging_pyx.so')] - -Export('cereal', 'messaging', 'messaging_python', 'visionipc') - # Build other submodules SConscript([ 'body/board/SConscript', diff --git a/cereal b/cereal index a4255106b7255e..2012d9fd16f62c 160000 --- a/cereal +++ b/cereal @@ -1 +1 @@ -Subproject commit a4255106b7255e00ae04162f7aa14aa3cae339c3 +Subproject commit 2012d9fd16f62c737951ce2d1eb19d39f0c7615f From c05b37979d49c0a586b56db9294aa061c2c079e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harald=20Sch=C3=A4fer?= Date: Tue, 27 Feb 2024 13:23:04 -0800 Subject: [PATCH 32/41] Wheeled body (#31614) * Wheeled body * 100hz only for balance * No carparams in locationd no more * Update ref --- common/params.cc | 1 - selfdrive/car/body/carcontroller.py | 20 ++----------------- selfdrive/locationd/locationd.cc | 8 +++----- .../test/process_replay/process_replay.py | 2 +- selfdrive/test/process_replay/ref_commit | 2 +- 5 files changed, 7 insertions(+), 26 deletions(-) diff --git a/common/params.cc b/common/params.cc index eb75705ca3f6af..aef2cbdecd6c7c 100644 --- a/common/params.cc +++ b/common/params.cc @@ -207,7 +207,6 @@ std::unordered_map keys = { {"UpdaterLastFetchTime", PERSISTENT}, {"Version", PERSISTENT}, {"VisionRadarToggle", PERSISTENT}, - {"WheeledBody", PERSISTENT}, }; } // namespace diff --git a/selfdrive/car/body/carcontroller.py b/selfdrive/car/body/carcontroller.py index 1dad8e796a7854..d15f11d3a47394 100644 --- a/selfdrive/car/body/carcontroller.py +++ b/selfdrive/car/body/carcontroller.py @@ -1,6 +1,5 @@ import numpy as np -from openpilot.common.params import Params from openpilot.common.realtime import DT_CTRL from opendbc.can.packer import CANPacker from openpilot.selfdrive.car.body import bodycan @@ -20,18 +19,13 @@ def __init__(self, dbc_name, CP, VM): self.frame = 0 self.packer = CANPacker(dbc_name) - # Speed, balance and turn PIDs - self.speed_pid = PIDController(0.115, k_i=0.23, rate=1/DT_CTRL) - self.balance_pid = PIDController(1300, k_i=0, k_d=280, rate=1/DT_CTRL) + # PIDs self.turn_pid = PIDController(110, k_i=11.5, rate=1/DT_CTRL) self.wheeled_speed_pid = PIDController(110, k_i=11.5, rate=1/DT_CTRL) self.torque_r_filtered = 0. self.torque_l_filtered = 0. - params = Params() - self.wheeled_body = params.get("WheeledBody") - @staticmethod def deadband_filter(torque, deadband): if torque > 0: @@ -55,17 +49,7 @@ def update(self, CC, CS, now_nanos): speed_measured = SPEED_FROM_RPM * (CS.out.wheelSpeeds.fl + CS.out.wheelSpeeds.fr) / 2. speed_error = speed_desired - speed_measured - if self.wheeled_body is None: - freeze_integrator = ((speed_error < 0 and self.speed_pid.error_integral <= -MAX_POS_INTEGRATOR) or - (speed_error > 0 and self.speed_pid.error_integral >= MAX_POS_INTEGRATOR)) - angle_setpoint = self.speed_pid.update(speed_error, freeze_integrator=freeze_integrator) - - # Clip angle error, this is enough to get up from stands - angle_error = np.clip((-CC.orientationNED[1]) - angle_setpoint, -MAX_ANGLE_ERROR, MAX_ANGLE_ERROR) - angle_error_rate = np.clip(-CC.angularVelocity[1], -1., 1.) - torque = self.balance_pid.update(angle_error, error_rate=angle_error_rate) - else: - torque = self.wheeled_speed_pid.update(speed_error, freeze_integrator=False) + torque = self.wheeled_speed_pid.update(speed_error, freeze_integrator=False) speed_diff_measured = SPEED_FROM_RPM * (CS.out.wheelSpeeds.fl - CS.out.wheelSpeeds.fr) turn_error = speed_diff_measured - speed_diff_desired diff --git a/selfdrive/locationd/locationd.cc b/selfdrive/locationd/locationd.cc index e32ed78a3ef071..1050d68b9b268b 100644 --- a/selfdrive/locationd/locationd.cc +++ b/selfdrive/locationd/locationd.cc @@ -691,10 +691,9 @@ int Localizer::locationd_thread() { this->configure_gnss_source(source); const std::initializer_list service_list = {gps_location_socket, "cameraOdometry", "liveCalibration", - "carState", "carParams", "accelerometer", "gyroscope"}; + "carState", "accelerometer", "gyroscope"}; - // TODO: remove carParams once we're always sending at 100Hz - SubMaster sm(service_list, {}, nullptr, {gps_location_socket, "carParams"}); + SubMaster sm(service_list, {}, nullptr, {gps_location_socket}); PubMaster pm({"liveLocationKalman"}); uint64_t cnt = 0; @@ -718,8 +717,7 @@ int Localizer::locationd_thread() { filterInitialized = sm.allAliveAndValid(); } - // 100Hz publish for notcars, 20Hz for cars - const char* trigger_msg = sm["carParams"].getCarParams().getNotCar() ? "accelerometer" : "cameraOdometry"; + const char* trigger_msg = "cameraOdometry"; if (sm.updated(trigger_msg)) { bool inputsOK = sm.allValid() && this->are_inputs_ok(); bool gpsOK = this->is_gps_ok(); diff --git a/selfdrive/test/process_replay/process_replay.py b/selfdrive/test/process_replay/process_replay.py index 4fb3e3c4de0116..5119be0a8c487d 100755 --- a/selfdrive/test/process_replay/process_replay.py +++ b/selfdrive/test/process_replay/process_replay.py @@ -512,7 +512,7 @@ def locationd_config_pubsub_callback(params, cfg, lr): proc_name="locationd", pubs=[ "cameraOdometry", "accelerometer", "gyroscope", "gpsLocationExternal", - "liveCalibration", "carState", "carParams", "gpsLocation" + "liveCalibration", "carState", "gpsLocation" ], subs=["liveLocationKalman"], ignore=["logMonoTime"], diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index fc38f873104b34..9c627fb7c9aa38 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -d0cdea7eb15f3cac8a921f7ace3eaa6baebb4fd5 +47609e372bf616932c4dca74d2616c3d97fa2443 From 19db56b1f6a86a6a250e6b69f1533ae02d1fb367 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Tue, 27 Feb 2024 17:06:18 -0500 Subject: [PATCH 33/41] tici tests: remove pytest.main (#31622) pytest.main is bad! --- selfdrive/test/test_onroad.py | 2 +- system/hardware/tici/tests/test_hardware.py | 2 +- system/hardware/tici/tests/test_power_draw.py | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/selfdrive/test/test_onroad.py b/selfdrive/test/test_onroad.py index de8a4420b38c2a..8f8c93ecff1e2c 100755 --- a/selfdrive/test/test_onroad.py +++ b/selfdrive/test/test_onroad.py @@ -424,4 +424,4 @@ def test_engagable(self): if __name__ == "__main__": - pytest.main() + unittest.main() diff --git a/system/hardware/tici/tests/test_hardware.py b/system/hardware/tici/tests/test_hardware.py index 0c436595ee1bb5..6c41c383a049b6 100755 --- a/system/hardware/tici/tests/test_hardware.py +++ b/system/hardware/tici/tests/test_hardware.py @@ -25,4 +25,4 @@ def test_power_save_time(self): if __name__ == "__main__": - pytest.main() + unittest.main() diff --git a/system/hardware/tici/tests/test_power_draw.py b/system/hardware/tici/tests/test_power_draw.py index 352fcdf18a8b10..180ec155e49e16 100755 --- a/system/hardware/tici/tests/test_power_draw.py +++ b/system/hardware/tici/tests/test_power_draw.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 from collections import defaultdict, deque -import sys import pytest import unittest import time @@ -132,4 +131,4 @@ def test_camera_procs(self): if __name__ == "__main__": - pytest.main(sys.argv) + unittest.main() From 262b328ad706194425479b1a56af9321d1a0c97a Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Tue, 27 Feb 2024 17:17:01 -0500 Subject: [PATCH 34/41] ban pytest.main (#31623) ban it! --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index ac5bb0922ccb5b..99a8602460aadf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -190,6 +190,7 @@ lint.flake8-implicit-str-concat.allow-multiline=false "system".msg = "Use openpilot.system" "third_party".msg = "Use openpilot.third_party" "tools".msg = "Use openpilot.tools" +"pytest.main".msg = "pytest.main requires special handling that is easy to mess up!" [tool.coverage.run] concurrency = ["multiprocessing", "thread"] From 56e343b3f1e0117d379ad4582170d51609599530 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 27 Feb 2024 19:41:52 -0600 Subject: [PATCH 35/41] Honda Accord: label non-essential ECUs (#31624) * note non-essential ecus * do accordh --- selfdrive/car/honda/values.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/selfdrive/car/honda/values.py b/selfdrive/car/honda/values.py index a2ef757d150d2b..f573296609d690 100644 --- a/selfdrive/car/honda/values.py +++ b/selfdrive/car/honda/values.py @@ -207,6 +207,8 @@ def init_make(self, CP: car.CarParams): Ecu.combinationMeter: [CAR.CIVIC_BOSCH, CAR.CRV_5G], Ecu.gateway: [CAR.CIVIC_BOSCH, CAR.CRV_5G], Ecu.electricBrakeBooster: [CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.shiftByWire: [CAR.ACCORD], # existence correlates with transmission type for ICE + Ecu.hud: [CAR.ACCORD, CAR.ACCORDH], # existence correlates with trim level }, extra_ecus=[ # The only other ECU on PT bus accessible by camera on radarless Civic From ce6637cd8ffdd9eef39a57fe67c3528c55b11c68 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 27 Feb 2024 22:09:02 -0600 Subject: [PATCH 36/41] Honda Accord: allow fingerprinting without comma power (#31477) * Do Accord * add comment * good test * this catches the accord/accordh issue! * as expected, only if both radar&camera have in common FW does the test fail * cmt * clean up * better * Use HondaFlags * detect alt brake * for test * hypothesis isn't installed * test failure * works * Revert " works" This reverts commit bfc0d808abe548630e6507431f13b01e8a1316cb. * Revert "test failure" This reverts commit 10ab6eb63ccd411740751b742f31fd610397fe8e. * Revert "hypothesis isn't installed" This reverts commit d474cc3f0ed7e84fe8bd24f452b3315fd2b8d47c. * Revert "for test" This reverts commit 98e039f4fc0189ccb57c1dae6b344209ef15eb1c. * this is important too * clean up * merge accord fingerprints, test * remove duplicates * accordh doesn't have these * rm * no unknown * start over, merge platforms * add cmt * note non-essential ecus * add non essential obd ecus * combine FW * format fingerprints (remove dups) * migrate test models segs * cmt * Update ref_commit * clean up --- selfdrive/car/honda/carstate.py | 4 +- selfdrive/car/honda/fingerprints.py | 85 ++++++++---------------- selfdrive/car/honda/interface.py | 4 +- selfdrive/car/honda/values.py | 22 +++--- selfdrive/car/tests/routes.py | 4 +- selfdrive/car/tests/test_models_segs.txt | 4 +- selfdrive/car/torque_data/params.toml | 3 +- selfdrive/test/process_replay/ref_commit | 2 +- 8 files changed, 49 insertions(+), 79 deletions(-) diff --git a/selfdrive/car/honda/carstate.py b/selfdrive/car/honda/carstate.py index 9025f7239728c4..4f5337813be4d9 100644 --- a/selfdrive/car/honda/carstate.py +++ b/selfdrive/car/honda/carstate.py @@ -64,7 +64,7 @@ def get_can_messages(CP, gearbox_msg): messages.append(("CRUISE_PARAMS", 50)) # TODO: clean this up - if CP.carFingerprint in (CAR.ACCORD, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_HYBRID, CAR.INSIGHT, + if CP.carFingerprint in (CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_HYBRID, CAR.INSIGHT, CAR.ACURA_RDX_3G, CAR.HONDA_E, CAR.CIVIC_2022, CAR.HRV_3G): pass elif CP.carFingerprint in (CAR.ODYSSEY_CHN, CAR.FREED, CAR.HRV): @@ -129,7 +129,7 @@ def update(self, cp, cp_cam, cp_body): # panda checks if the signal is non-zero ret.standstill = cp.vl["ENGINE_DATA"]["XMISSION_SPEED"] < 1e-5 # TODO: find a common signal across all cars - if self.CP.carFingerprint in (CAR.ACCORD, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_HYBRID, CAR.INSIGHT, + if self.CP.carFingerprint in (CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_HYBRID, CAR.INSIGHT, CAR.ACURA_RDX_3G, CAR.HONDA_E, CAR.CIVIC_2022, CAR.HRV_3G): ret.doorOpen = bool(cp.vl["SCM_FEEDBACK"]["DRIVERS_DOOR_OPEN"]) elif self.CP.carFingerprint in (CAR.ODYSSEY_CHN, CAR.FREED, CAR.HRV): diff --git a/selfdrive/car/honda/fingerprints.py b/selfdrive/car/honda/fingerprints.py index 359ae83b157b7d..0ae39751f97f53 100644 --- a/selfdrive/car/honda/fingerprints.py +++ b/selfdrive/car/honda/fingerprints.py @@ -48,6 +48,7 @@ ], (Ecu.shiftByWire, 0x18da0bf1, None): [ b'54008-TVC-A910\x00\x00', + b'54008-TWA-A910\x00\x00', ], (Ecu.transmission, 0x18da1ef1, None): [ b'28101-6A7-A220\x00\x00', @@ -89,6 +90,12 @@ b'57114-TVA-C530\x00\x00', b'57114-TVA-E520\x00\x00', b'57114-TVE-H250\x00\x00', + b'57114-TWA-A040\x00\x00', + b'57114-TWA-A050\x00\x00', + b'57114-TWA-A530\x00\x00', + b'57114-TWA-B520\x00\x00', + b'57114-TWA-C510\x00\x00', + b'57114-TWB-H030\x00\x00', ], (Ecu.eps, 0x18da30f1, None): [ b'39990-TBX-H120\x00\x00', @@ -100,6 +107,7 @@ b'39990-TVA-X030\x00\x00', b'39990-TVA-X040\x00\x00', b'39990-TVE-H130\x00\x00', + b'39990-TWB-H120\x00\x00', ], (Ecu.srs, 0x18da53f1, None): [ b'77959-TBX-H230\x00\x00', @@ -108,6 +116,9 @@ b'77959-TVA-H230\x00\x00', b'77959-TVA-L420\x00\x00', b'77959-TVA-X330\x00\x00', + b'77959-TWA-A440\x00\x00', + b'77959-TWA-L420\x00\x00', + b'77959-TWB-H220\x00\x00', ], (Ecu.combinationMeter, 0x18da60f1, None): [ b'78109-TBX-H310\x00\x00', @@ -141,7 +152,19 @@ b'78109-TVC-M510\x00\x00', b'78109-TVC-YF10\x00\x00', b'78109-TVE-H610\x00\x00', + b'78109-TWA-A010\x00\x00', + b'78109-TWA-A020\x00\x00', + b'78109-TWA-A030\x00\x00', + b'78109-TWA-A110\x00\x00', + b'78109-TWA-A120\x00\x00', + b'78109-TWA-A130\x00\x00', b'78109-TWA-A210\x00\x00', + b'78109-TWA-A220\x00\x00', + b'78109-TWA-A230\x00\x00', + b'78109-TWA-A610\x00\x00', + b'78109-TWA-H210\x00\x00', + b'78109-TWA-L010\x00\x00', + b'78109-TWA-L210\x00\x00', ], (Ecu.hud, 0x18da61f1, None): [ b'78209-TVA-A010\x00\x00', @@ -158,6 +181,9 @@ b'36802-TVE-H070\x00\x00', b'36802-TWA-A070\x00\x00', b'36802-TWA-A080\x00\x00', + b'36802-TWA-A210\x00\x00', + b'36802-TWA-A330\x00\x00', + b'36802-TWB-H060\x00\x00', ], (Ecu.fwdCamera, 0x18dab5f1, None): [ b'36161-TBX-H130\x00\x00', @@ -166,72 +192,17 @@ b'36161-TVC-A330\x00\x00', b'36161-TVE-H050\x00\x00', b'36161-TWA-A070\x00\x00', + b'36161-TWA-A330\x00\x00', + b'36161-TWB-H040\x00\x00', ], (Ecu.gateway, 0x18daeff1, None): [ b'38897-TVA-A010\x00\x00', b'38897-TVA-A020\x00\x00', b'38897-TVA-A230\x00\x00', b'38897-TVA-A240\x00\x00', - ], - }, - CAR.ACCORDH: { - (Ecu.gateway, 0x18daeff1, None): [ b'38897-TWA-A120\x00\x00', b'38897-TWD-J020\x00\x00', ], - (Ecu.vsa, 0x18da28f1, None): [ - b'57114-TWA-A040\x00\x00', - b'57114-TWA-A050\x00\x00', - b'57114-TWA-A530\x00\x00', - b'57114-TWA-B520\x00\x00', - b'57114-TWA-C510\x00\x00', - b'57114-TWB-H030\x00\x00', - ], - (Ecu.srs, 0x18da53f1, None): [ - b'77959-TWA-A440\x00\x00', - b'77959-TWA-L420\x00\x00', - b'77959-TWB-H220\x00\x00', - ], - (Ecu.combinationMeter, 0x18da60f1, None): [ - b'78109-TWA-A010\x00\x00', - b'78109-TWA-A020\x00\x00', - b'78109-TWA-A030\x00\x00', - b'78109-TWA-A110\x00\x00', - b'78109-TWA-A120\x00\x00', - b'78109-TWA-A130\x00\x00', - b'78109-TWA-A210\x00\x00', - b'78109-TWA-A220\x00\x00', - b'78109-TWA-A230\x00\x00', - b'78109-TWA-A610\x00\x00', - b'78109-TWA-H210\x00\x00', - b'78109-TWA-L010\x00\x00', - b'78109-TWA-L210\x00\x00', - ], - (Ecu.shiftByWire, 0x18da0bf1, None): [ - b'54008-TWA-A910\x00\x00', - ], - (Ecu.hud, 0x18da61f1, None): [ - b'78209-TVA-A010\x00\x00', - b'78209-TVA-A110\x00\x00', - ], - (Ecu.fwdCamera, 0x18dab5f1, None): [ - b'36161-TWA-A070\x00\x00', - b'36161-TWA-A330\x00\x00', - b'36161-TWB-H040\x00\x00', - ], - (Ecu.fwdRadar, 0x18dab0f1, None): [ - b'36802-TWA-A070\x00\x00', - b'36802-TWA-A080\x00\x00', - b'36802-TWA-A210\x00\x00', - b'36802-TWA-A330\x00\x00', - b'36802-TWB-H060\x00\x00', - ], - (Ecu.eps, 0x18da30f1, None): [ - b'39990-TVA-A150\x00\x00', - b'39990-TVA-A160\x00\x00', - b'39990-TVA-A340\x00\x00', - b'39990-TWB-H120\x00\x00', - ], }, CAR.CIVIC: { (Ecu.programmedFuelInjection, 0x18da10f1, None): [ diff --git a/selfdrive/car/honda/interface.py b/selfdrive/car/honda/interface.py index 153fa1e63593bb..041ab67a9731be 100755 --- a/selfdrive/car/honda/interface.py +++ b/selfdrive/car/honda/interface.py @@ -59,7 +59,7 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): if any(0x33DA in f for f in fingerprint.values()): ret.flags |= HondaFlags.BOSCH_EXT_HUD.value - # Accord 1.5T CVT has different gearbox message + # Accord ICE 1.5T CVT has different gearbox message if candidate == CAR.ACCORD and 0x191 in fingerprint[1]: ret.transmissionType = TransmissionType.cvt @@ -115,7 +115,7 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]] - elif candidate in (CAR.ACCORD, CAR.ACCORDH): + elif candidate == CAR.ACCORD: ret.mass = 3279. * CV.LB_TO_KG ret.wheelbase = 2.83 ret.centerToFront = ret.wheelbase * 0.39 diff --git a/selfdrive/car/honda/values.py b/selfdrive/car/honda/values.py index f573296609d690..434316943b5cfc 100644 --- a/selfdrive/car/honda/values.py +++ b/selfdrive/car/honda/values.py @@ -74,7 +74,6 @@ class CruiseButtons: class CAR(StrEnum): ACCORD = "HONDA ACCORD 2018" - ACCORDH = "HONDA ACCORD HYBRID 2018" CIVIC = "HONDA CIVIC 2016" CIVIC_BOSCH = "HONDA CIVIC (BOSCH) 2019" CIVIC_BOSCH_DIESEL = "HONDA CIVIC SEDAN 1.6 DIESEL 2019" @@ -119,8 +118,8 @@ def init_make(self, CP: car.CarParams): CAR.ACCORD: [ HondaCarInfo("Honda Accord 2018-22", "All", video_link="https://www.youtube.com/watch?v=mrUwlj3Mi58", min_steer_speed=3. * CV.MPH_TO_MS), HondaCarInfo("Honda Inspire 2018", "All", min_steer_speed=3. * CV.MPH_TO_MS), + HondaCarInfo("Honda Accord Hybrid 2018-22", "All", min_steer_speed=3. * CV.MPH_TO_MS), ], - CAR.ACCORDH: HondaCarInfo("Honda Accord Hybrid 2018-22", "All", min_steer_speed=3. * CV.MPH_TO_MS), CAR.CIVIC: HondaCarInfo("Honda Civic 2016-18", min_steer_speed=12. * CV.MPH_TO_MS, video_link="https://youtu.be/-IkImTe1NYE"), CAR.CIVIC_BOSCH: [ HondaCarInfo("Honda Civic 2019-21", "All", video_link="https://www.youtube.com/watch?v=4Iz1Mz5LGF8", @@ -201,14 +200,16 @@ def init_make(self, CP: car.CarParams): # We lose these ECUs without the comma power on these cars. # Note that we still attempt to match with them when they are present non_essential_ecus={ - Ecu.programmedFuelInjection: [CAR.CIVIC_BOSCH, CAR.CRV_5G], - Ecu.transmission: [CAR.CIVIC_BOSCH, CAR.CRV_5G], - Ecu.vsa: [CAR.CIVIC_BOSCH, CAR.CRV_5G], - Ecu.combinationMeter: [CAR.CIVIC_BOSCH, CAR.CRV_5G], - Ecu.gateway: [CAR.CIVIC_BOSCH, CAR.CRV_5G], - Ecu.electricBrakeBooster: [CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.programmedFuelInjection: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.transmission: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.srs: [CAR.ACCORD], + Ecu.eps: [CAR.ACCORD], + Ecu.vsa: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.combinationMeter: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.gateway: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.electricBrakeBooster: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], Ecu.shiftByWire: [CAR.ACCORD], # existence correlates with transmission type for ICE - Ecu.hud: [CAR.ACCORD, CAR.ACCORDH], # existence correlates with trim level + Ecu.hud: [CAR.ACCORD], # existence correlates with trim level }, extra_ecus=[ # The only other ECU on PT bus accessible by camera on radarless Civic @@ -219,7 +220,6 @@ def init_make(self, CP: car.CarParams): DBC = { CAR.ACCORD: dbc_dict('honda_accord_2018_can_generated', None), - CAR.ACCORDH: dbc_dict('honda_accord_2018_can_generated', None), CAR.ACURA_ILX: dbc_dict('acura_ilx_2016_can_generated', 'acura_ilx_2016_nidec'), CAR.ACURA_RDX: dbc_dict('acura_rdx_2018_can_generated', 'acura_ilx_2016_nidec'), CAR.ACURA_RDX_3G: dbc_dict('acura_rdx_2020_can_generated', None), @@ -252,6 +252,6 @@ def init_make(self, CP: car.CarParams): HONDA_NIDEC_ALT_PCM_ACCEL = {CAR.ODYSSEY} HONDA_NIDEC_ALT_SCM_MESSAGES = {CAR.ACURA_ILX, CAR.ACURA_RDX, CAR.CRV, CAR.CRV_EU, CAR.FIT, CAR.FREED, CAR.HRV, CAR.ODYSSEY_CHN, CAR.PILOT, CAR.RIDGELINE} -HONDA_BOSCH = {CAR.ACCORD, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_5G, +HONDA_BOSCH = {CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_5G, CAR.CRV_HYBRID, CAR.INSIGHT, CAR.ACURA_RDX_3G, CAR.HONDA_E, CAR.CIVIC_2022, CAR.HRV_3G} HONDA_BOSCH_RADARLESS = {CAR.CIVIC_2022, CAR.HRV_3G} diff --git a/selfdrive/car/tests/routes.py b/selfdrive/car/tests/routes.py index 9c14c0d25279c7..811416ccef1bf3 100755 --- a/selfdrive/car/tests/routes.py +++ b/selfdrive/car/tests/routes.py @@ -82,8 +82,8 @@ class CarTestRoute(NamedTuple): CarTestRoute("08a3deb07573f157|2020-03-06--16-11-19", HONDA.ACCORD), # 1.5T CarTestRoute("1da5847ac2488106|2021-05-24--19-31-50", HONDA.ACCORD), # 2.0T CarTestRoute("085ac1d942c35910|2021-03-25--20-11-15", HONDA.ACCORD), # 2021 with new style HUD msgs - CarTestRoute("07585b0da3c88459|2021-05-26--18-52-04", HONDA.ACCORDH), - CarTestRoute("f29e2b57a55e7ad5|2021-03-24--20-52-38", HONDA.ACCORDH), # 2021 with new style HUD msgs + CarTestRoute("07585b0da3c88459|2021-05-26--18-52-04", HONDA.ACCORD), # hybrid + CarTestRoute("f29e2b57a55e7ad5|2021-03-24--20-52-38", HONDA.ACCORD), # hybrid, 2021 with new style HUD msgs CarTestRoute("1ad763dd22ef1a0e|2020-02-29--18-37-03", HONDA.CRV_5G), CarTestRoute("0a96f86fcfe35964|2020-02-05--07-25-51", HONDA.ODYSSEY), CarTestRoute("d83f36766f8012a5|2020-02-05--18-42-21", HONDA.CIVIC_BOSCH_DIESEL), diff --git a/selfdrive/car/tests/test_models_segs.txt b/selfdrive/car/tests/test_models_segs.txt index ca089bbdded974..c983fb08e7f009 100644 --- a/selfdrive/car/tests/test_models_segs.txt +++ b/selfdrive/car/tests/test_models_segs.txt @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cadad21e1230729c70cffb4c46dd0a5dda4eec1a262b1bcd9f1b6b98265c20b5 -size 125104 +oid sha256:0810a361ec5b5f5f9a2ee73b89ffb2df62ef40e8feff7e97ecb62f80fa53f6f5 +size 124950 diff --git a/selfdrive/car/torque_data/params.toml b/selfdrive/car/torque_data/params.toml index 568646c84cf5a4..142332b2208ed4 100644 --- a/selfdrive/car/torque_data/params.toml +++ b/selfdrive/car/torque_data/params.toml @@ -11,8 +11,7 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"] "CHRYSLER PACIFICA HYBRID 2018" = [2.08887, 1.2943025830995154, 0.114818] "CHRYSLER PACIFICA HYBRID 2019" = [1.90120, 1.1958788168371808, 0.131520] "GENESIS G70 2018" = [3.8520195946707947, 2.354697063349854, 0.06830285485626221] -"HONDA ACCORD 2018" = [1.7135052593468778, 0.3461280068322071, 0.21579936052863807] -"HONDA ACCORD HYBRID 2018" = [1.6651615004829625, 0.30322180951193245, 0.2083000440586149] +"HONDA ACCORD 2018" = [1.6893333799149202, 0.3246749081720698, 0.2120497022936265] "HONDA CIVIC (BOSCH) 2019" = [1.691708637466905, 0.40132900729454185, 0.25460295304024094] "HONDA CIVIC 2016" = [1.6528895627785531, 0.4018518740819229, 0.25458812851328544] "HONDA CR-V 2016" = [0.7667141440182675, 0.5927571534745969, 0.40909087636157127] diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 9c627fb7c9aa38..0fa4652e4c568d 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -47609e372bf616932c4dca74d2616c3d97fa2443 +dab93e072903e80f91029a03600430c43c722cb7 From a5fa419fbd32afe176dc4380e84c785bf84ba8aa Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 27 Feb 2024 21:48:40 -0800 Subject: [PATCH 37/41] Volkswagen: log camera ECU FW --- selfdrive/car/volkswagen/values.py | 1 + 1 file changed, 1 insertion(+) diff --git a/selfdrive/car/volkswagen/values.py b/selfdrive/car/volkswagen/values.py index 4dff9205d64736..3344d58ea9289f 100644 --- a/selfdrive/car/volkswagen/values.py +++ b/selfdrive/car/volkswagen/values.py @@ -393,6 +393,7 @@ class CAR(Platforms): obd_multiplexing=obd_multiplexing, ), ]], + extra_ecus=[(Ecu.fwdCamera, 0x74f, None)], ) CAR_INFO = CAR.create_carinfo_map() From 2c247ea2c6f6c22aa6ce55a6220e75ab17b58e06 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 28 Feb 2024 00:12:00 -0600 Subject: [PATCH 38/41] Honda Civic (Nidec): allow fingerprinting without comma power (#31501) * civic: FP with no OBD port * non essential ecus --- selfdrive/car/honda/values.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/selfdrive/car/honda/values.py b/selfdrive/car/honda/values.py index 434316943b5cfc..ce4a531d01b863 100644 --- a/selfdrive/car/honda/values.py +++ b/selfdrive/car/honda/values.py @@ -187,7 +187,6 @@ def init_make(self, CP: car.CarParams): [StdQueries.UDS_VERSION_REQUEST], [StdQueries.UDS_VERSION_RESPONSE], bus=0, - logging=True, ), # Bosch PT bus Request( @@ -200,13 +199,13 @@ def init_make(self, CP: car.CarParams): # We lose these ECUs without the comma power on these cars. # Note that we still attempt to match with them when they are present non_essential_ecus={ - Ecu.programmedFuelInjection: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], - Ecu.transmission: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.programmedFuelInjection: [CAR.ACCORD, CAR.CIVIC, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.transmission: [CAR.ACCORD, CAR.CIVIC, CAR.CIVIC_BOSCH, CAR.CRV_5G], Ecu.srs: [CAR.ACCORD], Ecu.eps: [CAR.ACCORD], - Ecu.vsa: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], - Ecu.combinationMeter: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], - Ecu.gateway: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.vsa: [CAR.ACCORD, CAR.CIVIC, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.combinationMeter: [CAR.ACCORD, CAR.CIVIC, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.gateway: [CAR.ACCORD, CAR.CIVIC, CAR.CIVIC_BOSCH, CAR.CRV_5G], Ecu.electricBrakeBooster: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], Ecu.shiftByWire: [CAR.ACCORD], # existence correlates with transmission type for ICE Ecu.hud: [CAR.ACCORD], # existence correlates with trim level From 7cf2b28b7883fdc3e68ad9e0974879103fa3a6ba Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Wed, 28 Feb 2024 14:41:42 -0500 Subject: [PATCH 39/41] scons: fix race condition with opendbc (#31621) * fix race condition * add to release * fix for now * bump --- SConstruct | 8 +------- opendbc | 2 +- release/files_common | 2 ++ selfdrive/SConscript | 7 +++++++ selfdrive/controls/lib/lateral_mpc_lib/SConscript | 3 ++- selfdrive/controls/lib/longitudinal_mpc_lib/SConscript | 4 ++-- 6 files changed, 15 insertions(+), 11 deletions(-) create mode 100644 selfdrive/SConscript diff --git a/SConstruct b/SConstruct index 4d4f9ad4fe2eb7..dac352989259d5 100644 --- a/SConstruct +++ b/SConstruct @@ -384,13 +384,7 @@ if arch != "Darwin": # Build openpilot SConscript(['third_party/SConscript']) -SConscript(['selfdrive/boardd/SConscript']) -SConscript(['selfdrive/controls/lib/lateral_mpc_lib/SConscript']) -SConscript(['selfdrive/controls/lib/longitudinal_mpc_lib/SConscript']) -SConscript(['selfdrive/locationd/SConscript']) -SConscript(['selfdrive/navd/SConscript']) -SConscript(['selfdrive/modeld/SConscript']) -SConscript(['selfdrive/ui/SConscript']) +SConscript(['selfdrive/SConscript']) if arch in ['x86_64', 'aarch64', 'Darwin'] and Dir('#tools/cabana/').exists() and GetOption('extras'): SConscript(['tools/replay/SConscript']) diff --git a/opendbc b/opendbc index 0ac21652f2e643..5f096db742b0c5 160000 --- a/opendbc +++ b/opendbc @@ -1 +1 @@ -Subproject commit 0ac21652f2e643e29aa471ad6b238bf74b22e356 +Subproject commit 5f096db742b0c5dcd19976afdb07d5dd098f4b07 diff --git a/release/files_common b/release/files_common index d62ef8d1bb6dd9..1fb05b43a772cd 100644 --- a/release/files_common +++ b/release/files_common @@ -60,6 +60,8 @@ system/logmessaged.py system/micd.py system/version.py +selfdrive/SConscript + selfdrive/athena/__init__.py selfdrive/athena/athenad.py selfdrive/athena/manage_athenad.py diff --git a/selfdrive/SConscript b/selfdrive/SConscript new file mode 100644 index 00000000000000..6b72177d8e0c67 --- /dev/null +++ b/selfdrive/SConscript @@ -0,0 +1,7 @@ +SConscript(['boardd/SConscript']) +SConscript(['controls/lib/lateral_mpc_lib/SConscript']) +SConscript(['controls/lib/longitudinal_mpc_lib/SConscript']) +SConscript(['locationd/SConscript']) +SConscript(['navd/SConscript']) +SConscript(['modeld/SConscript']) +SConscript(['ui/SConscript']) \ No newline at end of file diff --git a/selfdrive/controls/lib/lateral_mpc_lib/SConscript b/selfdrive/controls/lib/lateral_mpc_lib/SConscript index 49666abe69a7a2..b6603e69fc185d 100644 --- a/selfdrive/controls/lib/lateral_mpc_lib/SConscript +++ b/selfdrive/controls/lib/lateral_mpc_lib/SConscript @@ -1,4 +1,4 @@ -Import('env', 'envCython', 'arch') +Import('env', 'envCython', 'arch', 'messaging_python', 'common_python', 'opendbc_python') gen = "c_generated_code" @@ -60,6 +60,7 @@ lenv.Clean(generated_files, Dir(gen)) generated_lat = lenv.Command(generated_files, source_list, f"cd {Dir('.').abspath} && python3 lat_mpc.py") +lenv.Depends(generated_lat, [messaging_python, common_python, opendbc_python]) lenv["CFLAGS"].append("-DACADOS_WITH_QPOASES") lenv["CXXFLAGS"].append("-DACADOS_WITH_QPOASES") diff --git a/selfdrive/controls/lib/longitudinal_mpc_lib/SConscript b/selfdrive/controls/lib/longitudinal_mpc_lib/SConscript index 79afa1d918b8d6..c00d5cb5a726f2 100644 --- a/selfdrive/controls/lib/longitudinal_mpc_lib/SConscript +++ b/selfdrive/controls/lib/longitudinal_mpc_lib/SConscript @@ -1,4 +1,4 @@ -Import('env', 'envCython', 'arch', 'messaging_python', 'common_python') +Import('env', 'envCython', 'arch', 'messaging_python', 'common_python', 'opendbc_python') gen = "c_generated_code" @@ -66,7 +66,7 @@ lenv.Clean(generated_files, Dir(gen)) generated_long = lenv.Command(generated_files, source_list, f"cd {Dir('.').abspath} && python3 long_mpc.py") -lenv.Depends(generated_long, [messaging_python, common_python]) +lenv.Depends(generated_long, [messaging_python, common_python, opendbc_python]) lenv["CFLAGS"].append("-DACADOS_WITH_QPOASES") lenv["CXXFLAGS"].append("-DACADOS_WITH_QPOASES") From e9a10ca712c79c51037f5c96b8f8e749c98ce060 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Wed, 28 Feb 2024 15:05:43 -0500 Subject: [PATCH 40/41] auto pr review (#31626) * auto PR comments * little more * test * update action * cleanup * ensure it only runs once * comment that part out --------- Co-authored-by: Adeeb Shihadeh --- .github/workflows/auto_pr_review.yaml | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/.github/workflows/auto_pr_review.yaml b/.github/workflows/auto_pr_review.yaml index abb6c38d6be010..0720c1e67666eb 100644 --- a/.github/workflows/auto_pr_review.yaml +++ b/.github/workflows/auto_pr_review.yaml @@ -34,6 +34,25 @@ jobs: already-exists-action: close_this already-exists-comment: "Your PR should be made against the `master` branch" + comment: + runs-on: ubuntu-latest + steps: + - name: comment + uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 + with: + message: | + + Thanks for contributing to openpilot! In order for us to review your PR as quickly as possible, check the following: + * Convert your PR to a draft unless it's ready to review + * Read the [contributing docs](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md) + * Before marking as "ready for review", ensure: + * the goal is clearly stated in the description + * all the tests are passing + * the change is [something we merge](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md#what-gets-merged) + * include a route or your device' dongle ID if relevant + comment_tag: run_id + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + check-pr-template: runs-on: ubuntu-latest permissions: @@ -41,7 +60,7 @@ jobs: issues: write pull-requests: write actions: read - if: github.event.pull_request.head.repo.full_name != 'commaai/openpilot' + if: false && github.event.pull_request.head.repo.full_name != 'commaai/openpilot' steps: - uses: actions/github-script@v7 with: @@ -91,7 +110,7 @@ jobs: // Utility function to check if a list of checkboxes is a subset of another list of checkboxes isCheckboxSubset = (templateCheckBoxTexts, prTextCheckBoxTexts) => { - // Check if each template checkbox text is a substring of at least one PR checkbox text + // Check if each template checkbox text is a substring of at least one PR checkbox text // (user should be allowed to add additional text) return templateCheckBoxTexts.every((item) => prTextCheckBoxTexts.some((element) => element.includes(item))) } From 76ad73a2ec9eba1b002e8ff6f3ac30054400b0a9 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Sat, 24 Feb 2024 10:43:16 -0800 Subject: [PATCH 41/41] Ford: enable radar parsing --- selfdrive/car/ford/interface.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/selfdrive/car/ford/interface.py b/selfdrive/car/ford/interface.py index fd4c381f889995..1771454774621e 100644 --- a/selfdrive/car/ford/interface.py +++ b/selfdrive/car/ford/interface.py @@ -3,7 +3,7 @@ from openpilot.common.conversions import Conversions as CV from openpilot.selfdrive.car import get_safety_config from openpilot.selfdrive.car.ford.fordcan import CanBus -from openpilot.selfdrive.car.ford.values import CANFD_CAR, Ecu +from openpilot.selfdrive.car.ford.values import CANFD_CAR, DBC, Ecu from openpilot.selfdrive.car.interfaces import CarInterfaceBase TransmissionType = car.CarParams.TransmissionType @@ -16,7 +16,7 @@ def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): ret.carName = "ford" ret.dashcamOnly = candidate in CANFD_CAR - ret.radarUnavailable = True + ret.radarUnavailable = DBC[candidate]['radar'] is None ret.steerControlType = car.CarParams.SteerControlType.angle ret.steerActuatorDelay = 0.2 ret.steerLimitTimer = 1.0