mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-09-27 04:33:43 +08:00
Merge branch 'master' into sync-priv-20240227
# Conflicts: # panda # selfdrive/car/chrysler/values.py # selfdrive/car/ford/carstate.py # selfdrive/car/ford/interface.py # selfdrive/car/ford/values.py # selfdrive/car/interfaces.py # selfdrive/car/nissan/values.py # selfdrive/car/subaru/interface.py # selfdrive/car/volkswagen/interface.py # selfdrive/car/volkswagen/values.py # selfdrive/controls/radard.py # selfdrive/manager/process.py # selfdrive/modeld/modeld.py
This commit is contained in:
@@ -117,7 +117,7 @@ jobs:
|
||||
- name: Merge x64 and arm64 tags
|
||||
run: |
|
||||
export PUSH_IMAGE=true
|
||||
selfdrive/test/docker_tag_multiarch.sh base x86_64 aarch64
|
||||
scripts/retry.sh selfdrive/test/docker_tag_multiarch.sh base x86_64 aarch64
|
||||
|
||||
static_analysis:
|
||||
name: static analysis
|
||||
|
||||
@@ -10,7 +10,6 @@ venv/
|
||||
.overlay_init
|
||||
.overlay_consistent
|
||||
.sconsign.dblite
|
||||
.vscode*
|
||||
model2.png
|
||||
a.out
|
||||
.hypothesis
|
||||
|
||||
@@ -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
|
||||
@@ -32,6 +32,11 @@ repos:
|
||||
# if you've got a short variable name that's getting flagged, add it here
|
||||
- -L bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie,preints
|
||||
- --builtins clear,rare,informal,usage,code,names,en-GB_to_en-US
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.2.2
|
||||
hooks:
|
||||
- id: ruff
|
||||
exclude: '^(third_party/)|(cereal/)|(panda/)|(rednose/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)|(teleoprtc/)|(teleoprtc_repo/)'
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: mypy
|
||||
@@ -43,11 +48,6 @@ repos:
|
||||
- --local-partial-types
|
||||
- --explicit-package-bases
|
||||
exclude: '^(third_party/)|(cereal/)|(opendbc/)|(panda/)|(rednose/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)|(teleoprtc/)|(teleoprtc_repo/)|(xx/)'
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.2.2
|
||||
hooks:
|
||||
- id: ruff
|
||||
exclude: '^(third_party/)|(cereal/)|(panda/)|(rednose/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)|(teleoprtc/)|(teleoprtc_repo/)'
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: cppcheck
|
||||
@@ -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
|
||||
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"ms-python.python",
|
||||
"ms-vscode.cpptools",
|
||||
"elagil.pre-commit-helper",
|
||||
"charliermarsh.ruff",
|
||||
]
|
||||
}
|
||||
Vendored
+47
@@ -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}",
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+16
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
Version 0.9.7 (2024-XX-XX)
|
||||
========================
|
||||
* New driving model
|
||||
* Support for many hybrid Ford models
|
||||
|
||||
Version 0.9.6 (2024-02-27)
|
||||
========================
|
||||
|
||||
@@ -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",
|
||||
]
|
||||
@@ -361,13 +359,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',
|
||||
|
||||
+1
-1
Submodule cereal updated: b891fcca7a...d4c43a0865
@@ -1,7 +1,6 @@
|
||||
import os
|
||||
import tempfile
|
||||
import contextlib
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class CallbackReader:
|
||||
@@ -24,7 +23,7 @@ class CallbackReader:
|
||||
|
||||
|
||||
@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, 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)
|
||||
|
||||
+3
-4
@@ -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():
|
||||
|
||||
@@ -6,7 +6,6 @@ example in common/tests/test_mock.py
|
||||
|
||||
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 @@ MOCK_GENERATOR = {
|
||||
}
|
||||
|
||||
|
||||
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]
|
||||
|
||||
|
||||
@@ -209,7 +209,6 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"UpdaterLastFetchTime", PERSISTENT},
|
||||
{"Version", PERSISTENT},
|
||||
{"VisionRadarToggle", PERSISTENT},
|
||||
{"WheeledBody", PERSISTENT},
|
||||
|
||||
{"AccMadsCombo", PERSISTENT},
|
||||
{"AmapKey1", PERSISTENT},
|
||||
|
||||
+1
-2
@@ -2,14 +2,13 @@ import os
|
||||
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, 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
|
||||
|
||||
+3
-4
@@ -5,7 +5,6 @@ import time
|
||||
import threading
|
||||
import psutil
|
||||
from collections import deque
|
||||
from typing import Optional, List, Union
|
||||
|
||||
from setproctitle import getproctitle
|
||||
|
||||
@@ -35,12 +34,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, ]
|
||||
@@ -56,7 +55,7 @@ def set_thread_affinity(thread: threading.Thread, cores: List[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
|
||||
|
||||
@@ -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,
|
||||
|
||||
+11
-2
@@ -4,7 +4,7 @@
|
||||
|
||||
A supported vehicle is one that just works when you install a comma device. All supported cars provide a better experience than any stock system. Supported vehicles reference the US market unless otherwise specified.
|
||||
|
||||
# 279 Supported Cars
|
||||
# 288 Supported Cars
|
||||
|
||||
|Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|<a href="##"><img width=2000></a>Hardware Needed<br> |Video|
|
||||
|---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||
@@ -37,11 +37,19 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Dodge|Durango 2020-21|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Dodge&model=Durango 2020-21">Buy Here</a></sub></details>||
|
||||
|Ford|Bronco Sport 2021-22|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Bronco Sport 2021-22">Buy Here</a></sub></details>||
|
||||
|Ford|Escape 2020-22|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Escape 2020-22">Buy Here</a></sub></details>||
|
||||
|Ford|Escape Hybrid 2020-22|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Escape Hybrid 2020-22">Buy Here</a></sub></details>||
|
||||
|Ford|Escape Plug-in Hybrid 2020-22|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Escape Plug-in Hybrid 2020-22">Buy Here</a></sub></details>||
|
||||
|Ford|Explorer 2020-23|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Explorer 2020-23">Buy Here</a></sub></details>||
|
||||
|Ford|Explorer Hybrid 2020-23|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Explorer Hybrid 2020-23">Buy Here</a></sub></details>||
|
||||
|Ford|Focus 2018[<sup>3</sup>](#footnotes)|Adaptive Cruise Control with Lane Centering|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Focus 2018">Buy Here</a></sub></details>||
|
||||
|Ford|Focus Hybrid 2018[<sup>3</sup>](#footnotes)|Adaptive Cruise Control with Lane Centering|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Focus Hybrid 2018">Buy Here</a></sub></details>||
|
||||
|Ford|Kuga 2020-22|Adaptive Cruise Control with Lane Centering|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Kuga 2020-22">Buy Here</a></sub></details>||
|
||||
|Ford|Kuga Hybrid 2020-22|Adaptive Cruise Control with Lane Centering|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Kuga Hybrid 2020-22">Buy Here</a></sub></details>||
|
||||
|Ford|Kuga Plug-in Hybrid 2020-22|Adaptive Cruise Control with Lane Centering|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Kuga Plug-in Hybrid 2020-22">Buy Here</a></sub></details>||
|
||||
|Ford|Maverick 2022|LARIAT Luxury|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Maverick 2022">Buy Here</a></sub></details>||
|
||||
|Ford|Maverick 2023|Co-Pilot360 Assist|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Maverick 2023">Buy Here</a></sub></details>||
|
||||
|Ford|Maverick Hybrid 2022|LARIAT Luxury|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Maverick Hybrid 2022">Buy Here</a></sub></details>||
|
||||
|Ford|Maverick Hybrid 2023|Co-Pilot360 Assist|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Maverick Hybrid 2023">Buy Here</a></sub></details>||
|
||||
|Genesis|G70 2018-19|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Genesis&model=G70 2018-19">Buy Here</a></sub></details>||
|
||||
|Genesis|G70 2020|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Genesis&model=G70 2020">Buy Here</a></sub></details>||
|
||||
|Genesis|G80 2017|All|Stock|19 mph|37 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai J connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Genesis&model=G80 2017">Buy Here</a></sub></details>||
|
||||
@@ -177,7 +185,8 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Lexus|RX Hybrid 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=RX Hybrid 2017-19">Buy Here</a></sub></details>||
|
||||
|Lexus|RX Hybrid 2020-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=RX Hybrid 2020-22">Buy Here</a></sub></details>||
|
||||
|Lexus|UX Hybrid 2019-23|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=UX Hybrid 2019-23">Buy Here</a></sub></details>||
|
||||
|Lincoln|Aviator 2020-21|Co-Pilot360 Plus|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lincoln&model=Aviator 2020-21">Buy Here</a></sub></details>||
|
||||
|Lincoln|Aviator 2020-23|Co-Pilot360 Plus|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lincoln&model=Aviator 2020-23">Buy Here</a></sub></details>||
|
||||
|Lincoln|Aviator Plug-in Hybrid 2020-23|Co-Pilot360 Plus|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lincoln&model=Aviator Plug-in Hybrid 2020-23">Buy Here</a></sub></details>||
|
||||
|MAN|eTGE 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=MAN&model=eTGE 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|MAN|TGE 2017-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=MAN&model=TGE 2017-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Mazda|CX-5 2022-24|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Mazda connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Mazda&model=CX-5 2022-24">Buy Here</a></sub></details>||
|
||||
|
||||
@@ -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).
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ export OPENBLAS_NUM_THREADS=1
|
||||
export VECLIB_MAXIMUM_THREADS=1
|
||||
|
||||
if [ -z "$AGNOS_VERSION" ]; then
|
||||
export AGNOS_VERSION="9.6"
|
||||
export AGNOS_VERSION="9.7"
|
||||
fi
|
||||
|
||||
export STAGING_ROOT="/data/safe_staging"
|
||||
|
||||
+1
-1
Submodule opendbc updated: e8e8ed7222...ecffe0cc98
@@ -1,3 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
+1
-1
Submodule panda updated: ec91ad7f06...87391d0067
Generated
+176
-175
@@ -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]
|
||||
|
||||
@@ -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"
|
||||
@@ -187,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"]
|
||||
|
||||
+1
-1
Submodule rednose_repo updated: 18b91458fd...c5762e8bc6
@@ -27,6 +27,7 @@ common/.gitignore
|
||||
common/__init__.py
|
||||
common/*.py
|
||||
common/*.pyx
|
||||
common/mock/*
|
||||
|
||||
common/transformations/__init__.py
|
||||
common/transformations/camera.py
|
||||
@@ -91,6 +92,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
|
||||
|
||||
Executable
+7
@@ -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
|
||||
+29
-28
@@ -19,7 +19,8 @@ from dataclasses import asdict, dataclass, replace
|
||||
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 @@ WS_FRAME_SIZE = 4096
|
||||
|
||||
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 @@ class 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 @@ send_queue: Queue[str] = queue.Queue()
|
||||
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 @@ class UploadQueueCache:
|
||||
@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) -> 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, place_details: str = 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 takeSnapshot() -> Optional[Union[str, Dict[str, str]]]:
|
||||
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):
|
||||
try:
|
||||
set_core_affinity([0, 1, 2, 3])
|
||||
except Exception:
|
||||
|
||||
@@ -3,7 +3,6 @@ import time
|
||||
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)
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import http.server
|
||||
import threading
|
||||
import socket
|
||||
from functools import wraps
|
||||
|
||||
|
||||
class MockResponse:
|
||||
@@ -65,25 +63,3 @@ class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
|
||||
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
|
||||
|
||||
@@ -12,7 +12,6 @@ import unittest
|
||||
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
|
||||
@@ -24,9 +23,9 @@ from openpilot.common.params import Params
|
||||
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):
|
||||
@@ -97,7 +96,7 @@ class TestAthenadMethods(unittest.TestCase):
|
||||
break
|
||||
|
||||
@staticmethod
|
||||
def _create_file(file: str, parent: Optional[str] = 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:
|
||||
|
||||
@@ -3,7 +3,7 @@ import subprocess
|
||||
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")
|
||||
|
||||
@@ -4,7 +4,7 @@ import os
|
||||
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))
|
||||
|
||||
|
||||
+29
-13
@@ -1,8 +1,7 @@
|
||||
# functions common among cars
|
||||
from collections import namedtuple
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field, replace
|
||||
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
|
||||
@@ -82,7 +81,8 @@ 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:
|
||||
return {'pt': pt_dbc, 'radar': radar_dbc, 'chassis': chassis_dbc, 'body': body_dbc}
|
||||
@@ -219,7 +219,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
|
||||
@@ -249,17 +249,33 @@ class CanSignalRateCalculator:
|
||||
return self.rate
|
||||
|
||||
|
||||
CarInfos = Union[CarInfo, List[CarInfo]]
|
||||
CarInfos = CarInfo | list[CarInfo]
|
||||
|
||||
@dataclass(order=True)
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class CarSpecs:
|
||||
mass: float
|
||||
wheelbase: float
|
||||
steerRatio: float
|
||||
centerToFrontRatio: float = field(default=0.5)
|
||||
minSteerSpeed: float = field(default=0.)
|
||||
minEnableSpeed: float = field(default=-1.)
|
||||
|
||||
|
||||
@dataclass(frozen=True, order=True)
|
||||
class PlatformConfig:
|
||||
platform_str: str
|
||||
car_info: CarInfos
|
||||
dbc_dict: DbcDict
|
||||
|
||||
specs: CarSpecs | None = None
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(self.platform_str)
|
||||
|
||||
def override(self, **kwargs):
|
||||
return replace(self, **kwargs)
|
||||
|
||||
|
||||
class Platforms(str, ReprEnum):
|
||||
config: PlatformConfig
|
||||
@@ -271,9 +287,9 @@ class Platforms(str, ReprEnum):
|
||||
return member
|
||||
|
||||
@classmethod
|
||||
def create_dbc_map(cls) -> Dict[str, DbcDict]:
|
||||
return {p.config.platform_str: p.config.dbc_dict for p in cls}
|
||||
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]:
|
||||
return {p.config.platform_str: p.config.car_info for p in cls}
|
||||
def create_carinfo_map(cls) -> dict[str, CarInfos]:
|
||||
return {p: p.config.car_info for p in cls}
|
||||
|
||||
@@ -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 @@ class CarController:
|
||||
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 @@ class CarController:
|
||||
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
|
||||
|
||||
@@ -3,11 +3,12 @@ import os
|
||||
import requests
|
||||
import threading
|
||||
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
|
||||
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
|
||||
@@ -67,7 +68,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():
|
||||
@@ -81,7 +82,7 @@ interface_names = _get_interface_names()
|
||||
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
|
||||
@@ -193,7 +194,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 is_connected_to_internet(timeout=5):
|
||||
|
||||
@@ -32,7 +32,6 @@ class CarInterface(CarInterfaceBase):
|
||||
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.
|
||||
@@ -43,10 +42,6 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
# 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]]
|
||||
@@ -54,9 +49,6 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
# 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')
|
||||
@@ -68,19 +60,12 @@ class CarInterface(CarInterfaceBase):
|
||||
elif candidate == CAR.RAM_1500:
|
||||
ret.steerActuatorDelay = 0.2
|
||||
ret.wheelbase = 3.88
|
||||
ret.steerRatio = 16.3
|
||||
ret.mass = 2493.
|
||||
ret.minSteerSpeed = 0.5
|
||||
ret.minEnableSpeed = 14.5
|
||||
if any(fw.ecu == 'eps' and fw.fwVersion in (b"68273275AF", b"68273275AG", b"68312176AE", b"68312176AG",) for fw in car_fw):
|
||||
ret.minEnableSpeed = 0.
|
||||
# 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.
|
||||
|
||||
elif candidate == CAR.RAM_HD:
|
||||
ret.steerActuatorDelay = 0.2
|
||||
ret.wheelbase = 3.785
|
||||
ret.steerRatio = 15.61
|
||||
ret.mass = 3405.
|
||||
ret.minSteerSpeed = 16
|
||||
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning, 1.0, False)
|
||||
ret.spFlags |= ChryslerFlagsSP.SP_RAM_HD_PARAMSD_IGNORE.value
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
from enum import IntFlag, StrEnum
|
||||
from enum import IntFlag
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Dict, List, Optional, Union
|
||||
|
||||
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
|
||||
|
||||
@@ -20,24 +19,89 @@ class ChryslerFlagsSP(IntFlag):
|
||||
SP_WP_S20 = 2
|
||||
|
||||
|
||||
class CAR(StrEnum):
|
||||
@dataclass
|
||||
class ChryslerCarInfo(CarInfo):
|
||||
package: str = "Adaptive Cruise Control (ACC)"
|
||||
car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.fca]))
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ChryslerPlatformConfig(PlatformConfig):
|
||||
dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('chrysler_pacifica_2017_hybrid_generated', None))
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ChryslerCarSpecs(CarSpecs):
|
||||
minSteerSpeed: float = 3.8 # m/s
|
||||
|
||||
|
||||
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:
|
||||
@@ -73,32 +137,6 @@ RAM_HD = {CAR.RAM_HD, }
|
||||
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, Optional[Union[ChryslerCarInfo, List[ChryslerCarInfo]]]] = {
|
||||
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]) + \
|
||||
@@ -138,16 +176,5 @@ FW_QUERY_CONFIG = FwQueryConfig(
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
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()
|
||||
|
||||
@@ -5,7 +5,6 @@ import jinja2
|
||||
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.docs_definitions import CarInfo, Column, CommonFoot
|
||||
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 @@ CARS_MD_OUT = os.path.join(BASEDIR, "docs", "CARS.md")
|
||||
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()]
|
||||
|
||||
@@ -3,7 +3,6 @@ from collections import namedtuple
|
||||
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, remove: list[EnumBase] = 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 @@ class CarInfo:
|
||||
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 @@ class CarInfo:
|
||||
if len(tools_docs):
|
||||
hardware_col += f'<details><summary>Tools</summary><sub>{display_func(tools_docs)}</sub></details>'
|
||||
|
||||
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 @@ class CarInfo:
|
||||
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):
|
||||
|
||||
@@ -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) -> 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]
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ class CarState(CarStateBase):
|
||||
self.shifter_values = can_define.dv["Gear_Shift_by_Wire_FD1"]["TrnRng_D_RqGsm"]
|
||||
|
||||
self.vehicle_sensors_valid = False
|
||||
self.unsupported_platform = False
|
||||
|
||||
self.lkas_enabled = None
|
||||
self.prev_lkas_enabled = None
|
||||
@@ -32,12 +31,6 @@ class CarState(CarStateBase):
|
||||
self.prev_lkas_enabled = self.lkas_enabled
|
||||
self.buttonStatesPrev = self.buttonStates.copy()
|
||||
|
||||
# Ford Q3 hybrid variants experience a bug where a message from the PCM sends invalid checksums,
|
||||
# this must be root-caused before enabling support. Ford Q4 hybrids do not have this problem.
|
||||
# TrnAin_Tq_Actl and its quality flag are only set on ICE platform variants
|
||||
self.unsupported_platform = (cp.vl["VehicleOperatingModes"]["TrnAinTq_D_Qf"] == 0 and
|
||||
self.CP.carFingerprint not in CANFD_CAR)
|
||||
|
||||
# Occasionally on startup, the ABS module recalibrates the steering pinion offset, so we need to block engagement
|
||||
# The vehicle usually recovers out of this state within a minute of normal driving
|
||||
self.vehicle_sensors_valid = cp.vl["SteeringPinion_Data"]["StePinCompAnEst_D_Qf"] == 3
|
||||
|
||||
@@ -3,7 +3,7 @@ from panda import Panda
|
||||
from openpilot.common.conversions import Conversions as CV
|
||||
from openpilot.selfdrive.car import get_safety_config, create_mads_event
|
||||
from openpilot.selfdrive.car.ford.fordcan import CanBus
|
||||
from openpilot.selfdrive.car.ford.values import CANFD_CAR, CAR, Ecu, BUTTON_STATES
|
||||
from openpilot.selfdrive.car.ford.values import CANFD_CAR, Ecu, BUTTON_STATES
|
||||
from openpilot.selfdrive.car.interfaces import CarInterfaceBase
|
||||
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
@@ -45,51 +45,6 @@ class CarInterface(CarInterfaceBase):
|
||||
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:
|
||||
@@ -169,8 +124,6 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
if not self.CS.vehicle_sensors_valid:
|
||||
events.add(car.CarEvent.EventName.vehicleSensorsInvalid)
|
||||
if self.CS.unsupported_platform:
|
||||
events.add(car.CarEvent.EventName.startupNoControl)
|
||||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -19,6 +19,7 @@ ECU_ADDRESSES = {
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +51,7 @@ class TestFordFW(unittest.TestCase):
|
||||
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")
|
||||
|
||||
+124
-50
@@ -1,13 +1,12 @@
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum, StrEnum
|
||||
from typing import Dict, List, Union
|
||||
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, 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
|
||||
from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries, p16
|
||||
|
||||
Ecu = car.CarParams.Ecu
|
||||
|
||||
@@ -50,33 +49,11 @@ BUTTON_STATES = {
|
||||
}
|
||||
|
||||
|
||||
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 " +
|
||||
@@ -97,25 +74,109 @@ class FordCarInfo(CarInfo):
|
||||
self.car_parts = CarParts([Device.threex, harness])
|
||||
|
||||
|
||||
CAR_INFO: Dict[str, Union[CarInfo, List[CarInfo]]] = {
|
||||
CAR.BRONCO_SPORT_MK1: FordCarInfo("Ford Bronco Sport 2021-22"),
|
||||
CAR.ESCAPE_MK4: [
|
||||
FordCarInfo("Ford Escape 2020-22"),
|
||||
FordCarInfo("Ford Kuga 2020-22", "Adaptive Cruise Control with Lane Centering"),
|
||||
],
|
||||
CAR.EXPLORER_MK6: [
|
||||
FordCarInfo("Ford Explorer 2020-23"),
|
||||
FordCarInfo("Lincoln Aviator 2020-21", "Co-Pilot360 Plus"),
|
||||
],
|
||||
CAR.F_150_MK14: FordCarInfo("Ford F-150 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]),
|
||||
CAR.MAVERICK_MK1: [
|
||||
FordCarInfo("Ford Maverick 2022", "LARIAT Luxury"),
|
||||
FordCarInfo("Ford Maverick 2023", "Co-Pilot360 Assist"),
|
||||
],
|
||||
}
|
||||
@dataclass(frozen=True)
|
||||
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}
|
||||
|
||||
|
||||
DATA_IDENTIFIER_FORD_ASBUILT = 0xDE00
|
||||
|
||||
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=[
|
||||
@@ -124,18 +185,31 @@ FW_QUERY_CONFIG = FwQueryConfig(
|
||||
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
|
||||
],
|
||||
)
|
||||
|
||||
CAR_INFO = CAR.create_carinfo_map()
|
||||
DBC = CAR.create_dbc_map()
|
||||
|
||||
@@ -3,16 +3,16 @@ import capnp
|
||||
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)):
|
||||
|
||||
@@ -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 @@ REQUESTS = [(brand, config, r) for brand, config in FW_QUERY_CONFIGS.items() for
|
||||
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) -> 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()
|
||||
|
||||
|
||||
@@ -152,11 +152,7 @@ class CarInterface(CarInterfaceBase):
|
||||
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 @@ class CarInterface(CarInterfaceBase):
|
||||
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 @@ class CarInterface(CarInterfaceBase):
|
||||
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 @@ class CarInterface(CarInterfaceBase):
|
||||
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)
|
||||
|
||||
+88
-46
@@ -1,10 +1,8 @@
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum, StrEnum
|
||||
from typing import Dict, List, Union
|
||||
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
|
||||
|
||||
@@ -62,23 +60,6 @@ class CarControllerParams:
|
||||
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 <a href="https://github.com/commaai/openpilot/wiki/GM#hardware" target="_blank">community built ASCM harness</a>. ' +
|
||||
@@ -98,28 +79,88 @@ class GMCarInfo(CarInfo):
|
||||
self.footnotes.append(Footnote.OBD_II)
|
||||
|
||||
|
||||
CAR_INFO: Dict[str, Union[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(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'))
|
||||
|
||||
|
||||
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:
|
||||
@@ -181,11 +222,12 @@ FW_QUERY_CONFIG = FwQueryConfig(
|
||||
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()
|
||||
|
||||
@@ -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
|
||||
@@ -126,7 +125,7 @@ class HondaCarInfo(CarInfo):
|
||||
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),
|
||||
@@ -220,6 +219,8 @@ FW_QUERY_CONFIG = FwQueryConfig(
|
||||
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
|
||||
|
||||
@@ -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
|
||||
@@ -173,7 +172,7 @@ class HyundaiCarInfo(CarInfo):
|
||||
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])),
|
||||
@@ -341,7 +340,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:
|
||||
@@ -360,12 +359,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)
|
||||
|
||||
+24
-12
@@ -7,7 +7,8 @@ import tomllib
|
||||
from abc import abstractmethod, ABC
|
||||
from difflib import SequenceMatcher
|
||||
from enum import StrEnum
|
||||
from typing import Any, Dict, Optional, Tuple, List, Callable, NamedTuple
|
||||
from typing import Any, NamedTuple
|
||||
from collections.abc import Callable
|
||||
|
||||
from cereal import car
|
||||
from openpilot.common.basedir import BASEDIR
|
||||
@@ -17,6 +18,7 @@ from openpilot.common.numpy_fast import clip
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.common.realtime import DT_CTRL
|
||||
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.desire_helper import LANE_CHANGE_SPEED_MIN
|
||||
from openpilot.selfdrive.controls.lib.drive_helpers import V_CRUISE_MAX, V_CRUISE_UNSET, get_friction
|
||||
from openpilot.selfdrive.controls.lib.events import Events
|
||||
@@ -258,15 +260,25 @@ class CarInterfaceBase(ABC):
|
||||
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"):
|
||||
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)
|
||||
|
||||
params = Params()
|
||||
@@ -302,8 +314,8 @@ class CarInterfaceBase(ABC):
|
||||
|
||||
@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: Platform, fingerprint: dict[int, dict[int, int]],
|
||||
car_fw: list[car.CarParams.CarFw], experimental_long: bool, docs: bool):
|
||||
raise NotImplementedError
|
||||
|
||||
@staticmethod
|
||||
@@ -395,7 +407,7 @@ class CarInterfaceBase(ABC):
|
||||
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:
|
||||
@@ -429,7 +441,7 @@ class CarInterfaceBase(ABC):
|
||||
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, c, extra_gears=None, pcm_enable=True, allow_enable=True,
|
||||
@@ -860,11 +872,11 @@ class CarStateBase(ABC):
|
||||
return customStockLong
|
||||
|
||||
@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,
|
||||
@@ -901,7 +913,7 @@ INTERFACE_ATTR_FILE = {
|
||||
|
||||
# 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
|
||||
@@ -934,7 +946,7 @@ class NanoFFModel:
|
||||
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):
|
||||
@@ -949,7 +961,7 @@ class NanoFFModel:
|
||||
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'])
|
||||
|
||||
@@ -12,7 +12,7 @@ from panda.python.uds import CanClient, IsoTpMessage, FUNCTIONAL_ADDRS, get_rx_a
|
||||
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
|
||||
|
||||
@@ -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
|
||||
@@ -49,7 +48,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"),
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -19,25 +19,13 @@ class CarInterface(CarInterfaceBase):
|
||||
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
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
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
|
||||
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
|
||||
|
||||
@@ -21,29 +19,57 @@ class CarControllerParams:
|
||||
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, Optional[Union[NissanCarInfo, List[NissanCarInfo]]]] = {
|
||||
CAR.XTRAIL: NissanCarInfo("Nissan X-Trail 2017"),
|
||||
CAR.LEAF: NissanCarInfo("Nissan Leaf 2018-23", video_link="https://youtu.be/vaMbtAh_0cY"),
|
||||
CAR.LEAF_IC: NissanCarInfo("Nissan Leaf Instrument Cluster 2018-23", video_link="https://youtu.be/vaMbtAh_0cY"), # 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 = NissanPlaformConfig(
|
||||
"NISSAN LEAF 2018 Instrument Cluster",
|
||||
NissanCarInfo("Nissan Leaf Instrument Cluster 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)
|
||||
)
|
||||
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])
|
||||
@@ -89,11 +115,3 @@ FW_QUERY_CONFIG = FwQueryConfig(
|
||||
),
|
||||
]],
|
||||
)
|
||||
|
||||
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),
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from cereal import car
|
||||
from panda import Panda
|
||||
from openpilot.selfdrive.car import get_safety_config, create_mads_event
|
||||
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, SubaruFlagsSP
|
||||
@@ -13,7 +14,7 @@ GearShifter = car.CarState.GearShifter
|
||||
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:
|
||||
@@ -50,10 +51,6 @@ class CarInterface(CarInterfaceBase):
|
||||
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
|
||||
|
||||
if candidate in (CAR.ASCENT, CAR.ASCENT_2023):
|
||||
ret.mass = 2031.
|
||||
ret.wheelbase = 2.89
|
||||
ret.centerToFront = ret.wheelbase * 0.5
|
||||
ret.steerRatio = 13.5
|
||||
ret.steerActuatorDelay = 0.3 # end-to-end angle controller
|
||||
ret.lateralTuning.init('pid')
|
||||
ret.lateralTuning.pid.kf = 0.00003
|
||||
@@ -61,10 +58,6 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.0025, 0.1], [0.00025, 0.01]]
|
||||
|
||||
elif candidate == CAR.IMPREZA:
|
||||
ret.mass = 1568.
|
||||
ret.wheelbase = 2.67
|
||||
ret.centerToFront = ret.wheelbase * 0.5
|
||||
ret.steerRatio = 15
|
||||
ret.steerActuatorDelay = 0.4 # end-to-end angle controller
|
||||
ret.lateralTuning.init('pid')
|
||||
ret.lateralTuning.pid.kf = 0.00005
|
||||
@@ -79,58 +72,31 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.133, 0.2], [0.0133, 0.02]]
|
||||
|
||||
elif candidate == CAR.IMPREZA_2020:
|
||||
ret.mass = 1480.
|
||||
ret.wheelbase = 2.67
|
||||
ret.centerToFront = ret.wheelbase * 0.5
|
||||
ret.steerRatio = 17 # learned, 14 stock
|
||||
ret.lateralTuning.init('pid')
|
||||
ret.lateralTuning.pid.kf = 0.00005
|
||||
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0., 14., 23.], [0., 14., 23.]]
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.045, 0.042, 0.20], [0.04, 0.035, 0.045]]
|
||||
|
||||
elif candidate == CAR.CROSSTREK_HYBRID:
|
||||
ret.mass = 1668.
|
||||
ret.wheelbase = 2.67
|
||||
ret.centerToFront = ret.wheelbase * 0.5
|
||||
ret.steerRatio = 17
|
||||
ret.steerActuatorDelay = 0.1
|
||||
|
||||
elif candidate in (CAR.FORESTER, CAR.FORESTER_2022, CAR.FORESTER_HYBRID):
|
||||
ret.mass = 1568.
|
||||
ret.wheelbase = 2.67
|
||||
ret.centerToFront = ret.wheelbase * 0.5
|
||||
ret.steerRatio = 17 # learned, 14 stock
|
||||
ret.lateralTuning.init('pid')
|
||||
ret.lateralTuning.pid.kf = 0.000038
|
||||
ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0., 14., 23.], [0., 14., 23.]]
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.01, 0.065, 0.2], [0.001, 0.015, 0.025]]
|
||||
|
||||
elif candidate in (CAR.OUTBACK, CAR.LEGACY, CAR.OUTBACK_2023):
|
||||
ret.mass = 1568.
|
||||
ret.wheelbase = 2.67
|
||||
ret.centerToFront = ret.wheelbase * 0.5
|
||||
ret.steerRatio = 17
|
||||
ret.steerActuatorDelay = 0.1
|
||||
|
||||
elif candidate in (CAR.FORESTER_PREGLOBAL, CAR.OUTBACK_PREGLOBAL_2018):
|
||||
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_SUBARU_PREGLOBAL_REVERSED_DRIVER_TORQUE # Outback 2018-2019 and Forester have reversed driver torque signal
|
||||
ret.mass = 1568
|
||||
ret.wheelbase = 2.67
|
||||
ret.centerToFront = ret.wheelbase * 0.5
|
||||
ret.steerRatio = 20 # learned, 14 stock
|
||||
|
||||
elif candidate == CAR.LEGACY_PREGLOBAL:
|
||||
ret.mass = 1568
|
||||
ret.wheelbase = 2.67
|
||||
ret.centerToFront = ret.wheelbase * 0.5
|
||||
ret.steerRatio = 12.5 # 14.5 stock
|
||||
ret.steerActuatorDelay = 0.15
|
||||
|
||||
elif candidate == CAR.OUTBACK_PREGLOBAL:
|
||||
ret.mass = 1568
|
||||
ret.wheelbase = 2.67
|
||||
ret.centerToFront = ret.wheelbase * 0.5
|
||||
ret.steerRatio = 20 # learned, 14 stock
|
||||
pass
|
||||
else:
|
||||
raise ValueError(f"unknown car: {candidate}")
|
||||
|
||||
|
||||
+105
-67
@@ -1,11 +1,10 @@
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum, IntFlag, StrEnum
|
||||
from enum import Enum, IntFlag
|
||||
from panda import Panda
|
||||
from typing import Dict, List, Union
|
||||
|
||||
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 CarFootnote, CarHarness, CarInfo, CarParts, Tool, Column
|
||||
from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries, p16
|
||||
|
||||
@@ -75,27 +74,6 @@ class CanBus:
|
||||
camera = 2
|
||||
|
||||
|
||||
class CAR(StrEnum):
|
||||
# Global platform
|
||||
ASCENT = "SUBARU ASCENT LIMITED 2019"
|
||||
ASCENT_2023 = "SUBARU ASCENT 2023"
|
||||
IMPREZA = "SUBARU IMPREZA LIMITED 2019"
|
||||
IMPREZA_2020 = "SUBARU IMPREZA SPORT 2020"
|
||||
FORESTER = "SUBARU FORESTER 2019"
|
||||
OUTBACK = "SUBARU OUTBACK 6TH GEN"
|
||||
CROSSTREK_HYBRID = "SUBARU CROSSTREK HYBRID 2020"
|
||||
FORESTER_HYBRID = "SUBARU FORESTER HYBRID 2020"
|
||||
LEGACY = "SUBARU LEGACY 7TH GEN"
|
||||
FORESTER_2022 = "SUBARU FORESTER 2022"
|
||||
OUTBACK_2023 = "SUBARU OUTBACK 7TH GEN"
|
||||
|
||||
# Pre-global
|
||||
FORESTER_PREGLOBAL = "SUBARU FORESTER 2017 - 2018"
|
||||
LEGACY_PREGLOBAL = "SUBARU LEGACY 2015 - 2018"
|
||||
OUTBACK_PREGLOBAL = "SUBARU OUTBACK 2015 - 2017"
|
||||
OUTBACK_PREGLOBAL_2018 = "SUBARU OUTBACK 2018 - 2019"
|
||||
|
||||
|
||||
class Footnote(Enum):
|
||||
GLOBAL = CarFootnote(
|
||||
"In the non-US market, openpilot requires the car to come equipped with EyeSight with Lane Keep Assistance.",
|
||||
@@ -109,7 +87,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])
|
||||
@@ -117,32 +95,107 @@ class SubaruCarInfo(CarInfo):
|
||||
if CP.experimentalLongitudinalAvailable:
|
||||
self.footnotes.append(Footnote.EXP_LONG)
|
||||
|
||||
CAR_INFO: Dict[str, Union[SubaruCarInfo, List[SubaruCarInfo]]] = {
|
||||
CAR.ASCENT: SubaruCarInfo("Subaru Ascent 2019-21", "All"),
|
||||
CAR.OUTBACK: SubaruCarInfo("Subaru Outback 2020-22", "All", car_parts=CarParts.common([CarHarness.subaru_b])),
|
||||
CAR.LEGACY: SubaruCarInfo("Subaru Legacy 2020-22", "All", car_parts=CarParts.common([CarHarness.subaru_b])),
|
||||
CAR.IMPREZA: [
|
||||
SubaruCarInfo("Subaru Impreza 2017-19"),
|
||||
SubaruCarInfo("Subaru Crosstrek 2018-19", video_link="https://youtu.be/Agww7oE1k-s?t=26"),
|
||||
SubaruCarInfo("Subaru XV 2018-19", video_link="https://youtu.be/Agww7oE1k-s?t=26"),
|
||||
],
|
||||
CAR.IMPREZA_2020: [
|
||||
SubaruCarInfo("Subaru Impreza 2020-22"),
|
||||
SubaruCarInfo("Subaru Crosstrek 2020-23"),
|
||||
SubaruCarInfo("Subaru XV 2020-21"),
|
||||
],
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SubaruPlatformConfig(PlatformConfig):
|
||||
dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('subaru_global_2017_generated', None))
|
||||
|
||||
|
||||
class CAR(Platforms):
|
||||
# Global platform
|
||||
ASCENT = SubaruPlatformConfig(
|
||||
"SUBARU ASCENT LIMITED 2019",
|
||||
SubaruCarInfo("Subaru Ascent 2019-21", "All"),
|
||||
specs=CarSpecs(mass=2031, wheelbase=2.89, steerRatio=13.5),
|
||||
)
|
||||
OUTBACK = SubaruPlatformConfig(
|
||||
"SUBARU OUTBACK 6TH GEN",
|
||||
SubaruCarInfo("Subaru Outback 2020-22", "All", car_parts=CarParts.common([CarHarness.subaru_b])),
|
||||
specs=CarSpecs(mass=1568, wheelbase=2.67, steerRatio=17),
|
||||
)
|
||||
LEGACY = SubaruPlatformConfig(
|
||||
"SUBARU LEGACY 7TH GEN",
|
||||
SubaruCarInfo("Subaru Legacy 2020-22", "All", car_parts=CarParts.common([CarHarness.subaru_b])),
|
||||
specs=OUTBACK.specs,
|
||||
)
|
||||
IMPREZA = SubaruPlatformConfig(
|
||||
"SUBARU IMPREZA LIMITED 2019",
|
||||
[
|
||||
SubaruCarInfo("Subaru Impreza 2017-19"),
|
||||
SubaruCarInfo("Subaru Crosstrek 2018-19", video_link="https://youtu.be/Agww7oE1k-s?t=26"),
|
||||
SubaruCarInfo("Subaru XV 2018-19", video_link="https://youtu.be/Agww7oE1k-s?t=26"),
|
||||
],
|
||||
specs=CarSpecs(mass=1568, wheelbase=2.67, steerRatio=15),
|
||||
)
|
||||
IMPREZA_2020 = SubaruPlatformConfig(
|
||||
"SUBARU IMPREZA SPORT 2020",
|
||||
[
|
||||
SubaruCarInfo("Subaru Impreza 2020-22"),
|
||||
SubaruCarInfo("Subaru Crosstrek 2020-23"),
|
||||
SubaruCarInfo("Subaru XV 2020-21"),
|
||||
],
|
||||
specs=CarSpecs(mass=1480, wheelbase=2.67, steerRatio=17),
|
||||
)
|
||||
# TODO: is there an XV and Impreza too?
|
||||
CAR.CROSSTREK_HYBRID: SubaruCarInfo("Subaru Crosstrek Hybrid 2020", car_parts=CarParts.common([CarHarness.subaru_b])),
|
||||
CAR.FORESTER_HYBRID: SubaruCarInfo("Subaru Forester Hybrid 2020"),
|
||||
CAR.FORESTER: SubaruCarInfo("Subaru Forester 2019-21", "All"),
|
||||
CAR.FORESTER_PREGLOBAL: SubaruCarInfo("Subaru Forester 2017-18"),
|
||||
CAR.LEGACY_PREGLOBAL: SubaruCarInfo("Subaru Legacy 2015-18"),
|
||||
CAR.OUTBACK_PREGLOBAL: SubaruCarInfo("Subaru Outback 2015-17"),
|
||||
CAR.OUTBACK_PREGLOBAL_2018: SubaruCarInfo("Subaru Outback 2018-19"),
|
||||
CAR.FORESTER_2022: SubaruCarInfo("Subaru Forester 2022-24", "All", car_parts=CarParts.common([CarHarness.subaru_c])),
|
||||
CAR.OUTBACK_2023: SubaruCarInfo("Subaru Outback 2023", "All", car_parts=CarParts.common([CarHarness.subaru_d])),
|
||||
CAR.ASCENT_2023: SubaruCarInfo("Subaru Ascent 2023", "All", car_parts=CarParts.common([CarHarness.subaru_d])),
|
||||
}
|
||||
CROSSTREK_HYBRID = SubaruPlatformConfig(
|
||||
"SUBARU CROSSTREK HYBRID 2020",
|
||||
SubaruCarInfo("Subaru Crosstrek Hybrid 2020", car_parts=CarParts.common([CarHarness.subaru_b])),
|
||||
dbc_dict('subaru_global_2020_hybrid_generated', None),
|
||||
specs=CarSpecs(mass=1668, wheelbase=2.67, steerRatio=17),
|
||||
)
|
||||
FORESTER = SubaruPlatformConfig(
|
||||
"SUBARU FORESTER 2019",
|
||||
SubaruCarInfo("Subaru Forester 2019-21", "All"),
|
||||
specs=CarSpecs(mass=1568, wheelbase=2.67, steerRatio=17),
|
||||
)
|
||||
FORESTER_HYBRID = SubaruPlatformConfig(
|
||||
"SUBARU FORESTER HYBRID 2020",
|
||||
SubaruCarInfo("Subaru Forester Hybrid 2020"),
|
||||
dbc_dict('subaru_global_2020_hybrid_generated', None),
|
||||
specs=FORESTER.specs,
|
||||
)
|
||||
# Pre-global
|
||||
FORESTER_PREGLOBAL = SubaruPlatformConfig(
|
||||
"SUBARU FORESTER 2017 - 2018",
|
||||
SubaruCarInfo("Subaru Forester 2017-18"),
|
||||
dbc_dict('subaru_forester_2017_generated', None),
|
||||
specs=CarSpecs(mass=1568, wheelbase=2.67, steerRatio=20),
|
||||
)
|
||||
LEGACY_PREGLOBAL = SubaruPlatformConfig(
|
||||
"SUBARU LEGACY 2015 - 2018",
|
||||
SubaruCarInfo("Subaru Legacy 2015-18"),
|
||||
dbc_dict('subaru_outback_2015_generated', None),
|
||||
specs=CarSpecs(mass=1568, wheelbase=2.67, steerRatio=12.5),
|
||||
)
|
||||
OUTBACK_PREGLOBAL = SubaruPlatformConfig(
|
||||
"SUBARU OUTBACK 2015 - 2017",
|
||||
SubaruCarInfo("Subaru Outback 2015-17"),
|
||||
dbc_dict('subaru_outback_2015_generated', None),
|
||||
specs=FORESTER_PREGLOBAL.specs,
|
||||
)
|
||||
OUTBACK_PREGLOBAL_2018 = SubaruPlatformConfig(
|
||||
"SUBARU OUTBACK 2018 - 2019",
|
||||
SubaruCarInfo("Subaru Outback 2018-19"),
|
||||
dbc_dict('subaru_outback_2019_generated', None),
|
||||
specs=FORESTER_PREGLOBAL.specs,
|
||||
)
|
||||
# Angle LKAS
|
||||
FORESTER_2022 = SubaruPlatformConfig(
|
||||
"SUBARU FORESTER 2022",
|
||||
SubaruCarInfo("Subaru Forester 2022-24", "All", car_parts=CarParts.common([CarHarness.subaru_c])),
|
||||
specs=FORESTER.specs,
|
||||
)
|
||||
OUTBACK_2023 = SubaruPlatformConfig(
|
||||
"SUBARU OUTBACK 7TH GEN",
|
||||
SubaruCarInfo("Subaru Outback 2023", "All", car_parts=CarParts.common([CarHarness.subaru_d])),
|
||||
specs=OUTBACK.specs,
|
||||
)
|
||||
ASCENT_2023 = SubaruPlatformConfig(
|
||||
"SUBARU ASCENT 2023",
|
||||
SubaruCarInfo("Subaru Ascent 2023", "All", car_parts=CarParts.common([CarHarness.subaru_d])),
|
||||
specs=ASCENT.specs,
|
||||
)
|
||||
|
||||
|
||||
LKAS_ANGLE = {CAR.FORESTER_2022, CAR.OUTBACK_2023, CAR.ASCENT_2023}
|
||||
GLOBAL_GEN2 = {CAR.OUTBACK, CAR.LEGACY, CAR.OUTBACK_2023, CAR.ASCENT_2023}
|
||||
@@ -193,20 +246,5 @@ FW_QUERY_CONFIG = FwQueryConfig(
|
||||
}
|
||||
)
|
||||
|
||||
DBC = {
|
||||
CAR.ASCENT: dbc_dict('subaru_global_2017_generated', None),
|
||||
CAR.ASCENT_2023: dbc_dict('subaru_global_2017_generated', None),
|
||||
CAR.IMPREZA: dbc_dict('subaru_global_2017_generated', None),
|
||||
CAR.IMPREZA_2020: dbc_dict('subaru_global_2017_generated', None),
|
||||
CAR.FORESTER: dbc_dict('subaru_global_2017_generated', None),
|
||||
CAR.FORESTER_2022: dbc_dict('subaru_global_2017_generated', None),
|
||||
CAR.OUTBACK: dbc_dict('subaru_global_2017_generated', None),
|
||||
CAR.FORESTER_HYBRID: dbc_dict('subaru_global_2020_hybrid_generated', None),
|
||||
CAR.CROSSTREK_HYBRID: dbc_dict('subaru_global_2020_hybrid_generated', None),
|
||||
CAR.OUTBACK_2023: dbc_dict('subaru_global_2017_generated', None),
|
||||
CAR.LEGACY: dbc_dict('subaru_global_2017_generated', None),
|
||||
CAR.FORESTER_PREGLOBAL: dbc_dict('subaru_forester_2017_generated', None),
|
||||
CAR.LEGACY_PREGLOBAL: dbc_dict('subaru_outback_2015_generated', None),
|
||||
CAR.OUTBACK_PREGLOBAL: dbc_dict('subaru_outback_2015_generated', None),
|
||||
CAR.OUTBACK_PREGLOBAL_2018: dbc_dict('subaru_outback_2019_generated', None),
|
||||
}
|
||||
CAR_INFO = CAR.create_carinfo_map()
|
||||
DBC = CAR.create_dbc_map()
|
||||
|
||||
@@ -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"),
|
||||
}
|
||||
|
||||
@@ -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 @@ non_tested_cars = [
|
||||
|
||||
class CarTestRoute(NamedTuple):
|
||||
route: str
|
||||
car_model: Optional[str]
|
||||
segment: Optional[int] = None
|
||||
car_model: str | None
|
||||
segment: int | None = None
|
||||
|
||||
|
||||
routes = [
|
||||
|
||||
@@ -20,7 +20,7 @@ class TestCarDocs(unittest.TestCase):
|
||||
|
||||
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 @@ class TestCarDocs(unittest.TestCase):
|
||||
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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -263,13 +263,13 @@ class TestFwFingerprintTiming(unittest.TestCase):
|
||||
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.05, 2: 6.95}
|
||||
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,
|
||||
@@ -277,10 +277,10 @@ class TestFwFingerprintTiming(unittest.TestCase):
|
||||
'subaru': 0.45,
|
||||
'tesla': 0.2,
|
||||
'toyota': 1.6,
|
||||
'volkswagen': 0.2,
|
||||
'volkswagen': 0.65,
|
||||
},
|
||||
2: {
|
||||
'ford': 0.3,
|
||||
'ford': 1.6,
|
||||
'hyundai': 1.85,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ from collections import defaultdict
|
||||
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 @@ ABOVE_LIMITS_CARS = [
|
||||
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)])
|
||||
|
||||
@@ -8,7 +8,6 @@ import unittest
|
||||
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 @@ MAX_EXAMPLES = int(os.environ.get("MAX_EXAMPLES", "300"))
|
||||
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):
|
||||
@@ -50,7 +49,7 @@ def get_test_cases() -> List[Tuple[str, Optional[CarTestRoute]]]:
|
||||
|
||||
for i, c in enumerate(sorted(all_known_cars())):
|
||||
if i % NUM_JOBS == JOB_ID:
|
||||
test_cases.extend(sorted((c.value, r) for r in routes_by_car.get(c, (None,))))
|
||||
test_cases.extend(sorted((c, r) for r in routes_by_car.get(c, (None,))))
|
||||
|
||||
else:
|
||||
segment_list = read_segment_list(os.path.join(BASEDIR, 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 @@ class TestCarModelBase(unittest.TestCase):
|
||||
|
||||
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):
|
||||
|
||||
@@ -573,6 +573,7 @@ FW_VERSIONS = {
|
||||
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 @@ FW_VERSIONS = {
|
||||
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 @@ FW_VERSIONS = {
|
||||
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',
|
||||
|
||||
@@ -2,7 +2,6 @@ import re
|
||||
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
|
||||
@@ -104,7 +103,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"),
|
||||
@@ -257,7 +256,7 @@ STATIC_DSU_MSGS = [
|
||||
]
|
||||
|
||||
|
||||
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:
|
||||
@@ -301,7 +300,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():
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
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
|
||||
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)}
|
||||
@@ -1,10 +1,9 @@
|
||||
from cereal import car
|
||||
from panda import Panda
|
||||
from openpilot.common.conversions import Conversions as CV
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.selfdrive.car import get_safety_config, create_mads_event
|
||||
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, \
|
||||
BUTTON_STATES, VolkswagenFlagsSP
|
||||
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
@@ -76,14 +75,17 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
# Global lateral tuning defaults, can be overridden per-vehicle
|
||||
|
||||
ret.steerActuatorDelay = 0.1
|
||||
ret.steerLimitTimer = 0.4
|
||||
ret.steerRatio = 15.6 # Let the params learner figure this out
|
||||
ret.lateralTuning.pid.kpBP = [0.]
|
||||
ret.lateralTuning.pid.kiBP = [0.]
|
||||
ret.lateralTuning.pid.kf = 0.00006
|
||||
ret.lateralTuning.pid.kpV = [0.6]
|
||||
ret.lateralTuning.pid.kiV = [0.2]
|
||||
if candidate in PQ_CARS:
|
||||
ret.steerActuatorDelay = 0.2
|
||||
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
|
||||
else:
|
||||
ret.steerActuatorDelay = 0.1
|
||||
ret.lateralTuning.pid.kpBP = [0.]
|
||||
ret.lateralTuning.pid.kiBP = [0.]
|
||||
ret.lateralTuning.pid.kf = 0.00006
|
||||
ret.lateralTuning.pid.kpV = [0.6]
|
||||
ret.lateralTuning.pid.kiV = [0.2]
|
||||
|
||||
# Global longitudinal tuning defaults, can be overridden per-vehicle
|
||||
|
||||
@@ -113,125 +115,6 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
# 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
|
||||
ret.steerActuatorDelay = 0.2
|
||||
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
|
||||
|
||||
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
|
||||
ret.steerActuatorDelay = 0.2
|
||||
|
||||
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
|
||||
|
||||
+221
-130
@@ -1,12 +1,12 @@
|
||||
from collections import defaultdict, namedtuple
|
||||
from collections import namedtuple
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum, IntFlag, StrEnum
|
||||
from typing import Dict, List, Union
|
||||
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
|
||||
@@ -130,48 +130,17 @@ BUTTON_STATES = {
|
||||
}
|
||||
|
||||
|
||||
# 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
|
||||
@dataclass(frozen=True)
|
||||
class VolkswagenMQBPlatformConfig(PlatformConfig):
|
||||
dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('vw_mqb_2010', None))
|
||||
|
||||
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(frozen=True)
|
||||
class VolkswagenPQPlatformConfig(PlatformConfig):
|
||||
dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('vw_golf_mk4', None))
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class VolkswagenCarSpecs(CarSpecs):
|
||||
steerRatio: float = field(default=15.6)
|
||||
|
||||
class Footnote(Enum):
|
||||
KAMIQ = CarFootnote(
|
||||
@@ -207,90 +176,202 @@ class VWCarInfo(CarInfo):
|
||||
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, Union[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.
|
||||
@@ -310,17 +391,27 @@ VOLKSWAGEN_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER +
|
||||
VOLKSWAGEN_RX_OFFSET = 0x6a
|
||||
|
||||
FW_QUERY_CONFIG = FwQueryConfig(
|
||||
requests=[
|
||||
# TODO: add back whitelists after we gather enough data
|
||||
requests=[request for bus, obd_multiplexing in [(1, True), (1, False), (0, False)] for request in [
|
||||
Request(
|
||||
[VOLKSWAGEN_VERSION_REQUEST_MULTI],
|
||||
[VOLKSWAGEN_VERSION_RESPONSE],
|
||||
whitelist_ecus=[Ecu.srs, Ecu.eps, Ecu.fwdRadar],
|
||||
# whitelist_ecus=[Ecu.srs, Ecu.eps, Ecu.fwdRadar],
|
||||
rx_offset=VOLKSWAGEN_RX_OFFSET,
|
||||
bus=bus,
|
||||
logging=(bus != 1 or not obd_multiplexing),
|
||||
obd_multiplexing=obd_multiplexing,
|
||||
),
|
||||
Request(
|
||||
[VOLKSWAGEN_VERSION_REQUEST_MULTI],
|
||||
[VOLKSWAGEN_VERSION_RESPONSE],
|
||||
whitelist_ecus=[Ecu.engine, Ecu.transmission],
|
||||
# whitelist_ecus=[Ecu.engine, Ecu.transmission],
|
||||
bus=bus,
|
||||
logging=(bus != 1 or not obd_multiplexing),
|
||||
obd_multiplexing=obd_multiplexing,
|
||||
),
|
||||
],
|
||||
]],
|
||||
)
|
||||
|
||||
CAR_INFO = CAR.create_carinfo_map()
|
||||
DBC = CAR.create_dbc_map()
|
||||
|
||||
@@ -3,7 +3,6 @@ import os
|
||||
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 @@ with open(os.path.join(BASEDIR, "selfdrive/controls/lib/alerts_offroad.json")) a
|
||||
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:
|
||||
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 @@ class AlertEntry:
|
||||
|
||||
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 @@ class AlertManager:
|
||||
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:
|
||||
|
||||
@@ -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 @@ EVENT_NAME = {v: k for k, v in EventName.schema.enumerants.items()}
|
||||
|
||||
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 @@ class Events:
|
||||
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 @@ class Alert:
|
||||
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}"
|
||||
@@ -364,7 +364,7 @@ def speed_limit_adjust_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.
|
||||
|
||||
|
||||
|
||||
EVENTS: Dict[int, Dict[str, Union[Alert, AlertCallbackType]]] = {
|
||||
EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = {
|
||||
# ********** events with no alerts **********
|
||||
|
||||
EventName.stockFcw: {},
|
||||
@@ -1150,7 +1150,7 @@ if __name__ == '__main__':
|
||||
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()
|
||||
@@ -1162,7 +1162,7 @@ if __name__ == '__main__':
|
||||
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)
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ x_dot = A*x + B*u
|
||||
|
||||
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:
|
||||
|
||||
@@ -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
|
||||
@@ -127,7 +127,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):
|
||||
@@ -168,8 +168,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, CP: car.CarParams, 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, CP: car.CarParams, 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)
|
||||
@@ -198,14 +198,14 @@ class RadarD:
|
||||
def __init__(self, radar_ts: float, CP: car.CarParams, 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
|
||||
|
||||
@@ -3,7 +3,6 @@ import argparse
|
||||
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 @@ if __name__ == "__main__":
|
||||
|
||||
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 == '':
|
||||
|
||||
@@ -3,7 +3,7 @@ import argparse
|
||||
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 @@ if __name__ == "__main__":
|
||||
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:
|
||||
|
||||
@@ -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 @@ TO_CHECK = ['carState']
|
||||
if __name__ == "__main__":
|
||||
sm = messaging.SubMaster(TO_CHECK)
|
||||
|
||||
prev_t: Dict[str, float] = {}
|
||||
prev_t: dict[str, float] = {}
|
||||
|
||||
while True:
|
||||
sm.update()
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -4,7 +4,7 @@ import math
|
||||
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 @@ if __name__ == "__main__":
|
||||
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
|
||||
|
||||
@@ -66,12 +66,12 @@ if __name__ == "__main__":
|
||||
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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ from collections import defaultdict
|
||||
|
||||
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 @@ if __name__ == "__main__":
|
||||
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 @@ if __name__ == "__main__":
|
||||
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:
|
||||
|
||||
@@ -10,7 +10,7 @@ import gc
|
||||
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 @@ class Calibrator:
|
||||
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:
|
||||
if not np.isfinite(rpy_init).all():
|
||||
self.rpy = RPY_INIT.copy()
|
||||
else:
|
||||
@@ -125,7 +125,7 @@ class Calibrator:
|
||||
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 @@ class Calibrator:
|
||||
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))
|
||||
|
||||
@@ -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 @@ class NPQueue:
|
||||
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 @@ class NPQueue:
|
||||
|
||||
|
||||
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 @@ class PointBuckets:
|
||||
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) -> 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)
|
||||
|
||||
|
||||
@@ -691,10 +691,9 @@ int Localizer::locationd_thread() {
|
||||
|
||||
this->configure_gnss_source(source);
|
||||
const std::initializer_list<const char *> 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();
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -4,7 +4,6 @@ import os
|
||||
import signal
|
||||
import sys
|
||||
import traceback
|
||||
from typing import List, Tuple, Union
|
||||
|
||||
from cereal import custom
|
||||
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"),
|
||||
@@ -200,7 +199,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:
|
||||
@@ -235,7 +234,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)
|
||||
|
||||
@@ -4,7 +4,7 @@ import signal
|
||||
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
|
||||
always_watchdog = False
|
||||
watchdog_seen = False
|
||||
shutting_down = False
|
||||
@@ -112,7 +112,7 @@ class ManagerProcess(ABC):
|
||||
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) -> int | None:
|
||||
if self.proc is None:
|
||||
return None
|
||||
|
||||
@@ -279,7 +279,7 @@ class DaemonProcess(ManagerProcess):
|
||||
|
||||
|
||||
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 = []
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import time
|
||||
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 @@ class ModelState:
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -43,7 +42,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, model_use_lateral_planner: bool) -> None:
|
||||
@@ -180,7 +179,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
|
||||
|
||||
@@ -4,9 +4,8 @@ import pathlib
|
||||
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
|
||||
|
||||
@@ -6,7 +6,6 @@ import numpy as np
|
||||
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
|
||||
@@ -53,7 +52,7 @@ class FrameMeta:
|
||||
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
|
||||
@@ -111,14 +110,14 @@ class ModelState:
|
||||
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:]
|
||||
@@ -331,7 +330,7 @@ def main(demo=False):
|
||||
'lateral_control_params': lateral_control_params
|
||||
}
|
||||
|
||||
inputs:Dict[str, np.ndarray] = {
|
||||
inputs:dict[str, np.ndarray] = {
|
||||
'desire': vec_desire,
|
||||
'traffic_convention': traffic_convention,
|
||||
**_inputs,
|
||||
|
||||
@@ -5,7 +5,6 @@ import time
|
||||
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
|
||||
@@ -44,7 +43,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
|
||||
|
||||
@@ -63,7 +62,7 @@ class ModelState:
|
||||
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()
|
||||
|
||||
@@ -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 @@ class Parser:
|
||||
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))
|
||||
|
||||
@@ -3,7 +3,7 @@ import itertools
|
||||
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:
|
||||
|
||||
@@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
|
||||
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) -> 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
|
||||
|
||||
|
||||
+3
-3
@@ -5,7 +5,7 @@ import time
|
||||
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 @@ class StatLog:
|
||||
|
||||
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 main() -> NoReturn:
|
||||
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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user