diff --git a/artifacts/iqpilot_hephaestusd_private/manifest.json b/artifacts/iqpilot_hephaestusd_private/manifest.json
index d130454..8893405 100644
--- a/artifacts/iqpilot_hephaestusd_private/manifest.json
+++ b/artifacts/iqpilot_hephaestusd_private/manifest.json
@@ -16,27 +16,27 @@
},
"python/iqpilot_private/konn3kt/backups/archive_codec.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
- "sha256": "3153fede975ec92281e8b33acf9dfd6305a24696f4b877df651f3742a67f368e",
+ "sha256": "8f9c7215f23878cf3ca3a07f013850f7e889a9e10deb4c1ec8bdabae488723e6",
"size": 135536
},
"python/iqpilot_private/konn3kt/backups/backup_keys.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
- "sha256": "37d32ea795dddce22b47ad2bdec838d360894b325719f48bab6d1be8427d3026",
+ "sha256": "c0d031c33712c71abcad3f9e10aa8e987ee801e20407a98344295e008657aab9",
"size": 67664
},
"python/iqpilot_private/konn3kt/backups/backup_orchestrator.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
- "sha256": "c71f7680e32cee7117409c399e915ad3740120c76a3e74af843d7f04644f0d08",
+ "sha256": "e049af92c953da53db2728f23484d8d691c9834d4130e3b6caa19c3ae69ce86d",
"size": 204624
},
"python/iqpilot_private/konn3kt/backups/cbc_vault.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
- "sha256": "71d52c82a254f0a66bc78dd947623747131a8883579f73fa61915d17bd2f4787",
+ "sha256": "a73a6a7ba5ac0a87d114db02e895921f0c452e9a8c6bd622116d94c347216ef1",
"size": 69752
},
"python/iqpilot_private/konn3kt/backups/imahelper.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
- "sha256": "1163d7ffafaa9179812c65362c3b99d47bd880747731009bf7d81cdef872f2d0",
+ "sha256": "692bde7a464bcef05c8b684224cc8fd6a6c05d226775ed3e81b6a02c748e11c5",
"size": 203072
},
"python/iqpilot_private/konn3kt/hephaestus/__init__.py": {
@@ -46,67 +46,67 @@
},
"python/iqpilot_private/konn3kt/hephaestus/_vendor/localapi_runtime.zip": {
"mode": 420,
- "sha256": "a6f2e86d5f44caabab7070263d9cc17c9222365e8f1ef04a1a6d27db0d2c2e88",
+ "sha256": "832067fea89470fc6224abc8b49c2624e0278e0027ea4e0bb93f939e03938230",
"size": 2100238
},
"python/iqpilot_private/konn3kt/hephaestus/ble_auth.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
- "sha256": "fbe4f442f7914a0238b7e78bfebe7b99f19e517122bfa5b2467c46ed73df1f05",
+ "sha256": "92b5f941d9198bdd12915996216014d4bbc9b13c1b2435c20b9a2811661b23e3",
"size": 268064
},
"python/iqpilot_private/konn3kt/hephaestus/ble_gatt.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
- "sha256": "3c4a6df8c4458fbefefe8761aaf99732b5f62bcb4bb4a5b1068b5f42b0fc9da7",
+ "sha256": "4a71f1c7f88fdbd51707812370e733d30b22c0c46a2f22ce32d1757debc14cff",
"size": 340584
},
"python/iqpilot_private/konn3kt/hephaestus/ble_rpc_dispatch.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
- "sha256": "79a9ec735831f904ae635d6628695fe7a985430a0ee81e7d7e58842f7588d61e",
+ "sha256": "25d6899e8ebb8c0c5d813d522033d115502d9b622882c0e59f276406702d9e57",
"size": 68048
},
"python/iqpilot_private/konn3kt/hephaestus/ble_transportd.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
- "sha256": "a93df625aca20374031343cbbbef4f8c2a819d69680205f9ac5c92a3841c24d9",
+ "sha256": "abee9f335c9ddabaa85f341cb33aaf5eebc433b2397b71c921667329728808bc",
"size": 335728
},
"python/iqpilot_private/konn3kt/hephaestus/bt_gamepad.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
- "sha256": "116dbd9cd287c4bb55672233b66601d2af9e023be03b78d6aec39d8c2a4eef04",
+ "sha256": "b5900c92a037f7ac88199b515f91692c0f86c45981ca3c929b6cbeb6ad6002a0",
"size": 271680
},
"python/iqpilot_private/konn3kt/hephaestus/cloud_routes.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
- "sha256": "c9d3e1cfdd36e30b6546e43a9cf51c2608a08210ac97d818bbbf098b6cc0a50f",
+ "sha256": "d8ebf16a39d29f9932fd1277bd0d552b60a748b0bad6d5c6314cfe5e80859ce2",
"size": 134408
},
"python/iqpilot_private/konn3kt/hephaestus/hephaestusd.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
- "sha256": "b3f2772b58d09c27042e4e0f9147a6ff45bcd6d198e32a6993bc9ca411110e6a",
+ "sha256": "6f50c91b87b5e37033b2f7a9db22f01aba9bf5e31733b6e753a23c211ae71492",
"size": 3514416
},
"python/iqpilot_private/konn3kt/hephaestus/kwp2000.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
- "sha256": "d37822e6fc68f07b22145fb7aaac87795af585221dc148d4ef2477580509dda6",
+ "sha256": "63eb11f7251748dab6ad9ba7483ace77b0709f0a3f59492d5a9f2b50bfd9e1ad",
"size": 136448
},
"python/iqpilot_private/konn3kt/hephaestus/manage_hephaestusd.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
- "sha256": "8c3c93cce17f873983c70396fe194c705ae19bc180ec6c4658183777a6d3fa03",
+ "sha256": "88d2df85126983f2036badc3fac85ee25d79119c95bbe983030c6ea756da111b",
"size": 68136
},
"python/iqpilot_private/konn3kt/hephaestus/motd.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
- "sha256": "1ac1dcdc3983907a0e653b9769c1bf32e46ad5e4302b7993805a8e1f02958f47",
+ "sha256": "f0aa1d1e50f73a27fff17a40c16affafbfdd56239da484ac04315e55a7018e0e",
"size": 67840
},
"python/iqpilot_private/konn3kt/hephaestus/tp20.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
- "sha256": "f81235f79eb78c77a3811e3676b5c76c49e09ca20c9cf3c01e5aa4640ef3de6c",
+ "sha256": "5e4f675dbc70a3cd21156727f430fec31ecee99f28af3873fea89fb185dba39d",
"size": 135648
},
"python/iqpilot_private/konn3kt/hephaestus/vw_pq_flasher.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
- "sha256": "fd1683c047a47b54c17581e749d8448c664f4f84549e6129ff0c50f9e335f324",
+ "sha256": "6f9d47e0d6c4156335fcfd6562022dbfad2dd40c860fac20288be43823195443",
"size": 269568
},
"python/iqpilot_private/konn3kt/uploaderd/__init__.py": {
@@ -116,7 +116,7 @@
},
"python/iqpilot_private/konn3kt/uploaderd/iquploaderd.cpython-312-aarch64-linux-gnu.so": {
"mode": 493,
- "sha256": "515f4e9a3865c8c5b34926005471df7328d2061034d8d490ad6c6556e4754fad",
+ "sha256": "995b9bcfa8544066a4b71565e834bedc4c1c3dd6b54e14765ef2365d32ccfe05",
"size": 204184
},
"runtime": {
@@ -148,23 +148,23 @@
}
},
"signatures": {
- "python/iqpilot_private/konn3kt/backups/archive_codec.cpython-312-aarch64-linux-gnu.so": "szqc9yDkYsxkYPyEfqBdz1B/T8WcrjvKjja+ORcUqAXVr4kPz5MQu2oT5HyJJ02NnR2QQ+OcVWgIR85aUg/VBA==",
- "python/iqpilot_private/konn3kt/backups/backup_keys.cpython-312-aarch64-linux-gnu.so": "S+fnijAxAphfMnzAB/zXpi8tPX2GGZUecpPwhfdO1eNnzuFyqPiV6Q6q7vSr3dD86lG3BPTfJZCFRmGwc0rpBg==",
- "python/iqpilot_private/konn3kt/backups/backup_orchestrator.cpython-312-aarch64-linux-gnu.so": "4xbYBIqUjczGMGWoz2P2PCCh+NGrPOKnWGluwPStk+oJHzZlVBnpj389tSqzJJzOyAJo2hA1GYeuMkfG8ETcCQ==",
- "python/iqpilot_private/konn3kt/backups/cbc_vault.cpython-312-aarch64-linux-gnu.so": "VdS8oqeVMuNiLyrU9REZ4YV84XLSV8MyaKTTWDk20lYGJpQU4wBRLwla6Tq8WrwlaRgZmdX9H1msMwV0WVFHBQ==",
- "python/iqpilot_private/konn3kt/backups/imahelper.cpython-312-aarch64-linux-gnu.so": "btwzW4V9KItwXYbRVjA8oYfI1y0xhvNfFseIuxO5o4uVsZ2h3W5WWoeZ3m+h1GvjcT/Ucdhn6lC3XbJxxfWgDQ==",
- "python/iqpilot_private/konn3kt/hephaestus/ble_auth.cpython-312-aarch64-linux-gnu.so": "1andY86F9L840fIgJekSJQSvpRDZMr4JbNYZn40K/9dcs5F/dQ6s5IyiZwpS2+4W/hDCZiVqCz05f5o96+E+DQ==",
- "python/iqpilot_private/konn3kt/hephaestus/ble_gatt.cpython-312-aarch64-linux-gnu.so": "JcJPlG9hSIWbcR8038As7VDvYVJNBg6L9qMr0ElBtHSvewFqcJ5tK4/swIo3IJS4DZpLjCwtIMmu+DqGQsnGCg==",
- "python/iqpilot_private/konn3kt/hephaestus/ble_rpc_dispatch.cpython-312-aarch64-linux-gnu.so": "KuA+FLmbERkD5+C+Bl9G+GNGHPEbbc79onDNkUTMtZNr7YxTIx7Py71K0WQkP0qa5sgxr17/hF7kQszTBtzFAg==",
- "python/iqpilot_private/konn3kt/hephaestus/ble_transportd.cpython-312-aarch64-linux-gnu.so": "O2p0H5siPJtTC0x72el2IEyoFSa/N+wvL9/G+XMgurZI6DQqqQrs+igpYvFFI1U2UO6lJwhxZxb2RbKaIhT8Bw==",
- "python/iqpilot_private/konn3kt/hephaestus/bt_gamepad.cpython-312-aarch64-linux-gnu.so": "XVgvLfvS1KtjzGCYXLanTWE392+DBZGQxP41cTvUiyzf+MXUo9jRjV8xXVpVTmCjN6sqFhJccIcYdUh2cTp1BA==",
- "python/iqpilot_private/konn3kt/hephaestus/cloud_routes.cpython-312-aarch64-linux-gnu.so": "iAlR196MOtgXdBLyOUhk19M2PAT1HjBQRlbEmuLrtKFCeHQC124ewsjClYVq/Hy6N+ksqzhSMeAL2hU6NcfTCQ==",
- "python/iqpilot_private/konn3kt/hephaestus/hephaestusd.cpython-312-aarch64-linux-gnu.so": "ymo9xAJEpoER5GLSWNLsOSxnZZ+Rwe0GUVTsxLGX7/tuLUNMPq0Og/yQ8D5EpTgaPGV3wPUFLsLBiWv//OXZDA==",
- "python/iqpilot_private/konn3kt/hephaestus/kwp2000.cpython-312-aarch64-linux-gnu.so": "PUPoFMxOzzmgaIFa0aTaKZDN81v2qTLj6j4jZkXnGlHXKfGbVpBLBYq8ytujJvamGevvVa5cssEA3XbMLFq8CQ==",
- "python/iqpilot_private/konn3kt/hephaestus/manage_hephaestusd.cpython-312-aarch64-linux-gnu.so": "JGyDxUcUXvCd8lwNaLscpIo9vKTNRvtKd9roHI+kLa9OImJfk1XFAn7qY/LFEfqcpga0vRcucZLqa5T1YB/gDw==",
- "python/iqpilot_private/konn3kt/hephaestus/motd.cpython-312-aarch64-linux-gnu.so": "9Kb9lnsLYhTCC7ctxVYvwO2iODIW0Z6NJ7+R+6BvIBV3ejL4yc8YVxjde0skgdjN5SvqlvRO1uG/ZE6aqK3VCQ==",
- "python/iqpilot_private/konn3kt/hephaestus/tp20.cpython-312-aarch64-linux-gnu.so": "8u8bDBQ7SxYTWX+cEMeAH0DQ+hoZDfjYyOzU+sBzrtZylUVZyzlRjohciDDQXF2bpxnuNQUWb4GgE41Y60hlCg==",
- "python/iqpilot_private/konn3kt/hephaestus/vw_pq_flasher.cpython-312-aarch64-linux-gnu.so": "8PyCivu4UmKF+biAg5aTRFRf6pSM6jt65/n0lrXgo4Ftpk4mNd623b/K/jPf+6wjgC8Sbqp40wNFwel0RUifAg==",
- "python/iqpilot_private/konn3kt/uploaderd/iquploaderd.cpython-312-aarch64-linux-gnu.so": "GpPbShzcrAK4tP9pRg+SJh0WZ8Me0mxEVEL6ED7v/tK3Az3KTDf4jU5a3Bhg/Q/IrWxqNlBg/RPdOv2RYMBPDA=="
+ "python/iqpilot_private/konn3kt/backups/archive_codec.cpython-312-aarch64-linux-gnu.so": "UehTRkDLBq77ERDm+ZSjxDU3+5EpJUOIzs5zk7Fz8Aru6yQX9ytRexns4dGse8BlIveGuHpWq+L+GvjG0Hf4Bw==",
+ "python/iqpilot_private/konn3kt/backups/backup_keys.cpython-312-aarch64-linux-gnu.so": "uddHEDnsMjWbMeWotUzZES/3hyLuPmZM1ENCkcTxMYXzM0g0YfbyOJlzq2FuSL4Zg2Hl+PyM/nmnEYbi88NIBg==",
+ "python/iqpilot_private/konn3kt/backups/backup_orchestrator.cpython-312-aarch64-linux-gnu.so": "2gPFBBZeMfvlnGtQkP6JMI/8c6uanTylvVtZ+1cifaK/ixsGDyfw051gv28uorxjDvRHbgGab/q2n3QYZj8EBA==",
+ "python/iqpilot_private/konn3kt/backups/cbc_vault.cpython-312-aarch64-linux-gnu.so": "KwOoTQlcNJA//GwfMeS8e1yw9agzaJDa/oUXXhiEFyrdEgZurmLbV0slgxUR+hC/LLrrzqqsw1BjQcYuqVXdCw==",
+ "python/iqpilot_private/konn3kt/backups/imahelper.cpython-312-aarch64-linux-gnu.so": "BbNS1vTfoizdCnZE3j/2kbY84uXDcGk0WgQ+nmBtySNBBJgT/5HspuY/AOxHukgVyjh7vm7BCnBuJO6/Gm30AQ==",
+ "python/iqpilot_private/konn3kt/hephaestus/ble_auth.cpython-312-aarch64-linux-gnu.so": "HU6uqhzgAx6mA9ScihdhYvmknQ9kZbI2p4a/ViB4BLo1OTZnfhFecQQ3rnvXNLGOyfbacqooz+s+JRuSOqEmDw==",
+ "python/iqpilot_private/konn3kt/hephaestus/ble_gatt.cpython-312-aarch64-linux-gnu.so": "Nw/QTfb9gk1QgTWKvacfS4BlKZ3DuWJKf5ll/H4Hb8YEaXmYz1xU0klwcybjHPs4twA5qsYUnjmzL110llD+Cw==",
+ "python/iqpilot_private/konn3kt/hephaestus/ble_rpc_dispatch.cpython-312-aarch64-linux-gnu.so": "WE552SVLgy0vmwvrJv54kW4bDyjB9bKUhMnGa+OI/L7WZT/ReWm3H2NbT0TzWZEGbzFHKr4I01Zmi+MHJGVrAQ==",
+ "python/iqpilot_private/konn3kt/hephaestus/ble_transportd.cpython-312-aarch64-linux-gnu.so": "N9u9KO1e4Xc9su7MndJ6MfyDMY1eV89xbIy6Qo5F5eg0xqfl8QGyYcUU6btIOFdrpRdpWxXTukff9FbU0c+RBg==",
+ "python/iqpilot_private/konn3kt/hephaestus/bt_gamepad.cpython-312-aarch64-linux-gnu.so": "t9HmTDU8a0a3rhm9rxzbUaYalAmjASZRbgCku8rg6AxQJohJo3eMVmH7dy7A6vtFvhYvvD9Ywi9kKeUaPTvPCQ==",
+ "python/iqpilot_private/konn3kt/hephaestus/cloud_routes.cpython-312-aarch64-linux-gnu.so": "Oq2wyp4UTAQg/Q16pgCJ9+C/4zi4ljCOHJRcnYXhUk997Tq/5LuBHBstfxrq9ZLubF2ntLLw5UhePtehjLliDg==",
+ "python/iqpilot_private/konn3kt/hephaestus/hephaestusd.cpython-312-aarch64-linux-gnu.so": "n2X6vqTFDy3dGiTiI9kWfAYySl0srw30k5aDqN/YWTzZomQabwZ1ETmUC6TIG3Wag074XNEJgrZhiguN1wgeAg==",
+ "python/iqpilot_private/konn3kt/hephaestus/kwp2000.cpython-312-aarch64-linux-gnu.so": "ami2SR9/GUXkFRDB5hN/JrJO4rz2piQNtEYJFAsvssLmcqzVPHehRIy61gctjKr5kBLOfUGJjpNU3ceswOUWBg==",
+ "python/iqpilot_private/konn3kt/hephaestus/manage_hephaestusd.cpython-312-aarch64-linux-gnu.so": "wCeURfEwJlXuy7FYiJ3ZWUJZUp8ehKehKqWH/nNyo+GlSlC8YhAGNvQxwZ9FH0agOsSQVHMExnL4ofLvJOytAA==",
+ "python/iqpilot_private/konn3kt/hephaestus/motd.cpython-312-aarch64-linux-gnu.so": "+G2me3BkbbjwwtVfjGz/ePsXQwNde7Y9bLELSRk8tDxLdGHWkFCU9i8ba8vue7uqfMTnRq5opCDFdIXvY7CwDg==",
+ "python/iqpilot_private/konn3kt/hephaestus/tp20.cpython-312-aarch64-linux-gnu.so": "lh63nHd0YApA9e9+C8SnRd+DILlprzpzt2PR8S6x8VSMQAzAySS9xuJ8Jw76JMpIItzW030n5/wazi4i/gK+Aw==",
+ "python/iqpilot_private/konn3kt/hephaestus/vw_pq_flasher.cpython-312-aarch64-linux-gnu.so": "3fYQP73XdXlWREMsM+P7D9EUSAwrLuih17DqmbDfQDa0S0TKbXcWJgRMbeOHRUDMZ04sUDrli82OfAkz6vlyBQ==",
+ "python/iqpilot_private/konn3kt/uploaderd/iquploaderd.cpython-312-aarch64-linux-gnu.so": "UtM9t4Db3LX6RfiMkADMI7Skre5FtPvjPB2xNuJofd4fVtrLo7r4YYcSOmq7jo4+UviYp4N3CPiGGoOc6WHzAA=="
}
}
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/archive_codec.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/archive_codec.cpython-312-aarch64-linux-gnu.so
index bdbb6bb..16b05ce 100755
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/archive_codec.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/archive_codec.cpython-312-aarch64-linux-gnu.so differ
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/backup_keys.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/backup_keys.cpython-312-aarch64-linux-gnu.so
index 95f2d55..b2d2795 100755
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/backup_keys.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/backup_keys.cpython-312-aarch64-linux-gnu.so differ
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/backup_orchestrator.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/backup_orchestrator.cpython-312-aarch64-linux-gnu.so
index 77e2780..a1bd81e 100755
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/backup_orchestrator.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/backup_orchestrator.cpython-312-aarch64-linux-gnu.so differ
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/cbc_vault.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/cbc_vault.cpython-312-aarch64-linux-gnu.so
index c262e77..10c4e03 100755
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/cbc_vault.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/cbc_vault.cpython-312-aarch64-linux-gnu.so differ
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/imahelper.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/imahelper.cpython-312-aarch64-linux-gnu.so
index 3f7c40f..bcec6ab 100755
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/imahelper.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/backups/imahelper.cpython-312-aarch64-linux-gnu.so differ
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/_vendor/localapi_runtime.zip b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/_vendor/localapi_runtime.zip
index e61630f..0aa10c3 100644
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/_vendor/localapi_runtime.zip and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/_vendor/localapi_runtime.zip differ
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/ble_auth.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/ble_auth.cpython-312-aarch64-linux-gnu.so
index 09d843e..56b5782 100755
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/ble_auth.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/ble_auth.cpython-312-aarch64-linux-gnu.so differ
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/ble_gatt.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/ble_gatt.cpython-312-aarch64-linux-gnu.so
index bb4705a..01ed395 100755
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/ble_gatt.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/ble_gatt.cpython-312-aarch64-linux-gnu.so differ
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/ble_rpc_dispatch.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/ble_rpc_dispatch.cpython-312-aarch64-linux-gnu.so
index e7089fe..562b1d4 100755
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/ble_rpc_dispatch.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/ble_rpc_dispatch.cpython-312-aarch64-linux-gnu.so differ
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/ble_transportd.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/ble_transportd.cpython-312-aarch64-linux-gnu.so
index 6a5090a..7887598 100755
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/ble_transportd.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/ble_transportd.cpython-312-aarch64-linux-gnu.so differ
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/bt_gamepad.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/bt_gamepad.cpython-312-aarch64-linux-gnu.so
index 19fb360..b0033e4 100755
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/bt_gamepad.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/bt_gamepad.cpython-312-aarch64-linux-gnu.so differ
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/cloud_routes.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/cloud_routes.cpython-312-aarch64-linux-gnu.so
index 1105c12..38ee1f1 100755
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/cloud_routes.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/cloud_routes.cpython-312-aarch64-linux-gnu.so differ
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/hephaestusd.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/hephaestusd.cpython-312-aarch64-linux-gnu.so
index fe144a9..f535d73 100755
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/hephaestusd.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/hephaestusd.cpython-312-aarch64-linux-gnu.so differ
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/kwp2000.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/kwp2000.cpython-312-aarch64-linux-gnu.so
index 330cab1..edde5ac 100755
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/kwp2000.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/kwp2000.cpython-312-aarch64-linux-gnu.so differ
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/manage_hephaestusd.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/manage_hephaestusd.cpython-312-aarch64-linux-gnu.so
index 348228a..0ace478 100755
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/manage_hephaestusd.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/manage_hephaestusd.cpython-312-aarch64-linux-gnu.so differ
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/motd.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/motd.cpython-312-aarch64-linux-gnu.so
index fd6666b..1dcb7f7 100755
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/motd.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/motd.cpython-312-aarch64-linux-gnu.so differ
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/tp20.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/tp20.cpython-312-aarch64-linux-gnu.so
index 45a0a6c..1052a8f 100755
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/tp20.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/tp20.cpython-312-aarch64-linux-gnu.so differ
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/vw_pq_flasher.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/vw_pq_flasher.cpython-312-aarch64-linux-gnu.so
index 4fa7f65..2238d6a 100755
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/vw_pq_flasher.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/hephaestus/vw_pq_flasher.cpython-312-aarch64-linux-gnu.so differ
diff --git a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/uploaderd/iquploaderd.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/uploaderd/iquploaderd.cpython-312-aarch64-linux-gnu.so
index b4edcb8..2d81282 100755
Binary files a/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/uploaderd/iquploaderd.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_hephaestusd_private/python/iqpilot_private/konn3kt/uploaderd/iquploaderd.cpython-312-aarch64-linux-gnu.so differ
diff --git a/iqdbc_repo/conftest.py b/iqdbc_repo/conftest.py
index 4b01283..da290ac 100644
--- a/iqdbc_repo/conftest.py
+++ b/iqdbc_repo/conftest.py
@@ -4,6 +4,59 @@ collect_ignore_glob = [
"iqdbc/safety/tests/misra/cppcheck/",
]
+# --- host test harness -------------------------------------------------------
+# tesla/volkswagen carstate+carcontroller import the closed-source ALC / odometer
+# runtime via import_verified_module(), which gates on a rootfs integrity manifest
+# that only exists on-device. Off-device (host CI / dev), install minimal stubs so
+# the whole car interface set is importable and test_car_interfaces can collect and
+# run. On-device the manifest is present and these stubs are never installed, so the
+# real verified modules are used.
+import os as _os
+
+if not _os.path.exists("/usr/libexec/iqpilot/runtime_integrity.json"):
+ import sys as _sys
+ import types as _types
+
+ def _stub_module(name, attrs):
+ mod = _types.ModuleType(name)
+ for key, value in attrs.items():
+ setattr(mod, key, value)
+ _sys.modules[name] = mod
+
+ _noop = lambda *args, **kwargs: None # noqa: E731
+
+ class _VehicleOdometerStoreStub:
+ def __init__(self, *args, **kwargs):
+ pass
+
+ def record(self, km):
+ return km
+
+ _stub_module("iqpilot_private.konn3kt.iqlvbs.vehicle_state",
+ {"VehicleOdometerStore": _VehicleOdometerStoreStub})
+ _stub_module("iqpilot_private.konn3kt.iqlvbs.alc", {
+ "angle_lateral_control_enabled": lambda *a, **k: False,
+ "update_vw_alc": _noop,
+ "append_private_apd": _noop,
+ "update_mqb_carstate_alc_state": _noop,
+ "update_mlb_carstate_alc_state": _noop,
+ "update_pq_carstate_alc_state": _noop,
+ })
+ _stub_module("iqpilot_private.konn3kt.iqlvbs.iqlvbs_commander", {})
+ _stub_module("iqpilot_private.konn3kt.hephaestus.vw_pq_flasher", {})
+
+ try:
+ from openpilot.system.proprietary_runtime import _verified_import as _vi
+ _real_import_verified_module = _vi.import_verified_module
+
+ def _import_verified_module(bundle, module):
+ return _sys.modules.get(module) or _real_import_verified_module(bundle, module)
+
+ _vi.import_verified_module = _import_verified_module
+ except Exception:
+ pass
+# --- end host test harness ---------------------------------------------------
+
_ABSTRACT_BASES = frozenset(("CarSafetyTest", "AolSafetyTestBase", "SafetyTest", "SafetyTestBase"))
def _method_from_base(cls, method_name):
diff --git a/iqdbc_repo/iqdbc/car/chrysler/carstate.py b/iqdbc_repo/iqdbc/car/chrysler/carstate.py
index 70d4448..a0bb499 100644
--- a/iqdbc_repo/iqdbc/car/chrysler/carstate.py
+++ b/iqdbc_repo/iqdbc/car/chrysler/carstate.py
@@ -4,8 +4,8 @@ from iqdbc.car.chrysler.values import DBC, STEER_THRESHOLD, RAM_CARS
from iqdbc.car.common.conversions import Conversions as CV
from iqdbc.car.interfaces import CarStateBase
-from iqdbc.iqpilot.car.chrysler.carstate_ext import CarStateExt
from iqdbc.iqpilot.car.chrysler.aol import AolCarState
+from iqdbc.iqpilot.car.chrysler.carstate_ext import CarStateExt
ButtonType = structs.CarState.ButtonEvent.Type
@@ -114,7 +114,10 @@ class CarState(CarStateBase, AolCarState, CarStateExt):
@staticmethod
def get_can_parsers(CP, CP_IQ):
+ pt_messages: list = []
+ cam_messages: list = []
+ AolCarState.get_parser(CP, pt_messages, cam_messages)
return {
- Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 0),
- Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 2),
+ Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], pt_messages, 0),
+ Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], cam_messages, 2),
}
diff --git a/iqdbc_repo/iqdbc/car/chrysler/fingerprints.py b/iqdbc_repo/iqdbc/car/chrysler/fingerprints.py
index ccfa863..838eeed 100644
--- a/iqdbc_repo/iqdbc/car/chrysler/fingerprints.py
+++ b/iqdbc_repo/iqdbc/car/chrysler/fingerprints.py
@@ -1,10 +1,10 @@
""" AUTO-FORMATTED USING iqdbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE."""
from iqdbc.car.structs import CarParams
from iqdbc.car.chrysler.values import CAR
-
from iqdbc.iqpilot.car.fingerprints_ext import merge_fw_versions
from iqdbc.iqpilot.car.chrysler.fingerprints_ext import FW_VERSIONS_EXT
+
Ecu = CarParams.Ecu
FW_VERSIONS = {
@@ -789,4 +789,6 @@ FW_VERSIONS = {
},
}
+
+
FW_VERSIONS = merge_fw_versions(FW_VERSIONS, FW_VERSIONS_EXT)
diff --git a/iqdbc_repo/iqdbc/car/chrysler/interface.py b/iqdbc_repo/iqdbc/car/chrysler/interface.py
index cde33e3..828120d 100755
--- a/iqdbc_repo/iqdbc/car/chrysler/interface.py
+++ b/iqdbc_repo/iqdbc/car/chrysler/interface.py
@@ -100,9 +100,10 @@ class CarInterface(CarInterfaceBase):
stock_cp.wheelbase = 3.79
stock_cp.steerRatio = 19.
+ # LKAS heartbeat on bus 0 (msg 0x4FF) means the camera is on the ADAS bus and
+ # IQ.Pilot can steer down to a standstill.
if 0x4FF in fingerprint[0]:
ret.flags |= ChryslerFlagsIQ.NO_MIN_STEERING_SPEED.value
stock_cp.minSteerSpeed = 0.
-
return ret
diff --git a/iqdbc_repo/iqdbc/car/ford/carstate.py b/iqdbc_repo/iqdbc/car/ford/carstate.py
index ee4bdec..7080d2e 100644
--- a/iqdbc_repo/iqdbc/car/ford/carstate.py
+++ b/iqdbc_repo/iqdbc/car/ford/carstate.py
@@ -5,17 +5,14 @@ from iqdbc.car.ford.fordcan import CanBus
from iqdbc.car.ford.values import DBC, CarControllerParams, FordFlags
from iqdbc.car.interfaces import CarStateBase
-from iqdbc.iqpilot.car.ford.aol import AolCarState
-
ButtonType = structs.CarState.ButtonEvent.Type
GearShifter = structs.CarState.GearShifter
TransmissionType = structs.CarParams.TransmissionType
-class CarState(CarStateBase, AolCarState):
+class CarState(CarStateBase):
def __init__(self, CP, CP_IQ):
CarStateBase.__init__(self, CP, CP_IQ)
- AolCarState.__init__(self, CP, CP_IQ)
can_define = CANDefine(DBC[CP.carFingerprint][Bus.pt])
if CP.transmissionType == TransmissionType.automatic:
self.shifter_values = can_define.dv["PowertrainData_10"]["TrnRng_D_Rq"]
@@ -112,8 +109,6 @@ class CarState(CarStateBase, AolCarState):
self.acc_tja_status_stock_values = cp_cam.vl["ACCDATA_3"]
self.lkas_status_stock_values = cp_cam.vl["IPMA_Data"]
- AolCarState.update_aol(self, ret, can_parsers)
-
ret.buttonEvents = [
*create_button_events(self.distance_button, prev_distance_button, {1: ButtonType.gapAdjustCruise}),
*create_button_events(self.lc_button, prev_lc_button, {1: ButtonType.lkas}),
diff --git a/iqdbc_repo/iqdbc/car/gm/fingerprints.py b/iqdbc_repo/iqdbc/car/gm/fingerprints.py
index 37d8c57..734415b 100644
--- a/iqdbc_repo/iqdbc/car/gm/fingerprints.py
+++ b/iqdbc_repo/iqdbc/car/gm/fingerprints.py
@@ -1,7 +1,6 @@
# ruff: noqa: E501
""" AUTO-FORMATTED USING iqdbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE."""
from iqdbc.car.gm.values import CAR
-
from iqdbc.iqpilot.car.fingerprints_ext import merge_fingerprints
from iqdbc.iqpilot.car.gm.fingerprints_ext import FINGERPRINTS_EXT
@@ -54,6 +53,9 @@ FINGERPRINTS = {
}],
CAR.CHEVROLET_SILVERADO: [{
190: 6, 193: 8, 197: 8, 201: 8, 208: 8, 209: 7, 211: 2, 241: 6, 249: 8, 257: 8, 288: 5, 289: 8, 298: 8, 304: 3, 309: 8, 311: 8, 313: 8, 320: 4, 322: 7, 328: 1, 352: 5, 381: 8, 384: 4, 386: 8, 388: 8, 413: 8, 451: 8, 452: 8, 453: 6, 455: 7, 460: 5, 463: 3, 479: 3, 481: 7, 485: 8, 489: 8, 497: 8, 500: 6, 501: 8, 528: 5, 532: 6, 534: 2, 560: 8, 562: 8, 563: 5, 565: 5, 587: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 707: 8, 715: 8, 717: 5, 761: 7, 789: 5, 800: 6, 801: 8, 810: 8, 840: 5, 842: 5, 844: 8, 848: 4, 869: 4, 880: 6, 977: 8, 1001: 8, 1011: 6, 1017: 8, 1020: 8, 1033: 7, 1034: 7, 1217: 8, 1221: 5, 1233: 8, 1249: 8, 1259: 8, 1261: 7, 1263: 4, 1265: 8, 1267: 1, 1271: 8, 1280: 4, 1296: 4, 1300: 8, 1611: 8, 1930: 7
+ },
+ {
+ 190: 6, 193: 8, 197: 8, 201: 8, 208: 8, 209: 7, 211: 2, 241: 6, 249: 8, 257: 3, 288: 5, 289: 8, 298: 8, 304: 3, 309: 8, 311: 8, 313: 8, 320: 4, 322: 7, 328: 1, 352: 5, 381: 8, 384: 4, 386: 8, 388: 8, 413: 8, 451: 8, 452: 8, 453: 6, 455: 7, 460: 5, 463: 3, 479: 3, 481: 7, 485: 8, 489: 8, 497: 8, 500: 6, 501: 8, 528: 5, 532: 6, 534: 2, 560: 8, 562: 8, 563: 5, 565: 5, 587: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 707: 8, 715: 8, 717: 5, 761: 7, 789: 5, 800: 6, 801: 8, 810: 8, 840: 5, 842: 5, 844: 8, 848: 4, 869: 4, 880: 6, 977: 8, 1001: 8, 1011: 6, 1017: 8, 1020: 8, 1033: 7, 1034: 7, 1217: 8, 1221: 5, 1233: 8, 1249: 8, 1259: 8, 1261: 7, 1263: 4, 1265: 8, 1267: 1, 1271: 8, 1280: 4, 1296: 4, 1300: 8, 1611: 8, 1930: 7
}],
CAR.CHEVROLET_EQUINOX: [{
190: 6, 193: 8, 197: 8, 201: 8, 209: 7, 211: 2, 241: 6, 249: 8, 257: 8, 288: 5, 289: 8, 298: 8, 304: 1, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 352: 5, 381: 8, 384: 4, 386: 8, 388: 8, 413: 8, 451: 8, 452: 8, 453: 6, 455: 7, 463: 3, 479: 3, 481: 7, 485: 8, 489: 8, 497: 8, 500: 6, 501: 8, 510: 8, 528: 5, 532: 6, 560: 8, 562: 8, 563: 5, 565: 5, 587: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 707: 8, 715: 8, 717: 5, 753: 5, 761: 7, 789: 5, 800: 6, 810: 8, 840: 5, 842: 5, 844: 8, 869: 4, 880: 6, 977: 8, 1001: 8, 1011: 6, 1017: 8, 1020: 8, 1033: 7, 1034: 7, 1217: 8, 1221: 5, 1233: 8, 1249: 8, 1259: 8, 1261: 7, 1263: 4, 1265: 8, 1267: 1, 1271: 8, 1280: 4, 1296: 4, 1300: 8, 1611: 8, 1930: 7
@@ -78,4 +80,5 @@ FINGERPRINTS = {
FW_VERSIONS: dict[str, dict[tuple, list[bytes]]] = {
}
+
FINGERPRINTS = merge_fingerprints(FINGERPRINTS, FINGERPRINTS_EXT)
diff --git a/iqdbc_repo/iqdbc/car/gm/interface.py b/iqdbc_repo/iqdbc/car/gm/interface.py
index 68c2d56..c377f16 100755
--- a/iqdbc_repo/iqdbc/car/gm/interface.py
+++ b/iqdbc_repo/iqdbc/car/gm/interface.py
@@ -16,7 +16,7 @@ from iqdbc.iqpilot.car.gm.values_ext import GMFlagsIQ, GMSafetyFlagsIQ
TransmissionType = structs.CarParams.TransmissionType
NetworkLocation = structs.CarParams.NetworkLocation
-# iqpilot-specific torque parameters for Bolt cars that actually use the d parameter
+# Bolt Non-ACC uses the 4th (d) tune parameter; stock tunes zero it out.
NON_LINEAR_TORQUE_PARAMS_IQ = {
CAR.CHEVROLET_BOLT_NON_ACC: [2.24, 1.1, 0.28, -0.07],
CAR.CHEVROLET_BOLT_NON_ACC_1ST_GEN: [1.8, 1.1, 0.3, -0.045],
@@ -241,11 +241,10 @@ class CarInterface(CarInterfaceBase, CarInterfaceExt):
CAR.CHEVROLET_BOLT_NON_ACC_2ND_GEN, CAR.CHEVROLET_TRAILBLAZER_NON_ACC_2ND_GEN):
stock_cp.steerActuatorDelay = 0.2
CarInterfaceBase.configure_torque_tune(candidate, stock_cp.lateralTuning)
-
elif candidate in (CAR.CHEVROLET_EQUINOX_NON_ACC_3RD_GEN, ):
CarInterfaceBase.configure_torque_tune(candidate, stock_cp.lateralTuning)
- # NON_ACC vehicles should use camera car speed thresholds
+ # Non-ACC cars steer/long via the forward camera and pcmCruise, not the ASCM.
if ret.flags & GMFlagsIQ.NON_ACC:
stock_cp.dashcamOnly = False
stock_cp.alphaLongitudinalAvailable = False
@@ -254,13 +253,13 @@ class CarInterface(CarInterfaceBase, CarInterfaceExt):
stock_cp.pcmCruise = True
stock_cp.safetyConfigs[0].safetyParam |= GMSafetyFlags.HW_CAM.value
ret.iqSafetyFlags |= GMSafetyFlagsIQ.NON_ACC
- stock_cp.minEnableSpeed = 24 * CV.MPH_TO_MS # 24 mph
- stock_cp.minSteerSpeed = 3.0 # ~6 mph
+ stock_cp.minEnableSpeed = 24 * CV.MPH_TO_MS
+ stock_cp.minSteerSpeed = 3.0
- # dashcamOnly platforms: untested platforms, need user validations
+ # Untested Non-ACC platforms ship dashcam-only pending user validation.
if candidate in (CAR.CHEVROLET_BOLT_NON_ACC_2ND_GEN, CAR.CHEVROLET_EQUINOX_NON_ACC_3RD_GEN,
- CAR.CHEVROLET_SUBURBAN_NON_ACC_11TH_GEN, CAR.CADILLAC_CT6_NON_ACC_1ST_GEN, CAR.CHEVROLET_TRAILBLAZER_NON_ACC_2ND_GEN,
- CAR.CADILLAC_XT5_NON_ACC_1ST_GEN):
+ CAR.CHEVROLET_SUBURBAN_NON_ACC_11TH_GEN, CAR.CADILLAC_CT6_NON_ACC_1ST_GEN,
+ CAR.CHEVROLET_TRAILBLAZER_NON_ACC_2ND_GEN, CAR.CADILLAC_XT5_NON_ACC_1ST_GEN):
stock_cp.dashcamOnly = True
return ret
diff --git a/iqdbc_repo/iqdbc/car/gm/values.py b/iqdbc_repo/iqdbc/car/gm/values.py
index 369083b..e1244dc 100644
--- a/iqdbc_repo/iqdbc/car/gm/values.py
+++ b/iqdbc_repo/iqdbc/car/gm/values.py
@@ -4,9 +4,8 @@ from enum import Enum, IntFlag
from iqdbc.car import Bus, PlatformConfig, DbcDict, Platforms, CarSpecs
from iqdbc.car.structs import CarParams
from iqdbc.car.docs_definitions import CarDocs, CarFootnote, CarHarness, CarParts, Column, SupportType
-from iqdbc.car.fw_query_definitions import FwQueryConfig, Request, StdQueries
-
from iqdbc.iqpilot.car.gm.values_ext import GMFlagsIQ
+from iqdbc.car.fw_query_definitions import FwQueryConfig, Request, StdQueries
Ecu = CarParams.Ecu
@@ -88,13 +87,6 @@ class GMCarDocs(CarDocs):
self.car_parts = CarParts.common([CarHarness.obd_ii])
-@dataclass
-class GMNonAccCarDocs(GMCarDocs):
- package: str = "No Adaptive Cruise Control (Non-ACC)"
- support_type: SupportType = SupportType.COMMUNITY
- support_link: str = "community"
-
-
@dataclass(frozen=True, kw_only=True)
class GMCarSpecs(CarSpecs):
tireStiffnessFactor: float = 0.444 # not optimized yet
@@ -123,6 +115,13 @@ class GMSDGMPlatformConfig(GMPlatformConfig):
self.car_docs = []
+@dataclass
+class GMNonAccCarDocs(GMCarDocs):
+ package: str = "No Adaptive Cruise Control (Non-ACC)"
+ support_type: SupportType = SupportType.COMMUNITY
+ support_link: str = "community"
+
+
@dataclass
class GMNonSccPlatformConfig(GMPlatformConfig):
def init(self):
@@ -209,13 +208,7 @@ class CAR(Platforms):
GMCarSpecs(mass=2490, wheelbase=2.94, steerRatio=17.3, centerToFrontRatio=0.5, tireStiffnessFactor=1.0),
)
- # port extensions
- # Separate car def is required when there is no ASCM
- # (for now) unless there is a way to detect it when it has been unplugged...
- # CHEVROLET_VOLT_CC = GMNonSccPlatformConfig(
- # [GMNonAccCarDocs("Chevrolet Volt LT 2017-18")],
- # CHEVROLET_VOLT.specs,
- # )
+ # IQ.Pilot Non-ACC camera-harness ports (no factory adaptive cruise).
CHEVROLET_BOLT_NON_ACC = GMNonSccPlatformConfig(
[GMNonAccCarDocs("Chevrolet Bolt EV Non-ACC 2017")],
CHEVROLET_BOLT_EUV.specs,
@@ -333,7 +326,7 @@ FW_QUERY_CONFIG = FwQueryConfig(
# TODO: detect most of these sets live
EV_CAR = {CAR.CHEVROLET_VOLT, CAR.CHEVROLET_VOLT_2019, CAR.CHEVROLET_BOLT_EUV,
- # port extensions, Non-ACC
+ # Non-ACC EV ports
CAR.CHEVROLET_BOLT_NON_ACC, CAR.CHEVROLET_BOLT_NON_ACC_1ST_GEN, CAR.CHEVROLET_BOLT_NON_ACC_2ND_GEN}
# We're integrated at the camera with VOACC on these cars (instead of ASCM w/ OBD-II harness)
diff --git a/iqdbc_repo/iqdbc/car/nissan/carstate.py b/iqdbc_repo/iqdbc/car/nissan/carstate.py
index 517c314..ce8c252 100644
--- a/iqdbc_repo/iqdbc/car/nissan/carstate.py
+++ b/iqdbc_repo/iqdbc/car/nissan/carstate.py
@@ -5,6 +5,7 @@ from iqdbc.car import Bus, create_button_events, structs
from iqdbc.car.common.conversions import Conversions as CV
from iqdbc.car.interfaces import CarStateBase
from iqdbc.car.nissan.values import CAR, DBC, CarControllerParams
+
from iqdbc.iqpilot.car.nissan.carstate_ext import CarStateExt
ButtonType = structs.CarState.ButtonEvent.Type
diff --git a/iqdbc_repo/iqdbc/car/rivian/interface.py b/iqdbc_repo/iqdbc/car/rivian/interface.py
index 2730e80..dbc6ef1 100644
--- a/iqdbc_repo/iqdbc/car/rivian/interface.py
+++ b/iqdbc_repo/iqdbc/car/rivian/interface.py
@@ -39,6 +39,8 @@ class CarInterface(CarInterfaceBase):
@staticmethod
def _get_params_iq(stock_cp: structs.CarParams, ret: structs.IQCarParams, candidate, fingerprint: dict[int, dict[int, int]],
car_fw: list[structs.CarParams.CarFw], alpha_long: bool, is_release_iq: bool, docs: bool) -> structs.IQCarParams:
+ # Longitudinal harness upgrade advertises msg 0x31a on bus 5; when present it
+ # unlocks radar, blind-spot and openpilot longitudinal on Rivian.
if 0x31a in fingerprint[5]:
ret.flags |= RivianFlagsIQ.LONGITUDINAL_HARNESS_UPGRADE.value
stock_cp.radarUnavailable = False
diff --git a/iqdbc_repo/iqdbc/car/torque_data/substitute.toml b/iqdbc_repo/iqdbc/car/torque_data/substitute.toml
index 6ac4533..75cc15f 100644
--- a/iqdbc_repo/iqdbc/car/torque_data/substitute.toml
+++ b/iqdbc_repo/iqdbc/car/torque_data/substitute.toml
@@ -99,3 +99,14 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
"SUBARU_FORESTER_PREGLOBAL" = "SUBARU_IMPREZA"
"SUBARU_LEGACY_PREGLOBAL" = "SUBARU_IMPREZA"
"SUBARU_ASCENT" = "SUBARU_FORESTER"
+
+# IQ.Pilot GM Non-ACC ports borrow their base platform's lateral tune
+"CHEVROLET_BOLT_NON_ACC" = "CHEVROLET_BOLT_EUV"
+"CHEVROLET_BOLT_NON_ACC_1ST_GEN" = "CHEVROLET_BOLT_EUV"
+"CHEVROLET_BOLT_NON_ACC_2ND_GEN" = "CHEVROLET_BOLT_EUV"
+"CHEVROLET_EQUINOX_NON_ACC_3RD_GEN" = "CHEVROLET_EQUINOX"
+"CHEVROLET_SUBURBAN_NON_ACC_11TH_GEN" = "CHEVROLET_SILVERADO"
+"CADILLAC_CT6_NON_ACC_1ST_GEN" = "CHEVROLET_VOLT"
+"CHEVROLET_TRAILBLAZER_NON_ACC_2ND_GEN" = "CHEVROLET_TRAILBLAZER"
+"CHEVROLET_MALIBU_NON_ACC_9TH_GEN" = "CHEVROLET_VOLT"
+"CADILLAC_XT5_NON_ACC_1ST_GEN" = "CADILLAC_XT4"
diff --git a/iqdbc_repo/iqdbc/car/volkswagen/interface.py b/iqdbc_repo/iqdbc/car/volkswagen/interface.py
index 637f1b1..85a4a9b 100644
--- a/iqdbc_repo/iqdbc/car/volkswagen/interface.py
+++ b/iqdbc_repo/iqdbc/car/volkswagen/interface.py
@@ -171,7 +171,7 @@ class CarInterface(CarInterfaceBase):
ret.steerLimitTimer = 0.4
if ret.flags & VolkswagenFlags.PQ:
ret.steerActuatorDelay = 0.2
- ret.longitudinalTuning.kfDEPRECATED = 1.2
+ ret.longitudinalTuning.kf = 1.2
ret.longitudinalTuning.kpBP = [0.]
ret.longitudinalTuning.kpV = [.45]
ret.longitudinalTuning.kiBP = [0.]
diff --git a/iqdbc_repo/iqdbc/car/volkswagen/tests/test_stopping.py b/iqdbc_repo/iqdbc/car/volkswagen/tests/test_stopping.py
index 1c21653..9a07a21 100644
--- a/iqdbc_repo/iqdbc/car/volkswagen/tests/test_stopping.py
+++ b/iqdbc_repo/iqdbc/car/volkswagen/tests/test_stopping.py
@@ -1,5 +1,6 @@
import pytest
+from iqdbc.car.volkswagen.interface import CarInterface
from iqdbc.car.volkswagen.values import (
CAR, PASSAT_B7_STOP_ACCEL, PASSAT_B7_STOPPING_SPEED, PQ_STOPPING_SPEED,
VolkswagenFlags, apply_pq_stopping_accel, get_longitudinal_stopping_speed_override,
@@ -20,3 +21,13 @@ def test_passat_b7_stop_accel_is_exact():
assert apply_pq_stopping_accel(CAR.VOLKSWAGEN_PASSAT_B7, -0.2, True) == PASSAT_B7_STOP_ACCEL == -0.55
assert apply_pq_stopping_accel(CAR.VOLKSWAGEN_PASSAT_B7, -0.2, False) == -0.2
assert apply_pq_stopping_accel(CAR.VOLKSWAGEN_JETTA_MK6, -0.2, True) == -0.2
+
+
+@pytest.mark.parametrize("candidate", [
+ CAR.VOLKSWAGEN_JETTA_MK6,
+ CAR.VOLKSWAGEN_PASSAT_NMS,
+])
+def test_pq_longitudinal_feedforward_uses_active_schema_field(candidate):
+ fingerprint = {bus: {} for bus in range(8)}
+ cp = CarInterface.get_params(candidate, fingerprint, [], alpha_long=True, is_release=False, docs=False)
+ assert cp.longitudinalTuning.kf == pytest.approx(1.2)
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/chrysler/__init__.py b/iqdbc_repo/iqdbc/iqpilot/car/chrysler/__init__.py
index 297dca9..e69de29 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/chrysler/__init__.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/chrysler/__init__.py
@@ -1,3 +0,0 @@
-"""
-Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
-"""
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/chrysler/aol.py b/iqdbc_repo/iqdbc/iqpilot/car/chrysler/aol.py
index 262546a..6af6f4c 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/chrysler/aol.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/chrysler/aol.py
@@ -1,21 +1,23 @@
"""
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
-"""
+Always-on-Lateral adapter for Chrysler. CarState reads the LKAS toggle button
+(and the forwarded LKAS heartbeat); CarController tracks the AOL state and, when
+AOL is available, drives the LKAS_DISABLED bit the dash reads from the heartbeat.
+"""
from enum import StrEnum
from collections import namedtuple
from iqdbc.car import Bus, structs
from iqdbc.car.chrysler.values import RAM_CARS
-
from iqdbc.iqpilot.aol_base import AolCarStateBase
from iqdbc.can.parser import CANParser
-AolDataIQ = namedtuple("AolDataIQ",
- ["enable_aol", "paused", "lkas_disabled"])
-
+AolDataIQ = namedtuple("AolDataIQ", ["enable_aol", "paused", "lkas_disabled"])
ButtonType = structs.CarState.ButtonEvent.Type
+_HEARTBIT_FIELDS = ("LKAS_DISABLED", "AUTO_HIGH_BEAM", "FORWARD_1", "FORWARD_2", "FORWARD_3")
+
class AolCarController:
def __init__(self):
@@ -23,28 +25,18 @@ class AolCarController:
@staticmethod
def create_lkas_heartbit(packer, lkas_heartbit, aol):
- # LKAS_HEARTBIT (0x2D9) LKAS heartbeat
- values = {s: lkas_heartbit[s] for s in [
- "LKAS_DISABLED",
- "AUTO_HIGH_BEAM",
- "FORWARD_1",
- "FORWARD_2",
- "FORWARD_3",
- ]}
-
+ values = {name: lkas_heartbit[name] for name in _HEARTBIT_FIELDS}
if aol.enable_aol:
values["LKAS_DISABLED"] = 1 if aol.lkas_disabled else 0
-
return packer.make_can_msg("LKAS_HEARTBIT", 0, values)
@staticmethod
def aol_status_update(CC: structs.CarControl, CC_IQ: structs.IQCarControl, CS) -> AolDataIQ:
enable_aol = CC_IQ.aol.available
paused = CC_IQ.aol.enabled and not CC.latActive
-
+ # A tap of the LKAS button flips the driver's "LKAS disabled" preference.
if any(be.type == ButtonType.lkas and be.pressed for be in CS.out.buttonEvents):
CS.lkas_disabled = not CS.lkas_disabled
-
return AolDataIQ(enable_aol, paused, CS.lkas_disabled)
def update(self, CC: structs.CarControl, CC_IQ: structs.IQCarControl, CS) -> None:
@@ -55,35 +47,27 @@ class AolCarState(AolCarStateBase):
def __init__(self, CP: structs.CarParams, CP_IQ: structs.IQCarParams):
super().__init__(CP, CP_IQ)
self.lkas_heartbit = 0
-
self.init_lkas_disabled = False
self.lkas_disabled = False
@staticmethod
def get_parser(CP, pt_messages, cam_messages) -> None:
if CP.carFingerprint in RAM_CARS:
- pt_messages += [
- ("Center_Stack_2", 1),
- ]
+ pt_messages.append(("Center_Stack_2", 1))
else:
pt_messages.append(("TRACTION_BUTTON", 1))
cam_messages.append(("LKAS_HEARTBIT", 1))
- def get_lkas_button(self, cp, cp_cam):
+ def _read_lkas_button(self, cp, cp_cam) -> int:
if self.CP.carFingerprint in RAM_CARS:
- lkas_button = cp.vl["Center_Stack_2"]["LKAS_Button"]
- else:
- lkas_button = cp.vl["TRACTION_BUTTON"]["TOGGLE_LKAS"]
- self.lkas_heartbit = cp_cam.vl["LKAS_HEARTBIT"]
- if not self.init_lkas_disabled:
- self.lkas_disabled = cp_cam.vl["LKAS_HEARTBIT"]["LKAS_DISABLED"]
- self.init_lkas_disabled = True
+ return cp.vl["Center_Stack_2"]["LKAS_Button"]
- return lkas_button
+ self.lkas_heartbit = cp_cam.vl["LKAS_HEARTBIT"]
+ if not self.init_lkas_disabled:
+ self.lkas_disabled = cp_cam.vl["LKAS_HEARTBIT"]["LKAS_DISABLED"]
+ self.init_lkas_disabled = True
+ return cp.vl["TRACTION_BUTTON"]["TOGGLE_LKAS"]
def update_aol(self, ret: structs.CarState, can_parsers: dict[StrEnum, CANParser]) -> None:
- cp = can_parsers[Bus.pt]
- cp_cam = can_parsers[Bus.cam]
-
self.prev_lkas_button = self.lkas_button
- self.lkas_button = self.get_lkas_button(cp, cp_cam)
+ self.lkas_button = self._read_lkas_button(can_parsers[Bus.pt], can_parsers[Bus.cam])
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/chrysler/carcontroller_ext.py b/iqdbc_repo/iqdbc/iqpilot/car/chrysler/carcontroller_ext.py
index fdeb0a8..7e88389 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/chrysler/carcontroller_ext.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/chrysler/carcontroller_ext.py
@@ -1,5 +1,8 @@
"""
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
+
+Chrysler low-speed steering gate: overrides the stock LKAS control bit when the
+no-min-steering-speed option is set, and holds the RAM DT engagement window.
"""
from iqdbc.car import structs
from iqdbc.car.interfaces import CarStateBase
@@ -16,8 +19,9 @@ class CarControllerExt:
def get_lkas_control_bit(self, CS: CarStateBase, CC: structs.CarControl, lkas_control_bit: bool) -> bool:
if self.CP_IQ.flags & ChryslerFlagsIQ.NO_MIN_STEERING_SPEED:
- lkas_control_bit = CC.latActive
- elif self.CP.carFingerprint in RAM_DT:
+ return CC.latActive
+
+ if self.CP.carFingerprint in RAM_DT:
if self.CP.minEnableSpeed <= CS.out.vEgo <= self.CP.minEnableSpeed + 0.5:
lkas_control_bit = True
if self.CP.minEnableSpeed >= 14.5 and CS.out.gearShifter != GearShifter.drive:
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/chrysler/carstate_ext.py b/iqdbc_repo/iqdbc/iqpilot/car/chrysler/carstate_ext.py
index 67cf260..1be0839 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/chrysler/carstate_ext.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/chrysler/carstate_ext.py
@@ -1,13 +1,13 @@
-
"""
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
-"""
+Chrysler cruise-button reader: emits edge ButtonEvents for the ACC steering-wheel
+buttons so IQ.Pilot can react to accel/decel/cancel/resume.
+"""
from enum import StrEnum
from iqdbc.car import Bus, structs
from iqdbc.can.parser import CANParser
-from iqdbc.car.chrysler.values import RAM_HD
from iqdbc.iqpilot.car.chrysler.values_ext import BUTTONS
@@ -15,23 +15,18 @@ class CarStateExt:
def __init__(self, CP, CP_IQ):
self.CP = CP
self.CP_IQ = CP_IQ
-
- self.button_events = []
+ self.button_events: list = []
self.button_states = {button.event_type: False for button in BUTTONS}
- def update(self, ret: structs.CarState, ret_iq: structs.IQCarState, can_parsers: dict[StrEnum, CANParser]):
+ def update(self, ret: structs.CarState, ret_iq: structs.IQCarState, can_parsers: dict[StrEnum, CANParser]) -> None:
cp = can_parsers[Bus.pt]
-
- button_events = []
+ events = []
for button in BUTTONS:
- state = (cp.vl[button.can_addr][button.can_msg] in button.values)
- if self.button_states[button.event_type] != state:
+ pressed = cp.vl[button.can_addr][button.can_msg] in button.values
+ if pressed != self.button_states[button.event_type]:
event = structs.CarState.ButtonEvent.new_message()
event.type = button.event_type
- event.pressed = state
- button_events.append(event)
- self.button_states[button.event_type] = state
- self.button_events = button_events
-
- if self.CP.carFingerprint in RAM_HD:
- ret.steeringAngleDeg = cp.vl["STEERING"]["STEERING_ANGLE"]
+ event.pressed = pressed
+ events.append(event)
+ self.button_states[button.event_type] = pressed
+ self.button_events = events
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/chrysler/values_ext.py b/iqdbc_repo/iqdbc/iqpilot/car/chrysler/values_ext.py
index 7b966ee..caee733 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/chrysler/values_ext.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/chrysler/values_ext.py
@@ -1,7 +1,9 @@
"""
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
-"""
+IQ.Pilot Chrysler extension flags + the cruise-button table read by the AOL
+cruise-button reader.
+"""
from collections import namedtuple
from enum import IntFlag
@@ -20,5 +22,3 @@ BUTTONS = [
class ChryslerFlagsIQ(IntFlag):
NO_MIN_STEERING_SPEED = 1
-
-
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/ford/__init__.py b/iqdbc_repo/iqdbc/iqpilot/car/ford/__init__.py
deleted file mode 100644
index 297dca9..0000000
--- a/iqdbc_repo/iqdbc/iqpilot/car/ford/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
-Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
-"""
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/ford/aol.py b/iqdbc_repo/iqdbc/iqpilot/car/ford/aol.py
deleted file mode 100644
index 510c9e0..0000000
--- a/iqdbc_repo/iqdbc/iqpilot/car/ford/aol.py
+++ /dev/null
@@ -1,21 +0,0 @@
-"""
-Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
-"""
-
-from enum import StrEnum
-
-from iqdbc.car import Bus,structs
-
-from iqdbc.iqpilot.aol_base import AolCarStateBase
-from iqdbc.can.parser import CANParser
-
-
-class AolCarState(AolCarStateBase):
- def __init__(self, CP: structs.CarParams, CP_IQ: structs.IQCarParams):
- super().__init__(CP, CP_IQ)
-
- def update_aol(self, ret: structs.CarState, can_parsers: dict[StrEnum, CANParser]) -> None:
- cp = can_parsers[Bus.pt]
-
- self.prev_lkas_button = self.lkas_button
- self.lkas_button = cp.vl["Steering_Data_FD1"]["TjaButtnOnOffPress"]
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/gm/__init__.py b/iqdbc_repo/iqdbc/iqpilot/car/gm/__init__.py
index 297dca9..e69de29 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/gm/__init__.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/gm/__init__.py
@@ -1,3 +0,0 @@
-"""
-Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
-"""
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/gm/carstate_ext.py b/iqdbc_repo/iqdbc/iqpilot/car/gm/carstate_ext.py
index 4ebe9a1..2bfb846 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/gm/carstate_ext.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/gm/carstate_ext.py
@@ -1,5 +1,8 @@
"""
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
+
+Non-ACC GM carState: these cars have no adaptive cruise, so cruise engage/set
+speed come from the stock (non-adaptive) ECM cruise message.
"""
from enum import StrEnum
@@ -15,9 +18,9 @@ class CarStateExt:
self.CP_IQ = CP_IQ
def update(self, ret: structs.CarState, can_parsers: dict[StrEnum, CANParser]) -> None:
+ if not self.CP_IQ.flags & GMFlagsIQ.NON_ACC:
+ return
pt_cp = can_parsers[Bus.pt]
-
- if self.CP_IQ.flags & GMFlagsIQ.NON_ACC:
- ret.cruiseState.enabled = pt_cp.vl["ECMCruiseControl"]["CruiseActive"] != 0
- ret.cruiseState.speed = pt_cp.vl["ECMCruiseControl"]["CruiseSetSpeed"] * CV.KPH_TO_MS
- ret.accFaulted = False
+ ret.cruiseState.enabled = pt_cp.vl["ECMCruiseControl"]["CruiseActive"] != 0
+ ret.cruiseState.speed = pt_cp.vl["ECMCruiseControl"]["CruiseSetSpeed"] * CV.KPH_TO_MS
+ ret.accFaulted = False
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/gm/interface_ext.py b/iqdbc_repo/iqdbc/iqpilot/car/gm/interface_ext.py
index 2c1bea1..2491266 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/gm/interface_ext.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/gm/interface_ext.py
@@ -1,18 +1,19 @@
"""
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
+
+GM torque-space feed-forward for the IQ.Pilot lateral extension: a sigmoid+linear
+lat-accel -> torque curve for the tuned platforms, else the linear default.
"""
-import os
from math import exp
from iqdbc.car import structs
-from iqdbc.car.common.basedir import BASEDIR
from iqdbc.car.gm.interface import CAR
-from iqdbc.iqpilot.car.interfaces import LatControlInputs, NanoFFModel, TorqueFromLateralAccelCallbackTypeTorqueSpace
+from iqdbc.iqpilot.car.interfaces import LatControlInputs, TorqueFromLateralAccelCallbackTypeTorqueSpace
-NON_LINEAR_TORQUE_PARAMS = {
+_NON_LINEAR_TORQUE_PARAMS = {
CAR.CHEVROLET_BOLT_EUV: [2.6531724862969748, 1.0, 0.1919764879840985, 0.009054123646805178],
CAR.GMC_ACADIA: [4.78003305, 1.0, 0.3122, 0.05591772],
- CAR.CHEVROLET_SILVERADO: [3.29974374, 1.0, 0.25571356, 0.0465122]
+ CAR.CHEVROLET_SILVERADO: [3.29974374, 1.0, 0.25571356, 0.0465122],
}
@@ -20,39 +21,23 @@ class CarInterfaceExt:
def __init__(self, CP: structs.CarParams, CI_Base):
self.CP = CP
self.CI_Base = CI_Base
- self.neural_ff_model = None
- def torque_from_lateral_accel_siglin(self, latcontrol_inputs: LatControlInputs, torque_params: structs.CarParams.LateralTorqueTuning,
+ @staticmethod
+ def _centered_sigmoid(val: float) -> float:
+ # sigmoid shifted to pass through the origin; branch keeps exp() from overflowing
+ if val >= 0:
+ return 1.0 / (1.0 + exp(-val)) - 0.5
+ z = exp(val)
+ return z / (1.0 + z) - 0.5
+
+ def torque_from_lateral_accel_siglin(self, latcontrol_inputs: LatControlInputs,
+ torque_params: structs.CarParams.LateralTorqueTuning,
gravity_adjusted: bool) -> float:
- def sig(val):
- # https://timvieira.github.io/blog/post/2014/02/11/exp-normalize-trick
- if val >= 0:
- return 1 / (1 + exp(-val)) - 0.5
- else:
- z = exp(val)
- return z / (1 + z) - 0.5
-
- # The "lat_accel vs torque" relationship is assumed to be the sum of "sigmoid + linear" curves
- # An important thing to consider is that the slope at 0 should be > 0 (ideally >1)
- # This has big effect on the stability about 0 (noise when going straight)
- # ToDo: To generalize to other GMs, explore tanh function as the nonlinear
- non_linear_torque_params = NON_LINEAR_TORQUE_PARAMS.get(self.CP.carFingerprint)
- assert non_linear_torque_params, "The params are not defined"
- a, b, c, _ = non_linear_torque_params
- steer_torque = (sig(latcontrol_inputs.lateral_acceleration * a) * b) + (latcontrol_inputs.lateral_acceleration * c)
- return float(steer_torque)
-
- def torque_from_lateral_accel_neural(self, latcontrol_inputs: LatControlInputs, orque_params: structs.CarParams.LateralTorqueTuning,
- gravity_adjusted: bool) -> float:
- inputs = list(latcontrol_inputs)
- if gravity_adjusted:
- inputs[0] += inputs[1]
- return float(self.neural_ff_model.predict(inputs))
+ a, b, c, _ = _NON_LINEAR_TORQUE_PARAMS[self.CP.carFingerprint]
+ lat_accel = latcontrol_inputs.lateral_acceleration
+ return float(self._centered_sigmoid(lat_accel * a) * b + lat_accel * c)
def torque_from_lateral_accel_in_torque_space(self) -> TorqueFromLateralAccelCallbackTypeTorqueSpace:
- if self.CP.carFingerprint == CAR.CHEVROLET_BOLT_EUV:
- return self.torque_from_lateral_accel_neural
- elif self.CP.carFingerprint in NON_LINEAR_TORQUE_PARAMS:
+ if self.CP.carFingerprint in _NON_LINEAR_TORQUE_PARAMS:
return self.torque_from_lateral_accel_siglin
- else:
- return self.CI_Base.torque_from_lateral_accel_linear_in_torque_space
+ return self.CI_Base.torque_from_lateral_accel_linear_in_torque_space
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/gm/values_ext.py b/iqdbc_repo/iqdbc/iqpilot/car/gm/values_ext.py
index ddbce1a..b52d293 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/gm/values_ext.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/gm/values_ext.py
@@ -1,7 +1,8 @@
"""
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
-"""
+IQ.Pilot GM extension flags for the non-adaptive-cruise (Non-ACC) camera-harness port.
+"""
from enum import IntFlag
@@ -11,5 +12,3 @@ class GMFlagsIQ(IntFlag):
class GMSafetyFlagsIQ:
NON_ACC = 1
-
-
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/interfaces.py b/iqdbc_repo/iqdbc/iqpilot/car/interfaces.py
index c19f68a..c0bf1f6 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/interfaces.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/interfaces.py
@@ -96,16 +96,17 @@ def _initialize_coop_steering(CP: structs.CarParams, CP_IQ: structs.IQCarParams,
def _initialize_stop_and_go(CP: structs.CarParams, CP_IQ: structs.IQCarParams, params_dict: dict[str, str]) -> None:
- if CP.brand == 'subaru' and not CP.flags & (SubaruFlags.GLOBAL_GEN2 | SubaruFlags.HYBRID):
- stop_and_go = int(params_dict.get("SubaruStopAndGo", 0)) == 1
- stop_and_go_manual_parking_brake = int(params_dict.get("SubaruStopAndGoManualParkingBrake", 0)) == 1
+ # Subaru stop-and-go; unsupported on gen2-global and hybrid platforms.
+ if CP.brand != 'subaru' or CP.flags & (SubaruFlags.GLOBAL_GEN2 | SubaruFlags.HYBRID):
+ return
- if stop_and_go:
- CP_IQ.flags |= SubaruFlagsIQ.STOP_AND_GO.value
- if stop_and_go_manual_parking_brake:
- CP_IQ.flags |= SubaruFlagsIQ.STOP_AND_GO_MANUAL_PARKING_BRAKE.value
- if stop_and_go or stop_and_go_manual_parking_brake:
- CP_IQ.safetyParam |= SubaruSafetyFlagsIQ.STOP_AND_GO
+ if int(params_dict.get("SubaruStopAndGo", 0)) == 1:
+ CP_IQ.flags |= SubaruFlagsIQ.STOP_AND_GO.value
+ if int(params_dict.get("SubaruStopAndGoManualParkingBrake", 0)) == 1:
+ CP_IQ.flags |= SubaruFlagsIQ.STOP_AND_GO_MANUAL_PARKING_BRAKE.value
+
+ if CP_IQ.flags & (SubaruFlagsIQ.STOP_AND_GO | SubaruFlagsIQ.STOP_AND_GO_MANUAL_PARKING_BRAKE):
+ CP_IQ.iqSafetyFlags |= SubaruSafetyFlagsIQ.STOP_AND_GO
def _initialize_toyota(CP: structs.CarParams, CP_IQ: structs.IQCarParams, params_dict: dict[str, str]) -> None:
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/mazda/__init__.py b/iqdbc_repo/iqdbc/iqpilot/car/mazda/__init__.py
deleted file mode 100644
index 297dca9..0000000
--- a/iqdbc_repo/iqdbc/iqpilot/car/mazda/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
-Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
-"""
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/nissan/__init__.py b/iqdbc_repo/iqdbc/iqpilot/car/nissan/__init__.py
index 297dca9..e69de29 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/nissan/__init__.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/nissan/__init__.py
@@ -1,3 +0,0 @@
-"""
-Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
-"""
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/nissan/carstate_ext.py b/iqdbc_repo/iqdbc/iqpilot/car/nissan/carstate_ext.py
index e28f9e4..73f0c76 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/nissan/carstate_ext.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/nissan/carstate_ext.py
@@ -1,7 +1,8 @@
"""
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
-"""
+Nissan cruise-button reader: emits edge ButtonEvents for the RES/SET buttons.
+"""
from enum import StrEnum
from iqdbc.car import Bus, structs
@@ -13,20 +14,18 @@ class CarStateExt:
def __init__(self, CP, CP_IQ):
self.CP = CP
self.CP_IQ = CP_IQ
-
- self.button_events = []
+ self.button_events: list = []
self.button_states = {button.event_type: False for button in BUTTONS}
- def update(self, ret: structs.CarState, ret_iq: structs.IQCarState, can_parsers: dict[StrEnum, CANParser]):
+ def update(self, ret: structs.CarState, ret_iq: structs.IQCarState, can_parsers: dict[StrEnum, CANParser]) -> None:
cp = can_parsers[Bus.pt]
-
- button_events = []
+ events = []
for button in BUTTONS:
- state = (cp.vl[button.can_addr][button.can_msg] in button.values)
- if self.button_states[button.event_type] != state:
+ pressed = cp.vl[button.can_addr][button.can_msg] in button.values
+ if pressed != self.button_states[button.event_type]:
event = structs.CarState.ButtonEvent.new_message()
event.type = button.event_type
- event.pressed = state
- button_events.append(event)
- self.button_states[button.event_type] = state
- self.button_events = button_events
+ event.pressed = pressed
+ events.append(event)
+ self.button_states[button.event_type] = pressed
+ self.button_events = events
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/nissan/values.py b/iqdbc_repo/iqdbc/iqpilot/car/nissan/values.py
index 2c2e333..d1cbe20 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/nissan/values.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/nissan/values.py
@@ -1,8 +1,10 @@
"""
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
-"""
+IQ.Pilot Nissan extension: safety flag + cruise-button table.
+"""
from collections import namedtuple
+
from iqdbc.car import structs
@@ -11,12 +13,9 @@ class NissanSafetyFlagsIQ:
LEAF = 1
-
-
ButtonType = structs.CarState.ButtonEvent.Type
Button = namedtuple('Button', ['event_type', 'can_addr', 'can_msg', 'values'])
-
BUTTONS = [
Button(ButtonType.accelCruise, "CRUISE_THROTTLE", "RES_BUTTON", [1]),
Button(ButtonType.decelCruise, "CRUISE_THROTTLE", "SET_BUTTON", [1]),
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/rivian/__init__.py b/iqdbc_repo/iqdbc/iqpilot/car/rivian/__init__.py
index 297dca9..e69de29 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/rivian/__init__.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/rivian/__init__.py
@@ -1,3 +0,0 @@
-"""
-Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
-"""
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/rivian/aol.py b/iqdbc_repo/iqdbc/iqpilot/car/rivian/aol.py
index f28c0c2..3c92c9a 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/rivian/aol.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/rivian/aol.py
@@ -1,33 +1,30 @@
"""
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
+
+Always-on-Lateral output adapter for Rivian: derives the per-frame lateral-active
+and lane-keep icon state the LKAS command needs from the shared AOL state.
"""
from collections import namedtuple
from iqdbc.car import structs
from iqdbc.car.interfaces import CarStateBase
-MAX_STEERING_ANGLE = 90.0
+# Rivian EPAS rejects large-angle torque, so lateral is dropped past this bound.
+_MAX_STEERING_ANGLE = 90.0
-AolDataIQ = namedtuple("AolDataIQ",
- ["lka_icon_states", "lat_active"])
+AolDataIQ = namedtuple("AolDataIQ", ["lka_icon_states", "lat_active"])
class AolCarController:
def __init__(self):
self.aol = AolDataIQ(False, False)
- self.lka_icon_states = False
- self.lat_active = False
-
- def aol_status_update(self, CC: structs.CarControl, CC_IQ: structs.IQCarControl, CS: CarStateBase) -> AolDataIQ:
- if CC_IQ.aol.available:
- self.lka_icon_states = self.lat_active
- self.lat_active = CC.latActive and abs(CS.out.steeringAngleDeg) < MAX_STEERING_ANGLE
- else:
- self.lka_icon_states = CC.enabled
- self.lat_active = CC.latActive
-
- return AolDataIQ(self.lka_icon_states, self.lat_active)
-
def update(self, CC: structs.CarControl, CC_IQ: structs.IQCarControl, CS: CarStateBase) -> None:
- self.aol = self.aol_status_update(CC, CC_IQ, CS)
+ prev_active = self.aol.lat_active
+ if CC_IQ.aol.available:
+ lat_active = CC.latActive and abs(CS.out.steeringAngleDeg) < _MAX_STEERING_ANGLE
+ lka_icon = prev_active
+ else:
+ lat_active = CC.latActive
+ lka_icon = CC.enabled
+ self.aol = AolDataIQ(lka_icon, lat_active)
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/rivian/carstate_ext.py b/iqdbc_repo/iqdbc/iqpilot/car/rivian/carstate_ext.py
index 051ed13..f638afc 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/rivian/carstate_ext.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/rivian/carstate_ext.py
@@ -1,5 +1,9 @@
"""
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
+
+Rivian longitudinal-harness-upgrade carState reader: with the upgrade harness the
+right steering-wheel controls and the drive stalk drive the openpilot set speed,
+and the harness exposes blind-spot indicators. Only active behind the upgrade flag.
"""
import math
from enum import StrEnum
@@ -12,8 +16,10 @@ from iqdbc.iqpilot.car.rivian.values import RivianFlagsIQ
ButtonType = structs.CarState.ButtonEvent.Type
-MAX_SET_SPEED = 85 * CV.MPH_TO_MS
-MIN_SET_SPEED = 20 * CV.MPH_TO_MS
+_SET_SPEED_MAX = 85 * CV.MPH_TO_MS
+_SET_SPEED_MIN = 20 * CV.MPH_TO_MS
+_LONG_PRESS_FRAMES = 66
+_STALK_HOLD_FRAMES = 50
class CarStateExt:
@@ -29,57 +35,57 @@ class CarStateExt:
self.decrease_counter = 0
self.stalk_down_counter = 0
+ def _apply_set_speed_buttons(self, ret: structs.CarState, cp_park, cp_adas) -> None:
+ was_increasing = self.increase_button
+ was_decreasing = self.decrease_button
+
+ self.increase_button = cp_park.vl["WheelButtons"]["RightButton_RightClick"] == 2
+ self.decrease_button = cp_park.vl["WheelButtons"]["RightButton_LeftClick"] == 2
+ self.increase_counter = self.increase_counter + 1 if self.increase_button else 0
+ self.decrease_counter = self.decrease_counter + 1 if self.decrease_button else 0
+
+ metric = cp_adas.vl["Cluster"]["Cluster_Unit"] == 0
+ conversion = CV.KPH_TO_MS if metric else CV.MPH_TO_MS
+ step = 10.0 if metric else 5.0
+ shown = self.set_speed * (CV.MS_TO_KPH if metric else CV.MS_TO_MPH)
+
+ # A held button steps to the next round multiple; a tap nudges by one unit.
+ if self.increase_button:
+ if self.increase_counter % _LONG_PRESS_FRAMES == 0:
+ self.set_speed = math.ceil((shown + 1) / step) * step * conversion
+ elif not was_increasing:
+ self.set_speed += conversion
+ if self.decrease_button:
+ if self.decrease_counter % _LONG_PRESS_FRAMES == 0:
+ self.set_speed = math.floor((shown - 1) / step) * step * conversion
+ elif not was_decreasing:
+ self.set_speed -= conversion
+
def update_longitudinal_upgrade(self, ret: structs.CarState, can_parsers: dict[StrEnum, CANParser]) -> None:
cp_park = can_parsers[Bus.alt]
cp_adas = can_parsers[Bus.adas]
cp = can_parsers[Bus.pt]
- prev_increase_button = self.increase_button
- prev_decrease_button = self.decrease_button
-
if self.CP.openpilotLongitudinalControl:
- # distance scroll wheel
right_scroll = cp_park.vl["WheelButtons"]["RightButton_Scroll"]
if right_scroll != 255:
if self.distance_button != right_scroll:
ret.buttonEvents = [structs.CarState.ButtonEvent(pressed=False, type=ButtonType.gapAdjustCruise)]
self.distance_button = right_scroll
- # button logic for set-speed
- self.increase_button = cp_park.vl["WheelButtons"]["RightButton_RightClick"] == 2
- self.decrease_button = cp_park.vl["WheelButtons"]["RightButton_LeftClick"] == 2
-
- self.increase_counter = self.increase_counter + 1 if self.increase_button else 0
- self.decrease_counter = self.decrease_counter + 1 if self.decrease_button else 0
-
- metric = cp_adas.vl["Cluster"]["Cluster_Unit"] == 0
- conversion = CV.KPH_TO_MS if metric else CV.MPH_TO_MS
- long_press_step = 10.0 if metric else 5.0
- set_speed_converted = self.set_speed * (CV.MS_TO_KPH if metric else CV.MS_TO_MPH)
-
- if self.increase_button:
- if self.increase_counter % 66 == 0:
- self.set_speed = (int(math.ceil((set_speed_converted + 1) / long_press_step)) * long_press_step) * conversion
- elif not prev_increase_button:
- self.set_speed += conversion
-
- if self.decrease_button:
- if self.decrease_counter % 66 == 0:
- self.set_speed = (int(math.floor((set_speed_converted - 1) / long_press_step)) * long_press_step) * conversion
- elif not prev_decrease_button:
- self.set_speed -= conversion
+ self._apply_set_speed_buttons(ret, cp_park, cp_adas)
if not ret.cruiseState.enabled:
self.set_speed = ret.vEgoCluster
- # VDM_UserAdasRequest: 0=IDLE, 1=UP_1, 2=UP_2, 3=DOWN_1, 4=DOWN_2
+ # Drive stalk held down (VDM_UserAdasRequest 3/4) for ~0.5s snaps set speed
+ # up to the current speed, matching stock Rivian ACC (it never lowers it).
stalk_down = int(cp.vl["VDM_AdasSts"]["VDM_UserAdasRequest"]) in (3, 4)
self.stalk_down_counter = self.stalk_down_counter + 1 if stalk_down else 0
- if self.stalk_down_counter == 50:
- # Mimic Rivian ACC: holding stalk 0.5s sets speed to current speed (never decreases)
+ if self.stalk_down_counter == _STALK_HOLD_FRAMES:
self.set_speed = max(self.set_speed, ret.vEgoCluster)
- self.set_speed = max(MIN_SET_SPEED, min(self.set_speed, MAX_SET_SPEED))
+ self.set_speed = max(_SET_SPEED_MIN, min(self.set_speed, _SET_SPEED_MAX))
ret.cruiseState.speed = self.set_speed
if self.CP.enableBsm:
@@ -92,9 +98,7 @@ class CarStateExt:
@staticmethod
def get_parser(CP, CP_IQ) -> dict[StrEnum, CANParser]:
- messages = {}
-
+ messages: dict[StrEnum, CANParser] = {}
if CP_IQ.flags & RivianFlagsIQ.LONGITUDINAL_HARNESS_UPGRADE:
messages[Bus.alt] = CANParser(DBC[CP.carFingerprint][Bus.alt], [], 5)
-
return messages
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/rivian/values.py b/iqdbc_repo/iqdbc/iqpilot/car/rivian/values.py
index c165a17..0cbd701 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/rivian/values.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/rivian/values.py
@@ -1,10 +1,10 @@
"""
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
+
+IQ.Pilot Rivian extension flags.
"""
from enum import IntFlag
class RivianFlagsIQ(IntFlag):
LONGITUDINAL_HARNESS_UPGRADE = 1
-
-
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/subaru/__init__.py b/iqdbc_repo/iqdbc/iqpilot/car/subaru/__init__.py
index 297dca9..e69de29 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/subaru/__init__.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/subaru/__init__.py
@@ -1,3 +0,0 @@
-"""
-Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
-"""
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/subaru/aol.py b/iqdbc_repo/iqdbc/iqpilot/car/subaru/aol.py
index 523d06f..9e0938e 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/subaru/aol.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/subaru/aol.py
@@ -1,45 +1,36 @@
"""
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
+
+Always-on-Lateral input adapter for Subaru: turns the dashboard LKAS button into
+a carState lkas ButtonEvent so the shared AOL state machine can toggle lateral.
"""
-
from enum import StrEnum
-from iqdbc.car import Bus, structs
+from iqdbc.car import Bus, structs
from iqdbc.car.subaru.values import SubaruFlags
from iqdbc.iqpilot.aol_base import AolCarStateBase
from iqdbc.can.parser import CANParser
-ButtonType = structs.CarState.ButtonEvent.Type
+_LKAS = structs.CarState.ButtonEvent.Type.lkas
+
+# ES_LKAS_State/LKAS_Dash_State: 0 = neutral, 1 = LKAS shown on, 2 = LKAS shown off
+_DASH_ON = 1
+_DASH_OFF = 2
class AolCarState(AolCarStateBase):
- def __init__(self, CP: structs.CarParams, CP_IQ: structs.IQCarParams):
- super().__init__(CP, CP_IQ)
-
- @staticmethod
- def create_lkas_button_events(cur_btn: int, prev_btn: int,
- buttons_dict: dict[int, structs.CarState.ButtonEvent.Type]) -> list[structs.CarState.ButtonEvent]:
- events: list[structs.CarState.ButtonEvent] = []
-
- if cur_btn == prev_btn:
- return events
-
- state_changes = [
- {"pressed": prev_btn != cur_btn and cur_btn != 2 and not (prev_btn == 2 and cur_btn == 1)},
- {"pressed": prev_btn != cur_btn and cur_btn == 2 and cur_btn != 1},
- ]
-
- for change in state_changes:
- if change["pressed"]:
- events.append(structs.CarState.ButtonEvent(pressed=change["pressed"],
- type=buttons_dict.get(cur_btn, ButtonType.unknown)))
- return events
-
def update_aol(self, ret: structs.CarState, can_parsers: dict[StrEnum, CANParser]) -> None:
- cp_cam = can_parsers[Bus.cam]
+ if self.CP.flags & SubaruFlags.PREGLOBAL:
+ return
self.prev_lkas_button = self.lkas_button
- if not self.CP.flags & SubaruFlags.PREGLOBAL:
- self.lkas_button = cp_cam.vl["ES_LKAS_State"]["LKAS_Dash_State"]
+ self.lkas_button = can_parsers[Bus.cam].vl["ES_LKAS_State"]["LKAS_Dash_State"]
- ret.buttonEvents = self.create_lkas_button_events(self.lkas_button, self.prev_lkas_button, {1: ButtonType.lkas})
+ if self._is_toggle_edge():
+ ret.buttonEvents = [*ret.buttonEvents, structs.CarState.ButtonEvent(type=_LKAS, pressed=True)]
+
+ def _is_toggle_edge(self) -> bool:
+ # every dash-state change is a deliberate press except the off->on rebound (2 -> 1)
+ if self.lkas_button == self.prev_lkas_button:
+ return False
+ return not (self.prev_lkas_button == _DASH_OFF and self.lkas_button == _DASH_ON)
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/subaru/stop_and_go.py b/iqdbc_repo/iqdbc/iqpilot/car/subaru/stop_and_go.py
index a696c22..15357c4 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/subaru/stop_and_go.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/subaru/stop_and_go.py
@@ -1,7 +1,11 @@
"""
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
-"""
+IQ.Pilot Subaru stop-and-go: nudges the ACC out of a standstill it would
+otherwise hold. Two variants gated by user flags — an electronic-parking-brake
+resume pulse (distance/lead triggered) and a manual-parking-brake hold-timer
+resume. Both work by spoofing the camera-bus throttle/brake frames.
+"""
import copy
from enum import StrEnum
@@ -14,93 +18,64 @@ from iqdbc.iqpilot.car.subaru import subarucan_ext
from iqdbc.iqpilot.car.subaru.values_ext import SubaruFlagsIQ
from iqdbc.can.parser import CANParser
-_SNG_ACC_MIN_DIST = 3
-_SNG_ACC_MAX_DIST = 4.5
+# EPB resume fires only while the lead is pulling away within this gap band (m).
+_RESUME_GAP_MIN = 3.0
+_RESUME_GAP_MAX = 4.5
+_EPB_PULSE_FRAMES = 15
class SnGCarController:
def __init__(self, CP: structs.CarParams, CP_IQ: structs.IQCarParams):
self.CP = CP
self.CP_IQ = CP_IQ
- self.enabled = CP_IQ.flags & (SubaruFlagsIQ.STOP_AND_GO | SubaruFlagsIQ.STOP_AND_GO_MANUAL_PARKING_BRAKE)
- self.manual_parking_brake = CP_IQ.flags & SubaruFlagsIQ.STOP_AND_GO_MANUAL_PARKING_BRAKE
+ self.enabled = bool(CP_IQ.flags & (SubaruFlagsIQ.STOP_AND_GO | SubaruFlagsIQ.STOP_AND_GO_MANUAL_PARKING_BRAKE))
+ self.manual_parking_brake = bool(CP_IQ.flags & SubaruFlagsIQ.STOP_AND_GO_MANUAL_PARKING_BRAKE)
- self.last_standstill_frame = 0
- self.epb_resume_frames_remaining = -1
- self.prev_close_distance = 0.0
+ self.standstill_since = 0
+ self._pulse_left = 0
+ self.prev_gap = 0.0
- def update_epb_resume_sequence(self, should_resume: bool) -> bool:
+ def _epb_pulse(self, trigger: bool) -> bool:
+ # A trigger arms a fixed-length resume pulse; the pulse then plays out frame by frame.
if self.manual_parking_brake:
return False
+ if trigger:
+ self._pulse_left = _EPB_PULSE_FRAMES
+ if self._pulse_left > 0:
+ self._pulse_left -= 1
+ return True
+ return False
- if should_resume:
- self.epb_resume_frames_remaining = 15
-
- send_resume = self.epb_resume_frames_remaining > 0
- if self.epb_resume_frames_remaining > 0:
- self.epb_resume_frames_remaining -= 1
-
- return send_resume
-
- def update_stop_and_go(self, CC: structs.CarControl, CS: CarStateBase, frame: int) -> bool:
- """
- Manages stop-and-go functionality for adaptive cruise control (ACC).
-
- Args:
- CC: Car control data
- CS: Car state data
- frame: Current frame number
-
- Returns:
- bool: True if resume command should be sent, False otherwise
- """
-
+ def _want_resume(self, CC: structs.CarControl, CS: CarStateBase, frame: int) -> bool:
if not CC.enabled or not CC.hudControl.leadVisible:
return False
- close_distance = CS.es_distance_msg["Close_Distance"]
- in_standstill = CS.out.standstill
+ gap = CS.es_distance_msg["Close_Distance"]
+ standing = CS.out.standstill
+ if not standing:
+ self.standstill_since = frame
- if not in_standstill:
- self.last_standstill_frame = frame
+ hold_arm, hold_reset = (0.75, 0.8) if self.CP.flags & SubaruFlags.PREGLOBAL else (0.5, 0.55)
+ held_for = (frame - self.standstill_since) * DT_CTRL
+ held_long_enough = held_for > hold_arm
+ if held_for >= hold_reset:
+ self.standstill_since = frame
- # Check if we've been in standstill long enough
- mpb_standstill_timers = (0.75, 0.8) if self.CP.flags & SubaruFlags.PREGLOBAL else (0.5, 0.55)
- standstill_duration = (frame - self.last_standstill_frame) * DT_CTRL
- in_standstill_hold = standstill_duration > mpb_standstill_timers[0]
- if (frame - self.last_standstill_frame) * DT_CTRL >= mpb_standstill_timers[1]:
- self.last_standstill_frame = frame
-
- # Car state distance-based conditions (EPB only)
- in_resume_distance = _SNG_ACC_MIN_DIST < close_distance < _SNG_ACC_MAX_DIST
- distance_increasing = close_distance > self.prev_close_distance
- distance_resume_allowed = in_resume_distance and distance_increasing
+ lead_pulling_away = _RESUME_GAP_MIN < gap < _RESUME_GAP_MAX and gap > self.prev_gap
+ self.prev_gap = gap
if self.manual_parking_brake:
- # Manual parking brake: Direct resume when the standstill hold threshold is reached to prevent ACC fault
- send_resume = in_standstill_hold
- else:
- # EPB: Resume sequence with trigger on distance with lead car increasing
- should_resume = CS.out.standstill and distance_resume_allowed
- send_resume = self.update_epb_resume_sequence(should_resume)
-
- self.prev_close_distance = close_distance
-
- return send_resume
+ return held_long_enough
+ return self._epb_pulse(standing and lead_pulling_away)
def create_stop_and_go(self, packer, CC: structs.CarControl, CS: CarStateBase, frame: int) -> list[CanData]:
- can_sends = []
-
if not self.enabled:
- return can_sends
-
- send_resume = self.update_stop_and_go(CC, CS, frame)
-
- can_sends.append(subarucan_ext.create_throttle(packer, self.CP, CS.throttle_msg, send_resume and not self.manual_parking_brake))
+ return []
+ resume = self._want_resume(CC, CS, frame)
+ can_sends = [subarucan_ext.create_throttle(packer, self.CP, CS.throttle_msg, resume and not self.manual_parking_brake)]
if frame % 2 == 0:
- can_sends.append(subarucan_ext.create_brake_pedal(packer, self.CP, CS.brake_pedal_msg, send_resume and self.manual_parking_brake))
-
+ can_sends.append(subarucan_ext.create_brake_pedal(packer, self.CP, CS.brake_pedal_msg, resume and self.manual_parking_brake))
return can_sends
@@ -108,14 +83,11 @@ class SnGCarState:
def __init__(self, CP: structs.CarParams, CP_IQ: structs.IQCarParams):
self.CP = CP
self.CP_IQ = CP_IQ
-
self.brake_pedal_msg: dict[str, float] = {}
self.throttle_msg: dict[str, float] = {}
def update(self, ret: structs.CarState, can_parsers: dict[StrEnum, CANParser]) -> None:
cp = can_parsers[Bus.pt]
-
self.brake_pedal_msg = copy.copy(cp.vl["Brake_Pedal"])
-
if not self.CP.flags & SubaruFlags.HYBRID:
self.throttle_msg = copy.copy(cp.vl["Throttle"])
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/subaru/subarucan_ext.py b/iqdbc_repo/iqdbc/iqpilot/car/subaru/subarucan_ext.py
index b6a710e..5fd8e16 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/subaru/subarucan_ext.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/subaru/subarucan_ext.py
@@ -1,68 +1,41 @@
+"""
+Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
+
+Camera-bus message spoofers for Subaru stop-and-go: re-emit the stock Throttle
+and Brake_Pedal frames, nudging a single field to trigger an ACC resume from a
+standstill. Field sets mirror the DBC message layout.
+"""
from iqdbc.car.subaru.values import CanBus, SubaruFlags
+_THROTTLE_FIELDS_PREGLOBAL = ("Throttle_Pedal", "Signal1", "Not_Full_Throttle", "Signal2", "Engine_RPM",
+ "Off_Throttle", "Signal3", "Throttle_Cruise", "Throttle_Combo", "Throttle_Body",
+ "Off_Throttle_2", "Signal4")
+_THROTTLE_FIELDS_GLOBAL = ("CHECKSUM", "Signal1", "Engine_RPM", "Neutral", "Throttle_Pedal", "Throttle_Cruise",
+ "Throttle_Combo", "Signal3", "Off_Accel")
+_BRAKE_FIELDS_PREGLOBAL = ("Speed", "Brake_Pedal", "Signal1")
+_BRAKE_FIELDS_GLOBAL = ("CHECKSUM", "Signal1", "Speed", "Signal2", "Brake_Lights", "Signal3", "Brake_Pedal", "Signal4")
-def create_counter(msg):
+
+def _next_counter(msg):
return (msg["COUNTER"] + 1) % 0x10
def create_throttle(packer, CP, throttle_msg, send_resume):
- if CP.flags & SubaruFlags.PREGLOBAL:
- values = {s: throttle_msg[s] for s in [
- "Throttle_Pedal",
- "Signal1",
- "Not_Full_Throttle",
- "Signal2",
- "Engine_RPM",
- "Off_Throttle",
- "Signal3",
- "Throttle_Cruise",
- "Throttle_Combo",
- "Throttle_Body",
- "Off_Throttle_2",
- "Signal4",
- ]}
- else:
- values = {s: throttle_msg[s] for s in [
- "CHECKSUM",
- "Signal1",
- "Engine_RPM",
- "Neutral",
- "Throttle_Pedal",
- "Throttle_Cruise",
- "Throttle_Combo",
- "Signal3",
- "Off_Accel",
- ]}
-
- values["COUNTER"] = create_counter(throttle_msg)
-
+ preglobal = bool(CP.flags & SubaruFlags.PREGLOBAL)
+ fields = _THROTTLE_FIELDS_PREGLOBAL if preglobal else _THROTTLE_FIELDS_GLOBAL
+ values = {name: throttle_msg[name] for name in fields}
+ values["COUNTER"] = _next_counter(throttle_msg)
if send_resume:
values["Throttle_Pedal"] = 5
-
return packer.make_can_msg("Throttle", CanBus.camera, values)
def create_brake_pedal(packer, CP, brake_pedal_msg, send_resume):
- if CP.flags & SubaruFlags.PREGLOBAL:
- values = {s: brake_pedal_msg[s] for s in [
- "Speed",
- "Brake_Pedal",
- "Signal1",
- ]}
- else:
- values = {s: brake_pedal_msg[s] for s in [
- "CHECKSUM",
- "Signal1",
- "Speed",
- "Signal2",
- "Brake_Lights",
- "Signal3",
- "Brake_Pedal",
- "Signal4",
- ]}
- values["COUNTER"] = create_counter(brake_pedal_msg)
-
+ preglobal = bool(CP.flags & SubaruFlags.PREGLOBAL)
+ fields = _BRAKE_FIELDS_PREGLOBAL if preglobal else _BRAKE_FIELDS_GLOBAL
+ values = {name: brake_pedal_msg[name] for name in fields}
+ if not preglobal:
+ values["COUNTER"] = _next_counter(brake_pedal_msg)
if send_resume:
- values["Speed"] = 1 if CP.flags & SubaruFlags.PREGLOBAL else 3
-
+ values["Speed"] = 1 if preglobal else 3
return packer.make_can_msg("Brake_Pedal", CanBus.camera, values)
diff --git a/iqdbc_repo/iqdbc/iqpilot/car/subaru/values_ext.py b/iqdbc_repo/iqdbc/iqpilot/car/subaru/values_ext.py
index a58d763..05552bf 100644
--- a/iqdbc_repo/iqdbc/iqpilot/car/subaru/values_ext.py
+++ b/iqdbc_repo/iqdbc/iqpilot/car/subaru/values_ext.py
@@ -1,14 +1,16 @@
"""
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos
+
+IQ.Pilot Subaru extension flags. Selected in setup_interfaces() from the user's
+stop-and-go params and consumed by the stop-and-go controller and panda safety.
"""
-
from enum import IntFlag
-class SubaruSafetyFlagsIQ:
- STOP_AND_GO = 1
-
-
class SubaruFlagsIQ(IntFlag):
STOP_AND_GO = 1
STOP_AND_GO_MANUAL_PARKING_BRAKE = 2
+
+
+class SubaruSafetyFlagsIQ:
+ STOP_AND_GO = 1
diff --git a/iqdbc_repo/iqdbc/safety/tests/test_gm.py b/iqdbc_repo/iqdbc/safety/tests/test_gm.py
index 55b265a..705bd3f 100755
--- a/iqdbc_repo/iqdbc/safety/tests/test_gm.py
+++ b/iqdbc_repo/iqdbc/safety/tests/test_gm.py
@@ -7,7 +7,8 @@ from iqdbc.safety.tests.libsafety import libsafety_py
import iqdbc.safety.tests.common as common
from iqdbc.safety.tests.common import CANPackerSafety
-from iqdbc.iqpilot.car.gm.values_ext import GMSafetyFlagsIQ
+# GM_PARAM_IQ_NON_ACC in safety/modes/gm.h (IQ safety framework flag)
+GM_PARAM_IQ_NON_ACC = 1
class Buttons:
@@ -236,7 +237,7 @@ class TestGmCameraNonACCSafety(TestGmCameraSafety):
self.packer = CANPackerSafety("gm_global_a_powertrain_generated")
self.packer_chassis = CANPackerSafety("gm_global_a_chassis")
self.safety = libsafety_py.libsafety
- self.safety.set_current_safety_param_iq(GMSafetyFlagsIQ.NON_ACC)
+ self.safety.set_current_safety_param_iq(GM_PARAM_IQ_NON_ACC)
self.safety.set_safety_hooks(CarParams.SafetyModel.gm, GMSafetyFlags.HW_CAM | self.EXTRA_SAFETY_PARAM)
self.safety.init_tests()
diff --git a/iqdbc_repo/iqdbc/safety/tests/test_nissan.py b/iqdbc_repo/iqdbc/safety/tests/test_nissan.py
index 7685f6c..fe09fa0 100755
--- a/iqdbc_repo/iqdbc/safety/tests/test_nissan.py
+++ b/iqdbc_repo/iqdbc/safety/tests/test_nissan.py
@@ -2,8 +2,10 @@
import unittest
from iqdbc.car.nissan.values import NissanSafetyFlags
-from iqdbc.iqpilot.car.nissan.values import NissanSafetyFlagsIQ
from iqdbc.car.structs import CarParams
+
+# NISSAN_PARAM_IQ_LEAF in safety/modes/nissan.h (IQ safety framework flag)
+NISSAN_PARAM_IQ_LEAF = 1
from iqdbc.safety.tests.libsafety import libsafety_py
import iqdbc.safety.tests.common as common
from iqdbc.safety.tests.common import CANPackerSafety
@@ -105,7 +107,7 @@ class TestNissanLeafSafety(TestNissanSafety):
def setUp(self):
self.packer = CANPackerSafety("nissan_leaf_2018_generated")
self.safety = libsafety_py.libsafety
- self.safety.set_current_safety_param_iq(NissanSafetyFlagsIQ.LEAF)
+ self.safety.set_current_safety_param_iq(NISSAN_PARAM_IQ_LEAF)
self.safety.set_safety_hooks(CarParams.SafetyModel.nissan, 0)
self.safety.init_tests()
diff --git a/iqpilot/ui/layouts/settings/iq_panels.py b/iqpilot/ui/layouts/settings/iq_panels.py
index fc6dfcb..4db8d54 100644
--- a/iqpilot/ui/layouts/settings/iq_panels.py
+++ b/iqpilot/ui/layouts/settings/iq_panels.py
@@ -872,10 +872,10 @@ class SteeringLayout(Widget):
lambda v: f"{int(round(v * (CV.MPH_TO_KPH if ui_state.is_metric else 1)))}"
f" {'km/h' if ui_state.is_metric else 'mph'}"
)
- self._lagd_toggle = toggle_item(tr("Live Learning Steer Delay"), "", param="IQLiveSteerDelay")
+ self._steer_delay_toggle = toggle_item(tr("Self-Tuning Steer Delay"), "", param="IQLiveSteerDelay")
self._delay_control = option_item(
- tr("Adjust Software Delay"), "IQSoftwareSteerDelay", 5, 50,
- tr("Adjust the fixed software delay added to steer actuator delay when Live Learning Steer Delay is turned off. The default software delay value is 0.2 s."),
+ tr("Manual Delay Offset"), "IQSoftwareSteerDelay", 5, 50,
+ tr("How much lead time to add on top of the car's own steering rack delay while self-tuning is off. Default is 0.2 s."),
1, None, True, "", style.BUTTON_ACTION_WIDTH, None, True, lambda v: f"{float(v):.2f}s"
)
@@ -890,7 +890,7 @@ class SteeringLayout(Widget):
self._lane_turn_desire_toggle,
self._lane_turn_value_control,
IQLineSeparator(40),
- self._lagd_toggle,
+ self._steer_delay_toggle,
self._delay_control,
]
return items
@@ -922,19 +922,20 @@ class SteeringLayout(Widget):
live_delay = ui_state.params.get_bool("IQLiveSteerDelay")
self._lane_turn_desire_toggle.action_item.set_state(turn_desire)
self._lane_turn_value_control.set_visible(turn_desire)
- self._lagd_toggle.action_item.set_state(live_delay)
+ self._steer_delay_toggle.action_item.set_state(live_delay)
self._delay_control.set_visible(not live_delay)
new_step = int(round(100 / CV.MPH_TO_KPH)) if ui_state.is_metric else 100
if self._lane_turn_value_control.action_item.value_change_step != new_step:
self._lane_turn_value_control.action_item.value_change_step = new_step
- lagd_desc = tr("Enable this for the car to learn and adapt its steering response time. Disable to use a fixed steering response time.")
+ delay_desc = tr("Let IQ.Pilot measure how long your steering takes to respond and keep that figure up to date. "
+ "Switch it off to pin the timing yourself.")
if live_delay:
- lagd_desc += f"
{tr('Live Steer Delay:')} {ui_state.sm['liveDelay'].lateralDelay:.3f} s"
+ delay_desc += f"
{tr('Measured:')} {ui_state.sm['liveDelay'].lateralDelay:.3f} s"
elif ui_state.CP:
sw = float(ui_state.params.get("IQSoftwareSteerDelay", "0.2"))
cp = ui_state.CP.steerActuatorDelay
- lagd_desc += f"
{tr('Actuator Delay:')} {cp:.2f} s + {tr('Software Delay:')} {sw:.2f} s = {tr('Total Delay:')} {cp + sw:.2f} s"
- self._lagd_toggle.set_description(lagd_desc)
+ delay_desc += f"
{tr('Rack:')} {cp:.2f} s + {tr('Offset:')} {sw:.2f} s = {tr('Total:')} {cp + sw:.2f} s"
+ self._steer_delay_toggle.set_description(delay_desc)
def _render(self, rect):
if self._current_panel == PanelType.LANE_CHANGE:
diff --git a/selfdrive/ui/mici/layouts/settings/models.py b/selfdrive/ui/mici/layouts/settings/models.py
index a85a6f7..d6d1aba 100644
--- a/selfdrive/ui/mici/layouts/settings/models.py
+++ b/selfdrive/ui/mici/layouts/settings/models.py
@@ -121,16 +121,16 @@ class ModelsLayoutMici(NavScroller):
self._clear.set_click_callback(self._confirm_clear_cache)
self._clear.set_enabled(lambda: ui_state.is_offroad())
- self._lagd = BigParamControl("live learning steer delay", "IQLiveSteerDelay")
- self._sw_delay = MappedParamToggle("software delay", "IQSoftwareSteerDelay", _DELAY_OPTIONS, _DELAY_VALUES)
- self._sw_delay.set_visible(lambda: not self._lagd._checked)
+ self._steer_delay = BigParamControl("self-tuning steer delay", "IQLiveSteerDelay")
+ self._sw_delay = MappedParamToggle("manual delay offset", "IQSoftwareSteerDelay", _DELAY_OPTIONS, _DELAY_VALUES)
+ self._sw_delay.set_visible(lambda: not self._steer_delay._checked)
self._lane_turn = BigParamControl("use lane turn desires", "IQLaneTurnDesire")
self._lane_speed = MappedParamToggle("lane turn speed", "IQLaneTurnValue", _LANE_TURN_OPTIONS, _LANE_TURN_VALUES)
self._lane_speed.set_visible(lambda: self._lane_turn._checked)
self._main_items = [self._current, self._cancel, self._supercombo, self._vision, self._policy, self._redownload, self._refresh, self._clear,
- self._lagd, self._sw_delay, self._lane_turn, self._lane_speed]
+ self._steer_delay, self._sw_delay, self._lane_turn, self._lane_speed]
self._scroller.add_widgets(self._main_items)
@property
@@ -368,7 +368,7 @@ class ModelsLayoutMici(NavScroller):
self._last_cache_t = now
self._clear.set_value(f"{self._calculate_cache_size():.1f} MB")
- self._update_lagd_subtext()
+ self._update_steer_delay_subtext()
def _progress_target_bundle(self):
try:
@@ -445,21 +445,21 @@ class ModelsLayoutMici(NavScroller):
return f"failed: {_display_model_name(bundle)}"
return self._active_model_name()
- def _update_lagd_subtext(self):
- if self._lagd._checked:
+ def _update_steer_delay_subtext(self):
+ if self._steer_delay._checked:
try:
- self._lagd.set_value(f"live {ui_state.sm['liveDelay'].lateralDelay:.3f} s")
+ self._steer_delay.set_value(f"measured {ui_state.sm['liveDelay'].lateralDelay:.3f} s")
except Exception:
- self._lagd.set_value("")
+ self._steer_delay.set_value("")
return
try:
sw = float(ui_state.params.get("IQSoftwareSteerDelay", return_default=True))
except (TypeError, ValueError):
sw = 0.2
if ui_state.CP is not None:
- self._lagd.set_value(f"total {ui_state.CP.steerActuatorDelay + sw:.2f} s")
+ self._steer_delay.set_value(f"total {ui_state.CP.steerActuatorDelay + sw:.2f} s")
else:
- self._lagd.set_value(f"+{sw:.2f} s software")
+ self._steer_delay.set_value(f"+{sw:.2f} s offset")
def _active_model_name(self) -> str:
if not self._has_active_bundle_param():
@@ -495,5 +495,5 @@ class ModelsLayoutMici(NavScroller):
def show_event(self):
super().show_event()
- for w in (self._lagd, self._sw_delay, self._lane_turn, self._lane_speed):
+ for w in (self._steer_delay, self._sw_delay, self._lane_turn, self._lane_speed):
w.refresh()
diff --git a/system/loggerd/loggerd.h b/system/loggerd/loggerd.h
index f4cf803..74cd043 100644
--- a/system/loggerd/loggerd.h
+++ b/system/loggerd/loggerd.h
@@ -43,7 +43,10 @@ struct EncoderSettings {
}
static EncoderSettings QcamEncoderSettings() {
- int _qcam_bitrate = getenv("QCAM_BITRATE") ? atoi(getenv("QCAM_BITRATE")) : 3'200'000;
+ // Keep Konn3kt route uploads useful without turning each 60-second qcamera
+ // segment into a 26 MB file. This is still a substantial improvement over
+ // stock qcam, while CBR keeps storage and upload usage predictable.
+ int _qcam_bitrate = getenv("QCAM_BITRATE") ? atoi(getenv("QCAM_BITRATE")) : 2'400'000;
return EncoderSettings{.encode_type = cereal::EncodeIndex::Type::QCAMERA_H264, .bitrate = _qcam_bitrate, .gop_size = 15};
}
@@ -137,8 +140,8 @@ const EncoderInfo qcam_encoder_info = {
.filename = "qcamera.ts",
.cbr = true, // enforce the bitrate so upload size stays predictable (no VBR overshoot)
.get_settings = [](int){return EncoderSettings::QcamEncoderSettings();},
- .frame_width = 1578, // 3x the stock 526x330, same road-cam aspect ratio
- .frame_height = 990,
+ .frame_width = 1315, // 2.5x the stock 526x330, same road-cam aspect ratio
+ .frame_height = 825,
.include_audio = Params().getBool("RecordAudio"),
INIT_ENCODE_FUNCTIONS(QRoadEncode),
};
diff --git a/system/manager/helpers.py b/system/manager/helpers.py
index 43c0f23..23fb35b 100644
--- a/system/manager/helpers.py
+++ b/system/manager/helpers.py
@@ -11,7 +11,6 @@ import threading
from openpilot.common.basedir import BASEDIR
from openpilot.common.params import Params
-from openpilot.common.swaglog import cloudlog
def unblock_stdout() -> None:
# get a non-blocking stdout
@@ -103,57 +102,3 @@ def save_bootlog():
t = threading.Thread(target=fn, args=(tmp, ))
t.daemon = True
t.start()
-
-
-# REVERT ME! ---------------------------------------------------------------
-# One-shot migration carrying values across the sunny -> IQ param key renames.
-# Old keys are no longer registered in params_keys.h, so their values are read
-# straight off disk, copied to the new IQ key, and the stale file removed.
-# Delete this block (and its manager_init() call) once fielded devices have
-# booted past it at least once.
-_RENAMED_PARAMS = {
- "QuietMode": "IQAlertSilence",
- "SpeedLimitMode": "IQSpeedAssistMode",
- "SpeedLimitPolicy": "IQSpeedAssistPolicy",
- "SpeedLimitOffsetType": "IQSpeedAssistOffsetType",
- "SpeedLimitValueOffset": "IQSpeedAssistValueOffset",
- "LaneTurnDesire": "IQLaneTurnDesire",
- "LaneTurnValue": "IQLaneTurnValue",
- "BlinkerPauseLateralControl": "IQBlinkerPauseLateral",
- "BlinkerMinLateralControlSpeed": "IQBlinkerMinLateralSpeed",
- "DevUIInfo": "IQDevUIInfo",
- "OffroadMode": "IQAlwaysOffroad",
- "AutoLaneChangeTimer": "IQLaneChangeTimer",
- "AutoLaneChangeBsmDelay": "IQLaneChangeBsmDelay",
- "LagdToggle": "IQLiveSteerDelay",
- "LagdToggleDelay": "IQSoftwareSteerDelay",
- "LagdValueCache": "IQSteerDelayCache",
-}
-
-
-def migrate_renamed_params(params: Params | None = None) -> None:
- """REVERT ME! carry stored values across the sunny->IQ key renames, then drop the old files.
-
- Copies at the file level: on-disk param values are raw bytes, so this preserves the exact
- stored representation and sidesteps put()'s typed-value check for BOOL/INT/FLOAT keys.
- """
- p = params if params is not None else Params()
- for old, new in _RENAMED_PARAMS.items():
- try:
- old_path = p.get_param_path(old)
- if not os.path.isfile(old_path):
- continue
- new_path = p.get_param_path(new)
- if not os.path.exists(new_path):
- with open(old_path, "rb") as f:
- value = f.read()
- tmp = new_path + ".tmp"
- with open(tmp, "wb") as f:
- f.write(value)
- f.flush()
- os.fsync(f.fileno())
- os.rename(tmp, new_path)
- os.remove(old_path)
- except Exception:
- cloudlog.exception(f"param rename migration failed for {old} -> {new}")
-# END REVERT ME! ------------------------------------------------------------
diff --git a/system/manager/manager.py b/system/manager/manager.py
index 57feb99..158fe8b 100755
--- a/system/manager/manager.py
+++ b/system/manager/manager.py
@@ -17,7 +17,7 @@ from openpilot.common.params import Params, ParamKeyFlag
from openpilot.common.text_window import TextWindow
from openpilot.system.hardware import HARDWARE
from openpilot.system.loggerd.crash_recovery import recover_unclean_segments
-from openpilot.system.manager.helpers import unblock_stdout, write_onroad_params, save_bootlog, heal_param_perms, migrate_renamed_params
+from openpilot.system.manager.helpers import unblock_stdout, write_onroad_params, save_bootlog, heal_param_perms
from openpilot.system.manager.process import ensure_running
from openpilot.system.manager.process_config import managed_processes
from openpilot.iqpilot.konn3kt.registration import register, UNREGISTERED_DONGLE_ID
@@ -40,7 +40,6 @@ def manager_init() -> None:
build_metadata = get_build_metadata()
params = Params()
- migrate_renamed_params(params) # REVERT ME! sunny->IQ param key migration (runs before defaults are filled)
params.clear_all(ParamKeyFlag.CLEAR_ON_MANAGER_START)
params.clear_all(ParamKeyFlag.CLEAR_ON_ONROAD_TRANSITION)
params.clear_all(ParamKeyFlag.CLEAR_ON_OFFROAD_TRANSITION)
diff --git a/system/ui/lib/wifi_manager.py b/system/ui/lib/wifi_manager.py
index 0993f04..4fe310a 100644
--- a/system/ui/lib/wifi_manager.py
+++ b/system/ui/lib/wifi_manager.py
@@ -67,6 +67,9 @@ class MeteredType(IntEnum):
NO = 2
+_WARNED_UNSUPPORTED_NETWORKS: set[tuple[int, int, int]] = set()
+
+
def get_security_type(flags: int, wpa_flags: int, rsn_flags: int) -> SecurityType:
wpa_props = wpa_flags | rsn_flags
@@ -83,7 +86,10 @@ def get_security_type(flags: int, wpa_flags: int, rsn_flags: int) -> SecurityTyp
# WPA2, WPA2+WPA3 mixed, or WPA — all handled via WPA key_mgmt (NM negotiates SAE if available)
return SecurityType.WPA2
else:
- cloudlog.warning(f"Unsupported network! flags: {flags}, wpa_flags: {wpa_flags}, rsn_flags: {rsn_flags}")
+ _key = (flags, wpa_flags, rsn_flags)
+ if _key not in _WARNED_UNSUPPORTED_NETWORKS:
+ _WARNED_UNSUPPORTED_NETWORKS.add(_key)
+ cloudlog.warning(f"Unsupported network! flags: {flags}, wpa_flags: {wpa_flags}, rsn_flags: {rsn_flags}")
return SecurityType.UNSUPPORTED