IQ.Pilot Release Commit @ 67fd9c2
This commit is contained in:
@@ -506,8 +506,8 @@
|
|||||||
},
|
},
|
||||||
"python/_iqclosure/iqpilot/system/hardware/usb.py": {
|
"python/_iqclosure/iqpilot/system/hardware/usb.py": {
|
||||||
"mode": 420,
|
"mode": 420,
|
||||||
"sha256": "7c2cd7c6d5a859fb8454059da1b36e3b5ce4639aca6fea296b4f91096b46c1ba",
|
"sha256": "8c5b26f3967100ce0e5af7043a47a852fb5e8311f00ac95e7a263934c38e4ec0",
|
||||||
"size": 7257
|
"size": 8069
|
||||||
},
|
},
|
||||||
"python/_iqclosure/iqpilot/system/micd.py": {
|
"python/_iqclosure/iqpilot/system/micd.py": {
|
||||||
"mode": 420,
|
"mode": 420,
|
||||||
@@ -536,28 +536,28 @@
|
|||||||
},
|
},
|
||||||
"python/iqpilot_private/emac/bulk_transport.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/emac/bulk_transport.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "2130f52658e9e6bbb2c3354b497c84a80fd29d0cd81c2c7d524ad31de56dc3f1",
|
"sha256": "f42a1bab373092b3010ca45b02d7ea7b27cd1e1e574c97f701129b2fad01f833",
|
||||||
"size": 333888
|
"size": 333888
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/emac/ffs_holder.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/emac/ffs_holder.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "4dea04cbb68903af8af7745b4691941d4dfd703e9b01bc238791d03d103192aa",
|
"sha256": "306f0362e86558d33072f800b736fa71bfaf4ee5e4383c4e743b72b74724d2e3",
|
||||||
"size": 68072
|
"size": 68064
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/emac/mac_client.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/emac/mac_client.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "87db24c0c6c5cc200cadaaf0348a3f969da3a9fdc99c3fc9e7624b6664d4f895",
|
"sha256": "31339f53f093c3877e13eac90a6647cbca2de92f339c47e5006a85bcd2e3656c",
|
||||||
"size": 267952
|
"size": 267960
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/emac/mac_protocol.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/emac/mac_protocol.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "1db2acc63c5538d47b336bb9703bcfbfa0de89f431d102fd727bb0c3e1a2248f",
|
"sha256": "d5e855d1784a8ba66844639b871d2747ccce264c55359cf0e641ce7e3d66460d",
|
||||||
"size": 203544
|
"size": 203512
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/emac/maciqmodeld.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/emac/maciqmodeld.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "a7a3ca084886882e8d61e3511a59c621bb44ff5e80a27ed6fcee36e9687d31d3",
|
"sha256": "34d4ef1746143ea714f84f3c325e2ddaecec6a19c544fed68d8fc4080578c73f",
|
||||||
"size": 333336
|
"size": 399040
|
||||||
},
|
},
|
||||||
"runtime": {
|
"runtime": {
|
||||||
"entries": {
|
"entries": {
|
||||||
@@ -568,10 +568,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"signatures": {
|
"signatures": {
|
||||||
"python/iqpilot_private/emac/bulk_transport.cpython-312-aarch64-linux-gnu.so": "ufSruB5sta4eGn6fuqxIp5v+uBkUTrot/V+Yf2kiZbrA3xcgOU2qG2AllwWDrn7Hg7a+eczvhJDHLzupuRZaAQ==",
|
"python/iqpilot_private/emac/bulk_transport.cpython-312-aarch64-linux-gnu.so": "7BtEAP11moL2lbQW5dYt1hDqJmDV1EuiEoSfJ0Tfislun2kS+/rwPiy7Ws8kjgrKLv+ZlXlWz6G5IBWk6z+aAw==",
|
||||||
"python/iqpilot_private/emac/ffs_holder.cpython-312-aarch64-linux-gnu.so": "G+hzeZYCDOph6YPDRVGbcWxojtJcBGjXcm6EPfUtfvYxvAu3QDjHXd+B3XdtOSekE/6AiH2CWURpDIwDqgZSBw==",
|
"python/iqpilot_private/emac/ffs_holder.cpython-312-aarch64-linux-gnu.so": "Sv2riVgvm+4PDVTDLTuy1wpf15JObbP8hSAD4iiwF4RUs49GVGhulXkjzO28mLmF6tEuNDNWHRucxmuZrCKNAg==",
|
||||||
"python/iqpilot_private/emac/mac_client.cpython-312-aarch64-linux-gnu.so": "8byO3iMIYoPD9r9SoS1LcxekC+9vdQaFW9s+CZ4MIZmq6h9scsIHNCq3peh6tUcScj/WRFuES/bdZxTItHycAg==",
|
"python/iqpilot_private/emac/mac_client.cpython-312-aarch64-linux-gnu.so": "d4kaBPAEwe55BrQEVHWmxcVlEoQPsMVLOAYgpZVd6uiBnwWSUxl1X5nmqdKtxWSk8TFqU2xZkhfw4OOgG9JmDw==",
|
||||||
"python/iqpilot_private/emac/mac_protocol.cpython-312-aarch64-linux-gnu.so": "YYmTLXA024Dgu8zxXxfXMWIv/lmMvhuH1/C7aaNumZD/b5pkV6gihKomGlM7v/EnE8lYVtWo5wsnUCvl9a9BCQ==",
|
"python/iqpilot_private/emac/mac_protocol.cpython-312-aarch64-linux-gnu.so": "hvBkDKSMKjpxmRzhhGoRZT5WuOWLY+g3p2NIMlA7b6qYYpVaApoZNuquOerywEF1zJnwPiwpsg5QtQVe/5DfAA==",
|
||||||
"python/iqpilot_private/emac/maciqmodeld.cpython-312-aarch64-linux-gnu.so": "f59Fh4UaquFHnDXTAmKdtOwc+++QN5MWi3Zx74L2qZgMLgk3T0/ouTb0WMSTbHgoWn61r+/g/2bH1//Y+NUeAw=="
|
"python/iqpilot_private/emac/maciqmodeld.cpython-312-aarch64-linux-gnu.so": "d3JAlH7P/X87II6iobeQ51melHy1vxdlXn0Nzo2DG65rcdVLM2B66YETPpwlX6Qv9NxhUlDcl/364CR+V+eyDQ=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
OSV+ZbTBvP8stU4KDyT4wavo+fGUZEqcuvN7ltBw4LyMopdaMcbz9jYyIimicnQQniA1d4vaGuWRRQmvm0emAg==
|
KylnzVsK5XC3Jq1G7bBbKa5lv+oJSlfBpBsNpWMEEUgHDyOEj7+5EeeHDOgy8Lt4LEFgEeIV2WEJW0GJVpxUCQ==
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ The USB eGPU dock is identified by VID/PID only. comma's internal codename for
|
|||||||
it is deliberately not used here: IQ.Pilot runs these models on several
|
it is deliberately not used here: IQ.Pilot runs these models on several
|
||||||
backends (eGPU dock, eMac), so the naming stays about the role, not the vendor.
|
backends (eGPU dock, eMac), so the naming stays about the role, not the vendor.
|
||||||
"""
|
"""
|
||||||
|
import subprocess
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
# comma's USB eGPU dock, both shipped USB IDs. The ROM ids are the same board
|
# comma's USB eGPU dock, both shipped USB IDs. The ROM ids are the same board
|
||||||
@@ -124,6 +125,26 @@ def get_link_error_count(soc: Path = SOC_PLATFORM_PATH) -> int:
|
|||||||
return sum(link_errors(c) for c in usb_controllers(soc))
|
return sum(link_errors(c) for c in usb_controllers(soc))
|
||||||
|
|
||||||
|
|
||||||
|
def host_role_controller(soc: Path = SOC_PLATFORM_PATH, udc_root: Path = UDC_PATH) -> Path | None:
|
||||||
|
ctrl = link_controller(udc_root)
|
||||||
|
return (soc / ctrl / "mode") if ctrl else None
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_host_role(mode_path: Path | None = None) -> bool:
|
||||||
|
"""A usbpd blip mid-drive can leave the Type-C controller in 'none'/'peripheral', and the
|
||||||
|
dock can never re-enumerate until something puts the port back into host mode."""
|
||||||
|
path = mode_path if mode_path is not None else host_role_controller()
|
||||||
|
if path is None:
|
||||||
|
return False
|
||||||
|
current = read(path)
|
||||||
|
if current == "host":
|
||||||
|
return True
|
||||||
|
if current is None:
|
||||||
|
return False
|
||||||
|
rc = subprocess.run(["sudo", "-n", "sh", "-c", f"echo host > {path}"], check=False, capture_output=True)
|
||||||
|
return rc.returncode == 0 and read(path) == "host"
|
||||||
|
|
||||||
|
|
||||||
def egpu_dock_present(root: Path = USB_DEVICES_PATH) -> bool:
|
def egpu_dock_present(root: Path = USB_DEVICES_PATH) -> bool:
|
||||||
"""A dock in ROM/bootloader state is deliberately NOT counted as present: it
|
"""A dock in ROM/bootloader state is deliberately NOT counted as present: it
|
||||||
enumerates but cannot serve a GPU until vendor firmware is flashed."""
|
enumerates but cannot serve a GPU until vendor firmware is flashed."""
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
3184657cdc4d4fc1c69a924491f8a52466f10ec2
|
|
||||||
@@ -186,7 +186,7 @@
|
|||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/__init__.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/__init__.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "9459a9e4551e5fd87cd98457a4cebcdd6f4763fc2ce03e13202011659289f8d3",
|
"sha256": "6e6de2f3270ad097c9b847fa10e833bac6b8eaab8ddad955603d163474a3c846",
|
||||||
"size": 67616
|
"size": 67616
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/__init__.py": {
|
"python/iqpilot_private/navd/__init__.py": {
|
||||||
@@ -196,107 +196,122 @@
|
|||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/alpr_matcher.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/alpr_matcher.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "ea3451196fa13a2a8e2f9be7abff1b084308c856c52f001260f8340cc22e220f",
|
"sha256": "516370d0603f5134955826a3d8e9fea8ec0a9d27c116ad05af149a5c7ac15bcc",
|
||||||
"size": 269936
|
"size": 269936
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/amap_client.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/amap_client.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "96398bb3c989d670b641582e15bcd3ebc73f43f20b081dfaecd3d26fa81dc873",
|
"sha256": "dc8f27970c61a3b60c383ea69804896ee356d76c8bf7af5532a9338525fbc956",
|
||||||
"size": 202040
|
"size": 202040
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/event_builder.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/event_builder.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "bdd6cc139cdac78d3b6bf93e7930764bbd0538f24799b939fedd1e32f25c5266",
|
"sha256": "96eb02a86cab08d557f8df0adebd2cc72232b9348e9896acd9b71784a86b42d5",
|
||||||
"size": 136960
|
"size": 136960
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/helpers.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/helpers.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "2df3400081a717f6ed6a819d3f5789ceda0707f89a6f6851dd77bd827b4721c6",
|
"sha256": "8fb8cc47f47971c530a68ccd81b9b5d9fc8ce82cdd1270967fa845399009e519",
|
||||||
"size": 135960
|
"size": 135960
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/incident_feed.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/incident_feed.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "fe29e5f6eb290d17c7fab03e55db700772d9b6abc77e34954d952175a9a8dd45",
|
"sha256": "b49f7ce7e9a33777ffa896a95fc4a5580988b4966d5a9330efd8c79a5116be91",
|
||||||
"size": 135528
|
"size": 135584
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/iqmapd.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/iqmapd.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "f6104209fc944accc4bca9d76598c14ea7bb32b5c06c6675c69ed71abbc18692",
|
"sha256": "747ae769bb35650dcd16b94a0a6260213373e352ede88bc1e57f114f27761d5a",
|
||||||
"size": 135632
|
"size": 135632
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/long_decel.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/long_decel.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "b9a69dc97ff120e5efc5a41b0e24d14d9b57a4e83faf4a2fb9c414cc5feae407",
|
"sha256": "eae425cd9bf60286fff4b980c6057351cb940f28981556269f05022258d80f0c",
|
||||||
"size": 69752
|
"size": 69752
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/mapbox_client.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/mapbox_client.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "c6e2f1e77e0ef71ddb7ae6178e3a22990b11b224b4b62e5db767e0f78d854402",
|
"sha256": "0fc4356fe57a11538e4a248dc803ceee61781d7c700640f78241a2d57cbb4574",
|
||||||
"size": 68144
|
"size": 68144
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/nav_cameras.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/nav_cameras.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "fcabb4944766db54e4ef13849886339b352f9604b620b93e7b09bbddc5172a58",
|
"sha256": "92521da14a5bf334324f32315b13773d37d5f7d209d4bad6d62afc12ab5d1705",
|
||||||
"size": 203056
|
"size": 203056
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/nav_turn_signals.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/nav_turn_signals.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "f95c6ae94b726d5c6634a0867e60cb433fcf41a07270512ee02ae422f580fb2a",
|
"sha256": "67454e461abb76c7a3053a7f728baa0beb30fba235639a0a2a927a9c80443a4a",
|
||||||
"size": 135560
|
"size": 135560
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/navd.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/navd.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "4b04550554f61540c72d7657d172e699f17535faaf29b8223f6640eb71a9c0dc",
|
"sha256": "9e0d5e929bfcd960fdba11804d1f70848ba40a68a65093c025a6d48171d0b2cc",
|
||||||
"size": 797328
|
"size": 797392
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/navincidentd.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/navincidentd.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "9a51d7c696a819e5ba47ba552bd1e7d21c28cdcb91fc9e0c22eb4b8d7c6d37e8",
|
"sha256": "33d40decd32e8cfe3f9a267ebfccf48e8bfc67bf9609206ef230a9566bf5581d",
|
||||||
"size": 135344
|
"size": 135344
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/navrenderd.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/navrenderd.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "fd120500f581eb408700c1c43dc6789b0391041b7a1b4341ee9352e5edeb1cf1",
|
"sha256": "edf0d16511686ed3d4d7d6bf2b6b44fd8d484af348dab0eb415999656eb1d0af",
|
||||||
"size": 135584
|
"size": 135584
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/osm_cameras.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/osm_cameras.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "89ca86442a4cad9c79046c6a7d5a96dd65c352829b6234e41d131997e27ef28b",
|
"sha256": "b11bec6f1b49f169f218a87467781b6d62d64c367e0c3df5356341adce8c3f6b",
|
||||||
"size": 202384
|
"size": 202384
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/reroute.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/reroute.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "8850331bcad9b7d708cb5cabff7c80364ed75b4dd000f1f3cca0098fb02bc5a7",
|
"sha256": "d38218a6787234730ed39bdb04c00ab0778b1b56eefcedcb9ecfb31346d36378",
|
||||||
"size": 136216
|
"size": 136216
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/road_incidents.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/road_incidents.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "9faab3cc244eeba8dfae46b6ec57f4e8d9d03ca0c465b5ce2da836f1988aa0f6",
|
"sha256": "f89f69e128b02eebc31b4c3702d62e12747f837863ad390026ea5004e506ea7c",
|
||||||
"size": 203136
|
"size": 203136
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/route_manager.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/route_manager.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "92e599dc73871b128be19c80057f983423023d7e2e3f9589ee8fe3c308ef2297",
|
"sha256": "311926ffa2b4474320411240e6656ee676ce8b61d1cea444c34cd9520113a6a6",
|
||||||
"size": 877864
|
"size": 943640
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/runtime_common.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/runtime_common.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "e24efc1da92e76a996549c22d8c56708e8713193be36c6365868de29be9a0276",
|
"sha256": "dc08b2e6bf7be3fe0b4a7ccdfceab6c434317e7626efd9b40ea5bf15739647ba",
|
||||||
"size": 135760
|
"size": 135760
|
||||||
},
|
},
|
||||||
"python/iqpilot_private/navd/traffic.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/traffic.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "b97fae21d32dee6f240b79e3090c94f06e0328b8bf511b869667e56a23836901",
|
"sha256": "f47146eddd7c8b499359d411150533c0e28e80851096d076ee8552a4d45175d9",
|
||||||
"size": 69720
|
"size": 69720
|
||||||
},
|
},
|
||||||
|
"python/iqpilot_private/navd/traffic_sources.cpython-312-aarch64-linux-gnu.so": {
|
||||||
|
"mode": 493,
|
||||||
|
"sha256": "98845f8be1fd44009acf88fe685f6985ffb996d5d508858bdbb3edd2984a5146",
|
||||||
|
"size": 135968
|
||||||
|
},
|
||||||
|
"python/iqpilot_private/navd/traffic_writer.cpython-312-aarch64-linux-gnu.so": {
|
||||||
|
"mode": 493,
|
||||||
|
"sha256": "15aba494968b9673987d2d0168d797bfbd307046555cb89efa2378acc8bb042a",
|
||||||
|
"size": 136936
|
||||||
|
},
|
||||||
"python/iqpilot_private/navd/turn_desire.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/turn_desire.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "822c67671b249a96bb5de1a83bd7c047ffb780bd252c62791a25a0ea7c2101fc",
|
"sha256": "715f94a985599a983750affa5bf36e1fc2e6502871f1af7de553f9aaf29028cb",
|
||||||
"size": 69768
|
"size": 69768
|
||||||
},
|
},
|
||||||
|
"python/iqpilot_private/navd/valhalla_process.cpython-312-aarch64-linux-gnu.so": {
|
||||||
|
"mode": 493,
|
||||||
|
"sha256": "2658d1a9f08f49e1294a3c26be733170ac7943970a79ee2969d9404cd4b55758",
|
||||||
|
"size": 204072
|
||||||
|
},
|
||||||
"python/iqpilot_private/navd/web_server.cpython-312-aarch64-linux-gnu.so": {
|
"python/iqpilot_private/navd/web_server.cpython-312-aarch64-linux-gnu.so": {
|
||||||
"mode": 493,
|
"mode": 493,
|
||||||
"sha256": "2c1c671d8d933d6896387894fe62b213b99b9d75085b54c61806e2bb7d381d7b",
|
"sha256": "d03bf4d8d7d1547c5fcd085dea2ff78f8071e04e51e7f4d002f7ba23b431038e",
|
||||||
"size": 201400
|
"size": 201400
|
||||||
},
|
},
|
||||||
"runtime": {
|
"runtime": {
|
||||||
@@ -336,27 +351,30 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"signatures": {
|
"signatures": {
|
||||||
"python/iqpilot_private/navd/__init__.cpython-312-aarch64-linux-gnu.so": "lg9M4QXLrh1ynX/Hev+0FAPnbN9mDoqv8diic0U+aYqjLMgkW+wHcB4r78J8oTrpDC+vF1wWztWj3cQOx98NCw==",
|
"python/iqpilot_private/navd/__init__.cpython-312-aarch64-linux-gnu.so": "9i3/SfFfCLGyTzyQQYpsSxbA3ASc1OSK7fCYXpIiIMnX+jKB288Qy7TzJnr3uINt+LhRW1wwnMI6hWBXjgv5AA==",
|
||||||
"python/iqpilot_private/navd/alpr_matcher.cpython-312-aarch64-linux-gnu.so": "DGacFfOsQ9paqF8ytUgX572A/wPOZi7rJefAl9vydnAFbQv5NL+c9ot5YDGI1s4mXs/SHPbn0WtTOOU2aS/hDQ==",
|
"python/iqpilot_private/navd/alpr_matcher.cpython-312-aarch64-linux-gnu.so": "5K4w4dDRtts8QvxBAXL0qrYofb/bg9PV/rKn/GrVmtAVDMd0DhAiKAugoxkhl8n4JviFY8ZmsHwWBrQPIMdkAA==",
|
||||||
"python/iqpilot_private/navd/amap_client.cpython-312-aarch64-linux-gnu.so": "r0vM+nE7A00o362Oj745OQzat76z889uBd/niFp18Qds4P1Wpvynd1ctrbOlo9H1yESeC09NuP/Qw4k1pvt1Cg==",
|
"python/iqpilot_private/navd/amap_client.cpython-312-aarch64-linux-gnu.so": "X+hzm32FyMwE9fSIaGZH/GQqHn78izqrX8o1FdATb0Fg4+62tcgI9LHe9PIM8VY6+IaryaWyKqFtATaq6BZrDw==",
|
||||||
"python/iqpilot_private/navd/event_builder.cpython-312-aarch64-linux-gnu.so": "JkfNSqU9uM4oZqxteomIbPo6abywxUzzdBx5B2myJNtUjGW5bHEii2D2DAUKuO+gd7x+6+IwgPwSOJJyN+QYBQ==",
|
"python/iqpilot_private/navd/event_builder.cpython-312-aarch64-linux-gnu.so": "dQnA8CCeRMXqiARr/Kzf2x736DuaT1/ALC8ZLDZep2/nY2IJ7StZeZ8DwOBuRPRK8KJ5HNU424QMZkVzQcDnBg==",
|
||||||
"python/iqpilot_private/navd/helpers.cpython-312-aarch64-linux-gnu.so": "/CNm/bxjvo/IgjjDTde0p8c1Gl6I54dSwiSS0sEVUcrTRP3Y31S0dh8dnBqn1VTH3PIGlUDBF7EmTavXUOAfDg==",
|
"python/iqpilot_private/navd/helpers.cpython-312-aarch64-linux-gnu.so": "tdLykhS2t9M7R115Rse80M2Urg/8sNQTLaOz3YFyUTTkEzpaBlk3JnbgOQVpzDjrPB7y22y6mNORCkYI3cKfCw==",
|
||||||
"python/iqpilot_private/navd/incident_feed.cpython-312-aarch64-linux-gnu.so": "3IB5k4NEsFoKHckxlqoOZVXBAyVhYkVWRCvRdBnH4H+8udEuW5EpRXHv0rxtqBAs82ozbpOcZ7QjtfFgQPbXCQ==",
|
"python/iqpilot_private/navd/incident_feed.cpython-312-aarch64-linux-gnu.so": "MJ/i1ZvGb3bYBVxKvT/zBk43CM/XT37GZa6la52Tfmqp9mrx6oz98PpvLZMgJ+18J4lSdMf2uGuJ2IHx5wWTAQ==",
|
||||||
"python/iqpilot_private/navd/iqmapd.cpython-312-aarch64-linux-gnu.so": "Dp4PpzIqDJ5ySg1lIi0b5V49g7U2aOx1T+SeKGGKhOaEcCLnUEAd2EilrXt2luq8Xj+nnHWbMrZUho0KV7MfBQ==",
|
"python/iqpilot_private/navd/iqmapd.cpython-312-aarch64-linux-gnu.so": "+ULQz9iDSDBtYRYSVVWz63TImB3DizGV2oFER6pmNttfJ6vA4SBVToxKV1YjHAebdMiSrTBrEkgPd5K4unE0Bg==",
|
||||||
"python/iqpilot_private/navd/long_decel.cpython-312-aarch64-linux-gnu.so": "z87MDJLWKyqWqsXzTnoxjNfjkPxi6W0wsUt+Cafw5QWHMB6jGkJ1ZedYeS83qqdaxZGR3OaBdKohMSi9JKQHDA==",
|
"python/iqpilot_private/navd/long_decel.cpython-312-aarch64-linux-gnu.so": "PB+q882Oo/cOi+fN0IahlaBP7xEQrjF7BykAnCsxrnK8zJGkFZdrVUcLCS4T5DYjXhwlXbdveb3ZHdG/LoMcBQ==",
|
||||||
"python/iqpilot_private/navd/mapbox_client.cpython-312-aarch64-linux-gnu.so": "FtOYM9RJA3LudYiGW9h4+EO94TqJVV4/hhEb9DOIL3hrbJYMWCctCTfo70UmgL+v8+8MSCyHgL3KBqPsW58gCg==",
|
"python/iqpilot_private/navd/mapbox_client.cpython-312-aarch64-linux-gnu.so": "vqQRU0t5AS/oUs1JWxZlwHC5mrpaaHD10jgQCLzDGUL4Yv1aFHWAoM6KfFdUldmdSG1d4e6VGu+Y2bMdBIwAAw==",
|
||||||
"python/iqpilot_private/navd/nav_cameras.cpython-312-aarch64-linux-gnu.so": "XfkYcx/mj7TT57RjfAdlleSW5kgdGkLYt0h+SpJV+UdQeb+NTVHYa3+PgglT1KP8WjO5Tbyr6i5V4pq4ZwbhCQ==",
|
"python/iqpilot_private/navd/nav_cameras.cpython-312-aarch64-linux-gnu.so": "OfuUD6/swlx5ggtvLfUVjGqpJbZWf+Ezwia5fE81FXA6RcuR4SMx1t/D38+TaMKDGvaBV31s08TJgh+/hXiiDA==",
|
||||||
"python/iqpilot_private/navd/nav_turn_signals.cpython-312-aarch64-linux-gnu.so": "GGhf7FRjRzg9uLp4ClSosUUXJk+ocH4NETh8wetaqTkXev1smeJCd2OWbTqgWmlGRfjLqsnXzpv+bxBIKishAw==",
|
"python/iqpilot_private/navd/nav_turn_signals.cpython-312-aarch64-linux-gnu.so": "WQOzntcyeraddagnvnxAwH/ciLFMztjfEhg07HFHy+++XJPCSGctdaxlgPWX6xq9kiE7aEkcTsW2CwOwYo3tDw==",
|
||||||
"python/iqpilot_private/navd/navd.cpython-312-aarch64-linux-gnu.so": "YwIAOpt1komu3aFiqx1uhCJFpFZ/tCub2RNrJMyh8RS7SI0ySxmiQ9MXMyuXt5Gxnt9ReGmxVSKo7x3UDsuCCg==",
|
"python/iqpilot_private/navd/navd.cpython-312-aarch64-linux-gnu.so": "5c68ZgFSkAXf9m32zKbBDSNHF0rVTwZPVu0puTiIcM7laHyHVtkQJduq6g4SUm+wz634nLK2u5pggaNf+mkhAw==",
|
||||||
"python/iqpilot_private/navd/navincidentd.cpython-312-aarch64-linux-gnu.so": "2agJVQwkglB5XE1acDWp+u/ZzwP0qJcEklPATDv4jez1KkftYqQb47J1/iGSxOtwh9NuXe//MNg+EEmwSlzvAQ==",
|
"python/iqpilot_private/navd/navincidentd.cpython-312-aarch64-linux-gnu.so": "LBV8K1SPj+bN8idsPR/3B24grXQYRNarYsCUbVaRdkfORuib70gRlGz4KtyOyYT/vpCU4iuDhnSRsd4ltH4RAg==",
|
||||||
"python/iqpilot_private/navd/navrenderd.cpython-312-aarch64-linux-gnu.so": "G2ccii+ezg3lFQcNXI15EMVXWpszZlJJ4dy+nylF0OLEWWKRGFofb+vq4fYfwrJXmbn4nK9F+286nt4Q81WQAQ==",
|
"python/iqpilot_private/navd/navrenderd.cpython-312-aarch64-linux-gnu.so": "ZT4bVD2W2w9w2AdbKkZ7AgfQv+zqTmJH5126ngiDDRFFuW2Bnp+E/4M+6U912uGZsV5xayCw8QmJbM9EeSqgDQ==",
|
||||||
"python/iqpilot_private/navd/osm_cameras.cpython-312-aarch64-linux-gnu.so": "+zTVSWeyZBkJFOC95QdK0LGd0EzLBZVB/GbKd3RiMsiQw83oAwNomLWs3SbsUhRBCZyGF56n2TQXEZQWjknaCg==",
|
"python/iqpilot_private/navd/osm_cameras.cpython-312-aarch64-linux-gnu.so": "jjmBJtLWRVkPsO4n7/N/pDVD9jrC4SCMm0lIT/P8HCzsMhIIAkXhRAMGKdl1kYDxK8VMGRMMF7eoiCKEFPq2AA==",
|
||||||
"python/iqpilot_private/navd/reroute.cpython-312-aarch64-linux-gnu.so": "V+CQv3lqojsqJ/1gJJCuaR94ncCkRX4fT0iD+mxvJNmTLBGvw90hKl9v6IgtUvCOhqnHo2nJf30iH07C8R7iBA==",
|
"python/iqpilot_private/navd/reroute.cpython-312-aarch64-linux-gnu.so": "A0FeGUh384rTKZJLOL6wNdX3bLTTsmUX7kF3ysax7WjnyUSlctbms15E+3Ww87qmXwjMGbyPdlTdsnhvpcstAA==",
|
||||||
"python/iqpilot_private/navd/road_incidents.cpython-312-aarch64-linux-gnu.so": "y5v5qBwMoKEvcYxjEy5tOwEB2BXaCAKIaKEBQKUuUfZpEZw7IpvPDGZbD5P5f1j05EJBde6jV9XbPB1mHIiHCg==",
|
"python/iqpilot_private/navd/road_incidents.cpython-312-aarch64-linux-gnu.so": "J/I+XcODFE7LKvtyImt/Dw8fh2uvQeEhZ1IWx2IHZPH8sXhuVGVQIECVFGQJGfsckjzoUpgZq8AYNReRF62sBw==",
|
||||||
"python/iqpilot_private/navd/route_manager.cpython-312-aarch64-linux-gnu.so": "BIpSZfiTIaOZucyCX3pGiAtNAtRIg8WNQyfaMqnMEy52Ttowb1NheURl/qn11wqKaKeQN5+wgDmTwIkx3Eu6CQ==",
|
"python/iqpilot_private/navd/route_manager.cpython-312-aarch64-linux-gnu.so": "n/RFD32mlinaYGrWvKWGv8ziTTSFP8+qCS/I1ibFXRYU6gtwx/+03eUR+p2jh5hzPteo5RxLUfHDwxFvJMJzDA==",
|
||||||
"python/iqpilot_private/navd/runtime_common.cpython-312-aarch64-linux-gnu.so": "pyRMyI5u6/IG5LKIgCuZf4rcquMN19P8M2rcmr+yjnfO50o8SRT18+iklNXj0VY96LKMyQx/ejV7y7Jgt+qnDw==",
|
"python/iqpilot_private/navd/runtime_common.cpython-312-aarch64-linux-gnu.so": "/5mYKn9um2aBLipkFsEptfM3sOId3SKkV8AHXGslWdH9Evp2ll8XENvirAX5tV1X35WslGYIybK3Xv3cZ4o8DQ==",
|
||||||
"python/iqpilot_private/navd/traffic.cpython-312-aarch64-linux-gnu.so": "MVSL4IXTQ8SFa6zDY5Y/QWN5yhcFBx6LaujCzLJQfALs0bYb7jyy7XVbxlyQshpOy4n151YggEBhuNSCGHSaCA==",
|
"python/iqpilot_private/navd/traffic.cpython-312-aarch64-linux-gnu.so": "kfl1Mm7G3CguQGtUvDutvbd4StDnKr0pW7ojLn6gydVTyxEiD/VAEFfTKBK/CAyUcw3eeX5+U8Qq2+6o0zEUBA==",
|
||||||
"python/iqpilot_private/navd/turn_desire.cpython-312-aarch64-linux-gnu.so": "A6QTQvEit2o797TrW2PuahnLODdACAAIahBw3UWtOTKHhD+vQaXke0yvxBcgVxgaBJLfpIz8SjKaZuEeIPphDg==",
|
"python/iqpilot_private/navd/traffic_sources.cpython-312-aarch64-linux-gnu.so": "SzicVJ2/F8aMjcOHVCmEeJ952a+JPL8NLI6wsVkA2f5xiOSKMdynvcf7EgvrvBA4bgTRUGOmtpoqzMiCcNh2AA==",
|
||||||
"python/iqpilot_private/navd/web_server.cpython-312-aarch64-linux-gnu.so": "Qe32cW7+K4rQR6eRvi9vM8BZta5mPsK/xo9/dF4IZnfPYTP0bHzBFXZjsO4LVntwY/bUwMagp4fnRgXxwhNFCw=="
|
"python/iqpilot_private/navd/traffic_writer.cpython-312-aarch64-linux-gnu.so": "tMmnyV9knGA0eoRq1+bYLaQRAmLLrpSC9KraH9iNWMgleg+xdY3dIpx+uyP77de/oOQ2Bovsp3Vq2MobcDACCQ==",
|
||||||
|
"python/iqpilot_private/navd/turn_desire.cpython-312-aarch64-linux-gnu.so": "kFb5U48pTMYRWee+JbH6CbOpE2je60Xk5ntJZIUCw66KWLTOUGFtQqMcUUcQ1b2/3xnCz7sb3Yt0GdbyyspMDg==",
|
||||||
|
"python/iqpilot_private/navd/valhalla_process.cpython-312-aarch64-linux-gnu.so": "u6o5lRGFT3PA7XPM0IXyr7iEsngyLKqh+kJhHNW7U7+iTI3hH25ag73YFQjnCfIuzPk2NtB4v2JKqcqBaNaQAQ==",
|
||||||
|
"python/iqpilot_private/navd/web_server.cpython-312-aarch64-linux-gnu.so": "4AB7oakyIWLG7OFuGpO+SidZnJzq3rC7/uWemSbhFVn9oOZBMQZ5IWN5Y3WfImyqoZXjZVGqxE9Yf0d8gmWdDA=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
Fhs5w4K9yXGTe1Y9xpYpVEnHRHUsq4pJ0opKgllTGam0njHeskbHsYQmlj3n94vPeCJhQw52x9Bd1S2/R37WAg==
|
NH/aexXGu1jWh6ks/x7lbVEUX9VZPhETrwkIozXSjmPR2isUyVlaZppveq23NB7BeIQTJuS/+KAuZ/pbL/kaDQ==
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -129,6 +129,8 @@ class CarInterface(CarInterfaceBase):
|
|||||||
car_fw: list[structs.CarParams.CarFw], alpha_long: bool, is_release_iq: bool, docs: bool) -> structs.IQCarParams:
|
car_fw: list[structs.CarParams.CarFw], alpha_long: bool, is_release_iq: bool, docs: bool) -> structs.IQCarParams:
|
||||||
if candidate in UNSUPPORTED_DSU_CAR:
|
if candidate in UNSUPPORTED_DSU_CAR:
|
||||||
ret.iqSafetyFlags |= ToyotaSafetyFlagsIQ.UNSUPPORTED_DSU
|
ret.iqSafetyFlags |= ToyotaSafetyFlagsIQ.UNSUPPORTED_DSU
|
||||||
|
if candidate in TSS2_CAR:
|
||||||
|
ret.iqSafetyFlags |= ToyotaSafetyFlagsIQ.LKAS_HUD
|
||||||
|
|
||||||
# Detect smartDSU, which intercepts ACC_CMD from the DSU (or radar) allowing openpilot to send it
|
# Detect smartDSU, which intercepts ACC_CMD from the DSU (or radar) allowing openpilot to send it
|
||||||
# 0x2AA is sent by a similar device which intercepts the radar instead of DSU on NO_DSU_CARs
|
# 0x2AA is sent by a similar device which intercepts the radar instead of DSU on NO_DSU_CARs
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from iqdbc.car import gen_empty_fingerprint, structs
|
from iqdbc.car import gen_empty_fingerprint, structs
|
||||||
from iqdbc.car.toyota.interface import CarInterface
|
from iqdbc.car.toyota.interface import CarInterface
|
||||||
from iqdbc.car.toyota.values import CAR, ToyotaFlags
|
from iqdbc.car.toyota.values import CAR, ToyotaFlags
|
||||||
from iqdbc.lvbs.car.toyota.values import ToyotaFlagsIQ
|
from iqdbc.lvbs.car.toyota.values import ToyotaFlagsIQ, ToyotaSafetyFlagsIQ
|
||||||
|
|
||||||
|
|
||||||
def test_secoc_toyota_not_dashcam_on_release():
|
def test_secoc_toyota_not_dashcam_on_release():
|
||||||
@@ -34,3 +34,11 @@ def test_smart_dsu_clears_disable_radar_on_radar_acc_toyota():
|
|||||||
assert not (cp.flags & ToyotaFlags.DISABLE_RADAR.value)
|
assert not (cp.flags & ToyotaFlags.DISABLE_RADAR.value)
|
||||||
assert cp.alphaLongitudinalAvailable
|
assert cp.alphaLongitudinalAvailable
|
||||||
assert cp.openpilotLongitudinalControl
|
assert cp.openpilotLongitudinalControl
|
||||||
|
|
||||||
|
|
||||||
|
def test_lkas_hud_safety_flag_tracks_tss2():
|
||||||
|
for candidate, expected in ((CAR.TOYOTA_CHR_TSS2, True), (CAR.TOYOTA_PRIUS_V, False)):
|
||||||
|
fingerprint = gen_empty_fingerprint()
|
||||||
|
cp = CarInterface.get_params(candidate, fingerprint, [], False, False, False)
|
||||||
|
cp_iq = CarInterface.get_params_iq(cp, candidate, fingerprint, [], False, False, False)
|
||||||
|
assert bool(cp_iq.iqSafetyFlags & ToyotaSafetyFlagsIQ.LKAS_HUD) is expected
|
||||||
|
|||||||
@@ -679,7 +679,7 @@ class CarState(CarStateBase):
|
|||||||
if self.CP.carFingerprint == CAR.PORSCHE_MACAN_MK1:
|
if self.CP.carFingerprint == CAR.PORSCHE_MACAN_MK1:
|
||||||
ret.gearShifter = self.parse_gear_shifter(self.CCP.shifter_values.get(pt_cp.vl["Getriebe_03"]["GE_Waehlhebel"], None))
|
ret.gearShifter = self.parse_gear_shifter(self.CCP.shifter_values.get(pt_cp.vl["Getriebe_03"]["GE_Waehlhebel"], None))
|
||||||
elif self.CP.transmissionType == TransmissionType.manual:
|
elif self.CP.transmissionType == TransmissionType.manual:
|
||||||
reverse = bool(pt_cp.vl["Gateway_05"]["BCM1_Rueckfahrlicht_Schalter"])
|
reverse = bool(br_cp.vl["Gateway_05"]["BCM1_Rueckfahrlicht_Schalter"])
|
||||||
ret.gearShifter = GearShifter.reverse if reverse else GearShifter.drive
|
ret.gearShifter = GearShifter.reverse if reverse else GearShifter.drive
|
||||||
else:
|
else:
|
||||||
ret.gearShifter = GearShifter.drive
|
ret.gearShifter = GearShifter.drive
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from iqdbc.car.volkswagen.carcontroller import CarController
|
|||||||
from iqdbc.car.volkswagen.carstate import CarState
|
from iqdbc.car.volkswagen.carstate import CarState
|
||||||
from iqdbc.car.volkswagen.values import (
|
from iqdbc.car.volkswagen.values import (
|
||||||
CAR, CanBus, DashcamOnlyReason, MLB_ACC_COORDINATOR_MSGS, MLB_GEARBOX_MSGS, MLB_MSG_ACC_10,
|
CAR, CanBus, DashcamOnlyReason, MLB_ACC_COORDINATOR_MSGS, MLB_GEARBOX_MSGS, MLB_MSG_ACC_10,
|
||||||
MLB_MSG_LH_EPS_03, NetworkLocation, RADAR_DISABLE_STATE, TransmissionType,
|
MLB_MSG_GATEWAY_05, MLB_MSG_LH_EPS_03, NetworkLocation, RADAR_DISABLE_STATE, TransmissionType,
|
||||||
VolkswagenFlags, VolkswagenSafetyFlags, VolkswagenFlagsIQ, get_longitudinal_stopping_speed_override,
|
VolkswagenFlags, VolkswagenSafetyFlags, VolkswagenFlagsIQ, get_longitudinal_stopping_speed_override,
|
||||||
)
|
)
|
||||||
from iqdbc.car.volkswagen.radar_interface import RadarInterface
|
from iqdbc.car.volkswagen.radar_interface import RadarInterface
|
||||||
@@ -115,7 +115,11 @@ class CarInterface(CarInterfaceBase):
|
|||||||
if fingerprinted and MLB_MSG_LH_EPS_03 not in pt_msgs:
|
if fingerprinted and MLB_MSG_LH_EPS_03 not in pt_msgs:
|
||||||
ret.flags |= VolkswagenFlagsIQ.IQ_MLB_NO_HCA_EPS.value
|
ret.flags |= VolkswagenFlagsIQ.IQ_MLB_NO_HCA_EPS.value
|
||||||
|
|
||||||
if fingerprinted and not any(msg in pt_msgs for msg in MLB_GEARBOX_MSGS):
|
all_msgs = ecan_msgs | fingerprint[1]
|
||||||
|
gearbox_seen = any(msg in all_msgs for msg in MLB_GEARBOX_MSGS)
|
||||||
|
transmission_ecu = any(fw.ecu == structs.CarParams.Ecu.transmission for fw in car_fw)
|
||||||
|
reverse_switch_seen = MLB_MSG_GATEWAY_05 in fingerprint[1]
|
||||||
|
if fingerprinted and not gearbox_seen and not transmission_ecu and reverse_switch_seen:
|
||||||
ret.transmissionType = TransmissionType.manual
|
ret.transmissionType = TransmissionType.manual
|
||||||
|
|
||||||
elif ret.flags & (VolkswagenFlags.MEB | VolkswagenFlags.MQB_EVO):
|
elif ret.flags & (VolkswagenFlags.MEB | VolkswagenFlags.MQB_EVO):
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ from iqdbc.car import Bus, DT_CTRL, structs
|
|||||||
from iqdbc.car.volkswagen.carstate import CarState
|
from iqdbc.car.volkswagen.carstate import CarState
|
||||||
from iqdbc.car.structs import CarParams
|
from iqdbc.car.structs import CarParams
|
||||||
from iqdbc.car.volkswagen.interface import CarInterface
|
from iqdbc.car.volkswagen.interface import CarInterface
|
||||||
from iqdbc.car.volkswagen.values import (CAR, FW_QUERY_CONFIG, MLB_ACC_COORDINATOR_MSGS, MLB_MSG_ACC_10,
|
from iqdbc.car.volkswagen.values import (CAR, FW_QUERY_CONFIG, MLB_ACC_COORDINATOR_MSGS, MLB_GEARBOX_MSGS, MLB_MSG_ACC_10,
|
||||||
MLB_MSG_LH_EPS_03, WMI, VolkswagenFlags, VolkswagenFlagsIQ,
|
MLB_MSG_GATEWAY_05, MLB_MSG_GETRIEBE_01, MLB_MSG_LH_EPS_03, WMI, VolkswagenFlags,
|
||||||
VolkswagenSafetyFlags)
|
VolkswagenFlagsIQ, VolkswagenSafetyFlags)
|
||||||
from iqdbc.car.volkswagen.fingerprints import FW_VERSIONS
|
from iqdbc.car.volkswagen.fingerprints import FW_VERSIONS
|
||||||
|
|
||||||
Ecu = CarParams.Ecu
|
Ecu = CarParams.Ecu
|
||||||
@@ -333,6 +333,58 @@ def test_mlb_manual_gear_follows_the_reverse_light_switch():
|
|||||||
assert _run(a4, lambda: _a4_mk4_frames(packer, reverse=False)).gearShifter == structs.CarState.GearShifter.drive
|
assert _run(a4, lambda: _a4_mk4_frames(packer, reverse=False)).gearShifter == structs.CarState.GearShifter.drive
|
||||||
|
|
||||||
|
|
||||||
|
def _q5_params(bus0, bus1=(), car_fw=()):
|
||||||
|
fingerprints = _mlb_fingerprint(0, bus0)
|
||||||
|
fingerprints[1] = {msg: 8 for msg in bus1}
|
||||||
|
fingerprints[2] = {msg: 8 for msg in MLB_ECAN_CAMERA}
|
||||||
|
return CarInterface.get_params(CAR.AUDI_Q5_MK1, fingerprints, list(car_fw), alpha_long=False, is_release=False, docs=False)
|
||||||
|
|
||||||
|
|
||||||
|
MLB_ECAN_GATEWAY_NO_GEARBOX = tuple(msg for msg in MLB_ECAN_GATEWAY if msg not in MLB_GEARBOX_MSGS)
|
||||||
|
|
||||||
|
|
||||||
|
def test_mlb_gearbox_on_the_powertrain_bus_keeps_automatic():
|
||||||
|
params = _q5_params(MLB_ECAN_GATEWAY_NO_GEARBOX, bus1=(MLB_MSG_GETRIEBE_01, MLB_MSG_GATEWAY_05))
|
||||||
|
assert params.transmissionType == CarParams.TransmissionType.automatic
|
||||||
|
|
||||||
|
|
||||||
|
def test_mlb_transmission_ecu_firmware_keeps_automatic():
|
||||||
|
transmission = CarParams.CarFw.new_message(ecu=Ecu.transmission, address=0x7e1)
|
||||||
|
params = _q5_params(MLB_ECAN_GATEWAY_NO_GEARBOX, bus1=(MLB_MSG_GATEWAY_05,), car_fw=(transmission,))
|
||||||
|
assert params.transmissionType == CarParams.TransmissionType.automatic
|
||||||
|
|
||||||
|
|
||||||
|
def test_mlb_reverse_switch_on_the_extended_can_alone_keeps_automatic():
|
||||||
|
params = _q5_params(MLB_ECAN_GATEWAY_NO_GEARBOX + (MLB_MSG_GATEWAY_05,))
|
||||||
|
assert params.transmissionType == CarParams.TransmissionType.automatic
|
||||||
|
|
||||||
|
|
||||||
|
def test_mlb_manual_needs_no_gearbox_anywhere_and_a_reverse_switch_on_the_powertrain_bus():
|
||||||
|
params = _q5_params(MLB_ECAN_GATEWAY_NO_GEARBOX, bus1=(MLB_MSG_GATEWAY_05,))
|
||||||
|
assert params.transmissionType == CarParams.TransmissionType.manual
|
||||||
|
|
||||||
|
|
||||||
|
def test_mlb_manual_gateway_car_reads_reverse_from_the_powertrain_bus():
|
||||||
|
fingerprints = _mlb_fingerprint(0, MLB_ECAN_GATEWAY_NO_GEARBOX)
|
||||||
|
fingerprints[1] = {MLB_MSG_GATEWAY_05: 8}
|
||||||
|
fingerprints[2] = {msg: 8 for msg in MLB_ECAN_CAMERA}
|
||||||
|
q5 = _build_mlb_car(CAR.AUDI_Q5_MK1, fingerprints)
|
||||||
|
assert q5.CP.transmissionType == CarParams.TransmissionType.manual
|
||||||
|
|
||||||
|
packer = CANPacker("vw_mlb")
|
||||||
|
frames = lambda reverse: [packer.make_can_msg("Gateway_05", 1, {"BCM1_Rueckfahrlicht_Schalter": int(reverse)})]
|
||||||
|
assert _run(q5, lambda: frames(True)).gearShifter == structs.CarState.GearShifter.reverse
|
||||||
|
assert _run(q5, lambda: frames(False)).gearShifter == structs.CarState.GearShifter.drive
|
||||||
|
assert MLB_MSG_GATEWAY_05 not in q5.can_parsers[Bus.pt].addresses
|
||||||
|
|
||||||
|
|
||||||
|
def test_mlb_automatic_never_subscribes_gateway_05():
|
||||||
|
q5 = _q5_mk1_car()
|
||||||
|
q5.update([(int(DT_CTRL * 1e9), [])])
|
||||||
|
assert MLB_MSG_GATEWAY_05 not in q5.can_parsers[Bus.pt].addresses
|
||||||
|
assert MLB_MSG_GATEWAY_05 not in q5.can_parsers[Bus.aux].addresses
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("button_type", (
|
@pytest.mark.parametrize("button_type", (
|
||||||
structs.CarState.ButtonEvent.Type.setCruise,
|
structs.CarState.ButtonEvent.Type.setCruise,
|
||||||
structs.CarState.ButtonEvent.Type.resumeCruise,
|
structs.CarState.ButtonEvent.Type.resumeCruise,
|
||||||
|
|||||||
@@ -348,6 +348,7 @@ MLB_MSG_ACC_01 = 0x109
|
|||||||
MLB_MSG_ACC_05 = 0x10D
|
MLB_MSG_ACC_05 = 0x10D
|
||||||
MLB_MSG_ACC_02 = 0x30C
|
MLB_MSG_ACC_02 = 0x30C
|
||||||
MLB_MSG_ACC_10 = 0x117
|
MLB_MSG_ACC_10 = 0x117
|
||||||
|
MLB_MSG_GATEWAY_05 = 0x39C
|
||||||
|
|
||||||
MLB_ACC_COORDINATOR_MSGS = (MLB_MSG_ACC_01, MLB_MSG_ACC_05, MLB_MSG_ACC_02)
|
MLB_ACC_COORDINATOR_MSGS = (MLB_MSG_ACC_01, MLB_MSG_ACC_05, MLB_MSG_ACC_02)
|
||||||
MLB_GEARBOX_MSGS = (MLB_MSG_GETRIEBE_01, MLB_MSG_GETRIEBE_02, MLB_MSG_GETRIEBE_03, MLB_MSG_GETRIEBE_04)
|
MLB_GEARBOX_MSGS = (MLB_MSG_GETRIEBE_01, MLB_MSG_GETRIEBE_02, MLB_MSG_GETRIEBE_03, MLB_MSG_GETRIEBE_04)
|
||||||
|
|||||||
@@ -17,5 +17,5 @@ class ToyotaSafetyFlagsIQ:
|
|||||||
DEFAULT = 0
|
DEFAULT = 0
|
||||||
UNSUPPORTED_DSU = 1
|
UNSUPPORTED_DSU = 1
|
||||||
GAS_INTERCEPTOR = 2
|
GAS_INTERCEPTOR = 2
|
||||||
|
LKAS_HUD = 4
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,6 @@
|
|||||||
#define TOYOTA_COMMON_RX_CHECKS(lta) \
|
#define TOYOTA_COMMON_RX_CHECKS(lta) \
|
||||||
{.msg = {{ 0xaa, 0, 8, 83U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
{.msg = {{ 0xaa, 0, 8, 83U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||||
{.msg = {{0x260, 0, 8, 50U, .ignore_counter = true, .ignore_quality_flag=!(lta)}, { 0 }, { 0 }}}, \
|
{.msg = {{0x260, 0, 8, 50U, .ignore_counter = true, .ignore_quality_flag=!(lta)}, { 0 }, { 0 }}}, \
|
||||||
{.msg = {{0x412, 2, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 1U}, { 0 }, { 0 }}}, \
|
|
||||||
|
|
||||||
#define TOYOTA_RX_CHECKS(lta) \
|
#define TOYOTA_RX_CHECKS(lta) \
|
||||||
TOYOTA_COMMON_RX_CHECKS(lta) \
|
TOYOTA_COMMON_RX_CHECKS(lta) \
|
||||||
@@ -66,6 +65,9 @@
|
|||||||
#define TOYOTA_GAS_INTERCEPTOR_ADDR_CHECK \
|
#define TOYOTA_GAS_INTERCEPTOR_ADDR_CHECK \
|
||||||
{.msg = {{0x201, 0, 6, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
{.msg = {{0x201, 0, 6, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||||
|
|
||||||
|
#define TOYOTA_LKAS_HUD_ADDR_CHECK \
|
||||||
|
{.msg = {{0x412, 2, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 1U}, { 0 }, { 0 }}}, \
|
||||||
|
|
||||||
static bool toyota_secoc = false;
|
static bool toyota_secoc = false;
|
||||||
static bool toyota_alt_brake = false;
|
static bool toyota_alt_brake = false;
|
||||||
static bool toyota_stock_longitudinal = false;
|
static bool toyota_stock_longitudinal = false;
|
||||||
@@ -433,6 +435,7 @@ static safety_config toyota_init(uint16_t param) {
|
|||||||
|
|
||||||
const uint16_t TOYOTA_PARAM_IQ_UNSUPPORTED_DSU = 1;
|
const uint16_t TOYOTA_PARAM_IQ_UNSUPPORTED_DSU = 1;
|
||||||
const uint16_t TOYTOA_PARAM_IQ_GAS_INTERCEPTOR = 2;
|
const uint16_t TOYTOA_PARAM_IQ_GAS_INTERCEPTOR = 2;
|
||||||
|
const uint16_t TOYOTA_PARAM_IQ_LKAS_HUD = 4;
|
||||||
|
|
||||||
#ifdef ALLOW_DEBUG
|
#ifdef ALLOW_DEBUG
|
||||||
const uint32_t TOYOTA_PARAM_SECOC = 8UL << TOYOTA_PARAM_OFFSET;
|
const uint32_t TOYOTA_PARAM_SECOC = 8UL << TOYOTA_PARAM_OFFSET;
|
||||||
@@ -446,6 +449,7 @@ static safety_config toyota_init(uint16_t param) {
|
|||||||
|
|
||||||
const bool toyota_unsupported_dsu = GET_FLAG(current_safety_param_iq, TOYOTA_PARAM_IQ_UNSUPPORTED_DSU);
|
const bool toyota_unsupported_dsu = GET_FLAG(current_safety_param_iq, TOYOTA_PARAM_IQ_UNSUPPORTED_DSU);
|
||||||
enable_gas_interceptor = GET_FLAG(current_safety_param_iq, TOYTOA_PARAM_IQ_GAS_INTERCEPTOR);
|
enable_gas_interceptor = GET_FLAG(current_safety_param_iq, TOYTOA_PARAM_IQ_GAS_INTERCEPTOR);
|
||||||
|
const bool toyota_lkas_hud = GET_FLAG(current_safety_param_iq, TOYOTA_PARAM_IQ_LKAS_HUD);
|
||||||
|
|
||||||
// gas interceptor should not be used if openpilot is not controlling longitudinal or is a TSK car
|
// gas interceptor should not be used if openpilot is not controlling longitudinal or is a TSK car
|
||||||
if (toyota_stock_longitudinal || toyota_secoc) {
|
if (toyota_stock_longitudinal || toyota_secoc) {
|
||||||
@@ -471,6 +475,7 @@ static safety_config toyota_init(uint16_t param) {
|
|||||||
static RxCheck toyota_secoc_rx_checks[] = {
|
static RxCheck toyota_secoc_rx_checks[] = {
|
||||||
TOYOTA_SECOC_RX_CHECKS
|
TOYOTA_SECOC_RX_CHECKS
|
||||||
TOYOTA_PCM_CRUISE_2_ADDR_CHECK
|
TOYOTA_PCM_CRUISE_2_ADDR_CHECK
|
||||||
|
TOYOTA_LKAS_HUD_ADDR_CHECK
|
||||||
};
|
};
|
||||||
|
|
||||||
SET_RX_CHECKS(toyota_secoc_rx_checks, ret);
|
SET_RX_CHECKS(toyota_secoc_rx_checks, ret);
|
||||||
@@ -479,6 +484,7 @@ static safety_config toyota_init(uint16_t param) {
|
|||||||
static RxCheck toyota_lta_rx_checks[] = {
|
static RxCheck toyota_lta_rx_checks[] = {
|
||||||
TOYOTA_RX_CHECKS(true)
|
TOYOTA_RX_CHECKS(true)
|
||||||
TOYOTA_PCM_CRUISE_2_ADDR_CHECK
|
TOYOTA_PCM_CRUISE_2_ADDR_CHECK
|
||||||
|
TOYOTA_LKAS_HUD_ADDR_CHECK
|
||||||
};
|
};
|
||||||
|
|
||||||
SET_RX_CHECKS(toyota_lta_rx_checks, ret);
|
SET_RX_CHECKS(toyota_lta_rx_checks, ret);
|
||||||
@@ -486,18 +492,22 @@ static safety_config toyota_init(uint16_t param) {
|
|||||||
static RxCheck toyota_lka_rx_checks[] = {
|
static RxCheck toyota_lka_rx_checks[] = {
|
||||||
TOYOTA_RX_CHECKS(false)
|
TOYOTA_RX_CHECKS(false)
|
||||||
TOYOTA_PCM_CRUISE_2_ADDR_CHECK
|
TOYOTA_PCM_CRUISE_2_ADDR_CHECK
|
||||||
|
TOYOTA_LKAS_HUD_ADDR_CHECK
|
||||||
};
|
};
|
||||||
static RxCheck toyota_lka_alt_brake_rx_checks[] = {
|
static RxCheck toyota_lka_alt_brake_rx_checks[] = {
|
||||||
TOYOTA_ALT_BRAKE_RX_CHECKS(false)
|
TOYOTA_ALT_BRAKE_RX_CHECKS(false)
|
||||||
TOYOTA_PCM_CRUISE_2_ADDR_CHECK
|
TOYOTA_PCM_CRUISE_2_ADDR_CHECK
|
||||||
|
TOYOTA_LKAS_HUD_ADDR_CHECK
|
||||||
};
|
};
|
||||||
static RxCheck toyota_lka_unsupported_dsu_rx_checks[] = {
|
static RxCheck toyota_lka_unsupported_dsu_rx_checks[] = {
|
||||||
TOYOTA_RX_CHECKS(false)
|
TOYOTA_RX_CHECKS(false)
|
||||||
TOYOTA_DSU_CRUISE_ADDR_CHECK
|
TOYOTA_DSU_CRUISE_ADDR_CHECK
|
||||||
|
TOYOTA_LKAS_HUD_ADDR_CHECK
|
||||||
};
|
};
|
||||||
static RxCheck toyota_lka_alt_brake_unsupported_dsu_rx_checks[] = {
|
static RxCheck toyota_lka_alt_brake_unsupported_dsu_rx_checks[] = {
|
||||||
TOYOTA_ALT_BRAKE_RX_CHECKS(false)
|
TOYOTA_ALT_BRAKE_RX_CHECKS(false)
|
||||||
TOYOTA_DSU_CRUISE_ADDR_CHECK
|
TOYOTA_DSU_CRUISE_ADDR_CHECK
|
||||||
|
TOYOTA_LKAS_HUD_ADDR_CHECK
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!toyota_alt_brake) {
|
if (!toyota_alt_brake) {
|
||||||
@@ -523,6 +533,7 @@ static safety_config toyota_init(uint16_t param) {
|
|||||||
TOYOTA_RX_CHECKS(true)
|
TOYOTA_RX_CHECKS(true)
|
||||||
TOYOTA_PCM_CRUISE_2_ADDR_CHECK
|
TOYOTA_PCM_CRUISE_2_ADDR_CHECK
|
||||||
TOYOTA_GAS_INTERCEPTOR_ADDR_CHECK
|
TOYOTA_GAS_INTERCEPTOR_ADDR_CHECK
|
||||||
|
TOYOTA_LKAS_HUD_ADDR_CHECK
|
||||||
};
|
};
|
||||||
|
|
||||||
SET_RX_CHECKS(toyota_lta_interceptor_rx_checks, ret);
|
SET_RX_CHECKS(toyota_lta_interceptor_rx_checks, ret);
|
||||||
@@ -531,21 +542,25 @@ static safety_config toyota_init(uint16_t param) {
|
|||||||
TOYOTA_RX_CHECKS(false)
|
TOYOTA_RX_CHECKS(false)
|
||||||
TOYOTA_PCM_CRUISE_2_ADDR_CHECK
|
TOYOTA_PCM_CRUISE_2_ADDR_CHECK
|
||||||
TOYOTA_GAS_INTERCEPTOR_ADDR_CHECK
|
TOYOTA_GAS_INTERCEPTOR_ADDR_CHECK
|
||||||
|
TOYOTA_LKAS_HUD_ADDR_CHECK
|
||||||
};
|
};
|
||||||
static RxCheck toyota_lka_alt_brake_interceptor_rx_checks[] = {
|
static RxCheck toyota_lka_alt_brake_interceptor_rx_checks[] = {
|
||||||
TOYOTA_ALT_BRAKE_RX_CHECKS(false)
|
TOYOTA_ALT_BRAKE_RX_CHECKS(false)
|
||||||
TOYOTA_PCM_CRUISE_2_ADDR_CHECK
|
TOYOTA_PCM_CRUISE_2_ADDR_CHECK
|
||||||
TOYOTA_GAS_INTERCEPTOR_ADDR_CHECK
|
TOYOTA_GAS_INTERCEPTOR_ADDR_CHECK
|
||||||
|
TOYOTA_LKAS_HUD_ADDR_CHECK
|
||||||
};
|
};
|
||||||
static RxCheck toyota_lka_unsupported_dsu_interceptor_rx_checks[] = {
|
static RxCheck toyota_lka_unsupported_dsu_interceptor_rx_checks[] = {
|
||||||
TOYOTA_RX_CHECKS(false)
|
TOYOTA_RX_CHECKS(false)
|
||||||
TOYOTA_DSU_CRUISE_ADDR_CHECK
|
TOYOTA_DSU_CRUISE_ADDR_CHECK
|
||||||
TOYOTA_GAS_INTERCEPTOR_ADDR_CHECK
|
TOYOTA_GAS_INTERCEPTOR_ADDR_CHECK
|
||||||
|
TOYOTA_LKAS_HUD_ADDR_CHECK
|
||||||
};
|
};
|
||||||
static RxCheck toyota_lka_alt_brake_unsupported_dsu_interceptor_rx_checks[] = {
|
static RxCheck toyota_lka_alt_brake_unsupported_dsu_interceptor_rx_checks[] = {
|
||||||
TOYOTA_ALT_BRAKE_RX_CHECKS(false)
|
TOYOTA_ALT_BRAKE_RX_CHECKS(false)
|
||||||
TOYOTA_DSU_CRUISE_ADDR_CHECK
|
TOYOTA_DSU_CRUISE_ADDR_CHECK
|
||||||
TOYOTA_GAS_INTERCEPTOR_ADDR_CHECK
|
TOYOTA_GAS_INTERCEPTOR_ADDR_CHECK
|
||||||
|
TOYOTA_LKAS_HUD_ADDR_CHECK
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!toyota_alt_brake) {
|
if (!toyota_alt_brake) {
|
||||||
@@ -564,6 +579,10 @@ static safety_config toyota_init(uint16_t param) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!toyota_lkas_hud) {
|
||||||
|
ret.rx_checks_len -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ TOYOTA_COMMON_LONG_TX_MSGS = [[0x283, 0], [0x2E6, 0], [0x2E7, 0], [0x33E, 0], [0
|
|||||||
GAS_INTERCEPTOR_TX_MSGS = [[0x200, 0]]
|
GAS_INTERCEPTOR_TX_MSGS = [[0x200, 0]]
|
||||||
|
|
||||||
UNSUPPORTED_DSU = [
|
UNSUPPORTED_DSU = [
|
||||||
{"SAFETY_PARAM_IQ": ToyotaSafetyFlagsIQ.DEFAULT},
|
{"SAFETY_PARAM_IQ": ToyotaSafetyFlagsIQ.LKAS_HUD},
|
||||||
{"SAFETY_PARAM_IQ": ToyotaSafetyFlagsIQ.UNSUPPORTED_DSU},
|
{"SAFETY_PARAM_IQ": ToyotaSafetyFlagsIQ.UNSUPPORTED_DSU | ToyotaSafetyFlagsIQ.LKAS_HUD},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ class TestToyotaSafetyBase(common.CarSafetyTest, common.LongitudinalAccelSafetyT
|
|||||||
FWD_BLACKLISTED_ADDRS = {2: [0x2E4, 0x412, 0x191, 0x343]}
|
FWD_BLACKLISTED_ADDRS = {2: [0x2E4, 0x412, 0x191, 0x343]}
|
||||||
EPS_SCALE = 73
|
EPS_SCALE = 73
|
||||||
|
|
||||||
SAFETY_PARAM_IQ: int = 0
|
SAFETY_PARAM_IQ: int = ToyotaSafetyFlagsIQ.LKAS_HUD
|
||||||
|
|
||||||
packer: CANPackerSafety
|
packer: CANPackerSafety
|
||||||
safety: libsafety_py.LibSafety
|
safety: libsafety_py.LibSafety
|
||||||
@@ -96,6 +96,9 @@ class TestToyotaSafetyBase(common.CarSafetyTest, common.LongitudinalAccelSafetyT
|
|||||||
return self.packer.make_can_msg_safety("LKAS_HUD", 2, values)
|
return self.packer.make_can_msg_safety("LKAS_HUD", 2, values)
|
||||||
|
|
||||||
def test_enable_control_allowed_with_aol_button(self):
|
def test_enable_control_allowed_with_aol_button(self):
|
||||||
|
self.safety.set_current_safety_param_iq(self.SAFETY_PARAM_IQ | ToyotaSafetyFlagsIQ.LKAS_HUD)
|
||||||
|
self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, self.safety.get_current_safety_param())
|
||||||
|
self.safety.init_tests()
|
||||||
for enable_aol in (True, False):
|
for enable_aol in (True, False):
|
||||||
with self.subTest("enable_aol", aol_enabled=enable_aol):
|
with self.subTest("enable_aol", aol_enabled=enable_aol):
|
||||||
self.safety.set_aol_params(enable_aol, False, False)
|
self.safety.set_aol_params(enable_aol, False, False)
|
||||||
@@ -120,6 +123,16 @@ class TestToyotaSafetyBase(common.CarSafetyTest, common.LongitudinalAccelSafetyT
|
|||||||
self.safety.set_controls_allowed_lat(False)
|
self.safety.set_controls_allowed_lat(False)
|
||||||
self.safety.set_aol_params(False, False, False)
|
self.safety.set_aol_params(False, False, False)
|
||||||
|
|
||||||
|
def test_lkas_button_requires_lkas_hud(self):
|
||||||
|
self.safety.set_current_safety_param_iq(self.SAFETY_PARAM_IQ & ~ToyotaSafetyFlagsIQ.LKAS_HUD)
|
||||||
|
self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, self.safety.get_current_safety_param())
|
||||||
|
self.safety.init_tests()
|
||||||
|
self.safety.set_aol_params(True, False, False)
|
||||||
|
button_state = self.safety.get_aol_button_press()
|
||||||
|
self._rx(self._lkas_button_msg(True))
|
||||||
|
self.assertEqual(button_state, self.safety.get_aol_button_press())
|
||||||
|
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||||
|
|
||||||
def test_diagnostics(self, stock_longitudinal: bool = False, ecu_disabled: bool = True):
|
def test_diagnostics(self, stock_longitudinal: bool = False, ecu_disabled: bool = True):
|
||||||
for should_tx, msg in ((False, b"\x6D\x02\x3E\x00\x00\x00\x00\x00"), # fwdCamera tester present
|
for should_tx, msg in ((False, b"\x6D\x02\x3E\x00\x00\x00\x00\x00"), # fwdCamera tester present
|
||||||
(False, b"\x0F\x03\xAA\xAA\x00\x00\x00\x00"), # non-tester present
|
(False, b"\x0F\x03\xAA\xAA\x00\x00\x00\x00"), # non-tester present
|
||||||
@@ -250,6 +263,7 @@ class TestToyotaSafetyAngle(TestToyotaSafetyBase, common.AngleSteeringSafetyTest
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.packer = CANPackerSafety("toyota_nodsu_pt_generated")
|
self.packer = CANPackerSafety("toyota_nodsu_pt_generated")
|
||||||
self.safety = libsafety_py.libsafety
|
self.safety = libsafety_py.libsafety
|
||||||
|
self.safety.set_current_safety_param_iq(self.SAFETY_PARAM_IQ)
|
||||||
self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, self.EPS_SCALE | ToyotaSafetyFlags.LTA)
|
self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, self.EPS_SCALE | ToyotaSafetyFlags.LTA)
|
||||||
self.safety.init_tests()
|
self.safety.init_tests()
|
||||||
|
|
||||||
@@ -431,6 +445,7 @@ class TestToyotaStockLongitudinalAngle(TestToyotaStockLongitudinalBase, TestToyo
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.packer = CANPackerSafety("toyota_nodsu_pt_generated")
|
self.packer = CANPackerSafety("toyota_nodsu_pt_generated")
|
||||||
self.safety = libsafety_py.libsafety
|
self.safety = libsafety_py.libsafety
|
||||||
|
self.safety.set_current_safety_param_iq(self.SAFETY_PARAM_IQ)
|
||||||
self.safety.set_safety_hooks(CarParams.SafetyModel.toyota,
|
self.safety.set_safety_hooks(CarParams.SafetyModel.toyota,
|
||||||
self.EPS_SCALE | ToyotaSafetyFlags.STOCK_LONGITUDINAL | ToyotaSafetyFlags.LTA)
|
self.EPS_SCALE | ToyotaSafetyFlags.STOCK_LONGITUDINAL | ToyotaSafetyFlags.LTA)
|
||||||
self.safety.init_tests()
|
self.safety.init_tests()
|
||||||
@@ -445,6 +460,7 @@ class TestToyotaSecOcSafetyBase(TestToyotaSafetyBase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.packer = CANPackerSafety("toyota_secoc_pt_generated")
|
self.packer = CANPackerSafety("toyota_secoc_pt_generated")
|
||||||
self.safety = libsafety_py.libsafety
|
self.safety = libsafety_py.libsafety
|
||||||
|
self.safety.set_current_safety_param_iq(self.SAFETY_PARAM_IQ)
|
||||||
self.safety.set_safety_hooks(CarParams.SafetyModel.toyota,
|
self.safety.set_safety_hooks(CarParams.SafetyModel.toyota,
|
||||||
self.EPS_SCALE | ToyotaSafetyFlags.SECOC)
|
self.EPS_SCALE | ToyotaSafetyFlags.SECOC)
|
||||||
self.safety.init_tests()
|
self.safety.init_tests()
|
||||||
@@ -485,6 +501,7 @@ class TestToyotaSecOcSafetyStockLongitudinal(TestToyotaSecOcSafetyBase, TestToyo
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.packer = CANPackerSafety("toyota_secoc_pt_generated")
|
self.packer = CANPackerSafety("toyota_secoc_pt_generated")
|
||||||
self.safety = libsafety_py.libsafety
|
self.safety = libsafety_py.libsafety
|
||||||
|
self.safety.set_current_safety_param_iq(self.SAFETY_PARAM_IQ)
|
||||||
self.safety.set_safety_hooks(CarParams.SafetyModel.toyota,
|
self.safety.set_safety_hooks(CarParams.SafetyModel.toyota,
|
||||||
self.EPS_SCALE | ToyotaSafetyFlags.STOCK_LONGITUDINAL | ToyotaSafetyFlags.SECOC)
|
self.EPS_SCALE | ToyotaSafetyFlags.STOCK_LONGITUDINAL | ToyotaSafetyFlags.SECOC)
|
||||||
self.safety.init_tests()
|
self.safety.init_tests()
|
||||||
@@ -498,6 +515,7 @@ class TestToyotaSecOcSafety(TestToyotaSecOcSafetyBase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.packer = CANPackerSafety("toyota_secoc_pt_generated")
|
self.packer = CANPackerSafety("toyota_secoc_pt_generated")
|
||||||
self.safety = libsafety_py.libsafety
|
self.safety = libsafety_py.libsafety
|
||||||
|
self.safety.set_current_safety_param_iq(self.SAFETY_PARAM_IQ)
|
||||||
self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, self.EPS_SCALE | ToyotaSafetyFlags.SECOC)
|
self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, self.EPS_SCALE | ToyotaSafetyFlags.SECOC)
|
||||||
self.safety.init_tests()
|
self.safety.init_tests()
|
||||||
|
|
||||||
|
|||||||
@@ -249,6 +249,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
|||||||
{"MacModelFailed", {CLEAR_ON_MANAGER_START, BOOL}},
|
{"MacModelFailed", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"MacModelLastError", {CLEAR_ON_MANAGER_START, STRING}},
|
{"MacModelLastError", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
{"MacModelLatencyMs", {CLEAR_ON_MANAGER_START, FLOAT, "0.0"}},
|
{"MacModelLatencyMs", {CLEAR_ON_MANAGER_START, FLOAT, "0.0"}},
|
||||||
|
{"MacModelRetryBackoff", {CLEAR_ON_MANAGER_START, STRING, "10.0"}},
|
||||||
|
|
||||||
// comma USB eGPU big-model backend. Mutually exclusive with eMac at
|
// comma USB eGPU big-model backend. Mutually exclusive with eMac at
|
||||||
// runtime (eMac wins). UsbGpu* naming/flags mirror comma's handover branch
|
// runtime (eMac wins). UsbGpu* naming/flags mirror comma's handover branch
|
||||||
@@ -363,6 +364,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
|||||||
{"IQLateralCurvatureLookahead", {PERSISTENT, BOOL, "0"}},
|
{"IQLateralCurvatureLookahead", {PERSISTENT, BOOL, "0"}},
|
||||||
{"IQSoftwareSteerDelay", {PERSISTENT, FLOAT, "0.2"}},
|
{"IQSoftwareSteerDelay", {PERSISTENT, FLOAT, "0.2"}},
|
||||||
{"IQSteerDelayCache", {PERSISTENT, FLOAT, "0.2"}},
|
{"IQSteerDelayCache", {PERSISTENT, FLOAT, "0.2"}},
|
||||||
|
{"IQLatJerkGain", {PERSISTENT, STRING, "1.0"}},
|
||||||
{"LaneChangeBsd", {PERSISTENT, INT, "0"}}, // -1 ignore BSD, 0 default, 1 block lane change on BSD
|
{"LaneChangeBsd", {PERSISTENT, INT, "0"}}, // -1 ignore BSD, 0 default, 1 block lane change on BSD
|
||||||
{"LaneChangeContinuous", {PERSISTENT, BOOL, "0"}}, // 0 one-shot per blinker, 1 chain on held blinker (torque-gated)
|
{"LaneChangeContinuous", {PERSISTENT, BOOL, "0"}}, // 0 one-shot per blinker, 1 chain on held blinker (torque-gated)
|
||||||
{"LaneChangeDelay", {PERSISTENT, FLOAT, "0.0"}}, // tenths of a second; scaled by 0.1 in desire_helper
|
{"LaneChangeDelay", {PERSISTENT, FLOAT, "0.0"}}, // tenths of a second; scaled by 0.1 in desire_helper
|
||||||
|
|||||||
@@ -209,6 +209,25 @@ def region_bundle_path(selector: str) -> Path:
|
|||||||
return region_bundle_dir(selector) / "tiles" / "offline.mbtiles"
|
return region_bundle_dir(selector) / "tiles" / "offline.mbtiles"
|
||||||
|
|
||||||
|
|
||||||
|
def region_valhalla_path(selector: str) -> Path:
|
||||||
|
# valhalla mmaps this tar in place, so it stays uncompressed on disk
|
||||||
|
return region_bundle_dir(selector) / "valhalla" / "tiles.tar"
|
||||||
|
|
||||||
|
|
||||||
|
def region_valhalla_installed(selector: str) -> bool:
|
||||||
|
return region_valhalla_path(selector).exists()
|
||||||
|
|
||||||
|
|
||||||
|
def installed_valhalla_selectors() -> list[str]:
|
||||||
|
regions_root = offline_map_root() / "regions"
|
||||||
|
if not regions_root.exists():
|
||||||
|
return []
|
||||||
|
return sorted(
|
||||||
|
child.name for child in regions_root.iterdir()
|
||||||
|
if child.is_dir() and (child / "valhalla" / "tiles.tar").exists()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def region_bundle_installed(selector: str) -> bool:
|
def region_bundle_installed(selector: str) -> bool:
|
||||||
return region_bundle_path(selector).exists()
|
return region_bundle_path(selector).exists()
|
||||||
|
|
||||||
@@ -313,6 +332,22 @@ class TileBundleDownloader:
|
|||||||
)
|
)
|
||||||
if not day_ok:
|
if not day_ok:
|
||||||
cloudlog.warning(f"iq_maps: day-style bundle failed for {selector}; night set installed")
|
cloudlog.warning(f"iq_maps: day-style bundle failed for {selector}; night set installed")
|
||||||
|
if entry.get("valhalla_path"):
|
||||||
|
# routing is additive: a region whose extract is missing or corrupt must still end up
|
||||||
|
# with a usable map rather than failing the whole download
|
||||||
|
try:
|
||||||
|
nav_ok = self._download_file(
|
||||||
|
selector, base_url, entry["valhalla_path"], int(entry.get("valhalla_bytes", 0)),
|
||||||
|
str(entry.get("valhalla_sha256", "")).strip().lower(),
|
||||||
|
region_valhalla_path(selector),
|
||||||
|
progress_offset + int(entry.get("bytes", 0)) + int(entry.get("day_bytes", 0)),
|
||||||
|
progress_total, 1, entry.get("valhalla_objects"),
|
||||||
|
)
|
||||||
|
except Exception as exc:
|
||||||
|
nav_ok = False
|
||||||
|
cloudlog.warning(f"iq_maps: routing extract errored for {selector}: {exc}")
|
||||||
|
if not nav_ok:
|
||||||
|
cloudlog.warning(f"iq_maps: routing extract failed for {selector}; map tiles installed")
|
||||||
_write_manifest(selector, entry)
|
_write_manifest(selector, entry)
|
||||||
cloudlog.info(f"iq_maps: installed tile bundle {selector}")
|
cloudlog.info(f"iq_maps: installed tile bundle {selector}")
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -186,6 +186,8 @@ class NNTorqueModel:
|
|||||||
|
|
||||||
PLAN_SAMPLE_START = 5
|
PLAN_SAMPLE_START = 5
|
||||||
LAG_EXTRA_S = 0.0
|
LAG_EXTRA_S = 0.0
|
||||||
|
JERK_AHEAD_TAU_S = 0.15 # low-pass on the model-derived jerk feed-forward (kills big-model accel.y noise)
|
||||||
|
JERK_PARAM_REFRESH = 100 # cycles (~1s at 100Hz)
|
||||||
|
|
||||||
BASE_P = 0.8
|
BASE_P = 0.8
|
||||||
BASE_I = 0.15
|
BASE_I = 0.15
|
||||||
@@ -264,6 +266,15 @@ class PilotLateralBrain:
|
|||||||
self.friction_look_ahead_bp = [9.0, 30.0]
|
self.friction_look_ahead_bp = [9.0, 30.0]
|
||||||
self.lat_jerk_friction_factor = 0.4
|
self.lat_jerk_friction_factor = 0.4
|
||||||
self.lat_accel_friction_factor = 0.7
|
self.lat_accel_friction_factor = 0.7
|
||||||
|
# The model-derived jerk term is a frame-to-frame derivative of model_v2.acceleration.y; on
|
||||||
|
# spatial/big models that array is slightly noisy and the raw derivative drives in-lane steering
|
||||||
|
# oscillation (sunny/stock has no such term). Low-pass it, and expose a live gain so it can be
|
||||||
|
# tuned to 0 (== stock friction ff) without a software push.
|
||||||
|
self._jerk_lp = FirstOrderFilter(0.0, JERK_AHEAD_TAU_S, 0.01)
|
||||||
|
self._jerk_gain = 1.0
|
||||||
|
self._jerk_param_frame = 0
|
||||||
|
self._jerk_param_ok = True
|
||||||
|
self._params = Params()
|
||||||
|
|
||||||
self.t_diffs = np.diff(ModelConstants.T_IDXS)
|
self.t_diffs = np.diff(ModelConstants.T_IDXS)
|
||||||
self.desired_lat_jerk_time = cp.steerActuatorDelay + LAG_EXTRA_S
|
self.desired_lat_jerk_time = cp.steerActuatorDelay + LAG_EXTRA_S
|
||||||
@@ -294,6 +305,17 @@ class PilotLateralBrain:
|
|||||||
self.jerk_ahead = 0.0
|
self.jerk_ahead = 0.0
|
||||||
|
|
||||||
def update_calculations(self, car_state, vehicle_model, desired_lat_accel):
|
def update_calculations(self, car_state, vehicle_model, desired_lat_accel):
|
||||||
|
self._jerk_param_frame += 1
|
||||||
|
if self._jerk_param_ok and self._jerk_param_frame % JERK_PARAM_REFRESH == 0:
|
||||||
|
try:
|
||||||
|
raw = self._params.get("IQLatJerkGain")
|
||||||
|
self._jerk_gain = float(raw) if raw not in (None, b"", "") else 1.0
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
self._jerk_gain = 1.0
|
||||||
|
except Exception:
|
||||||
|
# param key absent (params not rebuilt) — never let a param read touch lateral control
|
||||||
|
self._jerk_param_ok = False
|
||||||
|
self._jerk_gain = 1.0
|
||||||
self._reset_jerk_estimates(car_state, vehicle_model)
|
self._reset_jerk_estimates(car_state, vehicle_model)
|
||||||
if not self.model_valid:
|
if not self.model_valid:
|
||||||
return
|
return
|
||||||
@@ -305,6 +327,7 @@ class PilotLateralBrain:
|
|||||||
forecast = _pointwise_jerk(accel_y, self.t_diffs)
|
forecast = _pointwise_jerk(accel_y, self.t_diffs)
|
||||||
window = forecast[PLAN_SAMPLE_START:self._horizon_index(car_state.vEgo)]
|
window = forecast[PLAN_SAMPLE_START:self._horizon_index(car_state.vEgo)]
|
||||||
self.jerk_ahead = sign_locked_min(window, desired_jerk)
|
self.jerk_ahead = sign_locked_min(window, desired_jerk)
|
||||||
|
self.jerk_ahead = self._jerk_lp.update(self.jerk_ahead) * self._jerk_gain
|
||||||
|
|
||||||
if self.jerk_ahead == 0.0:
|
if self.jerk_ahead == 0.0:
|
||||||
self.jerk_now = 0.0
|
self.jerk_now = 0.0
|
||||||
|
|||||||
81
iqpilot/selfdrive/controls/tests/test_lat_jerk_lowpass.py
Normal file
81
iqpilot/selfdrive/controls/tests/test_lat_jerk_lowpass.py
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
"""
|
||||||
|
Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos/
|
||||||
|
"""
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from iqpilot.cereal import car, log
|
||||||
|
from iqdbc.car.car_helpers import interfaces
|
||||||
|
from iqdbc.car.toyota.values import CAR as TOYOTA
|
||||||
|
from iqdbc.car.vehicle_model import VehicleModel
|
||||||
|
from iqpilot.common.realtime import DT_CTRL
|
||||||
|
from iqpilot.selfdrive.controls.lib.latcontrol_torque import LatControlTorque
|
||||||
|
from iqpilot.selfdrive.car.helpers import convert_to_capnp
|
||||||
|
from iqpilot.selfdrive.car import interfaces as iqpilot_interfaces
|
||||||
|
from iqpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N
|
||||||
|
|
||||||
|
CAR_NAME = TOYOTA.TOYOTA_COROLLA_TSS2
|
||||||
|
|
||||||
|
|
||||||
|
def _brain():
|
||||||
|
CI_cls = interfaces[CAR_NAME]
|
||||||
|
CP = CI_cls.get_non_essential_params(CAR_NAME)
|
||||||
|
CP_IQ = CI_cls.get_non_essential_params_iq(CP, CAR_NAME)
|
||||||
|
CI = CI_cls(CP, CP_IQ)
|
||||||
|
iqpilot_interfaces.apply_iq_car_config(CI)
|
||||||
|
ctrl = LatControlTorque(CP.as_reader(), convert_to_capnp(CP_IQ).as_reader(), CI, DT_CTRL)
|
||||||
|
return ctrl.nnff_assist, VehicleModel(CP)
|
||||||
|
|
||||||
|
|
||||||
|
def _model(rng):
|
||||||
|
# same-sign accel ramp (so sign_locked_min yields a real jerk) whose slope jitters frame to
|
||||||
|
# frame the way a spatial big model's path does — this is what drives jerk_ahead to swing.
|
||||||
|
n = max(CONTROL_N, 33)
|
||||||
|
slope = abs(0.5 + rng.normal(0, 0.25))
|
||||||
|
m = log.ModelDataV2.new_message()
|
||||||
|
m.acceleration.y = (slope * np.arange(n) * 0.1).tolist()
|
||||||
|
m.orientation.x = [0.0] * n
|
||||||
|
return m
|
||||||
|
|
||||||
|
|
||||||
|
def _cs():
|
||||||
|
cs = car.CarState.new_message()
|
||||||
|
cs.vEgo = 25.0
|
||||||
|
cs.steeringRateDeg = 0.0
|
||||||
|
return cs
|
||||||
|
|
||||||
|
|
||||||
|
def _run(lp_on):
|
||||||
|
brain, VM = _brain()
|
||||||
|
rng = np.random.default_rng(7)
|
||||||
|
cs = _cs()
|
||||||
|
out = []
|
||||||
|
for _ in range(400):
|
||||||
|
brain.update_model_v2(_model(rng))
|
||||||
|
if not lp_on:
|
||||||
|
brain._jerk_lp.update = lambda x: x # bypass low-pass == pre-fix behavior
|
||||||
|
brain.update_calculations(cs, VM, 0.0)
|
||||||
|
out.append(brain.jerk_ahead)
|
||||||
|
return np.array(out)
|
||||||
|
|
||||||
|
|
||||||
|
def test_lowpass_cuts_jerk_command_swing():
|
||||||
|
old = _run(lp_on=False)
|
||||||
|
new = _run(lp_on=True)
|
||||||
|
# the path must actually exercise the jerk feed-forward (guard against a vacuous test)
|
||||||
|
assert np.abs(np.diff(old)).mean() > 0.02, "input did not exercise jerk_ahead"
|
||||||
|
old_swing = np.abs(np.diff(old)).mean()
|
||||||
|
new_swing = np.abs(np.diff(new)).mean()
|
||||||
|
# low-pass must cut the frame-to-frame jerk swing (the wheel oscillation) by a large margin
|
||||||
|
assert new_swing < 0.3 * old_swing, (old_swing, new_swing)
|
||||||
|
|
||||||
|
|
||||||
|
def test_gain_zero_matches_stock():
|
||||||
|
brain, VM = _brain()
|
||||||
|
brain._jerk_param_ok = False
|
||||||
|
brain._jerk_gain = 0.0
|
||||||
|
rng = np.random.default_rng(1)
|
||||||
|
cs = _cs()
|
||||||
|
for _ in range(60):
|
||||||
|
brain.update_model_v2(_model(rng))
|
||||||
|
brain.update_calculations(cs, VM, 0.0)
|
||||||
|
assert brain.jerk_ahead == 0.0 # no model-jerk term == sunny/stock feedforward
|
||||||
@@ -357,6 +357,7 @@ def main() -> None:
|
|||||||
}))
|
}))
|
||||||
if run_count % 100 == 0:
|
if run_count % 100 == 0:
|
||||||
cloudlog.warning(f"modeld_selector misses: {miss_reasons}")
|
cloudlog.warning(f"modeld_selector misses: {miss_reasons}")
|
||||||
|
pwriter.put_bool(keys["active"], latch.active)
|
||||||
cloudlog.warning(f"modeld_selector: big_used={big_used_count}/{run_count} "
|
cloudlog.warning(f"modeld_selector: big_used={big_used_count}/{run_count} "
|
||||||
f"last_big_peek={big_peek} target={target} active={latch.active} "
|
f"last_big_peek={big_peek} target={target} active={latch.active} "
|
||||||
f"max_big_lag={BIG_MAX_LAG_FRAMES}")
|
f"max_big_lag={BIG_MAX_LAG_FRAMES}")
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ import time
|
|||||||
os.environ.setdefault("FLOAT16", "1")
|
os.environ.setdefault("FLOAT16", "1")
|
||||||
os.environ.setdefault("JIT_BATCH_SIZE", "0")
|
os.environ.setdefault("JIT_BATCH_SIZE", "0")
|
||||||
os.environ.setdefault("GMMU", "0")
|
os.environ.setdefault("GMMU", "0")
|
||||||
os.environ.setdefault("TC_OPT", "2")
|
# TC_OPT=2 lets tinygrad pick tensor-core kernels; on some models a TC kernel miscompiles and biases
|
||||||
|
# the output (documented on Metal). A parity gate below catches it and re-compiles with TC off.
|
||||||
|
os.environ.setdefault("TC_OPT", "0" if ("--tc-off" in sys.argv or os.environ.get("IQ_EGPU_TC_OFF")) else "2")
|
||||||
|
|
||||||
HOST = "--host" in sys.argv
|
HOST = "--host" in sys.argv
|
||||||
if HOST:
|
if HOST:
|
||||||
@@ -32,6 +34,10 @@ INPUT_SPEC = dict(MODEL_INPUT_SPEC)
|
|||||||
patch_tinygrad_fetch_fw()
|
patch_tinygrad_fetch_fw()
|
||||||
|
|
||||||
SEED = 42
|
SEED = 42
|
||||||
|
|
||||||
|
|
||||||
|
class _ParityFail(RuntimeError):
|
||||||
|
pass
|
||||||
KERNEL_PROGRESS_SCALE = 260.0
|
KERNEL_PROGRESS_SCALE = 260.0
|
||||||
|
|
||||||
|
|
||||||
@@ -151,6 +157,25 @@ def _policy_frame(seed: int, input_spec: dict):
|
|||||||
return warped
|
return warped
|
||||||
|
|
||||||
|
|
||||||
|
def _tc_off_reference(onnx_path: str, meta: dict):
|
||||||
|
"""Compile+run the model with tensor cores OFF in a child process and return the last of 3
|
||||||
|
policy frames. This is the trusted reference: TC-off kernels are the conservative path the
|
||||||
|
eMac gate also trusts. Used to catch a TC kernel miscompile that would bias steering."""
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
with tempfile.TemporaryDirectory() as td:
|
||||||
|
ref = os.path.join(td, "ref.npy")
|
||||||
|
env = {k: v for k, v in os.environ.items() if k not in ("TC_OPT", "BEAM")}
|
||||||
|
env["TC_OPT"] = "0"
|
||||||
|
env["IQ_EGPU_REFERENCE"] = ref
|
||||||
|
r = subprocess.run([sys.executable, "-m", "iqpilot.selfdrive.iqmodeld.tools.compile_egpu_model",
|
||||||
|
"--model", meta["key"], "--onnx", onnx_path, "--tc-off"],
|
||||||
|
env=env, capture_output=True, text=True, timeout=14400)
|
||||||
|
if r.returncode != 0 or not os.path.isfile(ref):
|
||||||
|
raise RuntimeError(f"parity reference compile failed:\n{r.stderr[-2000:]}")
|
||||||
|
return np.load(ref)
|
||||||
|
|
||||||
|
|
||||||
def compile_policy_model(meta: dict, onnx_path: str, out_path: str) -> str:
|
def compile_policy_model(meta: dict, onnx_path: str, out_path: str) -> str:
|
||||||
from tinygrad.device import Device
|
from tinygrad.device import Device
|
||||||
from tinygrad.engine.jit import TinyJit
|
from tinygrad.engine.jit import TinyJit
|
||||||
@@ -216,6 +241,10 @@ def compile_policy_model(meta: dict, onnx_path: str, out_path: str) -> str:
|
|||||||
flat = out.numpy().reshape(-1)
|
flat = out.numpy().reshape(-1)
|
||||||
packed.views["prev_feat"][:] = flat[meta["output_slices"]["hidden_state"]].reshape(packed.views["prev_feat"].shape)
|
packed.views["prev_feat"][:] = flat[meta["output_slices"]["hidden_state"]].reshape(packed.views["prev_feat"].shape)
|
||||||
outs.append(flat)
|
outs.append(flat)
|
||||||
|
ref_target = os.environ.get("IQ_EGPU_REFERENCE")
|
||||||
|
if ref_target:
|
||||||
|
np.save(ref_target, outs[-1])
|
||||||
|
return out_path
|
||||||
if HOST:
|
if HOST:
|
||||||
os.replace(tmp, out_path)
|
os.replace(tmp, out_path)
|
||||||
return out_path
|
return out_path
|
||||||
@@ -229,6 +258,13 @@ def compile_policy_model(meta: dict, onnx_path: str, out_path: str) -> str:
|
|||||||
from iqpilot.selfdrive.iqmodeld.tools.compile_supercombo import _slice_outputs, _validate_pose_outputs
|
from iqpilot.selfdrive.iqmodeld.tools.compile_supercombo import _slice_outputs, _validate_pose_outputs
|
||||||
_validate_pose_outputs(PhaseParser().parse_vision_outputs(_slice_outputs(outs[-1], meta["output_slices"])))
|
_validate_pose_outputs(PhaseParser().parse_vision_outputs(_slice_outputs(outs[-1], meta["output_slices"])))
|
||||||
|
|
||||||
|
if os.environ.get("TC_OPT") != "0" and not os.environ.get("IQ_EGPU_SKIP_PARITY"):
|
||||||
|
ref = _tc_off_reference(onnx_path, meta)
|
||||||
|
rel = float(np.abs(outs[-1] - ref).mean() / max(1e-3, float(np.abs(ref).mean())))
|
||||||
|
if rel > 0.01:
|
||||||
|
raise _ParityFail(f"PARITY FAIL: TC kernels miscompiled {meta['key']} (rel={rel:.4f} vs TC-off); recompiling with tensor cores disabled")
|
||||||
|
print(f" parity vs TC-off reference: rel={rel:.6f} OK")
|
||||||
|
|
||||||
os.replace(tmp, out_path)
|
os.replace(tmp, out_path)
|
||||||
return out_path
|
return out_path
|
||||||
|
|
||||||
@@ -244,6 +280,7 @@ def main() -> None:
|
|||||||
p.add_argument("--format", type=int, default=2, choices=(1, 2))
|
p.add_argument("--format", type=int, default=2, choices=(1, 2))
|
||||||
p.add_argument("--host", action="store_true", help="compile on a mock dock (no AMD hardware); outputs need a dock parity gate")
|
p.add_argument("--host", action="store_true", help="compile on a mock dock (no AMD hardware); outputs need a dock parity gate")
|
||||||
p.add_argument("--arch", default=None, help="target gfx arch for --host")
|
p.add_argument("--arch", default=None, help="target gfx arch for --host")
|
||||||
|
p.add_argument("--tc-off", action="store_true", help="disable tensor-core kernels (conservative; auto-set on parity failure)")
|
||||||
args = p.parse_args()
|
args = p.parse_args()
|
||||||
if args.host and args.format != 2:
|
if args.host and args.format != 2:
|
||||||
raise SystemExit("--host supports format 2 only")
|
raise SystemExit("--host supports format 2 only")
|
||||||
@@ -275,7 +312,15 @@ def main() -> None:
|
|||||||
sampler.start()
|
sampler.start()
|
||||||
try:
|
try:
|
||||||
build = compile_policy_model if args.format == 2 else compile_model
|
build = compile_policy_model if args.format == 2 else compile_model
|
||||||
out = build(meta, onnx_path, args.output or egpu_pkl_path(meta))
|
try:
|
||||||
|
out = build(meta, onnx_path, args.output or egpu_pkl_path(meta))
|
||||||
|
except _ParityFail as e:
|
||||||
|
if os.environ.get("TC_OPT") == "0" or args.format != 2:
|
||||||
|
raise
|
||||||
|
print(f"{e}\nretrying compile with tensor cores disabled", flush=True)
|
||||||
|
os.environ["TC_OPT"] = "0"
|
||||||
|
os.environ["IQ_EGPU_TC_OFF"] = "1"
|
||||||
|
out = compile_policy_model(meta, onnx_path, args.output or egpu_pkl_path(meta))
|
||||||
finally:
|
finally:
|
||||||
if stop is not None:
|
if stop is not None:
|
||||||
stop.set()
|
stop.set()
|
||||||
|
|||||||
@@ -274,7 +274,10 @@ class SelfdriveD(GapButtonActions):
|
|||||||
dock_present = self.sm['deviceState'].egpuDockPresent
|
dock_present = self.sm['deviceState'].egpuDockPresent
|
||||||
mac_active = self.params.get_bool("MacModelActive")
|
mac_active = self.params.get_bool("MacModelActive")
|
||||||
model_unavailable = big_active is True and self.sm.seen['modelV2'] and not self.sm.alive['modelV2']
|
model_unavailable = big_active is True and self.sm.seen['modelV2'] and not self.sm.alive['modelV2']
|
||||||
big_failed = (big_active is False or model_unavailable
|
# an explicit False before this session's first activation is just the selector arming
|
||||||
|
# (it pre-clears the param on startup); alerting on it pops "big model failed" on every
|
||||||
|
# return to the road until the latch warms up
|
||||||
|
big_failed = ((self.big_model_active and big_active is False) or model_unavailable
|
||||||
or (self.big_model_active and not dock_present)) and not mac_active
|
or (self.big_model_active and not dock_present)) and not mac_active
|
||||||
if big_failed:
|
if big_failed:
|
||||||
self.events.add(EventName.bigModelFailed)
|
self.events.add(EventName.bigModelFailed)
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ class MainLayout(Widget):
|
|||||||
self._layouts[MainState.ROUTES].set_on_play(self.open_video)
|
self._layouts[MainState.ROUTES].set_on_play(self.open_video)
|
||||||
self._layouts[MainState.VIDEO].set_on_back(self.open_routes)
|
self._layouts[MainState.VIDEO].set_on_back(self.open_routes)
|
||||||
self._layouts[MainState.ONROAD].set_click_callback(self._on_onroad_clicked)
|
self._layouts[MainState.ONROAD].set_click_callback(self._on_onroad_clicked)
|
||||||
device.add_interactive_timeout_callback(self._set_mode_for_state)
|
device.add_interactive_timeout_callback(self._on_interactive_timeout)
|
||||||
|
|
||||||
def _update_layout_rects(self):
|
def _update_layout_rects(self):
|
||||||
self._sidebar_rect = rl.Rectangle(self._rect.x, self._rect.y, SIDEBAR_WIDTH, self._rect.height)
|
self._sidebar_rect = rl.Rectangle(self._rect.x, self._rect.y, SIDEBAR_WIDTH, self._rect.height)
|
||||||
@@ -166,6 +166,20 @@ class MainLayout(Widget):
|
|||||||
|
|
||||||
self._set_mode_for_state()
|
self._set_mode_for_state()
|
||||||
|
|
||||||
|
def _car_stationary(self) -> bool:
|
||||||
|
if not ui_state.sm.valid["carState"]:
|
||||||
|
return False
|
||||||
|
return ui_state.sm["carState"].vEgo < 0.1
|
||||||
|
|
||||||
|
def _on_interactive_timeout(self):
|
||||||
|
# The idle timeout normally returns the UI to the road view. Don't yank the user out of Settings
|
||||||
|
# while the car is stationary - e.g. a hybrid parked with the engine running to charge reads as
|
||||||
|
# onroad (ignition tracks the ICE), so this would otherwise make Settings unusable while parked.
|
||||||
|
# A moving car still returns to the road view.
|
||||||
|
if self._current_mode == MainState.SETTINGS and ui_state.started and self._car_stationary():
|
||||||
|
return
|
||||||
|
self._set_mode_for_state()
|
||||||
|
|
||||||
def _set_mode_for_state(self):
|
def _set_mode_for_state(self):
|
||||||
if ui_state.started:
|
if ui_state.started:
|
||||||
# Don't hide sidebar from interactive timeout
|
# Don't hide sidebar from interactive timeout
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
from types import SimpleNamespace
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from iqpilot.selfdrive.ui.layouts.main import MainLayout, MainState
|
||||||
|
|
||||||
|
|
||||||
|
def make_layout(current_mode):
|
||||||
|
layout = object.__new__(MainLayout)
|
||||||
|
layout._current_mode = current_mode
|
||||||
|
layout._set_mode_calls = []
|
||||||
|
layout._set_mode_for_state = lambda: layout._set_mode_calls.append(current_mode)
|
||||||
|
return layout
|
||||||
|
|
||||||
|
|
||||||
|
class FakeSm:
|
||||||
|
def __init__(self, v_ego, carstate_valid):
|
||||||
|
self.valid = {"carState": carstate_valid}
|
||||||
|
self._v_ego = v_ego
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return SimpleNamespace(vEgo=self._v_ego)
|
||||||
|
|
||||||
|
|
||||||
|
class TestSettingsInteractiveTimeout:
|
||||||
|
def _run(self, current_mode, started, v_ego, carstate_valid=True):
|
||||||
|
layout = make_layout(current_mode)
|
||||||
|
fake = SimpleNamespace(started=started, sm=FakeSm(v_ego, carstate_valid))
|
||||||
|
monkeypatch = pytest.MonkeyPatch()
|
||||||
|
monkeypatch.setattr("iqpilot.selfdrive.ui.layouts.main.ui_state", fake)
|
||||||
|
try:
|
||||||
|
layout._on_interactive_timeout()
|
||||||
|
finally:
|
||||||
|
monkeypatch.undo()
|
||||||
|
return layout._set_mode_calls
|
||||||
|
|
||||||
|
def test_stationary_in_settings_stays(self):
|
||||||
|
# parked/charging hybrid reads onroad; the timeout must not eject from Settings
|
||||||
|
assert self._run(MainState.SETTINGS, started=True, v_ego=0.0) == []
|
||||||
|
|
||||||
|
def test_moving_in_settings_returns_to_road(self):
|
||||||
|
assert self._run(MainState.SETTINGS, started=True, v_ego=5.0) == [MainState.SETTINGS]
|
||||||
|
|
||||||
|
def test_onroad_layout_always_handled(self):
|
||||||
|
assert self._run(MainState.ONROAD, started=True, v_ego=0.0) == [MainState.ONROAD]
|
||||||
|
|
||||||
|
def test_home_layout_always_handled(self):
|
||||||
|
assert self._run(MainState.HOME, started=True, v_ego=0.0) == [MainState.HOME]
|
||||||
|
|
||||||
|
def test_offroad_in_settings_handled(self):
|
||||||
|
# car off (offroad): existing behavior is unchanged
|
||||||
|
assert self._run(MainState.SETTINGS, started=False, v_ego=0.0) == [MainState.SETTINGS]
|
||||||
|
|
||||||
|
def test_invalid_carstate_treated_as_moving(self):
|
||||||
|
# if speed is unknown, fail safe to the road view rather than trapping in settings
|
||||||
|
assert self._run(MainState.SETTINGS, started=True, v_ego=0.0, carstate_valid=False) == [MainState.SETTINGS]
|
||||||
@@ -67,14 +67,14 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "boot",
|
"name": "boot",
|
||||||
"url": "https://git.konn3kt.com/IQ.Lvbs/iqos/raw/branch/master/boot-aea4aecefd188d9c95726b699902378676c6266a7ae37008b5c2aa0e1e1190fb.img.xz",
|
"url": "https://git.konn3kt.com/IQ.Lvbs/iqos/raw/branch/master/boot-4258981292746f5622f4a03a1e0c1d77379660e46bbaa455c504d638b5307906.img.xz",
|
||||||
"hash": "aea4aecefd188d9c95726b699902378676c6266a7ae37008b5c2aa0e1e1190fb",
|
"hash": "4258981292746f5622f4a03a1e0c1d77379660e46bbaa455c504d638b5307906",
|
||||||
"hash_raw": "aea4aecefd188d9c95726b699902378676c6266a7ae37008b5c2aa0e1e1190fb",
|
"hash_raw": "4258981292746f5622f4a03a1e0c1d77379660e46bbaa455c504d638b5307906",
|
||||||
"size": 18216960,
|
"size": 18216960,
|
||||||
"sparse": false,
|
"sparse": false,
|
||||||
"full_check": true,
|
"full_check": true,
|
||||||
"has_ab": true,
|
"has_ab": true,
|
||||||
"ondevice_hash": "f568e4394e36a367de58cce2b982bf597963e088b6a00b1ac88ca03cce8f62fd"
|
"ondevice_hash": "7be61ba2be5617ac22d6beb8ba8b896109a554347021f5e44b72458748336975"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "system",
|
"name": "system",
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
qT72MCHtDUWnARJbSsLUcPaISRZxjFPNf282R9ZC1SXvFJz6X6NmjgknK3OLDLijOQWlGvvJZGsDgz2vsdPVAg==
|
Myu8k7msX7pt28JKl1Lx5/NnXu9i15nT8bFWnwGsip8wdCYPJqj69AWrfCtlg9YrR98O6ThCAEA1uzUfsrTeDQ==
|
||||||
|
|||||||
@@ -56,14 +56,14 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "boot",
|
"name": "boot",
|
||||||
"url": "https://git.konn3kt.com/IQ.Lvbs/iqos/raw/branch/master/boot-aea4aecefd188d9c95726b699902378676c6266a7ae37008b5c2aa0e1e1190fb.img.xz",
|
"url": "https://git.konn3kt.com/IQ.Lvbs/iqos/raw/branch/master/boot-4258981292746f5622f4a03a1e0c1d77379660e46bbaa455c504d638b5307906.img.xz",
|
||||||
"hash": "aea4aecefd188d9c95726b699902378676c6266a7ae37008b5c2aa0e1e1190fb",
|
"hash": "4258981292746f5622f4a03a1e0c1d77379660e46bbaa455c504d638b5307906",
|
||||||
"hash_raw": "aea4aecefd188d9c95726b699902378676c6266a7ae37008b5c2aa0e1e1190fb",
|
"hash_raw": "4258981292746f5622f4a03a1e0c1d77379660e46bbaa455c504d638b5307906",
|
||||||
"size": 18216960,
|
"size": 18216960,
|
||||||
"sparse": false,
|
"sparse": false,
|
||||||
"full_check": true,
|
"full_check": true,
|
||||||
"has_ab": true,
|
"has_ab": true,
|
||||||
"ondevice_hash": "f568e4394e36a367de58cce2b982bf597963e088b6a00b1ac88ca03cce8f62fd"
|
"ondevice_hash": "7be61ba2be5617ac22d6beb8ba8b896109a554347021f5e44b72458748336975"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "system",
|
"name": "system",
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
fL46Z+k/wqjavP3J1S/VzE90BXcvvRF+S41MgHEXYjW+Jlnu5REOp6rvp3SJFEkKIEaiSf9PsHyiDgQkC6J2Aw==
|
aGtkoy//jP3MWJmd5uvb/mxKu1KsE8ZlhrTUr1CPCotwjIVzsxOncUGN9HnUcMXoUWZbUWz9H8Q+ARYxz41/Ag==
|
||||||
|
|||||||
Reference in New Issue
Block a user