Merge remote-tracking branch 'upstream/master' into gm-inactive-rate

pull/26196/head
Shane Smiskol 3 years ago
commit 1e59cad383
  1. 2
      cereal
  2. 93
      poetry.lock
  3. 5
      pyproject.toml
  4. 1
      selfdrive/car/gm/carcontroller.py
  5. 43
      selfdrive/car/gm/gmcan.py
  6. 3
      selfdrive/car/volkswagen/values.py
  7. 35
      selfdrive/locationd/calibrationd.py
  8. 2
      selfdrive/test/process_replay/ref_commit
  9. 391
      selfdrive/ui/translations/main_ar.ts
  10. 391
      selfdrive/ui/translations/main_nl.ts
  11. 391
      selfdrive/ui/translations/main_pl.ts
  12. 391
      selfdrive/ui/translations/main_th.ts
  13. 33
      tools/cabana/binaryview.cc
  14. 3
      tools/cabana/binaryview.h
  15. 9
      tools/cabana/canmessages.cc
  16. 18
      tools/cabana/dbcmanager.cc
  17. 2
      tools/cabana/dbcmanager.h
  18. 75
      tools/cabana/detailwidget.cc
  19. 6
      tools/cabana/detailwidget.h
  20. 6
      tools/cabana/mainwin.cc
  21. 1
      tools/cabana/messageswidget.cc
  22. 84
      tools/cabana/signaledit.cc
  23. 23
      tools/cabana/signaledit.h
  24. 7
      tools/replay/tests/test_replay.cc
  25. 3
      update_requirements.sh

@ -1 +1 @@
Subproject commit 79e6e4c26dd12ba979a5fb872b4e68a707c32203
Subproject commit 38133307b2e6036e76684b39878e79212e545e06

93
poetry.lock generated

@ -108,6 +108,7 @@ python-versions = "*"
[package.source]
type = "url"
url = "https://github.com/commaai/apex/releases/download/pytorch1.10.0%2Bcu11.1/apex-0.1-cp38-cp38-linux_x86_64.whl"
[[package]]
name = "appdirs"
version = "1.4.4"
@ -229,7 +230,7 @@ python-versions = ">=3.5"
dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"]
docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"]
tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"]
tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"]
tests_no_zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"]
[[package]]
name = "av"
@ -530,7 +531,7 @@ optional = false
python-versions = ">=3.6.0"
[package.extras]
unicode-backport = ["unicodedata2"]
unicode_backport = ["unicodedata2"]
[[package]]
name = "cleo"
@ -837,6 +838,14 @@ python-versions = ">=3.5.0"
[package.dependencies]
torch = "*"
[[package]]
name = "einops"
version = "0.5.0"
description = "A new flavour of deep learning operations"
category = "dev"
optional = false
python-versions = ">=3.7"
[[package]]
name = "elastic-transport"
version = "8.4.0"
@ -1401,7 +1410,7 @@ notebook = ["ipywidgets", "notebook"]
parallel = ["ipyparallel"]
qtconsole = ["qtconsole"]
test = ["pytest (<7.1)", "pytest-asyncio", "testpath"]
test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.19)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"]
test_extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.19)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"]
[[package]]
name = "ipython-genutils"
@ -1450,9 +1459,9 @@ python-versions = ">=3.6.1,<4.0"
[package.extras]
colors = ["colorama (>=0.4.3,<0.5.0)"]
pipfile-deprecated-finder = ["pipreqs", "requirementslib"]
pipfile_deprecated_finder = ["pipreqs", "requirementslib"]
plugins = ["setuptools"]
requirements-deprecated-finder = ["pip-api", "pipreqs"]
requirements_deprecated_finder = ["pip-api", "pipreqs"]
[[package]]
name = "itsdangerous"
@ -1883,7 +1892,7 @@ mdurl = ">=0.1,<1.0"
[package.extras]
benchmarking = ["psutil", "pytest", "pytest-benchmark (>=3.2,<4.0)"]
code-style = ["pre-commit (==2.6)"]
code_style = ["pre-commit (==2.6)"]
compare = ["commonmark (>=0.9.1,<0.10.0)", "markdown (>=3.3.6,<3.4.0)", "mistletoe (>=0.8.1,<0.9.0)", "mistune (>=2.0.2,<2.1.0)", "panflute (>=2.1.3,<2.2.0)"]
linkify = ["linkify-it-py (>=1.0,<2.0)"]
plugins = ["mdit-py-plugins"]
@ -1950,7 +1959,7 @@ python-versions = ">=3.7"
markdown-it-py = ">=1.0.0,<3.0.0"
[package.extras]
code-style = ["pre-commit"]
code_style = ["pre-commit"]
rtd = ["attrs", "myst-parser (>=0.16.1,<0.17.0)", "sphinx-book-theme (>=0.1.0,<0.2.0)"]
testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
@ -2160,7 +2169,7 @@ sphinx = ">=4,<6"
typing-extensions = "*"
[package.extras]
code-style = ["pre-commit (>=2.12,<3.0)"]
code_style = ["pre-commit (>=2.12,<3.0)"]
linkify = ["linkify-it-py (>=1.0,<2.0)"]
rtd = ["ipython", "sphinx-book-theme", "sphinx-design", "sphinxcontrib.mermaid (>=0.7.1,<0.8.0)", "sphinxext-opengraph (>=0.6.3,<0.7.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"]
testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=6,<7)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx (<5.2)", "sphinx-pytest"]
@ -2432,7 +2441,7 @@ lint = ["clang-format (==13.0.0)", "flake8", "mypy (==0.782)", "types-protobuf (
[[package]]
name = "onnxoptimizer"
version = "0.2.7"
version = "0.3.1"
description = "Open Neural Network Exchange"
category = "dev"
optional = false
@ -2479,6 +2488,7 @@ numpy = [
[package.source]
type = "url"
url = "https://github.com/commaai/opencv-python-builder/releases/download/4.5.5.64%2Bcu113/opencv_python_headless-4.5.5.64-cp38-cp38-manylinux_2_31_x86_64.whl"
[[package]]
name = "osmium"
version = "3.4.1"
@ -3183,7 +3193,7 @@ optional = false
python-versions = ">=3.6"
[package.extras]
asyncio-client = ["aiohttp (>=3.4)"]
asyncio_client = ["aiohttp (>=3.4)"]
client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"]
[[package]]
@ -3207,7 +3217,7 @@ bidict = ">=0.21.0"
python-engineio = ">=4.3.0"
[package.extras]
asyncio-client = ["aiohttp (>=3.4)"]
asyncio_client = ["aiohttp (>=3.4)"]
client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"]
[[package]]
@ -3383,7 +3393,7 @@ urllib3 = ">=1.21.1,<1.27"
[package.extras]
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "requests-oauthlib"
@ -3574,7 +3584,7 @@ falcon = ["falcon (>=1.4)"]
fastapi = ["fastapi (>=0.79.0)"]
flask = ["blinker (>=1.1)", "flask (>=0.11)"]
httpx = ["httpx (>=0.16.0)"]
pure-eval = ["asttokens", "executing", "pure-eval"]
pure_eval = ["asttokens", "executing", "pure-eval"]
pyspark = ["pyspark (>=2.4.4)"]
quart = ["blinker (>=1.1)", "quart (>=0.16.1)"]
rq = ["rq (>=0.6)"]
@ -3840,19 +3850,19 @@ aiomysql = ["aiomysql", "greenlet (!=0.4.17)"]
aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"]
asyncio = ["greenlet (!=0.4.17)"]
asyncmy = ["asyncmy (>=0.2.3,!=0.2.4)", "greenlet (!=0.4.17)"]
mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2)"]
mariadb_connector = ["mariadb (>=1.0.1,!=1.1.2)"]
mssql = ["pyodbc"]
mssql-pymssql = ["pymssql"]
mssql-pyodbc = ["pyodbc"]
mssql_pymssql = ["pymssql"]
mssql_pyodbc = ["pyodbc"]
mypy = ["mypy (>=0.910)", "sqlalchemy2-stubs"]
mysql = ["mysqlclient (>=1.4.0)", "mysqlclient (>=1.4.0,<2)"]
mysql-connector = ["mysql-connector-python"]
mysql_connector = ["mysql-connector-python"]
oracle = ["cx_oracle (>=7)", "cx_oracle (>=7,<8)"]
postgresql = ["psycopg2 (>=2.7)"]
postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"]
postgresql-pg8000 = ["pg8000 (>=1.16.6,!=1.29.0)"]
postgresql-psycopg2binary = ["psycopg2-binary"]
postgresql-psycopg2cffi = ["psycopg2cffi"]
postgresql_asyncpg = ["asyncpg", "greenlet (!=0.4.17)"]
postgresql_pg8000 = ["pg8000 (>=1.16.6,!=1.29.0)"]
postgresql_psycopg2binary = ["psycopg2-binary"]
postgresql_psycopg2cffi = ["psycopg2cffi"]
pymysql = ["pymysql", "pymysql (<1)"]
sqlcipher = ["sqlcipher3_binary"]
@ -4033,6 +4043,7 @@ typing-extensions = "*"
[package.source]
type = "url"
url = "https://download.pytorch.org/whl/cu113/torch-1.11.0%2Bcu113-cp38-cp38-linux_x86_64.whl"
[[package]]
name = "torchsummary"
version = "1.5.1"
@ -4062,6 +4073,7 @@ scipy = ["scipy"]
[package.source]
type = "url"
url = "https://download.pytorch.org/whl/cu113/torchvision-0.12.0%2Bcu113-cp38-cp38-linux_x86_64.whl"
[[package]]
name = "tornado"
version = "6.2"
@ -4316,7 +4328,7 @@ pyzmq = ">=13.1.0"
[package.source]
type = "git"
url = "git@github.com:commaai/zerorpc-python.git"
url = "https://github.com/commaai/zerorpc-python.git"
reference = "master"
resolved_reference = "0e27fd795bb9a7ec9cab81a771a2e35a91e397c9"
@ -4366,7 +4378,7 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
[metadata]
lock-version = "1.1"
python-versions = "~3.8"
content-hash = "f357744f2550b64cbd25e35881d6ec3c1180c90f830eb8d9f53322d6de485561"
content-hash = "76f06d46b1c308e59968994e42193599d8ba3cab6d552460c9c48f282313b64d"
[metadata.files]
adal = [
@ -5137,6 +5149,10 @@ dulwich = [
efficientnet-pytorch = [
{file = "efficientnet_pytorch-0.6.3.tar.gz", hash = "sha256:6667459336893e9bf6367de3788ba449fed97f65da3b6782bf2204b6273a319f"},
]
einops = [
{file = "einops-0.5.0-py3-none-any.whl", hash = "sha256:055de7eeb3cb9e9710ef3085a811090c6b52e809b7044e8785824ed185f486d1"},
{file = "einops-0.5.0.tar.gz", hash = "sha256:8b7a83cffc1ea88e306df099b7cbb9c3ba5003bd84d05ae44be5655864abb8d3"},
]
elastic-transport = [
{file = "elastic-transport-8.4.0.tar.gz", hash = "sha256:b9ad708ceb7fcdbc6b30a96f886609a109f042c0b9d9f2e44403b3133ba7ff10"},
{file = "elastic_transport-8.4.0-py3-none-any.whl", hash = "sha256:19db271ab79c9f70f8c43f8f5b5111408781a6176b54ab2e54d713b6d9ceb815"},
@ -6364,19 +6380,16 @@ onnx = [
{file = "onnx-1.12.0.tar.gz", hash = "sha256:13b3e77d27523b9dbf4f30dfc9c959455859d5e34e921c44f712d69b8369eff9"},
]
onnxoptimizer = [
{file = "onnxoptimizer-0.2.7-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:1aba09d802146bd0e08d9feb83b1e47edc52aa560e48e87451554d436ff07c99"},
{file = "onnxoptimizer-0.2.7-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:cba1ee65fe5e5752b887138ad805dc5b3845f09921b962a62b4dc9083b486f73"},
{file = "onnxoptimizer-0.2.7-cp36-cp36m-win_amd64.whl", hash = "sha256:f161979d34d9db636c623d0681c73de0cbe349805929cf966f7e657457a20d82"},
{file = "onnxoptimizer-0.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:884ac67280d3a4929c7154660105e6ca034d5a222c989864899056225a0aaa61"},
{file = "onnxoptimizer-0.2.7-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:f67e5119419da0f85251d607097fbf486354cc65871caf859acb572526e5d4b0"},
{file = "onnxoptimizer-0.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:0b604e402564ae1231e43edbd0ce766256fcd301f63b00ce8abe4e4f5dd23265"},
{file = "onnxoptimizer-0.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f7cfa72afc54735cf9a66ae7eaca40b6cddf9590e0c63c4f8761e03674b24a53"},
{file = "onnxoptimizer-0.2.7-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:07b028534dd592eb6d6cc5f95fb0b4cb6d9470ce8846c81d0fb24047af70397d"},
{file = "onnxoptimizer-0.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:42247221a35a8cf4cfa9f8f657b0cb234248c4d6ebe54ba03723468449de61c2"},
{file = "onnxoptimizer-0.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c139cd3bebc3f3ea7d1386282a4168bd02bf4d15c261d50896ef517858aa8b8d"},
{file = "onnxoptimizer-0.2.7-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:e278c11eae62a631c342d3618bf315017f6fc54b2e3fbe7840b0a1700e722da4"},
{file = "onnxoptimizer-0.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:86bdb883f33078d3ed89f2ff452e9b0b37624e332dc7d7aa49a23f0ce11c2478"},
{file = "onnxoptimizer-0.2.7.tar.gz", hash = "sha256:a9f972b2b68ceb82b1f268042879f807fceb9ad76e38def2a39f102e62216d21"},
{file = "onnxoptimizer-0.3.1-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:e73a5e2e3ca4db9bff54f7131768749c861677b97ee811a136fcf1a52783cf6e"},
{file = "onnxoptimizer-0.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8bf2bfe0dc43f0776867688e1759122dec049ff4f45f7221931b687fe7e139e"},
{file = "onnxoptimizer-0.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a9a815bba418abfb23f319838370cfd9450305a2da7d970a2261046889a70730"},
{file = "onnxoptimizer-0.3.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:60f1d3600f03466a451c05e3d12ce97565bae016e46f70396ba22208cfeae6f6"},
{file = "onnxoptimizer-0.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:056a765593d197b2b643bfb35520a66eacebfc682583d9ac0389a56c2a259e6f"},
{file = "onnxoptimizer-0.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:15da6a036df388c3f08c3fc638b4d313ee6a1b96aaaa1c602fd1b424dd7bbc23"},
{file = "onnxoptimizer-0.3.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:5547203ee3392e3dabcea68a3a4d316ee0269ad3cf8a3504d1f68d467f60a06a"},
{file = "onnxoptimizer-0.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c773b03313e253a60c7d8fe56ea5bba38fb3442ab84a825468a35a739e8fb20b"},
{file = "onnxoptimizer-0.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:aac4d5c4c5f4c471346dfb28356355b0c54c074a1f2fe1fe122b197f68c08a92"},
{file = "onnxoptimizer-0.3.1.tar.gz", hash = "sha256:0aa2e873a49f3762822e4400e1e8886236156f9d1dbf20319e2c18f7ebfb6a1d"},
]
onnxruntime-gpu = [
{file = "onnxruntime_gpu-1.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42b0393c5122ed90fa2eb76192a486261d86e9526ccb78b2a98923c22791d2d1"},
@ -6541,11 +6554,6 @@ pillow-avif-plugin = [
{file = "pillow_avif_plugin-1.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:017e5e52cb4320414e8ce3e2089eae2cb87c22c73ff6012b17ae326fc5753b20"},
{file = "pillow_avif_plugin-1.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2a57136d4866de5dc80cfb24d66655955fbdd87acf1d11d88c8dc2ab41023e46"},
{file = "pillow_avif_plugin-1.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:f339511d0fccb69e3a5e3af39f8fe6700b0a07279015006ea56f8f49e7fecff4"},
{file = "pillow_avif_plugin-1.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:05e821ecd90bb0b8d2dc7610625372cc47de9cb893d09662528bad572f669d1c"},
{file = "pillow_avif_plugin-1.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d33886a5f9796fe9a8a3bc25ccfdeba7db119adb50b7004f1928a14b07d0213a"},
{file = "pillow_avif_plugin-1.2.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:75b7ed186c2f740dd26e556f6a966c59a170b70263e429a2c81920fe444da8a7"},
{file = "pillow_avif_plugin-1.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a11aef6b79078b8dad25c928e5871c146ab94424472851d5bf539ba62abde9ac"},
{file = "pillow_avif_plugin-1.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:10696c536d68a14cefea3b98edb8d5a7ae29e8e07458f1d59c5d1cd780a8bf2a"},
{file = "pillow_avif_plugin-1.2.2-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:1a7291d6a5fb7336e72685a31d193e0b3a6bee9986c9ac4d8bd4b68dbe6d4f7f"},
{file = "pillow_avif_plugin-1.2.2-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:14b9c5dbf237e7dc12f69819ea181a457b3bd4f59f8cd71d028d3635fd3bcab4"},
{file = "pillow_avif_plugin-1.2.2-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:799cbfbeee831332d280c80df9ce16b5c3b1224c318264e97e89df8da32e870e"},
@ -6934,13 +6942,11 @@ pyprof2calltree = [
]
pyproj = [
{file = "pyproj-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f343725566267a296b09ee7e591894f1fdc90f84f8ad5ec476aeb53bd4479c07"},
{file = "pyproj-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5816807ca0bdc7256558770c6206a6783a3f02bcf844f94ee245f197bb5f7285"},
{file = "pyproj-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7e609903572a56cca758bbaee5c1663c3e829ddce5eec4f368e68277e37022b"},
{file = "pyproj-3.4.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4fd425ee8b6781c249c7adb7daa2e6c41ce573afabe4f380f5eecd913b56a3be"},
{file = "pyproj-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:954b068136518b3174d0a99448056e97af62b63392a95c420894f7de2229dae6"},
{file = "pyproj-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:4a23d84c5ffc383c7d9f0bde3a06fc1f6697b1b96725597f8f01e7b4bef0a2b5"},
{file = "pyproj-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1f9c100fd0fd80edbc7e4daa303600a8cbef6f0de43d005617acb38276b88dc0"},
{file = "pyproj-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:aa5171f700f174777a9e9ed8f4655583243967c0f9cf2c90e3f54e54ff740134"},
{file = "pyproj-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a496d9057b2128db9d733e66b206f2d5954bbae6b800d412f562d780561478c"},
{file = "pyproj-3.4.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52e54796e2d9554a5eb8f11df4748af1fbbc47f76aa234d6faf09216a84554c5"},
{file = "pyproj-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a454a7c4423faa2a14e939d08ef293ee347fa529c9df79022b0585a6e1d8310c"},
@ -6951,7 +6957,6 @@ pyproj = [
{file = "pyproj-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f80adda8c54b84271a93829477a01aa57bc178c834362e9f74e1de1b5033c74c"},
{file = "pyproj-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:221d8939685e0c43ee594c9f04b6a73a10e8e1cc0e85f28be0b4eb2f1bc8777d"},
{file = "pyproj-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d94afed99f31673d3d19fe750283621e193e2a53ca9e0443bf9d092c3905833b"},
{file = "pyproj-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0fff9c3a991508f16027be27d153f6c5583d03799443639d13c681e60f49e2d7"},
{file = "pyproj-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b85acf09e5a9e35cd9ee72989793adb7089b4e611be02a43d3d0bda50ad116b"},
{file = "pyproj-3.4.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:45554f47d1a12a84b0620e4abc08a2a1b5d9f273a4759eaef75e74788ec7162a"},
{file = "pyproj-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12f62c20656ac9b6076ebb213e9a635d52f4f01fef95310121d337e62e910cb6"},

@ -126,6 +126,7 @@ configargparse = "^1.5.3"
cupy-cuda113 = "^10.6.0"
datadog = "^0.44.0"
dotmap = "^1.3.30"
einops = "^0.5.0"
elasticsearch = "^8.3.1"
Flask-Cors = "^3.0.10"
Flask-SocketIO = "^5.2.0"
@ -144,7 +145,7 @@ mpld3 = "^0.5.8"
msgpack-python = "^0.5.6"
networkx = "~2.3"
nvidia-ml-py3 = "^7.352.0"
onnxoptimizer = "^0.2.6"
onnxoptimizer = "^0.3.1"
opencv-python-headless = { url = "https://github.com/commaai/opencv-python-builder/releases/download/4.5.5.64%2Bcu113/opencv_python_headless-4.5.5.64-cp38-cp38-manylinux_2_31_x86_64.whl" }
osmium = "^3.3.0"
pandas = "^1.4.3"
@ -168,7 +169,7 @@ torchsummary = "^1.5.1"
torchvision = { url = "https://download.pytorch.org/whl/cu113/torchvision-0.12.0%2Bcu113-cp38-cp38-linux_x86_64.whl" }
triton = "^1.1.1"
Werkzeug = "^2.1.2"
zerorpc = { git = "git@github.com:commaai/zerorpc-python.git", branch = "master" }
zerorpc = { git = "https://github.com/commaai/zerorpc-python.git", branch = "master" }
[build-system]

@ -129,6 +129,7 @@ class CarController:
self.last_button_frame = self.frame
can_sends.append(gmcan.create_buttons(self.packer_pt, CanBus.CAMERA, CS.buttons_counter, CruiseButtons.CANCEL))
if self.CP.networkLocation == NetworkLocation.fwdCamera:
# Silence "Take Steering" alert sent by camera, forward PSCMStatus with HandsOffSWlDetectionStatus=1
if self.frame % 10 == 0:
can_sends.append(gmcan.create_pscm_status(self.packer_pt, CanBus.CAMERA, CS.pscm_status))

@ -1,5 +1,6 @@
from selfdrive.car import make_can_msg
def create_buttons(packer, bus, idx, button):
values = {
"ACCButtons": button,
@ -7,14 +8,15 @@ def create_buttons(packer, bus, idx, button):
}
return packer.make_can_msg("ASCMSteeringButton", bus, values)
def create_pscm_status(packer, bus, pscm_status):
checksum_mod = int(1 - pscm_status["HandsOffSWlDetectionStatus"]) << 5
pscm_status["HandsOffSWlDetectionStatus"] = 1
pscm_status["PSCMStatusChecksum"] += checksum_mod
return packer.make_can_msg("PSCMStatus", bus, pscm_status)
def create_steering_control(packer, bus, apply_steer, idx, lkas_active):
def create_steering_control(packer, bus, apply_steer, idx, lkas_active):
values = {
"LKASteeringCmdActive": lkas_active,
"LKASteeringCmd": apply_steer,
@ -24,15 +26,17 @@ def create_steering_control(packer, bus, apply_steer, idx, lkas_active):
return packer.make_can_msg("ASCMLKASteeringCmd", bus, values)
def create_adas_keepalive(bus):
dat = b"\x00\x00\x00\x00\x00\x00\x00"
return [make_can_msg(0x409, dat, bus), make_can_msg(0x40a, dat, bus)]
def create_gas_regen_command(packer, bus, throttle, idx, acc_engaged, at_full_stop):
def create_gas_regen_command(packer, bus, throttle, idx, enabled, at_full_stop):
values = {
"GasRegenCmdActive": acc_engaged,
"GasRegenCmdActive": enabled,
"RollingCounter": idx,
"GasRegenCmdActiveInv": 1 - acc_engaged,
"GasRegenCmdActiveInv": 1 - enabled,
"GasRegenCmd": throttle,
"GasRegenFullStopActive": at_full_stop,
"GasRegenAlwaysOne": 1,
@ -47,6 +51,7 @@ def create_gas_regen_command(packer, bus, throttle, idx, acc_engaged, at_full_st
return packer.make_can_msg("ASCMGasRegenCmd", bus, values)
def create_friction_brake_command(packer, bus, apply_brake, idx, near_stop, at_full_stop):
mode = 0x1
if apply_brake > 0:
@ -63,44 +68,48 @@ def create_friction_brake_command(packer, bus, apply_brake, idx, near_stop, at_f
checksum = (0x10000 - (mode << 12) - brake - idx) & 0xffff
values = {
"RollingCounter" : idx,
"FrictionBrakeMode" : mode,
"RollingCounter": idx,
"FrictionBrakeMode": mode,
"FrictionBrakeChecksum": checksum,
"FrictionBrakeCmd" : -apply_brake
"FrictionBrakeCmd": -apply_brake
}
return packer.make_can_msg("EBCMFrictionBrakeCmd", bus, values)
def create_acc_dashboard_command(packer, bus, acc_engaged, target_speed_kph, lead_car_in_sight, fcw):
def create_acc_dashboard_command(packer, bus, enabled, target_speed_kph, lead_car_in_sight, fcw):
target_speed = min(target_speed_kph, 255)
values = {
"ACCAlwaysOne" : 1,
"ACCResumeButton" : 0,
"ACCSpeedSetpoint" : target_speed,
"ACCGapLevel" : 3 * acc_engaged, # 3 "far", 0 "inactive"
"ACCCmdActive" : acc_engaged,
"ACCAlwaysOne2" : 1,
"ACCLeadCar" : lead_car_in_sight,
"ACCAlwaysOne": 1,
"ACCResumeButton": 0,
"ACCSpeedSetpoint": target_speed,
"ACCGapLevel": 3 * enabled, # 3 "far", 0 "inactive"
"ACCCmdActive": enabled,
"ACCAlwaysOne2": 1,
"ACCLeadCar": lead_car_in_sight,
"FCWAlert": 0x3 if fcw else 0
}
return packer.make_can_msg("ASCMActiveCruiseControlStatus", bus, values)
def create_adas_time_status(bus, tt, idx):
dat = [(tt >> 20) & 0xff, (tt >> 12) & 0xff, (tt >> 4) & 0xff,
((tt & 0xf) << 4) + (idx << 2)]
((tt & 0xf) << 4) + (idx << 2)]
chksum = 0x1000 - dat[0] - dat[1] - dat[2] - dat[3]
chksum = chksum & 0xfff
dat += [0x40 + (chksum >> 8), chksum & 0xff, 0x12]
return make_can_msg(0xa1, bytes(dat), bus)
def create_adas_steering_status(bus, idx):
dat = [idx << 6, 0xf0, 0x20, 0, 0, 0]
chksum = 0x60 + sum(dat)
dat += [chksum >> 8, chksum & 0xff]
return make_can_msg(0x306, bytes(dat), bus)
def create_adas_accelerometer_speed_status(bus, speed_ms, idx):
spd = int(speed_ms * 16) & 0xfff
accel = 0 & 0xfff
@ -114,6 +123,7 @@ def create_adas_accelerometer_speed_status(bus, speed_ms, idx):
dat += [(idx << 5) + (far_range_mode << 4) + (near_range_mode << 3) + (chksum >> 8), chksum & 0xff]
return make_can_msg(0x308, bytes(dat), bus)
def create_adas_headlights_status(packer, bus):
values = {
"Always42": 0x42,
@ -121,6 +131,7 @@ def create_adas_headlights_status(packer, bus):
}
return packer.make_can_msg("ASCMHeadlight", bus, values)
def create_lka_icon_command(bus, active, critical, steer):
if active and steer == 1:
if critical:

@ -555,6 +555,7 @@ FW_VERSIONS = {
b'\xf1\x8703N906026E \xf1\x892114',
b'\xf1\x8704E906023AH\xf1\x893379',
b'\xf1\x8704L906026ET\xf1\x891990',
b'\xf1\x8704L906026FP\xf1\x892012',
b'\xf1\x8704L906026GA\xf1\x892013',
b'\xf1\x8704L906026KD\xf1\x894798',
b'\xf1\x873G0906264 \xf1\x890004',
@ -562,6 +563,7 @@ FW_VERSIONS = {
(Ecu.transmission, 0x7e1, None): [
b'\xf1\x870CW300043H \xf1\x891601',
b'\xf1\x870CW300048R \xf1\x890610',
b'\xf1\x870D9300013A \xf1\x894905',
b'\xf1\x870D9300014L \xf1\x895002',
b'\xf1\x870D9300041A \xf1\x894801',
b'\xf1\x870DD300045T \xf1\x891601',
@ -579,6 +581,7 @@ FW_VERSIONS = {
],
(Ecu.eps, 0x712, None): [
b'\xf1\x873Q0909144J \xf1\x895063\xf1\x82\x0566B00611A1',
b'\xf1\x873Q0909144J \xf1\x895063\xf1\x82\x0566B00711A1',
b'\xf1\x875Q0909143M \xf1\x892041\xf1\x820522B0060803',
b'\xf1\x875Q0909143M \xf1\x892041\xf1\x820522B0080803',
b'\xf1\x875Q0909144AB\xf1\x891082\xf1\x82\00521B00606A1',

@ -31,7 +31,6 @@ INPUTS_NEEDED = 5 # Minimum blocks needed for valid calibration
INPUTS_WANTED = 50 # We want a little bit more than we need for stability
MAX_ALLOWED_SPREAD = np.radians(2)
RPY_INIT = np.array([0.0,0.0,0.0])
WIDE_FROM_DEVICE_EULER_INIT = np.array([0.0, 0.0, 0.0])
# These values are needed to accommodate biggest modelframe
PITCH_LIMITS = np.array([-0.09074112085129739, 0.14907572052989657])
@ -68,7 +67,6 @@ class Calibrator:
calibration_params = params.get("CalibrationParams")
self.wide_camera = params.get_bool('WideCameraOnly')
rpy_init = RPY_INIT
wide_from_device_euler = WIDE_FROM_DEVICE_EULER_INIT
valid_blocks = 0
if param_put and calibration_params:
@ -76,34 +74,24 @@ class Calibrator:
msg = log.Event.from_bytes(calibration_params)
rpy_init = np.array(msg.liveCalibration.rpyCalib)
valid_blocks = msg.liveCalibration.validBlocks
wide_from_device_euler = np.array(msg.liveCalibration.wideFromDeviceEuler)
except Exception:
cloudlog.exception("Error reading cached CalibrationParams")
self.reset(rpy_init, valid_blocks, wide_from_device_euler)
self.reset(rpy_init, valid_blocks)
self.update_status()
def reset(self, rpy_init: np.ndarray = RPY_INIT,
valid_blocks: int = 0,
wide_from_device_euler: np.ndarray = WIDE_FROM_DEVICE_EULER_INIT,
smooth_from: Optional[np.ndarray] = None) -> None:
def reset(self, rpy_init: np.ndarray = RPY_INIT, valid_blocks: int = 0, smooth_from: Optional[np.ndarray] = None) -> None:
if not np.isfinite(rpy_init).all():
self.rpy = RPY_INIT.copy()
else:
self.rpy = rpy_init.copy()
if not np.isfinite(wide_from_device_euler).all():
self.wide_from_device_euler = WIDE_FROM_DEVICE_EULER_INIT.copy()
else:
self.wide_from_device_euler = wide_from_device_euler.copy()
if not np.isfinite(valid_blocks) or valid_blocks < 0:
self.valid_blocks = 0
else:
self.valid_blocks = valid_blocks
self.rpys = np.tile(self.rpy, (INPUTS_WANTED, 1))
self.wide_from_device_eulers = np.tile(wide_from_device_euler, (INPUTS_WANTED, 1))
self.idx = 0
self.block_idx = 0
@ -127,8 +115,6 @@ class Calibrator:
if valid_idxs:
rpys = self.rpys[valid_idxs]
self.rpy = np.mean(rpys, axis=0)
wide_from_device_eulers = self.wide_from_device_eulers[valid_idxs]
self.wide_from_device_euler = np.mean(wide_from_device_eulers, axis=0)
max_rpy_calib = np.array(np.max(rpys, axis=0))
min_rpy_calib = np.array(np.min(rpys, axis=0))
self.calib_spread = np.abs(max_rpy_calib - min_rpy_calib)
@ -160,10 +146,7 @@ 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]) -> Optional[np.ndarray]:
def handle_cam_odom(self, trans: List[float], rot: List[float], trans_std: List[float]) -> Optional[np.ndarray]:
self.old_rpy_weight = min(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))
@ -182,15 +165,7 @@ class Calibrator:
new_rpy = euler_from_rot(rot_from_euler(self.get_smooth_rpy()).dot(rot_from_euler(observed_rpy)))
new_rpy = sanity_clip(new_rpy)
if len(wide_from_device_euler):
new_wide_from_device_euler = np.array(wide_from_device_euler)
else:
new_wide_from_device_euler = WIDE_FROM_DEVICE_EULER_INIT
self.rpys[self.block_idx] = (self.idx*self.rpys[self.block_idx] +
(BLOCK_SIZE - self.idx) * new_rpy) / float(BLOCK_SIZE)
self.wide_from_device_eulers[self.block_idx] = (self.idx*self.wide_from_device_eulers[self.block_idx] +
(BLOCK_SIZE - self.idx) * new_wide_from_device_euler) / float(BLOCK_SIZE)
self.rpys[self.block_idx] = (self.idx*self.rpys[self.block_idx] + (BLOCK_SIZE - self.idx) * new_rpy) / float(BLOCK_SIZE)
self.idx = (self.idx + 1) % BLOCK_SIZE
if self.idx == 0:
self.block_idx += 1
@ -212,7 +187,6 @@ class Calibrator:
liveCalibration.calPerc = min(100 * (self.valid_blocks * BLOCK_SIZE + self.idx) // (INPUTS_NEEDED * BLOCK_SIZE), 100)
liveCalibration.rpyCalib = smooth_rpy.tolist()
liveCalibration.rpyCalibSpread = self.calib_spread.tolist()
liveCalibration.wideFromDeviceEuler = self.wide_from_device_euler.tolist()
if self.not_car:
liveCalibration.validBlocks = INPUTS_NEEDED
@ -249,7 +223,6 @@ def calibrationd_thread(sm: Optional[messaging.SubMaster] = None, pm: Optional[m
calibrator.handle_v_ego(sm['carState'].vEgo)
new_rpy = calibrator.handle_cam_odom(sm['cameraOdometry'].trans,
sm['cameraOdometry'].rot,
sm['cameraOdometry'].wideFromDeviceEuler,
sm['cameraOdometry'].transStd)
if DEBUG and new_rpy is not None:

@ -1 +1 @@
a5c77655fba5563e8128fb655f69b1bbd02198aa
f5a352666728344ca5065bb44c47c1f5650b4243

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -13,12 +13,6 @@
const int CELL_HEIGHT = 30;
static std::pair<int, int> getSignalRange(const Signal *s) {
int from = s->is_little_endian ? s->start_bit : bigEndianBitIndex(s->start_bit);
int to = from + s->size - 1;
return {from, to};
}
BinaryView::BinaryView(QWidget *parent) : QTableView(parent) {
model = new BinaryViewModel(this);
setModel(model);
@ -76,9 +70,10 @@ void BinaryView::mousePressEvent(QMouseEvent *event) {
void BinaryView::mouseMoveEvent(QMouseEvent *event) {
if (auto index = indexAt(event->pos()); index.isValid()) {
auto item = (BinaryViewModel::Item *)index.internalPointer();
highlight(item->sig);
item->sig ? QToolTip::showText(event->globalPos(), item->sig->name.c_str(), this, rect())
: QToolTip::hideText();
const Signal *sig = item->sigs.isEmpty() ? nullptr : item->sigs.back();
highlight(sig);
sig ? QToolTip::showText(event->globalPos(), sig->name.c_str(), this, rect())
: QToolTip::hideText();
}
QTableView::mouseMoveEvent(event);
}
@ -92,7 +87,8 @@ void BinaryView::mouseReleaseEvent(QMouseEvent *event) {
if (auto sig = getResizingSignal()) {
auto [sig_from, sig_to] = getSignalRange(sig);
if (from >= sig_from && to <= sig_to) { // reduce size
emit(from == sig_from ? resizeSignal(sig, to, sig_to) : resizeSignal(sig, sig_from, from));
emit(from == sig_from ? resizeSignal(sig, std::min(to + 1, sig_to), sig_to)
: resizeSignal(sig, sig_from, std::max(from - 1, sig_from)));
} else { // increase size
emit resizeSignal(sig, std::min(from, sig_from), std::max(to, sig_to));
}
@ -124,11 +120,13 @@ void BinaryView::updateState() {
const Signal *BinaryView::getResizingSignal() const {
if (anchor_index.isValid()) {
auto item = (const BinaryViewModel::Item *)anchor_index.internalPointer();
if (item && item->sig) {
if (item && item->sigs.size() > 0) {
int archor_pos = anchor_index.row() * 8 + anchor_index.column();
auto [sig_from, sig_to] = getSignalRange(item->sig);
if (archor_pos == sig_from || archor_pos == sig_to)
return item->sig;
for (auto s : item->sigs) {
auto [sig_from, sig_to] = getSignalRange(s);
if (archor_pos == sig_from || archor_pos == sig_to)
return s;
}
}
}
return nullptr;
@ -162,7 +160,7 @@ void BinaryViewModel::setMessage(const QString &message_id) {
sig.is_little_endian ? items[idx].is_msb = true : items[idx].is_lsb = true;
}
items[idx].bg_color = getColor(i);
items[idx].sig = &dbc_msg->sigs[i];
items[idx].sigs.push_back(&dbc_msg->sigs[i]);
}
}
}
@ -212,7 +210,7 @@ void BinaryViewModel::updateState() {
QVariant BinaryViewModel::headerData(int section, Qt::Orientation orientation, int role) const {
if (orientation == Qt::Vertical) {
switch (role) {
case Qt::DisplayRole: return section + 1;
case Qt::DisplayRole: return section;
case Qt::SizeHintRole: return QSize(30, CELL_HEIGHT);
case Qt::TextAlignmentRole: return Qt::AlignCenter;
}
@ -240,7 +238,8 @@ void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
BinaryView *bin_view = (BinaryView *)parent();
painter->save();
bool hover = item->sig && bin_view->hoveredSignal() == item->sig;
bool hover = std::find_if(item->sigs.begin(), item->sigs.end(), [=](auto s) { return s == bin_view->hoveredSignal(); }) !=
item->sigs.end();
// background
QColor bg_color = hover ? hoverColor(item->bg_color) : item->bg_color;
if (option.state & QStyle::State_Selected) {

@ -1,5 +1,6 @@
#pragma once
#include <QList>
#include <QStyledItemDelegate>
#include <QTableView>
@ -38,7 +39,7 @@ public:
bool is_msb = false;
bool is_lsb = false;
QString val = "0";
const Signal *sig = nullptr;
QList<const Signal *> sigs;
};
private:

@ -54,9 +54,9 @@ QList<QPointF> CANMessages::findSignalValues(const QString &id, const Signal *si
double val = get_raw_value((uint8_t *)c.getDat().begin(), c.getDat().size(), *signal);
if ((flag == EQ && val == value) || (flag == LT && val < value) || (flag == GT && val > value)) {
ret.push_back({(evt->mono_time / (double)1e9) - can->routeStartTime(), val});
if (ret.size() >= max_count)
return ret;
}
if (ret.size() >= max_count)
return ret;
}
}
}
@ -65,15 +65,14 @@ QList<QPointF> CANMessages::findSignalValues(const QString &id, const Signal *si
void CANMessages::process(QHash<QString, std::deque<CanData>> *messages) {
for (auto it = messages->begin(); it != messages->end(); ++it) {
++counters[it.key()];
auto &msgs = can_msgs[it.key()];
const auto &new_msgs = it.value();
if (new_msgs.size() == settings.can_msg_log_size || msgs.empty()) {
msgs = std::move(new_msgs);
} else {
msgs.insert(msgs.begin(), std::make_move_iterator(new_msgs.begin()), std::make_move_iterator(new_msgs.end()));
while (msgs.size() >= settings.can_msg_log_size) {
msgs.pop_back();
if (msgs.size() > settings.can_msg_log_size) {
msgs.resize(settings.can_msg_log_size);
}
}
}

@ -121,3 +121,21 @@ double get_raw_value(uint8_t *data, size_t data_size, const Signal &sig) {
double value = val * sig.factor + sig.offset;
return value;
}
void updateSigSizeParamsFromRange(Signal &s, int from, int to) {
s.start_bit = s.is_little_endian ? from : bigEndianBitIndex(from);
s.size = to - from + 1;
if (s.is_little_endian) {
s.lsb = s.start_bit;
s.msb = s.start_bit + s.size - 1;
} else {
s.lsb = bigEndianStartBitsIndex(bigEndianBitIndex(s.start_bit) + s.size - 1);
s.msb = s.start_bit;
}
}
std::pair<int, int> getSignalRange(const Signal *s) {
int from = s->is_little_endian ? s->start_bit : bigEndianBitIndex(s->start_bit);
int to = from + s->size - 1;
return {from, to};
}

@ -47,5 +47,7 @@ private:
double get_raw_value(uint8_t *data, size_t data_size, const Signal &sig);
int bigEndianStartBitsIndex(int start_bit);
int bigEndianBitIndex(int index);
void updateSigSizeParamsFromRange(Signal &s, int from, int to);
std::pair<int, int> getSignalRange(const Signal *s);
DBCManager *dbc();

@ -48,7 +48,7 @@ DetailWidget::DetailWidget(QWidget *parent) : QWidget(parent) {
warning_widget = new QWidget(this);
QHBoxLayout *warning_hlayout = new QHBoxLayout(warning_widget);
QLabel *warning_icon = new QLabel(this);
warning_icon->setPixmap(style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap({16, 16}));
warning_icon->setPixmap(style()->standardPixmap(QStyle::SP_MessageBoxWarning));
warning_hlayout->addWidget(warning_icon);
warning_label = new QLabel(this);
warning_hlayout->addWidget(warning_label, 1, Qt::AlignLeft);
@ -78,7 +78,7 @@ DetailWidget::DetailWidget(QWidget *parent) : QWidget(parent) {
QObject::connect(binary_view, &BinaryView::resizeSignal, this, &DetailWidget::resizeSignal);
QObject::connect(binary_view, &BinaryView::addSignal, this, &DetailWidget::addSignal);
QObject::connect(can, &CANMessages::updated, this, &DetailWidget::updateState);
QObject::connect(dbc(), &DBCManager::DBCFileChanged, this, &DetailWidget::dbcMsgChanged);
QObject::connect(dbc(), &DBCManager::DBCFileChanged, [this]() { dbcMsgChanged(); });
QObject::connect(tabbar, &QTabBar::currentChanged, [this](int index) { setMessage(messages[index]); });
QObject::connect(tabbar, &QTabBar::tabCloseRequested, [=](int index) {
messages.removeAt(index);
@ -103,7 +103,7 @@ void DetailWidget::setMessage(const QString &message_id) {
dbcMsgChanged();
}
void DetailWidget::dbcMsgChanged() {
void DetailWidget::dbcMsgChanged(int show_form_idx) {
if (msg_id.isEmpty()) return;
warning_widget->hide();
@ -111,7 +111,7 @@ void DetailWidget::dbcMsgChanged() {
QString msg_name = tr("untitled");
if (auto msg = dbc()->msg(msg_id)) {
for (int i = 0; i < msg->sigs.size(); ++i) {
auto form = new SignalEdit(i, msg_id, msg->sigs[i]);
auto form = new SignalEdit(i, msg_id, &(msg->sigs[i]));
signals_container->layout()->addWidget(form);
QObject::connect(form, &SignalEdit::showChart, [this, sig = &msg->sigs[i]]() { emit showChart(msg_id, sig); });
QObject::connect(form, &SignalEdit::showFormClicked, this, &DetailWidget::showForm);
@ -119,6 +119,9 @@ void DetailWidget::dbcMsgChanged() {
QObject::connect(form, &SignalEdit::save, this, &DetailWidget::saveSignal);
QObject::connect(form, &SignalEdit::highlight, binary_view, &BinaryView::highlight);
QObject::connect(binary_view, &BinaryView::signalHovered, form, &SignalEdit::signalHovered);
if (i == show_form_idx) {
QTimer::singleShot(0, [=]() { emit form->showFormClicked(); });
}
}
msg_name = msg->name.c_str();
if (msg->size != can->lastMessage(msg_id).dat.size()) {
@ -162,46 +165,54 @@ void DetailWidget::editMsg() {
}
}
void DetailWidget::addSignal(int start_bit, int to) {
if (dbc()->msg(msg_id)) {
AddSignalDialog dlg(msg_id, start_bit, to - start_bit + 1, this);
if (dlg.exec()) {
dbc()->addSignal(msg_id, dlg.form->getSignal());
dbcMsgChanged();
void DetailWidget::addSignal(int from, int to) {
if (auto msg = dbc()->msg(msg_id)) {
Signal sig = {};
for (int i = 1; /**/; ++i) {
sig.name = "NEW_SIGNAL_" + std::to_string(i);
auto it = std::find_if(msg->sigs.begin(), msg->sigs.end(), [&](auto &s) { return sig.name == s.name; });
if (it == msg->sigs.end()) break;
}
sig.is_little_endian = false,
updateSigSizeParamsFromRange(sig, from, to);
dbc()->addSignal(msg_id, sig);
dbcMsgChanged(msg->sigs.size() - 1);
}
}
void DetailWidget::resizeSignal(const Signal *sig, int from, int to) {
assert(sig != nullptr);
Signal s = *sig;
s.start_bit = s.is_little_endian ? from : bigEndianBitIndex(from);;
s.size = to - from + 1;
if (s.is_little_endian) {
s.lsb = s.start_bit;
s.msb = s.start_bit + s.size - 1;
} else {
s.lsb = bigEndianStartBitsIndex(bigEndianBitIndex(s.start_bit) + s.size - 1);
s.msb = s.start_bit;
}
dbc()->updateSignal(msg_id, s.name.c_str(), s);
dbcMsgChanged();
updateSigSizeParamsFromRange(s, from, to);
saveSignal(sig, s);
}
void DetailWidget::saveSignal() {
SignalEdit *sig_form = qobject_cast<SignalEdit *>(QObject::sender());
auto s = sig_form->form->getSignal();
dbc()->updateSignal(msg_id, sig_form->sig_name, s);
void DetailWidget::saveSignal(const Signal *sig, const Signal &new_sig) {
auto msg = dbc()->msg(msg_id);
if (new_sig.name != sig->name) {
auto it = std::find_if(msg->sigs.begin(), msg->sigs.end(), [&](auto &s) { return s.name == new_sig.name; });
if (it != msg->sigs.end()) {
QString warning_str = tr("There is already a signal with the same name '%1'").arg(new_sig.name.c_str());
QMessageBox::warning(this, tr("Failed to save signal"), warning_str);
return;
}
}
auto [start, end] = getSignalRange(&new_sig);
if (start < 0 || end >= msg->size * 8) {
QString warning_str = tr("Signal size [%1] exceed limit").arg(new_sig.size);
QMessageBox::warning(this, tr("Failed to save signal"), warning_str);
return;
}
dbc()->updateSignal(msg_id, sig->name.c_str(), new_sig);
// update binary view and history log
binary_view->setMessage(msg_id);
history_log->setMessage(msg_id);
dbcMsgChanged();
}
void DetailWidget::removeSignal() {
SignalEdit *sig_form = qobject_cast<SignalEdit *>(QObject::sender());
QString text = tr("Are you sure you want to remove signal '%1'").arg(sig_form->sig_name);
void DetailWidget::removeSignal(const Signal *sig) {
QString text = tr("Are you sure you want to remove signal '%1'").arg(sig->name.c_str());
if (QMessageBox::Yes == QMessageBox::question(this, tr("Remove signal"), text)) {
dbc()->removeSignal(msg_id, sig_form->sig_name);
dbc()->removeSignal(msg_id, sig->name.c_str());
dbcMsgChanged();
}
}

@ -32,7 +32,7 @@ class DetailWidget : public QWidget {
public:
DetailWidget(QWidget *parent);
void setMessage(const QString &message_id);
void dbcMsgChanged();
void dbcMsgChanged(int show_form_idx = -1);
signals:
void showChart(const QString &msg_id, const Signal *sig);
@ -41,8 +41,8 @@ signals:
private:
void addSignal(int start_bit, int to);
void resizeSignal(const Signal *sig, int from, int to);
void saveSignal();
void removeSignal();
void saveSignal(const Signal *sig, const Signal &new_sig);
void removeSignal(const Signal *sig);
void editMsg();
void showForm();
void updateState();

@ -14,9 +14,6 @@ void qLogMessageHandler(QtMsgType type, const QMessageLogContext &context, const
}
MainWindow::MainWindow() : QWidget() {
main_win = this;
qInstallMessageHandler(qLogMessageHandler);
QVBoxLayout *main_layout = new QVBoxLayout(this);
main_layout->setContentsMargins(11, 11, 11, 5);
main_layout->setSpacing(0);
@ -88,6 +85,9 @@ MainWindow::MainWindow() : QWidget() {
QObject::connect(charts_widget, &ChartsWidget::dock, this, &MainWindow::dockCharts);
QObject::connect(settings_btn, &QPushButton::clicked, this, &MainWindow::setOption);
QObject::connect(can, &CANMessages::eventsMerged, [=]() { fingerprint_label->setText(can->carFingerprint() ); });
main_win = this;
qInstallMessageHandler(qLogMessageHandler);
}
void MainWindow::updateDownloadProgress(uint64_t cur, uint64_t total, bool success) {

@ -2,6 +2,7 @@
#include <QCompleter>
#include <QDialogButtonBox>
#include <QFile>
#include <QFontDatabase>
#include <QHeaderView>
#include <QLineEdit>

@ -3,6 +3,7 @@
#include <QDialogButtonBox>
#include <QFormLayout>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QRadioButton>
#include <QScrollArea>
#include <QVBoxLayout>
@ -11,7 +12,7 @@
// SignalForm
SignalForm::SignalForm(const Signal &sig, QWidget *parent) : start_bit(sig.start_bit), QWidget(parent) {
SignalForm::SignalForm(const Signal &sig, QWidget *parent) : QWidget(parent) {
QFormLayout *form_layout = new QFormLayout(this);
name = new QLineEdit(sig.name.c_str());
@ -59,30 +60,9 @@ SignalForm::SignalForm(const Signal &sig, QWidget *parent) : start_bit(sig.start
form_layout->addRow(tr("Value descriptions"), val_desc);
}
Signal SignalForm::getSignal() {
// TODO: Check if the size is valid, and no duplicate name
Signal sig = {};
sig.start_bit = start_bit;
sig.name = name->text().toStdString();
sig.size = size->text().toInt();
sig.offset = offset->text().toDouble();
sig.factor = factor->text().toDouble();
sig.is_signed = sign->currentIndex() == 0;
sig.is_little_endian = endianness->currentIndex() == 0;
if (sig.is_little_endian) {
sig.lsb = sig.start_bit;
sig.msb = sig.start_bit + sig.size - 1;
} else {
sig.lsb = bigEndianStartBitsIndex(bigEndianBitIndex(sig.start_bit) + sig.size - 1);
sig.msb = sig.start_bit;
}
return sig;
}
// SignalEdit
SignalEdit::SignalEdit(int index, const QString &msg_id, const Signal &sig, QWidget *parent)
: sig(&sig), form_idx(index), sig_name(sig.name.c_str()), QWidget(parent) {
SignalEdit::SignalEdit(int index, const QString &msg_id, const Signal *sig, QWidget *parent) : msg_id(msg_id), sig(sig), form_idx(index), QWidget(parent) {
QVBoxLayout *main_layout = new QVBoxLayout(this);
main_layout->setContentsMargins(0, 0, 0, 0);
@ -93,7 +73,7 @@ SignalEdit::SignalEdit(int index, const QString &msg_id, const Signal &sig, QWid
title_layout->addWidget(icon);
title = new ElidedLabel(this);
title->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
title->setText(QString("%1. %2").arg(index + 1).arg(sig_name));
title->setText(QString("%1. %2").arg(index + 1).arg(sig->name.c_str()));
title->setStyleSheet(QString("font-weight:bold; color:%1").arg(getColor(index)));
title_layout->addWidget(title, 1);
@ -113,7 +93,7 @@ SignalEdit::SignalEdit(int index, const QString &msg_id, const Signal &sig, QWid
// signal form
form_container = new QWidget(this);
QVBoxLayout *v_layout = new QVBoxLayout(form_container);
form = new SignalForm(sig, this);
form = new SignalForm(*sig, this);
v_layout->addWidget(form);
QHBoxLayout *h = new QHBoxLayout();
@ -133,20 +113,34 @@ SignalEdit::SignalEdit(int index, const QString &msg_id, const Signal &sig, QWid
hline->setFrameShadow(QFrame::Sunken);
main_layout->addWidget(hline);
QObject::connect(remove_btn, &QPushButton::clicked, this, &SignalEdit::remove);
QObject::connect(remove_btn, &QPushButton::clicked, [this]() { emit remove(this->sig); });
QObject::connect(title, &ElidedLabel::clicked, this, &SignalEdit::showFormClicked);
QObject::connect(save_btn, &QPushButton::clicked, [=]() {
QString new_name = form->getSignal().name.c_str();
title->setText(QString("%1. %2").arg(index + 1).arg(new_name));
emit save();
sig_name = new_name;
});
QObject::connect(seek_btn, &QPushButton::clicked, [this, msg_id, s = &sig]() {
SignalFindDlg dlg(msg_id, s, this);
QObject::connect(save_btn, &QPushButton::clicked, this, &SignalEdit::saveSignal);
QObject::connect(seek_btn, &QPushButton::clicked, [this, msg_id]() {
SignalFindDlg dlg(msg_id, this->sig, this);
dlg.exec();
});
}
void SignalEdit::saveSignal() {
Signal s = *sig;
s.name = form->name->text().toStdString();
s.size = form->size->text().toInt();
s.offset = form->offset->text().toDouble();
s.factor = form->factor->text().toDouble();
s.is_signed = form->sign->currentIndex() == 0;
s.is_little_endian = form->endianness->currentIndex() == 0;
if (s.is_little_endian) {
s.lsb = s.start_bit;
s.msb = s.start_bit + s.size - 1;
} else {
s.lsb = bigEndianStartBitsIndex(bigEndianBitIndex(s.start_bit) + s.size - 1);
s.msb = s.start_bit;
}
title->setText(QString("%1. %2").arg(form_idx + 1).arg(form->name->text()));
emit save(this->sig, s);
}
void SignalEdit::setFormVisible(bool visible) {
form_container->setVisible(visible);
icon->setText(visible ? "" : ">");
@ -167,27 +161,7 @@ void SignalEdit::leaveEvent(QEvent *event) {
QWidget::leaveEvent(event);
}
// AddSignalDialog
AddSignalDialog::AddSignalDialog(const QString &id, int start_bit, int size, QWidget *parent) : QDialog(parent) {
setWindowTitle(tr("Add signal to %1").arg(dbc()->msg(id)->name.c_str()));
QVBoxLayout *main_layout = new QVBoxLayout(this);
Signal sig = {
.name = "untitled",
.start_bit = bigEndianBitIndex(start_bit),
.is_little_endian = false,
.size = size,
};
form = new SignalForm(sig, this);
main_layout->addWidget(form);
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
main_layout->addWidget(buttonBox);
setFixedWidth(parent->width() * 0.9);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
}
// SignalFindDlg
SignalFindDlg::SignalFindDlg(const QString &id, const Signal *signal, QWidget *parent) : QDialog(parent) {
setWindowTitle(tr("Find signal values"));

@ -15,48 +15,41 @@
class SignalForm : public QWidget {
public:
SignalForm(const Signal &sig, QWidget *parent);
Signal getSignal();
QLineEdit *name, *unit, *comment, *val_desc;
QSpinBox *size, *offset;
QDoubleSpinBox *factor, *min_val, *max_val;
QComboBox *sign, *endianness;
int start_bit = 0;
};
class SignalEdit : public QWidget {
Q_OBJECT
public:
SignalEdit(int index, const QString &msg_id, const Signal &sig, QWidget *parent = nullptr);
SignalEdit(int index, const QString &msg_id, const Signal *sig, QWidget *parent = nullptr);
void setFormVisible(bool show);
void signalHovered(const Signal *sig);
inline bool isFormVisible() const { return form_container->isVisible(); }
QString sig_name;
SignalForm *form;
int form_idx = 0;
const Signal *sig = nullptr;
signals:
void highlight(const Signal *sig);
void showChart();
void showFormClicked();
void remove();
void save();
void remove(const Signal *sig);
void save(const Signal *sig, const Signal &new_sig);
protected:
void enterEvent(QEvent *event) override;
void leaveEvent(QEvent *event) override;
void saveSignal();
SignalForm *form;
ElidedLabel *title;
QWidget *form_container;
QLabel *icon;
};
class AddSignalDialog : public QDialog {
public:
AddSignalDialog(const QString &id, int start_bit, int size, QWidget *parent);
SignalForm *form;
int form_idx = 0;
QString msg_id;
const Signal *sig = nullptr;
};
class SignalFindDlg : public QDialog {

@ -197,8 +197,8 @@ void TestReplay::test_seek() {
stream_thread_ = new QThread(this);
QEventLoop loop;
std::thread thread = std::thread([&]() {
for (int i = 0; i < 50; ++i) {
testSeekTo(random_int(0, 3 * 60));
for (int i = 0; i < 10; ++i) {
testSeekTo(random_int(0, 1 * 60));
}
loop.quit();
});
@ -207,8 +207,7 @@ void TestReplay::test_seek() {
}
TEST_CASE("Replay") {
auto flag = GENERATE(REPLAY_FLAG_NO_FILE_CACHE, REPLAY_FLAG_NONE);
TestReplay replay(DEMO_ROUTE, flag);
TestReplay replay(DEMO_ROUTE);
REQUIRE(replay.load());
replay.test_seek();
}

@ -46,7 +46,7 @@ pip install poetry==1.2.2
poetry config virtualenvs.prefer-active-python true --local
POETRY_INSTALL_ARGS=""
if [ -d "./xx" ]; then
if [ -d "./xx" ] || [ -n "$XX" ]; then
echo "WARNING: using xx dependency group, installing globally"
poetry config virtualenvs.create false --local
POETRY_INSTALL_ARGS="--with xx --sync"
@ -60,6 +60,7 @@ if [ -d "./xx" ] || [ -n "$POETRY_VIRTUALENVS_CREATE" ]; then
RUN=""
else
echo "PYTHONPATH=${PWD}" > .env
poetry self add poetry-dotenv-plugin@^0.1.0
RUN="poetry run"
fi

Loading…
Cancel
Save