diff --git a/.github/PULL_REQUEST_TEMPLATE/car_bugfix.md b/.github/PULL_REQUEST_TEMPLATE/car_bugfix.md index 76c86346c85491..d0c8bc58e4dbf7 100644 --- a/.github/PULL_REQUEST_TEMPLATE/car_bugfix.md +++ b/.github/PULL_REQUEST_TEMPLATE/car_bugfix.md @@ -1,6 +1,6 @@ --- name: Car Bug fix -about: For vehicle/brand specific bug fixes +about: For vehicle/brand specifc bug fixes title: '' labels: 'car bug fix' assignees: '' diff --git a/.gitignore b/.gitignore index 062358ef2478b5..6aee0ed8e0b077 100644 --- a/.gitignore +++ b/.gitignore @@ -36,7 +36,6 @@ a.out config.json clcache compile_commands.json -compare_runtime*.html persist board/obj/ diff --git a/.gitmodules b/.gitmodules index 26f93ef164e782..bc439b451c4583 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,6 +16,3 @@ [submodule "body"] path = body url = ../../commaai/body.git -[submodule "tinygrad"] - path = tinygrad_repo - url = https://github.com/geohot/tinygrad.git diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 347216f2fba3c2..e273cd9aeeab91 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,20 +15,11 @@ repos: - id: check-symlinks - id: check-added-large-files args: ['--maxkb=100'] -- repo: https://github.com/codespell-project/codespell - rev: v2.2.1 - hooks: - - id: codespell - exclude: '^(pyextra/)|(third_party/)|(body/)|(cereal/)|(rednose/)|(panda/)|(laika/)|(opendbc/)|(laika_repo/)|(rednose_repo/)|(include/)|(selfdrive/ui/translations/.*.ts)|(selfdrive/controls/lib/cluster)' - args: - # 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 - - --builtins clear,rare,informal,usage,code,names,en-GB_to_en-US - repo: https://github.com/pre-commit/mirrors-mypy rev: v0.931 hooks: - id: mypy - exclude: '^(pyextra/)|(cereal/)|(rednose/)|(panda/)|(laika/)|(opendbc/)|(laika_repo/)|(rednose_repo/)/|(tinygrad/)|(tinygrad_repo/)' + exclude: '^(pyextra/)|(cereal/)|(rednose/)|(panda/)|(laika/)|(opendbc/)|(laika_repo/)|(rednose_repo/)/' additional_dependencies: ['types-PyYAML', 'lxml', 'numpy', 'types-atomicwrites', 'types-pycurl', 'types-requests', 'types-certifi'] args: - --warn-redundant-casts @@ -40,7 +31,7 @@ repos: rev: 4.0.1 hooks: - id: flake8 - exclude: '^(pyextra/)|(cereal/)|(rednose/)|(panda/)|(laika/)|(opendbc/)|(laika_repo/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)|(selfdrive/debug/)/' + exclude: '^(pyextra/)|(cereal/)|(rednose/)|(panda/)|(laika/)|(opendbc/)|(laika_repo/)|(rednose_repo/)|(selfdrive/debug/)/' additional_dependencies: ['flake8-no-implicit-concat'] args: - --indent-size=2 @@ -55,11 +46,7 @@ repos: entry: pylint language: system types: [python] - exclude: '^(pyextra/)|(cereal/)|(rednose/)|(panda/)|(laika/)|(laika_repo/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)' - args: - - -rn - - -sn - - --rcfile=.pylintrc + exclude: '^(pyextra/)|(cereal/)|(rednose/)|(panda/)|(laika/)|(laika_repo/)|(rednose_repo/)' - repo: local hooks: - id: cppcheck diff --git a/Jenkinsfile b/Jenkinsfile index c4038090e14be9..6b05e81d790a33 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -131,8 +131,7 @@ pipeline { ["test boardd loopback", "python selfdrive/boardd/tests/test_boardd_loopback.py"], ["test loggerd", "python selfdrive/loggerd/tests/test_loggerd.py"], ["test encoder", "LD_LIBRARY_PATH=/usr/local/lib python selfdrive/loggerd/tests/test_encoder.py"], - ["test sensord", "python selfdrive/sensord/tests/test_sensord.py"], - ["test pigeond", "python selfdrive/sensord/tests/test_pigeond.py"], + ["test sensord", "python selfdrive/sensord/test/test_sensord.py"], ]) } } diff --git a/Pipfile b/Pipfile index 644fd2a90bb2e0..81669e4807fe57 100644 --- a/Pipfile +++ b/Pipfile @@ -88,7 +88,6 @@ urllib3 = "*" utm = "*" websocket_client = "*" hatanaka = "==2.4" -PySide2 = "*" [requires] python_version = "3.8" diff --git a/Pipfile.lock b/Pipfile.lock index e6f05fbcd4f294..0612d0ff396133 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "adf64558652d394d9de8e45777f1a2f50ed1ac37b75664206e7957792832b5a4" + "sha256": "c92514c0e6968af008916446514f41b4e004aa7aa4a2951cc1e9e258ac072111" }, "pipfile-spec": 6, "requires": { @@ -18,18 +18,19 @@ "default": { "astroid": { "hashes": [ - "sha256:396c88d0a58d7f8daadf730b2ce90838bf338c6752558db719ec6f99c18ec20e", - "sha256:d612609242996c4365aeb0345e61edba34363eaaba55f1c0addf6a98f073bef6" + "sha256:4f933d0bf5e408b03a6feb5d23793740c27e07340605f236496cd6ce552043d6", + "sha256:ba33a82a9a9c06a5ceed98180c5aab16e29c285b828d94696bf32d6015ea82a9" ], - "markers": "python_full_version >= '3.7.2'", - "version": "==2.12.5" + "markers": "python_full_version >= '3.6.2'", + "version": "==2.11.6" }, "atomicwrites": { "hashes": [ - "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11" + "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197", + "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a" ], "index": "pypi", - "version": "==1.4.1" + "version": "==1.4.0" }, "casadi": { "hashes": [ @@ -156,11 +157,11 @@ }, "charset-normalizer": { "hashes": [ - "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845", - "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f" + "sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5", + "sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413" ], "markers": "python_version >= '3.6'", - "version": "==2.1.1" + "version": "==2.1.0" }, "click": { "hashes": [ @@ -170,14 +171,6 @@ "markers": "python_version >= '3.7'", "version": "==8.1.3" }, - "coloredlogs": { - "hashes": [ - "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934", - "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==15.0.1" - }, "crcmod": { "hashes": [ "sha256:50586ab48981f11e5b117523d97bb70864a2a1af246cf6e4f5c4a21ef4611cd1", @@ -218,49 +211,49 @@ }, "cython": { "hashes": [ - "sha256:061e25151c38f2361bc790d3bcf7f9d9828a0b6a4d5afa56fbed3bd33fb2373a", - "sha256:06be83490c906b6429b4389e13487a26254ccaad2eef6f3d4ee21d8d3a4aaa2b", - "sha256:07d173d3289415bb496e72cb0ddd609961be08fe2968c39094d5712ffb78672b", - "sha256:0bbc27abdf6aebfa1bce34cd92bd403070356f28b0ecb3198ff8a182791d58b9", - "sha256:0ea8267fc373a2c5064ad77d8ff7bf0ea8b88f7407098ff51829381f8ec1d5d9", - "sha256:3875c2b2ea752816a4d7ae59d45bb546e7c4c79093c83e3ba7f4d9051dd02928", - "sha256:39afb4679b8c6bf7ccb15b24025568f4f9b4d7f9bf3cbd981021f542acecd75b", - "sha256:3f85eb2343d20d91a4ea9cf14e5748092b376a64b7e07fc224e85b2753e9070b", - "sha256:40eff7aa26e91cf108fd740ffd4daf49f39b2fdffadabc7292b4b7dc5df879f0", - "sha256:479690d2892ca56d34812fe6ab8f58e4b2e0129140f3d94518f15993c40553da", - "sha256:4a4b03ab483271f69221c3210f7cde0dcc456749ecf8243b95bc7a701e5677e0", - "sha256:513e9707407608ac0d306c8b09d55a28be23ea4152cbd356ceaec0f32ef08d65", - "sha256:5514f3b4122cb22317122a48e175a7194e18e1803ca555c4c959d7dfe68eaf98", - "sha256:5ba622326f2862f9c1f99ca8d47ade49871241920a352c917e16861e25b0e5c3", - "sha256:63b79d9e1f7c4d1f498ab1322156a0d7dc1b6004bf981a8abda3f66800e140cd", - "sha256:656dc5ff1d269de4d11ee8542f2ffd15ab466c447c1f10e5b8aba6f561967276", - "sha256:67fdd2f652f8d4840042e2d2d91e15636ba2bcdcd92e7e5ffbc68e6ef633a754", - "sha256:79e3bab19cf1b021b613567c22eb18b76c0c547b9bc3903881a07bfd9e7e64cf", - "sha256:856d2fec682b3f31583719cb6925c6cdbb9aa30f03122bcc45c65c8b6f515754", - "sha256:8669cadeb26d9a58a5e6b8ce34d2c8986cc3b5c0bfa77eda6ceb471596cb2ec3", - "sha256:8733cf4758b79304f2a4e39ebfac5e92341bce47bcceb26c1254398b2f8c1af7", - "sha256:97335b2cd4acebf30d14e2855d882de83ad838491a09be2011745579ac975833", - "sha256:afbce249133a830f121b917f8c9404a44f2950e0e4f5d1e68f043da4c2e9f457", - "sha256:b0595aee62809ba353cebc5c7978e0e443760c3e882e2c7672c73ffe46383673", - "sha256:b6da3063c5c476f5311fd76854abae6c315f1513ef7d7904deed2e774623bbb9", - "sha256:c8e8025f496b5acb6ba95da2fb3e9dacffc97d9a92711aacfdd42f9c5927e094", - "sha256:cddc47ec746a08603037731f5d10aebf770ced08666100bd2cdcaf06a85d4d1b", - "sha256:cdf10af3e2e3279dc09fdc5f95deaa624850a53913f30350ceee824dc14fc1a6", - "sha256:d968ffc403d92addf20b68924d95428d523436adfd25cf505d427ed7ba3bee8b", - "sha256:dbee03b8d42dca924e6aa057b836a064c769ddfd2a4c2919e65da2c8a362d528", - "sha256:e1958e0227a4a6a2c06fd6e35b7469de50adf174102454db397cec6e1403cce3", - "sha256:e6ffa08aa1c111a1ebcbd1cf4afaaec120bc0bbdec3f2545f8bb7d3e8e77a1cd", - "sha256:e83228e0994497900af954adcac27f64c9a57cd70a9ec768ab0cb2c01fd15cf1", - "sha256:ea1dcc07bfb37367b639415333cfbfe4a93c3be340edf1db10964bc27d42ed64", - "sha256:eca3065a1279456e81c615211d025ea11bfe4e19f0c5650b859868ca04b3fcbd", - "sha256:ed087eeb88a8cf96c60fb76c5c3b5fb87188adee5e179f89ec9ad9a43c0c54b3", - "sha256:eeb475eb6f0ccf6c039035eb4f0f928eb53ead88777e0a760eccb140ad90930b", - "sha256:eefd2b9a5f38ded8d859fe96cc28d7d06e098dc3f677e7adbafda4dcdd4a461c", - "sha256:f3fd44cc362eee8ae569025f070d56208908916794b6ab21e139cea56470a2b3", - "sha256:f9944013588a3543fca795fffb0a070a31a243aa4f2d212f118aa95e69485831" - ], - "index": "pypi", - "version": "==0.29.32" + "sha256:019d330ac580b2ca4a457c464ac0b8c35009d820ef5d09f328d6e31a10e1ce89", + "sha256:0b83a342a071c4f14e7410568e0c0bd95e2f20c0b32944e3a721649a1357fda4", + "sha256:0cd6c932e945af15ae4ddcf8fdc0532bda48784c92ed0a53cf4fae897067ccd1", + "sha256:1e078943bbde703ca08d43e719480eb8b187d9023cbd91798619f5b5e18d0d71", + "sha256:20778297c8bcba201ca122a2f792a9899d6e64c68a92363dd7eb24306d54d7ce", + "sha256:2235b62da8fe6fa8b99422c8e583f2fb95e143867d337b5c75e4b9a1a865f9e3", + "sha256:28db751e2d8365b39664d9cb62dc1668688b8fcc5b954e9ca9d20e0b8e03d8b0", + "sha256:3993aafd68a7311ef94e00e44a137f6a50a69af0575ebcc8a0a074ad4152a2b2", + "sha256:3d0239c7a22a0f3fb1deec75cab0078eba4dd17868aa992a54a178851e0c8684", + "sha256:5183356c756b56c2df12d96300d602e47ffb89943c5a0bded66faca5d3da7be0", + "sha256:58d2b734250c1093bc69c1c3a6f5736493b9f8b34eb765f0a28a4a09468c0b00", + "sha256:5a8a3709ad9343a1dc02b8ec9cf6bb284be248d2c64af85464d9c3525eec74a5", + "sha256:5c7cfd908efc77306ddd41ef07f5a7a352c9205ced5c1e00a0e5ece4391707c4", + "sha256:5f2dae7dd56860018d5fd5032a71f11fdc224020932b463d0511a1536f27df85", + "sha256:60d370c33d56077d30e5f425026e58c2559e93b4784106f61581cf54071f6270", + "sha256:6b389a94b42909ff56d3491fde7c44802053a103701a7d210dcdd449a5b4f7b4", + "sha256:71fd1d910aced510c001936667fc7f2901c49b2ca7a2ad67358979c94a7f42ac", + "sha256:786ee7b0cdb508b6de64c0f1f9c74f207186dfafad1ef938f25b7494cc481a80", + "sha256:7eff71c39b98078deaad1d1bdbf10864d234e2ab5d5257e980a6926a8523f697", + "sha256:80a7255ad84620f53235c0720cdee2bc7431d9e3db7b3742823a606c329eb539", + "sha256:88c5e2f92f16cd999ddfc43d572639679e8a057587088e627e98118e46a803e6", + "sha256:8e08f18d249b9b65e272a5a60f3360a8922c4c149036b98fc821fe1afad5bdae", + "sha256:9462e9cf284d9b1d2c5b53d62188e3c09cc5c7a0018ba349d99b73cf930238de", + "sha256:9826981308802c61a76f967875b31b7c683b7fc369eabaa6cbc22efeb12c90e8", + "sha256:9f1fe924c920b699af27aefebd722df4cfbb85206291623cd37d1a7ddfd57792", + "sha256:a30092c6e2d24255fbfe0525f9a750554f96a263ed986d12ac3c9f7d9a85a424", + "sha256:abcaf99f90cddc0f53600613eaafc81d27c4ac0671f0df8bce5466d4e86d54a1", + "sha256:acb72e0b42079862cf2f894964b41f261e941e75677e902c5f4304b3eb00af33", + "sha256:b17639b6a155abaa61a89f6f1323fb57b138d0529911ca03978d594945d062ba", + "sha256:c299c5b250ae9f81c38200441b6f1d023aeee9d8e7f61c04001c7437181ccb06", + "sha256:c79685dd4631a188e2385dc6a232896c7b67ea2e3e5f8b5555b4b743f475d6d7", + "sha256:d0859a958e0155b6ae4dee04170ccfac2c3d613a7e3bee8749614530b9e3b4a4", + "sha256:d0f34b44078e3e0b2f1be2b99044619b37127128e7d55c54bbd2438adcaf31d3", + "sha256:d166d9f853db436f5e10733a9bd615699ddb4238feadcbdf5ae50dc0b18b18f5", + "sha256:d52d5733dcb144deca8985f0a197c19cf71e6bd6bd9d8034f3f67b2dea68d12b", + "sha256:e29d3487f357108b711f2f29319811d92166643d29aec1b8e063aad46a346775", + "sha256:e36755e71fd20eceb410cc441b7f2586654c2edb013f4663842fdaf60b96c1ca", + "sha256:e5cb144728a335d7a7fd0a61dff6abb7a9aeff9acd46d50b886b7d9a95bb7311", + "sha256:e605635a92ae862cb46d84d1d6883324518f9aaff4a71cede6d61df20b6a410c", + "sha256:ffa8c09617833ff0824aa7926fa4fa9d2ec3929c67168e89105f276b7f36a63e" + ], + "index": "pypi", + "version": "==0.29.30" }, "dill": { "hashes": [ @@ -272,26 +265,26 @@ }, "flake8": { "hashes": [ - "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db", - "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248" + "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d", + "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d" ], "index": "pypi", - "version": "==5.0.4" + "version": "==4.0.1" }, "flask": { "hashes": [ - "sha256:642c450d19c4ad482f96729bd2a8f6d32554aa1e231f4f6b4e7e5264b16cca2b", - "sha256:b9c46cc36662a7949f34b52d8ec7bb59c0d74ba08ba6cb9ce9adc1d8676d9526" + "sha256:315ded2ddf8a6281567edb27393010fe3406188bafbfe65a3339d5787d89e477", + "sha256:fad5b446feb0d6db6aec0c3184d16a8c1f6c3e464b511649c8918a9be100b4fe" ], "index": "pypi", - "version": "==2.2.2" + "version": "==2.1.2" }, "flatbuffers": { "hashes": [ - "sha256:0ae7d69c5b82bf41962ca5fde9cc43033bc9501311d975fd5a25e8a7d29c1245", - "sha256:71e135d533be527192819aaab757c5e3d109cb10fbb01e687f6bdb7a61ad39d1" + "sha256:12158ab0272375eab8db2d663ae97370c33f152b27801fa6024e1d6105fd4dd2", + "sha256:3751954f0604580d3219ae49a85fafec9d85eec599c0b96226e1bc0b48e57474" ], - "version": "==2.0.7" + "version": "==2.0" }, "future-fstrings": { "hashes": [ @@ -363,14 +356,6 @@ "index": "pypi", "version": "==3.3" }, - "humanfriendly": { - "hashes": [ - "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477", - "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==10.0" - }, "idna": { "hashes": [ "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", @@ -389,18 +374,18 @@ }, "importlib-resources": { "hashes": [ - "sha256:5481e97fb45af8dcf2f798952625591c58fe599d0735d86b10f54de086a61681", - "sha256:f78a8df21a79bcc30cfd400bdc38f314333de7c0fb619763f6b9dabab8268bb7" + "sha256:568c9f16cb204f9decc8d6d24a572eeea27dacbb4cee9e6b03a8025736769751", + "sha256:7952325ffd516c05a8ad0858c74dff2c3343f136fe66a6002b2623dd1d43f223" ], "markers": "python_version >= '3.7'", - "version": "==5.9.0" + "version": "==5.8.0" }, "isort": { "hashes": [ "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7", "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951" ], - "markers": "python_version < '4.0' and python_full_version >= '3.6.1'", + "markers": "python_version < '4' and python_full_version >= '3.6.1'", "version": "==5.10.1" }, "itsdangerous": { @@ -528,11 +513,10 @@ }, "mccabe": { "hashes": [ - "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", - "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e" + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" ], - "markers": "python_version >= '3.6'", - "version": "==0.7.0" + "version": "==0.6.1" }, "mpmath": { "hashes": [ @@ -593,37 +577,31 @@ }, "numpy": { "hashes": [ - "sha256:17e5226674f6ea79e14e3b91bfbc153fdf3ac13f5cc54ee7bc8fdbe820a32da0", - "sha256:2bd879d3ca4b6f39b7770829f73278b7c5e248c91d538aab1e506c628353e47f", - "sha256:4f41f5bf20d9a521f8cab3a34557cd77b6f205ab2116651f12959714494268b0", - "sha256:5593f67e66dea4e237f5af998d31a43e447786b2154ba1ad833676c788f37cde", - "sha256:5e28cd64624dc2354a349152599e55308eb6ca95a13ce6a7d5679ebff2962913", - "sha256:633679a472934b1c20a12ed0c9a6c9eb167fbb4cb89031939bfd03dd9dbc62b8", - "sha256:806970e69106556d1dd200e26647e9bee5e2b3f1814f9da104a943e8d548ca38", - "sha256:806cc25d5c43e240db709875e947076b2826f47c2c340a5a2f36da5bb10c58d6", - "sha256:8247f01c4721479e482cc2f9f7d973f3f47810cbc8c65e38fd1bbd3141cc9842", - "sha256:8ebf7e194b89bc66b78475bd3624d92980fca4e5bb86dda08d677d786fefc414", - "sha256:8ecb818231afe5f0f568c81f12ce50f2b828ff2b27487520d85eb44c71313b9e", - "sha256:8f9d84a24889ebb4c641a9b99e54adb8cab50972f0166a3abc14c3b93163f074", - "sha256:909c56c4d4341ec8315291a105169d8aae732cfb4c250fbc375a1efb7a844f8f", - "sha256:9b83d48e464f393d46e8dd8171687394d39bc5abfe2978896b77dc2604e8635d", - "sha256:ac987b35df8c2a2eab495ee206658117e9ce867acf3ccb376a19e83070e69418", - "sha256:b78d00e48261fbbd04aa0d7427cf78d18401ee0abd89c7559bbf422e5b1c7d01", - "sha256:b8b97a8a87cadcd3f94659b4ef6ec056261fa1e1c3317f4193ac231d4df70215", - "sha256:bd5b7ccae24e3d8501ee5563e82febc1771e73bd268eef82a1e8d2b4d556ae66", - "sha256:bdc02c0235b261925102b1bd586579b7158e9d0d07ecb61148a1799214a4afd5", - "sha256:be6b350dfbc7f708d9d853663772a9310783ea58f6035eec649fb9c4371b5389", - "sha256:c403c81bb8ffb1c993d0165a11493fd4bf1353d258f6997b3ee288b0a48fce77", - "sha256:cf8c6aed12a935abf2e290860af8e77b26a042eb7f2582ff83dc7ed5f963340c", - "sha256:d98addfd3c8728ee8b2c49126f3c44c703e2b005d4a95998e2167af176a9e722", - "sha256:dc76bca1ca98f4b122114435f83f1fcf3c0fe48e4e6f660e07996abf2f53903c", - "sha256:dec198619b7dbd6db58603cd256e092bcadef22a796f778bf87f8592b468441d", - "sha256:df28dda02c9328e122661f399f7655cdcbcf22ea42daa3650a26bce08a187450", - "sha256:e603ca1fb47b913942f3e660a15e55a9ebca906857edfea476ae5f0fe9b457d5", - "sha256:ecfdd68d334a6b97472ed032b5b37a30d8217c097acfff15e8452c710e775524" - ], - "index": "pypi", - "version": "==1.23.2" + "sha256:092f5e6025813e64ad6d1b52b519165d08c730d099c114a9247c9bb635a2a450", + "sha256:196cd074c3f97c4121601790955f915187736f9cf458d3ee1f1b46aff2b1ade0", + "sha256:1c29b44905af288b3919803aceb6ec7fec77406d8b08aaa2e8b9e63d0fe2f160", + "sha256:2b2da66582f3a69c8ce25ed7921dcd8010d05e59ac8d89d126a299be60421171", + "sha256:5043bcd71fcc458dfb8a0fc5509bbc979da0131b9d08e3d5f50fb0bbb36f169a", + "sha256:58bfd40eb478f54ff7a5710dd61c8097e169bc36cc68333d00a9bcd8def53b38", + "sha256:79a506cacf2be3a74ead5467aee97b81fca00c9c4c8b3ba16dbab488cd99ba10", + "sha256:94b170b4fa0168cd6be4becf37cb5b127bd12a795123984385b8cd4aca9857e5", + "sha256:97a76604d9b0e79f59baeca16593c711fddb44936e40310f78bfef79ee9a835f", + "sha256:98e8e0d8d69ff4d3fa63e6c61e8cfe2d03c29b16b58dbef1f9baa175bbed7860", + "sha256:ac86f407873b952679f5f9e6c0612687e51547af0e14ddea1eedfcb22466babd", + "sha256:ae8adff4172692ce56233db04b7ce5792186f179c415c37d539c25de7298d25d", + "sha256:bd3fa4fe2e38533d5336e1272fc4e765cabbbde144309ccee8675509d5cd7b05", + "sha256:d0d2094e8f4d760500394d77b383a1b06d3663e8892cdf5df3c592f55f3bff66", + "sha256:d54b3b828d618a19779a84c3ad952e96e2c2311b16384e973e671aa5be1f6187", + "sha256:d6ca8dabe696c2785d0c8c9b0d8a9b6e5fdbe4f922bde70d57fa1a2848134f95", + "sha256:d8cc87bed09de55477dba9da370c1679bd534df9baa171dd01accbb09687dac3", + "sha256:f0f18804df7370571fb65db9b98bf1378172bd4e962482b857e612d1fec0f53e", + "sha256:f1d88ef79e0a7fa631bb2c3dda1ea46b32b1fe614e10fedd611d3d5398447f2f", + "sha256:f9c3fc2adf67762c9fe1849c859942d23f8d3e0bee7b5ed3d4a9c3eeb50a2f07", + "sha256:fc431493df245f3c627c0c05c2bd134535e7929dbe2e602b80e42bf52ff760bc", + "sha256:fe8b9683eb26d2c4d5db32cd29b38fdcf8381324ab48313b5b69088e0e355379" + ], + "index": "pypi", + "version": "==1.23.0" }, "onnx": { "hashes": [ @@ -654,26 +632,16 @@ }, "onnxruntime-gpu": { "hashes": [ - "sha256:296bd9733986cb7517d15bef5535c555d3f863963a71e6575e92d2a854aee61d", - "sha256:42b0393c5122ed90fa2eb76192a486261d86e9526ccb78b2a98923c22791d2d1", - "sha256:8e46d0724ce54c5908c5760037b78de741fbd48962b370c29ebc20e608b30eda", - "sha256:b37872527d03d3df10756408ca44014bd6ac354a044ab1c4286cd42dc138e518", - "sha256:d73204323aefebe4eecab9fcf76e22b1a00394e3d838c2962a28a27301186b73", - "sha256:e2be6f7f5a1ce0bc8471ce42e10eab92cfb19d0748b857edcb5320b5e98311b7", - "sha256:ecfe97335027e569d4f46725ba89316041e562b8c499690e25e11cfee4601cd1", - "sha256:fd919373be35b9ba54210688265df38ad5e19a530449385c40dab51da407345d" + "sha256:3f1363e9ba30051cc3d649beefbd12047e1c41b5c47bcacfbfb23b74a7d68f7b", + "sha256:3fad0d3df58815c11160714433ca3bcff6d9a06f721bcc97ade46abce30aea72", + "sha256:a4f5317838f4816a9b21fcb43d551ac95f9d35ca8ecd5c959419b3b94d458342", + "sha256:be1766a9d60ec774e1a7a0279ade5ec001c5d528f2f2dbe9f8d02133e49d1d68", + "sha256:c79f42cbdee18e059c0ba43f0efeb7117539dfb76d6ed0e4a9ecc34093ed97b3", + "sha256:dc34be44224aa855d7ab17f61942b665788a2136ae4f71ee857fa47b38d1fdb8" ], "index": "pypi", "markers": "platform_system != 'Darwin'", - "version": "==1.12.1" - }, - "packaging": { - "hashes": [ - "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", - "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522" - ], - "markers": "python_version >= '3.6'", - "version": "==21.3" + "version": "==1.11.1" }, "pillow": { "hashes": [ @@ -850,11 +818,11 @@ }, "pycodestyle": { "hashes": [ - "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785", - "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b" + "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20", + "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f" ], - "markers": "python_version >= '3.6'", - "version": "==2.9.1" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.8.0" }, "pycparser": { "hashes": [ @@ -901,11 +869,11 @@ }, "pyflakes": { "hashes": [ - "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2", - "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3" + "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c", + "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e" ], - "markers": "python_version >= '3.6'", - "version": "==2.5.0" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.4.0" }, "pyjwt": { "hashes": [ @@ -917,11 +885,11 @@ }, "pylint": { "hashes": [ - "sha256:4b124affc198b7f7c9b5f9ab690d85db48282a025ef9333f51d2d7281b92a6c3", - "sha256:4f3f7e869646b0bd63b3dfb79f3c0f28fc3d2d923ea220d52620fd625aed92b0" + "sha256:47705453aa9dce520e123a7d51843d5f0032cbfa06870f89f00927aa1f735a4a", + "sha256:89b61867db16eefb7b3c5b84afc94081edaf11544189e2b238154677529ad69f" ], "index": "pypi", - "version": "==2.15.0" + "version": "==2.14.4" }, "pyopencl": { "hashes": [ @@ -966,14 +934,6 @@ "index": "pypi", "version": "==2022.1.6" }, - "pyparsing": { - "hashes": [ - "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb", - "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc" - ], - "markers": "python_full_version >= '3.6.8'", - "version": "==3.0.9" - }, "pyserial": { "hashes": [ "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb", @@ -982,18 +942,6 @@ "index": "pypi", "version": "==3.5" }, - "pyside2": { - "hashes": [ - "sha256:235240b6ec8206d9fdf0232472c6ef3241783d480425e5b54796f06e39ed23da", - "sha256:23886c6391ebd916e835fa1b5ae66938048504fd3a2934ae3189a96cd5ac0b46", - "sha256:439509e53cfe05abbf9a99422a2cbad086408b0f9bf5e6f642ff1b13b1f8b055", - "sha256:a9e2e6bbcb5d2ebb421e46e72244a0f4fe0943b2288115f80a863aacc1de1f06", - "sha256:af6b263fe63ba6dea7eaebae80aa7b291491fe66f4f0057c0aafe780cc83da9d", - "sha256:b5e1d92f26b0bbaefff67727ccbb2e1b577f2c0164b349b3d6e80febb4c5bde2" - ], - "index": "pypi", - "version": "==5.15.2.1" - }, "python-dateutil": { "hashes": [ "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", @@ -1050,82 +998,66 @@ }, "pyzmq": { "hashes": [ - "sha256:022cf5ea7bcaa8a06a03c2706e0ae66904b6138b2155577cd34c64bc7cc637ab", - "sha256:044447ae4b2016a6b8697571fd633f799f860b19b76c4a2fd9b1140d52ee6745", - "sha256:07ed8aaf7ffe150af873269690cc654ffeca7491f62aae0f3821baa181f8d5fe", - "sha256:10d1910ec381b851aeb024a042a13db178cb1edf125e76a4e9d2548ad103aadb", - "sha256:12e62ff0d5223ec09b597ab6d73858b9f64a51221399f3cb08aa495e1dff7935", - "sha256:1f368a82b29f80071781b20663c0fc0c8f6b13273f9f5abe1526af939534f90f", - "sha256:20bafc4095eab00f41a510579363a3f5e1f5c69d7ee10f1d88895c4df0259183", - "sha256:2141e6798d5981be04c08996d27962086a1aa3ea536fe9cf7e89817fd4523f86", - "sha256:23e708fbfdf4ee3107422b69ca65da1b9f056b431fc0888096a8c1d6cd908e8f", - "sha256:28dbdb90b2f6b131f8f10e6081012e4e25234213433420e67e0c1162de537113", - "sha256:29b74774a0bfd3c4d98ac853f0bdca55bd9ec89d5b0def5486407cca54472ef8", - "sha256:2b381aa867ece7d0a82f30a0c7f3d4387b7cf2e0697e33efaa5bed6c5784abcd", - "sha256:2f67b63f53c6994d601404fd1a329e6d940ac3dd1d92946a93b2b9c70df67b9f", - "sha256:342ca3077f47ec2ee41b9825142b614e03e026347167cbc72a59b618c4f6106c", - "sha256:35e635343ff367f697d00fa1484262bb68e36bc74c9b80737eac5a1e04c4e1b1", - "sha256:385609812eafd9970c3752c51f2f6c4f224807e3e441bcfd8c8273877d00c8a8", - "sha256:38e106b64bad744fe469dc3dd864f2764d66399178c1bf39d45294cc7980f14f", - "sha256:39dd252b683816935702825e5bf775df16090619ced9bb4ba68c2d0b6f0c9b18", - "sha256:407f909c4e8fde62fbdad9ebd448319792258cc0550c2815567a4d9d8d9e6d18", - "sha256:415ff62ac525d9add1e3550430a09b9928d2d24a20cc4ce809e67caac41219ab", - "sha256:4805af9614b0b41b7e57d17673459facf85604dac502a5a9244f6e8c9a4de658", - "sha256:48400b96788cdaca647021bf19a9cd668384f46e4d9c55cf045bdd17f65299c8", - "sha256:49d30ba7074f469e8167917abf9eb854c6503ae10153034a6d4df33618f1db5f", - "sha256:4bb798bef181648827019001f6be43e1c48b34b477763b37a8d27d8c06d197b8", - "sha256:4d6f110c56f7d5b4d64dde3a382ae61b6d48174e30742859d8e971b18b6c9e5c", - "sha256:55568a020ad2cae9ae36da6058e7ca332a56df968f601cbdb7cf6efb2a77579a", - "sha256:565bd5ab81f6964fc4067ccf2e00877ad0fa917308975694bbb54378389215f8", - "sha256:5c558b50402fca1acc94329c5d8f12aa429738904a5cfb32b9ed3c61235221bb", - "sha256:5e05492be125dce279721d6b54fd1b956546ecc4bcdfcf8e7b4c413bc0874c10", - "sha256:624fd38071a817644acdae075b92a23ea0bdd126a58148288e8284d23ec361ce", - "sha256:650389bbfca73955b262b2230423d89992f38ec48033307ae80e700eaa2fbb63", - "sha256:67975a9e1237b9ccc78f457bef17691bbdd2055a9d26e81ee914ba376846d0ce", - "sha256:6b1e79bba24f6df1712e3188d5c32c480d8eda03e8ecff44dc8ecb0805fa62f3", - "sha256:6fd5d0d50cbcf4bc376861529a907bed026a4cbe8c22a500ff8243231ef02433", - "sha256:71b32a1e827bdcbf73750e60370d3b07685816ff3d8695f450f0f8c3226503f8", - "sha256:794871988c34727c7f79bdfe2546e6854ae1fa2e1feb382784f23a9c6c63ecb3", - "sha256:79a87831b47a9f6161ad23fa5e89d5469dc585abc49f90b9b07fea8905ae1234", - "sha256:7e0113d70b095339e99bb522fe7294f5ae6a7f3b2b8f52f659469a74b5cc7661", - "sha256:84678153432241bcdca2210cf4ff83560b200556867aea913ffbb960f5d5f340", - "sha256:8a68f57b7a3f7b6b52ada79876be1efb97c8c0952423436e84d70cc139f16f0d", - "sha256:8c02a0cd39dc01659b3d6cb70bb3a41aebd9885fd78239acdd8d9c91351c4568", - "sha256:8c842109d31a9281d678f668629241c405928afbebd913c48a5a8e7aee61f63d", - "sha256:8dc66f109a245653b19df0f44a5af7a3f14cb8ad6c780ead506158a057bd36ce", - "sha256:90d88f9d9a2ae6cfb1dc4ea2d1710cdf6456bc1b9a06dd1bb485c5d298f2517e", - "sha256:9269fbfe3a4eb2009199120861c4571ef1655fdf6951c3e7f233567c94e8c602", - "sha256:929d548b74c0f82f7f95b54e4a43f9e4ce2523cfb8a54d3f7141e45652304b2a", - "sha256:99a5a77a10863493a1ee8dece02578c6b32025fb3afff91b40476bc489e81648", - "sha256:9a39ddb0431a68954bd318b923230fa5b649c9c62b0e8340388820c5f1b15bd2", - "sha256:9d0ab2936085c85a1fc6f9fd8f89d5235ae99b051e90ec5baa5e73ad44346e1f", - "sha256:9e5bf6e7239fc9687239de7a283aa8b801ab85371116045b33ae20132a1325d6", - "sha256:a0f09d85c45f58aa8e715b42f8b26beba68b3b63a8f7049113478aca26efbc30", - "sha256:a114992a193577cb62233abf8cb2832970f9975805a64740e325d2f895e7f85a", - "sha256:a3fd44b5046d247e7f0f1660bcafe7b5fb0db55d0934c05dd57dda9e1f823ce7", - "sha256:ad28ddb40db8e450d7d4bf8a1d765d3f87b63b10e7e9a825a3c130c6371a8c03", - "sha256:aecd6ceaccc4b594e0092d6513ef3f1c0fa678dd89f86bb8ff1a47014b8fca35", - "sha256:b815991c7d024bf461f358ad871f2be1135576274caed5749c4828859e40354e", - "sha256:b861db65f6b8906c8d6db51dde2448f266f0c66bf28db2c37aea50f58a849859", - "sha256:c3ebf1668664d20c8f7d468955f18379b7d1f7bc8946b13243d050fa3888c7ff", - "sha256:c56b1a62a1fb87565343c57b6743fd5da6e138b8c6562361d7d9b5ce4acf399a", - "sha256:c780acddd2934c6831ff832ecbf78a45a7b62d4eb216480f863854a8b7d54fa7", - "sha256:c890309296f53f9aa32ffcfc51d805705e1982bffd27c9692a8f1e1b8de279f4", - "sha256:c9cfaf530e6a7ff65f0afe275e99f983f68b54dfb23ea401f0bc297a632766b6", - "sha256:d904f6595acfaaf99a1a61881fea068500c40374d263e5e073aa4005e5f9c28a", - "sha256:e06747014a5ad1b28cebf5bc1ddcdaccfb44e9b441d35e6feb1286c8a72e54be", - "sha256:e1fe30bcd5aea5948c42685fad910cd285eacb2518ea4dc6c170d6b535bee95d", - "sha256:e753eee6d3b93c5354e8ba0a1d62956ee49355f0a36e00570823ef64e66183f5", - "sha256:ec9803aca9491fd6f0d853d2a6147f19f8deaaa23b1b713d05c5d09e56ea7142", - "sha256:efb9e38b2a590282704269585de7eb33bf43dc294cad092e1b172e23d4c217e5", - "sha256:f07016e3cf088dbfc6e7c5a7b3f540db5c23b0190d539e4fd3e2b5e6beffa4b5", - "sha256:f392cbea531b7142d1958c0d4a0c9c8d760dc451e5848d8dd3387804d3e3e62c", - "sha256:f619fd38fc2641abfb53cca719c165182500600b82c695cc548a0f05f764be05", - "sha256:fefdf9b685fda4141b95ebec975946076a5e0723ff70b037032b2085c5317684", - "sha256:ffc6b1623d0f9affb351db4ca61f432dca3628a5ee015f9bf2bfbe9c6836881c" - ], - "index": "pypi", - "version": "==23.2.1" + "sha256:004a431dfa0459123e6f4660d7e3c4ac19217d134ca38bacfffb2e78716fe944", + "sha256:057b154471e096e2dda147f7b057041acc303bb7ca4aa24c3b88c6cecdd78717", + "sha256:0e08671dc202a1880fa522f921f35ca5925ba30da8bc96228d74a8f0643ead9c", + "sha256:1b2a21f595f8cc549abd6c8de1fcd34c83441e35fb24b8a59bf161889c62a486", + "sha256:21552624ce69e69f7924f413b802b1fb554f4c0497f837810e429faa1cd4f163", + "sha256:22ac0243a41798e3eb5d5714b28c2f28e3d10792dffbc8a5fca092f975fdeceb", + "sha256:2b054525c9f7e240562185bf21671ca16d56bde92e9bd0f822c07dec7626b704", + "sha256:30c365e60c39c53f8eea042b37ea28304ffa6558fb7241cf278745095a5757da", + "sha256:3a4d87342c2737fbb9eee5c33c792db27b36b04957b4e6b7edd73a5b239a2a13", + "sha256:420b9abd1a7330687a095373b8280a20cdee04342fbc8ccb3b56d9ec8efd4e62", + "sha256:444f7d615d5f686d0ef508b9edfa8a286e6d89f449a1ba37b60ef69d869220a3", + "sha256:558f5f636e3e65f261b64925e8b190e8689e334911595394572cc7523879006d", + "sha256:5592fb4316f895922b1cacb91b04a0fa09d6f6f19bbab4442b4d0a0825177b93", + "sha256:59928dfebe93cf1e203e3cb0fd5d5dd384da56b99c8305f2e1b0a933751710f6", + "sha256:5cb642e94337b0c76c9c8cb9bfb0f8a78654575847d080d3e1504f312d691fc3", + "sha256:5d57542429df6acff02ff022067aa75b677603cee70e3abb9742787545eec966", + "sha256:5d92e7cbeab7f70b08cc0f27255b0bb2500afc30f31075bca0b1cb87735d186c", + "sha256:602835e5672ca9ca1d78e6c148fb28c4f91b748ebc41fbd2f479d8763d58bc9b", + "sha256:60746a7e8558655420a69441c0a1d47ed225ed3ac355920b96a96d0554ef7e6b", + "sha256:61b97f624da42813f74977425a3a6144d604ea21cf065616d36ea3a866d92c1c", + "sha256:693c96ae4d975eb8efa1639670e9b1fac0c3f98b7845b65c0f369141fb4bb21f", + "sha256:814e5aaf0c3be9991a59066eafb2d6e117aed6b413e3e7e9be45d4e55f5e2748", + "sha256:83005d8928f8a5cebcfb33af3bfb84b1ad65d882b899141a331cc5d07d89f093", + "sha256:831da96ba3f36cc892f0afbb4fb89b28b61b387261676e55d55a682addbd29f7", + "sha256:8355744fdbdeac5cfadfa4f38b82029b5f2b8cab7472a33453a217a7f3a9dce2", + "sha256:8496a2a5efd055c61ac2c6a18116c768a25c644b6747dcfde43e91620ab3453c", + "sha256:859059caf564f0c9398c9005278055ed3d37af4d73de6b1597821193b04ca09b", + "sha256:8c0f4d6f8c985bab83792be26ff3233940ba42e22237610ac50cbcfc10a5c235", + "sha256:8c2d8b69a2bf239ae3d987537bf3fbc2b044a405394cf4c258fc684971dd48b2", + "sha256:984b232802eddf9f0be264a4d57a10b3a1fd7319df14ee6fc7b41c6d155a3e6c", + "sha256:99cedf38eaddf263cf7e2a50e405f12c02cedf6d9df00a0d9c5d7b9417b57f76", + "sha256:a3dc339f7bc185d5fd0fd976242a5baf35de404d467e056484def8a4dd95868b", + "sha256:a51f12a8719aad9dcfb55d456022f16b90abc8dde7d3ca93ce3120b40e3fa169", + "sha256:bbabd1df23bf63ae829e81200034c0e433499275a6ed29ca1a912ea7629426d9", + "sha256:bcc6953e47bcfc9028ddf9ab2a321a3c51d7cc969db65edec092019bb837959f", + "sha256:c0a5f987d73fd9b46c3d180891f829afda714ab6bab30a1218724d4a0a63afd8", + "sha256:c223a13555444707a0a7ebc6f9ee63053147c8c082bd1a31fd1207a03e8b0500", + "sha256:c616893a577e9d6773a3836732fd7e2a729157a108b8fccd31c87512fa01671a", + "sha256:c882f1d4f96fbd807e92c334251d8ebd159a1ef89059ccd386ddea83fdb91bd8", + "sha256:c8dec8a2f3f0bb462e6439df436cd8c7ec37968e90b4209ac621e7fbc0ed3b00", + "sha256:c9638e0057e3f1a8b7c5ce33c7575349d9183a033a19b5676ad55096ae36820b", + "sha256:ce4f71e17fa849de41a06109030d3f6815fcc33338bf98dd0dde6d456d33c929", + "sha256:ced12075cdf3c7332ecc1960f77f7439d5ebb8ea20bbd3c34c8299e694f1b0a1", + "sha256:d11628212fd731b8986f1561d9bb3f8c38d9c15b330c3d8a88963519fbcd553b", + "sha256:d1610260cc672975723fcf7705c69a95f3b88802a594c9867781bedd9b13422c", + "sha256:d4651de7316ec8560afe430fb042c0782ed8ac54c0be43a515944d7c78fddac8", + "sha256:da338e2728410d74ddeb1479ec67cfba73311607037455a40f92b6f5c62bf11d", + "sha256:de727ea906033b30527b4a99498f19aca3f4d1073230a958679a5b726e2784e0", + "sha256:e2e2db5c6ef376e97c912733dfc24406f5949474d03e800d5f07b6aca4d870af", + "sha256:e669913cb2179507628419ec4f0e453e48ce6f924de5884d396f18c31836089c", + "sha256:eb4a573a8499685d62545e806d8fd143c84ac8b3439f925cd92c8763f0ed9bd7", + "sha256:f146648941cadaaaf01254a75651a23c08159d009d36c5af42a7cc200a5e53ec", + "sha256:f3ff6abde52e702397949054cb5b06c1c75b5d6542f6a2ce029e46f71ffbbbf2", + "sha256:f5aa9da520e4bb8cee8189f2f541701405e7690745094ded7a37b425d60527ea", + "sha256:f5fdb00d65ec44b10cc6b9b6318ef1363b81647a4aa3270ca39565eadb2d1201", + "sha256:f685003d836ad0e5d4f08d1e024ee3ac7816eb2f873b2266306eef858f058133", + "sha256:fee86542dc4ee8229e023003e3939b4d58cc2453922cf127778b69505fc9064b" + ], + "index": "pypi", + "version": "==23.2.0" }, "requests": { "hashes": [ @@ -1137,105 +1069,104 @@ }, "scons": { "hashes": [ - "sha256:7703c4e9d2200b4854a31800c1dbd4587e1fa86e75f58795c740bcfa7eca7eaa", - "sha256:cbbd73b83cf85f1aaaf986370359de1bbfd3af97a765cb3554734f6dcec734e1" + "sha256:8c13911a2aa40552553488f7d625af4c0768fc8cdedab4a858d8ce42c8c3664d", + "sha256:d47081587e3675cc168f1f54f0d74a69b328a2fc90ec4feb85f728677419b879" ], "index": "pypi", - "version": "==4.4.0" + "version": "==4.3.0" }, "sentry-sdk": { "hashes": [ - "sha256:2d7ec7bc88ebbdf2c4b6b2650b3257893d386325a96c9b723adcd31033469b63", - "sha256:b4b41f90951ed83e7b4c176eef021b19ecba39da5b73aca106c97a9b7e279a90" + "sha256:b82ad57306d5546713f15d5d70daea0408cf7f998c7566db16e0e6257e51e561", + "sha256:ddbd191b6f4e696b7845b4d87389898ae1207981faf114f968a57363aa6be03c" ], "index": "pypi", - "version": "==1.9.5" + "version": "==1.6.0" }, "setproctitle": { "hashes": [ - "sha256:1c5d5dad7c28bdd1ec4187d818e43796f58a845aa892bb4481587010dc4d362b", - "sha256:1c8d9650154afaa86a44ff195b7b10d683c73509d085339d174e394a22cccbb9", - "sha256:1f0cde41857a644b7353a0060b5f94f7ba7cf593ebde5a1094da1be581ac9a31", - "sha256:1f29b75e86260b0ab59adb12661ef9f113d2f93a59951373eb6d68a852b13e83", - "sha256:1fa1a0fbee72b47dc339c87c890d3c03a72ea65c061ade3204f285582f2da30f", - "sha256:1ff863a20d1ff6ba2c24e22436a3daa3cd80be1dfb26891aae73f61b54b04aca", - "sha256:265ecbe2c6eafe82e104f994ddd7c811520acdd0647b73f65c24f51374cf9494", - "sha256:288943dec88e178bb2fd868adf491197cc0fc8b6810416b1c6775e686bab87fe", - "sha256:2e3ac25bfc4a0f29d2409650c7532d5ddfdbf29f16f8a256fc31c47d0dc05172", - "sha256:2fbd8187948284293f43533c150cd69a0e4192c83c377da837dbcd29f6b83084", - "sha256:4058564195b975ddc3f0462375c533cce310ccdd41b80ac9aed641c296c3eff4", - "sha256:4749a2b0c9ac52f864d13cee94546606f92b981b50e46226f7f830a56a9dc8e1", - "sha256:4d8938249a7cea45ab7e1e48b77685d0f2bab1ebfa9dde23e94ab97968996a7c", - "sha256:5194b4969f82ea842a4f6af2f82cd16ebdc3f1771fb2771796e6add9835c1973", - "sha256:55ce1e9925ce1765865442ede9dca0ba9bde10593fcd570b1f0fa25d3ec6b31c", - "sha256:589be87172b238f839e19f146b9ea47c71e413e951ef0dc6db4218ddacf3c202", - "sha256:5b932c3041aa924163f4aab970c2f0e6b4d9d773f4d50326e0ea1cd69240e5c5", - "sha256:5fb4f769c02f63fac90989711a3fee83919f47ae9afd4758ced5d86596318c65", - "sha256:630f6fe5e24a619ccf970c78e084319ee8be5be253ecc9b5b216b0f474f5ef18", - "sha256:65d884e22037b23fa25b2baf1a3316602ed5c5971eb3e9d771a38c3a69ce6e13", - "sha256:6c877691b90026670e5a70adfbcc735460a9f4c274d35ec5e8a43ce3f8443005", - "sha256:710e16fa3bade3b026907e4a5e841124983620046166f355bbb84be364bf2a02", - "sha256:7a55fe05f15c10e8c705038777656fe45e3bd676d49ad9ac8370b75c66dd7cd7", - "sha256:7aa0aac1711fadffc1d51e9d00a3bea61f68443d6ac0241a224e4d622489d665", - "sha256:7f0bed90a216ef28b9d227d8d73e28a8c9b88c0f48a082d13ab3fa83c581488f", - "sha256:7f2719a398e1a2c01c2a63bf30377a34d0b6ef61946ab9cf4d550733af8f1ef1", - "sha256:7fe9df7aeb8c64db6c34fc3b13271a363475d77bc157d3f00275a53910cb1989", - "sha256:8ff3c8cb26afaed25e8bca7b9dd0c1e36de71f35a3a0706b5c0d5172587a3827", - "sha256:9124bedd8006b0e04d4e8a71a0945da9b67e7a4ab88fdad7b1440dc5b6122c42", - "sha256:92c626edc66169a1b09e9541b9c0c9f10488447d8a2b1d87c8f0672e771bc927", - "sha256:a149a5f7f2c5a065d4e63cb0d7a4b6d3b66e6e80f12e3f8827c4f63974cbf122", - "sha256:a47d97a75fd2d10c37410b180f67a5835cb1d8fdea2648fd7f359d4277f180b9", - "sha256:a499fff50387c1520c085a07578a000123f519e5f3eee61dd68e1d301659651f", - "sha256:ab45146c71ca6592c9cc8b354a2cc9cc4843c33efcbe1d245d7d37ce9696552d", - "sha256:b2c9cb2705fc84cb8798f1ba74194f4c080aaef19d9dae843591c09b97678e98", - "sha256:b34baef93bfb20a8ecb930e395ccd2ae3268050d8cf4fe187de5e2bd806fd796", - "sha256:b617f12c9be61e8f4b2857be4a4319754756845dbbbd9c3718f468bbb1e17bcb", - "sha256:b9fb97907c830d260fa0658ed58afd48a86b2b88aac521135c352ff7fd3477fd", - "sha256:bae283e85fc084b18ffeb92e061ff7ac5af9e183c9d1345c93e178c3e5069cbe", - "sha256:c2c46200656280a064073447ebd363937562debef329482fd7e570c8d498f806", - "sha256:c8a09d570b39517de10ee5b718730e171251ce63bbb890c430c725c8c53d4484", - "sha256:c91b9bc8985d00239f7dc08a49927a7ca1ca8a6af2c3890feec3ed9665b6f91e", - "sha256:dad42e676c5261eb50fdb16bdf3e2771cf8f99a79ef69ba88729aeb3472d8575", - "sha256:de3a540cd1817ede31f530d20e6a4935bbc1b145fd8f8cf393903b1e02f1ae76", - "sha256:e00c9d5c541a2713ba0e657e0303bf96ddddc412ef4761676adc35df35d7c246", - "sha256:e1aafc91cbdacc9e5fe712c52077369168e6b6c346f3a9d51bf600b53eae56bb", - "sha256:e425be62524dc0c593985da794ee73eb8a17abb10fe692ee43bb39e201d7a099", - "sha256:e43f315c68aa61cbdef522a2272c5a5b9b8fd03c301d3167b5e1343ef50c676c", - "sha256:e49ae693306d7624015f31cb3e82708916759d592c2e5f72a35c8f4cc8aef258", - "sha256:e5c50e164cd2459bc5137c15288a9ef57160fd5cbf293265ea3c45efe7870865", - "sha256:e8579a43eafd246e285eb3a5b939e7158073d5087aacdd2308f23200eac2458b", - "sha256:e85e50b9c67854f89635a86247412f3ad66b132a4d8534ac017547197c88f27d", - "sha256:f0452282258dfcc01697026a8841258dd2057c4438b43914b611bccbcd048f10", - "sha256:f4bfc89bd33ebb8e4c0e9846a09b1f5a4a86f5cb7a317e75cc42fee1131b4f4f", - "sha256:fa2f50678f04fda7a75d0fe5dd02bbdd3b13cbe6ed4cf626e4472a7ccf47ae94", - "sha256:faec934cfe5fd6ac1151c02e67156c3f526e82f96b24d550b5d51efa4a5527c6", - "sha256:fcd3cf4286a60fdc95451d8d14e0389a6b4f5cebe02c7f2609325eb016535963", - "sha256:fe8a988c7220c002c45347430993830666e55bc350179d91fcee0feafe64e1d4", - "sha256:fed18e44711c5af4b681c2b3b18f85e6f0f1b2370a28854c645d636d5305ccd8", - "sha256:ffc61a388a5834a97953d6444a2888c24a05f2e333f9ed49f977a87bb1ad4761" - ], - "index": "pypi", - "version": "==1.3.2" + "sha256:01cef383afc7ea7a3b1696818c8712029bf2f1d64f5d4777dbaf0166becf2c00", + "sha256:0670f2130a7ca0e167d3d5a7c8e3c707340b8693d6af7416ff55c18ab2a0a43f", + "sha256:06aab65e68163ead9d046b452dd9ad1fc6834ce6bde490f63fdce3be53e9cc73", + "sha256:0a668acec8b61a971de54bc4c733869ea7b0eb1348eae5a32b9477f788908e5c", + "sha256:0b207de9e4f4aa5265b36dd826a1f6ef6566b064a042033bd7447efb7e9a7664", + "sha256:0b444ed4051161a3b0a85dec2bb9b50922f37c75f5fb86f7784b235cf6754336", + "sha256:138bfa853e607f06d95b0f253e9152b32a00af3d0dbec96abf0871236a483932", + "sha256:14641a4ec2f2110cf4afc666eaecc82ba67814e927e02647fa1f4cf74476e752", + "sha256:21d6e064b8fee4e58eb00cdd8771c638de1bc30bb6c02d0208af9ca0a1c00898", + "sha256:25538341e56f9e75e9759229ff674282dccb5b1ce79a974f968d36208d465674", + "sha256:28e0df80d5069586a08a3cb463fb23503a37cbb805826ef93164bc4bfb5f35b9", + "sha256:2c0be45535e934deab3aa72ed1a8487174af4ea12cec124478c68a312e1c8b13", + "sha256:2c8c245e08f6a296fdaa1b36894ec40e20464a4fc6458e6178c8d55a2f83457a", + "sha256:2d083cae02e344e760bd21c28d591ac5f7ddbd6e1a0ecba62092ae724abd5c28", + "sha256:32a84cc309b9e595f06a55bec2fa335a23c307a55d2989864b60ecd71ea87897", + "sha256:335750c9eb5b18326a138a09266862a52b4f474277c3e410b419bea9a1df8bee", + "sha256:35b869e416a105c59133a48b569c6e808159485d916f55e80c7394a42667a386", + "sha256:38855b06a124361dc73c198853dee3f2b775531c4f4b7472f0e3d441192b3d8a", + "sha256:3b1883ccdbee624386dc046cfbcd80c4e75e24c478f35627984a79892e088b88", + "sha256:3dbe87e76197f9a303451512088c18c96f09a6fc4f871a92e5bd695f46f94a26", + "sha256:3f55493c987935fa540ef9ffb7ee7db03b4a18a9d5cc103681e2e6a6dfbd7054", + "sha256:4051c3a3b07f8a4cca205cd45366a22f322da2f26491c0d6b313a10f8c77b734", + "sha256:409a39f92e123be061626fdfd3e76625b04db103479bb4ba1c85b587db0b9498", + "sha256:423f8a6d8116acf975ebf93d6b5c4a752f7d2039fa9aafe175a62de86e17016e", + "sha256:47f97f591ea2335b7d35f5e9ad7d806385338182dc6de5732d091e9c70ed1cc0", + "sha256:48ac48a94040ef21be37366cbc8270fcba2ca103d6c64da6099d5a7b034f72d0", + "sha256:4eed53c12146de5df959d84384ffc2774651cab406ee4854e12728cf0eee5297", + "sha256:501c084cf3df7d848e91c97d4f8c44d799ba545858a79c6960326ce6f285b4e4", + "sha256:52265182fe5ac237d179d8e949248d307882a2e6ec7f189c8dac1c9d1b3631fa", + "sha256:5464e6812d050c986e6e9b97d54ab88c23dbe9d81151a2fa10b48bb5133a1e2c", + "sha256:54c7315e53b49ef2227d47a75c3d28c4c51ea9ee46a066460732c0d0f8e605a7", + "sha256:60f7a2f5da36a3075dda7edbee2173be5b765b0460b8d401ee01a11f68dee1d2", + "sha256:65a9384cafdfed98f91416e93705ad08f049c298afcb9c515882beba23153bd0", + "sha256:71d00ef63a1f78e13c236895badac77b6c8503377467b9c1a4f81fe729d16e03", + "sha256:76f59444a25fb42ca07f53a4474b1545d97a06f016e6c6b8246eee5b146820b5", + "sha256:791bed39e4ecbdd008b64999a60c9cc560d17b3836ca0c27cd4708e8e1bcf495", + "sha256:7a72bbe53191fbe574c94c0f8b9451dce535b398b7c47ce2e26e21d55eaa1d7e", + "sha256:97accd117392b1e57e09888792750c403d7729b7e4b193005178b3736b325ea0", + "sha256:9a92978030616f5e20617b7b832efee398df82072b7239c53db41c8026f5fe55", + "sha256:9fb5d2e66f94eebc3d06cda9e71a3fffef24c5273971180a4b5628a37fae05a5", + "sha256:a39b30d7400c0d50941fe19e1fe0b7d35676186fec4d9c010129ac91b883fd26", + "sha256:a4a3cb19346a0cd680617742f5e39fdd14596f6fd91d6c9038272663e37441b4", + "sha256:a546cd2dfaecb227d24122257b98b2e062762871888835c7b608f1c41c3a77ad", + "sha256:a81067bdc015fee1cc148c79b346f24fdad1224a8898b4239c7cbdee1add8a60", + "sha256:a912df3f065572cef211e9ed9f157a0dd2bd73d150281f18f00728afa1b1e5d2", + "sha256:a993610383028f093112dce7f77b262e88fce9d70127535fcdc78953179857e8", + "sha256:b213376fc779c0e1a4b60008f3fd03f74e9baa9665db37fa6646e98d31baa6d8", + "sha256:b2fa9f4b382a6cf88f2f345044d0916a92f37cac21355585bd14bc7ee91af187", + "sha256:b9d905ac84dde5227de6516ec08639759f99684148bb88ba05f4cbdaebff5d69", + "sha256:be0b46beeb1c92450079a7f30a025d69b63fd6a5de040ebc478fd6e6bf3b63fc", + "sha256:c93a2272740e60cddf59d3e1d35dbb89fcc3676f5ca9618bb4e6ae9633fdf13c", + "sha256:ccb0b5334dbf248f7504d88b5e9e9a09a0da119eeafacd6f7247f7c055443522", + "sha256:d312a170f539895c8093b5e68ba126aa131c9f0d00f6360410db27ec50bf7afa", + "sha256:d45dbe4171f8c27a515ecb4562f4cd9ef67d98474bea18e0c14dfbdc2b225050", + "sha256:d8e4da68d4d4ba46d4c5db6ae5eb61b11de9c520f25ae8334570f4d0018a8611", + "sha256:e24fa9251cc22ddb88ef183070063fdca826c9636381f1c4fb9d2a1dccb7c2a4", + "sha256:e2ac0ebd9c63c3d19f768966be2f771bf088bc7373c63ed6fcbb3444a30d0f62", + "sha256:e40c35564081983eab6a07f9eb5693867bc447b0edf9c61b69446223d6593814", + "sha256:e80fc59739a738b5c67afbbb9d1c238aa47b6d290c2ada872b15c819350ec5f8", + "sha256:eb06c1086cf8c8cf12ce45a02450befcb408dfd646d0ccb47d388fd6e73c333a", + "sha256:eb82a49aaf440232c762539ab3737b5174d31aba0141fd4bf4d8739c28d18624", + "sha256:ec7c3a27460ae7811e868e5494e3d8aee5012912744c48fa2d80b5e614b1b972", + "sha256:ecf28b1c07a799d76f4326e508157b71aeda07b84b90368ea451c0710dbd32c0", + "sha256:efb3001fd9e71d3ae939d826bf436f0446fd30a6ac01e0ce08cd7eb55ee5ac57", + "sha256:f06ff922254023eaabef6af6631f89e5f2f420cf0112865d57d7703f933d4e9f", + "sha256:f272b84d79bbe15af26ecf6f7c129bbe642f628866c9253659cdb519216f138f", + "sha256:f2a137984d3436f13e4bf7c8ca6f6f292df119c009c5e39556cabba4f4bfbf92", + "sha256:f47f6704880869d8e8f52efac2f2f60f5ed4cb9662b98fc1c7e916eefe76e61d", + "sha256:f9cf1098205c23fbcaaaef798afaff714fa9ffadf24166f5e85e6d16b9ef82a1", + "sha256:fc586f002fd5dd8695718e22a83771fd9f744f081a2b8e614bf6b5f44135964a", + "sha256:fdb2231db176e0848b757fc5d9bed08bc8a498b5b9abb8b640f39e9720f309fc" + ], + "index": "pypi", + "version": "==1.2.3" }, "setuptools": { "hashes": [ - "sha256:2e24e0bec025f035a2e72cdd1961119f557d78ad331bb00ff82efb2ab8da8e82", - "sha256:7732871f4f7fa58fb6bdcaeadb0161b2bd046c85905dbaa066bdcbcc81953b57" + "sha256:16923d366ced322712c71ccb97164d07472abeecd13f3a6c283f6d5d26722793", + "sha256:db3b8e2f922b2a910a29804776c643ea609badb6a32c4bcc226fd4fd902cce65" ], "markers": "python_version >= '3.7'", - "version": "==65.3.0" - }, - "shiboken2": { - "hashes": [ - "sha256:63debfcc531b6a2b4985aa9b71433d2ad3bac542acffc729cc0ecaa3854390c0", - "sha256:87079c07587859a525b9800d60b1be971338ce9b371d6ead81f15ee5a46d448b", - "sha256:a0d0fdeb12b72c8af349b9642ccc67afd783dca449309f45e78cda50272fd6b7", - "sha256:eb0da44b6fa60c6bd317b8f219e500595e94e0322b33ec5b4e9f406bedaee555", - "sha256:f890f5611ab8f48b88cfecb716da2ac55aef99e2923198cefcf781842888ea65", - "sha256:ffd3d0ec3d508e592d7ee3885d27fee1f279a49989f734eb130f46d9501273a9" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '3.11'", - "version": "==5.15.2.1" + "version": "==63.1.0" }, "six": { "hashes": [ @@ -1255,19 +1186,19 @@ }, "sympy": { "hashes": [ - "sha256:1fe96b4c56bb7a7630cdf150a6cd98bc97a79e6be233e30502aba1cf54dee33d", - "sha256:b53069f5f30e4a4690b57cdb8e3d0d9065fff42627239db718214f804e442481" + "sha256:5939eeffdf9e152172601463626c022a2c27e75cf6278de8d401d50c9d58787b", + "sha256:df75d738930f6fe9ebe7034e59d56698f29e85f443f743e51e47df0caccc2130" ], "index": "pypi", - "version": "==1.11" + "version": "==1.10.1" }, "timezonefinder": { "hashes": [ - "sha256:2791ad459b85c110226057cb5ebdd6503f4fb0a33cc4f76fb93e98ed545edd68", - "sha256:406bea77a7baec5e2b1c2b4793ff8f40c174b6d8e894631e60864d956139afef" + "sha256:0471463083b5fef7a656c7e31a7376fa1941bf6a41a0750c6e0ca151e43646e7", + "sha256:2e8e958814f21fa809b16e98bd2f99082b69a0f88b864a4a1f2944d5a7e61827" ], "index": "pypi", - "version": "==6.1.1" + "version": "==6.0.1" }, "tomli": { "hashes": [ @@ -1279,11 +1210,11 @@ }, "tomlkit": { "hashes": [ - "sha256:25d4e2e446c453be6360c67ddfb88838cfc42026322770ba13d1fbd403a93a5c", - "sha256:3235a9010fae54323e727c3ac06fb720752fe6635b3426e379daec60fbd44a83" + "sha256:1c5bebdf19d5051e2e1de6cf70adfc5948d47221f097fcff7a3ffc91e953eaf5", + "sha256:61901f81ff4017951119cd0d1ed9b7af31c821d6845c8c477587bbdcd5e5854e" ], - "markers": "python_version >= '3.6' and python_version < '4.0'", - "version": "==0.11.4" + "markers": "python_version >= '3.6' and python_version < '4'", + "version": "==0.11.1" }, "tqdm": { "hashes": [ @@ -1298,16 +1229,16 @@ "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02", "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6" ], - "markers": "python_version < '3.10'", + "markers": "python_version >= '3.7'", "version": "==4.3.0" }, "urllib3": { "hashes": [ - "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e", - "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997" + "sha256:8298d6d56d39be0e3bc13c1c97d133f9b45d797169a0e11cdd0e0489d786f7ec", + "sha256:879ba4d1e89654d9769ce13121e0f94310ea32e8d2f8cf587b77c08bbcdb30d6" ], "index": "pypi", - "version": "==1.26.12" + "version": "==1.26.10" }, "utm": { "hashes": [ @@ -1318,19 +1249,19 @@ }, "websocket-client": { "hashes": [ - "sha256:33ad3cf0aef4270b95d10a5a66b670a66be1f5ccf10ce390b3644f9eddfdca9d", - "sha256:79d730c9776f4f112f33b10b78c8d209f23b5806d9a783e296b3813fc5add2f1" + "sha256:5d55652dc1d0b3c734f044337d929aaf83f4f9138816ec680c1aefefb4dc4877", + "sha256:d58c5f284d6a9bf8379dab423259fe8f85b70d5fa5d2916d5791a84594b122b1" ], "index": "pypi", - "version": "==1.4.0" + "version": "==1.3.3" }, "werkzeug": { "hashes": [ - "sha256:7ea2d48322cc7c0f8b3a215ed73eabd7b5d75d0b50e31ab006286ccff9e00b8f", - "sha256:f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5" + "sha256:1ce08e8093ed67d638d63879fd1ba3735817f7a80de3674d293f5984f25fb6e6", + "sha256:72a4b735692dd3135217911cbeaa1be5fa3f62bffb8745c5215420a03dc55255" ], "markers": "python_version >= '3.7'", - "version": "==2.2.2" + "version": "==2.1.2" }, "wrapt": { "hashes": [ @@ -1399,16 +1330,16 @@ "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015", "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af" ], - "markers": "python_version < '3.11'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==1.14.1" }, "zipp": { "hashes": [ - "sha256:05b45f1ee8f807d0cc928485ca40a07cb491cf092ff587c0df9cb1fd154848d2", - "sha256:47c40d7fe183a6f21403a199b3e4192cca5774656965b0a4988ad2f8feb5f009" + "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad", + "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099" ], "markers": "python_version >= '3.7'", - "version": "==3.8.1" + "version": "==3.8.0" } }, "develop": { @@ -1421,11 +1352,11 @@ }, "attrs": { "hashes": [ - "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6", - "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c" + "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4", + "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd" ], - "markers": "python_version >= '3.5'", - "version": "==22.1.0" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==21.4.0" }, "av": { "hashes": [ @@ -1503,21 +1434,20 @@ }, "bcrypt": { "hashes": [ - "sha256:0b0f0c7141622a31e9734b7f649451147c04ebb5122327ac0bd23744df84be90", - "sha256:1c3334446fac200499e8bc04a530ce3cf0b3d7151e0e4ac5c0dddd3d95e97843", - "sha256:2d0dd19aad87e4ab882ef1d12df505f4c52b28b69666ce83c528f42c07379227", - "sha256:594780b364fb45f2634c46ec8d3e61c1c0f1811c4f2da60e8eb15594ecbf93ed", - "sha256:7c7dd6c1f05bf89e65261d97ac3a6520f34c2acb369afb57e3ea4449be6ff8fd", - "sha256:845b1daf4df2dd94d2fdbc9454953ca9dd0e12970a0bfc9f3dcc6faea3fa96e4", - "sha256:8780e69f9deec9d60f947b169507d2c9816e4f11548f1f7ebee2af38b9b22ae4", - "sha256:bf413f2a9b0a2950fc750998899013f2e718d20fa4a58b85ca50b6df5ed1bbf9", - "sha256:bfb67f6a6c72dfb0a02f3df51550aa1862708e55128b22543e2b42c74f3620d7", - "sha256:c59c170fc9225faad04dde1ba61d85b413946e8ce2e5f5f5ff30dfd67283f319", - "sha256:dc6ec3dc19b1c193b2f7cf279d3e32e7caf447532fbcb7af0906fe4398900c33", - "sha256:ede0f506554571c8eda80db22b83c139303ec6b595b8f60c4c8157bdd0bdee36" + "sha256:2b02d6bfc6336d1094276f3f588aa1225a598e27f8e3388f4db9948cb707b521", + "sha256:433c410c2177057705da2a9f2cd01dd157493b2a7ac14c8593a16b3dab6b6bfb", + "sha256:4e029cef560967fb0cf4a802bcf4d562d3d6b4b1bf81de5ec1abbe0f1adb027e", + "sha256:61bae49580dce88095d669226d5076d0b9d927754cedbdf76c6c9f5099ad6f26", + "sha256:6d2cb9d969bfca5bc08e45864137276e4c3d3d7de2b162171def3d188bf9d34a", + "sha256:7180d98a96f00b1050e93f5b0f556e658605dd9f524d0b0e68ae7944673f525e", + "sha256:7d9ba2e41e330d2af4af6b1b6ec9e6128e91343d0b4afb9282e54e5508f31baa", + "sha256:7ff2069240c6bbe49109fe84ca80508773a904f5a8cb960e02a977f7f519b129", + "sha256:88273d806ab3a50d06bc6a2fc7c87d737dd669b76ad955f449c43095389bc8fb", + "sha256:a2c46100e315c3a5b90fdc53e429c006c5f962529bc27e1dfd656292c20ccc40", + "sha256:cd43303d6b8a165c29ec6756afd169faba9396a9472cdff753fe9f19b96ce2fa" ], "markers": "python_version >= '3.6'", - "version": "==4.0.0" + "version": "==3.2.2" }, "breathe": { "hashes": [ @@ -1629,11 +1559,11 @@ }, "charset-normalizer": { "hashes": [ - "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845", - "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f" + "sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5", + "sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413" ], "markers": "python_version >= '3.6'", - "version": "==2.1.1" + "version": "==2.1.0" }, "control": { "hashes": [ @@ -1644,59 +1574,50 @@ }, "coverage": { "hashes": [ - "sha256:01778769097dbd705a24e221f42be885c544bb91251747a8a3efdec6eb4788f2", - "sha256:08002f9251f51afdcc5e3adf5d5d66bb490ae893d9e21359b085f0e03390a820", - "sha256:1238b08f3576201ebf41f7c20bf59baa0d05da941b123c6656e42cdb668e9827", - "sha256:14a32ec68d721c3d714d9b105c7acf8e0f8a4f4734c811eda75ff3718570b5e3", - "sha256:15e38d853ee224e92ccc9a851457fb1e1f12d7a5df5ae44544ce7863691c7a0d", - "sha256:354df19fefd03b9a13132fa6643527ef7905712109d9c1c1903f2133d3a4e145", - "sha256:35ef1f8d8a7a275aa7410d2f2c60fa6443f4a64fae9be671ec0696a68525b875", - "sha256:4179502f210ebed3ccfe2f78bf8e2d59e50b297b598b100d6c6e3341053066a2", - "sha256:42c499c14efd858b98c4e03595bf914089b98400d30789511577aa44607a1b74", - "sha256:4b7101938584d67e6f45f0015b60e24a95bf8dea19836b1709a80342e01b472f", - "sha256:564cd0f5b5470094df06fab676c6d77547abfdcb09b6c29c8a97c41ad03b103c", - "sha256:5f444627b3664b80d078c05fe6a850dd711beeb90d26731f11d492dcbadb6973", - "sha256:6113e4df2fa73b80f77663445be6d567913fb3b82a86ceb64e44ae0e4b695de1", - "sha256:61b993f3998ee384935ee423c3d40894e93277f12482f6e777642a0141f55782", - "sha256:66e6df3ac4659a435677d8cd40e8eb1ac7219345d27c41145991ee9bf4b806a0", - "sha256:67f9346aeebea54e845d29b487eb38ec95f2ecf3558a3cffb26ee3f0dcc3e760", - "sha256:6913dddee2deff8ab2512639c5168c3e80b3ebb0f818fed22048ee46f735351a", - "sha256:6a864733b22d3081749450466ac80698fe39c91cb6849b2ef8752fd7482011f3", - "sha256:7026f5afe0d1a933685d8f2169d7c2d2e624f6255fb584ca99ccca8c0e966fd7", - "sha256:783bc7c4ee524039ca13b6d9b4186a67f8e63d91342c713e88c1865a38d0892a", - "sha256:7a98d6bf6d4ca5c07a600c7b4e0c5350cd483c85c736c522b786be90ea5bac4f", - "sha256:8d032bfc562a52318ae05047a6eb801ff31ccee172dc0d2504614e911d8fa83e", - "sha256:98c0b9e9b572893cdb0a00e66cf961a238f8d870d4e1dc8e679eb8bdc2eb1b86", - "sha256:9c7b9b498eb0c0d48b4c2abc0e10c2d78912203f972e0e63e3c9dc21f15abdaa", - "sha256:9cc4f107009bca5a81caef2fca843dbec4215c05e917a59dec0c8db5cff1d2aa", - "sha256:9d6e1f3185cbfd3d91ac77ea065d85d5215d3dfa45b191d14ddfcd952fa53796", - "sha256:a095aa0a996ea08b10580908e88fbaf81ecf798e923bbe64fb98d1807db3d68a", - "sha256:a3b2752de32c455f2521a51bd3ffb53c5b3ae92736afde67ce83477f5c1dd928", - "sha256:ab066f5ab67059d1f1000b5e1aa8bbd75b6ed1fc0014559aea41a9eb66fc2ce0", - "sha256:c1328d0c2f194ffda30a45f11058c02410e679456276bfa0bbe0b0ee87225fac", - "sha256:c35cca192ba700979d20ac43024a82b9b32a60da2f983bec6c0f5b84aead635c", - "sha256:cbbb0e4cd8ddcd5ef47641cfac97d8473ab6b132dd9a46bacb18872828031685", - "sha256:cdbb0d89923c80dbd435b9cf8bba0ff55585a3cdb28cbec65f376c041472c60d", - "sha256:cf2afe83a53f77aec067033199797832617890e15bed42f4a1a93ea24794ae3e", - "sha256:d5dd4b8e9cd0deb60e6fcc7b0647cbc1da6c33b9e786f9c79721fd303994832f", - "sha256:dfa0b97eb904255e2ab24166071b27408f1f69c8fbda58e9c0972804851e0558", - "sha256:e16c45b726acb780e1e6f88b286d3c10b3914ab03438f32117c4aa52d7f30d58", - "sha256:e1fabd473566fce2cf18ea41171d92814e4ef1495e04471786cbc943b89a3781", - "sha256:e3d3c4cc38b2882f9a15bafd30aec079582b819bec1b8afdbde8f7797008108a", - "sha256:e431e305a1f3126477abe9a184624a85308da8edf8486a863601d58419d26ffa", - "sha256:e7b4da9bafad21ea45a714d3ea6f3e1679099e420c8741c74905b92ee9bfa7cc", - "sha256:ee2b2fb6eb4ace35805f434e0f6409444e1466a47f620d1d5763a22600f0f892", - "sha256:ee6ae6bbcac0786807295e9687169fba80cb0617852b2fa118a99667e8e6815d", - "sha256:ef6f44409ab02e202b31a05dd6666797f9de2aa2b4b3534e9d450e42dea5e817", - "sha256:f67cf9f406cf0d2f08a3515ce2db5b82625a7257f88aad87904674def6ddaec1", - "sha256:f855b39e4f75abd0dfbcf74a82e84ae3fc260d523fcb3532786bcbbcb158322c", - "sha256:fc600f6ec19b273da1d85817eda339fb46ce9eef3e89f220055d8696e0a06908", - "sha256:fcbe3d9a53e013f8ab88734d7e517eb2cd06b7e689bedf22c0eb68db5e4a0a19", - "sha256:fde17bc42e0716c94bf19d92e4c9f5a00c5feb401f5bc01101fdf2a8b7cacf60", - "sha256:ff934ced84054b9018665ca3967fc48e1ac99e811f6cc99ea65978e1d384454b" - ], - "index": "pypi", - "version": "==6.4.4" + "sha256:01c5615d13f3dd3aa8543afc069e5319cfa0c7d712f6e04b920431e5c564a749", + "sha256:106c16dfe494de3193ec55cac9640dd039b66e196e4641fa8ac396181578b982", + "sha256:129cd05ba6f0d08a766d942a9ed4b29283aff7b2cccf5b7ce279d50796860bb3", + "sha256:145f296d00441ca703a659e8f3eb48ae39fb083baba2d7ce4482fb2723e050d9", + "sha256:1480ff858b4113db2718848d7b2d1b75bc79895a9c22e76a221b9d8d62496428", + "sha256:269eaa2c20a13a5bf17558d4dc91a8d078c4fa1872f25303dddcbba3a813085e", + "sha256:26dff09fb0d82693ba9e6231248641d60ba606150d02ed45110f9ec26404ed1c", + "sha256:2bd9a6fc18aab8d2e18f89b7ff91c0f34ff4d5e0ba0b33e989b3cd4194c81fd9", + "sha256:309ce4a522ed5fca432af4ebe0f32b21d6d7ccbb0f5fcc99290e71feba67c264", + "sha256:3384f2a3652cef289e38100f2d037956194a837221edd520a7ee5b42d00cc605", + "sha256:342d4aefd1c3e7f620a13f4fe563154d808b69cccef415415aece4c786665397", + "sha256:39ee53946bf009788108b4dd2894bf1349b4e0ca18c2016ffa7d26ce46b8f10d", + "sha256:4321f075095a096e70aff1d002030ee612b65a205a0a0f5b815280d5dc58100c", + "sha256:4803e7ccf93230accb928f3a68f00ffa80a88213af98ed338a57ad021ef06815", + "sha256:4ce1b258493cbf8aec43e9b50d89982346b98e9ffdfaae8ae5793bc112fb0068", + "sha256:664a47ce62fe4bef9e2d2c430306e1428ecea207ffd68649e3b942fa8ea83b0b", + "sha256:75ab269400706fab15981fd4bd5080c56bd5cc07c3bccb86aab5e1d5a88dc8f4", + "sha256:83c4e737f60c6936460c5be330d296dd5b48b3963f48634c53b3f7deb0f34ec4", + "sha256:84631e81dd053e8a0d4967cedab6db94345f1c36107c71698f746cb2636c63e3", + "sha256:84e65ef149028516c6d64461b95a8dbcfce95cfd5b9eb634320596173332ea84", + "sha256:865d69ae811a392f4d06bde506d531f6a28a00af36f5c8649684a9e5e4a85c83", + "sha256:87f4f3df85aa39da00fd3ec4b5abeb7407e82b68c7c5ad181308b0e2526da5d4", + "sha256:8c08da0bd238f2970230c2a0d28ff0e99961598cb2e810245d7fc5afcf1254e8", + "sha256:961e2fb0680b4f5ad63234e0bf55dfb90d302740ae9c7ed0120677a94a1590cb", + "sha256:9b3e07152b4563722be523e8cd0b209e0d1a373022cfbde395ebb6575bf6790d", + "sha256:a7f3049243783df2e6cc6deafc49ea123522b59f464831476d3d1448e30d72df", + "sha256:bf5601c33213d3cb19d17a796f8a14a9eaa5e87629a53979a5981e3e3ae166f6", + "sha256:cec3a0f75c8f1031825e19cd86ee787e87cf03e4fd2865c79c057092e69e3a3b", + "sha256:d42c549a8f41dc103a8004b9f0c433e2086add8a719da00e246e17cbe4056f72", + "sha256:d67d44996140af8b84284e5e7d398e589574b376fb4de8ccd28d82ad8e3bea13", + "sha256:d9c80df769f5ec05ad21ea34be7458d1dc51ff1fb4b2219e77fe24edf462d6df", + "sha256:e57816f8ffe46b1df8f12e1b348f06d164fd5219beba7d9433ba79608ef011cc", + "sha256:ee2ddcac99b2d2aec413e36d7a429ae9ebcadf912946b13ffa88e7d4c9b712d6", + "sha256:f02cbbf8119db68455b9d763f2f8737bb7db7e43720afa07d8eb1604e5c5ae28", + "sha256:f1d5aa2703e1dab4ae6cf416eb0095304f49d004c39e9db1d86f57924f43006b", + "sha256:f5b66caa62922531059bc5ac04f836860412f7f88d38a476eda0a6f11d4724f4", + "sha256:f69718750eaae75efe506406c490d6fc5a6161d047206cc63ce25527e8a3adad", + "sha256:fb73e0011b8793c053bfa85e53129ba5f0250fdc0392c1591fd35d915ec75c46", + "sha256:fd180ed867e289964404051a958f7cccabdeed423f91a899829264bb7974d3d3", + "sha256:fdb6f7bd51c2d1714cea40718f6149ad9be6a2ee7d93b19e9f00934c0f2a74d9", + "sha256:ffa9297c3a453fba4717d06df579af42ab9a28022444cae7fa605af4df612d54" + ], + "index": "pypi", + "version": "==6.4.1" }, "cryptography": { "hashes": [ @@ -1744,10 +1665,10 @@ }, "distlib": { "hashes": [ - "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46", - "sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e" + "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b", + "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579" ], - "version": "==0.3.6" + "version": "==0.3.4" }, "docutils": { "hashes": [ @@ -1810,52 +1731,46 @@ }, "filelock": { "hashes": [ - "sha256:55447caa666f2198c5b6b13a26d2084d26fa5b115c00d065664b2124680c4edc", - "sha256:617eb4e5eedc82fc5f47b6d61e4d11cb837c56cb4544e39081099fa17ad109d4" + "sha256:37def7b658813cda163b56fc564cdc75e86d338246458c4c28ae84cabefa2404", + "sha256:3a0fd85166ad9dbab54c9aec96737b744106dc5f15c0b09a6744a445299fcf04" ], "markers": "python_version >= '3.7'", - "version": "==3.8.0" + "version": "==3.7.1" }, "fonttools": { "hashes": [ - "sha256:4606e1a88ee1f6699d182fea9511bd9a8a915d913eab4584e5226da1180fcce7", - "sha256:fff6b752e326c15756c819fe2fe7ceab69f96a1dbcfe8911d0941cdb49905007" + "sha256:9a1c52488045cd6c6491fd07711a380f932466e317cb8e016fc4e99dc7eac2f0", + "sha256:d73f25b283cd8033367451122aa868a23de0734757a01984e4b30b18b9050c72" ], "markers": "python_version >= '3.7'", - "version": "==4.37.1" + "version": "==4.34.4" }, "ft4222": { "hashes": [ - "sha256:074f4eb234450306b9040d721eb5ab2a423d3b07d6f4a30824198afeb0a9bbb6", - "sha256:09f18a5610d0d81c568c9095798f542166b98025d119c9fa91555fa5bfddc2ee", - "sha256:0cceacb43d75a5cb3cdf2d95d4164fb2c1cfde007d9782538150bc10d7933680", - "sha256:10136015000719f68b2a4b319b612183a1601816870521e6a45c8c0b67d38325", - "sha256:1894469abffd739fc3a83f818ea29532283965c74c3c64e5c9b9e6b454971d03", - "sha256:24cdb72a7cd420c1ed009c0821555b9818b8828dc31a1a01224a35d4757c7e5d", - "sha256:286a2f3c023e9beb5c6ca6b692c3ed92a1fe44b326f7cb58807d0b99f372c7d7", - "sha256:28b472bbbb18e6f65dacd139231a53640827f2e486c54750fbcff7a16454cb6d", - "sha256:296555ca4096b5ce13e79b089622de5cf9236f3d32b074c8483ae72490e7448b", - "sha256:396f5c7c38e0c8dc1b31d5d9709d7eb86ef0ee75412867ccc352506aa3a29ae4", - "sha256:39a7d8795d32b8c126ed253a0c1a9d7971f3af83d2ceb796af47fbef03485741", - "sha256:50e37f59b8e553384cdbfab64096e3fb1c7ca9f15ae419ae0d0fdda3a2e05f54", - "sha256:511b785a23ba2fc8480dbaeda33e1f22ffe5dd58731e1c53e379989731fb42ad", - "sha256:5f91e530ee6fe6a13c08ec4dc3c7f54a704fc642b3d73f4392a9db22c5e243dd", - "sha256:65e5b7bfbe3552b771770807df0a251616bb2c8f7541e4e9f350715f225a71c0", - "sha256:6e208af13621b8a79a8c623c8deb3b971f4d4e4587156622a6558b91719f9d33", - "sha256:70aec6df75d1f8ee051c5d16a48363e4d3552feecf3466cec2700415c073e5e4", - "sha256:9670396daab3deb91847ee40c0338bca07f4041176b2aed1c49277dc1ef3497f", - "sha256:a300c2749adb674ef3d95b17a1311deaf0a3318e14ee7e9d7e56317e307b0012", - "sha256:a675b88124dfb1d2744f27823e3dfd094c0236674e453e83d486fc17358761ff", - "sha256:ab5ea9522bd0fd1b87348bf26d0a1131e87f586366271581c9b1d0acdf870173", - "sha256:baf80af3de3af376080bfb8f75f3d6aba9e9415001a6f72299cbb344e6b739cb", - "sha256:bb3cb6485d7a0d1eac0e0027eab6b9ec95e5f5722e853cdc2850d2ae70086eea", - "sha256:c5a993dd3af47ab69f5b58920dba15c98658de7a73b9c81d402fe6eaf292edab", - "sha256:c7e31cefcdcfe3653df35cd993f821b746e747b294ded8bff27d1f8bd8c5e43b", - "sha256:caec2458db0d8e29888da2c22aa4427c1d993e943ed325ef7a6b8eb24f55d163", - "sha256:d688830cf004cde39b3cc757fef8ec31ae266fceda1566ca53b3b79e5ab7b6e4" + "sha256:1489b08e4042cb2b24894495c1c8514fa115122e9f8a739f665f0e4d8c53d3f4", + "sha256:1c71913f9fb862634fb77eb6efeea38b2b839e09f739aee5864b9549bcf1c4a9", + "sha256:1f9be0961bd7f3e0c1729c9692f602244e93898610611602ce1fa16059ac5bfa", + "sha256:208cde748fc2bf4a753e217ee2844e75d7d1b6d370a8937a2055f9de8906f933", + "sha256:372be3d7d04c0f6dfa62ff66b3d4be5c39d57c258ab562d9eb0d7cdd3a90ed0f", + "sha256:3ebf9380315c6af8f9f3bc5c5c7a5ae06498349c14a7b2e65d5067b20462d21b", + "sha256:422740efac86f3fdd971bb9a94d9974e56cfe062284a2be1a85db96dd0e77e5e", + "sha256:4414ef82a6321c5205ab0e3dab2bf072f14b4dd3262e5f392560adf107210d41", + "sha256:459894dcca7db71a0d58e6f3abb4c9dd67654c92ad9d934f1e32dc08bed87645", + "sha256:4b7e4c8b5e4a8fe769127d3db99b7b410468ffe2718a07f7b317e7dc1ad9ca4f", + "sha256:68e6b357ea2287fe0e8dac287efbac2f0ce9632d65e828d422d3a0604555c174", + "sha256:800a26a4a8fc854f41e4de41e45b6deafdeb78ae5eff48818f710bb2d94a8c11", + "sha256:8790e96b4c3f8d1fb768f689f1c437a59b20889e4726ed7457ff3d188f0a3274", + "sha256:9369b55393b2e1f58f8b8516bcf9cd6fd34c05e77377c4cc48be39a49cad7be5", + "sha256:a6236f05b8948cd9c113c7159e3fdde202a0f73dce6440da078fd2fc9e411123", + "sha256:b7f58cd16213a5c92503c530b301f071d67283c80c1e8cb43d6f3ec5c186df35", + "sha256:cc368b06b92529a11add37d14196d2e2aaae19c6ffc51b9457513a0d05ceae1a", + "sha256:d479c037b417ff289727112f1d4725563b78448d3765f457c8bf6884e4d83abd", + "sha256:dce00d513be811f738954c5593c52b533a02331e8a26983280dea3f4d864962f", + "sha256:eadcbc1dd20ed6d7d07dc53354ea137bcea30fb0889d74bedcd189cdb4f61c84", + "sha256:ec984bd7e9300e5f2e50823dcd5874d54aa3e7503e69afe7eb3b4cea77071084" ], "index": "pypi", - "version": "==1.5.0" + "version": "==1.4.1" }, "hexdump": { "hashes": [ @@ -1876,11 +1791,11 @@ }, "identify": { "hashes": [ - "sha256:25851c8c1370effb22aaa3c987b30449e9ff0cece408f810ae6ce408fdd20893", - "sha256:887e7b91a1be152b0d46bbf072130235a8117392b9f1828446079a816a05ef44" + "sha256:0dca2ea3e4381c435ef9c33ba100a78a9b40c0bab11189c7cf121f75815efeaa", + "sha256:3d11b16f3fe19f52039fb7e39c9c884b21cb1b586988114fbe42671f03de3e82" ], "markers": "python_version >= '3.7'", - "version": "==2.5.3" + "version": "==2.5.1" }, "idna": { "hashes": [ @@ -1931,131 +1846,59 @@ }, "kiwisolver": { "hashes": [ - "sha256:02f79693ec433cb4b5f51694e8477ae83b3205768a6fb48ffba60549080e295b", - "sha256:03baab2d6b4a54ddbb43bba1a3a2d1627e82d205c5cf8f4c924dc49284b87166", - "sha256:1041feb4cda8708ce73bb4dcb9ce1ccf49d553bf87c3954bdfa46f0c3f77252c", - "sha256:10ee06759482c78bdb864f4109886dff7b8a56529bc1609d4f1112b93fe6423c", - "sha256:1d1573129aa0fd901076e2bfb4275a35f5b7aa60fbfb984499d661ec950320b0", - "sha256:283dffbf061a4ec60391d51e6155e372a1f7a4f5b15d59c8505339454f8989e4", - "sha256:28bc5b299f48150b5f822ce68624e445040595a4ac3d59251703779836eceff9", - "sha256:2a66fdfb34e05b705620dd567f5a03f239a088d5a3f321e7b6ac3239d22aa286", - "sha256:2e307eb9bd99801f82789b44bb45e9f541961831c7311521b13a6c85afc09767", - "sha256:2e407cb4bd5a13984a6c2c0fe1845e4e41e96f183e5e5cd4d77a857d9693494c", - "sha256:2f5e60fabb7343a836360c4f0919b8cd0d6dbf08ad2ca6b9cf90bf0c76a3c4f6", - "sha256:36dafec3d6d6088d34e2de6b85f9d8e2324eb734162fba59d2ba9ed7a2043d5b", - "sha256:3fe20f63c9ecee44560d0e7f116b3a747a5d7203376abeea292ab3152334d004", - "sha256:41dae968a94b1ef1897cb322b39360a0812661dba7c682aa45098eb8e193dbdf", - "sha256:4bd472dbe5e136f96a4b18f295d159d7f26fd399136f5b17b08c4e5f498cd494", - "sha256:4ea39b0ccc4f5d803e3337dd46bcce60b702be4d86fd0b3d7531ef10fd99a1ac", - "sha256:5853eb494c71e267912275e5586fe281444eb5e722de4e131cddf9d442615626", - "sha256:5bce61af018b0cb2055e0e72e7d65290d822d3feee430b7b8203d8a855e78766", - "sha256:6295ecd49304dcf3bfbfa45d9a081c96509e95f4b9d0eb7ee4ec0530c4a96514", - "sha256:62ac9cc684da4cf1778d07a89bf5f81b35834cb96ca523d3a7fb32509380cbf6", - "sha256:70e7c2e7b750585569564e2e5ca9845acfaa5da56ac46df68414f29fea97be9f", - "sha256:7577c1987baa3adc4b3c62c33bd1118c3ef5c8ddef36f0f2c950ae0b199e100d", - "sha256:75facbe9606748f43428fc91a43edb46c7ff68889b91fa31f53b58894503a191", - "sha256:787518a6789009c159453da4d6b683f468ef7a65bbde796bcea803ccf191058d", - "sha256:78d6601aed50c74e0ef02f4204da1816147a6d3fbdc8b3872d263338a9052c51", - "sha256:7c43e1e1206cd421cd92e6b3280d4385d41d7166b3ed577ac20444b6995a445f", - "sha256:81e38381b782cc7e1e46c4e14cd997ee6040768101aefc8fa3c24a4cc58e98f8", - "sha256:841293b17ad704d70c578f1f0013c890e219952169ce8a24ebc063eecf775454", - "sha256:872b8ca05c40d309ed13eb2e582cab0c5a05e81e987ab9c521bf05ad1d5cf5cb", - "sha256:877272cf6b4b7e94c9614f9b10140e198d2186363728ed0f701c6eee1baec1da", - "sha256:8c808594c88a025d4e322d5bb549282c93c8e1ba71b790f539567932722d7bd8", - "sha256:8ed58b8acf29798b036d347791141767ccf65eee7f26bde03a71c944449e53de", - "sha256:91672bacaa030f92fc2f43b620d7b337fd9a5af28b0d6ed3f77afc43c4a64b5a", - "sha256:968f44fdbf6dd757d12920d63b566eeb4d5b395fd2d00d29d7ef00a00582aac9", - "sha256:9f85003f5dfa867e86d53fac6f7e6f30c045673fa27b603c397753bebadc3008", - "sha256:a553dadda40fef6bfa1456dc4be49b113aa92c2a9a9e8711e955618cd69622e3", - "sha256:a68b62a02953b9841730db7797422f983935aeefceb1679f0fc85cbfbd311c32", - "sha256:abbe9fa13da955feb8202e215c4018f4bb57469b1b78c7a4c5c7b93001699938", - "sha256:ad881edc7ccb9d65b0224f4e4d05a1e85cf62d73aab798943df6d48ab0cd79a1", - "sha256:b1792d939ec70abe76f5054d3f36ed5656021dcad1322d1cc996d4e54165cef9", - "sha256:b428ef021242344340460fa4c9185d0b1f66fbdbfecc6c63eff4b7c29fad429d", - "sha256:b533558eae785e33e8c148a8d9921692a9fe5aa516efbdff8606e7d87b9d5824", - "sha256:ba59c92039ec0a66103b1d5fe588fa546373587a7d68f5c96f743c3396afc04b", - "sha256:bc8d3bd6c72b2dd9decf16ce70e20abcb3274ba01b4e1c96031e0c4067d1e7cd", - "sha256:bc9db8a3efb3e403e4ecc6cd9489ea2bac94244f80c78e27c31dcc00d2790ac2", - "sha256:bf7d9fce9bcc4752ca4a1b80aabd38f6d19009ea5cbda0e0856983cf6d0023f5", - "sha256:c2dbb44c3f7e6c4d3487b31037b1bdbf424d97687c1747ce4ff2895795c9bf69", - "sha256:c79ebe8f3676a4c6630fd3f777f3cfecf9289666c84e775a67d1d358578dc2e3", - "sha256:c97528e64cb9ebeff9701e7938653a9951922f2a38bd847787d4a8e498cc83ae", - "sha256:d0611a0a2a518464c05ddd5a3a1a0e856ccc10e67079bb17f265ad19ab3c7597", - "sha256:d06adcfa62a4431d404c31216f0f8ac97397d799cd53800e9d3efc2fbb3cf14e", - "sha256:d41997519fcba4a1e46eb4a2fe31bc12f0ff957b2b81bac28db24744f333e955", - "sha256:d5b61785a9ce44e5a4b880272baa7cf6c8f48a5180c3e81c59553ba0cb0821ca", - "sha256:da152d8cdcab0e56e4f45eb08b9aea6455845ec83172092f09b0e077ece2cf7a", - "sha256:da7e547706e69e45d95e116e6939488d62174e033b763ab1496b4c29b76fabea", - "sha256:db5283d90da4174865d520e7366801a93777201e91e79bacbac6e6927cbceede", - "sha256:db608a6757adabb32f1cfe6066e39b3706d8c3aa69bbc353a5b61edad36a5cb4", - "sha256:e0ea21f66820452a3f5d1655f8704a60d66ba1191359b96541eaf457710a5fc6", - "sha256:e7da3fec7408813a7cebc9e4ec55afed2d0fd65c4754bc376bf03498d4e92686", - "sha256:e92a513161077b53447160b9bd8f522edfbed4bd9759e4c18ab05d7ef7e49408", - "sha256:ecb1fa0db7bf4cff9dac752abb19505a233c7f16684c5826d1f11ebd9472b871", - "sha256:efda5fc8cc1c61e4f639b8067d118e742b812c930f708e6667a5ce0d13499e29", - "sha256:f0a1dbdb5ecbef0d34eb77e56fcb3e95bbd7e50835d9782a45df81cc46949750", - "sha256:f0a71d85ecdd570ded8ac3d1c0f480842f49a40beb423bb8014539a9f32a5897", - "sha256:f4f270de01dd3e129a72efad823da90cc4d6aafb64c410c9033aba70db9f1ff0", - "sha256:f6cb459eea32a4e2cf18ba5fcece2dbdf496384413bc1bae15583f19e567f3b2", - "sha256:f8ad8285b01b0d4695102546b342b493b3ccc6781fc28c8c6a1bb63e95d22f09", - "sha256:f9f39e2f049db33a908319cf46624a569b36983c7c78318e9726a4cb8923b26c" + "sha256:007799c7fa934646318fc128b033bb6e6baabe7fbad521bfb2279aac26225cd7", + "sha256:130c6c35eded399d3967cf8a542c20b671f5ba85bd6f210f8b939f868360e9eb", + "sha256:1858ad3cb686eccc7c6b7c5eac846a1cfd45aacb5811b2cf575e80b208f5622a", + "sha256:1ae7aa0784aeadfbd693c27993727792fbe1455b84d49970bad5886b42976b18", + "sha256:1d2c744aeedce22c122bb42d176b4aa6d063202a05a4abdacb3e413c214b3694", + "sha256:21a3a98f0a21fc602663ca9bce2b12a4114891bdeba2dea1e9ad84db59892fca", + "sha256:22ccba48abae827a0f952a78a7b1a7ff01866131e5bbe1f826ce9bda406bf051", + "sha256:26b5a70bdab09e6a2f40babc4f8f992e3771751e144bda1938084c70d3001c09", + "sha256:2d76780d9c65c7529cedd49fa4802d713e60798d8dc3b0d5b12a0a8f38cca51c", + "sha256:325fa1b15098e44fe4590a6c5c09a212ca10c6ebb5d96f7447d675f6c8340e4e", + "sha256:3a297d77b3d6979693f5948df02b89431ae3645ec95865e351fb45578031bdae", + "sha256:3b1dcbc49923ac3c973184a82832e1f018dec643b1e054867d04a3a22255ec6a", + "sha256:40240da438c0ebfe2aa76dd04b844effac6679423df61adbe3437d32f23468d9", + "sha256:46c6e5018ba31d5ee7582f323d8661498a154dea1117486a571db4c244531f24", + "sha256:46fb56fde006b7ef5f8eaa3698299b0ea47444238b869ff3ced1426aa9fedcb5", + "sha256:4dc350cb65fe4e3f737d50f0465fa6ea0dcae0e5722b7edf5d5b0a0e3cd2c3c7", + "sha256:51078855a16b7a4984ed2067b54e35803d18bca9861cb60c60f6234b50869a56", + "sha256:547111ef7cf13d73546c2de97ce434935626c897bdec96a578ca100b5fcd694b", + "sha256:5fb73cc8a34baba1dfa546ae83b9c248ef6150c238b06fc53d2773685b67ec67", + "sha256:654280c5f41831ddcc5a331c0e3ce2e480bbc3d7c93c18ecf6236313aae2d61a", + "sha256:6b3136eecf7e1b4a4d23e4b19d6c4e7a8e0b42d55f30444e3c529700cdacaa0d", + "sha256:7118ca592d25b2957ff7b662bc0fe4f4c2b5d5b27814b9b1bc9f2fb249a970e7", + "sha256:71af5b43e4fa286a35110fc5bb740fdeae2b36ca79fbcf0a54237485baeee8be", + "sha256:747190fcdadc377263223f8f72b038381b3b549a8a3df5baf4d067da4749b046", + "sha256:8395064d63b26947fa2c9faeea9c3eee35e52148c5339c37987e1d96fbf009b3", + "sha256:84f85adfebd7d3c3db649efdf73659e1677a2cf3fa6e2556a3f373578af14bf7", + "sha256:86bcf0009f2012847a688f2f4f9b16203ca4c835979a02549aa0595d9f457cc8", + "sha256:ab8a15c2750ae8d53e31f77a94f846d0a00772240f1c12817411fa2344351f86", + "sha256:af24b21c2283ca69c416a8a42cde9764dc36c63d3389645d28c69b0e93db3cd7", + "sha256:afe173ac2646c2636305ab820cc0380b22a00a7bca4290452e7166b4f4fa49d0", + "sha256:b9eb88593159a53a5ee0b0159daee531ff7dd9c87fa78f5d807ca059c7eb1b2b", + "sha256:c16635f8dddbeb1b827977d0b00d07b644b040aeb9ff8607a9fc0997afa3e567", + "sha256:ca3eefb02ef17257fae8b8555c85e7c1efdfd777f671384b0e4ef27409b02720", + "sha256:caa59e2cae0e23b1e225447d7a9ddb0f982f42a6a22d497a484dfe62a06f7c0e", + "sha256:cb55258931448d61e2d50187de4ee66fc9d9f34908b524949b8b2b93d0c57136", + "sha256:d248c46c0aa406695bda2abf99632db991f8b3a6d46018721a2892312a99f069", + "sha256:d2578e5149ff49878934debfacf5c743fab49eca5ecdb983d0b218e1e554c498", + "sha256:dd22085446f3eca990d12a0878eeb5199dc9553b2e71716bfe7bed9915a472ab", + "sha256:e7cf940af5fee00a92e281eb157abe8770227a5255207818ea9a34e54a29f5b2", + "sha256:f70f3d028794e31cf9d1a822914efc935aadb2438ec4e8d4871d95eb1ce032d6", + "sha256:fd2842a0faed9ab9aba0922c951906132d9384be89690570f0ed18cd4f20e658", + "sha256:fd628e63ffdba0112e3ddf1b1e9f3db29dd8262345138e08f4938acbc6d0805a", + "sha256:ffd7cf165ff71afb202b3f36daafbf298932bee325aac9f58e1c9cd55838bef0" ], "markers": "python_version >= '3.7'", - "version": "==1.4.4" + "version": "==1.4.3" }, "lru-dict": { "hashes": [ - "sha256:075b9dd46d7022b675419bc6e3631748ae184bc8af195d20365a98b4f3bb2914", - "sha256:0972d669e9e207617e06416166718b073a49bf449abbd23940d9545c0847a4d9", - "sha256:0f83cd70a6d32f9018d471be609f3af73058f700691657db4a3d3dd78d3f96dd", - "sha256:10fe823ff90b655f0b6ba124e2b576ecda8c61b8ead76b456db67831942d22f2", - "sha256:163079dbda54c3e6422b23da39fb3ecc561035d65e8496ff1950cbdb376018e1", - "sha256:1fe16ade5fd0a57e9a335f69b8055aaa6fb278fbfa250458e4f6b8255115578f", - "sha256:262a4e622010ceb960a6a5222ed011090e50954d45070fd369c0fa4d2ed7d9a9", - "sha256:2f340b61f3cdfee71f66da7dbfd9a5ea2db6974502ccff2065cdb76619840dca", - "sha256:348167f110494cfafae70c066470a6f4e4d43523933edf16ccdb8947f3b5fae0", - "sha256:3b1692755fef288b67af5cd8a973eb331d1f44cb02cbdc13660040809c2bfec6", - "sha256:3ca497cb25f19f24171f9172805f3ff135b911aeb91960bd4af8e230421ccb51", - "sha256:3d003a864899c29b0379e412709a6e516cbd6a72ee10b09d0b33226343617412", - "sha256:3fef595c4f573141d54a38bda9221b9ee3cbe0acc73d67304a1a6d5972eb2a02", - "sha256:484ac524e4615f06dc72ffbfd83f26e073c9ec256de5413634fbd024c010a8bc", - "sha256:55aeda6b6789b2d030066b4f5f6fc3596560ba2a69028f35f3682a795701b5b1", - "sha256:5a592363c93d6fc6472d5affe2819e1c7590746aecb464774a4f67e09fbefdfc", - "sha256:5b09dbe47bc4b4d45ffe56067aff190bc3c0049575da6e52127e114236e0a6a7", - "sha256:6e2a7aa9e36626fb48fdc341c7e3685a31a7b50ea4918677ea436271ad0d904d", - "sha256:70364e3cbef536adab8762b4835e18f5ca8e3fddd8bd0ec9258c42bbebd0ee77", - "sha256:720f5728e537f11a311e8b720793a224e985d20e6b7c3d34a891a391865af1a2", - "sha256:7284bdbc5579bbdc3fc8f869ed4c169f403835566ab0f84567cdbfdd05241847", - "sha256:7be1b66926277993cecdc174c15a20c8ce785c1f8b39aa560714a513eef06473", - "sha256:86d32a4498b74a75340497890a260d37bf1560ad2683969393032977dd36b088", - "sha256:878bc8ef4073e5cfb953dfc1cf4585db41e8b814c0106abde34d00ee0d0b3115", - "sha256:881104711900af45967c2e5ce3e62291dd57d5b2a224d58b7c9f60bf4ad41b8c", - "sha256:8c50ab9edaa5da5838426816a2b7bcde9d576b4fc50e6a8c062073dbc4969d78", - "sha256:8f6561f9cd5a452cb84905c6a87aa944fdfdc0f41cc057d03b71f9b29b2cc4bd", - "sha256:93336911544ebc0e466272043adab9fb9f6e9dcba6024b639c32553a3790e089", - "sha256:9447214e4857e16d14158794ef01e4501d8fad07d298d03308d9f90512df02fa", - "sha256:97c24ffc55de6013075979f440acd174e88819f30387074639fb7d7178ca253e", - "sha256:99f6cfb3e28490357a0805b409caf693e46c61f8dbb789c51355adb693c568d3", - "sha256:9be6c4039ef328676b868acea619cd100e3de1a35b3be211cf0eaf9775563b65", - "sha256:9d70257246b8207e8ef3d8b18457089f5ff0dfb087bd36eb33bce6584f2e0b3a", - "sha256:a777d48319d293b1b6a933d606c0e4899690a139b4c81173451913bbcab6f44f", - "sha256:add762163f4af7f4173fafa4092eb7c7f023cf139ef6d2015cfea867e1440d82", - "sha256:b6f64005ede008b7a866be8f3f6274dbf74e656e15e4004e9d99ad65efb01809", - "sha256:beb089c46bd95243d1ac5b2bd13627317b08bf40dd8dc16d4b7ee7ecb3cf65ca", - "sha256:c07163c9dcbb2eca377f366b1331f46302fd8b6b72ab4d603087feca00044bb0", - "sha256:c2fe692332c2f1d81fd27457db4b35143801475bfc2e57173a2403588dd82a42", - "sha256:ca8f89361e0e7aad0bf93ae03a31502e96280faeb7fb92267f4998fb230d36b2", - "sha256:d2ed4151445c3f30423c2698f72197d64b27b1cd61d8d56702ffe235584e47c2", - "sha256:db20597c4e67b4095b376ce2e83930c560f4ce481e8d05737885307ed02ba7c1", - "sha256:de972c7f4bc7b6002acff2a8de984c55fbd7f2289dba659cfd90f7a0f5d8f5d1", - "sha256:f1df1da204a9f0b5eb8393a46070f1d984fa8559435ee790d7f8f5602038fc00", - "sha256:f4d0a6d733a23865019b1c97ed6fb1fdb739be923192abf4dbb644f697a26a69", - "sha256:f874e9c2209dada1a080545331aa1277ec060a13f61684a8642788bf44b2325f", - "sha256:f877f53249c3e49bbd7612f9083127290bede6c7d6501513567ab1bf9c581381", - "sha256:f9d5815c0e85922cd0fb8344ca8b1c7cf020bf9fc45e670d34d51932c91fd7ec" - ], - "index": "pypi", - "version": "==1.1.8" + "sha256:45b81f67d75341d4433abade799a47e9c42a9e22a118531dcb5e549864032d7c" + ], + "index": "pypi", + "version": "==1.1.7" }, "markdown-it-py": { "hashes": [ @@ -2113,44 +1956,44 @@ }, "matplotlib": { "hashes": [ - "sha256:0bcdfcb0f976e1bac6721d7d457c17be23cf7501f977b6a38f9d38a3762841f7", - "sha256:1e64ac9be9da6bfff0a732e62116484b93b02a0b4d4b19934fb4f8e7ad26ad6a", - "sha256:22227c976ad4dc8c5a5057540421f0d8708c6560744ad2ad638d48e2984e1dbc", - "sha256:2886cc009f40e2984c083687251821f305d811d38e3df8ded414265e4583f0c5", - "sha256:2e6d184ebe291b9e8f7e78bbab7987d269c38ea3e062eace1fe7d898042ef804", - "sha256:3211ba82b9f1518d346f6309df137b50c3dc4421b4ed4815d1d7eadc617f45a1", - "sha256:339cac48b80ddbc8bfd05daae0a3a73414651a8596904c2a881cfd1edb65f26c", - "sha256:35a8ad4dddebd51f94c5d24bec689ec0ec66173bf614374a1244c6241c1595e0", - "sha256:3b4fa56159dc3c7f9250df88f653f085068bcd32dcd38e479bba58909254af7f", - "sha256:43e9d3fa077bf0cc95ded13d331d2156f9973dce17c6f0c8b49ccd57af94dbd9", - "sha256:57f1b4e69f438a99bb64d7f2c340db1b096b41ebaa515cf61ea72624279220ce", - "sha256:5c096363b206a3caf43773abebdbb5a23ea13faef71d701b21a9c27fdcef72f4", - "sha256:6bb93a0492d68461bd458eba878f52fdc8ac7bdb6c4acdfe43dba684787838c2", - "sha256:6ea6aef5c4338e58d8d376068e28f80a24f54e69f09479d1c90b7172bad9f25b", - "sha256:6fe807e8a22620b4cd95cfbc795ba310dc80151d43b037257250faf0bfcd82bc", - "sha256:73dd93dc35c85dece610cca8358003bf0760d7986f70b223e2306b4ea6d1406b", - "sha256:839d47b8ead7ad9669aaacdbc03f29656dc21f0d41a6fea2d473d856c39c8b1c", - "sha256:874df7505ba820e0400e7091199decf3ff1fde0583652120c50cd60d5820ca9a", - "sha256:879c7e5fce4939c6aa04581dfe08d57eb6102a71f2e202e3314d5fbc072fd5a0", - "sha256:94ff86af56a3869a4ae26a9637a849effd7643858a1a04dd5ee50e9ab75069a7", - "sha256:99482b83ebf4eb6d5fc6813d7aacdefdd480f0d9c0b52dcf9f1cc3b2c4b3361a", - "sha256:9ab29589cef03bc88acfa3a1490359000c18186fc30374d8aa77d33cc4a51a4a", - "sha256:9befa5954cdbc085e37d974ff6053da269474177921dd61facdad8023c4aeb51", - "sha256:a206a1b762b39398efea838f528b3a6d60cdb26fe9d58b48265787e29cd1d693", - "sha256:ab8d26f07fe64f6f6736d635cce7bfd7f625320490ed5bfc347f2cdb4fae0e56", - "sha256:b28de401d928890187c589036857a270a032961411934bdac4cf12dde3d43094", - "sha256:b428076a55fb1c084c76cb93e68006f27d247169f056412607c5c88828d08f88", - "sha256:bf618a825deb6205f015df6dfe6167a5d9b351203b03fab82043ae1d30f16511", - "sha256:c995f7d9568f18b5db131ab124c64e51b6820a92d10246d4f2b3f3a66698a15b", - "sha256:cd45a6f3e93a780185f70f05cf2a383daed13c3489233faad83e81720f7ede24", - "sha256:d2484b350bf3d32cae43f85dcfc89b3ed7bd2bcd781ef351f93eb6fb2cc483f9", - "sha256:d62880e1f60e5a30a2a8484432bcb3a5056969dc97258d7326ad465feb7ae069", - "sha256:dacddf5bfcec60e3f26ec5c0ae3d0274853a258b6c3fc5ef2f06a8eb23e042be", - "sha256:f3840c280ebc87a48488a46f760ea1c0c0c83fcf7abbe2e6baf99d033fd35fd8", - "sha256:f814504e459c68118bf2246a530ed953ebd18213dc20e3da524174d84ed010b2" - ], - "index": "pypi", - "version": "==3.5.3" + "sha256:03bbb3f5f78836855e127b5dab228d99551ad0642918ccbf3067fcd52ac7ac5e", + "sha256:24173c23d1bcbaed5bf47b8785d27933a1ac26a5d772200a0f3e0e38f471b001", + "sha256:2a0967d4156adbd0d46db06bc1a877f0370bce28d10206a5071f9ecd6dc60b79", + "sha256:2e8bda1088b941ead50caabd682601bece983cadb2283cafff56e8fcddbf7d7f", + "sha256:31fbc2af27ebb820763f077ec7adc79b5a031c2f3f7af446bd7909674cd59460", + "sha256:364e6bca34edc10a96aa3b1d7cd76eb2eea19a4097198c1b19e89bee47ed5781", + "sha256:3d8e129af95b156b41cb3be0d9a7512cc6d73e2b2109f82108f566dbabdbf377", + "sha256:44c6436868186564450df8fd2fc20ed9daaef5caad699aa04069e87099f9b5a8", + "sha256:48cf850ce14fa18067f2d9e0d646763681948487a8080ec0af2686468b4607a2", + "sha256:49a5938ed6ef9dda560f26ea930a2baae11ea99e1c2080c8714341ecfda72a89", + "sha256:4a05f2b37222319753a5d43c0a4fd97ed4ff15ab502113e3f2625c26728040cf", + "sha256:4a44cdfdb9d1b2f18b1e7d315eb3843abb097869cd1ef89cfce6a488cd1b5182", + "sha256:4fa28ca76ac5c2b2d54bc058b3dad8e22ee85d26d1ee1b116a6fd4d2277b6a04", + "sha256:5844cea45d804174bf0fac219b4ab50774e504bef477fc10f8f730ce2d623441", + "sha256:5a32ea6e12e80dedaca2d4795d9ed40f97bfa56e6011e14f31502fdd528b9c89", + "sha256:6c623b355d605a81c661546af7f24414165a8a2022cddbe7380a31a4170fa2e9", + "sha256:751d3815b555dcd6187ad35b21736dc12ce6925fc3fa363bbc6dc0f86f16484f", + "sha256:75c406c527a3aa07638689586343f4b344fcc7ab1f79c396699eb550cd2b91f7", + "sha256:77157be0fc4469cbfb901270c205e7d8adb3607af23cef8bd11419600647ceed", + "sha256:7d7705022df2c42bb02937a2a824f4ec3cca915700dd80dc23916af47ff05f1a", + "sha256:7f409716119fa39b03da3d9602bd9b41142fab7a0568758cd136cd80b1bf36c8", + "sha256:9480842d5aadb6e754f0b8f4ebeb73065ac8be1855baa93cd082e46e770591e9", + "sha256:9776e1a10636ee5f06ca8efe0122c6de57ffe7e8c843e0fb6e001e9d9256ec95", + "sha256:a91426ae910819383d337ba0dc7971c7cefdaa38599868476d94389a329e599b", + "sha256:b4fedaa5a9aa9ce14001541812849ed1713112651295fdddd640ea6620e6cf98", + "sha256:b6c63cd01cad0ea8704f1fd586e9dc5777ccedcd42f63cbbaa3eae8dd41172a1", + "sha256:b8d3f4e71e26307e8c120b72c16671d70c5cd08ae412355c11254aa8254fb87f", + "sha256:c4b82c2ae6d305fcbeb0eb9c93df2602ebd2f174f6e8c8a5d92f9445baa0c1d3", + "sha256:c772264631e5ae61f0bd41313bbe48e1b9bcc95b974033e1118c9caa1a84d5c6", + "sha256:c87973ddec10812bddc6c286b88fdd654a666080fbe846a1f7a3b4ba7b11ab78", + "sha256:e2b696699386766ef171a259d72b203a3c75d99d03ec383b97fc2054f52e15cf", + "sha256:ea75df8e567743207e2b479ba3d8843537be1c146d4b1e3e395319a4e1a77fe9", + "sha256:ebc27ad11df3c1661f4677a7762e57a8a91dd41b466c3605e90717c9a5f90c82", + "sha256:ee0b8e586ac07f83bb2950717e66cb305e2859baf6f00a9c39cc576e0ce9629c", + "sha256:ee175a571e692fc8ae8e41ac353c0e07259113f4cb063b0ec769eff9717e84bb" + ], + "index": "pypi", + "version": "==3.5.2" }, "mdit-py-plugins": { "hashes": [ @@ -2162,11 +2005,11 @@ }, "mdurl": { "hashes": [ - "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", - "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba" + "sha256:6a8f6804087b7128040b2fb2ebe242bdc2affaeaa034d5fc9feeed30b443651b", + "sha256:f79c9709944df218a4cdb0fcc0b0c7ead2f44594e3e84dc566606f04ad749c20" ], "markers": "python_version >= '3.7'", - "version": "==0.1.2" + "version": "==0.1.1" }, "mpld3": { "hashes": [ @@ -2178,32 +2021,32 @@ }, "mypy": { "hashes": [ - "sha256:02ef476f6dcb86e6f502ae39a16b93285fef97e7f1ff22932b657d1ef1f28655", - "sha256:0d054ef16b071149917085f51f89555a576e2618d5d9dd70bd6eea6410af3ac9", - "sha256:19830b7dba7d5356d3e26e2427a2ec91c994cd92d983142cbd025ebe81d69cf3", - "sha256:1f7656b69974a6933e987ee8ffb951d836272d6c0f81d727f1d0e2696074d9e6", - "sha256:23488a14a83bca6e54402c2e6435467a4138785df93ec85aeff64c6170077fb0", - "sha256:23c7ff43fff4b0df93a186581885c8512bc50fc4d4910e0f838e35d6bb6b5e58", - "sha256:25c5750ba5609a0c7550b73a33deb314ecfb559c350bb050b655505e8aed4103", - "sha256:2ad53cf9c3adc43cf3bea0a7d01a2f2e86db9fe7596dfecb4496a5dda63cbb09", - "sha256:3fa7a477b9900be9b7dd4bab30a12759e5abe9586574ceb944bc29cddf8f0417", - "sha256:40b0f21484238269ae6a57200c807d80debc6459d444c0489a102d7c6a75fa56", - "sha256:4b21e5b1a70dfb972490035128f305c39bc4bc253f34e96a4adf9127cf943eb2", - "sha256:5a361d92635ad4ada1b1b2d3630fc2f53f2127d51cf2def9db83cba32e47c856", - "sha256:77a514ea15d3007d33a9e2157b0ba9c267496acf12a7f2b9b9f8446337aac5b0", - "sha256:855048b6feb6dfe09d3353466004490b1872887150c5bb5caad7838b57328cc8", - "sha256:9796a2ba7b4b538649caa5cecd398d873f4022ed2333ffde58eaf604c4d2cb27", - "sha256:98e02d56ebe93981c41211c05adb630d1d26c14195d04d95e49cd97dbc046dc5", - "sha256:b793b899f7cf563b1e7044a5c97361196b938e92f0a4343a5d27966a53d2ec71", - "sha256:d1ea5d12c8e2d266b5fb8c7a5d2e9c0219fedfeb493b7ed60cd350322384ac27", - "sha256:d2022bfadb7a5c2ef410d6a7c9763188afdb7f3533f22a0a32be10d571ee4bbe", - "sha256:d3348e7eb2eea2472db611486846742d5d52d1290576de99d59edeb7cd4a42ca", - "sha256:d744f72eb39f69312bc6c2abf8ff6656973120e2eb3f3ec4f758ed47e414a4bf", - "sha256:ef943c72a786b0f8d90fd76e9b39ce81fb7171172daf84bf43eaf937e9f220a9", - "sha256:f2899a3cbd394da157194f913a931edfd4be5f274a88041c9dc2d9cdcb1c315c" - ], - "index": "pypi", - "version": "==0.971" + "sha256:006be38474216b833eca29ff6b73e143386f352e10e9c2fbe76aa8549e5554f5", + "sha256:03c6cc893e7563e7b2949b969e63f02c000b32502a1b4d1314cabe391aa87d66", + "sha256:0e9f70df36405c25cc530a86eeda1e0867863d9471fe76d1273c783df3d35c2e", + "sha256:1ece702f29270ec6af25db8cf6185c04c02311c6bb21a69f423d40e527b75c56", + "sha256:3e09f1f983a71d0672bbc97ae33ee3709d10c779beb613febc36805a6e28bb4e", + "sha256:439c726a3b3da7ca84a0199a8ab444cd8896d95012c4a6c4a0d808e3147abf5d", + "sha256:5a0b53747f713f490affdceef835d8f0cb7285187a6a44c33821b6d1f46ed813", + "sha256:5f1332964963d4832a94bebc10f13d3279be3ce8f6c64da563d6ee6e2eeda932", + "sha256:63e85a03770ebf403291ec50097954cc5caf2a9205c888ce3a61bd3f82e17569", + "sha256:64759a273d590040a592e0f4186539858c948302c653c2eac840c7a3cd29e51b", + "sha256:697540876638ce349b01b6786bc6094ccdaba88af446a9abb967293ce6eaa2b0", + "sha256:9940e6916ed9371809b35b2154baf1f684acba935cd09928952310fbddaba648", + "sha256:9f5f5a74085d9a81a1f9c78081d60a0040c3efb3f28e5c9912b900adf59a16e6", + "sha256:a5ea0875a049de1b63b972456542f04643daf320d27dc592d7c3d9cd5d9bf950", + "sha256:b117650592e1782819829605a193360a08aa99f1fc23d1d71e1a75a142dc7e15", + "sha256:b24be97351084b11582fef18d79004b3e4db572219deee0212078f7cf6352723", + "sha256:b88f784e9e35dcaa075519096dc947a388319cb86811b6af621e3523980f1c8a", + "sha256:bdd5ca340beffb8c44cb9dc26697628d1b88c6bddf5c2f6eb308c46f269bb6f3", + "sha256:d5aaf1edaa7692490f72bdb9fbd941fbf2e201713523bdb3f4038be0af8846c6", + "sha256:e999229b9f3198c0c880d5e269f9f8129c8862451ce53a011326cad38b9ccd24", + "sha256:f4a21d01fc0ba4e31d82f0fff195682e29f9401a8bdb7173891070eb260aeb3b", + "sha256:f4b794db44168a4fc886e3450201365c9526a522c46ba089b55e1f11c163750d", + "sha256:f730d56cb924d371c26b8eaddeea3cc07d78ff51c521c6d04899ac6904b75492" + ], + "index": "pypi", + "version": "==0.961" }, "mypy-extensions": { "hashes": [ @@ -2238,37 +2081,31 @@ }, "numpy": { "hashes": [ - "sha256:17e5226674f6ea79e14e3b91bfbc153fdf3ac13f5cc54ee7bc8fdbe820a32da0", - "sha256:2bd879d3ca4b6f39b7770829f73278b7c5e248c91d538aab1e506c628353e47f", - "sha256:4f41f5bf20d9a521f8cab3a34557cd77b6f205ab2116651f12959714494268b0", - "sha256:5593f67e66dea4e237f5af998d31a43e447786b2154ba1ad833676c788f37cde", - "sha256:5e28cd64624dc2354a349152599e55308eb6ca95a13ce6a7d5679ebff2962913", - "sha256:633679a472934b1c20a12ed0c9a6c9eb167fbb4cb89031939bfd03dd9dbc62b8", - "sha256:806970e69106556d1dd200e26647e9bee5e2b3f1814f9da104a943e8d548ca38", - "sha256:806cc25d5c43e240db709875e947076b2826f47c2c340a5a2f36da5bb10c58d6", - "sha256:8247f01c4721479e482cc2f9f7d973f3f47810cbc8c65e38fd1bbd3141cc9842", - "sha256:8ebf7e194b89bc66b78475bd3624d92980fca4e5bb86dda08d677d786fefc414", - "sha256:8ecb818231afe5f0f568c81f12ce50f2b828ff2b27487520d85eb44c71313b9e", - "sha256:8f9d84a24889ebb4c641a9b99e54adb8cab50972f0166a3abc14c3b93163f074", - "sha256:909c56c4d4341ec8315291a105169d8aae732cfb4c250fbc375a1efb7a844f8f", - "sha256:9b83d48e464f393d46e8dd8171687394d39bc5abfe2978896b77dc2604e8635d", - "sha256:ac987b35df8c2a2eab495ee206658117e9ce867acf3ccb376a19e83070e69418", - "sha256:b78d00e48261fbbd04aa0d7427cf78d18401ee0abd89c7559bbf422e5b1c7d01", - "sha256:b8b97a8a87cadcd3f94659b4ef6ec056261fa1e1c3317f4193ac231d4df70215", - "sha256:bd5b7ccae24e3d8501ee5563e82febc1771e73bd268eef82a1e8d2b4d556ae66", - "sha256:bdc02c0235b261925102b1bd586579b7158e9d0d07ecb61148a1799214a4afd5", - "sha256:be6b350dfbc7f708d9d853663772a9310783ea58f6035eec649fb9c4371b5389", - "sha256:c403c81bb8ffb1c993d0165a11493fd4bf1353d258f6997b3ee288b0a48fce77", - "sha256:cf8c6aed12a935abf2e290860af8e77b26a042eb7f2582ff83dc7ed5f963340c", - "sha256:d98addfd3c8728ee8b2c49126f3c44c703e2b005d4a95998e2167af176a9e722", - "sha256:dc76bca1ca98f4b122114435f83f1fcf3c0fe48e4e6f660e07996abf2f53903c", - "sha256:dec198619b7dbd6db58603cd256e092bcadef22a796f778bf87f8592b468441d", - "sha256:df28dda02c9328e122661f399f7655cdcbcf22ea42daa3650a26bce08a187450", - "sha256:e603ca1fb47b913942f3e660a15e55a9ebca906857edfea476ae5f0fe9b457d5", - "sha256:ecfdd68d334a6b97472ed032b5b37a30d8217c097acfff15e8452c710e775524" - ], - "index": "pypi", - "version": "==1.23.2" + "sha256:092f5e6025813e64ad6d1b52b519165d08c730d099c114a9247c9bb635a2a450", + "sha256:196cd074c3f97c4121601790955f915187736f9cf458d3ee1f1b46aff2b1ade0", + "sha256:1c29b44905af288b3919803aceb6ec7fec77406d8b08aaa2e8b9e63d0fe2f160", + "sha256:2b2da66582f3a69c8ce25ed7921dcd8010d05e59ac8d89d126a299be60421171", + "sha256:5043bcd71fcc458dfb8a0fc5509bbc979da0131b9d08e3d5f50fb0bbb36f169a", + "sha256:58bfd40eb478f54ff7a5710dd61c8097e169bc36cc68333d00a9bcd8def53b38", + "sha256:79a506cacf2be3a74ead5467aee97b81fca00c9c4c8b3ba16dbab488cd99ba10", + "sha256:94b170b4fa0168cd6be4becf37cb5b127bd12a795123984385b8cd4aca9857e5", + "sha256:97a76604d9b0e79f59baeca16593c711fddb44936e40310f78bfef79ee9a835f", + "sha256:98e8e0d8d69ff4d3fa63e6c61e8cfe2d03c29b16b58dbef1f9baa175bbed7860", + "sha256:ac86f407873b952679f5f9e6c0612687e51547af0e14ddea1eedfcb22466babd", + "sha256:ae8adff4172692ce56233db04b7ce5792186f179c415c37d539c25de7298d25d", + "sha256:bd3fa4fe2e38533d5336e1272fc4e765cabbbde144309ccee8675509d5cd7b05", + "sha256:d0d2094e8f4d760500394d77b383a1b06d3663e8892cdf5df3c592f55f3bff66", + "sha256:d54b3b828d618a19779a84c3ad952e96e2c2311b16384e973e671aa5be1f6187", + "sha256:d6ca8dabe696c2785d0c8c9b0d8a9b6e5fdbe4f922bde70d57fa1a2848134f95", + "sha256:d8cc87bed09de55477dba9da370c1679bd534df9baa171dd01accbb09687dac3", + "sha256:f0f18804df7370571fb65db9b98bf1378172bd4e962482b857e612d1fec0f53e", + "sha256:f1d88ef79e0a7fa631bb2c3dda1ea46b32b1fe614e10fedd611d3d5398447f2f", + "sha256:f9c3fc2adf67762c9fe1849c859942d23f8d3e0bee7b5ed3d4a9c3eeb50a2f07", + "sha256:fc431493df245f3c627c0c05c2bd134535e7929dbe2e602b80e42bf52ff760bc", + "sha256:fe8b9683eb26d2c4d5db32cd29b38fdcf8381324ab48313b5b69088e0e355379" + ], + "index": "pypi", + "version": "==1.23.0" }, "opencv-python-headless": { "hashes": [ @@ -2423,11 +2260,11 @@ }, "pre-commit": { "hashes": [ - "sha256:51a5ba7c480ae8072ecdb6933df22d2f812dc897d5fe848778116129a681aac7", - "sha256:a978dac7bc9ec0bcee55c18a277d553b0f419d259dadb4b9418ff2d00eb43959" + "sha256:10c62741aa5704faea2ad69cb550ca78082efe5697d6f04e5710c3c229afdd10", + "sha256:4233a1e38621c87d9dda9808c6606d7e7ba0e087cd56d3fe03202a01d2919615" ], "index": "pypi", - "version": "==2.20.0" + "version": "==2.19.0" }, "py": { "hashes": [ @@ -2517,11 +2354,11 @@ }, "pygments": { "hashes": [ - "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1", - "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42" + "sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb", + "sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519" ], "markers": "python_version >= '3.6'", - "version": "==2.13.0" + "version": "==2.12.0" }, "pynacl": { "hashes": [ @@ -2588,10 +2425,10 @@ }, "pytz": { "hashes": [ - "sha256:220f481bdafa09c3955dfbdddb7b57780e9a94f5127e35456a48589b9e0c0197", - "sha256:cea221417204f2d1a2aa03ddae3e867921971d0d76f14d87abb4414415bbdcf5" + "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7", + "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c" ], - "version": "==2022.2.1" + "version": "==2022.1" }, "pyyaml": { "hashes": [ @@ -2649,40 +2486,40 @@ }, "scipy": { "hashes": [ - "sha256:0419485dbcd0ed78c0d5bf234c5dd63e86065b39b4d669e45810d42199d49521", - "sha256:09412eb7fb60b8f00b328037fd814d25d261066ebc43a1e339cdce4f7502877e", - "sha256:26d28c468900e6d5fdb37d2812ab46db0ccd22c63baa095057871faa3a498bc9", - "sha256:34441dfbee5b002f9e15285014fd56e5e3372493c3e64ae297bae2c4b9659f5a", - "sha256:39ab9240cd215a9349c85ab908dda6d732f7d3b4b192fa05780812495536acc4", - "sha256:3bc1ab68b9a096f368ba06c3a5e1d1d50957a86665fc929c4332d21355e7e8f4", - "sha256:3c6f5d1d4b9a5e4fe5e14f26ffc9444fc59473bbf8d45dc4a9a15283b7063a72", - "sha256:47d1a95bd9d37302afcfe1b84c8011377c4f81e33649c5a5785db9ab827a6ade", - "sha256:71487c503e036740635f18324f62a11f283a632ace9d35933b2b0a04fd898c98", - "sha256:7a412c476a91b080e456229e413792bbb5d6202865dae963d1e6e28c2bb58691", - "sha256:825951b88f56765aeb6e5e38ac9d7d47407cfaaeb008d40aa1b45a2d7ea2731e", - "sha256:8cc81ac25659fec73599ccc52c989670e5ccd8974cf34bacd7b54a8d809aff1a", - "sha256:8d3faa40ac16c6357aaf7ea50394ea6f1e8e99d75e927a51102b1943b311b4d9", - "sha256:90c805f30c46cf60f1e76e947574f02954d25e3bb1e97aa8a07bc53aa31cf7d1", - "sha256:96d7cf7b25c9f23c59a766385f6370dab0659741699ecc7a451f9b94604938ce", - "sha256:b97b479f39c7e4aaf807efd0424dec74bbb379108f7d22cf09323086afcd312c", - "sha256:bc4e2c77d4cd015d739e75e74ebbafed59ba8497a7ed0fd400231ed7683497c4", - "sha256:c61b4a91a702e8e04aeb0bfc40460e1f17a640977c04dda8757efb0199c75332", - "sha256:d79da472015d0120ba9b357b28a99146cd6c17b9609403164b1a8ed149b4dfc8", - "sha256:e8fe305d9d67a81255e06203454729405706907dccbdfcc330b7b3482a6c371d", - "sha256:eb954f5aca4d26f468bbebcdc5448348eb287f7bea536c6306f62ea062f63d9a", - "sha256:f7c39f7dbb57cce00c108d06d731f3b0e2a4d3a95c66d96bce697684876ce4d4", - "sha256:f950a04b33e17b38ff561d5a0951caf3f5b47caa841edd772ffb7959f20a6af0" - ], - "index": "pypi", - "version": "==1.9.1" + "sha256:02b567e722d62bddd4ac253dafb01ce7ed8742cf8031aea030a41414b86c1125", + "sha256:1166514aa3bbf04cb5941027c6e294a000bba0cf00f5cdac6c77f2dad479b434", + "sha256:1da52b45ce1a24a4a22db6c157c38b39885a990a566748fc904ec9f03ed8c6ba", + "sha256:23b22fbeef3807966ea42d8163322366dd89da9bebdc075da7034cee3a1441ca", + "sha256:28d2cab0c6ac5aa131cc5071a3a1d8e1366dad82288d9ec2ca44df78fb50e649", + "sha256:2ef0fbc8bcf102c1998c1f16f15befe7cffba90895d6e84861cd6c6a33fb54f6", + "sha256:3b69b90c9419884efeffaac2c38376d6ef566e6e730a231e15722b0ab58f0328", + "sha256:4b93ec6f4c3c4d041b26b5f179a6aab8f5045423117ae7a45ba9710301d7e462", + "sha256:4e53a55f6a4f22de01ffe1d2f016e30adedb67a699a310cdcac312806807ca81", + "sha256:6311e3ae9cc75f77c33076cb2794fb0606f14c8f1b1c9ff8ce6005ba2c283621", + "sha256:65b77f20202599c51eb2771d11a6b899b97989159b7975e9b5259594f1d35ef4", + "sha256:6cc6b33139eb63f30725d5f7fa175763dc2df6a8f38ddf8df971f7c345b652dc", + "sha256:70de2f11bf64ca9921fda018864c78af7147025e467ce9f4a11bc877266900a6", + "sha256:70ebc84134cf0c504ce6a5f12d6db92cb2a8a53a49437a6bb4edca0bc101f11c", + "sha256:83606129247e7610b58d0e1e93d2c5133959e9cf93555d3c27e536892f1ba1f2", + "sha256:93d07494a8900d55492401917a119948ed330b8c3f1d700e0b904a578f10ead4", + "sha256:9c4e3ae8a716c8b3151e16c05edb1daf4cb4d866caa385e861556aff41300c14", + "sha256:9dd4012ac599a1e7eb63c114d1eee1bcfc6dc75a29b589ff0ad0bb3d9412034f", + "sha256:9e3fb1b0e896f14a85aa9a28d5f755daaeeb54c897b746df7a55ccb02b340f33", + "sha256:a0aa8220b89b2e3748a2836fbfa116194378910f1a6e78e4675a095bcd2c762d", + "sha256:d3b3c8924252caaffc54d4a99f1360aeec001e61267595561089f8b5900821bb", + "sha256:e013aed00ed776d790be4cb32826adb72799c61e318676172495383ba4570aa4", + "sha256:f3e7a8867f307e3359cc0ed2c63b61a1e33a19080f92fe377bc7d49f646f2ec1" + ], + "index": "pypi", + "version": "==1.8.1" }, "setuptools": { "hashes": [ - "sha256:2e24e0bec025f035a2e72cdd1961119f557d78ad331bb00ff82efb2ab8da8e82", - "sha256:7732871f4f7fa58fb6bdcaeadb0161b2bd046c85905dbaa066bdcbcc81953b57" + "sha256:16923d366ced322712c71ccb97164d07472abeecd13f3a6c283f6d5d26722793", + "sha256:db3b8e2f922b2a910a29804776c643ea609badb6a32c4bcc226fd4fd902cce65" ], "markers": "python_version >= '3.7'", - "version": "==65.3.0" + "version": "==63.1.0" }, "six": { "hashes": [ @@ -2708,11 +2545,11 @@ }, "sphinx": { "hashes": [ - "sha256:309a8da80cb6da9f4713438e5b55861877d5d7976b69d87e336733637ea12693", - "sha256:ba3224a4e206e1fbdecf98a4fae4992ef9b24b85ebf7b584bb340156eaf08d89" + "sha256:b18e978ea7565720f26019c702cd85c84376e948370f1cd43d60265010e1c7b0", + "sha256:d3e57663eed1d7c5c50895d191fdeda0b54ded6f44d5621b50709466c338d1e8" ], "index": "pypi", - "version": "==5.1.1" + "version": "==5.0.2" }, "sphinx-rtd-theme": { "hashes": [ @@ -2824,32 +2661,32 @@ "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02", "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6" ], - "markers": "python_version < '3.10'", + "markers": "python_version >= '3.7'", "version": "==4.3.0" }, "urllib3": { "hashes": [ - "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e", - "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997" + "sha256:8298d6d56d39be0e3bc13c1c97d133f9b45d797169a0e11cdd0e0489d786f7ec", + "sha256:879ba4d1e89654d9769ce13121e0f94310ea32e8d2f8cf587b77c08bbcdb30d6" ], "index": "pypi", - "version": "==1.26.12" + "version": "==1.26.10" }, "virtualenv": { "hashes": [ - "sha256:4193b7bc8a6cd23e4eb251ac64f29b4398ab2c233531e66e40b19a6b7b0d30c1", - "sha256:d86ea0bb50e06252d79e6c241507cb904fcd66090c3271381372d6221a3970f9" + "sha256:288171134a2ff3bfb1a2f54f119e77cd1b81c29fc1265a2356f3e8d14c7d58c4", + "sha256:b30aefac647e86af6d82bfc944c556f8f1a9c90427b2fb4e3bfbf338cb82becf" ], - "markers": "python_version >= '3.6'", - "version": "==20.16.3" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==20.15.1" }, "zipp": { "hashes": [ - "sha256:05b45f1ee8f807d0cc928485ca40a07cb491cf092ff587c0df9cb1fd154848d2", - "sha256:47c40d7fe183a6f21403a199b3e4192cca5774656965b0a4988ad2f8feb5f009" + "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad", + "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099" ], "markers": "python_version >= '3.7'", - "version": "==3.8.1" + "version": "==3.8.0" } } } diff --git a/README.md b/README.md index cfeb625bfebd6f..c2c90b0e61bf2b 100755 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ We have detailed instructions for [how to mount the device in a car](https://com Running on PC ------ -All openpilot services can run as usual on a PC without requiring special hardware or a car. You can also run openpilot on recorded or simulated data to develop or experiment with openpilot. +All of openpilot's services can run as normal on a PC, even without special hardware or a car. To develop or experiment with openpilot you can run openpilot on recorded or simulated data. With openpilot's tools, you can plot logs, replay drives, and watch the full-res camera streams. See [the tools README](tools/README.md) for more information. @@ -119,7 +119,7 @@ Directory Structure ├── debug # Tools to help you debug and do car ports ├── locationd # Precise localization and vehicle parameter estimation ├── loggerd # Logger and uploader of car data - ├── manager # Daemon that starts/stops all other daemons as needed + ├── manager # Deamon that starts/stops all other daemons as needed ├── modeld # Driving and monitoring model runners ├── monitoring # Daemon to determine driver attention ├── navd # Turn-by-turn navigation diff --git a/RELEASES.md b/RELEASES.md index 56cffeebe7e8d1..28a010968a016b 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -78,7 +78,7 @@ Version 0.8.14 (2022-06-01) Version 0.8.13 (2022-02-18) ======================== * Improved driver monitoring - * Re-tuned driver pose learner for relaxed driving positions + * Retuned driver pose learner for relaxed driving positions * Added reliance on driving model to be more scene adaptive * Matched strictness between comma two and comma three * Improved performance in turns by compensating for the road bank angle @@ -224,7 +224,7 @@ Version 0.8.4 (2021-05-17) * Delay controls start until system is ready * Fuzzy car identification, enabled with Community Features toggle * Localizer optimized for increased precision and less CPU usage - * Re-tuned lateral control to be more aggressive when model is confident + * Retuned lateral control to be more aggressive when model is confident * Toyota Mirai 2021 support * Lexus NX 300 2020 support thanks to goesreallyfast! * Volkswagen Atlas 2018-19 support thanks to jyoung8607! @@ -389,7 +389,7 @@ Version 0.7 (2019-12-13) * Improve GM longitudinal control: proper computations for 15Hz radar * Move GM port, Toyota with DSU removed, comma pedal in community features; toggle switch required * Remove upload over cellular toggle: only upload qlog and qcamera files if not on wifi - * Refactor Panda code towards ISO26262 and SIL2 compliance + * Refactor Panda code towards ISO26262 and SIL2 compliancy * Forward stock FCW for Honda Nidec * Volkswagen port now standard: comma Harness intercepts stock camera diff --git a/SConstruct b/SConstruct index 66a94f9b1b6475..878244768a2fc4 100644 --- a/SConstruct +++ b/SConstruct @@ -49,11 +49,6 @@ AddOption('--no-thneed', dest='no_thneed', help='avoid using thneed') -AddOption('--pc-thneed', - action='store_true', - dest='pc_thneed', - help='use thneed on pc') - AddOption('--no-test', action='store_false', dest='test', @@ -259,7 +254,7 @@ def abspath(x): # rpath works elsewhere return x[0].path.rsplit("/", 1)[1][:-3] -# Cython build environment +# Cython build enviroment py_include = sysconfig.get_paths()['include'] envCython = env.Clone() envCython["CPPPATH"] += [py_include, np.get_include()] diff --git a/cereal b/cereal index d3a943ef660dd2..589ef049a7b0ba 160000 --- a/cereal +++ b/cereal @@ -1 +1 @@ -Subproject commit d3a943ef660dd29f73700806ee0baf1d5aff6834 +Subproject commit 589ef049a7b0bac31f4c8987c0fc539839fae489 diff --git a/common/clutil.cc b/common/clutil.cc index 9d3447d8074727..b8f9fde4cfb65d 100644 --- a/common/clutil.cc +++ b/common/clutil.cc @@ -78,8 +78,7 @@ cl_program cl_program_from_file(cl_context ctx, cl_device_id device_id, const ch } cl_program cl_program_from_source(cl_context ctx, cl_device_id device_id, const std::string& src, const char* args) { - const char *csrc = src.c_str(); - cl_program prg = CL_CHECK_ERR(clCreateProgramWithSource(ctx, 1, &csrc, NULL, &err)); + cl_program prg = CL_CHECK_ERR(clCreateProgramWithSource(ctx, 1, (const char*[]){src.c_str()}, NULL, &err)); if (int err = clBuildProgram(prg, 1, &device_id, args, NULL, NULL); err != 0) { cl_print_build_errors(prg, device_id); assert(0); @@ -88,7 +87,7 @@ cl_program cl_program_from_source(cl_context ctx, cl_device_id device_id, const } cl_program cl_program_from_binary(cl_context ctx, cl_device_id device_id, const uint8_t* binary, size_t length, const char* args) { - cl_program prg = CL_CHECK_ERR(clCreateProgramWithBinary(ctx, 1, &device_id, &length, &binary, NULL, &err)); + cl_program prg = CL_CHECK_ERR(clCreateProgramWithBinary(ctx, 1, &device_id, &length, (const uint8_t*[]){binary}, NULL, &err)); if (int err = clBuildProgram(prg, 1, &device_id, args, NULL, NULL); err != 0) { cl_print_build_errors(prg, device_id); assert(0); diff --git a/common/gpio.py b/common/gpio.py index 260f8898a11000..32e5ca86cc3b2e 100644 --- a/common/gpio.py +++ b/common/gpio.py @@ -1,5 +1,3 @@ -from typing import Optional - def gpio_init(pin: int, output: bool) -> None: try: with open(f"/sys/class/gpio/gpio{pin}/direction", 'wb') as f: @@ -7,19 +5,10 @@ def gpio_init(pin: int, output: bool) -> None: except Exception as e: print(f"Failed to set gpio {pin} direction: {e}") + def gpio_set(pin: int, high: bool) -> None: try: with open(f"/sys/class/gpio/gpio{pin}/value", 'wb') as f: f.write(b"1" if high else b"0") except Exception as e: print(f"Failed to set gpio {pin} value: {e}") - -def gpio_read(pin: int) -> Optional[bool]: - val = None - try: - with open(f"/sys/class/gpio/gpio{pin}/value", 'rb') as f: - val = bool(int(f.read().strip())) - except Exception as e: - print(f"Failed to set gpio {pin} value: {e}") - - return val diff --git a/common/params.cc b/common/params.cc index 5c8002dfb76d28..a25cd278a6533f 100644 --- a/common/params.cc +++ b/common/params.cc @@ -88,8 +88,6 @@ std::unordered_map keys = { {"AthenadPid", PERSISTENT}, {"AthenadUploadQueue", PERSISTENT}, {"CalibrationParams", PERSISTENT}, - {"CameraDebugExpGain", CLEAR_ON_MANAGER_START}, - {"CameraDebugExpTime", CLEAR_ON_MANAGER_START}, {"CarBatteryCapacity", PERSISTENT}, {"CarParams", CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON}, {"CarParamsCache", CLEAR_ON_MANAGER_START}, @@ -100,7 +98,6 @@ std::unordered_map keys = { {"DashcamOverride", PERSISTENT}, {"DisableLogging", CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON}, {"DisablePowerDown", PERSISTENT}, - {"EndToEndLong", PERSISTENT}, {"DisableRadar_Allow", PERSISTENT}, {"DisableRadar", PERSISTENT}, // WARNING: THIS DISABLES AEB {"DisableUpdates", PERSISTENT}, diff --git a/common/tests/test_util.cc b/common/tests/test_util.cc index 25ecf09aa9db83..62e73275d42f80 100644 --- a/common/tests/test_util.cc +++ b/common/tests/test_util.cc @@ -136,7 +136,7 @@ TEST_CASE("util::create_directories") { REQUIRE(util::create_directories(dir + "/file", 0755) == false); REQUIRE(util::create_directories(dir + "/file/1/2/3", 0755) == false); } - SECTION("end with slashes") { + SECTION("end with slashs") { REQUIRE(util::create_directories(dir + "/", 0755)); } SECTION("empty") { diff --git a/docs/CARS.md b/docs/CARS.md index 1f0e24865deffd..78b4d3b168305e 100644 --- a/docs/CARS.md +++ b/docs/CARS.md @@ -6,213 +6,213 @@ A supported vehicle is one that just works when you install a comma three. All s # 205 Supported Cars -|Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|Harness| -|---|---|---|:---:|:---:|:---:|:---:|:---:|:---:| -|Acura|ILX 2016-19|AcuraWatch Plus|openpilot|25 mph|25 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Nidec| -|Acura|RDX 2016-18|AcuraWatch Plus|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Nidec| -|Acura|RDX 2019-22|All|Stock|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Bosch A| -|Audi|A3 2014-19|ACC + Lane Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Audi|A3 Sportback e-tron 2017-18|ACC + Lane Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Audi|Q2 2018|ACC + Lane Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Audi|Q3 2020-21|ACC + Lane Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Audi|RS3 2018|ACC + Lane Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Audi|S3 2015-17|ACC + Lane Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Cadillac|Escalade ESV 2016[1](#footnotes)|Adaptive Cruise Control (ACC) & LKAS|openpilot|0 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|OBD-II| -|Chevrolet|Bolt EUV 2022-23|Premier or Premier Redline Trim without Super Cruise Package|Stock|0 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|GM| -|Chevrolet|Silverado 1500 2020-21|Safety Package II|Stock|0 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|GM| -|Chevrolet|Volt 2017-18[1](#footnotes)|Adaptive Cruise Control|openpilot|0 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|OBD-II| -|Chrysler|Pacifica 2017-18|Adaptive Cruise Control|Stock|0 mph|9 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|FCA| -|Chrysler|Pacifica 2019-20|Adaptive Cruise Control|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|FCA| -|Chrysler|Pacifica 2021|All|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|FCA| -|Chrysler|Pacifica Hybrid 2017-18|Adaptive Cruise Control|Stock|0 mph|9 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|FCA| -|Chrysler|Pacifica Hybrid 2019-22|Adaptive Cruise Control|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|FCA| -|comma|body|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|None| -|Genesis|G70 2018-19|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai F| -|Genesis|G70 2020|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai F| -|Genesis|G80 2017-19|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai H| -|Genesis|G90 2017-18|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai C| -|GMC|Acadia 2018[1](#footnotes)|Adaptive Cruise Control|openpilot|0 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|OBD-II| -|GMC|Sierra 1500 2020-21|Driver Alert Package II|Stock|0 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|GM| -|Honda|Accord 2018-22|All|Stock|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Bosch A| -|Honda|Accord Hybrid 2018-22|All|Stock|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Bosch A| -|Honda|Civic 2016-18|Honda Sensing|openpilot|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Nidec| -|Honda|Civic 2019-21|All|Stock|0 mph|2 mph[2](#footnotes)|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Bosch A| -|Honda|Civic 2022|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Bosch B| -|Honda|Civic Hatchback 2017-21|Honda Sensing|Stock|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Bosch A| -|Honda|Civic Hatchback 2022|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Bosch B| -|Honda|CR-V 2015-16|Touring Trim|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Nidec| -|Honda|CR-V 2017-22|Honda Sensing|Stock|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Bosch A| -|Honda|CR-V Hybrid 2017-19|Honda Sensing|Stock|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Bosch A| -|Honda|e 2020|All|Stock|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Bosch A| -|Honda|Fit 2018-20|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Nidec| -|Honda|Freed 2020|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Nidec| -|Honda|HR-V 2019-22|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Nidec| -|Honda|Insight 2019-22|All|Stock|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Bosch A| -|Honda|Inspire 2018|All|Stock|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Bosch A| -|Honda|Odyssey 2018-20|Honda Sensing|openpilot|25 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Nidec| -|Honda|Passport 2019-21|All|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Nidec| -|Honda|Pilot 2016-22|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Nidec| -|Honda|Ridgeline 2017-22|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Honda Nidec| -|Hyundai|Elantra 2017-19|Smart Cruise Control (SCC) & LKAS|Stock|19 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai B| -|Hyundai|Elantra 2021-22|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai K| -|Hyundai|Elantra Hybrid 2021-22|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai K| -|Hyundai|Genesis 2015-16|Smart Cruise Control (SCC) & LKAS|Stock|19 mph|37 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai J| -|Hyundai|Ioniq 5 2022|Highway Driving Assist II|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai Q| -|Hyundai|Ioniq Electric 2019|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai C| -|Hyundai|Ioniq Electric 2020|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai H| -|Hyundai|Ioniq Hybrid 2017-19|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai C| -|Hyundai|Ioniq Hybrid 2020-22|Smart Cruise Control (SCC) & LFA|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai H| -|Hyundai|Ioniq Plug-in Hybrid 2019|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai C| -|Hyundai|Ioniq Plug-in Hybrid 2020-21|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai H| -|Hyundai|Kona 2020|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai B| -|Hyundai|Kona Electric 2018-21|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai G| -|Hyundai|Kona Electric 2022|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai O| -|Hyundai|Kona Hybrid 2020|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai I| -|Hyundai|Palisade 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai H| -|Hyundai|Santa Fe 2019-20|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai D| -|Hyundai|Santa Fe 2021-22|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai L| -|Hyundai|Santa Fe Hybrid 2022|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai L| -|Hyundai|Santa Fe Plug-in Hybrid 2022|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai L| -|Hyundai|Sonata 2018-19|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai E| -|Hyundai|Sonata 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai A| -|Hyundai|Sonata Hybrid 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai A| -|Hyundai|Tucson 2021|Smart Cruise Control (SCC)|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai L| -|Hyundai|Tucson Diesel 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai L| -|Hyundai|Tucson Hybrid 2022|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai N| -|Hyundai|Veloster 2019-20|Smart Cruise Control (SCC)|Stock|5 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai E| -|Jeep|Grand Cherokee 2016-18|Adaptive Cruise Control|Stock|0 mph|9 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|FCA| -|Jeep|Grand Cherokee 2019-21|Adaptive Cruise Control|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|FCA| -|Kia|Ceed 2019|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai E| -|Kia|EV6 2022|Highway Driving Assist II|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai P| -|Kia|Forte 2018|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai B| -|Kia|Forte 2019-21|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai G| -|Kia|K5 2021-22|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai A| -|Kia|Niro Electric 2019|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai H| -|Kia|Niro Electric 2020|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai F| -|Kia|Niro Electric 2021|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai C| -|Kia|Niro Electric 2022|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai H| -|Kia|Niro Hybrid 2021|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai F| -|Kia|Niro Hybrid 2022|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai H| -|Kia|Niro Plug-in Hybrid 2018-19|Smart Cruise Control (SCC) & LKAS|openpilot|10 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai C| -|Kia|Optima 2017|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai B| -|Kia|Optima 2019|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai G| -|Kia|Seltos 2021|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai A| -|Kia|Sorento 2018|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai C| -|Kia|Sorento 2019|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai E| -|Kia|Stinger 2018-20|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai C| -|Kia|Telluride 2020|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai H| -|Lexus|CT Hybrid 2017-18|Lexus Safety System+|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Lexus|ES 2019-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Lexus|ES Hybrid 2017-18|Lexus Safety System+|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Lexus|ES Hybrid 2019-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Lexus|IS 2017-19|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Lexus|NX 2018-19|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Lexus|NX 2020-21|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Lexus|NX Hybrid 2018-19|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Lexus|NX Hybrid 2020-21|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Lexus|RC 2017-20|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Lexus|RX 2016-19|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Lexus|RX 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Lexus|RX Hybrid 2016-19|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Lexus|RX Hybrid 2020-21|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Lexus|UX Hybrid 2019-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Mazda|CX-5 2022|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Mazda| -|Mazda|CX-9 2021-22|All|Stock|0 mph|28 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Mazda| -|Nissan|Altima 2019-20|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Nissan B| -|Nissan|Leaf 2018-22|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Nissan A| -|Nissan|Rogue 2018-20|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Nissan A| -|Nissan|X-Trail 2017|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Nissan A| -|Ram|1500 2019-22|Adaptive Cruise Control|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Ram| -|SEAT|Ateca 2018|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|SEAT|Leon 2014-20|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Subaru|Ascent 2019-21|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Subaru A| -|Subaru|Crosstrek 2018-19|EyeSight Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Subaru A| -|Subaru|Crosstrek 2020-21|EyeSight Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Subaru A| -|Subaru|Forester 2019-21|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Subaru A| -|Subaru|Impreza 2017-19|EyeSight Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Subaru A| -|Subaru|Impreza 2020-22|EyeSight Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Subaru A| -|Subaru|Legacy 2020-22|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Subaru B| -|Subaru|Outback 2020-22|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Subaru B| -|Subaru|XV 2018-19|EyeSight Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Subaru A| -|Subaru|XV 2020-21|EyeSight Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Subaru A| -|Škoda|Kamiq 2021[5](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Škoda|Karoq 2019-21[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Škoda|Kodiaq 2018-19|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Škoda|Octavia 2015, 2018-19|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Škoda|Octavia RS 2016|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Škoda|Scala 2020|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Škoda|Superb 2015-18|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Toyota|Alphard 2019-20|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|Alphard Hybrid 2021|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|Avalon 2016|Toyota Safety Sense P|Stock[3](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|Avalon 2017-18|All|Stock[3](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|Avalon 2019-21|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|Avalon 2022|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|Avalon Hybrid 2019-21|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|Avalon Hybrid 2022|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|C-HR 2017-21|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|C-HR Hybrid 2017-19|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|Camry 2018-20|All|Stock|0 mph[4](#footnotes)|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|Camry 2021-22|All|openpilot|0 mph[4](#footnotes)|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|Camry Hybrid 2018-20|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|Camry Hybrid 2021-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|Corolla 2017-19|All|Stock[3](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|Corolla 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|Corolla Cross (Non-US only) 2020-21|All|openpilot|17 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|Corolla Cross Hybrid (Non-US only) 2020-22|All|openpilot|17 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|Corolla Hatchback 2019-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|Corolla Hybrid 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|Highlander 2017-19|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|Highlander 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|Highlander Hybrid 2017-19|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|Highlander Hybrid 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|Mirai 2021|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|Prius 2016|Toyota Safety Sense P|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|Prius 2017-20|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|Prius 2021-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|Prius Prime 2017-20|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|Prius Prime 2021-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|Prius v 2017|Toyota Safety Sense P|Stock[3](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|RAV4 2016|Toyota Safety Sense P|Stock[3](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|RAV4 2017-18|All|Stock[3](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|RAV4 2019-21|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|RAV4 2022|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|RAV4 Hybrid 2016|Toyota Safety Sense P|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|RAV4 Hybrid 2017-18|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|RAV4 Hybrid 2019-21|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota| -|Toyota|RAV4 Hybrid 2022|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Toyota|Sienna 2018-20|All|Stock[3](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota| -|Volkswagen|Arteon 2018-22[7,8](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|Arteon eHybrid 2020-22[7,8](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|Arteon R 2020-22[7,8](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|Atlas 2018-23[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|Atlas Cross Sport 2021-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|California 2021[7](#footnotes)|Driver Assistance|Stock|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|Caravelle 2020[7](#footnotes)|Driver Assistance|Stock|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|CC 2018-22[7,8](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|e-Golf 2014-20|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Volkswagen|Golf 2015-20[8](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Volkswagen|Golf Alltrack 2015-19|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Volkswagen|Golf GTD 2015-20|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Volkswagen|Golf GTE 2015-20|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Volkswagen|Golf GTI 2015-21|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Volkswagen|Golf R 2015-19[8](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Volkswagen|Golf SportsVan 2015-20|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| -|Volkswagen|Jetta 2018-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|Jetta GLI 2021-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|Passat 2015-22[6,7,8](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|Passat Alltrack 2015-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|Passat GTE 2015-22[7,8](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|Polo 2020-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|Polo GTI 2020-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|T-Cross 2021[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|T-Roc 2021[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|Taos 2022[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|Teramont 2018-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|Teramont Cross Sport 2021-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|Teramont X 2021-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|Tiguan 2019-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533| -|Volkswagen|Touran 2017|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|VW| +|Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Harness| +|---|---|---|:---:|:---:|:---:|:---:|:---:| +|Acura|ILX 2016-19|AcuraWatch Plus|openpilot|25 mph|25 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Nidec| +|Acura|RDX 2016-18|AcuraWatch Plus|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Nidec| +|Acura|RDX 2019-22|All|Stock|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Bosch A| +|Audi|A3 2014-19|ACC + Lane Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Audi|A3 Sportback e-tron 2017-18|ACC + Lane Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Audi|Q2 2018|ACC + Lane Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Audi|Q3 2020-21|ACC + Lane Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Audi|RS3 2018|ACC + Lane Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Audi|S3 2015-17|ACC + Lane Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Cadillac|Escalade ESV 2016[1](#footnotes)|Adaptive Cruise Control (ACC) & LKAS|openpilot|0 mph|7 mph|[![star](assets/icon-star-full.svg)](##)|OBD-II| +|Chevrolet|Bolt EUV 2022-23|Premier or Premier Redline Trim without Super Cruise Package|Stock|0 mph|7 mph|[![star](assets/icon-star-full.svg)](##)|GM| +|Chevrolet|Silverado 1500 2020-21|Safety Package II|Stock|0 mph|7 mph|[![star](assets/icon-star-full.svg)](##)|GM| +|Chevrolet|Volt 2017-18[1](#footnotes)|Adaptive Cruise Control|openpilot|0 mph|7 mph|[![star](assets/icon-star-full.svg)](##)|OBD-II| +|Chrysler|Pacifica 2017-18|Adaptive Cruise Control|Stock|0 mph|9 mph|[![star](assets/icon-star-full.svg)](##)|FCA| +|Chrysler|Pacifica 2019-20|Adaptive Cruise Control|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|FCA| +|Chrysler|Pacifica 2021|All|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|FCA| +|Chrysler|Pacifica Hybrid 2017-18|Adaptive Cruise Control|Stock|0 mph|9 mph|[![star](assets/icon-star-full.svg)](##)|FCA| +|Chrysler|Pacifica Hybrid 2019-22|Adaptive Cruise Control|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|FCA| +|comma|body|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|None| +|Genesis|G70 2018-19|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai F| +|Genesis|G70 2020|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai F| +|Genesis|G80 2017-19|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai H| +|Genesis|G90 2017-18|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai C| +|GMC|Acadia 2018[1](#footnotes)|Adaptive Cruise Control|openpilot|0 mph|7 mph|[![star](assets/icon-star-full.svg)](##)|OBD-II| +|GMC|Sierra 1500 2020-21|Driver Alert Package II|Stock|0 mph|7 mph|[![star](assets/icon-star-full.svg)](##)|GM| +|Honda|Accord 2018-22|All|Stock|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Bosch A| +|Honda|Accord Hybrid 2018-22|All|Stock|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Bosch A| +|Honda|Civic 2016-18|Honda Sensing|openpilot|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Nidec| +|Honda|Civic 2019-21|All|Stock|0 mph|2 mph[2](#footnotes)|[![star](assets/icon-star-empty.svg)](##)|Honda Bosch A| +|Honda|Civic 2022|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Honda Bosch B| +|Honda|Civic Hatchback 2017-21|Honda Sensing|Stock|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Bosch A| +|Honda|Civic Hatchback 2022|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Honda Bosch B| +|Honda|CR-V 2015-16|Touring Trim|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Nidec| +|Honda|CR-V 2017-22|Honda Sensing|Stock|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Bosch A| +|Honda|CR-V Hybrid 2017-19|Honda Sensing|Stock|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Bosch A| +|Honda|e 2020|All|Stock|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Bosch A| +|Honda|Fit 2018-20|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Nidec| +|Honda|Freed 2020|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Nidec| +|Honda|HR-V 2019-22|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Nidec| +|Honda|Insight 2019-22|All|Stock|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Bosch A| +|Honda|Inspire 2018|All|Stock|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Bosch A| +|Honda|Odyssey 2018-20|Honda Sensing|openpilot|25 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Nidec| +|Honda|Passport 2019-21|All|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Nidec| +|Honda|Pilot 2016-22|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Nidec| +|Honda|Ridgeline 2017-22|Honda Sensing|openpilot|25 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|Honda Nidec| +|Hyundai|Elantra 2017-19|Smart Cruise Control (SCC) & LKAS|Stock|19 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai B| +|Hyundai|Elantra 2021-22|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai K| +|Hyundai|Elantra Hybrid 2021-22|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai K| +|Hyundai|Genesis 2015-16|Smart Cruise Control (SCC) & LKAS|Stock|19 mph|37 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai J| +|Hyundai|Ioniq 5 2022|Highway Driving Assist II|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai Q| +|Hyundai|Ioniq Electric 2019|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai C| +|Hyundai|Ioniq Electric 2020|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai H| +|Hyundai|Ioniq Hybrid 2017-19|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai C| +|Hyundai|Ioniq Hybrid 2020-22|Smart Cruise Control (SCC) & LFA|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai H| +|Hyundai|Ioniq Plug-in Hybrid 2019|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai C| +|Hyundai|Ioniq Plug-in Hybrid 2020-21|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai H| +|Hyundai|Kona 2020|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai B| +|Hyundai|Kona Electric 2018-21|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai G| +|Hyundai|Kona Electric 2022|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai O| +|Hyundai|Kona Hybrid 2020|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai I| +|Hyundai|Palisade 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai H| +|Hyundai|Santa Fe 2019-20|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai D| +|Hyundai|Santa Fe 2021-22|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai L| +|Hyundai|Santa Fe Hybrid 2022|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai L| +|Hyundai|Santa Fe Plug-in Hybrid 2022|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai L| +|Hyundai|Sonata 2018-19|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai E| +|Hyundai|Sonata 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai A| +|Hyundai|Sonata Hybrid 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai A| +|Hyundai|Tucson 2021|Smart Cruise Control (SCC)|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai L| +|Hyundai|Tucson Diesel 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai L| +|Hyundai|Tucson Hybrid 2022|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai N| +|Hyundai|Veloster 2019-20|Smart Cruise Control (SCC)|Stock|5 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai E| +|Jeep|Grand Cherokee 2016-18|Adaptive Cruise Control|Stock|0 mph|9 mph|[![star](assets/icon-star-full.svg)](##)|FCA| +|Jeep|Grand Cherokee 2019-21|Adaptive Cruise Control|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|FCA| +|Kia|Ceed 2019|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai E| +|Kia|EV6 2022|Highway Driving Assist II|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai P| +|Kia|Forte 2018|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai B| +|Kia|Forte 2019-21|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai G| +|Kia|K5 2021-22|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai A| +|Kia|Niro Electric 2019|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai H| +|Kia|Niro Electric 2020|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai F| +|Kia|Niro Electric 2021|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai C| +|Kia|Niro Electric 2022|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai H| +|Kia|Niro Hybrid 2021|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai F| +|Kia|Niro Hybrid 2022|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai H| +|Kia|Niro Plug-in Hybrid 2018-19|Smart Cruise Control (SCC) & LKAS|openpilot|10 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai C| +|Kia|Optima 2017|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai B| +|Kia|Optima 2019|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai G| +|Kia|Seltos 2021|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai A| +|Kia|Sorento 2018|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai C| +|Kia|Sorento 2019|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai E| +|Kia|Stinger 2018-20|Smart Cruise Control (SCC) & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai C| +|Kia|Telluride 2020|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Hyundai H| +|Lexus|CT Hybrid 2017-18|Lexus Safety System+|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Lexus|ES 2019-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Lexus|ES Hybrid 2017-18|Lexus Safety System+|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Lexus|ES Hybrid 2019-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Lexus|IS 2017-19|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Lexus|NX 2018-19|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Lexus|NX 2020-21|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Lexus|NX Hybrid 2018-19|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Lexus|NX Hybrid 2020-21|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Lexus|RC 2017-20|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Lexus|RX 2016-19|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Lexus|RX 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Lexus|RX Hybrid 2016-19|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Lexus|RX Hybrid 2020-21|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Lexus|UX Hybrid 2019-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Mazda|CX-5 2022|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Mazda| +|Mazda|CX-9 2021-22|All|Stock|0 mph|28 mph|[![star](assets/icon-star-full.svg)](##)|Mazda| +|Nissan|Altima 2019-20|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Nissan B| +|Nissan|Leaf 2018-22|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Nissan A| +|Nissan|Rogue 2018-20|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Nissan A| +|Nissan|X-Trail 2017|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Nissan A| +|Ram|1500 2019-22|Adaptive Cruise Control|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|Ram| +|SEAT|Ateca 2018|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|SEAT|Leon 2014-20|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Subaru|Ascent 2019-21|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Subaru A| +|Subaru|Crosstrek 2018-19|EyeSight Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|Subaru A| +|Subaru|Crosstrek 2020-21|EyeSight Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Subaru A| +|Subaru|Forester 2019-21|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Subaru A| +|Subaru|Impreza 2017-19|EyeSight Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|Subaru A| +|Subaru|Impreza 2020-22|EyeSight Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Subaru A| +|Subaru|Legacy 2020-22|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Subaru B| +|Subaru|Outback 2020-22|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Subaru B| +|Subaru|XV 2018-19|EyeSight Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|Subaru A| +|Subaru|XV 2020-21|EyeSight Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Subaru A| +|Škoda|Kamiq 2021[5](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Škoda|Karoq 2019-21[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Škoda|Kodiaq 2018-19|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Škoda|Octavia 2015, 2018-19|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Škoda|Octavia RS 2016|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Škoda|Scala 2020|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Škoda|Superb 2015-18|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Toyota|Alphard 2019-20|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Alphard Hybrid 2021|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Avalon 2016|Toyota Safety Sense P|Stock[3](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Avalon 2017-18|All|Stock[3](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Avalon 2019-21|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Avalon 2022|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Avalon Hybrid 2019-21|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Avalon Hybrid 2022|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|C-HR 2017-21|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|C-HR Hybrid 2017-19|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Camry 2018-20|All|Stock|0 mph[4](#footnotes)|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Camry 2021-22|All|openpilot|0 mph[4](#footnotes)|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Camry Hybrid 2018-20|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Camry Hybrid 2021-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Corolla 2017-19|All|Stock[3](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Corolla 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Corolla Cross (Non-US only) 2020-21|All|openpilot|17 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Corolla Cross Hybrid (Non-US only) 2020-22|All|openpilot|17 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Corolla Hatchback 2019-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Corolla Hybrid 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Highlander 2017-19|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Highlander 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Highlander Hybrid 2017-19|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Highlander Hybrid 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Mirai 2021|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Prius 2016|Toyota Safety Sense P|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Prius 2017-20|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Prius 2021-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Prius Prime 2017-20|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Prius Prime 2021-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Prius v 2017|Toyota Safety Sense P|Stock[3](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|RAV4 2016|Toyota Safety Sense P|Stock[3](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|RAV4 2017-18|All|Stock[3](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|RAV4 2019-21|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|RAV4 2022|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|RAV4 Hybrid 2016|Toyota Safety Sense P|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|RAV4 Hybrid 2017-18|All|Stock[3](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|RAV4 Hybrid 2019-21|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|RAV4 Hybrid 2022|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Toyota|Sienna 2018-20|All|Stock[3](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|Toyota| +|Volkswagen|Arteon 2018-22[7,8](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|Arteon eHybrid 2020-22[7,8](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|Arteon R 2020-22[7,8](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|Atlas 2018-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|Atlas Cross Sport 2021-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|California 2021[7](#footnotes)|Driver Assistance|Stock|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|Caravelle 2020[7](#footnotes)|Driver Assistance|Stock|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|CC 2018-22[7,8](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|e-Golf 2014-20|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Volkswagen|Golf 2015-20[8](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Volkswagen|Golf Alltrack 2015-19|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Volkswagen|Golf GTD 2015-20|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Volkswagen|Golf GTE 2015-20|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Volkswagen|Golf GTI 2015-21|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Volkswagen|Golf R 2015-19[8](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Volkswagen|Golf SportsVan 2015-20|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| +|Volkswagen|Jetta 2018-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|Jetta GLI 2021-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|Passat 2015-22[6,7,8](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|Passat Alltrack 2015-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|Passat GTE 2015-22[7,8](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|Polo 2020-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|Polo GTI 2020-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|T-Cross 2021[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|T-Roc 2021[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|Taos 2022[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|Teramont 2018-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|Teramont Cross Sport 2021-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|Teramont X 2021-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|Tiguan 2019-22[7](#footnotes)|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|J533| +|Volkswagen|Touran 2017|Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|VW| 1Requires a community built ASCM harness. NOTE: disconnecting the ASCM disables Automatic Emergency Braking (AEB).
diff --git a/docs/c_docs.rst b/docs/c_docs.rst index 77be7e51d89cc1..94d0adb560f719 100644 --- a/docs/c_docs.rst +++ b/docs/c_docs.rst @@ -72,6 +72,8 @@ modeld :project: selfdrive_modeld_transforms .. autodoxygenindex:: :project: selfdrive_modeld_models +.. autodoxygenindex:: + :project: selfdrive_modeld_thneed .. autodoxygenindex:: :project: selfdrive_modeld_runners diff --git a/opendbc b/opendbc index 8c634615c5b6eb..b913296c912344 160000 --- a/opendbc +++ b/opendbc @@ -1 +1 @@ -Subproject commit 8c634615c5b6eb05ebdecc097bdc72f5403a3afa +Subproject commit b913296c9123441b2b271c00239929ed388169b5 diff --git a/panda b/panda index 13d64d4cc38295..9d6496ece8465d 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit 13d64d4cc38295401ff1ffcf6a233a4b9625fd9f +Subproject commit 9d6496ece8465dfe30997b31dfb352e1e51dde6c diff --git a/release/build_release.sh b/release/build_release.sh index 80106eefb2336f..1000e607fa3687 100755 --- a/release/build_release.sh +++ b/release/build_release.sh @@ -78,7 +78,7 @@ find . -name 'moc_*' -delete find . -name '__pycache__' -delete rm -rf panda/board panda/certs panda/crypto rm -rf .sconsign.dblite Jenkinsfile release/ -rm selfdrive/modeld/models/supercombo.onnx +rm selfdrive/modeld/models/supercombo.dlc # Move back signed panda fw mkdir -p panda/board/obj diff --git a/release/files_common b/release/files_common index 10c66a8960fc43..04d13c8a5d639f 100644 --- a/release/files_common +++ b/release/files_common @@ -352,7 +352,7 @@ selfdrive/modeld/models/driving.cc selfdrive/modeld/models/driving.h selfdrive/modeld/models/dmonitoring.cc selfdrive/modeld/models/dmonitoring.h -selfdrive/modeld/models/supercombo.onnx +selfdrive/modeld/models/supercombo.dlc selfdrive/modeld/models/dmonitoring_model_q.dlc selfdrive/modeld/transforms/loadyuv.cc @@ -363,11 +363,12 @@ selfdrive/modeld/transforms/transform.h selfdrive/modeld/transforms/transform.cl selfdrive/modeld/thneed/*.py -selfdrive/modeld/thneed/thneed.h -selfdrive/modeld/thneed/thneed_common.cc -selfdrive/modeld/thneed/thneed_qcom2.cc +selfdrive/modeld/thneed/thneed.* selfdrive/modeld/thneed/serialize.cc +selfdrive/modeld/thneed/compile.cc +selfdrive/modeld/thneed/optimizer.cc selfdrive/modeld/thneed/include/* +selfdrive/modeld/thneed/kernels/*.cl selfdrive/modeld/runners/snpemodel.cc selfdrive/modeld/runners/snpemodel.h @@ -558,16 +559,3 @@ opendbc/vw_mqb_2010.dbc opendbc/tesla_can.dbc opendbc/tesla_radar.dbc opendbc/tesla_powertrain.dbc - -tinygrad_repo/openpilot/compile.py -tinygrad_repo/accel/opencl/* -tinygrad_repo/extra/onnx.py -tinygrad_repo/extra/utils.py -tinygrad_repo/tinygrad/llops/ops_gpu.py -tinygrad_repo/tinygrad/llops/ops_opencl.py -tinygrad_repo/tinygrad/helpers.py -tinygrad_repo/tinygrad/mlops.py -tinygrad_repo/tinygrad/ops.py -tinygrad_repo/tinygrad/shapetracker.py -tinygrad_repo/tinygrad/tensor.py -tinygrad_repo/tinygrad/nn/__init__.py diff --git a/selfdrive/athena/tests/helpers.py b/selfdrive/athena/tests/helpers.py index 071393cb14fa1f..bb5fcd1063caf1 100644 --- a/selfdrive/athena/tests/helpers.py +++ b/selfdrive/athena/tests/helpers.py @@ -116,7 +116,7 @@ def inner(*args, **kwargs): with Timeout(2, 'HTTP Server seeding failed'): while True: try: - requests.put(f'http://{host}:{port}/qlog.bz2', data='', timeout=10) + requests.put(f'http://{host}:{port}/qlog.bz2', data='') break except requests.exceptions.ConnectionError: time.sleep(0.1) diff --git a/selfdrive/boardd/boardd.cc b/selfdrive/boardd/boardd.cc index 47bff1c5b67ade..bd3a6c43841eb9 100644 --- a/selfdrive/boardd/boardd.cc +++ b/selfdrive/boardd/boardd.cc @@ -34,7 +34,7 @@ // - The internal panda will always be the first panda // - Consecutive pandas will be sorted based on panda type, and then serial number // Connecting: -// - If a panda connection is dropped, boardd will reconnect to all pandas +// - If a panda connection is dropped, boardd wil reconnect to all pandas // - If a panda is added, we will only reconnect when we are offroad // CAN buses: // - Each panda will have it's block of 4 buses. E.g.: the second panda will use @@ -44,7 +44,7 @@ // Safety: // - SafetyConfig is a list, which is mapped to the connected pandas // - If there are more pandas connected than there are SafetyConfigs, -// the excess pandas will remain in "silent" or "noOutput" mode +// the excess pandas will remain in "silent" ot "noOutput" mode // Ignition: // - If any of the ignition sources in any panda is high, ignition is high @@ -197,6 +197,12 @@ Panda *usb_connect(std::string serial="", uint32_t index=0) { } //panda->enable_deepsleep(); + // power on charging, only the first time. Panda can also change mode and it causes a brief disconneciton +#ifndef __x86_64__ + static std::once_flag connected_once; + std::call_once(connected_once, &Panda::set_usb_power_mode, panda, cereal::PeripheralState::UsbPowerMode::CDP); +#endif + sync_time(panda.get(), SyncTimeDir::FROM_PANDA); return panda.release(); } @@ -385,6 +391,13 @@ std::optional send_panda_states(PubMaster *pm, const std::vector } void send_peripheral_state(PubMaster *pm, Panda *panda) { + auto pandaState_opt = panda->get_state(); + if (!pandaState_opt) { + return; + } + + health_t pandaState = *pandaState_opt; + // build msg MessageBuilder msg; auto evt = msg.initEvent(); @@ -402,6 +415,7 @@ void send_peripheral_state(PubMaster *pm, Panda *panda) { } uint16_t fan_speed_rpm = panda->get_fan_speed(); + ps.setUsbPowerMode(cereal::PeripheralState::UsbPowerMode(pandaState.usb_power_mode_pkt)); ps.setFanSpeedRpm(fan_speed_rpm); pm->send("peripheralState", msg); @@ -477,6 +491,7 @@ void peripheral_control_thread(Panda *panda) { uint16_t prev_fan_speed = 999; uint16_t ir_pwr = 0; uint16_t prev_ir_pwr = 999; + bool prev_charging_disabled = false; unsigned int cnt = 0; FirstOrderFilter integ_lines_filter(0, 30.0, 0.05); @@ -485,9 +500,23 @@ void peripheral_control_thread(Panda *panda) { cnt++; sm.update(1000); // TODO: what happens if EINTR is sent while in sm.update? + if (!Hardware::PC() && sm.updated("deviceState")) { + // Charging mode + bool charging_disabled = sm["deviceState"].getDeviceState().getChargingDisabled(); + if (charging_disabled != prev_charging_disabled) { + if (charging_disabled) { + panda->set_usb_power_mode(cereal::PeripheralState::UsbPowerMode::CLIENT); + LOGW("TURN OFF CHARGING!\n"); + } else { + panda->set_usb_power_mode(cereal::PeripheralState::UsbPowerMode::CDP); + LOGW("TURN ON CHARGING!\n"); + } + prev_charging_disabled = charging_disabled; + } + } + // Other pandas don't have fan/IR to control if (panda->hw_type != cereal::PandaState::PandaType::UNO && panda->hw_type != cereal::PandaState::PandaType::DOS) continue; - if (sm.updated("deviceState")) { // Fan speed uint16_t fan_speed = sm["deviceState"].getDeviceState().getFanSpeedPercentDesired(); @@ -512,7 +541,6 @@ void peripheral_control_thread(Panda *panda) { ir_pwr = 100.0 * (MIN_IR_POWER + ((cur_integ_lines - CUTOFF_IL) * (MAX_IR_POWER - MIN_IR_POWER) / (SATURATE_IL - CUTOFF_IL))); } } - // Disable ir_pwr on front frame timeout uint64_t cur_t = nanos_since_boot(); if (cur_t - last_front_frame_t > 1e9) { diff --git a/selfdrive/boardd/panda.cc b/selfdrive/boardd/panda.cc index 685dabd873df48..d90c4cdab2a825 100644 --- a/selfdrive/boardd/panda.cc +++ b/selfdrive/boardd/panda.cc @@ -342,6 +342,10 @@ void Panda::enable_deepsleep() { usb_write(0xfb, 0, 0); } +void Panda::set_usb_power_mode(cereal::PeripheralState::UsbPowerMode power_mode) { + usb_write(0xe6, (uint16_t)power_mode, 0); +} + void Panda::send_heartbeat(bool engaged) { usb_write(0xf3, engaged, 0); } diff --git a/selfdrive/boardd/panda.h b/selfdrive/boardd/panda.h index 1cefc3cb4d9f29..23a10d5850f300 100644 --- a/selfdrive/boardd/panda.h +++ b/selfdrive/boardd/panda.h @@ -86,6 +86,7 @@ class Panda { std::optional get_serial(); void set_power_saving(bool power_saving); void enable_deepsleep(); + void set_usb_power_mode(cereal::PeripheralState::UsbPowerMode power_mode); void send_heartbeat(bool engaged); void set_can_speed_kbps(uint16_t bus, uint16_t speed); void set_data_speed_kbps(uint16_t bus, uint16_t speed); diff --git a/selfdrive/car/car_helpers.py b/selfdrive/car/car_helpers.py index 9e1260a6d5fa23..aa4b37d572e537 100644 --- a/selfdrive/car/car_helpers.py +++ b/selfdrive/car/car_helpers.py @@ -82,7 +82,7 @@ def fingerprint(logcan, sendcan): ecu_rx_addrs = set() if not fixed_fingerprint and not skip_fw_query: - # Vin query only reliably works through OBDII + # Vin query only reliably works thorugh OBDII bus = 1 cached_params = Params().get("CarParamsCache") diff --git a/selfdrive/car/chrysler/carstate.py b/selfdrive/car/chrysler/carstate.py index 0f0d30782aa2e3..fefd351a232741 100644 --- a/selfdrive/car/chrysler/carstate.py +++ b/selfdrive/car/chrysler/carstate.py @@ -58,8 +58,8 @@ def update(self, cp, cp_cam): ) # button presses - ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_stalk(200, cp.vl["STEERING_LEVERS"]["TURN_SIGNALS"] == 1, - cp.vl["STEERING_LEVERS"]["TURN_SIGNALS"] == 2) + ret.leftBlinker = cp.vl["STEERING_LEVERS"]["TURN_SIGNALS"] == 1 + ret.rightBlinker = cp.vl["STEERING_LEVERS"]["TURN_SIGNALS"] == 2 ret.genericToggle = cp.vl["STEERING_LEVERS"]["HIGH_BEAM_PRESSED"] == 1 # steering wheel diff --git a/selfdrive/car/chrysler/values.py b/selfdrive/car/chrysler/values.py index 0df2c18868531e..ef5471490977f3 100644 --- a/selfdrive/car/chrysler/values.py +++ b/selfdrive/car/chrysler/values.py @@ -130,11 +130,6 @@ class ChryslerCarInfo(CarInfo): } FW_VERSIONS = { - CAR.PACIFICA_2019_HYBRID: { - (Ecu.hcp, 0x7e2, None): [], - (Ecu.esp, 0x7e4, None): [], - }, - CAR.RAM_1500: { (Ecu.combinationMeter, 0x742, None): [ b'68294063AH', diff --git a/selfdrive/car/docs_definitions.py b/selfdrive/car/docs_definitions.py index 3f9d51b433828b..52d6388d7edf6b 100644 --- a/selfdrive/car/docs_definitions.py +++ b/selfdrive/car/docs_definitions.py @@ -10,6 +10,10 @@ GOOD_TORQUE_THRESHOLD = 1.0 # m/s^2 MODEL_YEARS_RE = r"(?<= )((\d{4}-\d{2})|(\d{4}))(,|$)" +# Makes that lack auto-resume with stock long, and auto resume in any configuration +NO_AUTO_RESUME_STOCK_LONG = {"toyota", "gm"} +NO_AUTO_RESUME = NO_AUTO_RESUME_STOCK_LONG | {"nissan", "subaru"} + class Column(Enum): MAKE = "Make" @@ -19,7 +23,6 @@ class Column(Enum): FSR_LONGITUDINAL = "No ACC accel below" FSR_STEERING = "No ALC below" STEERING_TORQUE = "Steering Torque" - AUTO_RESUME = "Resume from stop" HARNESS = "Harness" @@ -136,7 +139,6 @@ def init(self, CP: car.CarParams, all_footnotes: Dict[Enum, int]): Column.FSR_LONGITUDINAL: f"{max(self.min_enable_speed * CV.MS_TO_MPH, 0):.0f} mph", Column.FSR_STEERING: f"{max(self.min_steer_speed * CV.MS_TO_MPH, 0):.0f} mph", Column.STEERING_TORQUE: Star.EMPTY, - Column.AUTO_RESUME: Star.FULL if CP.autoResumeSng else Star.EMPTY, Column.HARNESS: self.harness.value, } @@ -164,7 +166,7 @@ def get_detail_sentence(self, CP): acc = "" if self.min_enable_speed > 0: acc = f" while driving above {self.min_enable_speed * CV.MS_TO_MPH:.0f} mph" - elif CP.autoResumeSng: + elif CP.carName not in NO_AUTO_RESUME or (CP.carName in NO_AUTO_RESUME_STOCK_LONG and CP.openpilotLongitudinalControl): acc = " that automatically resumes from a stop" if self.row[Column.STEERING_TORQUE] != Star.FULL: @@ -191,3 +193,4 @@ def get_column(self, column: Column, star_icon: str, footnote_tag: str) -> str: item += footnote_tag.format(f'{",".join(map(str, sups))}') return item + diff --git a/selfdrive/car/ford/carstate.py b/selfdrive/car/ford/carstate.py index 3c9961e9e128bc..aaa3af612f05d8 100644 --- a/selfdrive/car/ford/carstate.py +++ b/selfdrive/car/ford/carstate.py @@ -203,8 +203,7 @@ def get_cam_can_parser(CP): ("DasStats_D_Dsply", "IPMA_Data"), # DAS status ("DasWarn_D_Dsply", "IPMA_Data"), # DAS warning ("AhbHiBeam_D_Rq", "IPMA_Data"), # AHB status - ("Passthru_63", "IPMA_Data"), - ("Passthru_48", "IPMA_Data"), + ("Set_Me_X1", "IPMA_Data"), ] checks = [ diff --git a/selfdrive/car/ford/fordcan.py b/selfdrive/car/ford/fordcan.py index bb104aaf3c8530..29fec1f2dedc36 100644 --- a/selfdrive/car/ford/fordcan.py +++ b/selfdrive/car/ford/fordcan.py @@ -51,7 +51,7 @@ def create_tja_command(packer, lca_rq: int, ramp_type: int, precision: int, path return packer.make_can_msg("LateralMotionControl", 0, values) -def create_lkas_ui_command(packer, main_on: bool, enabled: bool, steer_alert: bool, stock_values: dict): +def create_lkas_ui_command(packer, main_on: bool, enabled: bool, steer_alert: bool, stock_values): """ Creates a CAN message for the Ford IPC IPMA/LKAS status. @@ -72,14 +72,25 @@ def create_lkas_ui_command(packer, main_on: bool, enabled: bool, steer_alert: bo lines = 30 values = { - **stock_values, - "LaActvStats_D_Dsply": lines, # LKAS status (lines) [0|31] - "LaHandsOff_D_Dsply": 2 if steer_alert else 0, # 0=HandsOn, 1=Level1 (w/o chime), 2=Level2 (w/ chime), 3=Suppressed + "FeatConfigIpmaActl": stock_values["FeatConfigIpmaActl"], # [0|65535] + "FeatNoIpmaActl": stock_values["FeatNoIpmaActl"], # [0|65535] + "PersIndexIpma_D_Actl": stock_values["PersIndexIpma_D_Actl"], # [0|7] + "AhbcRampingV_D_Rq": stock_values["AhbcRampingV_D_Rq"], # AHB ramping [0|3] + "LaActvStats_D_Dsply": lines, # LKAS status (lines) [0|31] + "LaDenyStats_B_Dsply": stock_values["LaDenyStats_B_Dsply"], # LKAS error [0|1] + "LaHandsOff_D_Dsply": 2 if steer_alert else 0, # 0=HandsOn, 1=Level1 (w/o chime), 2=Level2 (w/ chime), 3=Suppressed + "CamraDefog_B_Req": stock_values["CamraDefog_B_Req"], # Windshield heater? [0|1] + "CamraStats_D_Dsply": stock_values["CamraStats_D_Dsply"], # Camera status [0|3] + "DasAlrtLvl_D_Dsply": stock_values["DasAlrtLvl_D_Dsply"], # DAS alert level [0|7] + "DasStats_D_Dsply": stock_values["DasStats_D_Dsply"], # DAS status [0|3] + "DasWarn_D_Dsply": stock_values["DasWarn_D_Dsply"], # DAS warning [0|3] + "AhbHiBeam_D_Rq": stock_values["AhbHiBeam_D_Rq"], # AHB status [0|3] + "Set_Me_X1": stock_values["Set_Me_X1"], # [0|15] } return packer.make_can_msg("IPMA_Data", 0, values) -def create_acc_ui_command(packer, main_on: bool, enabled: bool, stock_values: dict): +def create_acc_ui_command(packer, main_on: bool, enabled: bool, stock_values): """ Creates a CAN message for the Ford IPC adaptive cruise, forward collision warning and traffic jam assist status. @@ -90,8 +101,32 @@ def create_acc_ui_command(packer, main_on: bool, enabled: bool, stock_values: di """ values = { - **stock_values, - "Tja_D_Stat": 2 if enabled else (1 if main_on else 0), # TJA status: 0=Off, 1=Standby, 2=Active, 3=InterventionLeft, 4=InterventionRight, 5=WarningLeft, 6=WarningRight, 7=NotUsed [0|7] + "HaDsply_No_Cs": stock_values["HaDsply_No_Cs"], # [0|255] + "HaDsply_No_Cnt": stock_values["HaDsply_No_Cnt"], # [0|15] + "AccStopStat_D_Dsply": stock_values["AccStopStat_D_Dsply"], # ACC stopped status message: 0=NoDisplay, 1=ResumeReady, 2=Stopped, 3=PressResume [0|3] + "AccTrgDist2_D_Dsply": stock_values["AccTrgDist2_D_Dsply"], # ACC target distance [0|15] + "AccStopRes_B_Dsply": stock_values["AccStopRes_B_Dsply"], # [0|1] + "TjaWarn_D_Rq": stock_values["TjaWarn_D_Rq"], # TJA warning: 0=NoWarning, 1=Cancel, 2=HardTakeOverLevel1, 3=HardTakeOverLevel2 [0|7] + "Tja_D_Stat": 2 if enabled else (1 if main_on else 0), # TJA status: 0=Off, 1=Standby, 2=Active, 3=InterventionLeft, 4=InterventionRight, 5=WarningLeft, 6=WarningRight, 7=NotUsed [0|7] + "TjaMsgTxt_D_Dsply": stock_values["TjaMsgTxt_D_Dsply"], # TJA text [0|7] + "IaccLamp_D_Rq": stock_values["IaccLamp_D_Rq"], # iACC status icon [0|3] + "AccMsgTxt_D2_Rq": stock_values["AccMsgTxt_D2_Rq"], # ACC text [0|15] + "FcwDeny_B_Dsply": stock_values["FcwDeny_B_Dsply"], # FCW disabled [0|1] + "FcwMemStat_B_Actl": stock_values["FcwMemStat_B_Actl"], # FCW enabled setting [0|1] + "AccTGap_B_Dsply": stock_values["AccTGap_B_Dsply"], # ACC time gap display setting [0|1] + "CadsAlignIncplt_B_Actl": stock_values["CadsAlignIncplt_B_Actl"], # Radar alignment? [0|1] + "AccFllwMde_B_Dsply": stock_values["AccFllwMde_B_Dsply"], # ACC follow mode display setting [0|1] + "CadsRadrBlck_B_Actl": stock_values["CadsRadrBlck_B_Actl"], # Radar blocked? [0|1] + "CmbbPostEvnt_B_Dsply": stock_values["CmbbPostEvnt_B_Dsply"], # AEB event status [0|1] + "AccStopMde_B_Dsply": stock_values["AccStopMde_B_Dsply"], # ACC stop mode display setting [0|1] + "FcwMemSens_D_Actl": stock_values["FcwMemSens_D_Actl"], # FCW sensitivity setting [0|3] + "FcwMsgTxt_D_Rq": stock_values["FcwMsgTxt_D_Rq"], # FCW text [0|7] + "AccWarn_D_Dsply": stock_values["AccWarn_D_Dsply"], # ACC warning [0|3] + "FcwVisblWarn_B_Rq": stock_values["FcwVisblWarn_B_Rq"], # FCW alert: 0=Off, 1=On [0|1] + "FcwAudioWarn_B_Rq": stock_values["FcwAudioWarn_B_Rq"], # FCW audio: 0=Off, 1=On [0|1] + "AccTGap_D_Dsply": stock_values["AccTGap_D_Dsply"], # ACC time gap: 1=Time_Gap_1, 2=Time_Gap_2, ..., 5=Time_Gap_5 [0|7] + "AccMemEnbl_B_RqDrv": stock_values["AccMemEnbl_B_RqDrv"], # ACC setting: 0=NormalCruise, 1=AdaptiveCruise [0|1] + "FdaMem_B_Stat": stock_values["FdaMem_B_Stat"], # FDA enabled setting [0|1] } return packer.make_can_msg("ACCDATA_3", 0, values) diff --git a/selfdrive/car/fw_versions.py b/selfdrive/car/fw_versions.py index 363b852ebedd82..886bf4aff49912 100755 --- a/selfdrive/car/fw_versions.py +++ b/selfdrive/car/fw_versions.py @@ -220,7 +220,7 @@ class Request: "chrysler", [CHRYSLER_VERSION_REQUEST], [CHRYSLER_VERSION_RESPONSE], - whitelist_ecus=[Ecu.esp, Ecu.hcp, Ecu.engine, Ecu.transmission], + whitelist_ecus=[Ecu.engine, Ecu.transmission], ), Request( "chrysler", diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py index ac8bc458091833..09d950ea8d0072 100755 --- a/selfdrive/car/gm/interface.py +++ b/selfdrive/car/gm/interface.py @@ -49,7 +49,6 @@ def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None, disa ret = CarInterfaceBase.get_std_params(candidate, fingerprint) ret.carName = "gm" ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.gm)] - ret.autoResumeSng = False if candidate in EV_CAR: ret.transmissionType = TransmissionType.direct @@ -74,7 +73,7 @@ def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None, disa ret.dashcamOnly = candidate in {CAR.CADILLAC_ATS, CAR.HOLDEN_ASTRA, CAR.MALIBU, CAR.BUICK_REGAL} # Start with a baseline tuning for all GM vehicles. Override tuning as needed in each model section below. - ret.minSteerSpeed = 10 * CV.KPH_TO_MS + ret.minSteerSpeed = 7 * CV.MPH_TO_MS ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]] ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.2], [0.00]] ret.lateralTuning.pid.kf = 0.00004 # full torque for 20 deg at 80mph means 0.00007818594 diff --git a/selfdrive/car/hyundai/carcontroller.py b/selfdrive/car/hyundai/carcontroller.py index 586d215ffe5645..971330a33516ce 100644 --- a/selfdrive/car/hyundai/carcontroller.py +++ b/selfdrive/car/hyundai/carcontroller.py @@ -15,7 +15,6 @@ def process_hud_alert(enabled, fingerprint, hud_control): sys_warning = (hud_control.visualAlert in (VisualAlert.steerRequired, VisualAlert.ldw)) # initialize to no line visible - # TODO: this is not accurate for all cars sys_state = 1 if hud_control.leftLaneVisible and hud_control.rightLaneVisible or sys_warning: # HUD alert only display when LKAS status is active sys_state = 3 if enabled or sys_warning else 4 diff --git a/selfdrive/car/hyundai/hyundaican.py b/selfdrive/car/hyundai/hyundaican.py index f94cc508a7bfeb..8a5e33f11144e6 100644 --- a/selfdrive/car/hyundai/hyundaican.py +++ b/selfdrive/car/hyundai/hyundaican.py @@ -37,26 +37,12 @@ def create_lkas11(packer, frame, car_fingerprint, apply_steer, steer_req, # Note: the warning is hidden while the blinkers are on values["CF_Lkas_SysWarning"] = 4 if sys_warning else 0 - # Likely cars lacking the ability to show individual lane lines in the dash - elif car_fingerprint in (CAR.KIA_OPTIMA,): - # SysWarning 4 = keep hands on wheel + beep - values["CF_Lkas_SysWarning"] = 4 if sys_warning else 0 - - # SysState 0 = no icons - # SysState 1-2 = white car + lanes - # SysState 3 = green car + lanes, green steering wheel - # SysState 4 = green car + lanes - values["CF_Lkas_LdwsSysState"] = 3 if enabled else 1 - values["CF_Lkas_LdwsOpt_USM"] = 2 # non-2 changes above SysState definition - - # these have no effect - values["CF_Lkas_LdwsActivemode"] = 0 - values["CF_Lkas_FcwOpt_USM"] = 0 - elif car_fingerprint == CAR.HYUNDAI_GENESIS: # This field is actually LdwsActivemode # Genesis and Optima fault when forwarding while engaged values["CF_Lkas_LdwsActivemode"] = 2 + elif car_fingerprint == CAR.KIA_OPTIMA: + values["CF_Lkas_LdwsActivemode"] = 0 dat = packer.make_can_msg("LKAS11", 0, values)[2] diff --git a/selfdrive/car/hyundai/interface.py b/selfdrive/car/hyundai/interface.py index bbb797c2e0c962..fbf2334980ef44 100644 --- a/selfdrive/car/hyundai/interface.py +++ b/selfdrive/car/hyundai/interface.py @@ -299,7 +299,6 @@ def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=[], disabl # non-HDA2 if 0x1cf not in fingerprint[4]: ret.flags |= HyundaiFlags.CANFD_ALT_BUTTONS.value - ret.safetyConfigs[1].safetyParam |= Panda.FLAG_HYUNDAI_CANFD_ALT_BUTTONS else: ret.enableBsm = 0x58b in fingerprint[0] diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index 79e3ea419038c9..aa18235223a6eb 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -140,7 +140,7 @@ class HyundaiCarInfo(CarInfo): # Kia CAR.KIA_FORTE: [ HyundaiCarInfo("Kia Forte 2018", harness=Harness.hyundai_b), - HyundaiCarInfo("Kia Forte 2019-21", harness=Harness.hyundai_g), + HyundaiCarInfo("Kia Forte 2019-21", "All", harness=Harness.hyundai_g), ], CAR.KIA_K5_2021: HyundaiCarInfo("Kia K5 2021-22", "Smart Cruise Control (SCC)", harness=Harness.hyundai_a), CAR.KIA_NIRO_EV: [ diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index 1e14aca8cfd3dd..9da6aabd67b7cf 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -107,14 +107,11 @@ def get_std_params(candidate, fingerprint): ret = car.CarParams.new_message() ret.carFingerprint = candidate - # Car docs fields - ret.maxLateralAccel = get_torque_params(candidate)['MAX_LAT_ACCEL_MEASURED'] - ret.autoResumeSng = True # describes whether car can resume from a stop automatically - # standard ALC params ret.steerControlType = car.CarParams.SteerControlType.torque ret.minSteerSpeed = 0. ret.wheelSpeedFactor = 1.0 + ret.maxLateralAccel = get_torque_params(candidate)['MAX_LAT_ACCEL_MEASURED'] ret.pcmCruise = True # openpilot's state is tied to the PCM's cruise state on most cars ret.minEnableSpeed = -1. # enable is done by stock ACC, so ignore this @@ -271,12 +268,12 @@ def __init__(self, CP): self.left_blinker_prev = False self.right_blinker_prev = False - # Q = np.matrix([[0.0, 0.0], [0.0, 100.0]]) - # R = 0.3 + # Q = np.matrix([[10.0, 0.0], [0.0, 100.0]]) + # R = 1e3 self.v_ego_kf = KF1D(x0=[[0.0], [0.0]], A=[[1.0, DT_CTRL], [0.0, 1.0]], C=[1.0, 0.0], - K=[[0.17406039], [1.65925647]]) + K=[[0.12287673], [0.29666309]]) def update_speed_kf(self, v_ego_raw): if abs(v_ego_raw - self.v_ego_kf.x[0][0]) > 2.0: # Prevent large accelerations when car starts at non zero speed diff --git a/selfdrive/car/nissan/interface.py b/selfdrive/car/nissan/interface.py index fe567468bba894..9c04d975f93161 100644 --- a/selfdrive/car/nissan/interface.py +++ b/selfdrive/car/nissan/interface.py @@ -13,7 +13,6 @@ def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None, disa ret = CarInterfaceBase.get_std_params(candidate, fingerprint) ret.carName = "nissan" ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.nissan)] - ret.autoResumeSng = False ret.steerLimitTimer = 1.0 diff --git a/selfdrive/car/subaru/interface.py b/selfdrive/car/subaru/interface.py index b84291225690a6..a464734a30b9bb 100644 --- a/selfdrive/car/subaru/interface.py +++ b/selfdrive/car/subaru/interface.py @@ -15,7 +15,6 @@ def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None, disa ret.carName = "subaru" ret.radarOffCan = True ret.dashcamOnly = candidate in PREGLOBAL_CARS - ret.autoResumeSng = False if candidate in PREGLOBAL_CARS: ret.enableBsm = 0x25c in fingerprint[0] diff --git a/selfdrive/car/tests/test_fingerprints.py b/selfdrive/car/tests/test_fingerprints.py index 26ade29e4a507b..9dd28b2d5092e6 100755 --- a/selfdrive/car/tests/test_fingerprints.py +++ b/selfdrive/car/tests/test_fingerprints.py @@ -94,4 +94,4 @@ def check_can_ignition_conflicts(fingerprints, brands): print("TEST FAILED") sys.exit(1) else: - print("TEST SUCCESSFUL") + print("TEST SUCESSFUL") diff --git a/selfdrive/car/tests/test_fw_fingerprint.py b/selfdrive/car/tests/test_fw_fingerprint.py index 2a47c60bf3d18b..cda241c73f049a 100755 --- a/selfdrive/car/tests/test_fw_fingerprint.py +++ b/selfdrive/car/tests/test_fw_fingerprint.py @@ -37,40 +37,44 @@ def test_fw_fingerprint(self, brand, car_model, ecus): self.assertFingerprints(matches, car_model) def test_no_duplicate_fw_versions(self): + passed = True for car_model, ecus in FW_VERSIONS.items(): - with self.subTest(car_model=car_model): - for ecu, ecu_fw in ecus.items(): - with self.subTest(ecu): - duplicates = {fw for fw in ecu_fw if ecu_fw.count(fw) > 1} - self.assertFalse(len(duplicates), f"{car_model}: Duplicate FW versions: Ecu.{ECU_NAME[ecu[0]]}, {duplicates}") + for ecu, ecu_fw in ecus.items(): + duplicates = {fw for fw in ecu_fw if ecu_fw.count(fw) > 1} + if len(duplicates): + print(car_model, ECU_NAME[ecu[0]], duplicates) + passed = False + + self.assertTrue(passed, "Duplicate FW versions found") def test_blacklisted_ecus(self): + passed = True blacklisted_addrs = (0x7c4, 0x7d0) # includes A/C ecu and an unknown ecu for car_model, ecus in FW_VERSIONS.items(): - with self.subTest(car_model=car_model): - CP = interfaces[car_model][0].get_params(car_model) - if CP.carName == 'subaru': - for ecu in ecus.keys(): - self.assertNotIn(ecu[1], blacklisted_addrs, f'{car_model}: Blacklisted ecu: (Ecu.{ECU_NAME[ecu[0]]}, {hex(ecu[1])})') + CP = interfaces[car_model][0].get_params(car_model) + if CP.carName == 'subaru': + for ecu in ecus.keys(): + if ecu[1] in blacklisted_addrs: + print(f'{car_model}: Blacklisted ecu: (Ecu.{ECU_NAME[ecu[0]]}, {hex(ecu[1])})') + passed = False - elif CP.carName == "chrysler": - # Some HD trucks have a combined TCM and ECM - if CP.carFingerprint.startswith("RAM HD"): - for ecu in ecus.keys(): - self.assertNotEqual(ecu[0], Ecu.transmission, f"{car_model}: Blacklisted ecu: (Ecu.{ECU_NAME[ecu[0]]}, {hex(ecu[1])})") + self.assertTrue(passed, "Blacklisted FW versions found") def test_fw_request_ecu_whitelist(self): - for brand in set(r.brand for r in REQUESTS): - with self.subTest(brand=brand): - whitelisted_ecus = [ecu for r in REQUESTS for ecu in r.whitelist_ecus if r.brand == brand] - brand_ecus = set([fw[0] for car_fw in VERSIONS[brand].values() for fw in car_fw]) - - # each ecu in brand's fw versions needs to be whitelisted at least once - ecus_not_whitelisted = set(brand_ecus) - set(whitelisted_ecus) + passed = True + brands = set(r.brand for r in REQUESTS) + for brand in brands: + whitelisted_ecus = [ecu for r in REQUESTS for ecu in r.whitelist_ecus if r.brand == brand] + brand_ecus = set([fw[0] for car_fw in VERSIONS[brand].values() for fw in car_fw]) + # each ecu in brand's fw versions needs to be whitelisted at least once + ecus_not_whitelisted = set(brand_ecus) - set(whitelisted_ecus) + if len(whitelisted_ecus) and len(ecus_not_whitelisted): ecu_strings = ", ".join([f'Ecu.{ECU_NAME[ecu]}' for ecu in ecus_not_whitelisted]) - self.assertFalse(len(whitelisted_ecus) and len(ecus_not_whitelisted), - f'{brand.title()}: FW query whitelist missing ecus: {ecu_strings}') + print(f'{brand.title()}: FW query whitelist missing ecus: {ecu_strings}') + passed = False + + self.assertTrue(passed, "Not all ecus in FW versions found in query whitelists") if __name__ == "__main__": diff --git a/selfdrive/car/tests/test_models.py b/selfdrive/car/tests/test_models.py index cc7d3da874d8e5..502df3fe3f1524 100755 --- a/selfdrive/car/tests/test_models.py +++ b/selfdrive/car/tests/test_models.py @@ -137,7 +137,7 @@ def test_car_params(self): elif tuning == 'indi': self.assertTrue(len(self.CP.lateralTuning.indi.outerLoopGainV)) else: - raise Exception("unknown tuning") + raise Exception("unkown tuning") def test_car_interface(self): # TODO: also check for checksum violations from can parser @@ -234,9 +234,6 @@ def test_panda_safety_carstate(self): checks['gasPressed'] += CS.gasPressed != self.safety.get_gas_pressed_prev() checks['cruiseState'] += CS.cruiseState.enabled and not CS.cruiseState.available - if self.CP.carName in ("honda", "toyota"): - # TODO: fix standstill mismatches for other makes - checks['standstill'] += CS.standstill == self.safety.get_vehicle_moving() # TODO: remove this exception once this mismatch is resolved brake_pressed = CS.brakePressed @@ -266,6 +263,8 @@ def test_panda_safety_carstate(self): if self.CP.carName == "honda": checks['mainOn'] += CS.cruiseState.available != self.safety.get_acc_main_on() + # TODO: fix standstill mismatches for other makes + checks['standstill'] += CS.standstill == self.safety.get_vehicle_moving() CS_prev = CS diff --git a/selfdrive/car/toyota/carstate.py b/selfdrive/car/toyota/carstate.py index 70ba690aa16b64..843e7806dc9bba 100644 --- a/selfdrive/car/toyota/carstate.py +++ b/selfdrive/car/toyota/carstate.py @@ -53,7 +53,7 @@ def update(self, cp, cp_cam): ret.vEgoRaw = mean([ret.wheelSpeeds.fl, ret.wheelSpeeds.fr, ret.wheelSpeeds.rl, ret.wheelSpeeds.rr]) ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw) - ret.standstill = ret.vEgoRaw == 0 + ret.standstill = ret.vEgoRaw < 0.001 ret.steeringAngleDeg = cp.vl["STEER_ANGLE_SENSOR"]["STEER_ANGLE"] + cp.vl["STEER_ANGLE_SENSOR"]["STEER_FRACTION"] torque_sensor_angle_deg = cp.vl["STEER_TORQUE_SENSOR"]["STEER_ANGLE"] diff --git a/selfdrive/car/toyota/interface.py b/selfdrive/car/toyota/interface.py index a0d3ce9b8d9a76..642c39952e3367 100644 --- a/selfdrive/car/toyota/interface.py +++ b/selfdrive/car/toyota/interface.py @@ -218,7 +218,6 @@ def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=[], disabl ret.openpilotLongitudinalControl = smartDsu or ret.enableDsu or candidate in (TSS2_CAR - RADAR_ACC_CAR) if not ret.openpilotLongitudinalControl: - ret.autoResumeSng = False ret.safetyConfigs[0].safetyParam |= Panda.FLAG_TOYOTA_STOCK_LONGITUDINAL # we can't use the fingerprint to detect this reliably, since diff --git a/selfdrive/car/toyota/values.py b/selfdrive/car/toyota/values.py index 42a67ec969c71e..5649e7d65a8b7f 100644 --- a/selfdrive/car/toyota/values.py +++ b/selfdrive/car/toyota/values.py @@ -718,7 +718,6 @@ class ToyotaCarInfo(CarInfo): b'\x03312N6000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203402\x00\x00\x00\x00', b'\x03312N6100\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203302\x00\x00\x00\x00', b'\x03312N6100\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203402\x00\x00\x00\x00', - b'\x03312N6200\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203302\x00\x00\x00\x00', b'\x02312K4000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00', b'\x02312U5000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00', ], diff --git a/selfdrive/car/vin.py b/selfdrive/car/vin.py index ae3aa675c763dd..5ace68649b9c31 100755 --- a/selfdrive/car/vin.py +++ b/selfdrive/car/vin.py @@ -5,6 +5,7 @@ import cereal.messaging as messaging import panda.python.uds as uds +from panda.python.uds import FUNCTIONAL_ADDRS from selfdrive.car.isotp_parallel_query import IsoTpParallelQuery from system.swaglog import cloudlog @@ -23,11 +24,10 @@ def is_valid_vin(vin: str): def get_vin(logcan, sendcan, bus, timeout=0.1, retry=5, debug=False): - addrs = [0x7e0, 0x7e2, 0x18da10f1, 0x18da0ef1] # engine, VMCU, 29-bit engine, PGM-FI for i in range(retry): for request, response in ((UDS_VIN_REQUEST, UDS_VIN_RESPONSE), (OBD_VIN_REQUEST, OBD_VIN_RESPONSE)): try: - query = IsoTpParallelQuery(sendcan, logcan, bus, addrs, [request, ], [response, ], debug=debug) + query = IsoTpParallelQuery(sendcan, logcan, bus, FUNCTIONAL_ADDRS, [request, ], [response, ], functional_addr=True, debug=debug) for (addr, rx_addr), vin in query.get_data(timeout).items(): # Honda Bosch response starts with a length, trim to correct length diff --git a/selfdrive/car/volkswagen/interface.py b/selfdrive/car/volkswagen/interface.py index 6f0bb9a197932c..7e686b970712b3 100644 --- a/selfdrive/car/volkswagen/interface.py +++ b/selfdrive/car/volkswagen/interface.py @@ -197,7 +197,6 @@ def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None, disa else: raise ValueError(f"unsupported car {candidate}") - ret.autoResumeSng = ret.minEnableSpeed == -1 ret.rotationalInertia = scale_rot_inertia(ret.mass, ret.wheelbase) ret.centerToFront = ret.wheelbase * 0.45 ret.tireStiffnessFront, ret.tireStiffnessRear = scale_tire_stiffness(ret.mass, ret.wheelbase, ret.centerToFront, diff --git a/selfdrive/car/volkswagen/values.py b/selfdrive/car/volkswagen/values.py index 278f4bc665f2d9..954b7060c546e5 100755 --- a/selfdrive/car/volkswagen/values.py +++ b/selfdrive/car/volkswagen/values.py @@ -174,7 +174,7 @@ class VWCarInfo(CarInfo): VWCarInfo("Volkswagen CC 2018-22", footnotes=[Footnote.VW_HARNESS, Footnote.VW_VARIANT], harness=Harness.j533, video_link="https://youtu.be/FAomFKPFlDA"), ], CAR.ATLAS_MK1: [ - VWCarInfo("Volkswagen Atlas 2018-23", footnotes=[Footnote.VW_HARNESS], harness=Harness.j533), + VWCarInfo("Volkswagen Atlas 2018-22", footnotes=[Footnote.VW_HARNESS], harness=Harness.j533), VWCarInfo("Volkswagen Atlas Cross Sport 2021-22", footnotes=[Footnote.VW_HARNESS], harness=Harness.j533), VWCarInfo("Volkswagen Teramont 2018-22", footnotes=[Footnote.VW_HARNESS], harness=Harness.j533), VWCarInfo("Volkswagen Teramont Cross Sport 2021-22", footnotes=[Footnote.VW_HARNESS], harness=Harness.j533), @@ -275,7 +275,6 @@ class VWCarInfo(CarInfo): b'\xf1\x8703H906026AA\xf1\x899970', b'\xf1\x8703H906026AJ\xf1\x890638', b'\xf1\x8703H906026AT\xf1\x891922', - b'\xf1\x8703H906026BC\xf1\x892664', b'\xf1\x8703H906026F \xf1\x896696', b'\xf1\x8703H906026F \xf1\x899970', b'\xf1\x8703H906026J \xf1\x896026', @@ -288,14 +287,12 @@ class VWCarInfo(CarInfo): b'\xf1\x8709G927158DR\xf1\x893536', b'\xf1\x8709G927158DR\xf1\x893742', b'\xf1\x8709G927158FT\xf1\x893835', - b'\xf1\x8709G927158GL\xf1\x893939', ], (Ecu.srs, 0x715, None): [ b'\xf1\x873Q0959655BC\xf1\x890503\xf1\x82\0161914151912001103111122031200', b'\xf1\x873Q0959655BN\xf1\x890713\xf1\x82\0162214152212001105141122052900', b'\xf1\x873Q0959655DB\xf1\x890720\xf1\x82\0162214152212001105141122052900', b'\xf1\x873Q0959655DM\xf1\x890732\xf1\x82\x0e1114151112001105161122052J00', - b'\xf1\x873Q0959655DM\xf1\x890732\xf1\x82\x0e1115151112001105171122052J00', ], (Ecu.eps, 0x712, None): [ b'\xf1\x873QF909144B \xf1\x891582\xf1\x82\00571B60924A1', @@ -303,7 +300,6 @@ class VWCarInfo(CarInfo): b'\xf1\x875Q0909143P \xf1\x892051\xf1\x820528B6090105', ], (Ecu.fwdRadar, 0x757, None): [ - b'\xf1\x872Q0907572AA\xf1\x890396', b'\xf1\x872Q0907572R \xf1\x890372', b'\xf1\x872Q0907572T \xf1\x890383', b'\xf1\x875Q0907572H \xf1\x890620', @@ -374,7 +370,6 @@ class VWCarInfo(CarInfo): b'\xf1\x870D9300012 \xf1\x895045', b'\xf1\x870D9300014M \xf1\x895004', b'\xf1\x870D9300014Q \xf1\x895006', - b'\xf1\x870D9300020Q \xf1\x895201', b'\xf1\x870D9300020S \xf1\x895201', b'\xf1\x870D9300040A \xf1\x893613', b'\xf1\x870D9300040S \xf1\x894311', @@ -426,7 +421,6 @@ class VWCarInfo(CarInfo): b'\xf1\x873Q0909144L \xf1\x895081\xf1\x82\x0571A0JA15A1', b'\xf1\x873Q0909144M \xf1\x895082\xf1\x82\x0571A01A18A1', b'\xf1\x873Q0909144M \xf1\x895082\xf1\x82\x0571A0JA16A1', - b'\xf1\x873QM909144 \xf1\x895072\xf1\x82\x0571A01714A1', b'\xf1\x875Q0909143K \xf1\x892033\xf1\x820519A9040203', b'\xf1\x875Q0909144AA\xf1\x891081\xf1\x82\x0521A00441A1', b'\xf1\x875Q0909144AA\xf1\x891081\xf1\x82\x0521A00608A1', diff --git a/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py b/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py index 405ef819162b7d..94efd7a87545d7 100644 --- a/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py +++ b/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py @@ -3,7 +3,7 @@ import numpy as np from common.realtime import sec_since_boot -from common.numpy_fast import clip +from common.numpy_fast import clip, interp from system.swaglog import cloudlog from selfdrive.modeld.constants import index_function from selfdrive.controls.lib.radar_helpers import _LEAD_ACCEL_TAU @@ -20,7 +20,7 @@ EXPORT_DIR = os.path.join(LONG_MPC_DIR, "c_generated_code") JSON_FILE = os.path.join(LONG_MPC_DIR, "acados_ocp_long.json") -SOURCES = ['lead0', 'lead1', 'cruise', 'e2e'] +SOURCES = ['lead0', 'lead1', 'cruise'] X_DIM = 3 U_DIM = 1 @@ -50,7 +50,6 @@ T_IDXS = np.array(T_IDXS_LST) T_DIFFS = np.diff(T_IDXS, prepend=[0.]) MIN_ACCEL = -3.5 -MAX_ACCEL = 2.0 T_FOLLOW = 1.45 COMFORT_BRAKE = 2.5 STOP_DISTANCE = 6.0 @@ -191,8 +190,8 @@ def gen_long_ocp(): class LongitudinalMpc: - def __init__(self, mode='acc'): - self.mode = mode + def __init__(self, e2e=False): + self.e2e = e2e self.solver = AcadosOcpSolverCython(MODEL_NAME, ACADOS_SOLVER_TYPE, N) self.reset() self.source = SOURCES[2] @@ -226,42 +225,49 @@ def reset(self): self.x0 = np.zeros(X_DIM) self.set_weights() - def set_cost_weights(self, cost_weights, constraint_cost_weights): - W = np.asfortranarray(np.diag(cost_weights)) + def set_weights(self, prev_accel_constraint=True): + if self.e2e: + self.set_weights_for_xva_policy() + self.params[:,0] = -10. + self.params[:,1] = 10. + self.params[:,2] = 1e5 + else: + self.set_weights_for_lead_policy(prev_accel_constraint) + + def set_weights_for_lead_policy(self, prev_accel_constraint=True): + a_change_cost = A_CHANGE_COST if prev_accel_constraint else 0 + W = np.asfortranarray(np.diag([X_EGO_OBSTACLE_COST, X_EGO_COST, V_EGO_COST, A_EGO_COST, a_change_cost, J_EGO_COST])) for i in range(N): - # TODO don't hardcode A_CHANGE_COST idx # reduce the cost on (a-a_prev) later in the horizon. - W[4,4] = cost_weights[4] * np.interp(T_IDXS[i], [0.0, 1.0, 2.0], [1.0, 1.0, 0.0]) + W[4,4] = a_change_cost * np.interp(T_IDXS[i], [0.0, 1.0, 2.0], [1.0, 1.0, 0.0]) self.solver.cost_set(i, 'W', W) # Setting the slice without the copy make the array not contiguous, # causing issues with the C interface. self.solver.cost_set(N, 'W', np.copy(W[:COST_E_DIM, :COST_E_DIM])) # Set L2 slack cost on lower bound constraints - Zl = np.array(constraint_cost_weights) + Zl = np.array([LIMIT_COST, LIMIT_COST, LIMIT_COST, DANGER_ZONE_COST]) for i in range(N): self.solver.cost_set(i, 'Zl', Zl) - def set_weights(self, prev_accel_constraint=True): - if self.mode == 'acc': - a_change_cost = A_CHANGE_COST if prev_accel_constraint else 0 - cost_weights = [X_EGO_OBSTACLE_COST, X_EGO_COST, V_EGO_COST, A_EGO_COST, a_change_cost, J_EGO_COST] - constraint_cost_weights = [LIMIT_COST, LIMIT_COST, LIMIT_COST, DANGER_ZONE_COST] - elif self.mode == 'blended': - cost_weights = [0., 0.2, 0.25, 1.0, 0.0, 1.0] - constraint_cost_weights = [LIMIT_COST, LIMIT_COST, LIMIT_COST, 5.0] - elif self.mode == 'e2e': - cost_weights = [0., 0.2, 0.25, 1., 0.0, .1] - constraint_cost_weights = [LIMIT_COST, LIMIT_COST, LIMIT_COST, 0.0] - else: - raise NotImplementedError(f'Planner mode {self.mode} not recognized in planner cost set') - self.set_cost_weights(cost_weights, constraint_cost_weights) + def set_weights_for_xva_policy(self): + W = np.asfortranarray(np.diag([0., 0.2, 0.25, 1., 0.0, .1])) + for i in range(N): + self.solver.cost_set(i, 'W', W) + # Setting the slice without the copy make the array not contiguous, + # causing issues with the C interface. + self.solver.cost_set(N, 'W', np.copy(W[:COST_E_DIM, :COST_E_DIM])) + + # Set L2 slack cost on lower bound constraints + Zl = np.array([LIMIT_COST, LIMIT_COST, LIMIT_COST, 0.0]) + for i in range(N): + self.solver.cost_set(i, 'Zl', Zl) def set_cur_state(self, v, a): v_prev = self.x0[1] self.x0[1] = v self.x0[2] = a - if abs(v_prev - v) > 2.: # probably only helps if v < v_prev + if abs(v_prev - v) > 2.: # probably only helps if v < v_prev for i in range(0, N+1): self.solver.set(i, 'x', self.x0) @@ -300,63 +306,34 @@ def set_accel_limits(self, min_a, max_a): self.cruise_min_a = min_a self.cruise_max_a = max_a - def update(self, carstate, radarstate, v_cruise, x, v, a, j): + def update(self, carstate, radarstate, v_cruise): v_ego = self.x0[1] self.status = radarstate.leadOne.status or radarstate.leadTwo.status lead_xv_0 = self.process_lead(radarstate.leadOne) lead_xv_1 = self.process_lead(radarstate.leadTwo) + # set accel limits in params + self.params[:,0] = interp(float(self.status), [0.0, 1.0], [self.cruise_min_a, MIN_ACCEL]) + self.params[:,1] = self.cruise_max_a + # To estimate a safe distance from a moving lead, we calculate how much stopping # distance that lead needs as a minimum. We can add that to the current distance # and then treat that as a stopped car/obstacle at this new distance. lead_0_obstacle = lead_xv_0[:,0] + get_stopped_equivalence_factor(lead_xv_0[:,1]) lead_1_obstacle = lead_xv_1[:,0] + get_stopped_equivalence_factor(lead_xv_1[:,1]) - # Update in ACC mode or ACC/e2e blend - if self.mode == 'acc': - self.params[:,0] = MIN_ACCEL if self.status else self.cruise_min_a - self.params[:,1] = self.cruise_max_a - - # Fake an obstacle for cruise, this ensures smooth acceleration to set speed - # when the leads are no factor. - v_lower = v_ego + (T_IDXS * self.cruise_min_a * 1.05) - v_upper = v_ego + (T_IDXS * self.cruise_max_a * 1.05) - v_cruise_clipped = np.clip(v_cruise * np.ones(N+1), - v_lower, - v_upper) - cruise_obstacle = np.cumsum(T_DIFFS * v_cruise_clipped) + get_safe_obstacle_distance(v_cruise_clipped) - x_obstacles = np.column_stack([lead_0_obstacle, lead_1_obstacle, cruise_obstacle]) - self.source = SOURCES[np.argmin(x_obstacles[0])] - - # These are not used in ACC mode - x[:], v[:], a[:], j[:] = 0.0, 0.0, 0.0, 0.0 - - elif self.mode == 'blended': - self.params[:,0] = MIN_ACCEL - self.params[:,1] = MAX_ACCEL - - x_obstacles = np.column_stack([lead_0_obstacle, - lead_1_obstacle]) - cruise_target = T_IDXS * v_cruise + x[0] - xforward = ((v[1:] + v[:-1]) / 2) * (T_IDXS[1:] - T_IDXS[:-1]) - x = np.cumsum(np.insert(xforward, 0, x[0])) - - x_and_cruise = np.column_stack([x, cruise_target]) - x = np.min(x_and_cruise, axis=1) - self.source = 'e2e' - - else: - raise NotImplementedError(f'Planner mode {self.mode} not recognized in planner update') - - self.yref[:,1] = x - self.yref[:,2] = v - self.yref[:,3] = a - self.yref[:,5] = j - for i in range(N): - self.solver.set(i, "yref", self.yref[i]) - self.solver.set(N, "yref", self.yref[N][:COST_E_DIM]) - + # Fake an obstacle for cruise, this ensures smooth acceleration to set speed + # when the leads are no factor. + v_lower = v_ego + (T_IDXS * self.cruise_min_a * 1.05) + v_upper = v_ego + (T_IDXS * self.cruise_max_a * 1.05) + v_cruise_clipped = np.clip(v_cruise * np.ones(N+1), + v_lower, + v_upper) + cruise_obstacle = np.cumsum(T_DIFFS * v_cruise_clipped) + get_safe_obstacle_distance(v_cruise_clipped) + + x_obstacles = np.column_stack([lead_0_obstacle, lead_1_obstacle, cruise_obstacle]) + self.source = SOURCES[np.argmin(x_obstacles[0])] self.params[:,2] = np.min(x_obstacles, axis=1) self.params[:,3] = np.copy(self.prev_a) @@ -368,10 +345,6 @@ def update(self, carstate, radarstate, v_cruise, x, v, a, j): self.crash_cnt = 0 def update_with_xva(self, x, v, a): - self.params[:,0] = -10. - self.params[:,1] = 10. - self.params[:,2] = 1e5 - # v, and a are in local frame, but x is wrt the x[0] position # In >90degree turns, x goes to 0 (and may even be -ve) # So, we use integral(v) + x[0] to obtain the forward-distance diff --git a/selfdrive/controls/lib/longitudinal_planner.py b/selfdrive/controls/lib/longitudinal_planner.py index b6120d2451277b..cf511367702902 100755 --- a/selfdrive/controls/lib/longitudinal_planner.py +++ b/selfdrive/controls/lib/longitudinal_planner.py @@ -6,7 +6,6 @@ import cereal.messaging as messaging from common.conversions import Conversions as CV from common.filter_simple import FirstOrderFilter -from common.params import Params from common.realtime import DT_MDL from selfdrive.modeld.constants import T_IDXS from selfdrive.controls.lib.longcontrol import LongCtrlState @@ -48,40 +47,18 @@ def limit_accel_in_turns(v_ego, angle_steers, a_target, CP): class Planner: def __init__(self, CP, init_v=0.0, init_a=0.0): self.CP = CP - params = Params() - # TODO read param in the loop for live toggling - mode = 'blended' if params.get_bool('EndToEndLong') else 'acc' - self.mpc = LongitudinalMpc(mode=mode) + self.mpc = LongitudinalMpc() self.fcw = False self.a_desired = init_a self.v_desired_filter = FirstOrderFilter(init_v, 2.0, DT_MDL) - self.t_uniform = np.arange(0.0, T_IDXS_MPC[-1] + 0.5, 0.5) self.v_desired_trajectory = np.zeros(CONTROL_N) self.a_desired_trajectory = np.zeros(CONTROL_N) self.j_desired_trajectory = np.zeros(CONTROL_N) self.solverExecutionTime = 0.0 - def parse_model(self, model_msg): - if (len(model_msg.position.x) == 33 and - len(model_msg.velocity.x) == 33 and - len(model_msg.acceleration.x) == 33): - x = np.interp(T_IDXS_MPC, T_IDXS, model_msg.position.x) - v = np.interp(T_IDXS_MPC, T_IDXS, model_msg.velocity.x) - a = np.interp(T_IDXS_MPC, T_IDXS, model_msg.acceleration.x) - # Uniform interp so gradient is less noisy - a_sparse = np.interp(self.t_uniform, T_IDXS, model_msg.acceleration.x) - j_sparse = np.gradient(a_sparse, self.t_uniform) - j = np.interp(T_IDXS_MPC, self.t_uniform, j_sparse) - else: - x = np.zeros(len(T_IDXS_MPC)) - v = np.zeros(len(T_IDXS_MPC)) - a = np.zeros(len(T_IDXS_MPC)) - j = np.zeros(len(T_IDXS_MPC)) - return x, v, a, j - def update(self, sm): v_ego = sm['carState'].vEgo @@ -118,16 +95,14 @@ def update(self, sm): self.mpc.set_weights(prev_accel_constraint) self.mpc.set_accel_limits(accel_limits_turns[0], accel_limits_turns[1]) self.mpc.set_cur_state(self.v_desired_filter.x, self.a_desired) - x, v, a, j = self.parse_model(sm['modelV2']) - self.mpc.update(sm['carState'], sm['radarState'], v_cruise, x, v, a, j) + self.mpc.update(sm['carState'], sm['radarState'], v_cruise) self.v_desired_trajectory = np.interp(T_IDXS[:CONTROL_N], T_IDXS_MPC, self.mpc.v_solution) self.a_desired_trajectory = np.interp(T_IDXS[:CONTROL_N], T_IDXS_MPC, self.mpc.a_solution) self.j_desired_trajectory = np.interp(T_IDXS[:CONTROL_N], T_IDXS_MPC[:-1], self.mpc.j_solution) # TODO counter is only needed because radar is glitchy, remove once radar is gone - # TODO write fcw in e2e_long mode - self.fcw = self.mpc.mode == 'acc' and self.mpc.crash_cnt > 5 + self.fcw = self.mpc.crash_cnt > 5 if self.fcw: cloudlog.info("FCW triggered") diff --git a/selfdrive/controls/lib/tests/test_vehicle_model.py b/selfdrive/controls/lib/tests/test_vehicle_model.py index 3e08cb0aa08d30..f2636027e88201 100755 --- a/selfdrive/controls/lib/tests/test_vehicle_model.py +++ b/selfdrive/controls/lib/tests/test_vehicle_model.py @@ -41,7 +41,7 @@ def test_dyn_ss_sol_against_yaw_rate(self): self.assertAlmostEqual(float(yr1), yr2) def test_syn_ss_sol_simulate(self): - """Verifies that dyn_ss_sol matches a simulation""" + """Verifies that dyn_ss_sol mathes a simulation""" for roll in np.linspace(math.radians(-20), math.radians(20), num=11): for u in np.linspace(1, 30, num=10): diff --git a/selfdrive/controls/tests/test_alerts.py b/selfdrive/controls/tests/test_alerts.py index 9ed7eee1228826..79c56d6bc0a952 100755 --- a/selfdrive/controls/tests/test_alerts.py +++ b/selfdrive/controls/tests/test_alerts.py @@ -52,7 +52,7 @@ def test_alert_text_length(self): bold_font_path = os.path.join(font_path, "Inter-Bold.ttf") semibold_font_path = os.path.join(font_path, "Inter-SemiBold.ttf") - max_text_width = 2160 - 300 # full screen width is usable, minus sidebar + max_text_width = 2160 - 300 # full screen width is useable, minus sidebar draw = ImageDraw.Draw(Image.new('RGB', (0, 0))) fonts = { diff --git a/selfdrive/debug/README.md b/selfdrive/debug/README.md index 83b8a994db1a74..f6903170a284ea 100644 --- a/selfdrive/debug/README.md +++ b/selfdrive/debug/README.md @@ -19,7 +19,7 @@ optional arguments: ``` usage: dump.py [-h] [--pipe] [--raw] [--json] [--dump-json] [--no-print] [--addr ADDR] [--values VALUES] [socket [socket ...]] -Dump communication sockets. See cereal/services.py for a complete list of available sockets. +Dump communcation sockets. See cereal/services.py for a complete list of available sockets. positional arguments: socket socket names to dump. defaults to all services defined in cereal diff --git a/selfdrive/debug/cpu_usage_stat.py b/selfdrive/debug/cpu_usage_stat.py index b3294c8728412a..76e809d2c469b9 100755 --- a/selfdrive/debug/cpu_usage_stat.py +++ b/selfdrive/debug/cpu_usage_stat.py @@ -5,8 +5,8 @@ Features: Use psutil library to sample cpu usage(avergage for all cores) of openpilot processes, at a rate of 5 samples/sec. Do cpu usage statistics periodically, 5 seconds as a cycle. - Calculate the average cpu usage within this cycle. - Calculate minumium/maximum/accumulated_average cpu usage as long term inspections. + Caculate the average cpu usage within this cycle. + Caculate minumium/maximium/accumulated_average cpu usage as long term inspections. Monitor multiple processes simuteneously. Sample usage: root@localhost:/data/openpilot$ python selfdrive/debug/cpu_usage_stat.py boardd,ubloxd diff --git a/selfdrive/debug/hyundai_enable_radar_points.py b/selfdrive/debug/hyundai_enable_radar_points.py index ac7e7102d05d31..f182026aa69839 100755 --- a/selfdrive/debug/hyundai_enable_radar_points.py +++ b/selfdrive/debug/hyundai_enable_radar_points.py @@ -6,7 +6,7 @@ in case it's different from the other radars and you need to revert the changes. After changing the config the car should not show any faults when openpilot is not running. -These config changes are persistent across car reboots. You need to run this script again +These config changes are persistent accross car reboots. You need to run this script again to go back to the default values. USE AT YOUR OWN RISK! Safety features, like AEB and FCW, might be affected by these changes.""" diff --git a/selfdrive/debug/internal/power_monitor.py b/selfdrive/debug/internal/power_monitor.py index 34d2a12adcb1c6..09fb89835b03f5 100755 --- a/selfdrive/debug/internal/power_monitor.py +++ b/selfdrive/debug/internal/power_monitor.py @@ -59,6 +59,6 @@ def average(avg, sample): print(f" {(stop_time - start_time).total_seconds():.2f} Seconds {voltage_average[1]} samples") print("----------------------------------------------------------------") - # re-enable charging + # reenable charging os.system('echo "1" > /sys/class/power_supply/battery/charging_enabled') print("charging enabled\n") diff --git a/selfdrive/debug/print_docs_diff.py b/selfdrive/debug/print_docs_diff.py index b80428645873d3..b7721ca3a5abb9 100755 --- a/selfdrive/debug/print_docs_diff.py +++ b/selfdrive/debug/print_docs_diff.py @@ -10,7 +10,7 @@ FOOTNOTE_TAG = "{}" STAR_ICON = '' COLUMNS = "|" + "|".join([column.value for column in Column]) + "|" -COLUMN_HEADER = "|---|---|---|{}|".format("|".join([":---:"] * (len(Column) - 3))) +COLUMN_HEADER = "|---|---|---|:---:|:---:|:---:|:---:|" ARROW_SYMBOL = "➡️" @@ -81,6 +81,10 @@ def print_car_info_diff(path): changes["additions"].append(format_row([car_info.get_column(column, STAR_ICON, FOOTNOTE_TAG) for column in Column])) for new_car, base_car in car_changes: + # Tier changes + if base_car.tier != new_car.tier: + changes["tier"].append(f"- Tier for {base_car.name} changed! ({base_car.tier.name.title()} {ARROW_SYMBOL} {new_car.tier.name.title()})") + # Column changes row_diff = build_column_diff(base_car, new_car) if ARROW_SYMBOL in row_diff: @@ -98,10 +102,10 @@ def print_car_info_diff(path): if any(len(c) for c in changes.values()): markdown_builder = ["### ⚠️ This PR makes changes to [CARS.md](../blob/master/docs/CARS.md) ⚠️"] - for title, category in (("## 🔀 Column Changes", "column"), ("## ❌ Removed", "removals"), ("## ➕ Added", "additions"), ("## 📖 Detail Sentence Changes", "detail")): + for title, category in (("## 🏅 Tier Changes", "tier"), ("## 🔀 Column Changes", "column"), ("## ❌ Removed", "removals"), ("## ➕ Added", "additions"), ("## 📖 Detail Sentence Changes", "detail")): if len(changes[category]): markdown_builder.append(title) - if category not in ("detail",): + if category not in ("tier", "detail"): markdown_builder.append(COLUMNS) markdown_builder.append(COLUMN_HEADER) markdown_builder.extend(changes[category]) diff --git a/selfdrive/debug/test_fw_query_on_routes.py b/selfdrive/debug/test_fw_query_on_routes.py index 595e25e8c3242f..868813b0feba29 100755 --- a/selfdrive/debug/test_fw_query_on_routes.py +++ b/selfdrive/debug/test_fw_query_on_routes.py @@ -56,7 +56,7 @@ qlog_path = f"cd:/{dongle_id}/{time}/0/qlog.bz2" else: route = Route(route) - qlog_path = next((p for p in route.qlog_paths() if p is not None), None) + qlog_path = route.qlog_paths()[0] if qlog_path is None: continue @@ -168,7 +168,7 @@ break print() - # Print FW versions that need to be added separated out by car and address + # Print FW versions that need to be added seperated out by car and address for car, m in sorted(mismatches.items()): print(car) addrs = defaultdict(list) diff --git a/selfdrive/locationd/laikad.py b/selfdrive/locationd/laikad.py index c7f2d2ceac1f8e..830eb3320729d4 100755 --- a/selfdrive/locationd/laikad.py +++ b/selfdrive/locationd/laikad.py @@ -28,7 +28,7 @@ MAX_TIME_GAP = 10 EPHEMERIS_CACHE = 'LaikadEphemeris' -DOWNLOADS_CACHE_FOLDER = "/tmp/comma_download_cache/" +DOWNLOADS_CACHE_FOLDER = "/tmp/comma_download_cache" CACHE_VERSION = 0.1 POS_FIX_RESIDUAL_THRESHOLD = 100.0 diff --git a/selfdrive/locationd/locationd.cc b/selfdrive/locationd/locationd.cc index 2fb3e0081d8378..7714931b949d99 100755 --- a/selfdrive/locationd/locationd.cc +++ b/selfdrive/locationd/locationd.cc @@ -476,9 +476,9 @@ bool Localizer::isGpsOK() { } void Localizer::determine_gps_mode(double current_time) { - // 1. If the pos_std is greater than what's not acceptable and localizer is in gps-mode, reset to no-gps-mode - // 2. If the pos_std is greater than what's not acceptable and localizer is in no-gps-mode, fake obs - // 3. If the pos_std is smaller than what's not acceptable, let gps-mode be whatever it is + // 1. If the pos_std is greater than what's not acceptible and localizer is in gps-mode, reset to no-gps-mode + // 2. If the pos_std is greater than what's not acceptible and localizer is in no-gps-mode, fake obs + // 3. If the pos_std is smaller than what's not acceptible, let gps-mode be whatever it is VectorXd current_pos_std = this->kf->get_P().block(STATE_ECEF_POS_ERR_START, STATE_ECEF_POS_ERR_START).diagonal().array().sqrt(); if (current_pos_std.norm() > SANE_GPS_UNCERTAINTY){ if (this->gps_mode){ diff --git a/selfdrive/locationd/models/loc_kf.py b/selfdrive/locationd/models/loc_kf.py index 4c947422b15cc9..25bf36d2cb3535 100755 --- a/selfdrive/locationd/models/loc_kf.py +++ b/selfdrive/locationd/models/loc_kf.py @@ -33,7 +33,7 @@ class States(): ACCELEROMETER_BIAS = slice(30, 33) # bias of mems accelerometer # TODO the offset is likely a translation of the sensor, not a rotation of the camera WIDE_FROM_DEVICE_EULER = slice(33, 36) # wide camera offset angles in radians (tici only) - # We currently do not use ACCELEROMETER_SCALE to avoid instability due to too many free variables (ACCELEROMETER_SCALE, ACCELEROMETER_BIAS, IMU_FROM_DEVICE_EULER). + # We curently do not use ACCELEROMETER_SCALE to avoid instability due to too many free variables (ACCELEROMETER_SCALE, ACCELEROMETER_BIAS, IMU_FROM_DEVICE_EULER). # From experiments we see that ACCELEROMETER_BIAS is more correct than ACCELEROMETER_SCALE # Error-state has different slices because it is an ESKF diff --git a/selfdrive/locationd/test/ubloxd.py b/selfdrive/locationd/test/ubloxd.py index 82aa502ceb4652..b0339851d43b3e 100755 --- a/selfdrive/locationd/test/ubloxd.py +++ b/selfdrive/locationd/test/ubloxd.py @@ -65,7 +65,7 @@ def configure_ublox(dev): print("backup restore polling message (implement custom response handler!):") dev.configure_poll(0x09, 0x14) - print("if successful, send this to clear the flash:") + print("if succesfull, send this to clear the flash:") dev.send_message(0x09, 0x14, b"\x01\x00\x00\x00") print("send on stop:") diff --git a/selfdrive/loggerd/bootlog.cc b/selfdrive/loggerd/bootlog.cc index 6ff052655a465a..90ba487ff0984e 100644 --- a/selfdrive/loggerd/bootlog.cc +++ b/selfdrive/loggerd/bootlog.cc @@ -26,13 +26,10 @@ static kj::Array build_boot_log() { // Gather output of commands std::vector bootlog_commands = { + "[ -e /dev/nvme0 ] && sudo nvme smart-log --output-format=json /dev/nvme0", "[ -x \"$(command -v journalctl)\" ] && journalctl", }; - if (Hardware::TICI()) { - bootlog_commands.push_back("[ -e /dev/nvme0 ] && sudo nvme smart-log --output-format=json /dev/nvme0"); - } - auto commands = boot.initCommands().initEntries(bootlog_commands.size()); for (int j = 0; j < bootlog_commands.size(); j++) { auto lentry = commands[j]; diff --git a/selfdrive/loggerd/logger.cc b/selfdrive/loggerd/logger.cc index aaf267e523a593..da3710cc72a69b 100644 --- a/selfdrive/loggerd/logger.cc +++ b/selfdrive/loggerd/logger.cc @@ -182,7 +182,7 @@ int logger_next(LoggerState *s, const char* root_path, pthread_mutex_unlock(&s->lock); - // write beginning of log metadata + // write beggining of log metadata log_init_data(s); lh_log_sentinel(s->cur_handle, is_start_of_route ? SentinelType::START_OF_ROUTE : SentinelType::START_OF_SEGMENT); return 0; diff --git a/selfdrive/loggerd/tests/test_logger.cc b/selfdrive/loggerd/tests/test_logger.cc index 18a0e57df75da9..c8f6620924c9d6 100644 --- a/selfdrive/loggerd/tests/test_logger.cc +++ b/selfdrive/loggerd/tests/test_logger.cc @@ -47,7 +47,7 @@ void verify_segment(const std::string &route_path, int segment, int max_segment, } ++i; } catch (const kj::Exception &ex) { - INFO("failed parse " << i << " exception :" << ex.getDescription()); + INFO("failed parse " << i << " excpetion :" << ex.getDescription()); REQUIRE(0); break; } diff --git a/selfdrive/loggerd/tests/test_loggerd.py b/selfdrive/loggerd/tests/test_loggerd.py index b0907c54af0934..9dbc7ac332af94 100755 --- a/selfdrive/loggerd/tests/test_loggerd.py +++ b/selfdrive/loggerd/tests/test_loggerd.py @@ -186,7 +186,7 @@ def test_qlog(self): pm = messaging.PubMaster(services) # sleep enough for the first poll to time out - # TODO: fix loggerd bug dropping the msgs from the first poll + # TOOD: fix loggerd bug dropping the msgs from the first poll managed_processes["loggerd"].start() for s in services: while not pm.all_readers_updated(s): diff --git a/selfdrive/manager/build.py b/selfdrive/manager/build.py index c8a7d415398b04..12f894061a8061 100755 --- a/selfdrive/manager/build.py +++ b/selfdrive/manager/build.py @@ -15,7 +15,7 @@ MAX_CACHE_SIZE = 4e9 if "CI" in os.environ else 2e9 CACHE_DIR = Path("/data/scons_cache" if AGNOS else "/tmp/scons_cache") -TOTAL_SCONS_NODES = 2395 +TOTAL_SCONS_NODES = 2035 MAX_BUILD_PROGRESS = 100 PREBUILT = os.path.exists(os.path.join(BASEDIR, 'prebuilt')) diff --git a/selfdrive/manager/helpers.py b/selfdrive/manager/helpers.py index 983c7cc0b16c56..b07362dd4d39f2 100644 --- a/selfdrive/manager/helpers.py +++ b/selfdrive/manager/helpers.py @@ -33,6 +33,6 @@ def unblock_stdout() -> None: pass # os.wait() returns a tuple with the pid and a 16 bit value - # whose low byte is the signal number and whose high byte is the exit status + # whose low byte is the signal number and whose high byte is the exit satus exit_status = os.wait()[1] >> 8 os._exit(exit_status) diff --git a/selfdrive/modeld/SConscript b/selfdrive/modeld/SConscript index 246f8c2941575b..a108e2c9d5940d 100644 --- a/selfdrive/modeld/SConscript +++ b/selfdrive/modeld/SConscript @@ -23,9 +23,9 @@ common_src = [ ] thneed_src = [ - "thneed/thneed_common.cc", - "thneed/thneed_qcom2.cc", + "thneed/thneed.cc", "thneed/serialize.cc", + "thneed/optimizer.cc", "runners/thneedmodel.cc", ] @@ -61,53 +61,25 @@ else: common_model = lenv.Object(common_src) +# build thneed model +if use_thneed and arch == "larch64": + fn = File("models/supercombo").abspath + compiler = lenv.Program('thneed/compile', ["thneed/compile.cc"]+common_model, LIBS=libs) + cmd = f"cd {Dir('.').abspath} && {compiler[0].abspath} --in {fn}.dlc --out {fn}.thneed --binary --optimize" + + lib_paths = ':'.join(Dir(p).abspath for p in lenv["LIBPATH"]) + kernel_path = os.path.join(Dir('.').abspath, "thneed", "kernels") + cenv = Environment(ENV={'LD_LIBRARY_PATH': f"{lib_paths}:{lenv['ENV']['LD_LIBRARY_PATH']}", 'KERNEL_PATH': kernel_path}) + + kernels = [os.path.join(kernel_path, x) for x in os.listdir(kernel_path) if x.endswith(".cl")] + cenv.Command(fn + ".thneed", [fn + ".dlc", kernels, compiler], cmd) + lenv.Program('_dmonitoringmodeld', [ "dmonitoringmodeld.cc", "models/dmonitoring.cc", ]+common_model, LIBS=libs) -# build thneed model -if use_thneed and arch == "larch64" or GetOption('pc_thneed'): - fn = File("models/supercombo").abspath - - if GetOption('pc_thneed'): - cmd = f"cd {Dir('#').abspath}/tinygrad_repo && NATIVE_EXPLOG=1 OPTWG=1 UNSAFE_FLOAT4=1 DEBUGCL=1 python3 openpilot/compile.py {fn}.onnx {fn}.thneed" - else: - cmd = f"cd {Dir('#').abspath}/tinygrad_repo && FLOAT16=1 PYOPENCL_NO_CACHE=1 MATMUL=1 NATIVE_EXPLOG=1 OPTWG=1 UNSAFE_FLOAT4=1 DEBUGCL=1 python3 openpilot/compile.py {fn}.onnx {fn}.thneed" - - # is there a better way then listing all of tinygrad? - lenv.Command(fn + ".thneed", [fn + ".onnx", - "#tinygrad_repo/openpilot/compile.py", - "#tinygrad_repo/accel/opencl/conv.cl", - "#tinygrad_repo/accel/opencl/matmul.cl", - "#tinygrad_repo/accel/opencl/ops_opencl.py", - "#tinygrad_repo/accel/opencl/preprocessing.py", - "#tinygrad_repo/extra/onnx.py", - "#tinygrad_repo/extra/utils.py", - "#tinygrad_repo/tinygrad/llops/ops_gpu.py", - "#tinygrad_repo/tinygrad/llops/ops_opencl.py", - "#tinygrad_repo/tinygrad/helpers.py", - "#tinygrad_repo/tinygrad/mlops.py", - "#tinygrad_repo/tinygrad/ops.py", - "#tinygrad_repo/tinygrad/shapetracker.py", - "#tinygrad_repo/tinygrad/tensor.py", - "#tinygrad_repo/tinygrad/nn/__init__.py" - ], cmd) - -llenv = lenv.Clone() -if GetOption('pc_thneed'): - pc_thneed_src = [ - "thneed/thneed_common.cc", - "thneed/thneed_pc.cc", - "thneed/serialize.cc", - "runners/thneedmodel.cc", - ] - llenv['CFLAGS'].append("-DUSE_THNEED") - llenv['CXXFLAGS'].append("-DUSE_THNEED") - common_model += llenv.Object(pc_thneed_src) - libs += ['dl'] - -llenv.Program('_modeld', [ +lenv.Program('_modeld', [ "modeld.cc", "models/driving.cc", ]+common_model, LIBS=libs + transformations) diff --git a/selfdrive/modeld/models/driving.cc b/selfdrive/modeld/models/driving.cc index 8d02eb6b2f1d36..8bfe584725ab5c 100644 --- a/selfdrive/modeld/models/driving.cc +++ b/selfdrive/modeld/models/driving.cc @@ -38,7 +38,7 @@ void model_init(ModelState* s, cl_device_id device_id, cl_context context) { #else s->m = std::make_unique("models/supercombo.dlc", #endif - &s->output[0], NET_OUTPUT_SIZE, USE_GPU_RUNTIME, true, false, context); + &s->output[0], NET_OUTPUT_SIZE, USE_GPU_RUNTIME, true); #ifdef TEMPORAL s->m->addRecurrent(&s->output[OUTPUT_SIZE], TEMPORAL_SIZE); @@ -203,7 +203,6 @@ void fill_plan(cereal::ModelDataV2::Builder &framed, const ModelOutputPlanPredic std::array pos_x_std, pos_y_std, pos_z_std; std::array vel_x, vel_y, vel_z; std::array rot_x, rot_y, rot_z; - std::array acc_x, acc_y, acc_z; std::array rot_rate_x, rot_rate_y, rot_rate_z; for(int i=0; i SNPEModel::addExtra(float *state, in } void SNPEModel::execute() { - bool ret = inputBuffer->setBufferAddress(input); - assert(ret == true); - if (use_extra) { - bool extra_ret = extraBuffer->setBufferAddress(extra); - assert(extra_ret == true); - } - if (!snpe->execute(inputMap, outputMap)) { - PrintErrorStringAndExit(); +#ifdef USE_THNEED + if (Runtime == zdl::DlSystem::Runtime_t::GPU) { + if (!thneed_recorded) { + bool ret = inputBuffer->setBufferAddress(input); + assert(ret == true); + if (use_extra) { + assert(extra != NULL); + bool extra_ret = extraBuffer->setBufferAddress(extra); + assert(extra_ret == true); + } + if (!snpe->execute(inputMap, outputMap)) { + PrintErrorStringAndExit(); + } + memset(recurrent, 0, recurrent_size*sizeof(float)); + thneed->record = true; + if (!snpe->execute(inputMap, outputMap)) { + PrintErrorStringAndExit(); + } + thneed->stop(); + printf("thneed cached\n"); + + // doing self test + float *outputs_golden = (float *)malloc(output_size*sizeof(float)); + memcpy(outputs_golden, output, output_size*sizeof(float)); + memset(output, 0, output_size*sizeof(float)); + memset(recurrent, 0, recurrent_size*sizeof(float)); + uint64_t start_time = nanos_since_boot(); + if (extra != NULL) { + float *inputs[5] = {recurrent, trafficConvention, desire, extra, input}; + thneed->execute(inputs, output); + } else { + float *inputs[4] = {recurrent, trafficConvention, desire, input}; + thneed->execute(inputs, output); + } + uint64_t elapsed_time = nanos_since_boot() - start_time; + printf("ran model in %.2f ms\n", float(elapsed_time)/1e6); + + if (memcmp(output, outputs_golden, output_size*sizeof(float)) == 0) { + printf("thneed selftest passed\n"); + } else { + for (int i = 0; i < output_size; i++) { + printf("mismatch %3d: %f %f\n", i, output[i], outputs_golden[i]); + } + assert(false); + } + free(outputs_golden); + thneed_recorded = true; + } else { + if (use_extra) { + float *inputs[5] = {recurrent, trafficConvention, desire, extra, input}; + thneed->execute(inputs, output); + } else { + float *inputs[4] = {recurrent, trafficConvention, desire, input}; + thneed->execute(inputs, output); + } + } + } else { +#endif + bool ret = inputBuffer->setBufferAddress(input); + assert(ret == true); + if (use_extra) { + bool extra_ret = extraBuffer->setBufferAddress(extra); + assert(extra_ret == true); + } + if (!snpe->execute(inputMap, outputMap)) { + PrintErrorStringAndExit(); + } +#ifdef USE_THNEED } +#endif } diff --git a/selfdrive/modeld/runners/snpemodel.h b/selfdrive/modeld/runners/snpemodel.h index 08ae16c2b1598f..ed9d58d1e11335 100644 --- a/selfdrive/modeld/runners/snpemodel.h +++ b/selfdrive/modeld/runners/snpemodel.h @@ -23,7 +23,7 @@ class SNPEModel : public RunModel { public: - SNPEModel(const char *path, float *loutput, size_t loutput_size, int runtime, bool luse_extra = false, bool use_tf8 = false, cl_context context = NULL); + SNPEModel(const char *path, float *loutput, size_t loutput_size, int runtime, bool luse_extra = false, bool use_tf8 = false); void addRecurrent(float *state, int state_size); void addTrafficConvention(float *state, int state_size); void addCalib(float *state, int state_size); diff --git a/selfdrive/modeld/runners/thneedmodel.cc b/selfdrive/modeld/runners/thneedmodel.cc index 67db01bb952cf1..dbe80a9463b1d2 100644 --- a/selfdrive/modeld/runners/thneedmodel.cc +++ b/selfdrive/modeld/runners/thneedmodel.cc @@ -2,10 +2,11 @@ #include -ThneedModel::ThneedModel(const char *path, float *loutput, size_t loutput_size, int runtime, bool luse_extra, bool luse_tf8, cl_context context) { - thneed = new Thneed(true, context); +ThneedModel::ThneedModel(const char *path, float *loutput, size_t loutput_size, int runtime, bool luse_extra) { + thneed = new Thneed(true); thneed->load(path); thneed->clexec(); + thneed->find_inputs_outputs(); recorded = false; output = loutput; diff --git a/selfdrive/modeld/runners/thneedmodel.h b/selfdrive/modeld/runners/thneedmodel.h index f3f34dc7f4bac4..fe0f9ae44fb287 100644 --- a/selfdrive/modeld/runners/thneedmodel.h +++ b/selfdrive/modeld/runners/thneedmodel.h @@ -5,7 +5,7 @@ class ThneedModel : public RunModel { public: - ThneedModel(const char *path, float *loutput, size_t loutput_size, int runtime, bool luse_extra = false, bool use_tf8 = false, cl_context context = NULL); + ThneedModel(const char *path, float *loutput, size_t loutput_size, int runtime, bool luse_extra = false); void addRecurrent(float *state, int state_size); void addTrafficConvention(float *state, int state_size); void addDesire(float *state, int state_size); diff --git a/selfdrive/modeld/thneed/compile.cc b/selfdrive/modeld/thneed/compile.cc new file mode 100644 index 00000000000000..f76c63b2b917cd --- /dev/null +++ b/selfdrive/modeld/thneed/compile.cc @@ -0,0 +1,81 @@ +#include +#include + +#include "selfdrive/modeld/runners/snpemodel.h" +#include "selfdrive/modeld/thneed/thneed.h" +#include "system/hardware/hw.h" + +#define TEMPORAL_SIZE 512 +#define DESIRE_LEN 8 +#define TRAFFIC_CONVENTION_LEN 2 + +// TODO: This should probably use SNPE directly. +int main(int argc, char* argv[]) { + bool run_optimizer = false, save_binaries = false; + const char *input_file = NULL, *output_file = NULL; + static struct option long_options[] = { + {"in", required_argument, 0, 'i' }, + {"out", required_argument, 0, 'o' }, + {"binary", no_argument, 0, 'b' }, + {"optimize", no_argument, 0, 'f' }, + {0, 0, 0, 0 } + }; + int long_index = 0, opt = 0; + while ((opt = getopt_long_only(argc, argv,"", long_options, &long_index)) != -1) { + switch (opt) { + case 'i': input_file = optarg; break; + case 'o': output_file = optarg; break; + case 'b': save_binaries = true; break; + case 'f': run_optimizer = true; break; + } + } + + // no input? + if (!input_file) { + printf("usage: -i -o --binary --optimize\n"); + return -1; + } + + #define OUTPUT_SIZE 0x10000 + + float *output = (float*)calloc(OUTPUT_SIZE, sizeof(float)); + SNPEModel mdl(input_file, output, 0, USE_GPU_RUNTIME, true); + mdl.thneed->run_optimizer = run_optimizer; + + float state[TEMPORAL_SIZE] = {0}; + float desire[DESIRE_LEN] = {0}; + float traffic_convention[TRAFFIC_CONVENTION_LEN] = {0}; + float *input = (float*)calloc(0x1000000, sizeof(float)); + float *extra = (float*)calloc(0x1000000, sizeof(float)); + + mdl.addRecurrent(state, TEMPORAL_SIZE); + mdl.addDesire(desire, DESIRE_LEN); + mdl.addTrafficConvention(traffic_convention, TRAFFIC_CONVENTION_LEN); + mdl.addImage(input, 0); + mdl.addExtra(extra, 0); + + // first run + printf("************** execute 1 **************\n"); + memset(output, 0, OUTPUT_SIZE * sizeof(float)); + mdl.execute(); + + // don't save? + if (!output_file) { + printf("no output file, exiting\n"); + return 0; + } + + // save model + printf("saving %s with binary %d\n", output_file, save_binaries); + mdl.thneed->save(output_file, save_binaries); + + // test model + auto thneed = new Thneed(true); + thneed->record = false; + thneed->load(output_file); + thneed->clexec(); + thneed->find_inputs_outputs(); + + return 0; +} + diff --git a/selfdrive/modeld/thneed/kernels/convolution_.cl b/selfdrive/modeld/thneed/kernels/convolution_.cl new file mode 100644 index 00000000000000..1b9d74b83f433a --- /dev/null +++ b/selfdrive/modeld/thneed/kernels/convolution_.cl @@ -0,0 +1,272 @@ + read_only image2d_t input, +#ifndef DEPTHWISE + short startPackedInputChannel, + short numPackedInputChannelsForGroup, short totalNumPackedInputChannels, + // typo required for API compatibility + short packedOuputChannelOffset, short totalNumPackedOutputChannels, +#else + short totalNumPackedChannels, +#endif + read_only image2d_t weights, __constant float *biases, + short filterSizeX, short filterSizeY, + write_only image2d_t output, + short paddingX, short paddingY, short strideX, short strideY, +#ifdef SUPPORT_DILATION + short dilationX, short dilationY, +#endif + short neuron, float a, float b, float min_clamp, float max_clamp, +#ifndef DEPTHWISE + // note: these are not supported + __constant float *parameters, __constant float *batchNormBiases, +#endif + short numOutputColumns +#ifdef SUPPORT_ACCUMULATION + , short doAccumulate, read_only image2d_t accumulator +#endif + ) { + +#ifndef NUM_OUTPUTS + #define NUM_OUTPUTS 4 +#endif + + // init + const sampler_t smp = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP | CLK_FILTER_NEAREST; + short packedOutputChannel = get_global_id(0); + short startOutputColumn = mul24((short)get_global_id(1), NUM_OUTPUTS); + short outputRow = get_global_id(2); + +#ifdef DEPTHWISE + short totalNumPackedInputChannels = totalNumPackedChannels; + short totalNumPackedOutputChannels = totalNumPackedChannels; + short startPackedInputChannel = packedOutputChannel; +#endif + + short startX = mad24(mad24(startOutputColumn, strideX, -paddingX), totalNumPackedInputChannels, startPackedInputChannel); + short strideWithChannels = mul24(strideX, totalNumPackedInputChannels); + + float4 outputValues[NUM_OUTPUTS]; + for (short i = 0; i < NUM_OUTPUTS; ++i) { + outputValues[i] = (float4)(0, 0, 0, 0); + } + + int2 inputLocation; + inputLocation.y = mad24(outputRow, strideY, -paddingY); + + int2 weightLocation; + weightLocation.x = 0; + weightLocation.y = packedOutputChannel; + +#ifdef DEPTHWISE + +#ifdef SUPPORT_DILATION + + // depthwise convolution + for (short rfRow = 0; rfRow < filterSizeY; ++rfRow) { + for (short rfColumn = 0; rfColumn < filterSizeX; ++rfColumn) { + short dilatedStepX = mul24(totalNumPackedChannels, dilationX); + inputLocation.x = mad24(rfColumn, dilatedStepX, startX); + float4 inputValues[4]; + for (short i = 0; i < 4; ++i) { + inputValues[i] = read_imagef(input, smp, inputLocation); + inputLocation.x += strideWithChannels; + } + float4 weightValues = read_imagef(weights, smp, weightLocation); + ++weightLocation.x; + outputValues[0] += inputValues[0] * weightValues; + outputValues[1] += inputValues[1] * weightValues; + outputValues[2] += inputValues[2] * weightValues; + outputValues[3] += inputValues[3] * weightValues; + } + inputLocation.y += dilationY; + } + +#else + + // depthwise unstrided convolution + for (short rfRow = 0; rfRow < filterSizeY; ++rfRow) { + float4 inputValues[4]; + inputLocation.x = startX; + for (short i = 1; i < 4; ++i) { + inputValues[i] = read_imagef(input, smp, inputLocation); + inputLocation.x += totalNumPackedOutputChannels; + } + for (short rfColumn = 0; rfColumn < filterSizeX; ++rfColumn) { + inputValues[0] = inputValues[1]; + inputValues[1] = inputValues[2]; + inputValues[2] = inputValues[3]; + inputValues[3] = read_imagef(input, smp, inputLocation); + inputLocation.x += totalNumPackedChannels; + float4 weightValues = read_imagef(weights, smp, weightLocation); + ++weightLocation.x; + outputValues[0] += inputValues[0] * weightValues; + outputValues[1] += inputValues[1] * weightValues; + outputValues[2] += inputValues[2] * weightValues; + outputValues[3] += inputValues[3] * weightValues; + } + ++inputLocation.y; + } + +#endif + +#elif defined(ONLY_1X1_CONV) + + // 1x1 convolution + short endPackedInputChannel = startPackedInputChannel + numPackedInputChannelsForGroup; + for (short packedInputChannel = startPackedInputChannel; packedInputChannel < endPackedInputChannel; ++packedInputChannel) { + float4 weightValues[4]; + for (short outChIdx = 0; outChIdx < 4; ++outChIdx) { + weightValues[outChIdx] = read_imagef(weights, smp, weightLocation); + ++weightLocation.x; + } + + inputLocation.x = startX + packedInputChannel; + float4 inputValues[NUM_OUTPUTS]; + for (short i = 0; i < NUM_OUTPUTS; ++i) { + inputValues[i] = read_imagef(input, smp, inputLocation); + inputLocation.x += strideWithChannels; + } + + for (short i = 0; i < NUM_OUTPUTS; ++i) { + float4 curOutputValues = outputValues[i]; + curOutputValues.x += inputValues[i].x * weightValues[0].x; + curOutputValues.x += inputValues[i].y * weightValues[0].y; + curOutputValues.x += inputValues[i].z * weightValues[0].z; + curOutputValues.x += inputValues[i].w * weightValues[0].w; + curOutputValues.y += inputValues[i].x * weightValues[1].x; + curOutputValues.y += inputValues[i].y * weightValues[1].y; + curOutputValues.y += inputValues[i].z * weightValues[1].z; + curOutputValues.y += inputValues[i].w * weightValues[1].w; + curOutputValues.z += inputValues[i].x * weightValues[2].x; + curOutputValues.z += inputValues[i].y * weightValues[2].y; + curOutputValues.z += inputValues[i].z * weightValues[2].z; + curOutputValues.z += inputValues[i].w * weightValues[2].w; + curOutputValues.w += inputValues[i].x * weightValues[3].x; + curOutputValues.w += inputValues[i].y * weightValues[3].y; + curOutputValues.w += inputValues[i].z * weightValues[3].z; + curOutputValues.w += inputValues[i].w * weightValues[3].w; + outputValues[i] = curOutputValues; + } + } + packedOutputChannel += packedOuputChannelOffset; + +#else + + // normal convolution + for (short rfRow = 0; rfRow < filterSizeY; ++rfRow) { + for (short packedInputChannel = 0; packedInputChannel < numPackedInputChannelsForGroup; ++packedInputChannel) { + short startXForChannel = startX + packedInputChannel; + for (short rfColumn = 0; rfColumn < filterSizeX; ++rfColumn) { + + float4 weightValues[4]; + for (short outChIdx = 0; outChIdx < 4; ++outChIdx) { + weightValues[outChIdx] = read_imagef(weights, smp, weightLocation); + ++weightLocation.x; + } + +#ifdef SUPPORT_DILATION + short dilatedStepX = mul24(totalNumPackedInputChannels, dilationX); + inputLocation.x = mad24(rfColumn, dilatedStepX, startXForChannel); +#else + inputLocation.x = mad24(rfColumn, totalNumPackedInputChannels, startXForChannel); +#endif + float4 inputValues[NUM_OUTPUTS]; + for (short i = 0; i < NUM_OUTPUTS; ++i) { + inputValues[i] = read_imagef(input, smp, inputLocation); + inputLocation.x += strideWithChannels; + } + for (short i = 0; i < NUM_OUTPUTS; ++i) { + float4 curOutputValues = outputValues[i]; + curOutputValues.x += inputValues[i].x * weightValues[0].x; + curOutputValues.x += inputValues[i].y * weightValues[0].y; + curOutputValues.x += inputValues[i].z * weightValues[0].z; + curOutputValues.x += inputValues[i].w * weightValues[0].w; + curOutputValues.y += inputValues[i].x * weightValues[1].x; + curOutputValues.y += inputValues[i].y * weightValues[1].y; + curOutputValues.y += inputValues[i].z * weightValues[1].z; + curOutputValues.y += inputValues[i].w * weightValues[1].w; + curOutputValues.z += inputValues[i].x * weightValues[2].x; + curOutputValues.z += inputValues[i].y * weightValues[2].y; + curOutputValues.z += inputValues[i].z * weightValues[2].z; + curOutputValues.z += inputValues[i].w * weightValues[2].w; + curOutputValues.w += inputValues[i].x * weightValues[3].x; + curOutputValues.w += inputValues[i].y * weightValues[3].y; + curOutputValues.w += inputValues[i].z * weightValues[3].z; + curOutputValues.w += inputValues[i].w * weightValues[3].w; + outputValues[i] = curOutputValues; + } + } + } +#ifdef SUPPORT_DILATION + inputLocation.y += dilationY; +#else + ++inputLocation.y; +#endif + } + packedOutputChannel += packedOuputChannelOffset; +#endif + + // bias + short outputChannel = mul24(packedOutputChannel, 4); + float4 biasValues = vload4(0, biases + outputChannel); + for (short i = 0; i < NUM_OUTPUTS; ++i) { + outputValues[i] += biasValues; + } + +#ifdef SUPPORT_ACCUMULATION + // accumulate + if (doAccumulate) { + int2 outputLocation; + short outputColumn = startOutputColumn; + outputLocation.y = outputRow; + for (short i = 0; i < NUM_OUTPUTS; ++i) { + outputLocation.x = mad24(outputColumn, totalNumPackedOutputChannels, packedOutputChannel); + if (outputColumn < numOutputColumns) { + outputValues[i] += read_imagef(accumulator, smp, outputLocation); + } + ++outputColumn; + } + } +#endif + + // activation + switch (neuron) { + case 1: + for (short i = 0; i < NUM_OUTPUTS; ++i) { + outputValues[i] = max(outputValues[i], 0.0f); + } + break; + case 2: + for (short i = 0; i < NUM_OUTPUTS; ++i) { + outputValues[i] = a * tanh(b * outputValues[i]); + } + break; + case 3: + for (short i = 0; i < NUM_OUTPUTS; ++i) { + outputValues[i] = native_recip(1.0f + native_exp(-a * outputValues[i] + b)); + } + break; + case 4: + for (short i = 0; i < NUM_OUTPUTS; ++i) { + outputValues[i] = max(outputValues[i], min_clamp); + outputValues[i] = min(outputValues[i], max_clamp); + } + break; + case 5: + for (short i = 0; i < NUM_OUTPUTS; ++i) { + outputValues[i] = max(outputValues[i], 0.0f) + a * (native_exp(min(outputValues[i], 0.0f)) - 1.0f); + } + break; + } + + // output + int2 outputLocation; + short outputColumn = startOutputColumn; + outputLocation.y = outputRow; + for (short i = 0; i < NUM_OUTPUTS; ++i) { + outputLocation.x = mad24(outputColumn, totalNumPackedOutputChannels, packedOutputChannel); + if (outputColumn < numOutputColumns) { + write_imagef(output, outputLocation, outputValues[i]); + } + ++outputColumn; + } +} diff --git a/selfdrive/modeld/thneed/kernels/convolution_horizontal_reduced_reads.cl b/selfdrive/modeld/thneed/kernels/convolution_horizontal_reduced_reads.cl new file mode 100644 index 00000000000000..fcea88ce90e97d --- /dev/null +++ b/selfdrive/modeld/thneed/kernels/convolution_horizontal_reduced_reads.cl @@ -0,0 +1,3 @@ +#define SUPPORT_DILATION + +__kernel void convolution_horizontal_reduced_reads( diff --git a/selfdrive/modeld/thneed/kernels/convolution_horizontal_reduced_reads_1x1.cl b/selfdrive/modeld/thneed/kernels/convolution_horizontal_reduced_reads_1x1.cl new file mode 100644 index 00000000000000..0d15d8058179ff --- /dev/null +++ b/selfdrive/modeld/thneed/kernels/convolution_horizontal_reduced_reads_1x1.cl @@ -0,0 +1,4 @@ +#define ONLY_1X1_CONV +#define SUPPORT_ACCUMULATION + +__kernel void convolution_horizontal_reduced_reads_1x1( diff --git a/selfdrive/modeld/thneed/kernels/convolution_horizontal_reduced_reads_5_outputs.cl b/selfdrive/modeld/thneed/kernels/convolution_horizontal_reduced_reads_5_outputs.cl new file mode 100644 index 00000000000000..69421fc2a938c9 --- /dev/null +++ b/selfdrive/modeld/thneed/kernels/convolution_horizontal_reduced_reads_5_outputs.cl @@ -0,0 +1,3 @@ +#define NUM_OUTPUTS 5 + +__kernel void convolution_horizontal_reduced_reads_5_outputs( diff --git a/selfdrive/modeld/thneed/kernels/convolution_horizontal_reduced_reads_depthwise.cl b/selfdrive/modeld/thneed/kernels/convolution_horizontal_reduced_reads_depthwise.cl new file mode 100644 index 00000000000000..50e39941d40422 --- /dev/null +++ b/selfdrive/modeld/thneed/kernels/convolution_horizontal_reduced_reads_depthwise.cl @@ -0,0 +1,4 @@ +#define DEPTHWISE +#define SUPPORT_DILATION + +__kernel void convolution_horizontal_reduced_reads_depthwise( diff --git a/selfdrive/modeld/thneed/kernels/convolution_horizontal_reduced_reads_depthwise_stride_1.cl b/selfdrive/modeld/thneed/kernels/convolution_horizontal_reduced_reads_depthwise_stride_1.cl new file mode 100644 index 00000000000000..b347cb6c7186b6 --- /dev/null +++ b/selfdrive/modeld/thneed/kernels/convolution_horizontal_reduced_reads_depthwise_stride_1.cl @@ -0,0 +1,3 @@ +#define DEPTHWISE + +__kernel void convolution_horizontal_reduced_reads_depthwise_stride_1( diff --git a/selfdrive/modeld/thneed/optimizer.cc b/selfdrive/modeld/thneed/optimizer.cc new file mode 100644 index 00000000000000..39737d3d7623ba --- /dev/null +++ b/selfdrive/modeld/thneed/optimizer.cc @@ -0,0 +1,261 @@ +#include +#include +#include +#include +#include "thneed.h" + +#include "common/util.h" +#include "common/clutil.h" + +extern map g_program_source; + +/*static int is_same_size_image(cl_mem a, cl_mem b) { + size_t a_width, a_height, a_depth, a_array_size, a_row_pitch, a_slice_pitch; + clGetImageInfo(a, CL_IMAGE_WIDTH, sizeof(a_width), &a_width, NULL); + clGetImageInfo(a, CL_IMAGE_HEIGHT, sizeof(a_height), &a_height, NULL); + clGetImageInfo(a, CL_IMAGE_DEPTH, sizeof(a_depth), &a_depth, NULL); + clGetImageInfo(a, CL_IMAGE_ARRAY_SIZE, sizeof(a_array_size), &a_array_size, NULL); + clGetImageInfo(a, CL_IMAGE_ROW_PITCH, sizeof(a_row_pitch), &a_row_pitch, NULL); + clGetImageInfo(a, CL_IMAGE_SLICE_PITCH, sizeof(a_slice_pitch), &a_slice_pitch, NULL); + + size_t b_width, b_height, b_depth, b_array_size, b_row_pitch, b_slice_pitch; + clGetImageInfo(b, CL_IMAGE_WIDTH, sizeof(b_width), &b_width, NULL); + clGetImageInfo(b, CL_IMAGE_HEIGHT, sizeof(b_height), &b_height, NULL); + clGetImageInfo(b, CL_IMAGE_DEPTH, sizeof(b_depth), &b_depth, NULL); + clGetImageInfo(b, CL_IMAGE_ARRAY_SIZE, sizeof(b_array_size), &b_array_size, NULL); + clGetImageInfo(b, CL_IMAGE_ROW_PITCH, sizeof(b_row_pitch), &b_row_pitch, NULL); + clGetImageInfo(b, CL_IMAGE_SLICE_PITCH, sizeof(b_slice_pitch), &b_slice_pitch, NULL); + + return (a_width == b_width) && (a_height == b_height) && + (a_depth == b_depth) && (a_array_size == b_array_size) && + (a_row_pitch == b_row_pitch) && (a_slice_pitch == b_slice_pitch); +}*/ + +static cl_mem make_image_like(cl_context context, cl_mem val) { + cl_image_format format; + size_t width, height, row_pitch; + clGetImageInfo(val, CL_IMAGE_FORMAT, sizeof(format), &format, NULL); + assert(format.image_channel_order == CL_RGBA); + assert(format.image_channel_data_type == CL_HALF_FLOAT); + clGetImageInfo(val, CL_IMAGE_WIDTH, sizeof(width), &width, NULL); + clGetImageInfo(val, CL_IMAGE_HEIGHT, sizeof(height), &height, NULL); + clGetImageInfo(val, CL_IMAGE_ROW_PITCH, sizeof(row_pitch), &row_pitch, NULL); + + cl_image_desc desc = {0}; + desc.image_type = CL_MEM_OBJECT_IMAGE2D; + desc.image_width = width; + desc.image_height = height; + desc.image_row_pitch = row_pitch; + + cl_mem buf = clCreateBuffer(context, CL_MEM_READ_WRITE, row_pitch*height, NULL, NULL); + assert(buf != NULL); + desc.buffer = buf; + + cl_int err; + cl_mem tmp = clCreateImage(context, CL_MEM_READ_WRITE, &format, &desc, NULL, &err); + //printf("got %d for image %zux%zu %zu\n", err, width, height, row_pitch); + assert(tmp != NULL); + + return tmp; +} + +// convolution_horizontal_reduced_reads_1x1 is 66% of the model runtime +// make that faster and the model gets faster + +// this cuts ~2 ms off the model runtime right now +int Thneed::optimize() { + const char *kernel_path = getenv("KERNEL_PATH"); + if (!kernel_path) { kernel_path = "/data/openpilot/selfdrive/modeld/thneed/kernels"; printf("no KERNEL_PATH set, defaulting to %s\n", kernel_path); } + + string convolution_; + { + char fn[0x100]; + snprintf(fn, sizeof(fn), "%s/%s.cl", kernel_path, "convolution_"); + convolution_ = util::read_file(fn); + } + + // load custom kernels + map g_programs; + for (auto &k : kq) { + // replace program? + if (g_programs.find(k->name) == g_programs.end()) { + char fn[0x100]; + snprintf(fn, sizeof(fn), "%s/%s.cl", kernel_path, k->name.c_str()); + if (util::file_exists(fn)) { + string kernel_src = util::read_file(fn); + if (k->name.rfind("convolution_", 0) == 0) { + kernel_src += convolution_; + } + printf("building kernel %s with len %lu\n", k->name.c_str(), kernel_src.length()); + k->program = cl_program_from_source(context, device_id, kernel_src); + + // save in cache + g_programs[k->name] = k->program; + g_program_source[k->program] = kernel_src; + } else { + g_programs[k->name] = NULL; + } + } else { + // cached replacement + if (g_programs[k->name] != NULL) { + k->program = g_programs[k->name]; + } + } + + // hack in accumulator to convolution_horizontal_reduced_reads_1x1 + if (k->name == "convolution_horizontal_reduced_reads_1x1") { + k->arg_names.push_back("doAccumulate"); + short doAccumulate = 0; + k->args.push_back(string((char *)&doAccumulate, sizeof(doAccumulate))); + k->args_size.push_back(2); + k->arg_names.push_back("accumulator"); + k->args.push_back(k->args[k->get_arg_num("output")]); + k->args_size.push_back(8); + k->num_args += 2; + } + + // assert that parameters + batchNormBiases are not used + // since they aren't supported in custom replacement kernels + if (k->name == "convolution_horizontal_reduced_reads_1x1" || + k->name == "convolution_horizontal_reduced_reads" || + k->name == "convolution_horizontal_reduced_reads_5_outputs") { + string p1 = k->args[k->get_arg_num("parameters")]; + string p2 = k->args[k->get_arg_num("batchNormBiases")]; + assert(p1.length() == 8 && *((uint64_t*)p1.data()) == 0); + assert(p2.length() == 8 && *((uint64_t*)p2.data()) == 0); + } + } + + // optimizer + size_t start_size; + do { + start_size = kq.size(); + + // get optimizations + map replacements; + for (int i = 0; i < kq.size(); i++) { + // fusing elementwise_sum + activate_image will save 3 enqueues + + // delete useless copy layers + // saves ~0.7 ms + /*if (kq[i]->name == "concatenation" || kq[i]->name == "flatten") { + string in = kq[i]->args[kq[i]->get_arg_num("input")]; + string out = kq[i]->args[kq[i]->get_arg_num("output")]; + if (is_same_size_image(*(cl_mem*)in.data(), *(cl_mem*)out.data())) { + cl_mem tmp = make_image_like(context, *(cl_mem *)in.data()); + replacements[in] = string((char *)&tmp, sizeof(tmp)); + replacements[out] = string((char *)&tmp, sizeof(tmp)); + + kq.erase(kq.begin()+i); --i; + } + }*/ + + // NOTE: if activations/accumulation are done in the wrong order, this will be wrong + + // fuse activations into convs and fc_Wtx + // saves ~1.5 ms + // NOTE: this changes the outputs because of rounding, should be better now! + if (i != 0 && kq[i]->name == "activate_image") { + if (kq[i-1]->name == "convolution_horizontal_reduced_reads_1x1" || + kq[i-1]->name == "convolution_horizontal_reduced_reads_5_outputs" || + kq[i-1]->name == "convolution_horizontal_reduced_reads" || + kq[i-1]->name == "convolution_horizontal_reduced_reads_depthwise" || + kq[i-1]->name == "convolution_horizontal_reduced_reads_depthwise_stride_1" || + kq[i-1]->name == "fc_Wtx") { + string lastout = kq[i-1]->args[kq[i-1]->get_arg_num("output")]; + string in = kq[i]->args[kq[i]->get_arg_num("input")]; + string out = kq[i]->args[kq[i]->get_arg_num("output")]; + + if (lastout == in) { + short neuron = *(int*)kq[i]->args[kq[i]->get_arg_num("neuron")].data(); + assert(neuron <= 5); + + // ELU isn't supported in fc_Wtx + assert(!(kq[i-1]->name == "fc_Wtx" && neuron == 5)); + + kq[i-1]->args[kq[i-1]->get_arg_num("neuron")] = string((char *)&neuron, sizeof(neuron)); + + cl_mem tmp = make_image_like(context, *(cl_mem *)lastout.data()); + replacements[in] = string((char *)&tmp, sizeof(tmp)); + replacements[out] = string((char *)&tmp, sizeof(tmp)); + + kq.erase(kq.begin()+i); --i; + } + } + } + + // fuse accumulation into convs and fc_Wtx + if (i != 0 && kq[i]->name == "elementwise_sum") { + if (kq[i-1]->name == "convolution_horizontal_reduced_reads_1x1" || + kq[i-1]->name == "fc_Wtx") { + string lastout = kq[i-1]->args[kq[i-1]->get_arg_num("output")]; + string a = kq[i]->args[kq[i]->get_arg_num("a")]; + string b = kq[i]->args[kq[i]->get_arg_num("b")]; + string out = kq[i]->args[kq[i]->get_arg_num("output")]; + + if (lastout == a) { + kq[i-1]->args[kq[i-1]->get_arg_num("accumulator")] = b; + } else if (lastout == b) { + kq[i-1]->args[kq[i-1]->get_arg_num("accumulator")] = a; + } else { + continue; + } + + cl_mem tmp = make_image_like(context, *(cl_mem *)lastout.data()); + replacements[lastout] = string((char *)&tmp, sizeof(tmp)); + replacements[out] = string((char *)&tmp, sizeof(tmp)); + + short doAccumulate = 1; + kq[i-1]->args[kq[i-1]->get_arg_num("doAccumulate")] = string((char *)&doAccumulate, sizeof(doAccumulate)); + + kq.erase(kq.begin()+i); --i; + } + } + } + + // remap inputs and outputs, and clear the kernels + for (int i = 0; i < kq.size(); i++) { + kq[i]->kernel = NULL; + for (int j = 0; j < kq[i]->num_args; j++) { + if (replacements.find(kq[i]->args[j]) != replacements.end()) { + kq[i]->args[j] = replacements[kq[i]->args[j]]; + } + } + } + + printf("optimize %lu -> %lu\n", start_size, kq.size()); + } while (kq.size() != start_size); + + size_t work_group_size = 0; + clGetDeviceInfo(device_id, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(work_group_size), &work_group_size, NULL); + printf("max work group size %lu\n", work_group_size); + + // local work group optimizer + for (auto &k : kq) { + // only do it for convs, since others might share memory + if (k->name.rfind("convolution_", 0) == 0) { + int best = -1; + if (k->local_work_size[0] * k->local_work_size[1] * k->local_work_size[2] < work_group_size/2) { + uint64_t base_time = k->benchmark(); + uint64_t best_time = base_time; + for (int i = 0; i < 3; i++) { + k->local_work_size[i] *= 2; + uint64_t this_time = k->benchmark(); + if (this_time < best_time) { + best = i; + best_time = this_time; + } + k->local_work_size[i] /= 2; + } + if (best != -1) { + k->local_work_size[best] *= 2; + //printf("%s %.2f ms doubled %d to %.2f ms\n", k->name.c_str(), base_time/1e6, best, best_time/1e6); + } + } + + } + } + + return 0; +} + diff --git a/selfdrive/modeld/thneed/serialize.cc b/selfdrive/modeld/thneed/serialize.cc index f789e5bf577f6d..136576fe1ceb60 100644 --- a/selfdrive/modeld/thneed/serialize.cc +++ b/selfdrive/modeld/thneed/serialize.cc @@ -14,9 +14,9 @@ void Thneed::load(const char *filename) { string buf = util::read_file(filename); int jsz = *(int *)buf.data(); - string jsonerr; + string err; string jj(buf.data() + sizeof(int), jsz); - Json jdat = Json::parse(jj, jsonerr); + Json jdat = Json::parse(jj, err); map real_mem; real_mem[NULL] = NULL; @@ -33,14 +33,11 @@ void Thneed::load(const char *filename) { assert(mobj["needs_load"].bool_value() == false); } else { if (mobj["needs_load"].bool_value()) { + //printf("loading %p %d @ 0x%X\n", clbuf, sz, ptr); clbuf = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR | CL_MEM_READ_WRITE, sz, &buf[ptr], NULL); - if (debug >= 1) printf("loading %p %d @ 0x%X\n", clbuf, sz, ptr); ptr += sz; } else { - // TODO: is there a faster way to init zeroed out buffers? - void *host_zeros = calloc(sz, 1); - clbuf = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR | CL_MEM_READ_WRITE, sz, host_zeros, NULL); - free(host_zeros); + clbuf = clCreateBuffer(context, CL_MEM_READ_WRITE, sz, NULL, NULL); } } assert(clbuf != NULL); @@ -51,33 +48,13 @@ void Thneed::load(const char *filename) { desc.image_width = mobj["width"].int_value(); desc.image_height = mobj["height"].int_value(); desc.image_row_pitch = mobj["row_pitch"].int_value(); - assert(sz == desc.image_height*desc.image_row_pitch); -#ifdef QCOM2 desc.buffer = clbuf; -#else - // TODO: we are creating unused buffers on PC - clReleaseMemObject(clbuf); -#endif - cl_image_format format = {0}; - format.image_channel_order = CL_RGBA; - format.image_channel_data_type = mobj["float32"].bool_value() ? CL_FLOAT : CL_HALF_FLOAT; - cl_int errcode; + cl_image_format format; + format.image_channel_order = CL_RGBA; + format.image_channel_data_type = CL_HALF_FLOAT; -#ifndef QCOM2 - if (mobj["needs_load"].bool_value()) { - clbuf = clCreateImage(context, CL_MEM_COPY_HOST_PTR | CL_MEM_READ_WRITE, &format, &desc, &buf[ptr-sz], &errcode); - } else { - clbuf = clCreateImage(context, CL_MEM_READ_WRITE, &format, &desc, NULL, &errcode); - } -#else - clbuf = clCreateImage(context, CL_MEM_READ_WRITE, &format, &desc, NULL, &errcode); -#endif - if (clbuf == NULL) { - printf("clError: %s create image %zux%zu rp %zu with buffer %p\n", cl_get_error_string(errcode), - desc.image_width, desc.image_height, desc.image_row_pitch, desc.buffer - ); - } + clbuf = clCreateImage(context, CL_MEM_READ_WRITE, &format, &desc, NULL, NULL); assert(clbuf != NULL); } @@ -90,30 +67,6 @@ void Thneed::load(const char *filename) { g_programs[name] = cl_program_from_source(context, device_id, source.string_value()); } - for (auto &obj : jdat["inputs"].array_items()) { - auto mobj = obj.object_items(); - int sz = mobj["size"].int_value(); - cl_mem aa = real_mem[*(cl_mem*)(mobj["buffer_id"].string_value().data())]; - input_clmem.push_back(aa); - input_sizes.push_back(sz); - printf("Thneed::load: adding input %s with size %d\n", mobj["name"].string_value().data(), sz); - - cl_int cl_err; - void *ret = clEnqueueMapBuffer(command_queue, aa, CL_TRUE, CL_MAP_WRITE, 0, sz, 0, NULL, NULL, &cl_err); - if (cl_err != CL_SUCCESS) printf("clError: %s map %p %d\n", cl_get_error_string(cl_err), aa, sz); - assert(cl_err == CL_SUCCESS); - inputs.push_back(ret); - } - - for (auto &obj : jdat["outputs"].array_items()) { - auto mobj = obj.object_items(); - int sz = mobj["size"].int_value(); - printf("Thneed::save: adding output with size %d\n", sz); - // TODO: support multiple outputs - output = real_mem[*(cl_mem*)(mobj["buffer_id"].string_value().data())]; - assert(output != NULL); - } - for (auto &obj : jdat["binaries"].array_items()) { string name = obj["name"].string_value(); size_t length = obj["length"].int_value(); @@ -152,3 +105,154 @@ void Thneed::load(const char *filename) { clFinish(command_queue); } + +void Thneed::save(const char *filename, bool save_binaries) { + printf("Thneed::save: saving to %s\n", filename); + + // get kernels + std::vector kernels; + std::set saved_objects; + std::vector objects; + std::map programs; + std::map binaries; + + for (auto &k : kq) { + kernels.push_back(k->to_json()); + + // check args for objects + int i = 0; + for (auto &a : k->args) { + if (a.size() == 8) { + if (saved_objects.find(a) == saved_objects.end()) { + saved_objects.insert(a); + cl_mem val = *(cl_mem*)(a.data()); + if (val != NULL) { + bool needs_load = k->arg_names[i] == "weights" || k->arg_names[i] == "biases"; + + auto jj = Json::object({ + {"id", a}, + {"arg_type", k->arg_types[i]}, + }); + + if (k->arg_types[i] == "image2d_t" || k->arg_types[i] == "image1d_t") { + cl_mem buf; + clGetImageInfo(val, CL_IMAGE_BUFFER, sizeof(buf), &buf, NULL); + string aa = string((char *)&buf, sizeof(buf)); + jj["buffer_id"] = aa; + + size_t width, height, row_pitch; + clGetImageInfo(val, CL_IMAGE_WIDTH, sizeof(width), &width, NULL); + clGetImageInfo(val, CL_IMAGE_HEIGHT, sizeof(height), &height, NULL); + clGetImageInfo(val, CL_IMAGE_ROW_PITCH, sizeof(row_pitch), &row_pitch, NULL); + jj["width"] = (int)width; + jj["height"] = (int)height; + jj["row_pitch"] = (int)row_pitch; + jj["size"] = (int)(height * row_pitch); + jj["needs_load"] = false; + + if (saved_objects.find(aa) == saved_objects.end()) { + saved_objects.insert(aa); + size_t sz; + clGetMemObjectInfo(buf, CL_MEM_SIZE, sizeof(sz), &sz, NULL); + // save the buffer + objects.push_back(Json::object({ + {"id", aa}, + {"arg_type", ""}, + {"needs_load", needs_load}, + {"size", (int)sz} + })); + if (needs_load) assert(sz == height * row_pitch); + } + } else { + size_t sz = 0; + clGetMemObjectInfo(val, CL_MEM_SIZE, sizeof(sz), &sz, NULL); + jj["size"] = (int)sz; + jj["needs_load"] = needs_load; + } + + objects.push_back(jj); + } + } + } + i++; + } + + if (save_binaries) { + int err; + size_t binary_size = 0; + err = clGetProgramInfo(k->program, CL_PROGRAM_BINARY_SIZES, sizeof(binary_size), &binary_size, NULL); + assert(err == 0); + assert(binary_size > 0); + string sv(binary_size, '\x00'); + + uint8_t* bufs[1] = { (uint8_t*)sv.data(), }; + err = clGetProgramInfo(k->program, CL_PROGRAM_BINARIES, sizeof(bufs), &bufs, NULL); + assert(err == 0); + + binaries[k->name] = sv; + } else { + programs[k->name] = g_program_source[k->program]; + } + } + + vector saved_buffers; + for (auto &obj : objects) { + auto mobj = obj.object_items(); + cl_mem val = *(cl_mem*)(mobj["id"].string_value().data()); + int sz = mobj["size"].int_value(); + if (mobj["needs_load"].bool_value()) { + char *buf = (char *)malloc(sz); + if (mobj["arg_type"] == "image2d_t" || mobj["arg_type"] == "image1d_t") { + assert(false); + } else { + // buffers allocated with CL_MEM_HOST_WRITE_ONLY, hence this hack + //hexdump((uint32_t*)val, 0x100); + + // the worst hack in thneed, the flags are at 0x14 + ((uint32_t*)val)[0x14] &= ~CL_MEM_HOST_WRITE_ONLY; + cl_int ret = clEnqueueReadBuffer(command_queue, val, CL_TRUE, 0, sz, buf, 0, NULL, NULL); + assert(ret == CL_SUCCESS); + } + //printf("saving buffer: %d %p %s\n", sz, buf, mobj["arg_type"].string_value().c_str()); + saved_buffers.push_back(string(buf, sz)); + free(buf); + } + } + + std::vector jbinaries; + for (auto &obj : binaries) { + jbinaries.push_back(Json::object({{"name", obj.first}, {"length", (int)obj.second.size()}})); + saved_buffers.push_back(obj.second); + } + + Json jdat = Json::object({ + {"kernels", kernels}, + {"objects", objects}, + {"programs", programs}, + {"binaries", jbinaries}, + }); + + string str = jdat.dump(); + int jsz = str.length(); + + FILE *f = fopen(filename, "wb"); + fwrite(&jsz, 1, sizeof(jsz), f); + fwrite(str.data(), 1, jsz, f); + for (auto &s : saved_buffers) { + fwrite(s.data(), 1, s.length(), f); + } + fclose(f); +} + +Json CLQueuedKernel::to_json() const { + return Json::object { + { "name", name }, + { "work_dim", (int)work_dim }, + { "global_work_size", Json::array { (int)global_work_size[0], (int)global_work_size[1], (int)global_work_size[2] } }, + { "local_work_size", Json::array { (int)local_work_size[0], (int)local_work_size[1], (int)local_work_size[2] } }, + { "num_args", (int)num_args }, + { "args", args }, + { "args_size", args_size }, + }; +} + diff --git a/selfdrive/modeld/thneed/thneed.cc b/selfdrive/modeld/thneed/thneed.cc new file mode 100644 index 00000000000000..d673c4f56ffc37 --- /dev/null +++ b/selfdrive/modeld/thneed/thneed.cc @@ -0,0 +1,604 @@ +#include "selfdrive/modeld/thneed/thneed.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include "common/clutil.h" +#include "common/timing.h" + +Thneed *g_thneed = NULL; +int g_fd = -1; +map, string> g_args; +map, int> g_args_size; +map g_program_source; + +void hexdump(uint8_t *d, int len) { + assert((len%4) == 0); + printf(" dumping %p len 0x%x\n", d, len); + for (int i = 0; i < len/4; i++) { + if (i != 0 && (i%0x10) == 0) printf("\n"); + printf("%8x ", d[i]); + } + printf("\n"); +} + +// *********** ioctl interceptor *********** + +extern "C" { + +int (*my_ioctl)(int filedes, unsigned long request, void *argp) = NULL; +#undef ioctl +int ioctl(int filedes, unsigned long request, void *argp) { + request &= 0xFFFFFFFF; // needed on QCOM2 + if (my_ioctl == NULL) my_ioctl = reinterpret_cast(dlsym(RTLD_NEXT, "ioctl")); + Thneed *thneed = g_thneed; + + // save the fd + if (request == IOCTL_KGSL_GPUOBJ_ALLOC) g_fd = filedes; + + // note that this runs always, even without a thneed object + if (request == IOCTL_KGSL_DRAWCTXT_CREATE) { + struct kgsl_drawctxt_create *create = (struct kgsl_drawctxt_create *)argp; + create->flags &= ~KGSL_CONTEXT_PRIORITY_MASK; + create->flags |= 1 << KGSL_CONTEXT_PRIORITY_SHIFT; // priority from 1-15, 1 is max priority + printf("IOCTL_KGSL_DRAWCTXT_CREATE: creating context with flags 0x%x\n", create->flags); + } + + if (thneed != NULL) { + if (request == IOCTL_KGSL_GPU_COMMAND) { + struct kgsl_gpu_command *cmd = (struct kgsl_gpu_command *)argp; + if (thneed->record) { + thneed->timestamp = cmd->timestamp; + thneed->context_id = cmd->context_id; + thneed->cmds.push_back(unique_ptr(new CachedCommand(thneed, cmd))); + } + if (thneed->debug >= 1) { + printf("IOCTL_KGSL_GPU_COMMAND(%2zu): flags: 0x%lx context_id: %u timestamp: %u numcmds: %d numobjs: %d\n", + thneed->cmds.size(), + cmd->flags, + cmd->context_id, cmd->timestamp, cmd->numcmds, cmd->numobjs); + } + } else if (request == IOCTL_KGSL_GPUOBJ_SYNC) { + struct kgsl_gpuobj_sync *cmd = (struct kgsl_gpuobj_sync *)argp; + struct kgsl_gpuobj_sync_obj *objs = (struct kgsl_gpuobj_sync_obj *)(cmd->objs); + + if (thneed->debug >= 2) { + printf("IOCTL_KGSL_GPUOBJ_SYNC count:%d ", cmd->count); + for (int i = 0; i < cmd->count; i++) { + printf(" -- offset:0x%lx len:0x%lx id:%d op:%d ", objs[i].offset, objs[i].length, objs[i].id, objs[i].op); + } + printf("\n"); + } + + if (thneed->record) { + thneed->cmds.push_back(unique_ptr(new + CachedSync(thneed, string((char *)objs, sizeof(struct kgsl_gpuobj_sync_obj)*cmd->count)))); + } + } else if (request == IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID) { + struct kgsl_device_waittimestamp_ctxtid *cmd = (struct kgsl_device_waittimestamp_ctxtid *)argp; + if (thneed->debug >= 1) { + printf("IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID: context_id: %d timestamp: %d timeout: %d\n", + cmd->context_id, cmd->timestamp, cmd->timeout); + } + } else if (request == IOCTL_KGSL_SETPROPERTY) { + if (thneed->debug >= 1) { + struct kgsl_device_getproperty *prop = (struct kgsl_device_getproperty *)argp; + printf("IOCTL_KGSL_SETPROPERTY: 0x%x sizebytes:%zu\n", prop->type, prop->sizebytes); + if (thneed->debug >= 2) { + hexdump((uint8_t *)prop->value, prop->sizebytes); + if (prop->type == KGSL_PROP_PWR_CONSTRAINT) { + struct kgsl_device_constraint *constraint = (struct kgsl_device_constraint *)prop->value; + hexdump((uint8_t *)constraint->data, constraint->size); + } + } + } + } else if (request == IOCTL_KGSL_DRAWCTXT_CREATE || request == IOCTL_KGSL_DRAWCTXT_DESTROY) { + // this happens + } else if (request == IOCTL_KGSL_GPUOBJ_ALLOC || request == IOCTL_KGSL_GPUOBJ_FREE) { + // this happens + } else { + if (thneed->debug >= 1) { + printf("other ioctl %lx\n", request); + } + } + } + + int ret = my_ioctl(filedes, request, argp); + if (ret != 0) printf("ioctl returned %d with errno %d\n", ret, errno); + return ret; +} + +} + +// *********** GPUMalloc *********** + +GPUMalloc::GPUMalloc(int size, int fd) { + struct kgsl_gpuobj_alloc alloc; + memset(&alloc, 0, sizeof(alloc)); + alloc.size = size; + alloc.flags = 0x10000a00; + ioctl(fd, IOCTL_KGSL_GPUOBJ_ALLOC, &alloc); + void *addr = mmap64(NULL, alloc.mmapsize, 0x3, 0x1, fd, alloc.id*0x1000); + assert(addr != MAP_FAILED); + + base = (uint64_t)addr; + remaining = size; +} + +GPUMalloc::~GPUMalloc() { + // TODO: free the GPU malloced area +} + +void *GPUMalloc::alloc(int size) { + void *ret = (void*)base; + size = (size+0xff) & (~0xFF); + assert(size <= remaining); + remaining -= size; + base += size; + return ret; +} + +// *********** CachedSync, at the ioctl layer *********** + +void CachedSync::exec() { + struct kgsl_gpuobj_sync cmd; + + cmd.objs = (uint64_t)data.data(); + cmd.obj_len = data.length(); + cmd.count = data.length() / sizeof(struct kgsl_gpuobj_sync_obj); + + int ret = ioctl(thneed->fd, IOCTL_KGSL_GPUOBJ_SYNC, &cmd); + assert(ret == 0); +} + +// *********** CachedCommand, at the ioctl layer *********** + +CachedCommand::CachedCommand(Thneed *lthneed, struct kgsl_gpu_command *cmd) { + thneed = lthneed; + assert(cmd->numsyncs == 0); + + memcpy(&cache, cmd, sizeof(cache)); + + if (cmd->numcmds > 0) { + cmds = make_unique(cmd->numcmds); + memcpy(cmds.get(), (void *)cmd->cmdlist, sizeof(struct kgsl_command_object)*cmd->numcmds); + cache.cmdlist = (uint64_t)cmds.get(); + for (int i = 0; i < cmd->numcmds; i++) { + void *nn = thneed->ram->alloc(cmds[i].size); + memcpy(nn, (void*)cmds[i].gpuaddr, cmds[i].size); + cmds[i].gpuaddr = (uint64_t)nn; + } + } + + if (cmd->numobjs > 0) { + objs = make_unique(cmd->numobjs); + memcpy(objs.get(), (void *)cmd->objlist, sizeof(struct kgsl_command_object)*cmd->numobjs); + cache.objlist = (uint64_t)objs.get(); + for (int i = 0; i < cmd->numobjs; i++) { + void *nn = thneed->ram->alloc(objs[i].size); + memset(nn, 0, objs[i].size); + objs[i].gpuaddr = (uint64_t)nn; + } + } + + kq = thneed->ckq; + thneed->ckq.clear(); +} + +void CachedCommand::exec() { + cache.timestamp = ++thneed->timestamp; + int ret = ioctl(thneed->fd, IOCTL_KGSL_GPU_COMMAND, &cache); + + if (thneed->debug >= 1) printf("CachedCommand::exec got %d\n", ret); + + if (thneed->debug >= 2) { + for (auto &it : kq) { + it->debug_print(false); + } + } + + assert(ret == 0); +} + +// *********** Thneed *********** + +Thneed::Thneed(bool do_clinit) { + if (do_clinit) clinit(); + assert(g_fd != -1); + fd = g_fd; + ram = make_unique(0x80000, fd); + timestamp = -1; + g_thneed = this; + char *thneed_debug_env = getenv("THNEED_DEBUG"); + debug = (thneed_debug_env != NULL) ? atoi(thneed_debug_env) : 0; +} + +void Thneed::stop() { + find_inputs_outputs(); + printf("Thneed::stop: recorded %lu commands\n", cmds.size()); + record = false; +} + +void Thneed::find_inputs_outputs() { + cl_int err; + if (inputs.size() > 0) return; + + // save the global inputs/outputs + for (auto &k : kq) { + for (int i = 0; i < k->num_args; i++) { + if (k->name == "zero_pad_image_float" && k->arg_names[i] == "input") { + cl_mem aa = *(cl_mem*)(k->args[i].data()); + input_clmem.push_back(aa); + + size_t sz; + clGetMemObjectInfo(aa, CL_MEM_SIZE, sizeof(sz), &sz, NULL); + input_sizes.push_back(sz); + + void *ret = clEnqueueMapBuffer(command_queue, aa, CL_TRUE, CL_MAP_WRITE, 0, sz, 0, NULL, NULL, &err); + assert(err == CL_SUCCESS); + inputs.push_back(ret); + } + + if (k->name == "image2d_to_buffer_float" && k->arg_names[i] == "output") { + output = *(cl_mem*)(k->args[i].data()); + } + } + } +} + +void Thneed::copy_inputs(float **finputs) { + //cl_int ret; + for (int idx = 0; idx < inputs.size(); ++idx) { + if (debug >= 1) printf("copying %lu -- %p -> %p\n", input_sizes[idx], finputs[idx], inputs[idx]); + if (finputs[idx] != NULL) memcpy(inputs[idx], finputs[idx], input_sizes[idx]); + } +} + +void Thneed::copy_output(float *foutput) { + if (output != NULL) { + size_t sz; + clGetMemObjectInfo(output, CL_MEM_SIZE, sizeof(sz), &sz, NULL); + if (debug >= 1) printf("copying %lu for output %p -> %p\n", sz, output, foutput); + clEnqueueReadBuffer(command_queue, output, CL_TRUE, 0, sz, foutput, 0, NULL, NULL); + } else { + printf("CAUTION: model output is NULL, does it have no outputs?\n"); + } +} + +void Thneed::wait() { + struct kgsl_device_waittimestamp_ctxtid wait; + wait.context_id = context_id; + wait.timestamp = timestamp; + wait.timeout = -1; + + uint64_t tb = nanos_since_boot(); + int wret = ioctl(fd, IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID, &wait); + uint64_t te = nanos_since_boot(); + + if (debug >= 1) printf("wait %d after %lu us\n", wret, (te-tb)/1000); +} + +void Thneed::execute(float **finputs, float *foutput, bool slow) { + uint64_t tb, te; + if (debug >= 1) tb = nanos_since_boot(); + + // ****** copy inputs + copy_inputs(finputs); + + // ****** set power constraint + int ret; + struct kgsl_device_constraint_pwrlevel pwrlevel; + pwrlevel.level = KGSL_CONSTRAINT_PWR_MAX; + + struct kgsl_device_constraint constraint; + constraint.type = KGSL_CONSTRAINT_PWRLEVEL; + constraint.context_id = context_id; + constraint.data = (void*)&pwrlevel; + constraint.size = sizeof(pwrlevel); + + struct kgsl_device_getproperty prop; + prop.type = KGSL_PROP_PWR_CONSTRAINT; + prop.value = (void*)&constraint; + prop.sizebytes = sizeof(constraint); + ret = ioctl(fd, IOCTL_KGSL_SETPROPERTY, &prop); + assert(ret == 0); + + // ****** run commands + int i = 0; + for (auto &it : cmds) { + ++i; + if (debug >= 1) printf("run %2d @ %7lu us: ", i, (nanos_since_boot()-tb)/1000); + it->exec(); + if ((i == cmds.size()) || slow) wait(); + } + + // ****** copy outputs + copy_output(foutput); + + // ****** unset power constraint + constraint.type = KGSL_CONSTRAINT_NONE; + constraint.data = NULL; + constraint.size = 0; + + ret = ioctl(fd, IOCTL_KGSL_SETPROPERTY, &prop); + assert(ret == 0); + + if (debug >= 1) { + te = nanos_since_boot(); + printf("model exec in %lu us\n", (te-tb)/1000); + } +} + +void Thneed::clinit() { + device_id = cl_get_device_id(CL_DEVICE_TYPE_DEFAULT); + context = CL_CHECK_ERR(clCreateContext(NULL, 1, &device_id, NULL, NULL, &err)); + //cl_command_queue_properties props[3] = {CL_QUEUE_PROPERTIES, CL_QUEUE_PROFILING_ENABLE, 0}; + cl_command_queue_properties props[3] = {CL_QUEUE_PROPERTIES, 0, 0}; + command_queue = CL_CHECK_ERR(clCreateCommandQueueWithProperties(context, device_id, props, &err)); + printf("Thneed::clinit done\n"); +} + +cl_int Thneed::clexec() { + printf("Thneed::clexec: running %lu queued kernels\n", kq.size()); + for (auto &k : kq) { + if (record) ckq.push_back(k); + cl_int ret = k->exec(); + assert(ret == CL_SUCCESS); + } + return clFinish(command_queue); +} + +// *********** OpenCL interceptor *********** + +cl_int thneed_clSetKernelArg(cl_kernel kernel, cl_uint arg_index, size_t arg_size, const void *arg_value) { + g_args_size[make_pair(kernel, arg_index)] = arg_size; + if (arg_value != NULL) { + g_args[make_pair(kernel, arg_index)] = string((char*)arg_value, arg_size); + } else { + g_args[make_pair(kernel, arg_index)] = string(""); + } + cl_int ret = clSetKernelArg(kernel, arg_index, arg_size, arg_value); + return ret; +} + +cl_int thneed_clEnqueueNDRangeKernel(cl_command_queue command_queue, + cl_kernel kernel, + cl_uint work_dim, + const size_t *global_work_offset, + const size_t *global_work_size, + const size_t *local_work_size, + cl_uint num_events_in_wait_list, + const cl_event *event_wait_list, + cl_event *event) { + + Thneed *thneed = g_thneed; + + // SNPE doesn't use these + assert(num_events_in_wait_list == 0); + assert(global_work_offset == NULL); + assert(event_wait_list == NULL); + + cl_int ret = 0; + if (thneed != NULL && thneed->record) { + if (thneed->context == NULL) { + thneed->command_queue = command_queue; + clGetKernelInfo(kernel, CL_KERNEL_CONTEXT, sizeof(thneed->context), &thneed->context, NULL); + clGetContextInfo(thneed->context, CL_CONTEXT_DEVICES, sizeof(thneed->device_id), &thneed->device_id, NULL); + } + + // if we are recording, we don't actually enqueue the kernel + thneed->kq.push_back(unique_ptr(new CLQueuedKernel(thneed, kernel, work_dim, global_work_size, local_work_size))); + *event = NULL; + } else { + ret = clEnqueueNDRangeKernel(command_queue, kernel, work_dim, + global_work_offset, global_work_size, local_work_size, + num_events_in_wait_list, event_wait_list, event); + } + + return ret; +} + +cl_int thneed_clFinish(cl_command_queue command_queue) { + Thneed *thneed = g_thneed; + + if (thneed != NULL && thneed->record) { + if (thneed->run_optimizer) thneed->optimize(); + return thneed->clexec(); + } else { + return clFinish(command_queue); + } +} + +cl_program thneed_clCreateProgramWithSource(cl_context context, cl_uint count, const char **strings, const size_t *lengths, cl_int *errcode_ret) { + assert(count == 1); + cl_program ret = clCreateProgramWithSource(context, count, strings, lengths, errcode_ret); + g_program_source[ret] = strings[0]; + return ret; +} + +void *dlsym(void *handle, const char *symbol) { +#ifdef QCOM2 + void *(*my_dlsym)(void *handle, const char *symbol) = (void *(*)(void *handle, const char *symbol))((uintptr_t)dlopen + DLSYM_OFFSET); +#else + #error "Unsupported platform for thneed" +#endif + if (memcmp("REAL_", symbol, 5) == 0) { + return my_dlsym(handle, symbol+5); + } else if (strcmp("clFinish", symbol) == 0) { + return (void*)thneed_clFinish; + } else if (strcmp("clEnqueueNDRangeKernel", symbol) == 0) { + return (void*)thneed_clEnqueueNDRangeKernel; + } else if (strcmp("clSetKernelArg", symbol) == 0) { + return (void*)thneed_clSetKernelArg; + } else if (strcmp("clCreateProgramWithSource", symbol) == 0) { + return (void*)thneed_clCreateProgramWithSource; + } else { + return my_dlsym(handle, symbol); + } +} + +// *********** CLQueuedKernel *********** + +CLQueuedKernel::CLQueuedKernel(Thneed *lthneed, + cl_kernel _kernel, + cl_uint _work_dim, + const size_t *_global_work_size, + const size_t *_local_work_size) { + thneed = lthneed; + kernel = _kernel; + work_dim = _work_dim; + assert(work_dim <= 3); + for (int i = 0; i < work_dim; i++) { + global_work_size[i] = _global_work_size[i]; + local_work_size[i] = _local_work_size[i]; + } + + char _name[0x100]; + clGetKernelInfo(kernel, CL_KERNEL_FUNCTION_NAME, sizeof(_name), _name, NULL); + name = string(_name); + clGetKernelInfo(kernel, CL_KERNEL_NUM_ARGS, sizeof(num_args), &num_args, NULL); + + // get args + for (int i = 0; i < num_args; i++) { + char arg_name[0x100]; + clGetKernelArgInfo(kernel, i, CL_KERNEL_ARG_NAME, sizeof(arg_name), arg_name, NULL); + arg_names.push_back(string(arg_name)); + clGetKernelArgInfo(kernel, i, CL_KERNEL_ARG_TYPE_NAME, sizeof(arg_name), arg_name, NULL); + arg_types.push_back(string(arg_name)); + + args.push_back(g_args[make_pair(kernel, i)]); + args_size.push_back(g_args_size[make_pair(kernel, i)]); + } + + // get program + clGetKernelInfo(kernel, CL_KERNEL_PROGRAM, sizeof(program), &program, NULL); +} + +int CLQueuedKernel::get_arg_num(const char *search_arg_name) { + for (int i = 0; i < num_args; i++) { + if (arg_names[i] == search_arg_name) return i; + } + printf("failed to find %s in %s\n", search_arg_name, name.c_str()); + assert(false); +} + +cl_int CLQueuedKernel::exec() { + if (kernel == NULL) { + kernel = clCreateKernel(program, name.c_str(), NULL); + arg_names.clear(); + arg_types.clear(); + + for (int j = 0; j < num_args; j++) { + char arg_name[0x100]; + clGetKernelArgInfo(kernel, j, CL_KERNEL_ARG_NAME, sizeof(arg_name), arg_name, NULL); + arg_names.push_back(string(arg_name)); + clGetKernelArgInfo(kernel, j, CL_KERNEL_ARG_TYPE_NAME, sizeof(arg_name), arg_name, NULL); + arg_types.push_back(string(arg_name)); + + cl_int ret; + if (args[j].size() != 0) { + assert(args[j].size() == args_size[j]); + ret = thneed_clSetKernelArg(kernel, j, args[j].size(), args[j].data()); + } else { + ret = thneed_clSetKernelArg(kernel, j, args_size[j], NULL); + } + assert(ret == CL_SUCCESS); + } + } + + if (thneed->debug >= 1) { + debug_print(thneed->debug >= 2); + } + + return clEnqueueNDRangeKernel(thneed->command_queue, + kernel, work_dim, NULL, global_work_size, local_work_size, 0, NULL, NULL); +} + +uint64_t CLQueuedKernel::benchmark() { + uint64_t ret = 0; + int old_record = thneed->record; + thneed->record = 0; + clFinish(thneed->command_queue); + // TODO: benchmarking at a lower level will make this more accurate + for (int i = 0; i < 10; i++) { + uint64_t sb = nanos_since_boot(); + exec(); + clFinish(thneed->command_queue); + uint64_t et = nanos_since_boot() - sb; + if (ret == 0 || et < ret) ret = et; + } + thneed->record = old_record; + return ret; +} + +void CLQueuedKernel::debug_print(bool verbose) { + printf("%p %56s -- ", kernel, name.c_str()); + for (int i = 0; i < work_dim; i++) { + printf("%4zu ", global_work_size[i]); + } + printf(" -- "); + for (int i = 0; i < work_dim; i++) { + printf("%4zu ", local_work_size[i]); + } + printf("\n"); + + if (verbose) { + for (int i = 0; i < num_args; i++) { + string arg = args[i]; + printf(" %s %s", arg_types[i].c_str(), arg_names[i].c_str()); + void *arg_value = (void*)arg.data(); + int arg_size = arg.size(); + if (arg_size == 0) { + printf(" (size) %d", args_size[i]); + } else if (arg_size == 1) { + printf(" = %d", *((char*)arg_value)); + } else if (arg_size == 2) { + printf(" = %d", *((short*)arg_value)); + } else if (arg_size == 4) { + if (arg_types[i] == "float") { + printf(" = %f", *((float*)arg_value)); + } else { + printf(" = %d", *((int*)arg_value)); + } + } else if (arg_size == 8) { + cl_mem val = (cl_mem)(*((uintptr_t*)arg_value)); + printf(" = %p", val); + if (val != NULL) { + if (arg_types[i] == "image2d_t" || arg_types[i] == "image1d_t") { + cl_image_format format; + size_t width, height, depth, array_size, row_pitch, slice_pitch; + cl_mem buf; + clGetImageInfo(val, CL_IMAGE_FORMAT, sizeof(format), &format, NULL); + assert(format.image_channel_order == CL_RGBA); + assert(format.image_channel_data_type == CL_HALF_FLOAT); + clGetImageInfo(val, CL_IMAGE_WIDTH, sizeof(width), &width, NULL); + clGetImageInfo(val, CL_IMAGE_HEIGHT, sizeof(height), &height, NULL); + clGetImageInfo(val, CL_IMAGE_ROW_PITCH, sizeof(row_pitch), &row_pitch, NULL); + clGetImageInfo(val, CL_IMAGE_DEPTH, sizeof(depth), &depth, NULL); + clGetImageInfo(val, CL_IMAGE_ARRAY_SIZE, sizeof(array_size), &array_size, NULL); + clGetImageInfo(val, CL_IMAGE_SLICE_PITCH, sizeof(slice_pitch), &slice_pitch, NULL); + assert(depth == 0); + assert(array_size == 0); + assert(slice_pitch == 0); + + clGetImageInfo(val, CL_IMAGE_BUFFER, sizeof(buf), &buf, NULL); + size_t sz; + clGetMemObjectInfo(buf, CL_MEM_SIZE, sizeof(sz), &sz, NULL); + printf(" image %zu x %zu rp %zu @ %p buffer %zu", width, height, row_pitch, buf, sz); + } else { + size_t sz; + clGetMemObjectInfo(val, CL_MEM_SIZE, sizeof(sz), &sz, NULL); + printf(" buffer %zu", sz); + } + } + } + printf("\n"); + } + } +} diff --git a/selfdrive/modeld/thneed/thneed.h b/selfdrive/modeld/thneed/thneed.h index 65475ccf7f3366..0ccea59a3c3e8a 100644 --- a/selfdrive/modeld/thneed/thneed.h +++ b/selfdrive/modeld/thneed/thneed.h @@ -16,8 +16,6 @@ using namespace std; -cl_int thneed_clSetKernelArg(cl_kernel kernel, cl_uint arg_index, size_t arg_size, const void *arg_value); - namespace json11 { class Json; } @@ -42,6 +40,7 @@ class CLQueuedKernel { const size_t *_global_work_size, const size_t *_local_work_size); cl_int exec(); + uint64_t benchmark(); void debug_print(bool verbose); int get_arg_num(const char *search_arg_name); cl_program program; @@ -90,10 +89,12 @@ class CachedCommand: public CachedIoctl { class Thneed { public: - Thneed(bool do_clinit=false, cl_context _context = NULL); + Thneed(bool do_clinit=false); void stop(); void execute(float **finputs, float *foutput, bool slow=false); void wait(); + int optimize(); + bool run_optimizer = false; vector input_clmem; vector inputs; @@ -109,15 +110,13 @@ class Thneed { bool record = false; int debug; int timestamp; - -#ifdef QCOM2 unique_ptr ram; vector > cmds; int fd; -#endif // all CL kernels - void copy_inputs(float **finputs, bool internal=false); + void find_inputs_outputs(); + void copy_inputs(float **finputs); void copy_output(float *foutput); cl_int clexec(); vector > kq; @@ -125,8 +124,9 @@ class Thneed { // pending CL kernels vector > ckq; - // loading + // loading and saving void load(const char *filename); + void save(const char *filename, bool save_binaries=false); private: void clinit(); }; diff --git a/selfdrive/modeld/thneed/thneed_common.cc b/selfdrive/modeld/thneed/thneed_common.cc deleted file mode 100644 index 21170b13a65712..00000000000000 --- a/selfdrive/modeld/thneed/thneed_common.cc +++ /dev/null @@ -1,216 +0,0 @@ -#include "selfdrive/modeld/thneed/thneed.h" - -#include -#include -#include - -#include "common/clutil.h" -#include "common/timing.h" - -map, string> g_args; -map, int> g_args_size; -map g_program_source; - -void Thneed::stop() { - printf("Thneed::stop: recorded %lu commands\n", cmds.size()); - record = false; -} - -void Thneed::clinit() { - device_id = cl_get_device_id(CL_DEVICE_TYPE_DEFAULT); - if (context == NULL) context = CL_CHECK_ERR(clCreateContext(NULL, 1, &device_id, NULL, NULL, &err)); - //cl_command_queue_properties props[3] = {CL_QUEUE_PROPERTIES, CL_QUEUE_PROFILING_ENABLE, 0}; - cl_command_queue_properties props[3] = {CL_QUEUE_PROPERTIES, 0, 0}; - command_queue = CL_CHECK_ERR(clCreateCommandQueueWithProperties(context, device_id, props, &err)); - printf("Thneed::clinit done\n"); -} - -cl_int Thneed::clexec() { - if (debug >= 1) printf("Thneed::clexec: running %lu queued kernels\n", kq.size()); - for (auto &k : kq) { - if (record) ckq.push_back(k); - cl_int ret = k->exec(); - assert(ret == CL_SUCCESS); - } - return clFinish(command_queue); -} - -void Thneed::copy_inputs(float **finputs, bool internal) { - for (int idx = 0; idx < inputs.size(); ++idx) { - if (debug >= 1) printf("copying %lu -- %p -> %p (cl %p)\n", input_sizes[idx], finputs[idx], inputs[idx], input_clmem[idx]); - - if (internal) { - // if it's internal, using memcpy is fine since the buffer sync is cached in the ioctl layer - if (finputs[idx] != NULL) memcpy(inputs[idx], finputs[idx], input_sizes[idx]); - } else { - if (finputs[idx] != NULL) CL_CHECK(clEnqueueWriteBuffer(command_queue, input_clmem[idx], CL_TRUE, 0, input_sizes[idx], finputs[idx], 0, NULL, NULL)); - } - } -} - -void Thneed::copy_output(float *foutput) { - if (output != NULL) { - size_t sz; - clGetMemObjectInfo(output, CL_MEM_SIZE, sizeof(sz), &sz, NULL); - if (debug >= 1) printf("copying %lu for output %p -> %p\n", sz, output, foutput); - CL_CHECK(clEnqueueReadBuffer(command_queue, output, CL_TRUE, 0, sz, foutput, 0, NULL, NULL)); - } else { - printf("CAUTION: model output is NULL, does it have no outputs?\n"); - } -} - -// *********** CLQueuedKernel *********** - -CLQueuedKernel::CLQueuedKernel(Thneed *lthneed, - cl_kernel _kernel, - cl_uint _work_dim, - const size_t *_global_work_size, - const size_t *_local_work_size) { - thneed = lthneed; - kernel = _kernel; - work_dim = _work_dim; - assert(work_dim <= 3); - for (int i = 0; i < work_dim; i++) { - global_work_size[i] = _global_work_size[i]; - local_work_size[i] = _local_work_size[i]; - } - - char _name[0x100]; - clGetKernelInfo(kernel, CL_KERNEL_FUNCTION_NAME, sizeof(_name), _name, NULL); - name = string(_name); - clGetKernelInfo(kernel, CL_KERNEL_NUM_ARGS, sizeof(num_args), &num_args, NULL); - - // get args - for (int i = 0; i < num_args; i++) { - char arg_name[0x100] = {0}; - clGetKernelArgInfo(kernel, i, CL_KERNEL_ARG_NAME, sizeof(arg_name), arg_name, NULL); - arg_names.push_back(string(arg_name)); - clGetKernelArgInfo(kernel, i, CL_KERNEL_ARG_TYPE_NAME, sizeof(arg_name), arg_name, NULL); - arg_types.push_back(string(arg_name)); - - args.push_back(g_args[make_pair(kernel, i)]); - args_size.push_back(g_args_size[make_pair(kernel, i)]); - } - - // get program - clGetKernelInfo(kernel, CL_KERNEL_PROGRAM, sizeof(program), &program, NULL); -} - -int CLQueuedKernel::get_arg_num(const char *search_arg_name) { - for (int i = 0; i < num_args; i++) { - if (arg_names[i] == search_arg_name) return i; - } - printf("failed to find %s in %s\n", search_arg_name, name.c_str()); - assert(false); -} - -cl_int CLQueuedKernel::exec() { - if (kernel == NULL) { - kernel = clCreateKernel(program, name.c_str(), NULL); - arg_names.clear(); - arg_types.clear(); - - for (int j = 0; j < num_args; j++) { - char arg_name[0x100] = {0}; - clGetKernelArgInfo(kernel, j, CL_KERNEL_ARG_NAME, sizeof(arg_name), arg_name, NULL); - arg_names.push_back(string(arg_name)); - clGetKernelArgInfo(kernel, j, CL_KERNEL_ARG_TYPE_NAME, sizeof(arg_name), arg_name, NULL); - arg_types.push_back(string(arg_name)); - - cl_int ret; - if (args[j].size() != 0) { - assert(args[j].size() == args_size[j]); - ret = thneed_clSetKernelArg(kernel, j, args[j].size(), args[j].data()); - } else { - ret = thneed_clSetKernelArg(kernel, j, args_size[j], NULL); - } - assert(ret == CL_SUCCESS); - } - } - - if (thneed->debug >= 1) { - debug_print(thneed->debug >= 2); - } - - return clEnqueueNDRangeKernel(thneed->command_queue, - kernel, work_dim, NULL, global_work_size, local_work_size, 0, NULL, NULL); -} - -void CLQueuedKernel::debug_print(bool verbose) { - printf("%p %56s -- ", kernel, name.c_str()); - for (int i = 0; i < work_dim; i++) { - printf("%4zu ", global_work_size[i]); - } - printf(" -- "); - for (int i = 0; i < work_dim; i++) { - printf("%4zu ", local_work_size[i]); - } - printf("\n"); - - if (verbose) { - for (int i = 0; i < num_args; i++) { - string arg = args[i]; - printf(" %s %s", arg_types[i].c_str(), arg_names[i].c_str()); - void *arg_value = (void*)arg.data(); - int arg_size = arg.size(); - if (arg_size == 0) { - printf(" (size) %d", args_size[i]); - } else if (arg_size == 1) { - printf(" = %d", *((char*)arg_value)); - } else if (arg_size == 2) { - printf(" = %d", *((short*)arg_value)); - } else if (arg_size == 4) { - if (arg_types[i] == "float") { - printf(" = %f", *((float*)arg_value)); - } else { - printf(" = %d", *((int*)arg_value)); - } - } else if (arg_size == 8) { - cl_mem val = (cl_mem)(*((uintptr_t*)arg_value)); - printf(" = %p", val); - if (val != NULL) { - cl_mem_object_type obj_type; - clGetMemObjectInfo(val, CL_MEM_TYPE, sizeof(obj_type), &obj_type, NULL); - if (arg_types[i] == "image2d_t" || arg_types[i] == "image1d_t" || obj_type == CL_MEM_OBJECT_IMAGE2D) { - cl_image_format format; - size_t width, height, depth, array_size, row_pitch, slice_pitch; - cl_mem buf; - clGetImageInfo(val, CL_IMAGE_FORMAT, sizeof(format), &format, NULL); - assert(format.image_channel_order == CL_RGBA); - assert(format.image_channel_data_type == CL_HALF_FLOAT || format.image_channel_data_type == CL_FLOAT); - clGetImageInfo(val, CL_IMAGE_WIDTH, sizeof(width), &width, NULL); - clGetImageInfo(val, CL_IMAGE_HEIGHT, sizeof(height), &height, NULL); - clGetImageInfo(val, CL_IMAGE_ROW_PITCH, sizeof(row_pitch), &row_pitch, NULL); - clGetImageInfo(val, CL_IMAGE_DEPTH, sizeof(depth), &depth, NULL); - clGetImageInfo(val, CL_IMAGE_ARRAY_SIZE, sizeof(array_size), &array_size, NULL); - clGetImageInfo(val, CL_IMAGE_SLICE_PITCH, sizeof(slice_pitch), &slice_pitch, NULL); - assert(depth == 0); - assert(array_size == 0); - assert(slice_pitch == 0); - - clGetImageInfo(val, CL_IMAGE_BUFFER, sizeof(buf), &buf, NULL); - size_t sz = 0; - if (buf != NULL) clGetMemObjectInfo(buf, CL_MEM_SIZE, sizeof(sz), &sz, NULL); - printf(" image %zu x %zu rp %zu @ %p buffer %zu", width, height, row_pitch, buf, sz); - } else { - size_t sz; - clGetMemObjectInfo(val, CL_MEM_SIZE, sizeof(sz), &sz, NULL); - printf(" buffer %zu", sz); - } - } - } - printf("\n"); - } - } -} - -cl_int thneed_clSetKernelArg(cl_kernel kernel, cl_uint arg_index, size_t arg_size, const void *arg_value) { - g_args_size[make_pair(kernel, arg_index)] = arg_size; - if (arg_value != NULL) { - g_args[make_pair(kernel, arg_index)] = string((char*)arg_value, arg_size); - } else { - g_args[make_pair(kernel, arg_index)] = string(""); - } - cl_int ret = clSetKernelArg(kernel, arg_index, arg_size, arg_value); - return ret; -} diff --git a/selfdrive/modeld/thneed/thneed_pc.cc b/selfdrive/modeld/thneed/thneed_pc.cc deleted file mode 100644 index 8d0037628e2f3d..00000000000000 --- a/selfdrive/modeld/thneed/thneed_pc.cc +++ /dev/null @@ -1,32 +0,0 @@ -#include "selfdrive/modeld/thneed/thneed.h" - -#include - -#include "common/clutil.h" -#include "common/timing.h" - -Thneed::Thneed(bool do_clinit, cl_context _context) { - context = _context; - if (do_clinit) clinit(); - char *thneed_debug_env = getenv("THNEED_DEBUG"); - debug = (thneed_debug_env != NULL) ? atoi(thneed_debug_env) : 0; -} - -void Thneed::execute(float **finputs, float *foutput, bool slow) { - uint64_t tb, te; - if (debug >= 1) tb = nanos_since_boot(); - - // ****** copy inputs - copy_inputs(finputs); - - // ****** run commands - clexec(); - - // ****** copy outputs - copy_output(foutput); - - if (debug >= 1) { - te = nanos_since_boot(); - printf("model exec in %lu us\n", (te-tb)/1000); - } -} diff --git a/selfdrive/modeld/thneed/thneed_qcom2.cc b/selfdrive/modeld/thneed/thneed_qcom2.cc deleted file mode 100644 index a29a82c8c87338..00000000000000 --- a/selfdrive/modeld/thneed/thneed_qcom2.cc +++ /dev/null @@ -1,283 +0,0 @@ -#include "selfdrive/modeld/thneed/thneed.h" - -#include -#include - -#include -#include -#include -#include -#include - -#include "common/clutil.h" -#include "common/timing.h" - -Thneed *g_thneed = NULL; -int g_fd = -1; - -void hexdump(uint8_t *d, int len) { - assert((len%4) == 0); - printf(" dumping %p len 0x%x\n", d, len); - for (int i = 0; i < len/4; i++) { - if (i != 0 && (i%0x10) == 0) printf("\n"); - printf("%8x ", d[i]); - } - printf("\n"); -} - -// *********** ioctl interceptor *********** - -extern "C" { - -int (*my_ioctl)(int filedes, unsigned long request, void *argp) = NULL; -#undef ioctl -int ioctl(int filedes, unsigned long request, void *argp) { - request &= 0xFFFFFFFF; // needed on QCOM2 - if (my_ioctl == NULL) my_ioctl = reinterpret_cast(dlsym(RTLD_NEXT, "ioctl")); - Thneed *thneed = g_thneed; - - // save the fd - if (request == IOCTL_KGSL_GPUOBJ_ALLOC) g_fd = filedes; - - // note that this runs always, even without a thneed object - if (request == IOCTL_KGSL_DRAWCTXT_CREATE) { - struct kgsl_drawctxt_create *create = (struct kgsl_drawctxt_create *)argp; - create->flags &= ~KGSL_CONTEXT_PRIORITY_MASK; - create->flags |= 1 << KGSL_CONTEXT_PRIORITY_SHIFT; // priority from 1-15, 1 is max priority - printf("IOCTL_KGSL_DRAWCTXT_CREATE: creating context with flags 0x%x\n", create->flags); - } - - if (thneed != NULL) { - if (request == IOCTL_KGSL_GPU_COMMAND) { - struct kgsl_gpu_command *cmd = (struct kgsl_gpu_command *)argp; - if (thneed->record) { - thneed->timestamp = cmd->timestamp; - thneed->context_id = cmd->context_id; - thneed->cmds.push_back(unique_ptr(new CachedCommand(thneed, cmd))); - } - if (thneed->debug >= 1) { - printf("IOCTL_KGSL_GPU_COMMAND(%2zu): flags: 0x%lx context_id: %u timestamp: %u numcmds: %d numobjs: %d\n", - thneed->cmds.size(), - cmd->flags, - cmd->context_id, cmd->timestamp, cmd->numcmds, cmd->numobjs); - } - } else if (request == IOCTL_KGSL_GPUOBJ_SYNC) { - struct kgsl_gpuobj_sync *cmd = (struct kgsl_gpuobj_sync *)argp; - struct kgsl_gpuobj_sync_obj *objs = (struct kgsl_gpuobj_sync_obj *)(cmd->objs); - - if (thneed->debug >= 2) { - printf("IOCTL_KGSL_GPUOBJ_SYNC count:%d ", cmd->count); - for (int i = 0; i < cmd->count; i++) { - printf(" -- offset:0x%lx len:0x%lx id:%d op:%d ", objs[i].offset, objs[i].length, objs[i].id, objs[i].op); - } - printf("\n"); - } - - if (thneed->record) { - thneed->cmds.push_back(unique_ptr(new - CachedSync(thneed, string((char *)objs, sizeof(struct kgsl_gpuobj_sync_obj)*cmd->count)))); - } - } else if (request == IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID) { - struct kgsl_device_waittimestamp_ctxtid *cmd = (struct kgsl_device_waittimestamp_ctxtid *)argp; - if (thneed->debug >= 1) { - printf("IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID: context_id: %d timestamp: %d timeout: %d\n", - cmd->context_id, cmd->timestamp, cmd->timeout); - } - } else if (request == IOCTL_KGSL_SETPROPERTY) { - if (thneed->debug >= 1) { - struct kgsl_device_getproperty *prop = (struct kgsl_device_getproperty *)argp; - printf("IOCTL_KGSL_SETPROPERTY: 0x%x sizebytes:%zu\n", prop->type, prop->sizebytes); - if (thneed->debug >= 2) { - hexdump((uint8_t *)prop->value, prop->sizebytes); - if (prop->type == KGSL_PROP_PWR_CONSTRAINT) { - struct kgsl_device_constraint *constraint = (struct kgsl_device_constraint *)prop->value; - hexdump((uint8_t *)constraint->data, constraint->size); - } - } - } - } else if (request == IOCTL_KGSL_DRAWCTXT_CREATE || request == IOCTL_KGSL_DRAWCTXT_DESTROY) { - // this happens - } else if (request == IOCTL_KGSL_GPUOBJ_ALLOC || request == IOCTL_KGSL_GPUOBJ_FREE) { - // this happens - } else { - if (thneed->debug >= 1) { - printf("other ioctl %lx\n", request); - } - } - } - - int ret = my_ioctl(filedes, request, argp); - if (ret != 0) printf("ioctl returned %d with errno %d\n", ret, errno); - return ret; -} - -} - -// *********** GPUMalloc *********** - -GPUMalloc::GPUMalloc(int size, int fd) { - struct kgsl_gpuobj_alloc alloc; - memset(&alloc, 0, sizeof(alloc)); - alloc.size = size; - alloc.flags = 0x10000a00; - ioctl(fd, IOCTL_KGSL_GPUOBJ_ALLOC, &alloc); - void *addr = mmap64(NULL, alloc.mmapsize, 0x3, 0x1, fd, alloc.id*0x1000); - assert(addr != MAP_FAILED); - - base = (uint64_t)addr; - remaining = size; -} - -GPUMalloc::~GPUMalloc() { - // TODO: free the GPU malloced area -} - -void *GPUMalloc::alloc(int size) { - void *ret = (void*)base; - size = (size+0xff) & (~0xFF); - assert(size <= remaining); - remaining -= size; - base += size; - return ret; -} - -// *********** CachedSync, at the ioctl layer *********** - -void CachedSync::exec() { - struct kgsl_gpuobj_sync cmd; - - cmd.objs = (uint64_t)data.data(); - cmd.obj_len = data.length(); - cmd.count = data.length() / sizeof(struct kgsl_gpuobj_sync_obj); - - int ret = ioctl(thneed->fd, IOCTL_KGSL_GPUOBJ_SYNC, &cmd); - assert(ret == 0); -} - -// *********** CachedCommand, at the ioctl layer *********** - -CachedCommand::CachedCommand(Thneed *lthneed, struct kgsl_gpu_command *cmd) { - thneed = lthneed; - assert(cmd->numsyncs == 0); - - memcpy(&cache, cmd, sizeof(cache)); - - if (cmd->numcmds > 0) { - cmds = make_unique(cmd->numcmds); - memcpy(cmds.get(), (void *)cmd->cmdlist, sizeof(struct kgsl_command_object)*cmd->numcmds); - cache.cmdlist = (uint64_t)cmds.get(); - for (int i = 0; i < cmd->numcmds; i++) { - void *nn = thneed->ram->alloc(cmds[i].size); - memcpy(nn, (void*)cmds[i].gpuaddr, cmds[i].size); - cmds[i].gpuaddr = (uint64_t)nn; - } - } - - if (cmd->numobjs > 0) { - objs = make_unique(cmd->numobjs); - memcpy(objs.get(), (void *)cmd->objlist, sizeof(struct kgsl_command_object)*cmd->numobjs); - cache.objlist = (uint64_t)objs.get(); - for (int i = 0; i < cmd->numobjs; i++) { - void *nn = thneed->ram->alloc(objs[i].size); - memset(nn, 0, objs[i].size); - objs[i].gpuaddr = (uint64_t)nn; - } - } - - kq = thneed->ckq; - thneed->ckq.clear(); -} - -void CachedCommand::exec() { - cache.timestamp = ++thneed->timestamp; - int ret = ioctl(thneed->fd, IOCTL_KGSL_GPU_COMMAND, &cache); - - if (thneed->debug >= 1) printf("CachedCommand::exec got %d\n", ret); - - if (thneed->debug >= 2) { - for (auto &it : kq) { - it->debug_print(false); - } - } - - assert(ret == 0); -} - -// *********** Thneed *********** - -Thneed::Thneed(bool do_clinit, cl_context _context) { - // TODO: QCOM2 actually requires a different context - //context = _context; - if (do_clinit) clinit(); - assert(g_fd != -1); - fd = g_fd; - ram = make_unique(0x80000, fd); - timestamp = -1; - g_thneed = this; - char *thneed_debug_env = getenv("THNEED_DEBUG"); - debug = (thneed_debug_env != NULL) ? atoi(thneed_debug_env) : 0; -} - -void Thneed::wait() { - struct kgsl_device_waittimestamp_ctxtid wait; - wait.context_id = context_id; - wait.timestamp = timestamp; - wait.timeout = -1; - - uint64_t tb = nanos_since_boot(); - int wret = ioctl(fd, IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID, &wait); - uint64_t te = nanos_since_boot(); - - if (debug >= 1) printf("wait %d after %lu us\n", wret, (te-tb)/1000); -} - -void Thneed::execute(float **finputs, float *foutput, bool slow) { - uint64_t tb, te; - if (debug >= 1) tb = nanos_since_boot(); - - // ****** copy inputs - copy_inputs(finputs, true); - - // ****** set power constraint - int ret; - struct kgsl_device_constraint_pwrlevel pwrlevel; - pwrlevel.level = KGSL_CONSTRAINT_PWR_MAX; - - struct kgsl_device_constraint constraint; - constraint.type = KGSL_CONSTRAINT_PWRLEVEL; - constraint.context_id = context_id; - constraint.data = (void*)&pwrlevel; - constraint.size = sizeof(pwrlevel); - - struct kgsl_device_getproperty prop; - prop.type = KGSL_PROP_PWR_CONSTRAINT; - prop.value = (void*)&constraint; - prop.sizebytes = sizeof(constraint); - ret = ioctl(fd, IOCTL_KGSL_SETPROPERTY, &prop); - assert(ret == 0); - - // ****** run commands - int i = 0; - for (auto &it : cmds) { - ++i; - if (debug >= 1) printf("run %2d @ %7lu us: ", i, (nanos_since_boot()-tb)/1000); - it->exec(); - if ((i == cmds.size()) || slow) wait(); - } - - // ****** copy outputs - copy_output(foutput); - - // ****** unset power constraint - constraint.type = KGSL_CONSTRAINT_NONE; - constraint.data = NULL; - constraint.size = 0; - - ret = ioctl(fd, IOCTL_KGSL_SETPROPERTY, &prop); - assert(ret == 0); - - if (debug >= 1) { - te = nanos_since_boot(); - printf("model exec in %lu us\n", (te-tb)/1000); - } -} diff --git a/selfdrive/modeld/thneed/weights_fixup.py b/selfdrive/modeld/thneed/weights_fixup.py new file mode 100755 index 00000000000000..539b1b5d326160 --- /dev/null +++ b/selfdrive/modeld/thneed/weights_fixup.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python3 +import os +import struct +import zipfile +import numpy as np +from tqdm import tqdm + +from common.basedir import BASEDIR +from selfdrive.modeld.thneed.lib import load_thneed, save_thneed + +# this is junk code, but it doesn't have deps +def load_dlc_weights(fn): + archive = zipfile.ZipFile(fn, 'r') + dlc_params = archive.read("model.params") + + def extract(rdat): + idx = rdat.find(b"\x00\x00\x00\x09\x04\x00\x00\x00") + rdat = rdat[idx+8:] + ll = struct.unpack("I", rdat[0:4])[0] + buf = np.frombuffer(rdat[4:4+ll*4], dtype=np.float32) + rdat = rdat[4+ll*4:] + dims = struct.unpack("I", rdat[0:4])[0] + buf = buf.reshape(struct.unpack("I"*dims, rdat[4:4+dims*4])) + if len(buf.shape) == 4: + buf = np.transpose(buf, (3,2,0,1)) + return buf + + def parse(tdat): + ll = struct.unpack("I", tdat[0:4])[0] + 4 + return (None, [extract(tdat[0:]), extract(tdat[ll:])]) + + ptr = 0x20 + def r4(): + nonlocal ptr + ret = struct.unpack("I", dlc_params[ptr:ptr+4])[0] + ptr += 4 + return ret + ranges = [] + cnt = r4() + for _ in range(cnt): + o = r4() + ptr + # the header is 0xC + plen, is_4, is_2 = struct.unpack("III", dlc_params[o:o+0xC]) + assert is_4 == 4 and is_2 == 2 + ranges.append((o+0xC, o+plen+0xC)) + ranges = sorted(ranges, reverse=True) + + return [parse(dlc_params[s:e]) for s,e in ranges] + +# this won't run on device without onnx +def load_onnx_weights(fn): + import onnx + from onnx import numpy_helper + + model = onnx.load(fn) + graph = model.graph # pylint: disable=maybe-no-member + init = {x.name:x for x in graph.initializer} + + onnx_layers = [] + for node in graph.node: + #print(node.name, node.op_type, node.input, node.output) + vals = [] + for inp in node.input: + if inp in init: + vals.append(numpy_helper.to_array(init[inp])) + if len(vals) > 0: + onnx_layers.append((node.name, vals)) + return onnx_layers + +def weights_fixup(target, source_thneed, dlc): + #onnx_layers = load_onnx_weights(os.path.join(BASEDIR, "models/supercombo.onnx")) + onnx_layers = load_dlc_weights(dlc) + jdat = load_thneed(source_thneed) + + bufs = {} + for o in jdat['objects']: + bufs[o['id']] = o + + thneed_layers = [] + for k in jdat['kernels']: + #print(k['name']) + vals = [] + for a in k['args']: + if a in bufs: + o = bufs[a] + if o['needs_load'] or ('buffer_id' in o and bufs[o['buffer_id']]['needs_load']): + #print(" ", o['arg_type']) + vals.append(o) + if len(vals) > 0: + thneed_layers.append((k['name'], vals)) + + assert len(thneed_layers) == len(onnx_layers) + + # fix up weights + for tl, ol in tqdm(zip(thneed_layers, onnx_layers), total=len(thneed_layers)): + #print(tl[0], ol[0]) + assert len(tl[1]) == len(ol[1]) + for o, onnx_weight in zip(tl[1], ol[1]): + if o['arg_type'] == "image2d_t": + obuf = bufs[o['buffer_id']] + saved_weights = np.frombuffer(obuf['data'], dtype=np.float16).reshape(o['height'], o['row_pitch']//2) + + if len(onnx_weight.shape) == 4: + # convolution + oc,ic,ch,cw = onnx_weight.shape + + if 'depthwise' in tl[0]: + assert ic == 1 + weights = np.transpose(onnx_weight.reshape(oc//4,4,ch,cw), (0,2,3,1)).reshape(o['height'], o['width']*4) + else: + weights = np.transpose(onnx_weight.reshape(oc//4,4,ic//4,4,ch,cw), (0,4,2,5,1,3)).reshape(o['height'], o['width']*4) + else: + # fc_Wtx + weights = onnx_weight + + new_weights = np.zeros((o['height'], o['row_pitch']//2), dtype=np.float32) + new_weights[:, :weights.shape[1]] = weights + + # weights shouldn't be too far off + err = np.mean((saved_weights.astype(np.float32) - new_weights)**2) + assert err < 1e-3 + rerr = np.mean(np.abs((saved_weights.astype(np.float32) - new_weights)/(new_weights+1e-12))) + assert rerr < 0.5 + + # fix should improve things + fixed_err = np.mean((new_weights.astype(np.float16).astype(np.float32) - new_weights)**2) + assert (err/fixed_err) >= 1 + + #print(" ", o['size'], onnx_weight.shape, o['row_pitch'], o['width'], o['height'], "err %.2fx better" % (err/fixed_err)) + + obuf['data'] = new_weights.astype(np.float16).tobytes() + + elif o['arg_type'] == "float*": + # unconverted floats are correct + new_weights = np.zeros(o['size']//4, dtype=np.float32) + new_weights[:onnx_weight.shape[0]] = onnx_weight + assert new_weights.tobytes() == o['data'] + #print(" ", o['size'], onnx_weight.shape) + + save_thneed(jdat, target) + +if __name__ == "__main__": + model_dir = os.path.join(BASEDIR, "selfdrive/modeld/models/") + weights_fixup(os.path.join(model_dir, "supercombo_fixed.thneed"), + os.path.join(model_dir, "supercombo.thneed"), + os.path.join(model_dir, "supercombo.dlc")) diff --git a/selfdrive/modeld/transforms/transform.cc b/selfdrive/modeld/transforms/transform.cc index f341314144ec02..cabc58a46d8337 100644 --- a/selfdrive/modeld/transforms/transform.cc +++ b/selfdrive/modeld/transforms/transform.cc @@ -32,7 +32,7 @@ void transform_queue(Transform* s, const int zero = 0; // sampled using pixel center origin - // (because that's how fastcv and opencv does it) + // (because thats how fastcv and opencv does it) mat3 projection_y = projection; diff --git a/selfdrive/navd/navd.py b/selfdrive/navd/navd.py index 72874b2113d19f..3c2a7f555dd2ae 100755 --- a/selfdrive/navd/navd.py +++ b/selfdrive/navd/navd.py @@ -135,7 +135,7 @@ def calculate_route(self, destination): url = self.mapbox_host + f'/directions/v5/mapbox/driving-traffic/{self.last_position.longitude},{self.last_position.latitude};{destination.longitude},{destination.latitude}' try: - resp = requests.get(url, params=params, timeout=10) + resp = requests.get(url, params=params) resp.raise_for_status() r = resp.json() @@ -194,10 +194,10 @@ def send_instruction(self): parse_banner_instructions(msg.navInstruction, step['bannerInstructions'], distance_to_maneuver_along_geometry) # Compute total remaining time and distance - remaining = 1.0 - along_geometry / max(step['distance'], 1) - total_distance = step['distance'] * remaining - total_time = step['duration'] * remaining - total_time_typical = step['duration_typical'] * remaining + remaning = 1.0 - along_geometry / max(step['distance'], 1) + total_distance = step['distance'] * remaning + total_time = step['duration'] * remaning + total_time_typical = step['duration_typical'] * remaning # Add up totals for future steps for i in range(self.step_idx + 1, len(self.route)): diff --git a/selfdrive/sensord/pigeond.py b/selfdrive/sensord/pigeond.py index e38e2d4c33143d..95a27189d0842f 100755 --- a/selfdrive/sensord/pigeond.py +++ b/selfdrive/sensord/pigeond.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 + import sys import time import signal @@ -7,7 +8,6 @@ import requests import urllib.parse from datetime import datetime -from typing import List, Optional from cereal import messaging from common.params import Params @@ -25,7 +25,7 @@ UBLOX_BACKUP_RESTORE_MSG = b"\xb5\x62\x09\x14\x08\x00\x03" UBLOX_ASSIST_ACK = b"\xb5\x62\x13\x60\x08\x00" -def set_power(enabled: bool) -> None: +def set_power(enabled): gpio_init(GPIO.UBLOX_SAFEBOOT_N, True) gpio_init(GPIO.UBLOX_PWR_EN, True) gpio_init(GPIO.UBLOX_RST_N, True) @@ -35,14 +35,14 @@ def set_power(enabled: bool) -> None: gpio_set(GPIO.UBLOX_RST_N, enabled) -def add_ubx_checksum(msg: bytes) -> bytes: +def add_ubx_checksum(msg): A = B = 0 for b in msg[2:]: A = (A + b) % 256 B = (B + A) % 256 return msg + bytes([A, B]) -def get_assistnow_messages(token: bytes) -> List[bytes]: +def get_assistnow_messages(token): # make request # TODO: implement adding the last known location r = requests.get("https://online-live2.services.u-blox.com/GetOnlineData.ashx", params=urllib.parse.urlencode({ @@ -64,13 +64,14 @@ def get_assistnow_messages(token: bytes) -> List[bytes]: class TTYPigeon(): - def __init__(self): + def __init__(self, path): + self.path = path self.tty = serial.VTIMESerial(UBLOX_TTY, baudrate=9600, timeout=0) - def send(self, dat: bytes) -> None: + def send(self, dat): self.tty.write(dat) - def receive(self) -> bytes: + def receive(self): dat = b'' while len(dat) < 0x1000: d = self.tty.read(0x40) @@ -79,10 +80,10 @@ def receive(self) -> bytes: break return dat - def set_baud(self, baud: int) -> None: + def set_baud(self, baud): self.tty.baudrate = baud - def wait_for_ack(self, ack: bytes = UBLOX_ACK, nack: bytes = UBLOX_NACK, timeout: float = 0.5) -> bool: + def wait_for_ack(self, ack=UBLOX_ACK, nack=UBLOX_NACK, timeout=0.5): dat = b'' st = time.monotonic() while True: @@ -98,11 +99,11 @@ def wait_for_ack(self, ack: bytes = UBLOX_ACK, nack: bytes = UBLOX_NACK, timeout raise TimeoutError('No response from ublox') time.sleep(0.001) - def send_with_ack(self, dat: bytes, ack: bytes = UBLOX_ACK, nack: bytes = UBLOX_NACK) -> None: + def send_with_ack(self, dat, ack=UBLOX_ACK, nack=UBLOX_NACK): self.send(dat) self.wait_for_ack(ack, nack) - def wait_for_backup_restore_status(self, timeout: float = 1.) -> int: + def wait_for_backup_restore_status(self, timeout=1): dat = b'' st = time.monotonic() while True: @@ -116,7 +117,7 @@ def wait_for_backup_restore_status(self, timeout: float = 1.) -> int: time.sleep(0.001) -def initialize_pigeon(pigeon: TTYPigeon) -> None: +def initialize_pigeon(pigeon): # try initializing a few times for _ in range(10): try: @@ -199,22 +200,21 @@ def initialize_pigeon(pigeon: TTYPigeon) -> None: except TimeoutError: cloudlog.warning("Initialization failed, trying again!") -def deinitialize_and_exit(pigeon: Optional[TTYPigeon]): +def deinitialize_and_exit(pigeon): cloudlog.warning("Storing almanac in ublox flash") - if pigeon is not None: - # controlled GNSS stop - pigeon.send(b"\xB5\x62\x06\x04\x04\x00\x00\x00\x08\x00\x16\x74") + # controlled GNSS stop + pigeon.send(b"\xB5\x62\x06\x04\x04\x00\x00\x00\x08\x00\x16\x74") - # store almanac in flash - pigeon.send(b"\xB5\x62\x09\x14\x04\x00\x00\x00\x00\x00\x21\xEC") - try: - if pigeon.wait_for_ack(ack=UBLOX_SOS_ACK, nack=UBLOX_SOS_NACK): - cloudlog.warning("Done storing almanac") - else: - cloudlog.error("Error storing almanac") - except TimeoutError: - pass + # store almanac in flash + pigeon.send(b"\xB5\x62\x09\x14\x04\x00\x00\x00\x00\x00\x21\xEC") + try: + if pigeon.wait_for_ack(ack=UBLOX_SOS_ACK, nack=UBLOX_SOS_NACK): + cloudlog.warning("Done storing almanac") + else: + cloudlog.error("Error storing almanac") + except TimeoutError: + pass # turn off power and exit cleanly set_power(False) @@ -223,10 +223,6 @@ def deinitialize_and_exit(pigeon: Optional[TTYPigeon]): def main(): assert TICI, "unsupported hardware for pigeond" - # register exit handler - pigeon = None - signal.signal(signal.SIGINT, lambda sig, frame: deinitialize_and_exit(pigeon)) - pm = messaging.PubMaster(['ubloxRaw']) # power cycle ublox @@ -235,9 +231,12 @@ def main(): set_power(True) time.sleep(0.5) - pigeon = TTYPigeon() + pigeon = TTYPigeon(UBLOX_TTY) initialize_pigeon(pigeon) + # register exit handler + signal.signal(signal.SIGINT, lambda sig, frame: deinitialize_and_exit(pigeon)) + # start receiving data while True: dat = pigeon.receive() diff --git a/selfdrive/sensord/sensors/lsm6ds3_accel.cc b/selfdrive/sensord/sensors/lsm6ds3_accel.cc index d923986dbe2f51..bcac7de9f7adc5 100644 --- a/selfdrive/sensord/sensors/lsm6ds3_accel.cc +++ b/selfdrive/sensord/sensors/lsm6ds3_accel.cc @@ -27,7 +27,7 @@ int LSM6DS3_Accel::init() { source = cereal::SensorEventData::SensorSource::LSM6DS3TRC; } - // TODO: set scale and bandwidth. Default is +- 2G, 50 Hz + // TODO: set scale and bandwith. Default is +- 2G, 50 Hz ret = set_register(LSM6DS3_ACCEL_I2C_REG_CTRL1_XL, LSM6DS3_ACCEL_ODR_104HZ); if (ret < 0) { goto fail; diff --git a/selfdrive/sensord/__init__.py b/selfdrive/sensord/test/__init__.py similarity index 100% rename from selfdrive/sensord/__init__.py rename to selfdrive/sensord/test/__init__.py diff --git a/selfdrive/sensord/tests/test_sensord.py b/selfdrive/sensord/test/test_sensord.py similarity index 100% rename from selfdrive/sensord/tests/test_sensord.py rename to selfdrive/sensord/test/test_sensord.py diff --git a/selfdrive/sensord/tests/ttff_test.py b/selfdrive/sensord/test/ttff_test.py similarity index 100% rename from selfdrive/sensord/tests/ttff_test.py rename to selfdrive/sensord/test/ttff_test.py diff --git a/selfdrive/sensord/tests/__init__.py b/selfdrive/sensord/tests/__init__.py deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/selfdrive/sensord/tests/test_pigeond.py b/selfdrive/sensord/tests/test_pigeond.py deleted file mode 100755 index d15b731d0c3f20..00000000000000 --- a/selfdrive/sensord/tests/test_pigeond.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python3 -import time -import unittest - -import cereal.messaging as messaging -from cereal.services import service_list -from common.gpio import gpio_read -from selfdrive.test.helpers import with_processes -from selfdrive.manager.process_config import managed_processes -from system.hardware import TICI -from system.hardware.tici.pins import GPIO - - -# TODO: test TTFF when we have good A-GNSS -class TestPigeond(unittest.TestCase): - @classmethod - def setUpClass(cls): - if not TICI: - raise unittest.SkipTest - - def tearDown(self): - managed_processes['pigeond'].stop() - - @with_processes(['pigeond']) - def test_frequency(self): - sm = messaging.SubMaster(['ubloxRaw']) - - # setup time - time.sleep(2) - sm.update() - - for _ in range(int(10 * service_list['ubloxRaw'].frequency)): - sm.update() - assert sm.all_checks() - - def test_startup_time(self): - for _ in range(5): - sm = messaging.SubMaster(['ubloxRaw']) - managed_processes['pigeond'].start() - - start_time = time.monotonic() - for __ in range(10): - sm.update(1 * 1000) - if sm.updated['ubloxRaw']: - break - assert sm.rcv_frame['ubloxRaw'] > 0, "pigeond didn't start outputting messages in time" - - et = time.monotonic() - start_time - assert et < 5, f"pigeond took {et:.1f}s to start" - managed_processes['pigeond'].stop() - - def test_turns_off_ublox(self): - for s in (0.1, 0.5, 1, 5): - managed_processes['pigeond'].start() - time.sleep(s) - managed_processes['pigeond'].stop() - - assert gpio_read(GPIO.UBLOX_RST_N) == 0 - assert gpio_read(GPIO.UBLOX_PWR_EN) == 0 - - -if __name__ == "__main__": - unittest.main() diff --git a/selfdrive/test/longitudinal_maneuvers/plant.py b/selfdrive/test/longitudinal_maneuvers/plant.py index b11f6bef3597db..3bd50ebcfaa68c 100755 --- a/selfdrive/test/longitudinal_maneuvers/plant.py +++ b/selfdrive/test/longitudinal_maneuvers/plant.py @@ -54,7 +54,6 @@ def step(self, v_lead=0.0, prob=1.0, v_cruise=50.): radar = messaging.new_message('radarState') control = messaging.new_message('controlsState') car_state = messaging.new_message('carState') - model = messaging.new_message('modelV2') a_lead = (v_lead - self.v_lead_prev)/self.ts self.v_lead_prev = v_lead @@ -96,8 +95,7 @@ def step(self, v_lead=0.0, prob=1.0, v_cruise=50.): # ******** get controlsState messages for plotting *** sm = {'radarState': radar.radarState, 'carState': car_state.carState, - 'controlsState': control.controlsState, - 'modelV2': model.modelV2} + 'controlsState': control.controlsState} self.planner.update(sm) self.speed = self.planner.v_desired_filter.x self.acceleration = self.planner.a_desired diff --git a/selfdrive/test/process_replay/model_replay.py b/selfdrive/test/process_replay/model_replay.py index ccd89bea9a0f06..d2090aa76aa625 100755 --- a/selfdrive/test/process_replay/model_replay.py +++ b/selfdrive/test/process_replay/model_replay.py @@ -173,7 +173,7 @@ def model_replay(lr, frs): 'driverStateV2.modelExecutionTime', 'driverStateV2.dspExecutionTime' ] - # TODO this tolerance is absurdly large + # TODO this tolerence is absurdly large tolerance = 5e-1 if PC else None results: Any = {TEST_ROUTE: {}} log_paths: Any = {TEST_ROUTE: {"models": {'ref': BASE_URL + log_fn, 'new': log_fn}}} diff --git a/selfdrive/test/process_replay/model_replay_ref_commit b/selfdrive/test/process_replay/model_replay_ref_commit index 958d3da14df35b..80be9b464f5ca5 100644 --- a/selfdrive/test/process_replay/model_replay_ref_commit +++ b/selfdrive/test/process_replay/model_replay_ref_commit @@ -1 +1 @@ -c40319a454840d8a2196ec1227d27b536ee14375 +ca90e11f8d59902af38d3785ddd91a27d0fbb411 diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 672763461a1b86..f77f244594f725 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -5cb8e7ea92f333bdb49682b0593ab2ae5a5f3824 +656daeb9de3680258527500ecae4ddff323b2e59 \ No newline at end of file diff --git a/selfdrive/thermald/power_monitoring.py b/selfdrive/thermald/power_monitoring.py index 7834569088d288..2d2ff5a147d695 100644 --- a/selfdrive/thermald/power_monitoring.py +++ b/selfdrive/thermald/power_monitoring.py @@ -15,9 +15,9 @@ CAR_BATTERY_CAPACITY_uWh = 30e6 CAR_CHARGING_RATE_W = 45 -VBATT_PAUSE_CHARGING = 11.0 # Lower limit on the LPF car battery voltage +VBATT_PAUSE_CHARGING = 11.8 # Lower limit on the LPF car battery voltage VBATT_INSTANT_PAUSE_CHARGING = 7.0 # Lower limit on the instant car battery voltage measurements to avoid triggering on instant power loss -MAX_TIME_OFFROAD_S = 30*3600 +MAX_TIME_OFFROAD_S = 5*3600 MIN_ON_TIME_S = 3600 class PowerMonitoring: @@ -108,19 +108,32 @@ def get_power_used(self) -> int: def get_car_battery_capacity(self) -> int: return int(self.car_battery_capacity_uWh) + # See if we need to disable charging + def should_disable_charging(self, ignition: bool, in_car: bool, offroad_timestamp: Optional[float]) -> bool: + if offroad_timestamp is None: + return False + + now = sec_since_boot() + disable_charging = False + disable_charging |= (now - offroad_timestamp) > MAX_TIME_OFFROAD_S + disable_charging |= (self.car_voltage_mV < (VBATT_PAUSE_CHARGING * 1e3)) and (self.car_voltage_instant_mV > (VBATT_INSTANT_PAUSE_CHARGING * 1e3)) + disable_charging |= (self.car_battery_capacity_uWh <= 0) + disable_charging &= not ignition + disable_charging &= (not self.params.get_bool("DisablePowerDown")) + disable_charging &= in_car + disable_charging |= self.params.get_bool("ForcePowerDown") + return disable_charging + # See if we need to shutdown - def should_shutdown(self, ignition: bool, in_car: bool, offroad_timestamp: Optional[float], started_seen: bool): + def should_shutdown(self, peripheralState, ignition, in_car, offroad_timestamp, started_seen): if offroad_timestamp is None: return False now = sec_since_boot() + panda_charging = (peripheralState.usbPowerMode != log.PeripheralState.UsbPowerMode.client) + should_shutdown = False - should_shutdown |= (now - offroad_timestamp) > MAX_TIME_OFFROAD_S - should_shutdown |= (self.car_voltage_mV < (VBATT_PAUSE_CHARGING * 1e3)) and (self.car_voltage_instant_mV > (VBATT_INSTANT_PAUSE_CHARGING * 1e3)) - should_shutdown |= (self.car_battery_capacity_uWh <= 0) - should_shutdown &= not ignition - should_shutdown &= (not self.params.get_bool("DisablePowerDown")) - should_shutdown &= in_car - should_shutdown |= self.params.get_bool("ForcePowerDown") + # Wait until we have shut down charging before powering down + should_shutdown |= (not panda_charging and self.should_disable_charging(ignition, in_car, offroad_timestamp)) should_shutdown &= started_seen or (now > MIN_ON_TIME_S) return should_shutdown diff --git a/selfdrive/thermald/tests/test_power_monitoring.py b/selfdrive/thermald/tests/test_power_monitoring.py index 5d7463d455d1f9..adcdaf427d0585 100755 --- a/selfdrive/thermald/tests/test_power_monitoring.py +++ b/selfdrive/thermald/tests/test_power_monitoring.py @@ -129,8 +129,8 @@ def test_max_time_offroad(self, hw_type): while ssb <= start_time + MOCKED_MAX_OFFROAD_TIME: pm.calculate(peripheralState, ignition) if (ssb - start_time) % 1000 == 0 and ssb < start_time + MOCKED_MAX_OFFROAD_TIME: - self.assertFalse(pm.should_shutdown(ignition, True, start_time, False)) - self.assertTrue(pm.should_shutdown(ignition, True, start_time, False)) + self.assertFalse(pm.should_disable_charging(ignition, True, start_time)) + self.assertTrue(pm.should_disable_charging(ignition, True, start_time)) # Test to check policy of stopping charging when the car voltage is too low @parameterized.expand(ALL_PANDA_TYPES) @@ -145,8 +145,8 @@ def test_car_voltage(self, hw_type): for i in range(TEST_TIME): pm.calculate(peripheralState, ignition) if i % 10 == 0: - self.assertEqual(pm.should_shutdown(ignition, True, ssb, True), (pm.car_voltage_mV < VBATT_PAUSE_CHARGING*1e3)) - self.assertTrue(pm.should_shutdown(ignition, True, ssb, True)) + self.assertEqual(pm.should_disable_charging(ignition, True, ssb), (pm.car_voltage_mV < VBATT_PAUSE_CHARGING*1e3)) + self.assertTrue(pm.should_disable_charging(ignition, True, ssb)) # Test to check policy of not stopping charging when DisablePowerDown is set def test_disable_power_down(self): @@ -161,8 +161,8 @@ def test_disable_power_down(self): for i in range(TEST_TIME): pm.calculate(peripheralState, ignition) if i % 10 == 0: - self.assertFalse(pm.should_shutdown(ignition, True, ssb, False)) - self.assertFalse(pm.should_shutdown(ignition, True, ssb, False)) + self.assertFalse(pm.should_disable_charging(ignition, True, ssb)) + self.assertFalse(pm.should_disable_charging(ignition, True, ssb)) # Test to check policy of not stopping charging when ignition def test_ignition(self): @@ -176,8 +176,8 @@ def test_ignition(self): for i in range(TEST_TIME): pm.calculate(peripheralState, ignition) if i % 10 == 0: - self.assertFalse(pm.should_shutdown(ignition, True, ssb, False)) - self.assertFalse(pm.should_shutdown(ignition, True, ssb, False)) + self.assertFalse(pm.should_disable_charging(ignition, True, ssb)) + self.assertFalse(pm.should_disable_charging(ignition, True, ssb)) # Test to check policy of not stopping charging when harness is not connected def test_harness_connection(self): @@ -192,8 +192,8 @@ def test_harness_connection(self): for i in range(TEST_TIME): pm.calculate(peripheralState, ignition) if i % 10 == 0: - self.assertFalse(pm.should_shutdown(ignition, False, ssb, False)) - self.assertFalse(pm.should_shutdown(ignition, False, ssb, False)) + self.assertFalse(pm.should_disable_charging(ignition, False,ssb)) + self.assertFalse(pm.should_disable_charging(ignition, False, ssb)) if __name__ == "__main__": unittest.main() diff --git a/selfdrive/thermald/thermald.py b/selfdrive/thermald/thermald.py index 5c2fbd68253573..c765af664f7557 100755 --- a/selfdrive/thermald/thermald.py +++ b/selfdrive/thermald/thermald.py @@ -177,6 +177,7 @@ def thermald_thread(end_event, hw_queue): modem_temps=[], ) + current_filter = FirstOrderFilter(0., CURRENT_TAU, DT_TRML) temp_filter = FirstOrderFilter(0., TEMP_TAU, DT_TRML) should_start_prev = False in_car = False @@ -238,6 +239,8 @@ def thermald_thread(end_event, hw_queue): msg.deviceState.modemTempC = last_hw_state.modem_temps msg.deviceState.screenBrightnessPercent = HARDWARE.get_screen_brightness() + msg.deviceState.usbOnline = HARDWARE.get_usb_present() + current_filter.update(msg.deviceState.batteryCurrent / 1e6) max_comp_temp = temp_filter.update( max(max(msg.deviceState.cpuTempC), msg.deviceState.memoryTempC, max(msg.deviceState.gpuTempC)) @@ -347,11 +350,15 @@ def thermald_thread(end_event, hw_queue): statlog.sample("som_power_draw", som_power_draw) msg.deviceState.somPowerDrawW = som_power_draw + # Check if we need to disable charging (handled by boardd) + msg.deviceState.chargingDisabled = power_monitor.should_disable_charging(onroad_conditions["ignition"], in_car, off_ts) + # Check if we need to shut down - if power_monitor.should_shutdown(onroad_conditions["ignition"], in_car, off_ts, started_seen): + if power_monitor.should_shutdown(peripheralState, onroad_conditions["ignition"], in_car, off_ts, started_seen): cloudlog.warning(f"shutting device down, offroad since {off_ts}") params.put_bool("DoShutdown", True) + msg.deviceState.chargingError = current_filter.x > 0. and msg.deviceState.batteryPercent < 90 # if current is positive, then battery is being discharged msg.deviceState.started = started_ts is not None msg.deviceState.startedMonoTime = int(1e9*(started_ts or 0)) diff --git a/selfdrive/ui/.gitignore b/selfdrive/ui/.gitignore index e5b27adce537fe..5f8a96edf025ae 100644 --- a/selfdrive/ui/.gitignore +++ b/selfdrive/ui/.gitignore @@ -4,6 +4,8 @@ moc_* _mui watch3 installer/installers/* +replay/replay +replay/tests/test_replay qt/text qt/spinner qt/setup/setup diff --git a/selfdrive/ui/SConscript b/selfdrive/ui/SConscript index c62a6b19d9eab6..9e89576a540129 100644 --- a/selfdrive/ui/SConscript +++ b/selfdrive/ui/SConscript @@ -78,7 +78,7 @@ if GetOption('extras'): if GetOption('extras'): - # build updater UI + # buidl updater UI qt_env.Program("qt/setup/updater", ["qt/setup/updater.cc", asset_obj], LIBS=qt_libs) # build mui diff --git a/selfdrive/ui/installer/installer.cc b/selfdrive/ui/installer/installer.cc index db33e1cd67c73a..ee98c4d3d9b119 100644 --- a/selfdrive/ui/installer/installer.cc +++ b/selfdrive/ui/installer/installer.cc @@ -107,7 +107,7 @@ void Installer::doInstall() { qDebug() << "Waiting for valid time"; } - // cleanup previous install attempts + // cleanup previous install attemps run("rm -rf " TMP_INSTALL_PATH " " INSTALL_PATH); // do the install diff --git a/selfdrive/ui/qt/offroad/settings.cc b/selfdrive/ui/qt/offroad/settings.cc index 09ff0eed948ca7..5e0e87e64d0deb 100644 --- a/selfdrive/ui/qt/offroad/settings.cc +++ b/selfdrive/ui/qt/offroad/settings.cc @@ -53,12 +53,6 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) { tr("Upload data from the driver facing camera and help improve the driver monitoring algorithm."), "../assets/offroad/icon_monitoring.png", }, - { - "EndToEndLong", - tr("🌮 End-to-end longitudinal (extremely alpha) 🌮"), - tr("Let the driving model control the gas and brakes, openpilot will drive as it thinks a human would. Super experimental."), - "../assets/offroad/icon_road.png", - }, { "DisengageOnAccelerator", tr("Disengage On Accelerator Pedal"), diff --git a/selfdrive/ui/translations/create_badges.py b/selfdrive/ui/translations/create_badges.py index 32904f242aa407..451fbb23eb12b3 100755 --- a/selfdrive/ui/translations/create_badges.py +++ b/selfdrive/ui/translations/create_badges.py @@ -30,7 +30,7 @@ percent_finished = int(100 - (unfinished_translations / total_translations * 100.)) color = "green" if percent_finished == 100 else "orange" if percent_finished >= 70 else "red" - r = requests.get(f"https://img.shields.io/badge/LANGUAGE {name}-{percent_finished}%25 complete-{color}", timeout=10) + r = requests.get(f"https://img.shields.io/badge/LANGUAGE {name}-{percent_finished}%25 complete-{color}") assert r.status_code == 200, "Error downloading badge" content_svg = r.content.decode("utf-8") diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts index d56f4e846670c4..dd9f933dcf75ff 100644 --- a/selfdrive/ui/translations/main_ja.ts +++ b/selfdrive/ui/translations/main_ja.ts @@ -108,152 +108,152 @@ DevicePanel - + Dongle ID ドングル番号 (Dongle ID) - + N/A N/A - + Serial シリアル番号 - + Driver Camera 車内カメラ - + PREVIEW 見る - + Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) 車内カメラをプレビューして、ドライバー監視システムの視界を確認ができます。(車両の電源を切る必要があります) - + Reset Calibration キャリブレーションをリセット - + RESET リセット - + Are you sure you want to reset calibration? キャリブレーションをリセットしてもよろしいですか? - + Review Training Guide 入門書を見る - + REVIEW 見る - + Review the rules, features, and limitations of openpilot openpilot の特徴を見る - + Are you sure you want to review the training guide? 入門書を見てもよろしいですか? - + Regulatory 認証情報 - + VIEW 見る - + Change Language 言語を変更 - + CHANGE 変更 - + Select a language 言語を選択 - + Reboot 再起動 - + Power Off 電源を切る - + openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. openpilot は、左または右の4°以内、上の5°または下の8°以内にデバイスを取付ける必要があります。キャリブレーションを引き続きます、リセットはほとんど必要ありません。 - + Your device is pointed %1° %2 and %3° %4. このデバイスは%2の%1°、%4の%3°に向けます。 - + down - + up - + left - + right - + Are you sure you want to reboot? 再起動してもよろしいですか? - + Disengage to Reboot openpilot をキャンセルして再起動ができます - + Are you sure you want to power off? シャットダウンしてもよろしいですか? - + Disengage to Power Off openpilot をキャンセルしてシャットダウンができます @@ -718,33 +718,33 @@ location set SettingsWindow - + × × - + Device デバイス - - + + Network ネットワーク - + Toggles 切り替え - + Software ソフトウェア - + Navigation ナビゲーション @@ -983,89 +983,89 @@ location set SoftwarePanel - + Git Branch Git ブランチ - + Git Commit Git コミット - + OS Version OS バージョン - + Version バージョン - + Last Update Check 最終更新確認 - + The last time openpilot successfully checked for an update. The updater only runs while the car is off. openpilotが最後にアップデートの確認に成功してからの時間です。アップデート処理は、車の電源が切れているときのみ実行されます。 - + Check for Update 更新プログラムをチェック - + CHECKING 確認中 - + Switch Branch ブランチの切り替え - + ENTER 切替 - - + + The new branch will be pulled the next time the updater runs. updater を実行する時にブランチを切り替えます。 - + Enter branch name ブランチ名を入力 - + UNINSTALL アンインストール - + Uninstall %1 %1をアンインストール - + Are you sure you want to uninstall? アンインストールしてもよろしいですか? - + failed to fetch update 更新のダウンロードにエラーが発生しました - - + + CHECK 確認 @@ -1194,51 +1194,41 @@ location set - 🌮 End-to-end longitudinal (extremely alpha) 🌮 - - - - - Let the driving model control the gas and brakes, openpilot will drive as it thinks a human would. Super experimental. - - - - Disengage On Accelerator Pedal アクセル踏むと openpilot をキャンセル - + When enabled, pressing the accelerator pedal will disengage openpilot. 有効な場合は、アクセルを踏むと openpilot をキャンセルします。 - + Show ETA in 24h Format 24時間表示 - + Use 24h format instead of am/pm AM/PM の代わりに24時間形式を使用します - + Show Map on Left Side of UI ディスプレイの左側にマップを表示 - + Show map on left side when in split screen view. 分割画面表示の場合、ディスプレイの左側にマップを表示します。 - + openpilot Longitudinal Control openpilot 縦方向制御 - + openpilot will disable the car's radar and will take over control of gas and brakes. Warning: this disables AEB! openpilot は、車のレーダーを無効化し、アクセルとブレーキの制御を引き継ぎます。注意:AEB を無効化にします! diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index bb4f884aa93c10..d4abe861962c3a 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -108,152 +108,152 @@ DevicePanel - + Dongle ID Dongle ID - + N/A N/A - + Serial Serial - + Driver Camera 운전자 카메라 - + PREVIEW 미리보기 - + Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) 운전자 모니터링이 좋은 가시성을 갖도록 운전자를 향한 카메라를 미리 봅니다. (차량연결은 해제되어있어야 합니다) - + Reset Calibration 캘리브레이션 재설정 - + RESET 재설정 - + Are you sure you want to reset calibration? 캘리브레이션을 재설정하시겠습니까? - + Review Training Guide 트레이닝 가이드 다시보기 - + REVIEW 다시보기 - + Review the rules, features, and limitations of openpilot openpilot의 규칙, 기능 및 제한 다시보기 - + Are you sure you want to review the training guide? 트레이닝 가이드를 다시보시겠습니까? - + Regulatory 규제 - + VIEW 보기 - + Change Language 언어 변경 - + CHANGE 변경 - + Select a language 언어를 선택하세요 - + Reboot 재부팅 - + Power Off 전원 종료 - + openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. openpilot은 장치를 좌측 또는 우측은 4° 이내, 위쪽 5° 또는 아래쪽은 8° 이내로 설치해야 합니다. openpilot은 지속적으로 보정되므로 리셋이 거의 필요하지 않습니다. - + Your device is pointed %1° %2 and %3° %4. 사용자의 장치가 %1° %2 및 %3° %4를 가리키고 있습니다. - + down 아래로 - + up 위로 - + left 좌측으로 - + right 우측으로 - + Are you sure you want to reboot? 재부팅 하시겠습니까? - + Disengage to Reboot 재부팅 하려면 해제하세요 - + Are you sure you want to power off? 전원을 종료하시겠습니까? - + Disengage to Power Off 전원을 종료하려면 해제하세요 @@ -718,33 +718,33 @@ location set SettingsWindow - + × × - + Device 장치 - - + + Network 네트워크 - + Toggles 토글 - + Software 소프트웨어 - + Navigation 네비게이션 @@ -983,89 +983,89 @@ location set SoftwarePanel - + Git Branch Git 브렌치 - + Git Commit Git 커밋 - + OS Version OS 버전 - + Version 버전 - + Last Update Check 최신 업데이트 검사 - + The last time openpilot successfully checked for an update. The updater only runs while the car is off. 최근에 openpilot이 업데이트를 성공적으로 확인했습니다. 업데이트 프로그램은 차량 연결이 해제되었을때만 작동합니다. - + Check for Update 업데이트 확인 - + CHECKING 확인중 - + Switch Branch 브랜치 변경 - + ENTER 입력하세요 - - + + The new branch will be pulled the next time the updater runs. 다음 업데이트 프로그램이 실행될 때 새 브랜치가 적용됩니다. - + Enter branch name 브랜치명 입력 - + UNINSTALL 제거 - + Uninstall %1 %1 제거 - + Are you sure you want to uninstall? 제거하시겠습니까? - + failed to fetch update 업데이트를 가져올수없습니다 - - + + CHECK 확인 @@ -1194,51 +1194,41 @@ location set - 🌮 End-to-end longitudinal (extremely alpha) 🌮 - - - - - Let the driving model control the gas and brakes, openpilot will drive as it thinks a human would. Super experimental. - - - - Disengage On Accelerator Pedal 가속페달 조작시 해제 - + When enabled, pressing the accelerator pedal will disengage openpilot. 활성화된 경우 가속 페달을 누르면 openpilot이 해제됩니다. - + Show ETA in 24h Format 24시간 형식으로 도착예정시간 표시 - + Use 24h format instead of am/pm 오전/오후 대신 24시간 형식 사용 - + Show Map on Left Side of UI UI 왼쪽에 지도 표시 - + Show map on left side when in split screen view. 분할 화면 보기에서 지도를 왼쪽에 표시합니다. - + openpilot Longitudinal Control openpilot Longitudinal Control - + openpilot will disable the car's radar and will take over control of gas and brakes. Warning: this disables AEB! openpilot은 차량'의 레이더를 무력화시키고 가속페달과 브레이크의 제어를 인계받을 것이다. 경고: AEB를 비활성화합니다! diff --git a/selfdrive/ui/translations/main_nl.ts b/selfdrive/ui/translations/main_nl.ts deleted file mode 100644 index 99646ed749e9f7..00000000000000 --- a/selfdrive/ui/translations/main_nl.ts +++ /dev/null @@ -1,1307 +0,0 @@ - - - - - AbstractAlert - - - Close - Sluit - - - - Snooze Update - Update uitstellen - - - - Reboot and Update - Opnieuw Opstarten en Updaten - - - - AdvancedNetworking - - - Back - Terug - - - - Enable Tethering - Tethering Inschakelen - - - - Tethering Password - Tethering Wachtwoord - - - - - EDIT - AANPASSEN - - - - Enter new tethering password - Voer nieuw tethering wachtwoord in - - - - IP Address - IP Adres - - - - Enable Roaming - Roaming Inschakelen - - - - APN Setting - APN Instelling - - - - Enter APN - Voer APN in - - - - leave blank for automatic configuration - laat leeg voor automatische configuratie - - - - ConfirmationDialog - - - - Ok - Ok - - - - Cancel - Annuleren - - - - DeclinePage - - - You must accept the Terms and Conditions in order to use openpilot. - U moet de Algemene Voorwaarden accepteren om openpilot te gebruiken. - - - - Back - Terug - - - - Decline, uninstall %1 - Afwijzen, verwijder %1 - - - - DevicePanel - - - Dongle ID - Dongle ID - - - - N/A - Nvt - - - - Serial - Serienummer - - - - Driver Camera - Bestuurders Camera - - - - PREVIEW - BEKIJKEN - - - - Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) - Bekijk de naar de bestuurder gerichte camera om ervoor te zorgen dat het monitoren van de bestuurder goed zicht heeft. (Voertuig moet uitgschakeld zijn) - - - - Reset Calibration - Kalibratie Resetten - - - - RESET - RESET - - - - Are you sure you want to reset calibration? - Weet u zeker dat u de kalibratie wilt resetten? - - - - Review Training Guide - Doorloop de Training Opnieuw - - - - REVIEW - BEKIJKEN - - - - Review the rules, features, and limitations of openpilot - Bekijk de regels, functies en beperkingen van openpilot - - - - Are you sure you want to review the training guide? - Weet u zeker dat u de training opnieuw wilt doorlopen? - - - - Regulatory - Regelgeving - - - - VIEW - BEKIJKEN - - - - Change Language - Taal Wijzigen - - - - CHANGE - WIJZIGEN - - - - Select a language - Selecteer een taal - - - - Reboot - Opnieuw Opstarten - - - - Power Off - Uitschakelen - - - - openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. - openpilot vereist dat het apparaat binnen 4° links of rechts en binnen 5° omhoog of 8° omlaag wordt gemonteerd. openpilot kalibreert continu, resetten is zelden nodig. - - - - Your device is pointed %1° %2 and %3° %4. - Uw apparaat is gericht op %1° %2 en %3° %4. - - - - down - omlaag - - - - up - omhoog - - - - left - links - - - - right - rechts - - - - Are you sure you want to reboot? - Weet u zeker dat u opnieuw wilt opstarten? - - - - Disengage to Reboot - Deactiveer openpilot om opnieuw op te starten - - - - Are you sure you want to power off? - Weet u zeker dat u wilt uitschakelen? - - - - Disengage to Power Off - Deactiveer openpilot om uit te schakelen - - - - DriveStats - - - Drives - Ritten - - - - Hours - Uren - - - - ALL TIME - TOTAAL - - - - PAST WEEK - AFGELOPEN WEEK - - - - KM - Km - - - - Miles - Mijl - - - - DriverViewScene - - - camera starting - Camera wordt gestart - - - - InputDialog - - - Cancel - Annuleren - - - - Need at least %n character(s)! - - Heeft minstens %n karakter nodig! - Heeft minstens %n karakters nodig! - - - - - Installer - - - Installing... - Installeren... - - - - Receiving objects: - Objecten ontvangen: - - - - Resolving deltas: - Deltas verwerken: - - - - Updating files: - Bestanden bijwerken: - - - - MapETA - - - eta - eta - - - - min - min - - - - hr - uur - - - - km - km - - - - mi - mi - - - - MapInstructions - - - km - km - - - - m - m - - - - mi - mi - - - - ft - ft - - - - MapPanel - - - Current Destination - Huidige Bestemming - - - - CLEAR - LEEGMAKEN - - - - Recent Destinations - Recente Bestemmingen - - - - Try the Navigation Beta - Probeer de Navigatie Bèta - - - - Get turn-by-turn directions displayed and more with a comma -prime subscription. Sign up now: https://connect.comma.ai - Krijg stapsgewijze routebeschrijving en meer met een comma -prime abonnement. Meld u nu aan: https://connect.comma.ai - - - - No home -location set - Geen thuislocatie -ingesteld - - - - No work -location set - Geen werklocatie -ingesteld - - - - no recent destinations - geen recente bestemmingen - - - - MapWindow - - - Map Loading - Kaart wordt geladen - - - - Waiting for GPS - Wachten op GPS - - - - MultiOptionDialog - - - Select - Selecteer - - - - Cancel - Annuleren - - - - Networking - - - Advanced - Geavanceerd - - - - Enter password - Voer wachtwoord in - - - - - for "%1" - voor "%1" - - - - Wrong password - Verkeerd wachtwoord - - - - NvgWindow - - - km/h - km/u - - - - mph - mph - - - - - MAX - MAX - - - - - SPEED - SPEED - - - - - LIMIT - LIMIT - - - - OffroadHome - - - UPDATE - UPDATE - - - - ALERTS - WAARSCHUWINGEN - - - - ALERT - WAARSCHUWING - - - - PairingPopup - - - Pair your device to your comma account - Koppel uw apparaat aan uw comma-account - - - - Go to https://connect.comma.ai on your phone - Ga naar https://connect.comma.ai op uw telefoon - - - - Click "add new device" and scan the QR code on the right - Klik op "add new device" en scan de QR-code aan de rechterkant - - - - Bookmark connect.comma.ai to your home screen to use it like an app - Voeg connect.comma.ai toe op uw startscherm om het als een app te gebruiken - - - - PrimeAdWidget - - - Upgrade Now - Upgrade nu - - - - Become a comma prime member at connect.comma.ai - Word een comma prime lid op connect.comma.ai - - - - PRIME FEATURES: - PRIME BEVAT: - - - - Remote access - Toegang op afstand - - - - 1 year of storage - 1 jaar lang opslag - - - - Developer perks - Voordelen voor ontwikkelaars - - - - PrimeUserWidget - - - ✓ SUBSCRIBED - ✓ GEABONNEERD - - - - comma prime - comma prime - - - - CONNECT.COMMA.AI - CONNECT.COMMA.AI - - - - COMMA POINTS - COMMA PUNTEN - - - - QObject - - - Reboot - Opnieuw Opstarten - - - - Exit - Afsluiten - - - - dashcam - dashcam - - - - openpilot - openpilot - - - - %n minute(s) ago - - %n minuut geleden - %n minuten geleden - - - - - %n hour(s) ago - - %n uur geleden - %n uur geleden - - - - - %n day(s) ago - - %n dag geleden - %n dagen geleden - - - - - Reset - - - Reset failed. Reboot to try again. - Opnieuw instellen mislukt. Start opnieuw op om opnieuw te proberen. - - - - Are you sure you want to reset your device? - Weet u zeker dat u uw apparaat opnieuw wilt instellen? - - - - Resetting device... - Apparaat opnieuw instellen... - - - - System Reset - Systeemreset - - - - System reset triggered. Press confirm to erase all content and settings. Press cancel to resume boot. - Systeemreset geactiveerd. Druk op bevestigen om alle inhoud en instellingen te wissen. Druk op Annuleren om het opstarten te hervatten. - - - - Cancel - Annuleren - - - - Reboot - Opnieuw Opstarten - - - - Confirm - Bevestigen - - - - Unable to mount data partition. Press confirm to reset your device. - Kan gegevenspartitie niet koppelen. Druk op bevestigen om uw apparaat te resetten. - - - - RichTextDialog - - - Ok - Ok - - - - SettingsWindow - - - × - × - - - - Device - Apparaat - - - - - Network - Netwerk - - - - Toggles - Opties - - - - Software - Software - - - - Navigation - Navigatie - - - - Setup - - - WARNING: Low Voltage - WAARCHUWING: Lage Spanning - - - - Power your device in a car with a harness or proceed at your own risk. - Voorzie uw apparaat van stroom in een auto met een harnas (car harness) of ga op eigen risico verder. - - - - Power off - Uitschakelen - - - - - - Continue - Doorgaan - - - - Getting Started - Aan de slag - - - - Before we get on the road, let’s finish installation and cover some details. - Laten we, voordat we op pad gaan, de installatie afronden en enkele details bespreken. - - - - Connect to Wi-Fi - Maak verbinding met Wi-Fi - - - - - Back - Terug - - - - Continue without Wi-Fi - Doorgaan zonder Wi-Fi - - - - Waiting for internet - Wachten op internet - - - - Choose Software to Install - Kies Software om te Installeren - - - - Dashcam - Dashcam - - - - Custom Software - Andere Software - - - - Enter URL - Voer URL in - - - - for Custom Software - voor Andere Software - - - - Downloading... - Downloaden... - - - - Download Failed - Downloaden Mislukt - - - - Ensure the entered URL is valid, and the device’s internet connection is good. - Zorg ervoor dat de ingevoerde URL geldig is en dat de internetverbinding van het apparaat goed is. - - - - Reboot device - Apparaat opnieuw opstarten - - - - Start over - Begin opnieuw - - - - SetupWidget - - - Finish Setup - Installatie voltooien - - - - Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. - Koppel uw apparaat met comma connect (connect.comma.ai) en claim uw comma prime-aanbieding. - - - - Pair device - Apparaat koppelen - - - - Sidebar - - - - CONNECT - VERBINDING - - - - OFFLINE - OFFLINE - - - - - ONLINE - ONLINE - - - - ERROR - FOUT - - - - - - TEMP - TEMP - - - - HIGH - HOOG - - - - GOOD - GOED - - - - OK - OK - - - - VEHICLE - VOERTUIG - - - - NO - GEEN - - - - PANDA - PANDA - - - - GPS - GPS - - - - SEARCH - ZOEKEN - - - - -- - -- - - - - Wi-Fi - Wi-Fi - - - - ETH - ETH - - - - 2G - 2G - - - - 3G - 3G - - - - LTE - 4G - - - - 5G - 5G - - - - SoftwarePanel - - - Git Branch - Git Branch - - - - Git Commit - Git Commit - - - - OS Version - OS Versie - - - - Version - Versie - - - - Last Update Check - Laatste Updatecontrole - - - - The last time openpilot successfully checked for an update. The updater only runs while the car is off. - De laatste keer dat openpilot met succes heeft gecontroleerd op een update. De updater werkt alleen als de auto is uitgeschakeld. - - - - Check for Update - Controleer op Updates - - - - CHECKING - CONTROLEER - - - - Switch Branch - Branch Verwisselen - - - - ENTER - INVOEREN - - - - - The new branch will be pulled the next time the updater runs. - Tijdens de volgende update wordt de nieuwe branch opgehaald. - - - - Enter branch name - Voer branch naam in - - - - Uninstall %1 - Verwijder %1 - - - - UNINSTALL - VERWIJDER - - - - Are you sure you want to uninstall? - Weet u zeker dat u de installatie ongedaan wilt maken? - - - - failed to fetch update - ophalen van update mislukt - - - - - CHECK - CONTROLEER - - - - SshControl - - - SSH Keys - SSH Sleutels - - - - Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username other than your own. A comma employee will NEVER ask you to add their GitHub username. - Waarschuwing: dit geeft SSH toegang tot alle openbare sleutels in uw GitHub-instellingen. Voer nooit een andere GitHub-gebruikersnaam in dan die van uzelf. Een medewerker van comma zal u NOOIT vragen om zijn GitHub-gebruikersnaam toe te voegen. - - - - - ADD - TOEVOEGEN - - - - Enter your GitHub username - Voer uw GitHub gebruikersnaam in - - - - LOADING - LADEN - - - - REMOVE - VERWIJDEREN - - - - Username '%1' has no keys on GitHub - Gebruikersnaam '%1' heeft geen SSH sleutels op GitHub - - - - Request timed out - Time-out van aanvraag - - - - Username '%1' doesn't exist on GitHub - Gebruikersnaam '%1' bestaat niet op GitHub - - - - SshToggle - - - Enable SSH - SSH Inschakelen - - - - TermsPage - - - Terms & Conditions - Algemene Voorwaarden - - - - Decline - Afwijzen - - - - Scroll to accept - Scroll om te accepteren - - - - Agree - Akkoord - - - - TogglesPanel - - - Enable openpilot - openpilot Inschakelen - - - - Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. - Gebruik het openpilot-systeem voor adaptieve cruisecontrol en rijstrookassistentie. Uw aandacht is te allen tijde vereist om deze functie te gebruiken. Het wijzigen van deze instelling wordt van kracht wanneer de auto wordt uitgeschakeld. - - - - Enable Lane Departure Warnings - Waarschuwingen bij Verlaten Rijstrook Inschakelen - - - - Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h). - Ontvang waarschuwingen om terug naar de rijstrook te sturen wanneer uw voertuig over een gedetecteerde rijstrookstreep drijft zonder dat de richtingaanwijzer wordt geactiveerd terwijl u harder rijdt dan 50 km/u (31 mph). - - - - Use Metric System - Gebruik Metrisch Systeem - - - - Display speed in km/h instead of mph. - Geef snelheid weer in km/u in plaats van mph. - - - - Record and Upload Driver Camera - Opnemen en Uploaden van de Bestuurders Camera - - - - Upload data from the driver facing camera and help improve the driver monitoring algorithm. - Upload gegevens van de bestuurders camera en help het algoritme voor het monitoren van de bestuurder te verbeteren. - - - - Disengage On Accelerator Pedal - Deactiveren Met Gaspedaal - - - - When enabled, pressing the accelerator pedal will disengage openpilot. - Indien ingeschakeld, zal het indrukken van het gaspedaal openpilot deactiveren. - - - - Show ETA in 24h Format - Toon verwachte aankomsttijd in 24-uurs formaat - - - - Use 24h format instead of am/pm - Gebruik 24-uurs formaat in plaats van AM en PM - - - - Show Map on Left Side of UI - Toon kaart aan linkerkant van het scherm - - - - Show map on left side when in split screen view. - Toon kaart links in gesplitste schermweergave. - - - - openpilot Longitudinal Control - openpilot Longitudinale Controle - - - - openpilot will disable the car's radar and will take over control of gas and brakes. Warning: this disables AEB! - openpilot zal de radar van de auto uitschakelen en de controle over gas en remmen overnemen. Waarschuwing: hierdoor wordt AEB (automatische noodrem) uitgeschakeld! - - - - Updater - - - Update Required - Update Vereist - - - - An operating system update is required. Connect your device to Wi-Fi for the fastest update experience. The download size is approximately 1GB. - Een update van het besturingssysteem is vereist. Verbind je apparaat met Wi-Fi voor de snelste update-ervaring. De downloadgrootte is ongeveer 1 GB. - - - - Connect to Wi-Fi - Maak verbinding met Wi-Fi - - - - Install - Installeer - - - - Back - Terug - - - - Loading... - Aan het laden... - - - - Reboot - Opnieuw Opstarten - - - - Update failed - Update mislukt - - - - WifiUI - - - - Scanning for networks... - Scannen naar netwerken... - - - - CONNECTING... - VERBINDEN... - - - - FORGET - VERGETEN - - - - Forget Wi-Fi Network "%1"? - Vergeet Wi-Fi Netwerk "%1"? - - - diff --git a/selfdrive/ui/translations/main_pl.ts b/selfdrive/ui/translations/main_pl.ts deleted file mode 100644 index 8593d68261b5c8..00000000000000 --- a/selfdrive/ui/translations/main_pl.ts +++ /dev/null @@ -1,1311 +0,0 @@ - - - - - AbstractAlert - - - Close - Zamknij - - - - Snooze Update - Zaktualizuj później - - - - Reboot and Update - Uruchom ponownie i zaktualizuj - - - - AdvancedNetworking - - - Back - Wróć - - - - Enable Tethering - Włącz hotspot osobisty - - - - Tethering Password - Hasło do hotspotu - - - - - EDIT - EDYTUJ - - - - Enter new tethering password - Wprowadź nowe hasło do hotspotu - - - - IP Address - Adres IP - - - - Enable Roaming - Włącz roaming danych - - - - APN Setting - Ustawienia APN - - - - Enter APN - Wprowadź APN - - - - leave blank for automatic configuration - Pozostaw puste, aby użyć domyślnej konfiguracji - - - - ConfirmationDialog - - - - Ok - Ok - - - - Cancel - Anuluj - - - - DeclinePage - - - You must accept the Terms and Conditions in order to use openpilot. - Aby korzystać z openpilota musisz zaakceptować regulamin. - - - - Back - Wróć - - - - Decline, uninstall %1 - Odrzuć, odinstaluj %1 - - - - DevicePanel - - - Dongle ID - ID adaptera - - - - N/A - N/A - - - - Serial - Numer seryjny - - - - Driver Camera - Kamera kierowcy - - - - PREVIEW - PODGLĄD - - - - Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) - Wyświetl podgląd z kamery skierowanej na kierowcę, aby upewnić się, że monitoring kierowcy ma dobry zakres widzenia. (pojazd musi być wyłączony) - - - - Reset Calibration - Zresetuj kalibrację - - - - RESET - ZRESETUJ - - - - Are you sure you want to reset calibration? - Czy na pewno chcesz zresetować kalibrację? - - - - Review Training Guide - Zapoznaj się z samouczkiem - - - - REVIEW - ZAPOZNAJ SIĘ - - - - Review the rules, features, and limitations of openpilot - Zapoznaj się z zasadami, funkcjami i ograniczeniami openpilota - - - - Are you sure you want to review the training guide? - Czy na pewno chcesz się zapoznać z samouczkiem? - - - - Regulatory - Regulacja - - - - VIEW - WIDOK - - - - Change Language - Zmień język - - - - CHANGE - ZMIEŃ - - - - Select a language - Wybierz język - - - - Reboot - Uruchom ponownie - - - - Power Off - Wyłącz - - - - openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. - openpilot wymaga, aby urządzenie było zamontowane z maksymalnym odchyłem 4° poziomo, 5° w górę oraz 8° w dół. openpilot jest ciągle kalibrowany, rzadko konieczne jest resetowania urządzenia. - - - - Your device is pointed %1° %2 and %3° %4. - Twoje urządzenie jest skierowane %1° %2 oraz %3° %4. - - - - down - w dół - - - - up - w górę - - - - left - w lewo - - - - right - w prawo - - - - Are you sure you want to reboot? - Czy na pewno chcesz uruchomić ponownie urządzenie? - - - - Disengage to Reboot - Aby uruchomić ponownie, odłącz sterowanie - - - - Are you sure you want to power off? - Czy na pewno chcesz wyłączyć urządzenie? - - - - Disengage to Power Off - Aby wyłączyć urządzenie, odłącz sterowanie - - - - DriveStats - - - Drives - Przejazdy - - - - Hours - Godziny - - - - ALL TIME - CAŁKOWICIE - - - - PAST WEEK - OSTATNI TYDZIEŃ - - - - KM - KM - - - - Miles - Mile - - - - DriverViewScene - - - camera starting - uruchamianie kamery - - - - InputDialog - - - Cancel - Anuluj - - - - Need at least %n character(s)! - - Wpisana wartość powinna składać się przynajmniej z %n znaku! - Wpisana wartość powinna skłądać się przynajmniej z %n znaków! - Wpisana wartość powinna skłądać się przynajmniej z %n znaków! - - - - - Installer - - - Installing... - Instalowanie... - - - - Receiving objects: - Odbieranie obiektów: - - - - Resolving deltas: - Rozwiązywanie różnic: - - - - Updating files: - Aktualizacja plików: - - - - MapETA - - - eta - przewidywany czas - - - - min - min - - - - hr - godz - - - - km - km - - - - mi - mi - - - - MapInstructions - - - km - km - - - - m - m - - - - mi - mi - - - - ft - ft - - - - MapPanel - - - Current Destination - Miejsce docelowe - - - - CLEAR - WYCZYŚĆ - - - - Recent Destinations - Ostatnie miejsca docelowe - - - - Try the Navigation Beta - Wypróbuj nawigację w wersji beta - - - - Get turn-by-turn directions displayed and more with a comma -prime subscription. Sign up now: https://connect.comma.ai - Odblokuj nawigację zakręt po zakęcie i wiele więcej subskrybując -comma prime. Zarejestruj się teraz: https://connect.comma.ai - - - - No home -location set - Lokalizacja domu -nie została ustawiona - - - - No work -location set - Miejsce pracy -nie zostało ustawione - - - - no recent destinations - brak ostatnich miejsc docelowych - - - - MapWindow - - - Map Loading - Ładowanie Mapy - - - - Waiting for GPS - Oczekiwanie na sygnał GPS - - - - MultiOptionDialog - - - Select - Wybierz - - - - Cancel - Anuluj - - - - Networking - - - Advanced - Zaawansowane - - - - Enter password - Wprowadź hasło - - - - - for "%1" - do "%1" - - - - Wrong password - Niepoprawne hasło - - - - NvgWindow - - - km/h - km/h - - - - mph - mph - - - - - MAX - MAX - - - - - SPEED - PRĘDKOŚĆ - - - - - LIMIT - OGRANICZENIE - - - - OffroadHome - - - UPDATE - UAKTUALNIJ - - - - ALERTS - ALERTY - - - - ALERT - ALERT - - - - PairingPopup - - - Pair your device to your comma account - Sparuj swoje urzadzenie ze swoim kontem comma - - - - Go to https://connect.comma.ai on your phone - Wejdź na stronę https://connect.comma.ai na swoim telefonie - - - - Click "add new device" and scan the QR code on the right - Kliknij "add new device" i zeskanuj kod QR znajdujący się po prawej stronie - - - - Bookmark connect.comma.ai to your home screen to use it like an app - Dodaj connect.comma.ai do zakładek na swoim ekranie początkowym, aby korzystać z niej jak z aplikacji - - - - PrimeAdWidget - - - Upgrade Now - Uaktualnij teraz - - - - Become a comma prime member at connect.comma.ai - Zostań członkiem comma prime na connect.comma.ai - - - - PRIME FEATURES: - FUNKCJE PRIME: - - - - Remote access - Zdalny dostęp - - - - 1 year of storage - 1 rok przechowywania danych - - - - Developer perks - Udogodnienia dla programistów - - - - PrimeUserWidget - - - ✓ SUBSCRIBED - ✓ ZASUBSKRYBOWANO - - - - comma prime - comma prime - - - - CONNECT.COMMA.AI - CONNECT.COMMA.AI - - - - COMMA POINTS - COMMA POINTS - - - - QObject - - - Reboot - Uruchom Ponownie - - - - Exit - Wyjdź - - - - dashcam - wideorejestrator - - - - openpilot - openpilot - - - - %n minute(s) ago - - %n minutę temu - %n minuty temu - %n minut temu - - - - - %n hour(s) ago - - % godzinę temu - %n godziny temu - %n godzin temu - - - - - %n day(s) ago - - %n dzień temu - %n dni temu - %n dni temu - - - - - Reset - - - Reset failed. Reboot to try again. - Wymazywanie zakończone niepowodzeniem. Aby spróbować ponownie, uruchom ponownie urządzenie. - - - - Are you sure you want to reset your device? - Czy na pewno chcesz wymazać urządzenie? - - - - Resetting device... - Wymazywanie urządzenia... - - - - System Reset - Przywróć do ustawień fabrycznych - - - - System reset triggered. Press confirm to erase all content and settings. Press cancel to resume boot. - Przywracanie do ustawień fabrycznych. Wciśnij potwierdź, aby usunąć wszystkie dane oraz ustawienia. Wciśnij anuluj, aby wznowić uruchamianie. - - - - Cancel - Anuluj - - - - Reboot - Uruchom ponownie - - - - Confirm - Potwiedź - - - - Unable to mount data partition. Press confirm to reset your device. - Partycja nie została zamontowana poprawnie. Wciśnij potwierdź, aby uruchomić ponownie urządzenie. - - - - RichTextDialog - - - Ok - Ok - - - - SettingsWindow - - - × - x - - - - Device - Urządzenie - - - - - Network - Sieć - - - - Toggles - Przełączniki - - - - Software - Oprogramowanie - - - - Navigation - Nawigacja - - - - Setup - - - WARNING: Low Voltage - OSTRZEŻENIE: Niskie Napięcie - - - - Power your device in a car with a harness or proceed at your own risk. - Podłącz swoje urządzenie do zasilania poprzez podłączenienie go do pojazdu lub kontynuuj na własną odpowiedzialność. - - - - Power off - Wyłącz - - - - - - Continue - Kontynuuj - - - - Getting Started - Zacznij - - - - Before we get on the road, let’s finish installation and cover some details. - Zanim ruszysz w drogę, dokończ instalację i podaj kilka szczegółów. - - - - Connect to Wi-Fi - Połącz z Wi-Fi - - - - - Back - Wróć - - - - Continue without Wi-Fi - Kontynuuj bez połączenia z Wif-Fi - - - - Waiting for internet - Oczekiwanie na połączenie sieciowe - - - - Choose Software to Install - Wybierz oprogramowanie do instalacji - - - - Dashcam - Wideorejestrator - - - - Custom Software - Własne oprogramowanie - - - - Enter URL - Wprowadź adres URL - - - - for Custom Software - do własnego oprogramowania - - - - Downloading... - Pobieranie... - - - - Download Failed - Pobieranie nie powiodło się - - - - Ensure the entered URL is valid, and the device’s internet connection is good. - Upewnij się, że wpisany adres URL jest poprawny, a połączenie internetowe działa poprawnie. - - - - Reboot device - Uruchom ponownie - - - - Start over - Zacznij od początku - - - - SetupWidget - - - Finish Setup - Zakończ konfigurację - - - - Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. - Sparuj swoje urządzenie z comma connect (connect.comma.ai) i wybierz swoją ofertę comma prime. - - - - Pair device - Sparuj urządzenie - - - - Sidebar - - - - CONNECT - POŁĄCZENIE - - - - OFFLINE - OFFLINE - - - - - ONLINE - ONLINE - - - - ERROR - BŁĄD - - - - - - TEMP - TEMP - - - - HIGH - WYSOKA - - - - GOOD - DOBRA - - - - OK - OK - - - - VEHICLE - POJAZD - - - - NO - BRAK - - - - PANDA - PANDA - - - - GPS - GPS - - - - SEARCH - SZUKAJ - - - - -- - -- - - - - Wi-Fi - Wi-FI - - - - ETH - ETH - - - - 2G - 2G - - - - 3G - 3G - - - - LTE - LTE - - - - 5G - 5G - - - - SoftwarePanel - - - Git Branch - Gałąź Git - - - - Git Commit - Git commit - - - - OS Version - Wersja systemu - - - - Version - Wersja - - - - Last Update Check - Ostatnie sprawdzenie aktualizacji - - - - The last time openpilot successfully checked for an update. The updater only runs while the car is off. - Ostatni raz kiedy openpilot znalazł aktualizację. Aktualizator może być uruchomiony wyłącznie wtedy, kiedy pojazd jest wyłączony. - - - - Check for Update - Sprawdź uaktualnienia - - - - CHECKING - SPRAWDZANIE - - - - Switch Branch - Zmień gąłąź - - - - ENTER - WPROWADŹ - - - - - The new branch will be pulled the next time the updater runs. - Nowa gałąź będzie pobrana przy następnym uruchomieniu aktualizatora. - - - - Enter branch name - Wprowadź nazwę gałęzi - - - - Uninstall %1 - Odinstaluj %1 - - - - UNINSTALL - ODINSTALUJ - - - - Are you sure you want to uninstall? - Czy na pewno chcesz odinstalować? - - - - failed to fetch update - pobieranie aktualizacji zakończone niepowodzeniem - - - - - CHECK - SPRAWDŹ - - - - SshControl - - - SSH Keys - Klucze SSH - - - - Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username other than your own. A comma employee will NEVER ask you to add their GitHub username. - Ostrzeżenie: To spowoduje przekazanie dostępu do wszystkich Twoich publicznych kuczy z ustawień GitHuba. Nigdy nie wprowadzaj nazwy użytkownika innej niż swoja. Pracownik comma NIGDY nie poprosi o dodanie swojej nazwy uzytkownika. - - - - - ADD - DODAJ - - - - Enter your GitHub username - Wpisz swoją nazwę użytkownika GitHub - - - - LOADING - ŁADOWANIE - - - - REMOVE - USUŃ - - - - Username '%1' has no keys on GitHub - Użytkownik '%1' nie posiada żadnych kluczy na GitHubie - - - - Request timed out - Limit czasu rządania - - - - Username '%1' doesn't exist on GitHub - Użytkownik '%1' nie istnieje na GitHubie - - - - SshToggle - - - Enable SSH - Włącz SSH - - - - TermsPage - - - Terms & Conditions - Regulamin - - - - Decline - Odrzuć - - - - Scroll to accept - Przewiń w dół, aby zaakceptować - - - - Agree - Zaakceptuj - - - - TogglesPanel - - - Enable openpilot - Włącz openpilota - - - - Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. - Użyj openpilota do zachowania bezpiecznego odstępu między pojazdami i do asystowania w utrzymywaniu pasa ruchu. Twoja pełna uwaga jest wymagana przez cały czas korzystania z tej funkcji. Ustawienie to może być wdrożone wyłącznie wtedy, gdy pojazd jest wyłączony. - - - - Enable Lane Departure Warnings - Włącz ostrzeganie przed zmianą pasa ruchu - - - - Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h). - Otrzymuj alerty o powrocie na właściwy pas, kiedy Twój pojazd przekroczy linię bez włączonego kierunkowskazu jadąc powyżej 50 km/h (31 mph). - - - - Use Metric System - Korzystaj z systemu metrycznego - - - - Display speed in km/h instead of mph. - Wyświetl prędkość w km/h zamiast mph. - - - - Record and Upload Driver Camera - Nagraj i prześlij nagranie z kamery kierowcy - - - - Upload data from the driver facing camera and help improve the driver monitoring algorithm. - Prześlij dane z kamery skierowanej na kierowcę i pomóż poprawiać algorytm monitorowania kierowcy. - - - - Disengage On Accelerator Pedal - Odłącz poprzez naciśnięcie gazu - - - - When enabled, pressing the accelerator pedal will disengage openpilot. - Po włączeniu, naciśnięcie na pedał gazu odłączy openpilota. - - - - Show ETA in 24h Format - Pokaż oczekiwany czas dojazdu w formacie 24-godzinnym - - - - Use 24h format instead of am/pm - Korzystaj z formatu 24-godzinnego zamiast 12-godzinnego - - - - Show Map on Left Side of UI - Pokaż mapę po lewej stronie ekranu - - - - Show map on left side when in split screen view. - Pokaż mapę po lewej stronie kiedy ekran jest podzielony. - - - - openpilot Longitudinal Control - Kontrola wzdłużna openpilota - - - - openpilot will disable the car's radar and will take over control of gas and brakes. Warning: this disables AEB! - openpilot wyłączy radar samochodu i przejmie kontrolę nad gazem i hamulcem. Ostrzeżenie: wyłączony zostanie system AEB! - - - - Updater - - - Update Required - Wymagana Aktualizacja - - - - An operating system update is required. Connect your device to Wi-Fi for the fastest update experience. The download size is approximately 1GB. - Wymagana aktualizacja systemu operacyjnego. Aby przyspieszyć proces aktualizacji połącz swoje urzeądzenie do Wi-Fi. Rozmiar pobieranej paczki wynosi około 1GB. - - - - Connect to Wi-Fi - Połącz się z Wi-Fi - - - - Install - Zainstaluj - - - - Back - Wróć - - - - Loading... - Ładowanie... - - - - Reboot - Uruchom ponownie - - - - Update failed - Aktualizacja nie powiodła się - - - - WifiUI - - - - Scanning for networks... - Wyszukiwanie sieci... - - - - CONNECTING... - ŁĄCZENIE... - - - - FORGET - ZAPOMNIJ - - - - Forget Wi-Fi Network "%1"? - Czy chcesz zapomnieć sieć "%1"? - - - diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index e4df8f36b002b1..c6c7ca26d5f024 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -108,152 +108,152 @@ DevicePanel - + Dongle ID Dongle ID - + N/A N/A - + Serial Serial - + Driver Camera Câmera voltada para o Motorista - + PREVIEW PREVISUAL - + Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) Pré-visualizar a câmera voltada para o motorista para garantir que monitor tem uma boa visibilidade (veículo precisa estar desligado) - + Reset Calibration Resetar Calibragem - + RESET RESET - + Are you sure you want to reset calibration? Tem certeza que quer resetar a calibragem? - + Review Training Guide Revisar o Treinamento - + REVIEW REVISAR - + Review the rules, features, and limitations of openpilot Revisar regras, aprimoramentos e limitações do openpilot - + Are you sure you want to review the training guide? Tem certeza que quer rever o treinamento? - + Regulatory Regulatório - + VIEW VER - + Change Language - Mudar Linguagem + Mudar Língua - + CHANGE MUDAR - + Select a language Selecione uma linguagem - + Reboot Reiniciar - + Power Off Desligar - + openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. o openpilot requer que o dispositivo seja montado dentro de 4° esquerda ou direita e dentro de 5° para cima ou 8° para baixo. o openpilot está continuamente calibrando, resetar raramente é necessário. - + Your device is pointed %1° %2 and %3° %4. Seu dispositivo está montado %1° %2 e %3° %4. - + down baixo - + up cima - + left esquerda - + right direita - + Are you sure you want to reboot? Tem certeza que quer reiniciar? - + Disengage to Reboot Desacione para Reiniciar - + Are you sure you want to power off? Tem certeza que quer desligar? - + Disengage to Power Off Desacione para Desligar @@ -722,33 +722,33 @@ trabalho definido SettingsWindow - + × × - + Device Dispositivo - - + + Network Rede - + Toggles Ajustes - + Software Software - + Navigation Navegação @@ -987,89 +987,89 @@ trabalho definido SoftwarePanel - + Git Branch Ramo Git - + Git Commit Commit Git - + OS Version Versão do Sistema - + Version Versão - + Last Update Check Verificação da última atualização - + The last time openpilot successfully checked for an update. The updater only runs while the car is off. A última vez que o openpilot verificou com sucesso uma atualização. O atualizador só funciona com o carro desligado. - + Check for Update Verifique atualizações - + CHECKING VERIFICANDO - + Switch Branch - Trocar Branch + Trocar Ramo - + ENTER INSERIR - - + + The new branch will be pulled the next time the updater runs. - A nova branch será aplicada ao verificar atualizações. + O novo ramo será aplicado na próxima execução do atualizador. - + Enter branch name - Inserir o nome da branch + Inserir o nome do ramo - + UNINSTALL DESINSTALAR - + Uninstall %1 - Desintalar o %1 + Desintalando %1 - + Are you sure you want to uninstall? Tem certeza que quer desinstalar? - + failed to fetch update falha ao buscar atualização - - + + CHECK VERIFICAR @@ -1198,51 +1198,41 @@ trabalho definido - 🌮 End-to-end longitudinal (extremely alpha) 🌮 - 🌮 End-to-end longitudinal (experimental) 🌮 - - - - Let the driving model control the gas and brakes, openpilot will drive as it thinks a human would. Super experimental. - Deixe o modelo de direção controlar o acelerador e o freio, o openpilot dirigirá da maneira como ele entende que um humano o faria. Super experimental. - - - Disengage On Accelerator Pedal Desacionar Com Pedal Do Acelerador - + When enabled, pressing the accelerator pedal will disengage openpilot. Quando ativado, pressionar o pedal do acelerador desacionará o openpilot. - + Show ETA in 24h Format Mostrar ETA em formato 24h - + Use 24h format instead of am/pm Use o formato 24h em vez de am/pm - + Show Map on Left Side of UI Exibir Mapa no Lado Esquerdo - + Show map on left side when in split screen view. Exibir mapa do lado esquerdo quando a tela for dividida. - + openpilot Longitudinal Control openpilot Controle Longitudinal - + openpilot will disable the car's radar and will take over control of gas and brakes. Warning: this disables AEB! openpilot desativará o radar do carro e assumirá o controle do acelerador e freios. Atenção: isso desativa AEB! diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts index e8c9b8ec52de42..a26cddc0c34859 100644 --- a/selfdrive/ui/translations/main_zh-CHS.ts +++ b/selfdrive/ui/translations/main_zh-CHS.ts @@ -108,152 +108,152 @@ DevicePanel - + Dongle ID 设备ID(Dongle ID) - + N/A N/A - + Serial 序列号 - + Driver Camera 驾驶员摄像头 - + PREVIEW 预览 - + Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) 打开并预览驾驶员摄像头,以确保驾驶员监控具有良好视野。仅熄火时可用。 - + Reset Calibration 重置设备校准 - + RESET 重置 - + Are you sure you want to reset calibration? 您确定要重置设备校准吗? - + Review Training Guide 新手指南 - + REVIEW 查看 - + Review the rules, features, and limitations of openpilot 查看openpilot的使用规则,以及其功能和限制。 - + Are you sure you want to review the training guide? 您确定要查看新手指南吗? - + Regulatory 监管信息 - + VIEW 查看 - + Change Language 切换语言 - + CHANGE 切换 - + Select a language 选择语言 - + Reboot 重启 - + Power Off 关机 - + openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. openpilot要求设备安装的偏航角在左4°和右4°之间,俯仰角在上5°和下8°之间。一般来说,openpilot会持续更新校准,很少需要重置。 - + Your device is pointed %1° %2 and %3° %4. 您的设备校准为%1° %2、%3° %4。 - + down 朝下 - + up 朝上 - + left 朝左 - + right 朝右 - + Are you sure you want to reboot? 您确定要重新启动吗? - + Disengage to Reboot 取消openpilot以重新启动 - + Are you sure you want to power off? 您确定要关机吗? - + Disengage to Power Off 取消openpilot以关机 @@ -716,33 +716,33 @@ location set SettingsWindow - + × × - + Device 设备 - - + + Network 网络 - + Toggles 设定 - + Software 软件 - + Navigation 导航 @@ -981,89 +981,89 @@ location set SoftwarePanel - + Git Branch Git Branch - + Git Commit Git Commit - + OS Version 系统版本 - + Version 软件版本 - + Last Update Check 上次检查更新 - + The last time openpilot successfully checked for an update. The updater only runs while the car is off. 上一次成功检查更新的时间。更新程序仅在汽车熄火时运行。 - + Check for Update 检查更新 - + CHECKING 正在检查更新 - + Switch Branch 切换分支 - + ENTER 输入 - - + + The new branch will be pulled the next time the updater runs. 分支将在更新服务下次启动时自动切换。 - + Enter branch name 输入分支名称 - + UNINSTALL 卸载 - + Uninstall %1 卸载 %1 - + Are you sure you want to uninstall? 您确定要卸载吗? - + failed to fetch update 获取更新失败 - - + + CHECK 查看 @@ -1192,51 +1192,41 @@ location set - 🌮 End-to-end longitudinal (extremely alpha) 🌮 - - - - - Let the driving model control the gas and brakes, openpilot will drive as it thinks a human would. Super experimental. - - - - Disengage On Accelerator Pedal 踩油门时取消控制 - + When enabled, pressing the accelerator pedal will disengage openpilot. 启用后,踩下油门踏板将取消openpilot。 - + Show ETA in 24h Format 以24小时格式显示预计到达时间 - + Use 24h format instead of am/pm 使用24小时制代替am/pm - + Show Map on Left Side of UI 在介面左侧显示地图 - + Show map on left side when in split screen view. 在分屏模式中,将地图置于屏幕左侧。 - + openpilot Longitudinal Control openpilot纵向控制 - + openpilot will disable the car's radar and will take over control of gas and brakes. Warning: this disables AEB! openpilot将禁用车辆的雷达并接管油门和刹车的控制。警告:AEB将被禁用! diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts index 9b792e6df08cd2..f4681f85d940c2 100644 --- a/selfdrive/ui/translations/main_zh-CHT.ts +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -108,152 +108,152 @@ DevicePanel - + Dongle ID Dongle ID - + N/A 無法使用 - + Serial 序號 - + Driver Camera 駕駛員攝像頭 - + PREVIEW 預覽 - + Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) 預覽駕駛員監控鏡頭畫面,以確保其具有良好視野。(僅在熄火時可用) - + Reset Calibration 重置校準 - + RESET 重置 - + Are you sure you want to reset calibration? 您確定要重置校準嗎? - + Review Training Guide 觀看使用教學 - + REVIEW 觀看 - + Review the rules, features, and limitations of openpilot 觀看 openpilot 的使用規則、功能和限制 - + Are you sure you want to review the training guide? 您確定要觀看使用教學嗎? - + Regulatory 法規/監管 - + VIEW 觀看 - + Change Language 更改語言 - + CHANGE 更改 - + Select a language 選擇語言 - + Reboot 重新啟動 - + Power Off 關機 - + openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. openpilot 需要將裝置固定在左右偏差 4° 以內,朝上偏差 5° 以内或朝下偏差 8° 以内。鏡頭在後台會持續自動校準,很少有需要重置的情况。 - + Your device is pointed %1° %2 and %3° %4. 你的設備目前朝%2 %1° 以及朝%4 %3° 。 - + down - + up - + left - + right - + Are you sure you want to reboot? 您確定要重新啟動嗎? - + Disengage to Reboot 請先取消控車才能重新啟動 - + Are you sure you want to power off? 您確定您要關機嗎? - + Disengage to Power Off 請先取消控車才能關機 @@ -718,33 +718,33 @@ location set SettingsWindow - + × × - + Device 設備 - - + + Network 網路 - + Toggles 設定 - + Software 軟體 - + Navigation 導航 @@ -983,89 +983,89 @@ location set SoftwarePanel - + Git Branch Git 分支 - + Git Commit Git 提交 - + OS Version 系統版本 - + Version 版本 - + Last Update Check 上次檢查時間 - + The last time openpilot successfully checked for an update. The updater only runs while the car is off. 上次成功檢查更新的時間。更新系統只會在車子熄火時執行。 - + Check for Update 檢查更新 - + CHECKING 檢查中 - + Switch Branch 切換分支 - + ENTER 切換 - - + + The new branch will be pulled the next time the updater runs. 新的分支將會在下次檢查更新時切換過去。 - + Enter branch name 輸入分支名稱 - + UNINSTALL 卸載 - + Uninstall %1 卸載 %1 - + Are you sure you want to uninstall? 您確定您要卸載嗎? - + failed to fetch update 下載更新失敗 - - + + CHECK 檢查 @@ -1194,51 +1194,41 @@ location set - 🌮 End-to-end longitudinal (extremely alpha) 🌮 - - - - - Let the driving model control the gas and brakes, openpilot will drive as it thinks a human would. Super experimental. - - - - Disengage On Accelerator Pedal 油門取消控車 - + When enabled, pressing the accelerator pedal will disengage openpilot. 啟用後,踩踏油門將會取消 openpilot 控制。 - + Show ETA in 24h Format 預計到達時間單位改用 24 小時制 - + Use 24h format instead of am/pm 使用 24 小時制。(預設值為 12 小時制) - + Show Map on Left Side of UI 將地圖顯示在畫面的左側 - + Show map on left side when in split screen view. 進入分割畫面後,地圖將會顯示在畫面的左側。 - + openpilot Longitudinal Control openpilot 縱向控制 - + openpilot will disable the car's radar and will take over control of gas and brakes. Warning: this disables AEB! openpilot 將會關閉雷達訊號並接管油門和剎車的控制。注意:這也會關閉自動緊急煞車 (AEB) 系統! diff --git a/system/camerad/cameras/camera_common.h b/system/camerad/cameras/camera_common.h index e87eaf4b91f2a4..198efca0bb3f8f 100644 --- a/system/camerad/cameras/camera_common.h +++ b/system/camerad/cameras/camera_common.h @@ -40,7 +40,6 @@ const bool env_disable_wide_road = getenv("DISABLE_WIDE_ROAD") != NULL; const bool env_disable_driver = getenv("DISABLE_DRIVER") != NULL; const bool env_debug_frames = getenv("DEBUG_FRAMES") != NULL; const bool env_log_raw_frames = getenv("LOG_RAW_FRAMES") != NULL; -const bool env_ctrl_exp_from_params = getenv("CTRL_EXP_FROM_PARAMS") != NULL; typedef struct CameraInfo { uint32_t frame_width, frame_height; diff --git a/system/camerad/cameras/camera_qcom2.cc b/system/camerad/cameras/camera_qcom2.cc index a86218c06e8448..31af284d52a776 100644 --- a/system/camerad/cameras/camera_qcom2.cc +++ b/system/camerad/cameras/camera_qcom2.cc @@ -949,7 +949,7 @@ std::map> CameraState::ar0231_build_register_lut(u // // 0xAA is used to indicate the MSB of the address, 0xA5 for the LSB of the address. // Every byte of data (MSB and LSB) is preceded by 0x5A. Specifying an address is optional - // for contiguous ranges. See page 27-29 of the AR0231 Developer guide for more information. + // for contigous ranges. See page 27-29 of the AR0231 Developer guide for more information. int max_i[] = {1828 / 2 * 3, 1500 / 2 * 3}; auto get_next_idx = [](int cur_idx) { @@ -1077,7 +1077,7 @@ void CameraState::set_camera_exposure(float grey_frac) { // It takes 3 frames for the commanded exposure settings to take effect. The first frame is already started by the time // we reach this function, the other 2 are due to the register buffering in the sensor. // Therefore we use the target EV from 3 frames ago, the grey fraction that was just measured was the result of that control action. - // TODO: Lower latency to 2 frames, by using the histogram outputted by the sensor we can do AE before the debayering is complete + // TODO: Lower latency to 2 frames, by using the histogram outputed by the sensor we can do AE before the debayering is complete const float cur_ev_ = cur_ev[buf.cur_frame_data.frame_id % 3]; @@ -1102,51 +1102,35 @@ void CameraState::set_camera_exposure(float grey_frac) { enable_dc_gain = false; } - std::string gain_bytes, time_bytes; - if (env_ctrl_exp_from_params) { - gain_bytes = Params().get("CameraDebugExpGain"); - time_bytes = Params().get("CameraDebugExpTime"); - } - - if (gain_bytes.size() > 0 && time_bytes.size() > 0) { - // Override gain and exposure time - gain_idx = std::stoi(gain_bytes); - exposure_time = std::stoi(time_bytes); - - new_g = gain_idx; - new_t = exposure_time; - enable_dc_gain = false; - } else { - // Simple brute force optimizer to choose sensor parameters - // to reach desired EV - for (int g = std::max((int)ANALOG_GAIN_MIN_IDX, gain_idx - 1); g <= std::min((int)ANALOG_GAIN_MAX_IDX, gain_idx + 1); g++) { - float gain = sensor_analog_gains[g] * (enable_dc_gain ? DC_GAIN : 1); + // Simple brute force optimizer to choose sensor parameters + // to reach desired EV + for (int g = std::max((int)ANALOG_GAIN_MIN_IDX, gain_idx - 1); g <= std::min((int)ANALOG_GAIN_MAX_IDX, gain_idx + 1); g++) { + float gain = sensor_analog_gains[g] * (enable_dc_gain ? DC_GAIN : 1); - // Compute optimal time for given gain - int t = std::clamp(int(std::round(desired_ev / gain)), EXPOSURE_TIME_MIN, EXPOSURE_TIME_MAX); + // Compute optimal time for given gain + int t = std::clamp(int(std::round(desired_ev / gain)), EXPOSURE_TIME_MIN, EXPOSURE_TIME_MAX); - // Only go below recommended gain when absolutely necessary to not overexpose - if (g < ANALOG_GAIN_REC_IDX && t > 20 && g < gain_idx) { - continue; - } + // Only go below recomended gain when absolutely necessary to not overexpose + if (g < ANALOG_GAIN_REC_IDX && t > 20 && g < gain_idx) { + continue; + } - // Compute error to desired ev - float score = std::abs(desired_ev - (t * gain)) * 10; + // Compute error to desired ev + float score = std::abs(desired_ev - (t * gain)) * 10; - // Going below recommended gain needs lower penalty to not overexpose - float m = g > ANALOG_GAIN_REC_IDX ? 5.0 : 0.1; - score += std::abs(g - (int)ANALOG_GAIN_REC_IDX) * m; + // Going below recomended gain needs lower penalty to not overexpose + float m = g > ANALOG_GAIN_REC_IDX ? 5.0 : 0.1; + score += std::abs(g - (int)ANALOG_GAIN_REC_IDX) * m; - // LOGE("cam: %d - gain: %d, t: %d (%.2f), score %.2f, score + gain %.2f, %.3f, %.3f", camera_num, g, t, desired_ev / gain, score, score + std::abs(g - gain_idx) * (score + 1.0) / 10.0, desired_ev, min_ev); + // LOGE("cam: %d - gain: %d, t: %d (%.2f), score %.2f, score + gain %.2f, %.3f, %.3f", camera_num, g, t, desired_ev / gain, score, score + std::abs(g - gain_idx) * (score + 1.0) / 10.0, desired_ev, min_ev); - // Small penalty on changing gain - score += std::abs(g - gain_idx) * (score + 1.0) / 10.0; + // Small penalty on changing gain + score += std::abs(g - gain_idx) * (score + 1.0) / 10.0; - if (score < best_ev_score) { - new_t = t; - new_g = g; - best_ev_score = score; - } + if (score < best_ev_score) { + new_t = t; + new_g = g; + best_ev_score = score; } } diff --git a/system/camerad/cameras/camera_qcom2.h b/system/camerad/cameras/camera_qcom2.h index e75e7e586a0d16..03d3d1a8232508 100644 --- a/system/camerad/cameras/camera_qcom2.h +++ b/system/camerad/cameras/camera_qcom2.h @@ -7,7 +7,6 @@ #include #include "system/camerad/cameras/camera_common.h" -#include "common/params.h" #include "common/util.h" #define FRAME_BUF_COUNT 4 diff --git a/system/hardware/base.py b/system/hardware/base.py index 31df1babe0f21b..c9c02f3a5976a2 100644 --- a/system/hardware/base.py +++ b/system/hardware/base.py @@ -78,6 +78,10 @@ def get_network_metered(self, network_type) -> bool: def set_bandwidth_limit(upload_speed_kbps: int, download_speed_kbps: int) -> None: pass + @abstractmethod + def get_usb_present(self): + pass + @abstractmethod def get_current_power_draw(self): pass diff --git a/system/hardware/pc/hardware.py b/system/hardware/pc/hardware.py index 564f9e483add9d..60d14e4a6b1568 100644 --- a/system/hardware/pc/hardware.py +++ b/system/hardware/pc/hardware.py @@ -50,9 +50,12 @@ def get_sim_info(self): def get_network_strength(self, network_type): return NetworkStrength.unknown + def get_usb_present(self): + return False + def get_current_power_draw(self): return 0 - + def get_som_power_draw(self): return 0 diff --git a/system/hardware/tici/agnos.py b/system/hardware/tici/agnos.py index 51998bf8b735ea..ca2498a00c4208 100755 --- a/system/hardware/tici/agnos.py +++ b/system/hardware/tici/agnos.py @@ -20,7 +20,7 @@ class StreamingDecompressor: def __init__(self, url: str) -> None: self.buf = b"" - self.req = requests.get(url, stream=True, headers={'Accept-Encoding': None}) # type: ignore # pylint: disable=missing-timeout + self.req = requests.get(url, stream=True, headers={'Accept-Encoding': None}) # type: ignore self.it = self.req.iter_content(chunk_size=1024 * 1024) self.decompressor = lzma.LZMADecompressor(format=lzma.FORMAT_AUTO) self.eof = False @@ -241,7 +241,7 @@ def flash_partition(target_slot_number: int, partition: dict, cloudlog, standalo else: extract_compressed_image(target_slot_number, partition, cloudlog) - # Write hash after successful flash + # Write hash after successfull flash if not full_check: with open(path, 'wb+') as out: out.seek(partition['size']) @@ -257,7 +257,7 @@ def swap(manifest_path: str, target_slot_number: int, cloudlog) -> None: while True: out = subprocess.check_output(f"abctl --set_active {target_slot_number}", shell=True, stderr=subprocess.STDOUT, encoding='utf8') if ("No such file or directory" not in out) and ("lun as boot lun" in out): - cloudlog.info(f"Swap successful {out}") + cloudlog.info(f"Swap successfull {out}") break else: cloudlog.error(f"Swap failed {out}") diff --git a/system/hardware/tici/hardware.py b/system/hardware/tici/hardware.py index 340093b6043896..c3f8c7f82ad947 100644 --- a/system/hardware/tici/hardware.py +++ b/system/hardware/tici/hardware.py @@ -287,7 +287,7 @@ def set_bandwidth_limit(upload_speed_kbps: int, download_speed_kbps: int) -> Non ] upload = [ - # Create root Hierarchy Token Bucket that sends all traffic to 1:20 + # Create root Hierarchy Token Bucket that sends all trafic to 1:20 (True, tc + ["qdisc", "add", "dev", adapter, "root", "handle", "1:", "htb", "default", "20"]), # Create class 1:20 with specified rate limit @@ -372,6 +372,7 @@ def get_som_power_draw(self): return (self.read_param_file("/sys/class/power_supply/bms/voltage_now", int) * self.read_param_file("/sys/class/power_supply/bms/current_now", int) / 1e12) def shutdown(self): + # Note that for this to work and have the device stay powered off, the panda needs to be in UsbPowerMode::CLIENT! os.system("sudo poweroff") def get_thermal_config(self): diff --git a/system/hardware/tici/test_agnos_updater.py b/system/hardware/tici/test_agnos_updater.py index e0d6ed88145a5c..9f188b83dc5713 100755 --- a/system/hardware/tici/test_agnos_updater.py +++ b/system/hardware/tici/test_agnos_updater.py @@ -15,7 +15,7 @@ def test_manifest(self): m = json.load(f) for img in m: - r = requests.head(img['url'], timeout=10) + r = requests.head(img['url']) r.raise_for_status() self.assertEqual(r.headers['Content-Type'], "application/x-xz") if not img['sparse']: diff --git a/system/hardware/tici/tests/compare_casync_manifest.py b/system/hardware/tici/tests/compare_casync_manifest.py index b462e93ebc83bc..5e5fa24556e4fd 100755 --- a/system/hardware/tici/tests/compare_casync_manifest.py +++ b/system/hardware/tici/tests/compare_casync_manifest.py @@ -17,7 +17,7 @@ def get_chunk_download_size(chunk): if os.path.isfile(path): return os.path.getsize(path) else: - r = requests.head(path, timeout=10) + r = requests.head(path) r.raise_for_status() return int(r.headers['content-length']) diff --git a/system/proclogd/proclog.cc b/system/proclogd/proclog.cc index cbe3b53493ca54..9064547d29af3b 100644 --- a/system/proclogd/proclog.cc +++ b/system/proclogd/proclog.cc @@ -72,7 +72,7 @@ std::optional procStat(std::string stat) { } std::string name = stat.substr(open_paren + 1, close_paren - open_paren - 1); - // replace space in name with _ + // repace space in name with _ std::replace(&stat[open_paren], &stat[close_paren], ' ', '_'); std::istringstream iss(stat); std::vector v{std::istream_iterator(iss), diff --git a/tinygrad b/tinygrad deleted file mode 120000 index cb003823c6d777..00000000000000 --- a/tinygrad +++ /dev/null @@ -1 +0,0 @@ -tinygrad_repo/tinygrad \ No newline at end of file diff --git a/tinygrad_repo b/tinygrad_repo deleted file mode 160000 index 2e9b7637b3c3c8..00000000000000 --- a/tinygrad_repo +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2e9b7637b3c3c8895fda9f964215db3a35fe3441 diff --git a/tools/README.md b/tools/README.md index 59eea3230d5487..a61d9268d2c132 100644 --- a/tools/README.md +++ b/tools/README.md @@ -2,7 +2,7 @@ ## System Requirements -openpilot is developed and tested on **Ubuntu 20.04**, which is the primary development target aside from the [supported embedded hardware](https://github.com/commaai/openpilot#running-on-pc). We also have a CI test to verify that openpilot builds on macOS, but the tools are untested. For the best experience, stick to Ubuntu 20.04, otherwise openpilot and the tools should work with minimal to no modifications on macOS and other Linux systems. +openpilot is developed and tested on **Ubuntu 20.04**, which is the primary development target aside from the [supported embdedded hardware](https://github.com/commaai/openpilot#running-on-pc). We also have a CI test to verify that openpilot builds on macOS, but the tools are untested. For the best experience, stick to Ubuntu 20.04, otherwise openpilot and the tools should work with minimal to no modifications on macOS and other Linux systems. ## Setup your PC @@ -39,7 +39,7 @@ scons -u -j$(nproc) ### Windows -Neither openpilot nor any of the tools are developed or tested on Windows, but the [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/about) should get Windows users a similar experience to Ubuntu. [WSL 2](https://docs.microsoft.com/en-us/windows/wsl/compare-versions) specifically has been reported by several users to be a seamless experience. +Neither openpilot nor any of the tools are developed or tested on Windows, but the [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/about) should get Windows users a similiar experience to Ubuntu. [WSL 2](https://docs.microsoft.com/en-us/windows/wsl/compare-versions) specifically has been reported by several users to be a seamless experience. Follow [these instructions](https://docs.microsoft.com/en-us/windows/wsl/install) to setup the WSL and install the `Ubuntu-20.04` distribution. Once your Ubuntu WSL environment is setup, follow the Linux setup instructions to finish setting up your environment. diff --git a/tools/camerastream/compressed_vipc.py b/tools/camerastream/compressed_vipc.py index 4322ce279a0ff2..d321d6fd2b4286 100755 --- a/tools/camerastream/compressed_vipc.py +++ b/tools/camerastream/compressed_vipc.py @@ -86,7 +86,7 @@ def decoder(addr, sock_name, vipc_server, vst, nvidia): print("%2d %4d %.3f %.3f roll %6.2f ms latency %6.2f ms + %6.2f ms + %6.2f ms = %6.2f ms" % (len(msgs), evta.idx.encodeId, evt.logMonoTime/1e9, evta.idx.timestampEof/1e6, frame_latency, process_latency, network_latency, pc_latency, process_latency+network_latency+pc_latency ), len(evta.data), sock_name) if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Decode video streams and broadcast on VisionIPC") + parser = argparse.ArgumentParser(description="Decode video streams and broacast on VisionIPC") parser.add_argument("addr", help="Address of comma three") parser.add_argument("--nvidia", action="store_true", help="Use nvidia instead of ffmpeg") parser.add_argument("--cams", default="0,1,2", help="Cameras to decode") diff --git a/tools/joystick/joystickd.py b/tools/joystick/joystickd.py index 8374cf8a741f2a..35ecca351d1250 100755 --- a/tools/joystick/joystickd.py +++ b/tools/joystick/joystickd.py @@ -77,7 +77,7 @@ def send_thread(joystick): print('\n' + ', '.join(f'{name}: {round(v, 3)}' for name, v in joystick.axes_values.items())) if "WEB" in os.environ: import requests - requests.get("http://"+os.environ["WEB"]+":5000/control/%f/%f" % tuple([joystick.axes_values[a] for a in joystick.axes_order][::-1]), timeout=None) + requests.get("http://"+os.environ["WEB"]+":5000/control/%f/%f" % tuple([joystick.axes_values[a] for a in joystick.axes_order][::-1])) rk.keep_time() def joystick_thread(use_keyboard): diff --git a/tools/latencylogger/latency_logger.py b/tools/latencylogger/latency_logger.py index 81a4790dea2670..161befbc7cd28f 100755 --- a/tools/latencylogger/latency_logger.py +++ b/tools/latencylogger/latency_logger.py @@ -13,7 +13,7 @@ DEMO_ROUTE = "9f583b1d93915c31|2022-05-18--10-49-51--0" SERVICES = ['camerad', 'modeld', 'plannerd', 'controlsd', 'boardd'] -# Retrieve controlsd frameId from lateralPlan, mismatch with longitudinalPlan will be ignored +# Retrive controlsd frameId from lateralPlan, mismatch with longitudinalPlan will be ignored MONOTIME_KEYS = ['modelMonoTime', 'lateralPlanMonoTime'] MSGQ_TO_SERVICE = { 'roadCameraState': 'camerad', @@ -79,7 +79,7 @@ def read_logs(lr): if not data['start'][frame_id][service]: data['start'][frame_id][service] = msg_obj.timestampSof elif msg.which() == 'controlsState': - # Sendcan is published before controlsState, but the frameId is retrieved in CS + # Sendcan is published before controlsState, but the frameId is retrived in CS data['timestamp'][frame_id][service].append(("sendcan published", latest_sendcan_monotime)) elif msg.which() == 'modelV2': if msg_obj.frameIdExtra != frame_id: diff --git a/tools/lib/README.md b/tools/lib/README.md index 3cf239d2dfc932..241232eae26cad 100644 --- a/tools/lib/README.md +++ b/tools/lib/README.md @@ -1,6 +1,6 @@ ## LogReader -Route is a class for conveniently accessing all the [logs](/selfdrive/loggerd/) from your routes. The LogReader class reads the non-video logs, i.e. rlog.bz2 and qlog.bz2. There's also a matching FrameReader class for reading the videos. +Route is a class for conviently accessing all the [logs](/selfdrive/loggerd/) from your routes. The LogReader class reads the non-video logs, i.e. rlog.bz2 and qlog.bz2. There's also a matching FrameReader class for reading the videos. ```python from tools.lib.route import Route diff --git a/tools/lib/filereader.py b/tools/lib/filereader.py index 215f7b21855553..4ea9ad4290a184 100644 --- a/tools/lib/filereader.py +++ b/tools/lib/filereader.py @@ -1,7 +1,7 @@ import os from tools.lib.url_file import URLFile -DATA_ENDPOINT = os.getenv("DATA_ENDPOINT", "http://data-raw.comma.internal/") +DATA_ENDPOINT = os.getenv("DATA_ENDPOINT", "http://data-raw.internal/") def FileReader(fn, debug=False): if fn.startswith("cd:/"): diff --git a/tools/lib/tests/test_readers.py b/tools/lib/tests/test_readers.py index 6efa0dc351d9d9..1d8918ba54880f 100755 --- a/tools/lib/tests/test_readers.py +++ b/tools/lib/tests/test_readers.py @@ -10,7 +10,7 @@ class TestReaders(unittest.TestCase): - @unittest.skip("skip for bandwidth reasons") + @unittest.skip("skip for bandwith reasons") def test_logreader(self): def _check_data(lr): hist = defaultdict(int) @@ -21,7 +21,7 @@ def _check_data(lr): self.assertEqual(hist['logMessage'], 6857) with tempfile.NamedTemporaryFile(suffix=".bz2") as fp: - r = requests.get("https://github.com/commaai/comma2k19/blob/master/Example_1/b0c9d2329ad1606b%7C2018-08-02--08-34-47/40/raw_log.bz2?raw=true", timeout=10) + r = requests.get("https://github.com/commaai/comma2k19/blob/master/Example_1/b0c9d2329ad1606b%7C2018-08-02--08-34-47/40/raw_log.bz2?raw=true") fp.write(r.content) fp.flush() @@ -31,7 +31,7 @@ def _check_data(lr): lr_url = LogReader("https://github.com/commaai/comma2k19/blob/master/Example_1/b0c9d2329ad1606b%7C2018-08-02--08-34-47/40/raw_log.bz2?raw=true") _check_data(lr_url) - @unittest.skip("skip for bandwidth reasons") + @unittest.skip("skip for bandwith reasons") def test_framereader(self): def _check_data(f): self.assertEqual(f.frame_count, 1200) @@ -53,7 +53,7 @@ def _check_data(f): assert np.all(frame_first_30[15] == frame_15[0]) with tempfile.NamedTemporaryFile(suffix=".hevc") as fp: - r = requests.get("https://github.com/commaai/comma2k19/blob/master/Example_1/b0c9d2329ad1606b%7C2018-08-02--08-34-47/40/video.hevc?raw=true", timeout=10) + r = requests.get("https://github.com/commaai/comma2k19/blob/master/Example_1/b0c9d2329ad1606b%7C2018-08-02--08-34-47/40/video.hevc?raw=true") fp.write(r.content) fp.flush() diff --git a/tools/plotjuggler/README.md b/tools/plotjuggler/README.md index b4190384dbcb0d..25fcb5931a60c7 100644 --- a/tools/plotjuggler/README.md +++ b/tools/plotjuggler/README.md @@ -4,7 +4,7 @@ ## Installation -Once you've [set up the openpilot environment](../README.md), this command will download PlotJuggler and install our plugins: +Once you've cloned and are in openpilot, this command will download PlotJuggler and install our plugins: `cd tools/plotjuggler && ./juggle.py --install` diff --git a/tools/plotjuggler/juggle.py b/tools/plotjuggler/juggle.py index b7c32d9bf1257f..a25a5640d49753 100755 --- a/tools/plotjuggler/juggle.py +++ b/tools/plotjuggler/juggle.py @@ -37,7 +37,7 @@ def install(): os.mkdir(INSTALL_DIR) url = os.path.join(RELEASES_URL, m + ".tar.gz") - with requests.get(url, stream=True, timeout=10) as r, tempfile.NamedTemporaryFile() as tmp: + with requests.get(url, stream=True) as r, tempfile.NamedTemporaryFile() as tmp: r.raise_for_status() with open(tmp.name, 'wb') as tmpf: for chunk in r.iter_content(chunk_size=1024*1024): @@ -110,8 +110,8 @@ def juggle_route(route_or_segment_name, segment_count, qlog, can, layout, dbc=No logs = logs[segment_start:segment_end] if None in logs: - resp = input(f"{logs.count(None)}/{len(logs)} of the rlogs in this segment are missing, would you like to fall back to the qlogs? (y/n) ") - if resp == 'y': + ans = input(f"{logs.count(None)}/{len(logs)} of the rlogs in this segment are missing, would you like to fall back to the qlogs? (y/n) ") + if ans == 'y': logs = r.qlog_paths()[segment_start:segment_end] else: print("Please try a different route or segment") diff --git a/tools/plotjuggler/layouts/max-torque-debug.xml b/tools/plotjuggler/layouts/max-torque-debug.xml index 20a49c2181691e..6903ca8b1532b8 100644 --- a/tools/plotjuggler/layouts/max-torque-debug.xml +++ b/tools/plotjuggler/layouts/max-torque-debug.xml @@ -16,7 +16,7 @@ - + @@ -53,7 +53,7 @@ - + if (v3 == 0 and v4 == 1) then return (value * v1 ^ 2) - (v2 * 9.81) diff --git a/tools/replay/framereader.cc b/tools/replay/framereader.cc index a1ff7b9f8e92a5..ecde9ad5d2b14e 100644 --- a/tools/replay/framereader.cc +++ b/tools/replay/framereader.cc @@ -133,7 +133,7 @@ bool FrameReader::load(const std::byte *data, size_t size, bool no_hw_decoder, s break; } packets.push_back(pkt); - // some stream seems to contain no keyframes + // some stream seems to contian no keyframes key_frames_count_ += pkt->flags & AV_PKT_FLAG_KEY; } valid_ = valid_ && !packets.empty(); diff --git a/tools/replay/replay.cc b/tools/replay/replay.cc index ed8dea61218b51..4b983fff85969d 100644 --- a/tools/replay/replay.cc +++ b/tools/replay/replay.cc @@ -81,7 +81,7 @@ void Replay::start(int seconds) { } void Replay::updateEvents(const std::function &lambda) { - // set updating_events to true to force stream thread release the lock and wait for evnets_udpated. + // set updating_events to true to force stream thread relase the lock and wait for evnets_udpated. updating_events_ = true; { std::unique_lock lk(stream_lock_); diff --git a/tools/replay/replay.h b/tools/replay/replay.h index e4217736d57c8d..86d609683a5034 100644 --- a/tools/replay/replay.h +++ b/tools/replay/replay.h @@ -61,7 +61,7 @@ class Replay : public QObject { void streamStarted(); protected slots: - void segmentLoadFinished(bool success); + void segmentLoadFinished(bool sucess); protected: typedef std::map> SegmentMap; diff --git a/tools/scripts/fetch_image_from_route.py b/tools/scripts/fetch_image_from_route.py index 139373f6650f06..39751ba55123d0 100755 --- a/tools/scripts/fetch_image_from_route.py +++ b/tools/scripts/fetch_image_from_route.py @@ -18,7 +18,7 @@ frame = int(sys.argv[3]) url = 'https://api.commadotai.com/v1/route/'+sys.argv[1]+"/files" -r = requests.get(url, headers={"Authorization": "JWT "+jwt}, timeout=10) +r = requests.get(url, headers={"Authorization": "JWT "+jwt}) assert r.status_code == 200 print("got api response") diff --git a/tools/scripts/setup_ssh_keys.py b/tools/scripts/setup_ssh_keys.py index b6d448673306da..5b5ebfbac5b68b 100755 --- a/tools/scripts/setup_ssh_keys.py +++ b/tools/scripts/setup_ssh_keys.py @@ -11,7 +11,7 @@ exit(1) username = sys.argv[1] - keys = requests.get(f"https://github.com/{username}.keys", timeout=10) + keys = requests.get(f"https://github.com/{username}.keys") if keys.status_code == 200: Params().put("GithubSshKeys", keys.text) diff --git a/tools/sim/bridge.py b/tools/sim/bridge.py index 0e4f47963b27ba..71a92ac771c501 100755 --- a/tools/sim/bridge.py +++ b/tools/sim/bridge.py @@ -346,7 +346,7 @@ def create_camera(fov, callback): vehicle_state = VehicleState() - # re-enable IMU + # reenable IMU imu_bp = blueprint_library.find('sensor.other.imu') imu = world.spawn_actor(imu_bp, transform, attach_to=vehicle) imu.listen(lambda imu: imu_callback(imu, vehicle_state)) diff --git a/update_requirements.sh b/update_requirements.sh index 060dca76ef4298..719a28c3599ead 100755 --- a/update_requirements.sh +++ b/update_requirements.sh @@ -44,7 +44,6 @@ pip install pip==21.3.1 pip install pipenv==2021.11.23 if [ -d "./xx" ]; then - echo "WARNING: using xx Pipfile ******" export PIPENV_SYSTEM=1 export PIPENV_PIPFILE=./xx/Pipfile fi @@ -57,8 +56,7 @@ else fi echo "pip packages install..." -pipenv sync --dev -pipenv --clear +pipenv install --dev --deploy --clear pyenv rehash echo "pre-commit hooks install..."