IQ.Pilot Release Commit @ 24db8ae

This commit is contained in:
IQ.Lvbs CI [bot]
2026-08-25 22:13:17 -05:00
parent 2f0ec679ec
commit 31a37f5a3c
67 changed files with 6134 additions and 137 deletions

View File

@@ -1 +1 @@
292ca77fab7ffaa87ab6a011206a1f5fdd3aeeb5
5dd3eebe813d76a72d63c76b1aac25e1c70b36bf

View File

@@ -1,8 +1,8 @@
{
"python/_iqclosure/_vendored.json": {
"mode": 420,
"sha256": "650f5873e58bb90fbe2429bb7e63eb7ac2145a39562b0780523835812b8baad3",
"size": 1805
"sha256": "6312a5dbc6e57c32c9ac07dbc30244d76e30f628f3633e576a02782fc140f522",
"size": 1734
},
"python/_iqclosure/iqpilot/__init__.py": {
"mode": 420,
@@ -134,6 +134,11 @@
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"size": 0
},
"python/_iqclosure/iqpilot/selfdrive/car/vehicle_catalog.json": {
"mode": 420,
"sha256": "205c2220b1e04bbb7400bcde757543dd538f6b9929fe0cac624da0195c878550",
"size": 122245
},
"python/_iqclosure/iqpilot/selfdrive/car/vehicle_catalog.py": {
"mode": 420,
"sha256": "8193cfcd9bda8651bf93f8d629996a22c760a42351c35a10c94329ab23fbf3f3",
@@ -141,8 +146,8 @@
},
"python/_iqclosure/iqpilot/selfdrive/iqmodeld/__init__.py": {
"mode": 420,
"sha256": "1fe78b73b9f08b7081f28b80e01ca06b2ed423231459d30942184297ce1e50d7",
"size": 632
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"size": 0
},
"python/_iqclosure/iqpilot/selfdrive/iqmodeld/config.py": {
"mode": 420,
@@ -151,8 +156,8 @@
},
"python/_iqclosure/iqpilot/selfdrive/iqmodeld/models/__init__.py": {
"mode": 420,
"sha256": "5865243a95ca4557d2a960302124a9898545cc3a8387e88ef569308e3d0f7077",
"size": 119
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"size": 0
},
"python/_iqclosure/iqpilot/selfdrive/iqmodeld/models/fetcher.py": {
"mode": 420,
@@ -351,27 +356,27 @@
},
"python/iqpilot_private/konn3kt/backups/archive_codec.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "82183cba3d305058bda02b49949fe7b12d52cd906cf10107a2e091632173b82e",
"sha256": "33808d1f465badf479acd5c52421820b1099ba45dffd05069ae020c0ab27956b",
"size": 135552
},
"python/iqpilot_private/konn3kt/backups/backup_keys.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "62b3742751af4c8fef9e3b0a439ba68dfc7acf6680340275894c4156c05de223",
"sha256": "447102fb8ebb45404bb34c7a8219e77a6813b841596a590f0c649c8b016d161e",
"size": 67664
},
"python/iqpilot_private/konn3kt/backups/backup_orchestrator.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "59a6ffcd63088e8b44c52d013f52d89fee01db9a3774b29a86de806c83960454",
"sha256": "f560709ef0c7b2b2186fe79369b52e4825ea9de7dd931492528605315b4e88bf",
"size": 204640
},
"python/iqpilot_private/konn3kt/backups/cbc_vault.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "f8d9435ef9281a3fa268b504dc326a98962dd02bd52df0570b2a0904e77a961f",
"sha256": "a26def1e1570d41ff76289be1232c9eb2f6d401006a817ec0e6d1892dbdfca3e",
"size": 69768
},
"python/iqpilot_private/konn3kt/backups/imahelper.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "bcbcf79fb098d3647d856958be01bbf4b2cc28b57db0e4dfe4cd41d90b0ea040",
"sha256": "e00f1fde78e58eb86270730f41279615dd8f1132e0d37f6e75e0b07b6a14967a",
"size": 203088
},
"python/iqpilot_private/konn3kt/flockd/__init__.py": {
@@ -381,12 +386,12 @@
},
"python/iqpilot_private/konn3kt/flockd/flockd.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "83ac740a10c113e1342cb9eee311fd2c0cb88e550441468155318207bdf400b7",
"sha256": "d240551319c007e1defd47d9e280b54199f32905024f3c549f8abf4f2183cb8a",
"size": 202184
},
"python/iqpilot_private/konn3kt/flockd/signatures.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "fbd898edf0446b6dcfb6787400dd6fd5bb344c429be491ac40318f8a1946d195",
"sha256": "b756bbe5241a27cb1eeb3bd7acc881eaf533ecb88a81d44b0b28d0355c2ce67a",
"size": 68080
},
"python/iqpilot_private/konn3kt/hephaestus/__init__.py": {
@@ -396,67 +401,67 @@
},
"python/iqpilot_private/konn3kt/hephaestus/_vendor/localapi_runtime.zip": {
"mode": 420,
"sha256": "9acc808279e1d740fd384ad2f31de7398c52c27baa8fa7a6e2f65b38cafc49e4",
"sha256": "ebd0dfe45771ce084690a6dfe4f8f5c198a167b4df2ed7a609fc31bccea7d6a1",
"size": 2100238
},
"python/iqpilot_private/konn3kt/hephaestus/ble_auth.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "eef8e9fdaea989bd323b8a3dde2ce1cc1090a8c60d31a81cf3eec53dd3600071",
"sha256": "f4a10a4ade9e9104eaa95b6cccbee87485293090437106683ac157596f305620",
"size": 268080
},
"python/iqpilot_private/konn3kt/hephaestus/ble_gatt.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "343423a3dbec1198f40745a6f303569c7b566d1a5eff8ff10ae5e3dacd0044b9",
"sha256": "81588dedf772af8847505f2b6ff2bb99f9988140b0ed26bbaaf8b178038881e8",
"size": 406176
},
"python/iqpilot_private/konn3kt/hephaestus/ble_rpc_dispatch.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "bf40085a06442714fb8386a77ac8e2d047eeadac084c09e80f3a5846137b2a16",
"sha256": "1d847dc09d7a9253e75b4712ea74a57cfacc45f7af28eb8e4096390f50512548",
"size": 68048
},
"python/iqpilot_private/konn3kt/hephaestus/ble_transportd.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "a14d91fb1ec6150a2eb11e206301ca1275e2a28c5e759823ed2ede57da05e34b",
"sha256": "3ce8f20ab0cf2d72f8f7003b5ef669b82eabbf42a1232ebb1858532d4607947f",
"size": 335776
},
"python/iqpilot_private/konn3kt/hephaestus/bt_gamepad.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "2ba6c8cb47106c3073d72d3291957c7aeefb5d704b851732b532c4f20e9f6b71",
"size": 271696
"sha256": "0c40d0452abf32d61c589f6c0450ace82b394daeef5ffa37578f4cbc2eed3ab2",
"size": 272112
},
"python/iqpilot_private/konn3kt/hephaestus/cloud_routes.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "a73ebe2e3dba51692fb8b227e3287209c2763a3f2d9fc8d5c7d62f7cdbf760dc",
"sha256": "92844c34453ae2c7848be78d2694014696194f7d3f1bdce3f9200f5f02c46afd",
"size": 134408
},
"python/iqpilot_private/konn3kt/hephaestus/hephaestusd.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "5825a4f141a829f7b3a8bbaf848fd8c25f38d99c6bf8c97cf19ca75c1c025241",
"size": 3715880
"sha256": "960b75c5cd0a71268e5b7feeb2564ec955b787620a878cd9568072cc0f856172",
"size": 3782232
},
"python/iqpilot_private/konn3kt/hephaestus/kwp2000.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "dc2147325ea4e1dafcaa3357c0878c3f39f3c4630417314f8bcb9af95abc7e91",
"sha256": "a56bc2bec547cda4b7301d4f39899f2178a985b36fd82f7c8440f44e3a18714b",
"size": 136472
},
"python/iqpilot_private/konn3kt/hephaestus/manage_hephaestusd.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "c3755a8dcfda46fce09fb8eb69d6b9dccdc5487fe6aa94f4df49279ebeb41acc",
"sha256": "f75e5bb8b1f08b0091e048402a80592a53e5c3c8ee9c299fc9a06538f74cae7e",
"size": 68208
},
"python/iqpilot_private/konn3kt/hephaestus/motd.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "270b887b04eba51006aff5c71c6b57a29099813752a49a6a1942380edb25790a",
"sha256": "558bdc66ebaa83b24f967ebc7f67479119d5ff8dc1853fd4ed6137b292050cbf",
"size": 67840
},
"python/iqpilot_private/konn3kt/hephaestus/tp20.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "fdc61d802b53f6233eab0a73f7ef732d4a67134a3849343e259871bc08fec0ef",
"sha256": "fa5503ef3e8b428a290252de3a7f7dae1bdbcc276505b20e77993057feb48c08",
"size": 135664
},
"python/iqpilot_private/konn3kt/hephaestus/vw_pq_flasher.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "98770387cdda540ce42c8d0b0508fd76b1c03a457d675823aa827b5725d5f888",
"sha256": "865c3c52118802edab7999b9f046de23757d26c504b3d33d77d7862c9e49bc7f",
"size": 269600
},
"python/iqpilot_private/konn3kt/uploaderd/__init__.py": {
@@ -466,8 +471,8 @@
},
"python/iqpilot_private/konn3kt/uploaderd/iquploaderd.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "84394628653c76537d7e2be1938415eeea3decc0791d57b4296f6177e30588db",
"size": 204296
"sha256": "af6f8c6d5c7e99316953f4249317a6c86ae68263445e570c659809fb05c03e15",
"size": 336280
},
"runtime": {
"entries": {
@@ -510,25 +515,25 @@
}
},
"signatures": {
"python/iqpilot_private/konn3kt/backups/archive_codec.cpython-312-aarch64-linux-gnu.so": "NAbCqbvyXIPYE7Il+5iOFO4gAWCSn+45RUlrGjxJydXtONcibCK7MMZmwC/bxvf94FdwaayTc5Bk2viE4sR3Aw==",
"python/iqpilot_private/konn3kt/backups/backup_keys.cpython-312-aarch64-linux-gnu.so": "GmZl9B5gnEtrfR2puNGucdznMZ1QAdTwI1T+HkJeXooHRdnhSh9/GarqxzjhOBT/br471jx9h7Qm8ZcYkc8VBw==",
"python/iqpilot_private/konn3kt/backups/backup_orchestrator.cpython-312-aarch64-linux-gnu.so": "ShJ0b8MtUi1uupmlF26qPutyMxazGJFRmoI7phHNyYZaocv3iEtqtUPwO9icjO9Oh6q2dNZhYNUel+MpRW9oBw==",
"python/iqpilot_private/konn3kt/backups/cbc_vault.cpython-312-aarch64-linux-gnu.so": "J01e8wupmVBf6jEqodutokSkmkSAbMCeoiTPkhM1ME125NtHrSbJOuoka9c3wdUXVeVz3itnt2KkiayDwCvmBA==",
"python/iqpilot_private/konn3kt/backups/imahelper.cpython-312-aarch64-linux-gnu.so": "DKRmG1/vNDmW/fM5LDEfiRFRKCUXWl/zs/w9pyLuP3P0uX+NOvVP4V3niGVjdfpcVQsoeSds+Y/2ml2BVhepDg==",
"python/iqpilot_private/konn3kt/flockd/flockd.cpython-312-aarch64-linux-gnu.so": "z+x9JhNkR5wwo+oN64kBuDfeGmWQtrm73iqmK8e4KYDi6bW5EbR17YGJd2w2Qpy3Y+O4hqWPTzimC76NvvgoBg==",
"python/iqpilot_private/konn3kt/flockd/signatures.cpython-312-aarch64-linux-gnu.so": "6+o1p0LzuO2fyXgzmKQ8yqIxTPoww9wkE5BBQNiTthEw/KSa8mFn1QxmN/5Rc+O3fmgNydxEdjMIwcsmQpL/DA==",
"python/iqpilot_private/konn3kt/hephaestus/ble_auth.cpython-312-aarch64-linux-gnu.so": "YxpFvXNm0HIXYVVaW1zDXwWOsh5nz7eZS6DdsMlnMdl8OHaSgabWZBN7RF4iWJP/GU9S0x6u9hOBXLosf12wDQ==",
"python/iqpilot_private/konn3kt/hephaestus/ble_gatt.cpython-312-aarch64-linux-gnu.so": "FX+aDGY2Xs5Y6ekJBuRhjlw/CxxwSfC/ZwOyY+k/v7PULJ9T5fEJjuHE8hAmkdPK4ED7GT5VO5FB4twOvOiiCw==",
"python/iqpilot_private/konn3kt/hephaestus/ble_rpc_dispatch.cpython-312-aarch64-linux-gnu.so": "uPcSh8CGEYHeu9ApsPIn0rNCFz+EBTyhuqQyGLGjU/RSnoWhkhHmqpbeCfgZTBmkwLol7Onfex0w/ELEjUyrDQ==",
"python/iqpilot_private/konn3kt/hephaestus/ble_transportd.cpython-312-aarch64-linux-gnu.so": "BJgU130UhimX2PSMYbNZJ0/nUFHI0MolmTrk0d5wTJ7uvmIT0wGsaO78PGp66krMtXaDFdhg/UJUz/KRyVPCBg==",
"python/iqpilot_private/konn3kt/hephaestus/bt_gamepad.cpython-312-aarch64-linux-gnu.so": "UzuHr0ym4jsHBzBW4e5XPcP+46zeds6Ec+7FK9hqMjJx+CVRfg9/1CfLCwqCUhe7QC4puqt0R8AQ6tCWppflCg==",
"python/iqpilot_private/konn3kt/hephaestus/cloud_routes.cpython-312-aarch64-linux-gnu.so": "aPUVcHH/ashhYDylUw7AblIIYPOzavy+NHAwxhCkavILBvEwyvpoZAQuq1ajAUrsqUUoVDBRGUT8qQpcXQslBw==",
"python/iqpilot_private/konn3kt/hephaestus/hephaestusd.cpython-312-aarch64-linux-gnu.so": "9LDSMTtL21Ec4iVjYxBL8UjclFf16M/vTSehYveVHOnVOaZPiki9mhf1UJScCxbTK24EqLMD14AdKzZ44qokBA==",
"python/iqpilot_private/konn3kt/hephaestus/kwp2000.cpython-312-aarch64-linux-gnu.so": "hjQ9KQsNSTO3Sj2DpZ9RQHMIgzvGQMhCcFsMs7fjV2v4gzd4AblfY09I2/Jg/WmghjB9q2onqaA+ARKixvAvCA==",
"python/iqpilot_private/konn3kt/hephaestus/manage_hephaestusd.cpython-312-aarch64-linux-gnu.so": "agjSn1SbGK6VW8X/dDRFpqz5sTpjvBnlnMKnLXf/o0ApUeECcgujLuOAZu+TPyfmcEVcPyE8TYYamCM0VGY0Dw==",
"python/iqpilot_private/konn3kt/hephaestus/motd.cpython-312-aarch64-linux-gnu.so": "MUiDt9IKQ1YTyGTAVYO2bcG8rfvkbECFQOAq5q6m1y+V37y9O0dN6OK8YyHPDRbshBCDupcaUx3xdu2Rh5toAA==",
"python/iqpilot_private/konn3kt/hephaestus/tp20.cpython-312-aarch64-linux-gnu.so": "1U+W1BeavzaoaMEQxCFBPB4RleaE704xgf7a9tsqMfvScfU80nvge/VuvgIF64OPxYZIoYv9s0oMrzTNy6ZfDw==",
"python/iqpilot_private/konn3kt/hephaestus/vw_pq_flasher.cpython-312-aarch64-linux-gnu.so": "RzZ8ZwI9zExHqNph32fB54/fs1oZZHHFoYWlqR5P53QPKws15FJ/hPalVSaijO9rgspgNSHMOZ6Z/ln3Z3JpDg==",
"python/iqpilot_private/konn3kt/uploaderd/iquploaderd.cpython-312-aarch64-linux-gnu.so": "3W7enZXiH/fkwzwm3YMt3lw8OvetDzHK08jeZdNvQ6JMTjojSiO/jgulmOplMaNOrdp4aC/C1jOER70DwzxPCQ=="
"python/iqpilot_private/konn3kt/backups/archive_codec.cpython-312-aarch64-linux-gnu.so": "I5WvMYxvGUQ21GFf3z5Bb/iwHyX9DXkImJPcJ2+pvYKepYkWXfKv44bsoN4gi+MszZDRfByXWOBpglSVL5G3Aw==",
"python/iqpilot_private/konn3kt/backups/backup_keys.cpython-312-aarch64-linux-gnu.so": "rE32aIZL5MMCi/bx9Xn2i6YA8wg1Y2FkkrKpZcXRvd7k+eIPny0Rftle54HfxuKm6atBp8Gy2yWTgt2+pl8+AQ==",
"python/iqpilot_private/konn3kt/backups/backup_orchestrator.cpython-312-aarch64-linux-gnu.so": "QqiXU+Mfh/tcjB7S2ZBGoV0F4QrCi1Fz1NgBDWVQhYwnZh99vrBcZWuKkpCf8l1ej7cfsei6dPEIZ2ppnGIwCw==",
"python/iqpilot_private/konn3kt/backups/cbc_vault.cpython-312-aarch64-linux-gnu.so": "h4w1OXzywntiUNy9DZ4lIoimrIqzPbmD/Kx66veVsAZYuH4U2mAtTSRIU3OVD+01QCJTraux0ky21UmdbLLWBQ==",
"python/iqpilot_private/konn3kt/backups/imahelper.cpython-312-aarch64-linux-gnu.so": "NFd15/tCR0axTA271DvJDg/UkGT7hJztxpjS9SnwgjSGawY3OseP8RjFT1eBk7aj6+j4zld3gIzfBbbYv6gxBQ==",
"python/iqpilot_private/konn3kt/flockd/flockd.cpython-312-aarch64-linux-gnu.so": "Kd1ueNtTDzE6rVn8dfTA6NtjGgzQOTuNq/eSmnvX+Y3CqSZXHsSEdts/hXTcieJaPBX3S1HYb9lJCRYPqqHJBg==",
"python/iqpilot_private/konn3kt/flockd/signatures.cpython-312-aarch64-linux-gnu.so": "bA+/ixBULXSP2307fH18UnkQH8Ld6L9F9RtiFTgLeNC+sPyAM917lN7FBeY2HmFhOY3fqrwWmKI/2l1krgXcAg==",
"python/iqpilot_private/konn3kt/hephaestus/ble_auth.cpython-312-aarch64-linux-gnu.so": "z1gIQSglkHTy0Kt3fNocuxc8A6BxpsOgCWNkU0+bqU04YDibWFTYMhWwysMyG7rs8WH286R6oHAQJXCSD9FUAg==",
"python/iqpilot_private/konn3kt/hephaestus/ble_gatt.cpython-312-aarch64-linux-gnu.so": "l0jmZ40q0Don2N8dqLWbWXfjA1QSE0hpWN9egEVlKeW+uKEEzdEqdCuVhpgGEhqwpT7T0PRIyu9ljs9BM0lLCw==",
"python/iqpilot_private/konn3kt/hephaestus/ble_rpc_dispatch.cpython-312-aarch64-linux-gnu.so": "KsBNelgm9ymfgcNkxKIPCGs0u3XY4cZV/WoWZ0a2kc75EeGb18Wvb/sEoNFIZJ5TAuUjty0CPGXSrBsQhzTZAQ==",
"python/iqpilot_private/konn3kt/hephaestus/ble_transportd.cpython-312-aarch64-linux-gnu.so": "pqqHfl09zhLuNxfuUjbN8CKrXJhlSzLdkXn37Lw8XnwCBZKzYeq8FT/PCvi3EF/YTMi/Xd/tfLP4Zs86Jn5YDA==",
"python/iqpilot_private/konn3kt/hephaestus/bt_gamepad.cpython-312-aarch64-linux-gnu.so": "tC0FMPYQToZvSvG/DIAUEpuRDGyhHt7KvygVWwdk9Iz1/oIp8zquQ9tIGM5xAEt2y+i2w2jSz88OJBaYZvmtDA==",
"python/iqpilot_private/konn3kt/hephaestus/cloud_routes.cpython-312-aarch64-linux-gnu.so": "uDYCHGcv2Mp1RURMROVAyJBFLOumSOzUJGEQoioXkyVoAhRG2UoguXikj0oBWGXKos98L4kI/TIAv0z73F5hBw==",
"python/iqpilot_private/konn3kt/hephaestus/hephaestusd.cpython-312-aarch64-linux-gnu.so": "F8BHYoLSCoNw9SVvp0cH8ZRFGuj7Ojg9FzJvKOgLiNkKsr5Kp5Da/t0jqLljUjRlEZh0a6lSBGRCj0VqS6n7BQ==",
"python/iqpilot_private/konn3kt/hephaestus/kwp2000.cpython-312-aarch64-linux-gnu.so": "sJXu00WLY6Xsbkc7YqoGbyKz8V07TTAda+LbtFmVyKTsfx1I/w4BrR6rK9QQ0uIvG80X/onVyWcJYkHcHI8GAg==",
"python/iqpilot_private/konn3kt/hephaestus/manage_hephaestusd.cpython-312-aarch64-linux-gnu.so": "2g0YPlO4c9mwv2p1FtVrQEatX/WM69bLDhVEhIg5rHeBBx75sdWRaKmnCKfR/odNleLhXWLolABESA830u4cAg==",
"python/iqpilot_private/konn3kt/hephaestus/motd.cpython-312-aarch64-linux-gnu.so": "ATjdthMRDwYdJT00DALdiXQVoHTUNB9iyjPU6vUIf4GfC4vaOOBirUPZ4gtBOrLQS+hLn9w7nM2gF4fbSMsxCg==",
"python/iqpilot_private/konn3kt/hephaestus/tp20.cpython-312-aarch64-linux-gnu.so": "7N+zB4DBl9X2izAm4qBVafrtg5uaX7/sKyU4WzHgYtwo38qNZPSEALXcLdFHZ0bF3n3qvOZPKL7zGDLgNuapAg==",
"python/iqpilot_private/konn3kt/hephaestus/vw_pq_flasher.cpython-312-aarch64-linux-gnu.so": "LS6HrT0pDfbHnLHbfH60IRhAwO3kK5oFYsCiJhDbpPI8MxyNSqg7tU7SOoo3m0a+CzBKfEQP7ri0ZC2FFBhIBw==",
"python/iqpilot_private/konn3kt/uploaderd/iquploaderd.cpython-312-aarch64-linux-gnu.so": "uQbFciwEpkVFn/LMozK0Jm9+ZDh2VuNpryBmT6m1NaC4v9bxJSFxC/CT4JvvtipRgJRTbFnzxOppiX+bt5pOBQ=="
}
}

View File

@@ -1 +1 @@
cQ9jTWO/J9039E1TJAs/oACuUTbhSRciZy07VantcDjTofWJPxCZ32Go8eqQPHipjbeXU8Oo4jJlNdjsSg2DAg==
0MdDcjhhpW0t9PD/b+przWxHmtrchzKk9Q24ViXNM7b46lNHbM1s5AfPwX2gFYhaJb9HKrSNDqq6GukmhdUBAw==

View File

@@ -21,9 +21,7 @@
"iqpilot.konn3kt.registration",
"iqpilot.konn3kt.service_health",
"iqpilot.selfdrive.car.vehicle_catalog",
"iqpilot.selfdrive.iqmodeld",
"iqpilot.selfdrive.iqmodeld.config",
"iqpilot.selfdrive.iqmodeld.models",
"iqpilot.selfdrive.iqmodeld.models.fetcher",
"iqpilot.selfdrive.iqmodeld.models.helpers",
"iqpilot.selfdrive.locationd.calibrationd",

View File

@@ -1,23 +0,0 @@
"""
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos/
"""
from pathlib import Path
def _models_dir() -> Path:
return Path(__file__).resolve().parent / "models"
def _artifact_path(stem: str, suffix: str) -> Path:
return _models_dir() / f"{stem}{suffix}"
MODEL_ASSETS = {
"onnx": _artifact_path("supercombo", ".onnx"),
"tinygrad": _artifact_path("supercombo", "_tinygrad.pkl"),
"metadata": _artifact_path("supercombo", "_metadata.pkl"),
}
MODEL_PATH = MODEL_ASSETS["onnx"]
MODEL_PKL_PATH = MODEL_ASSETS["tinygrad"]
METADATA_PATH = MODEL_ASSETS["metadata"]

View File

@@ -1,3 +0,0 @@
"""
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos/
"""

View File

@@ -11,7 +11,7 @@
},
"python/iqpilot_private/maps/__init__.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "19691460aa4e727e250e955410bdf5b142cfd1d4f53dc9c657e06578b58d78c1",
"sha256": "b4f12341a5ebeb6263226cd03391c6505c708279c9c4ff4c0057326f6325e8ab",
"size": 67616
},
"python/iqpilot_private/maps/__init__.py": {
@@ -21,7 +21,7 @@
},
"python/iqpilot_private/maps/git_auth.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "208e08697aa6209a758594dbe0a04110fdc290c822638f5afa10c12086335ee0",
"sha256": "84600544b6ca61637b1d332d4881a00083ef9001efba65ac45cca79a2a526c33",
"size": 67856
},
"runtime": {
@@ -33,7 +33,7 @@
}
},
"signatures": {
"python/iqpilot_private/maps/__init__.cpython-312-aarch64-linux-gnu.so": "y/tdmrE8VKvJv4U3hyMIKK3j92wcdXXlyPZ2UGHhtGM5Pb/xJPtekQavxkzvraDZuE+YGyaDyzwI6Y147/vXBQ==",
"python/iqpilot_private/maps/git_auth.cpython-312-aarch64-linux-gnu.so": "xeIydgwjiL7jOaheUl/ZHImzGkj9FJomDs5bsynePQa+YcPrm6vFm5wSJ9DEaA9LZ8XnsUVBSR/iftUap6IsDg=="
"python/iqpilot_private/maps/__init__.cpython-312-aarch64-linux-gnu.so": "f9iG6goRpO0HKZpoQUoZ7KGcO7YBqV3oBtZxtES4IjeOqUl7zPaVAMxGYD0jkkjtC5HKBH2fldpGGOAoQvhbBw==",
"python/iqpilot_private/maps/git_auth.cpython-312-aarch64-linux-gnu.so": "63rRKgkKdIVzRaDNRFYj+X/NRNnZrwra43QGZF8VcafRopvwXnXrSgjxmgLPIRZQVk5YPcn9cgHXAuU2UJjdDw=="
}
}

View File

@@ -1 +1 @@
uTmhlpbkdONUUp92muUv9TbgTDG50cv97k+PrzEzt5QQHbiMxJ6B7UZ1VYz43hJ+865DuMYGSmpLTvN4DueDBA==
UrGrwApvCiaSCaGrD+6aKwLNTm5TaQ02X2dS4DVbM9Gw6qvQ3w6/ql/mfbr/i0Y1SgPIDfKx8fCOdcCWIwJtBA==

View File

@@ -16,18 +16,18 @@
},
"python/iqpilot_private/updater/_iqos_pat_blob.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "50f00d356371a60a50b2395966b6b1646fd3b8306e9ad6fe0229ad0e24186683",
"sha256": "949c976482e5168aa1898087a5a0c02f523e4b8a43940eaadba56e5df81819f2",
"size": 67616
},
"python/iqpilot_private/updater/_pat_blob.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "57b15e47bcc1084d33bda3908fb50347c2403cde0c9c951dad1b107ef56b06f1",
"sha256": "908a448f4ddad2d95ef524a771ee0038c62e72c44598cc8db2755c178b950de0",
"size": 67616
},
"python/iqpilot_private/updater/git_remote.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
"sha256": "1d3611c753cc94d1e22802900a2487a13c445def98fa998385fa72935a0dd110",
"size": 136488
"sha256": "c3495a4480205bbf1e21e7ea0b55a27409be1da68e974ef070946bfd726c8c90",
"size": 136576
},
"runtime": {
"entries": {
@@ -38,8 +38,8 @@
}
},
"signatures": {
"python/iqpilot_private/updater/_iqos_pat_blob.cpython-312-aarch64-linux-gnu.so": "ZIgAfOcrpjAYBY/iLm9oovGs6jv7dQAToObwc9rrPpPTEgQZ/zTcTOa0TcqGTU/lK0tPhum2WVrPpxwosKUwDg==",
"python/iqpilot_private/updater/_pat_blob.cpython-312-aarch64-linux-gnu.so": "Zv7AsE+0KgGABA4n9Hf40UQVOz7k2ew/vxgKqkUpyFjZKdst6DUecAxyBPbK4Z8owTaKnnbNRxuRGiJtr+sJDA==",
"python/iqpilot_private/updater/git_remote.cpython-312-aarch64-linux-gnu.so": "2aLUgznDiiBF3sYwIxZKMjMW2A1S9q+tHZUnyAiEB48QbxAFjDAS6tMHUp5ej6/JAmejOzxQePYPL1jJnxKsBQ=="
"python/iqpilot_private/updater/_iqos_pat_blob.cpython-312-aarch64-linux-gnu.so": "2BgXuTkWa3sjvPsyTgFHVBaZYOE+6MmRE+/lUlINyD05fHG6qgf6GJPeYyy6TPNZqhBWoI5z/NmRjAoVzzsSDQ==",
"python/iqpilot_private/updater/_pat_blob.cpython-312-aarch64-linux-gnu.so": "EvASRs8Z45SknoiFmd9FpFV0boTy2L+OIJqEQMfVq88jglU/RVs5RNg/JW3SrghodMvxgTIXzBrZy2OggDPRCQ==",
"python/iqpilot_private/updater/git_remote.cpython-312-aarch64-linux-gnu.so": "wbN3CwOrLv0iX3a2nSmr4dTr3kEHrSEPmQ+S6IiccUzgVo8rBQXRe0dduyiQZzXrnEBYRAvz66WXfyWPrWs8AQ=="
}
}

View File

@@ -1 +1 @@
D9FZfSC3DUspPq4ewwPjNoCS1N8ai3jcgutVQo94CnOI6Wcx3L1H30hTZ6SS8jw9MfMsVaggFXfMo2QT4yJlBQ==
JJCbPdLrTbJu+aVPIcsTJTbsltzP0Zl97r6EM77B7ebCsnS9yU1Tx9+NPui1OVVPiQAigyDxi/TZZyIYBWigDw==

View File

@@ -375,7 +375,9 @@ class CarController(CarControllerBase):
self.LateralController.reset()
if self.steering_power_last > 0:
hca_enabled = True
apply_curvature = np.clip(CS.out.steeringCurvature, -self.CCP.CURVATURE_LIMITS.CURVATURE_MAX, self.CCP.CURVATURE_LIMITS.CURVATURE_MAX)
handoff_curvature = self.apply_curvature_last + (CS.out.steeringCurvature - self.apply_curvature_last) * self.CCP.CURVATURE_HANDOFF_RATE
apply_curvature = apply_std_curvature_limits(handoff_curvature, self.apply_curvature_last, CS.out.vEgoRaw, CS.out.steeringCurvature,
CS.out.steeringPressed, self.CCP.STEER_STEP, True, self.CCP.CURVATURE_LIMITS)
steering_power = max(self.steering_power_last - self.CCP.STEERING_POWER_STEP, 0)
else:
hca_enabled = False

View File

@@ -6,9 +6,10 @@ import os
import math
import time
from iqdbc.can import CANParser
from iqdbc.car import Bus, structs
from iqdbc.car import DT_CTRL, Bus, structs
from iqdbc.car.interfaces import CarStateBase
from iqdbc.car.common.conversions import Conversions as CV
from iqdbc.car.common.filter_simple import FirstOrderFilter
from iqdbc.car.volkswagen.values import CAR, DBC, CanBus, NetworkLocation, RADAR_DISABLE_STATE, TransmissionType, GearShifter, \
CarControllerParams, VolkswagenFlags, VolkswagenFlagsIQ
from iqdbc.car.volkswagen.speed_limit_manager import SpeedLimitManager
@@ -28,6 +29,7 @@ class CarState(CarStateBase):
CRUISE_FAULT_LATERAL_DISABLE_FRAMES = 20
MEB_TEMP_CRUISE_FAULT = 6
MEB_TOLERANCE_MAX = 100
DRIVER_TORQUE_TAU = 0.10
def __init__(self, CP, CP_IQ):
from iqpilot.system.proprietary_runtime._verified_import import import_verified_module
@@ -37,6 +39,7 @@ class CarState(CarStateBase):
self.frame = 0
self.eps_init_complete = False
self.CCP = CarControllerParams(CP)
self.driver_torque_filter = FirstOrderFilter(0.0, self.DRIVER_TORQUE_TAU, DT_CTRL)
self.button_states = {button.event_type: False for button in self.CCP.BUTTONS}
self.esp_hold_confirmation = False
self.upscale_lead_car_signal = False
@@ -323,7 +326,7 @@ class CarState(CarStateBase):
ret.steeringRateDeg = pt_cp.vl["LWI_01"]["LWI_Lenkradw_Geschw"] * (1, -1)[int(pt_cp.vl["LWI_01"]["LWI_VZ_Lenkradw_Geschw"])]
ret.steeringTorque = pt_cp.vl["LH_EPS_03"]["EPS_Lenkmoment"] * (1, -1)[int(pt_cp.vl["LH_EPS_03"]["EPS_VZ_Lenkmoment"])]
driver_override_threshold = self._iq_lvbs_alc.vw_driver_override_threshold_cnm(self, "mqb", self.CCP.STEER_DRIVER_ALLOWANCE)
ret.steeringPressed = abs(ret.steeringTorque) > driver_override_threshold
ret.steeringPressed = abs(self.driver_torque_filter.update(ret.steeringTorque)) > driver_override_threshold
self.curvature = -pt_cp.vl["QFK_01"]["Curvature"] * (1, -1)[int(pt_cp.vl["QFK_01"]["Curvature_VZ"])]
ret.steeringCurvature = self.curvature

View File

@@ -118,7 +118,7 @@ class CarControllerParams:
if CP.flags & VolkswagenFlags.PQ:
self.LDW_STEP = 5 # LDW_1 message frequency 20Hz
self.ACC_HUD_STEP = 4 # ACC_GRA_Anzeige frequency 25Hz
self.STEER_DRIVER_ALLOWANCE = 80 # Driver intervention threshold 0.8 Nm
self.STEER_DRIVER_ALLOWANCE = 80
self.STEER_DELTA_UP = 6
self.STEER_DELTA_DOWN = 10
@@ -147,11 +147,12 @@ class CarControllerParams:
elif CP.flags & (VolkswagenFlags.MEB | VolkswagenFlags.MQB_EVO):
self.LDW_STEP = 10
self.ACC_HUD_STEP = 6
self.STEER_DRIVER_ALLOWANCE = 60
self.STEER_DRIVER_ALLOWANCE = 80
self.STEER_DRIVER_MAX = 300
self.STEERING_POWER_MAX = 90
self.STEERING_POWER_MIN = 4
self.STEERING_POWER_STEP = 2
self.CURVATURE_HANDOFF_RATE = 0.20
self.CURVATURE_PID: structs.CarParams.LateralPIDTuning = structs.CarParams.LateralPIDTuning(
kpBP=[10., 40.],
@@ -204,7 +205,7 @@ class CarControllerParams:
self.hca_status_values = can_define.dv["LH_EPS_03"]["EPS_HCA_Status"]
if CP.flags & VolkswagenFlags.MLB:
self.STEER_DRIVER_ALLOWANCE = 60 # Driver intervention threshold 0.6 Nm
self.STEER_DRIVER_ALLOWANCE = 80 # Driver intervention threshold 0.8 Nm
self.STEER_DELTA_UP = 9 # Max HCA reached in 0.66s (STEER_MAX / (50Hz * 0.66))
self.STEER_DELTA_DOWN = 10 # Min HCA reached in 0.60s (STEER_MAX / (50Hz * 0.60))
self.ACC_HUD_TEXT_STEP = int(2.0 / DT_CTRL) # ACC_02 primary display text dwell time
@@ -231,7 +232,7 @@ class CarControllerParams:
self.ACC_HUD_TEXT_DISTANCE = {1: 2, 2: 3, 3: 4, 4: 5} # follow distance bars to display text
else:
self.STEER_DRIVER_ALLOWANCE = 80 # Driver intervention threshold 0.8 Nm
self.STEER_DRIVER_ALLOWANCE = 80
self.STEER_DELTA_UP = 4 # Max HCA reached in 1.50s (STEER_MAX / (50Hz * 1.50))
self.STEER_DELTA_DOWN = 10 # Min HCA reached in 0.60s (STEER_MAX / (50Hz * 0.60))

View File

@@ -175,7 +175,7 @@ static bool volkswagen_mlb_tx_hook(const CANPacket_t *msg) {
.max_rt_delta = 169, // 10 max rate up * 50Hz send rate * 250000 RT interval / 1000000 = 112.5 ; 112.5 * 1.5 for safety pad = 168.75
.max_rate_up = 9, // 5.0 Nm/s RoC limit (EPS rack has own soft-limit of 5.0 Nm/s)
.max_rate_down = 10, // 5.0 Nm/s RoC limit (EPS rack has own soft-limit of 5.0 Nm/s)
.driver_torque_allowance = 60,
.driver_torque_allowance = 80,
.driver_torque_multiplier = 3,
.type = TorqueDriverLimited,
};

View File

@@ -32,7 +32,7 @@ class TestVolkswagenMlbSafetyBase(common.CarSafetyTest, common.DriverTorqueSteer
MAX_TORQUE_LOOKUP = [0], [300]
MAX_RT_DELTA = 169
DRIVER_TORQUE_ALLOWANCE = 60
DRIVER_TORQUE_ALLOWANCE = 80
DRIVER_TORQUE_FACTOR = 3
# Wheel speeds _esp_03_msg

View File

@@ -15,6 +15,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"AthenadPid", {PERSISTENT, INT}},
{"AthenadUploadQueue", {PERSISTENT, JSON}},
{"AthenadRecentlyViewedRoutes", {PERSISTENT, STRING}},
{"IQUploaderDeferred", {PERSISTENT, JSON}},
{"BackupManagerK3_CreateBackup", {CLEAR_ON_MANAGER_START, BOOL}},
{"BackupManagerK3_RestoreVersion", {CLEAR_ON_MANAGER_START, STRING}},
{"BootCount", {PERSISTENT, INT}},
@@ -269,6 +270,32 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"iqMqbAccResume", {PERSISTENT, BOOL, "0"}},
{"iqMqbSteeringLockout", {PERSISTENT, BOOL, "0"}},
{"AllowLateralWhenLongUnavailable", {PERSISTENT, BOOL}},
{"IQEmacEnabled", {PERSISTENT, BOOL, "0"}},
{"IQEmacHost", {PERSISTENT, STRING}},
{"IQEmacModel", {PERSISTENT, STRING}},
{"IQEmacCatalogCache", {PERSISTENT, JSON}},
{"IQEgpuDisabled", {PERSISTENT, BOOL, "0"}},
{"IQEgpuEnabled", {PERSISTENT, BOOL, "0"}},
{"MacModelStatus", {CLEAR_ON_MANAGER_START, JSON}},
{"MacModelLatencyMs", {CLEAR_ON_MANAGER_START, FLOAT}},
{"MacModelMissRate", {CLEAR_ON_MANAGER_START, FLOAT}},
{"MacModelPresent", {CLEAR_ON_MANAGER_START, BOOL}},
{"MacModelReachable", {CLEAR_ON_MANAGER_START, BOOL}},
{"MacModelCompiled", {CLEAR_ON_MANAGER_START, BOOL}},
{"MacModelReady", {CLEAR_ON_MANAGER_START, BOOL}},
{"MacModelActive", {CLEAR_ON_MANAGER_START, BOOL}},
{"MacModelFailed", {CLEAR_ON_MANAGER_START, BOOL}},
{"MacModelLastError", {CLEAR_ON_MANAGER_START, STRING}},
{"MacModelDownloadProgress", {CLEAR_ON_MANAGER_START, FLOAT}},
{"UsbGpuStatus", {CLEAR_ON_MANAGER_START, JSON}},
{"UsbGpuLatencyMs", {CLEAR_ON_MANAGER_START, FLOAT}},
{"UsbGpuActive", {CLEAR_ON_MANAGER_START, BOOL}},
{"UsbGpuFailed", {CLEAR_ON_MANAGER_START, BOOL}},
{"UsbGpuPresent", {CLEAR_ON_MANAGER_START, BOOL}},
{"UsbGpuLastError", {CLEAR_ON_MANAGER_START, STRING}},
{"UsbGpuSetupProgress", {CLEAR_ON_MANAGER_START, FLOAT}},
{"UsbGpuCompiled", {CLEAR_ON_MANAGER_START, BOOL}},
{"UsbGpuLoading", {CLEAR_ON_MANAGER_START, BOOL}},
{"IQDynamicMode", {PERSISTENT, BOOL, "0"}},
{"IQDynamicBlendStockRadar", {PERSISTENT, BOOL, "0"}},

View File

@@ -21,11 +21,21 @@ except Exception: # ProprietaryModuleMissing or import errors in stripped build
_private_base_urls = None
_private_auth = None
DEFAULT_TILE_BUNDLE_BASE_URL = "https://maps.konn3kt.com/iqosmd/v1"
# Tile bundles live as LFS objects in the PRIVATE repo IQ.Lvbs/iqmaps (R2 is gone).
# Anonymous access 404s by design; devices authenticate with the embedded read-only PAT
# carried by the closed-source updater bundle (same fetch account as the OS images).
DEFAULT_TILE_BUNDLE_BASE_URL = "https://git.konn3kt.com/IQ.Lvbs/iqmaps/raw/branch/master"
FALLBACK_TILE_BUNDLE_BASE_URL = "https://gitlvb.teallvbs.xyz/IQ.Lvbs/iqmaps/raw/branch/master"
# Gitea /raw NEVER returns LFS content -- it returns this pointer, and the real bytes come
# from the LFS batch API (see _resolve_object_url).
LFS_POINTER_MAGIC = b"version https://git-lfs"
BASE_URL_PARAM = "OfflineTilesBaseUrl"
PROGRESS_PARAM = "OfflineTilesDownloadProgress"
REQUEST_PARAM = "OfflineTilesDownloadRequest"
CHUNK_BYTES = 1 << 20
# must match scripts/iqpilot/tile_factory/upload_bundles_lfs.py
PART_BYTES = 90 * 1024 * 1024
HTTP_TIMEOUT_S = 30.0
STREAM_RETRIES = 8
@@ -44,9 +54,52 @@ def candidate_base_urls(params: Params) -> list[str]:
except Exception:
pass
urls.append(DEFAULT_TILE_BUNDLE_BASE_URL)
urls.append(FALLBACK_TILE_BUNDLE_BASE_URL)
return urls
def _maps_auth_module():
"""The read PAT lives in the compiled updater bundle (never in this open file)."""
try:
from iqpilot.system.proprietary_runtime._verified_import import import_verified_module
return import_verified_module("iqpilot_updater_private", "iqpilot_private.updater.git_remote")
except Exception:
pass
try:
import importlib
import os
import sys
root = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
bundle_python = os.path.join(root, "artifacts", "iqpilot_updater_private", "python")
if os.path.isdir(bundle_python):
if bundle_python not in sys.path:
sys.path.insert(0, bundle_python)
return importlib.import_module("iqpilot_private.updater.git_remote")
except Exception:
pass
return None
def request_headers(url: str) -> dict:
mod = _maps_auth_module()
if mod is not None:
try:
headers = mod.map_tiles_headers(url)
if headers:
return headers
except Exception:
pass
try:
from iqpilot.common.git_creds import get_credentials
creds = get_credentials()
if creds and all(creds) and "/iq.lvbs/iqmaps" in url.lower():
import base64
return {"Authorization": "Basic " + base64.b64encode(f"{creds[0]}:{creds[1]}".encode()).decode()}
except Exception:
pass
return {}
def request_auth() -> tuple[str, str] | None:
if _private_auth is None:
return None
@@ -56,8 +109,67 @@ def request_auth() -> tuple[str, str] | None:
return None
def _lfs_endpoint(base_url: str) -> str:
"""<host>/<owner>/<repo>/raw/branch/<b> -> <host>/<owner>/<repo>.git/info/lfs"""
return base_url.split("/raw/", 1)[0] + ".git/info/lfs"
def _resolve_oid_url(session: requests.Session, base_url: str, oid: str, size: int,
headers: dict) -> tuple[str, dict]:
"""Bundles are stored as bare LFS objects addressed by oid from the index -- no pointer
files, because committing one per part meant hundreds of concurrent commits per branch."""
batch = session.post(f"{_lfs_endpoint(base_url)}/objects/batch",
data=json.dumps({"operation": "download", "transfers": ["basic"],
"objects": [{"oid": oid, "size": size}]}),
headers={"Content-Type": "application/vnd.git-lfs+json",
"Accept": "application/vnd.git-lfs+json", **headers},
timeout=HTTP_TIMEOUT_S)
batch.raise_for_status()
entry = batch.json()["objects"][0]
if "actions" not in entry:
raise requests.RequestException(f"LFS object unavailable: {entry.get('error', oid)}")
action = entry["actions"]["download"]
return action["href"], action.get("header", {})
def _resolve_object_url(session: requests.Session, url: str, headers: dict) -> tuple[str, dict]:
"""Follow a Gitea LFS pointer to the real (pre-signed) object URL.
Returns the URL to stream plus any extra headers it needs. A plain host that serves the
bytes directly (local test server, static mirror) resolves to itself unchanged."""
probe = session.get(url, headers={**headers, "Accept-Encoding": None}, stream=True,
timeout=HTTP_TIMEOUT_S)
probe.raise_for_status()
if int(probe.headers.get("content-length") or 0) >= 1024:
probe.close()
return url, {}
body = probe.content
probe.close()
if not body.startswith(LFS_POINTER_MAGIC):
return url, {}
meta = dict(line.split(" ", 1) for line in body.decode().strip().splitlines() if " " in line)
oid = meta["oid"].split(":", 1)[1]
size = int(meta["size"])
lfs_base = url.split("/raw/", 1)[0] + ".git/info/lfs"
batch = session.post(f"{lfs_base}/objects/batch",
data=json.dumps({"operation": "download", "transfers": ["basic"],
"objects": [{"oid": oid, "size": size}]}),
headers={"Content-Type": "application/vnd.git-lfs+json",
"Accept": "application/vnd.git-lfs+json", **headers},
timeout=HTTP_TIMEOUT_S)
batch.raise_for_status()
action = batch.json()["objects"][0]["actions"]["download"]
return action["href"], action.get("header", {})
def fetch_index(base_url: str, session: requests.Session) -> dict:
response = session.get(f"{base_url}/index.json", timeout=HTTP_TIMEOUT_S, auth=request_auth())
index_url = f"{base_url}/index.json"
headers = request_headers(index_url)
# requests' auth= rewrites the Authorization header, so only fall back to it when the
# closed-source bundle gave us nothing.
response = session.get(index_url, timeout=HTTP_TIMEOUT_S, headers=headers,
auth=None if headers else request_auth())
response.raise_for_status()
index = response.json()
regions = index.get("regions")
@@ -164,7 +276,7 @@ class TileBundleDownloader:
ok = self._download_file(
selector, base_url, entry["path"], int(entry.get("bytes", 0)),
str(entry.get("sha256", "")).strip().lower(), night_path,
progress_offset, progress_total,
progress_offset, progress_total, int(entry.get("parts", 1)), entry.get("objects"),
)
if not ok:
return False
@@ -174,6 +286,7 @@ class TileBundleDownloader:
str(entry.get("day_sha256", "")).strip().lower(),
night_path.with_name("offline_day.mbtiles"),
progress_offset + int(entry.get("bytes", 0)), progress_total,
int(entry.get("day_parts", 1)), entry.get("day_objects"),
)
if not day_ok:
cloudlog.warning(f"iq_maps: day-style bundle failed for {selector}; night set installed")
@@ -183,8 +296,16 @@ class TileBundleDownloader:
def _download_file(self, selector: str, base_url: str, remote_path: str, expected_bytes: int,
expected_sha: str, final_path: Path,
progress_offset: int, progress_total: int) -> bool:
url = f"{base_url}/{remote_path.lstrip('/')}"
progress_offset: int, progress_total: int, parts: int = 1,
objects: list | None = None) -> bool:
# Bundles are published as <name>.pNN because Cloudflare caps proxied bodies at ~100MB.
# They stream back-to-back into ONE .part file: concatenating afterwards would need
# double the free space, which devices do not have.
base = f"{base_url}/{remote_path.lstrip('/')}"
if objects:
urls = [None] * len(objects) # resolved per-attempt from the oid
else:
urls = [base] if parts <= 1 else [f"{base}.p{i:02d}" for i in range(parts)]
part_path = final_path.with_name(final_path.name + ".part")
part_path.parent.mkdir(parents=True, exist_ok=True)
@@ -207,28 +328,45 @@ class TileBundleDownloader:
digest = hashlib.sha256()
resume_from = 0
headers = {"Range": f"bytes={resume_from}-"} if resume_from else {}
auth = request_auth()
response = self.session.get(url, headers=headers, stream=True, timeout=HTTP_TIMEOUT_S, auth=auth)
if resume_from and response.status_code != 206:
digest = hashlib.sha256()
resume_from = 0
part_path.unlink(missing_ok=True)
if response.status_code == 416:
response = self.session.get(url, stream=True, timeout=HTTP_TIMEOUT_S, auth=auth)
response.raise_for_status()
# every part but the last is exactly PART_BYTES, so a byte offset maps to a part index
first_part = resume_from // PART_BYTES if len(urls) > 1 else 0
skip_in_part = resume_from - first_part * PART_BYTES if len(urls) > 1 else resume_from
downloaded = resume_from
mode = "ab" if resume_from else "wb"
with open(part_path, mode) as f:
for chunk in response.iter_content(chunk_size=CHUNK_BYTES):
if self._should_abort():
cloudlog.warning(f"iq_maps: tile bundle download cancelled for {selector}")
return False
f.write(chunk)
digest.update(chunk)
downloaded += len(chunk)
self._publish_progress(selector, progress_offset + downloaded, progress_total, active=True)
for index in range(first_part, len(urls)):
if objects:
url_headers = request_headers(base_url)
auth = None if url_headers else request_auth()
object_url, object_headers = _resolve_oid_url(
self.session, base_url, objects[index]["oid"], int(objects[index]["size"]),
url_headers)
else:
url = urls[index]
url_headers = request_headers(url)
auth = None if url_headers else request_auth()
# Re-resolve per part: a pre-signed LFS object URL can expire mid-download.
object_url, object_headers = _resolve_object_url(self.session, url, url_headers)
headers = dict(object_headers)
offset = skip_in_part if index == first_part else 0
if offset:
headers["Range"] = f"bytes={offset}-"
response = self.session.get(object_url, headers=headers, stream=True,
timeout=HTTP_TIMEOUT_S, auth=auth)
if offset and response.status_code != 206:
# server ignored the range: restart this whole file cleanly
f.close()
part_path.unlink(missing_ok=True)
raise requests.RequestException(f"range not honoured for part {index}")
response.raise_for_status()
for chunk in response.iter_content(chunk_size=CHUNK_BYTES):
if self._should_abort():
cloudlog.warning(f"iq_maps: tile bundle download cancelled for {selector}")
return False
f.write(chunk)
digest.update(chunk)
downloaded += len(chunk)
self._publish_progress(selector, progress_offset + downloaded, progress_total, active=True)
break
except requests.RequestException as exc:
last_error = exc

View File

@@ -48,6 +48,7 @@ CTRL_FLAG_MISSING_INPUTS = 1 << 0
CTRL_FLAG_RK_OVERRUN = 1 << 1
SMOOTH_STEER_W0 = 46.0
SMOOTH_STEER_ZETA = 1.0
SMOOTH_STEER_HOLD_FRAMES = 50
LAT_SMOOTH_SECONDS = 0.0
@@ -100,6 +101,7 @@ class Controls(IQControlsLayer):
self.VM = VehicleModel(self.CP)
self.smooth_steer = PT2Filter(SMOOTH_STEER_W0, SMOOTH_STEER_ZETA, DT_CTRL)
self.smooth_steer_inactive_frames = SMOOTH_STEER_HOLD_FRAMES
self.is_curvature_car = self.CP.steerControlType == car.CarParams.SteerControlType.curvatureDEPRECATED
if self.is_curvature_car and self.params.get("EnableSmoothSteer") is None:
self.params.put_bool("EnableSmoothSteer", True)
@@ -235,7 +237,8 @@ class Controls(IQControlsLayer):
else:
new_desired_curvature = model_v2.action.desiredCurvature
if self.is_curvature_car and self.enable_smooth_steer and CC.latActive:
self.smooth_steer_inactive_frames = 0 if CC.latActive else self.smooth_steer_inactive_frames + 1
if self.is_curvature_car and self.enable_smooth_steer and self.smooth_steer_inactive_frames < SMOOTH_STEER_HOLD_FRAMES:
new_desired_curvature = self.smooth_steer.update(new_desired_curvature)
else:
self.smooth_steer.reset(new_desired_curvature)

View File

@@ -13,7 +13,8 @@ def dmonitoringd_thread():
sm = messaging.SubMaster(['driverStateV2', 'extrinsicsCalibration', 'carState', 'selfdriveState', 'modelV2',
'carControl'], poll='driverStateV2')
DM = DriverMonitoring(rhd_saved=params.get_bool("IsRhdDetected"), always_on=params.get_bool("AlwaysOnDM"))
DM = DriverMonitoring(rhd_saved=params.get_bool("IsRhdDetected"), always_on=params.get_bool("AlwaysOnDM"),
force_rhd=params.get_bool("ForceRHDForBSM"))
demo_mode=False
# 20Hz <- dmonitoringmodeld
@@ -36,10 +37,11 @@ def dmonitoringd_thread():
# load live always-on toggle
if sm['driverStateV2'].frameId % 40 == 1:
DM.always_on = params.get_bool("AlwaysOnDM")
DM.force_rhd = params.get_bool("ForceRHDForBSM")
demo_mode = params.get_bool("IsDriverViewEnabled")
# save rhd virtual toggle every 5 mins
if (sm['driverStateV2'].frameId % 6000 == 0 and not demo_mode and
if (sm['driverStateV2'].frameId % 6000 == 0 and not demo_mode and not DM.force_rhd and
DM.wheelpos.prob_offseter.filtered_stat.n > DM.settings._WHEELPOS_FILTER_MIN_COUNT and
DM.wheel_on_right == (DM.wheelpos.prob_offseter.filtered_stat.M > DM.settings._WHEELPOS_THRESHOLD)):
params.put_bool_nonblocking("IsRhdDetected", DM.wheel_on_right)

View File

@@ -145,7 +145,7 @@ def face_orientation_from_net(angles_desc, pos_desc, rpy_calib):
class DriverMonitoring:
def __init__(self, rhd_saved=False, settings=None, always_on=False):
def __init__(self, rhd_saved=False, settings=None, always_on=False, force_rhd=False):
# init policy settings
self.settings = settings if settings is not None else DRIVER_MONITOR_SETTINGS(device_type=HARDWARE.get_device_type())
@@ -158,6 +158,7 @@ class DriverMonitoring:
self.blink = DriverBlink()
self.always_on = always_on
self.force_rhd = force_rhd
self.distracted_types = []
self.driver_distracted = False
self.driver_distraction_filter = FirstOrderFilter(0., self.settings._DISTRACTED_FILTER_TS, self.settings._DT_DMON)
@@ -268,18 +269,20 @@ class DriverMonitoring:
def _update_states(self, driver_state, cal_rpy, car_speed, op_engaged, standstill, demo_mode=False):
rhd_pred = driver_state.wheelOnRightProb
# calibrates only when there's movement and either face detected
if car_speed > self.settings._WHEELPOS_CALIB_MIN_SPEED and (driver_state.leftDriverData.faceProb > self.settings._FACE_THRESHOLD or
if not self.force_rhd and car_speed > self.settings._WHEELPOS_CALIB_MIN_SPEED and (driver_state.leftDriverData.faceProb > self.settings._FACE_THRESHOLD or
driver_state.rightDriverData.faceProb > self.settings._FACE_THRESHOLD):
self.wheelpos.prob_offseter.push_and_update(rhd_pred)
self.wheelpos.prob_calibrated = self.wheelpos.prob_offseter.filtered_stat.n > self.settings._WHEELPOS_FILTER_MIN_COUNT
if self.wheelpos.prob_calibrated or demo_mode:
if self.force_rhd:
self.wheel_on_right = True
elif self.wheelpos.prob_calibrated or demo_mode:
self.wheel_on_right = self.wheelpos.prob_offseter.filtered_stat.M > self.settings._WHEELPOS_THRESHOLD
else:
self.wheel_on_right = self.wheel_on_right_default # use default/saved if calibration is unfinished
# make sure no switching when engaged
if op_engaged and self.wheel_on_right_last is not None and self.wheel_on_right_last != self.wheel_on_right and not demo_mode:
if not self.force_rhd and op_engaged and self.wheel_on_right_last is not None and self.wheel_on_right_last != self.wheel_on_right and not demo_mode:
self.wheel_on_right = self.wheel_on_right_last
driver_data = driver_state.rightDriverData if self.wheel_on_right else driver_state.leftDriverData
if not all(len(x) > 0 for x in (driver_data.faceOrientation, driver_data.facePosition,

View File

@@ -247,6 +247,22 @@ class TestMonitoring:
dm._update_states(ds, [0., 0., 0.], 20.0, True, False)
assert dm.wheel_on_right
def test_state_update_forces_rhd(self):
dm = DriverMonitoring(force_rhd=True)
dm.wheel_on_right_last = False
dm.wheelpos.prob_offseter.filtered_stat.M = 0.0
dm.wheelpos.prob_offseter.filtered_stat.n = dm.settings._WHEELPOS_FILTER_MIN_COUNT + 1
ds = log.DriverStateV2.new_message()
ds.wheelOnRightProb = 0.0
set_driver_data(ds.rightDriverData)
dm._update_states(ds, [0., 0., 0.], 20.0, True, False)
assert dm.wheel_on_right
assert dm.face_detected
assert dm.wheelpos.prob_offseter.filtered_stat.n == dm.settings._WHEELPOS_FILTER_MIN_COUNT + 1
assert dm.get_state_packet().driverMonitoringState.isRHD
def test_state_update_rejects_incomplete_driver_data(self):
dm = DriverMonitoring()
dm._update_states(log.DriverStateV2.new_message(), [0., 0., 0.], 0.0, False, False)

View File

@@ -93,6 +93,33 @@ class EngagedConfirmationButton(BigButton):
self.set_click_callback(lambda: _engaged_confirmation_click(callback, action_text, icon, exit_on_confirm=exit_on_confirm, red=red))
class ForceOffroadButton(BigButton):
def __init__(self):
self._offroad_icon = gui_app.texture("icons/iq/square-parking.png", 64, 64)
super().__init__(tr("force\noffroad"), "", self._offroad_icon)
self.set_press_effect_enabled(False)
self._label.set_font_size(40)
self._label.set_line_height(0.95)
self.set_click_callback(self._on_click)
self._sync_from_params()
def _forced(self) -> bool:
return ui_state.params.get_bool("IQAlwaysOffroad")
def _on_click(self):
forced = self._forced()
action = tr("disable force offroad") if forced else tr("force offroad")
_engaged_confirmation_click(lambda: ui_state.params.put_bool("IQAlwaysOffroad", not forced),
action, self._offroad_icon, exit_on_confirm=False)
def _sync_from_params(self):
self.set_text(tr("disable\nforce offroad") if self._forced() else tr("force\noffroad"))
def _update_state(self):
super()._update_state()
self._sync_from_params()
class DeviceInfoLayoutMici(Widget):
def __init__(self):
super().__init__()
@@ -226,6 +253,7 @@ class DeviceLayoutMici(NavScroller):
terms_btn,
regulatory_btn,
reset_calibration_btn,
ForceOffroadButton(),
reboot_btn,
self._power_off_btn,
])

View File

@@ -1830,6 +1830,31 @@ msgstr ""
msgid "power off"
msgstr ""
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "disable force offroad"
msgstr ""
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "force offroad"
msgstr ""
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"disable\n"
"force offroad"
msgstr ""
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:99
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"force\n"
"offroad"
msgstr ""
#: openpilot/selfdrive/ui/mici/layouts/onboarding.py:100
#, python-brace-format
msgid ""

View File

@@ -3386,6 +3386,20 @@ msgstr "الجهاز"
msgid "device ID"
msgstr "معرّف الجهاز"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"disable\n"
"force offroad"
msgstr ""
"إلغاء\n"
"فرض التوقف"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "disable force offroad"
msgstr "إلغاء فرض وضع التوقف"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:56
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:190
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:199
@@ -3543,11 +3557,26 @@ msgstr "لـ \"{}\""
msgid "for private branch updates"
msgstr "لتحديثات الفروع الخاصة"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:99
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"force\n"
"offroad"
msgstr ""
"فرض\n"
"وضع التوقف"
#: openpilot/selfdrive/ui/mici/layouts/settings/display.py:28
#, python-brace-format
msgid "force mici UI"
msgstr "فرض واجهة mici"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "force offroad"
msgstr "فرض وضع التوقف"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/wifi_ui.py:247
#, python-brace-format
msgid "forgetting..."

View File

@@ -3453,6 +3453,20 @@ msgstr "gerät"
msgid "device ID"
msgstr "geräte-ID"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"disable\n"
"force offroad"
msgstr ""
"parkmodus\n"
"freigeben"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "disable force offroad"
msgstr "parkmodus freigeben"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:56
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:190
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:199
@@ -3610,11 +3624,26 @@ msgstr "für „{}“"
msgid "for private branch updates"
msgstr "für Updates aus privaten Branches"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:99
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"force\n"
"offroad"
msgstr ""
"parkmodus\n"
"erzwingen"
#: openpilot/selfdrive/ui/mici/layouts/settings/display.py:28
#, python-brace-format
msgid "force mici UI"
msgstr "mici-oberfläche erzwingen"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "force offroad"
msgstr "parkmodus erzwingen"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/wifi_ui.py:247
#, python-brace-format
msgid "forgetting..."

View File

@@ -3411,6 +3411,20 @@ msgstr "device"
msgid "device ID"
msgstr "device ID"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"disable\n"
"force offroad"
msgstr ""
"disable\n"
"force offroad"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "disable force offroad"
msgstr "disable force offroad"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:56
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:190
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:199
@@ -3568,11 +3582,26 @@ msgstr "for \"{}\""
msgid "for private branch updates"
msgstr "for private branch updates"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:99
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"force\n"
"offroad"
msgstr ""
"force\n"
"offroad"
#: openpilot/selfdrive/ui/mici/layouts/settings/display.py:28
#, python-brace-format
msgid "force mici UI"
msgstr "force mici UI"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "force offroad"
msgstr "force offroad"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/wifi_ui.py:247
#, python-brace-format
msgid "forgetting..."

View File

@@ -3458,6 +3458,20 @@ msgstr "dispositivo"
msgid "device ID"
msgstr "ID del dispositivo"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"disable\n"
"force offroad"
msgstr ""
"salir de\n"
"aparcado"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "disable force offroad"
msgstr "desactivar aparcado forzado"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:56
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:190
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:199
@@ -3615,11 +3629,26 @@ msgstr "para «{}»"
msgid "for private branch updates"
msgstr "para actualizaciones de ramas privadas"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:99
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"force\n"
"offroad"
msgstr ""
"forzar\n"
"aparcado"
#: openpilot/selfdrive/ui/mici/layouts/settings/display.py:28
#, python-brace-format
msgid "force mici UI"
msgstr "forzar interfaz mici"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "force offroad"
msgstr "forzar aparcado"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/wifi_ui.py:247
#, python-brace-format
msgid "forgetting..."

View File

@@ -3475,6 +3475,20 @@ msgstr "appareil"
msgid "device ID"
msgstr "ID appareil"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"disable\n"
"force offroad"
msgstr ""
"quitter\n"
"hors route"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "disable force offroad"
msgstr "désactiver hors route forcé"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:56
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:190
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:199
@@ -3632,11 +3646,26 @@ msgstr "pour \"{}\""
msgid "for private branch updates"
msgstr "pour les mises à jour de branches privées"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:99
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"force\n"
"offroad"
msgstr ""
"forcer\n"
"hors route"
#: openpilot/selfdrive/ui/mici/layouts/settings/display.py:28
#, python-brace-format
msgid "force mici UI"
msgstr "forcer l'interface mici"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "force offroad"
msgstr "forcer hors route"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/wifi_ui.py:247
#, python-brace-format
msgid "forgetting..."

View File

@@ -3281,6 +3281,20 @@ msgstr "デバイス"
msgid "device ID"
msgstr "デバイスID"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"disable\n"
"force offroad"
msgstr ""
"強制オフロード\n"
"解除"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "disable force offroad"
msgstr "強制オフロードを解除"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:56
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:190
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:199
@@ -3438,11 +3452,26 @@ msgstr "「{}」向け"
msgid "for private branch updates"
msgstr "プライベートブランチの更新用"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:99
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"force\n"
"offroad"
msgstr ""
"強制\n"
"オフロード"
#: openpilot/selfdrive/ui/mici/layouts/settings/display.py:28
#, python-brace-format
msgid "force mici UI"
msgstr "mici UIを強制"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "force offroad"
msgstr "強制オフロード"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/wifi_ui.py:247
#, python-brace-format
msgid "forgetting..."

View File

@@ -3303,6 +3303,20 @@ msgstr "기기"
msgid "device ID"
msgstr "기기 ID"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"disable\n"
"force offroad"
msgstr ""
"강제 오프로드\n"
"해제"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "disable force offroad"
msgstr "강제 오프로드 해제"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:56
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:190
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:199
@@ -3460,11 +3474,26 @@ msgstr "\"{}\"용"
msgid "for private branch updates"
msgstr "비공개 브랜치 업데이트용"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:99
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"force\n"
"offroad"
msgstr ""
"강제\n"
"오프로드"
#: openpilot/selfdrive/ui/mici/layouts/settings/display.py:28
#, python-brace-format
msgid "force mici UI"
msgstr "mici UI 강제"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "force offroad"
msgstr "강제 오프로드"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/wifi_ui.py:247
#, python-brace-format
msgid "forgetting..."

View File

@@ -3450,6 +3450,20 @@ msgstr "urządzenie"
msgid "device ID"
msgstr "ID urządzenia"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"disable\n"
"force offroad"
msgstr ""
"wyłącz\n"
"wymuszenie"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "disable force offroad"
msgstr "wyłącz wymuszony postój"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:56
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:190
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:199
@@ -3607,11 +3621,26 @@ msgstr "dla „{}”"
msgid "for private branch updates"
msgstr "do aktualizacji z prywatnych gałęzi"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:99
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"force\n"
"offroad"
msgstr ""
"wymuś\n"
"postój"
#: openpilot/selfdrive/ui/mici/layouts/settings/display.py:28
#, python-brace-format
msgid "force mici UI"
msgstr "wymuś interfejs mici"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "force offroad"
msgstr "wymuś postój"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/wifi_ui.py:247
#, python-brace-format
msgid "forgetting..."

View File

@@ -3452,6 +3452,20 @@ msgstr "dispositivo"
msgid "device ID"
msgstr "ID do dispositivo"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"disable\n"
"force offroad"
msgstr ""
"sair de\n"
"estacionado"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "disable force offroad"
msgstr "desativar estacionado forçado"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:56
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:190
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:199
@@ -3609,11 +3623,26 @@ msgstr "para \"{}\""
msgid "for private branch updates"
msgstr "para atualizações de branches privadas"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:99
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"force\n"
"offroad"
msgstr ""
"forçar\n"
"estacionado"
#: openpilot/selfdrive/ui/mici/layouts/settings/display.py:28
#, python-brace-format
msgid "force mici UI"
msgstr "forçar interface mici"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "force offroad"
msgstr "forçar estacionado"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/wifi_ui.py:247
#, python-brace-format
msgid "forgetting..."

View File

@@ -3392,6 +3392,20 @@ msgstr "อุปกรณ์"
msgid "device ID"
msgstr "รหัสอุปกรณ์"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"disable\n"
"force offroad"
msgstr ""
"ปิดโหมด\n"
"จอดบังคับ"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "disable force offroad"
msgstr "ปิดโหมดจอดแบบบังคับ"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:56
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:190
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:199
@@ -3549,11 +3563,26 @@ msgstr "สำหรับ \"{}\""
msgid "for private branch updates"
msgstr "สำหรับการอัปเดตจากสาขาส่วนตัว"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:99
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"force\n"
"offroad"
msgstr ""
"บังคับ\n"
"โหมดจอด"
#: openpilot/selfdrive/ui/mici/layouts/settings/display.py:28
#, python-brace-format
msgid "force mici UI"
msgstr "บังคับใช้อินเทอร์เฟซ mici"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "force offroad"
msgstr "บังคับโหมดจอด"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/wifi_ui.py:247
#, python-brace-format
msgid "forgetting..."

View File

@@ -3427,6 +3427,20 @@ msgstr "cihaz"
msgid "device ID"
msgstr "cihaz kimliği"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"disable\n"
"force offroad"
msgstr ""
"zorlamayı\n"
"kapat"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "disable force offroad"
msgstr "park zorlamasını kapat"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:56
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:190
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:199
@@ -3584,11 +3598,26 @@ msgstr "\"{}\" için"
msgid "for private branch updates"
msgstr "özel dal güncellemeleri için"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:99
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"force\n"
"offroad"
msgstr ""
"park modunu\n"
"zorla"
#: openpilot/selfdrive/ui/mici/layouts/settings/display.py:28
#, python-brace-format
msgid "force mici UI"
msgstr "mici arayüzünü zorla"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "force offroad"
msgstr "park modunu zorla"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/wifi_ui.py:247
#, python-brace-format
msgid "forgetting..."

View File

@@ -3436,6 +3436,20 @@ msgstr "пристрій"
msgid "device ID"
msgstr "ID пристрою"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"disable\n"
"force offroad"
msgstr ""
"вимкнути\n"
"примус"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "disable force offroad"
msgstr "вимкнути примусовий офроуд"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:56
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:190
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:199
@@ -3593,11 +3607,26 @@ msgstr "для \"{}\""
msgid "for private branch updates"
msgstr "для оновлень із приватних гілок"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:99
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"force\n"
"offroad"
msgstr ""
"офроуд\n"
"примусово"
#: openpilot/selfdrive/ui/mici/layouts/settings/display.py:28
#, python-brace-format
msgid "force mici UI"
msgstr "примусовий інтерфейс mici"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "force offroad"
msgstr "примусовий офроуд"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/wifi_ui.py:247
#, python-brace-format
msgid "forgetting..."

View File

@@ -3260,6 +3260,20 @@ msgstr "设备"
msgid "device ID"
msgstr "设备 ID"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"disable\n"
"force offroad"
msgstr ""
"关闭\n"
"强制驻车"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "disable force offroad"
msgstr "关闭强制驻车"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:56
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:190
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:199
@@ -3417,11 +3431,26 @@ msgstr "用于“{}”"
msgid "for private branch updates"
msgstr "用于私有分支更新"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:99
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"force\n"
"offroad"
msgstr ""
"强制\n"
"驻车"
#: openpilot/selfdrive/ui/mici/layouts/settings/display.py:28
#, python-brace-format
msgid "force mici UI"
msgstr "强制使用 mici 界面"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "force offroad"
msgstr "强制驻车"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/wifi_ui.py:247
#, python-brace-format
msgid "forgetting..."

View File

@@ -3262,6 +3262,20 @@ msgstr "裝置"
msgid "device ID"
msgstr "裝置 ID"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"disable\n"
"force offroad"
msgstr ""
"關閉\n"
"強制駐車"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "disable force offroad"
msgstr "關閉強制駐車"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:56
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:190
#: openpilot/selfdrive/ui/mici/layouts/settings/network/network_layout.py:199
@@ -3419,11 +3433,26 @@ msgstr "適用於「{}」"
msgid "for private branch updates"
msgstr "用於私有分支更新"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:99
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:116
#, python-brace-format
msgid ""
"force\n"
"offroad"
msgstr ""
"強制\n"
"駐車"
#: openpilot/selfdrive/ui/mici/layouts/settings/display.py:28
#, python-brace-format
msgid "force mici UI"
msgstr "強制使用 mici 介面"
#: openpilot/selfdrive/ui/mici/layouts/settings/device.py:111
#, python-brace-format
msgid "force offroad"
msgstr "強制駐車"
#: openpilot/selfdrive/ui/mici/layouts/settings/network/wifi_ui.py:247
#, python-brace-format
msgid "forgetting..."

View File

@@ -13,7 +13,7 @@ from iqpilot.selfdrive.ui.ui_state import ui_state
_FPS_OVERRIDE = os.getenv("FPS")
UI_OFFROAD_FPS = int(os.getenv("UI_OFFROAD_FPS", _FPS_OVERRIDE or "60"))
UI_ONROAD_FPS = int(os.getenv("UI_ONROAD_FPS", _FPS_OVERRIDE or "20"))
UI_ONROAD_FPS = int(os.getenv("UI_ONROAD_FPS", _FPS_OVERRIDE or "60"))
def main():

View File

@@ -83,6 +83,7 @@ class WebRTCBaseStream(abc.ABC):
self._audio_track_state: List[Tuple[Track, Any, RtpPacketizationConfig]] = []
self._receiver_reports: Dict[str, RtcpReceiverReport] = {}
self._receiver_report_tracks: Dict[str, Tuple[Track, int]] = {}
self._negotiated_tracks: Dict[str, Track] = {}
self.incoming_media_ready_event = asyncio.Event()
self.messaging_channel_ready_event = asyncio.Event()
@@ -206,7 +207,11 @@ class WebRTCBaseStream(abc.ABC):
def _add_producer_tracks(self, remote_sdp: Optional[str] = None):
for track in self.outgoing_video_tracks:
media, ssrc, payload_type, cname = self._make_video_media(track, remote_sdp or "")
rtc_track = self.peer_connection.add_track(media)
rtc_track = self._negotiated_tracks.get(media.mid())
if rtc_track is not None:
rtc_track.set_description(media)
else:
rtc_track = self.peer_connection.add_track(media)
rtp_config = RtpPacketizationConfig(ssrc, cname, payload_type, H264RtpPacketizer.CLOCK_RATE)
rtp_config.start_timestamp = random.randint(0, 0xFFFFFFFF)
@@ -232,6 +237,8 @@ class WebRTCBaseStream(abc.ABC):
# same MID, which leaves libdatachannel stuck in signalling/ICE negotiation.
rtc_track = self.incoming_audio_tracks[0]
negotiated_media = rtc_track.description()
negotiated_media.clear_ssrcs()
negotiated_media.remove_attribute("msid")
negotiated_media.add_ssrc(ssrc, cname, "audio", "audio")
rtc_track.set_description(negotiated_media)
else:
@@ -276,6 +283,7 @@ class WebRTCBaseStream(abc.ABC):
def _on_incoming_track(self, track: Track):
self._log_debug("got track: %s", track.mid())
self._negotiated_tracks[track.mid()] = track
media_type = track.description().type()
if media_type == "audio":
if self.expected_incoming_audio:
@@ -478,6 +486,7 @@ class WebRTCBaseStream(abc.ABC):
self._audio_track_state.clear()
self._receiver_reports.clear()
self._receiver_report_tracks.clear()
self._negotiated_tracks.clear()
@abc.abstractmethod
async def start(self) -> RTCSessionDescription:

View File

@@ -19,8 +19,17 @@ async def test_native_video_audio_and_data_channel():
async def connect(offer):
nonlocal answer_session
answer_session = StreamSession(offer.sdp, offer.video, [], [], [], debug_mode=True)
browser_offer = offer.sdp.replace("profile-level-id=42e01f", "profile-level-id=640c1f", 1)
audio_offset = browser_offer.index("m=audio")
browser_offer = browser_offer[:audio_offset] + browser_offer[audio_offset:].replace(
"a=recvonly",
"a=sendrecv\r\na=msid:ios-microphone ios-audio-track\r\na=ssrc:123456 cname:ios-audio\r\na=ssrc:123456 msid:ios-microphone ios-audio-track",
1,
)
answer_session = StreamSession(browser_offer, offer.video, [], [], [], debug_mode=True)
answer = await answer_session.get_answer()
assert not any(line.startswith("m=video 0 ") for line in answer.sdp.splitlines())
assert answer_session.stream._track_state[0][0] is answer_session.stream._negotiated_tracks["road"]
answer_session.start()
return RTCSessionDescription(answer.sdp, answer.type)
@@ -56,9 +65,16 @@ async def test_native_duplex_audio_negotiation():
async def connect(offer):
nonlocal answer_session
sendrecv_offer = offer.sdp.replace("a=recvonly", "a=sendrecv", 1)
sendrecv_offer = offer.sdp.replace(
"a=recvonly",
"a=sendrecv\r\na=msid:ios-microphone ios-audio-track\r\na=ssrc:123456 cname:ios-audio\r\na=ssrc:123456 msid:ios-microphone ios-audio-track",
1,
)
answer_session = StreamSession(sendrecv_offer, offer.video, [], [], [], debug_mode=True)
answer = await answer_session.get_answer()
assert "ios-microphone" not in answer.sdp
assert "ios-audio-track" not in answer.sdp
assert answer.sdp.count("a=msid:audio audio") == 1
answer_session.start()
return RTCSessionDescription(answer.sdp, answer.type)