diff --git a/artifacts/iqpilot_emac_private/manifest.json b/artifacts/iqpilot_emac_private/manifest.json index d547a738b..cf339e3b3 100644 --- a/artifacts/iqpilot_emac_private/manifest.json +++ b/artifacts/iqpilot_emac_private/manifest.json @@ -201,8 +201,8 @@ }, "python/_iqclosure/iqpilot/selfdrive/iqmodeld/egpu_helpers.py": { "mode": 420, - "sha256": "0b8f118dc45ad0c3809855800960b47c893ee121ea75d94e8569dcce46d58ce5", - "size": 7312 + "sha256": "07b3ace231d9912f1926ffe7cef0f2a5d9649f75b7ebac2b9f296957d98be166", + "size": 7681 }, "python/_iqclosure/iqpilot/selfdrive/iqmodeld/egpu_model.py": { "mode": 420, @@ -216,8 +216,8 @@ }, "python/_iqclosure/iqpilot/selfdrive/iqmodeld/messaging.py": { "mode": 420, - "sha256": "17d48331eeeaf746ee6982a9c65f28d740a15a4c34c37617115c104894d49c06", - "size": 11920 + "sha256": "1d345eb35d4eea2a0b8c8e8491b4c1a74e073d8340703cdd334ec78992026f72", + "size": 12033 }, "python/_iqclosure/iqpilot/selfdrive/iqmodeld/metadata.py": { "mode": 420, @@ -536,27 +536,27 @@ }, "python/iqpilot_private/emac/bulk_transport.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "f42a1bab373092b3010ca45b02d7ea7b27cd1e1e574c97f701129b2fad01f833", + "sha256": "0fec7e56196064f024cf317a6f23d9f2111f90753c48bb7d616e06e27335157d", "size": 333888 }, "python/iqpilot_private/emac/ffs_holder.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "306f0362e86558d33072f800b736fa71bfaf4ee5e4383c4e743b72b74724d2e3", + "sha256": "4d6e7c4bc97ced0bf2def103d2fc8eb98364747aa33e495bc448c68644739750", "size": 68064 }, "python/iqpilot_private/emac/mac_client.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "31339f53f093c3877e13eac90a6647cbca2de92f339c47e5006a85bcd2e3656c", + "sha256": "a23b14f9f2c5c7a058c20ef0421bb741fc67c2adff13824c1c808e6831430f91", "size": 267960 }, "python/iqpilot_private/emac/mac_protocol.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "d5e855d1784a8ba66844639b871d2747ccce264c55359cf0e641ce7e3d66460d", - "size": 203512 + "sha256": "189c7d6d5599f92fc224a086ef55520118130785f482c0667cc808071c84e718", + "size": 203544 }, "python/iqpilot_private/emac/maciqmodeld.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "34d4ef1746143ea714f84f3c325e2ddaecec6a19c544fed68d8fc4080578c73f", + "sha256": "2cf0bc9d6362f2d4c9691f4f0ef7989a5651cc3153e99e5c2e15d9da1b93e598", "size": 399040 }, "runtime": { @@ -568,10 +568,10 @@ } }, "signatures": { - "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": "Sv2riVgvm+4PDVTDLTuy1wpf15JObbP8hSAD4iiwF4RUs49GVGhulXkjzO28mLmF6tEuNDNWHRucxmuZrCKNAg==", - "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": "hvBkDKSMKjpxmRzhhGoRZT5WuOWLY+g3p2NIMlA7b6qYYpVaApoZNuquOerywEF1zJnwPiwpsg5QtQVe/5DfAA==", - "python/iqpilot_private/emac/maciqmodeld.cpython-312-aarch64-linux-gnu.so": "d3JAlH7P/X87II6iobeQ51melHy1vxdlXn0Nzo2DG65rcdVLM2B66YETPpwlX6Qv9NxhUlDcl/364CR+V+eyDQ==" + "python/iqpilot_private/emac/bulk_transport.cpython-312-aarch64-linux-gnu.so": "laKo35uiFJAsuGj7+N5l5IVbXmTQ/jyB01c31OfA7XCT0AG09/cg9ArgDhQv5qr3babesKgUKoPg2vtFnnXyDg==", + "python/iqpilot_private/emac/ffs_holder.cpython-312-aarch64-linux-gnu.so": "Sd6VF2hrGHXoXTe3IpCYoTDczM741xcQ1sKiHGcCgNqkeORvLumWxic20ylmWhWOTHziPB9Y723vFOGcKZzDAQ==", + "python/iqpilot_private/emac/mac_client.cpython-312-aarch64-linux-gnu.so": "O9O/B4IDlCutovmEPDnLxdKAFsURjXS+pyaK0OvmoOlOQW1fQS+ZahxaQ0dkwASDzEMWUxUFr0j9PrlihUVpCA==", + "python/iqpilot_private/emac/mac_protocol.cpython-312-aarch64-linux-gnu.so": "77vKNawQIdv95LPwTFn79N2RXaz6dQUcRtgtnH+R7T2TN2LBSKhKvtzu2sKkKyDG7038qrJfhE9BiJYtho56BA==", + "python/iqpilot_private/emac/maciqmodeld.cpython-312-aarch64-linux-gnu.so": "Fhxo++ZiJmWGBghe/dH/ytHe+T67v/HAA6k4js7Bd+C07dA/zMlgTI45QlBx2fZN2qC602Z4Stijy+/EQziuCg==" } } diff --git a/artifacts/iqpilot_emac_private/manifest.json.sig b/artifacts/iqpilot_emac_private/manifest.json.sig index aa8f71111..5e95c35ca 100644 --- a/artifacts/iqpilot_emac_private/manifest.json.sig +++ b/artifacts/iqpilot_emac_private/manifest.json.sig @@ -1 +1 @@ -KylnzVsK5XC3Jq1G7bBbKa5lv+oJSlfBpBsNpWMEEUgHDyOEj7+5EeeHDOgy8Lt4LEFgEeIV2WEJW0GJVpxUCQ== +nBzDAB5lnwH7Ynehfwf48y7ACh39HIRNiff55kmMtNG466wcxBrkMcnEJz/rDf7ehRcZmyD08CVW5QCfMsHBAA== diff --git a/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/iqmodeld/egpu_helpers.py b/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/iqmodeld/egpu_helpers.py index 1317d78be..652fe37de 100644 --- a/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/iqmodeld/egpu_helpers.py +++ b/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/iqmodeld/egpu_helpers.py @@ -71,6 +71,11 @@ def egpu_oob_pkl_path(meta: dict) -> str: return os.path.join(Paths.model_root(), f"egpu_{meta['key']}_{meta['sha256'][:8]}_amd_policy_oob.pkl") +def egpu_model_oob_pkl_path(meta: dict) -> str: + from iqpilot.system.hardware.hw import Paths + return os.path.join(Paths.model_root(), f"egpu_{meta['key']}_{meta['sha256'][:8]}_amd_model_oob.pkl") + + def onnx_cache_path(meta: dict) -> str: from iqpilot.system.hardware.hw import Paths return os.path.join(Paths.model_root(), f"{meta['model_name']}_{meta['sha256'][:8]}.onnx") @@ -156,13 +161,21 @@ def download_onnx(meta: dict, progress_cb=None) -> str: return path -def download_precompiled(meta: dict, progress_cb=None, policy: bool = False, oob: bool = False) -> str | None: - field = "egpu_oob_artifact" if oob else "egpu_policy_artifact" if policy else "egpu_artifact" +ARTIFACT_PATHS = { + "egpu_model_oob_artifact": egpu_model_oob_pkl_path, + "egpu_oob_artifact": egpu_oob_pkl_path, + "egpu_policy_artifact": egpu_policy_pkl_path, + "egpu_artifact": egpu_pkl_path, +} + + +def download_precompiled(meta: dict, progress_cb=None, policy: bool = False, oob: bool = False, field: str | None = None) -> str | None: + field = field or ("egpu_oob_artifact" if oob else "egpu_policy_artifact" if policy else "egpu_artifact") art = meta.get(field) if not art or not (art.get("objects") or art.get("hf_path")): return None from iqpilot.selfdrive.iqmodeld.model_bundle_downloader import download_hf_file, download_lfs_bundle - dest = egpu_oob_pkl_path(meta) if oob else egpu_policy_pkl_path(meta) if policy else egpu_pkl_path(meta) + dest = ARTIFACT_PATHS[field](meta) if art.get("hf_path"): try: return download_hf_file(art["hf_path"], dest, art["sha256"], int(art.get("size", 0)), progress_cb=progress_cb) diff --git a/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/iqmodeld/messaging.py b/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/iqmodeld/messaging.py index ca43b2702..7f3ff5db6 100644 --- a/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/iqmodeld/messaging.py +++ b/artifacts/iqpilot_emac_private/python/_iqclosure/iqpilot/selfdrive/iqmodeld/messaging.py @@ -248,16 +248,19 @@ def populate_drive_messages(primary_msg: capnp._DynamicStructBuilder, extended_m def populate_odometry_message(msg: capnp._DynamicStructBuilder, outputs: dict[str, np.ndarray], vipc_frame_id: int, vipc_dropped_frames: int, timestamp_eof: int, live_calib_seen: bool) -> None: - msg.valid = live_calib_seen & (vipc_dropped_frames < 1) + pose = outputs["pose"][0, :6] + pose_stds = outputs["pose_stds"][0, :6] + pose_finite = bool(np.isfinite(pose).all() and np.isfinite(pose_stds).all()) + msg.valid = live_calib_seen & (vipc_dropped_frames < 1) & pose_finite odo = msg.cameraOdometry odo.frameId = vipc_frame_id odo.timestampEof = timestamp_eof - odo.trans = outputs["pose"][0, :3].tolist() - odo.rot = outputs["pose"][0, 3:].tolist() + odo.trans = pose[:3].tolist() + odo.rot = pose[3:6].tolist() odo.wideFromDeviceEuler = outputs["wide_from_device_euler"][0, :].tolist() odo.roadTransformTrans = outputs["road_transform"][0, :3].tolist() - odo.transStd = outputs["pose_stds"][0, :3].tolist() - odo.rotStd = outputs["pose_stds"][0, 3:].tolist() + odo.transStd = pose_stds[:3].tolist() + odo.rotStd = pose_stds[3:6].tolist() odo.wideFromDeviceEulerStd = outputs["wide_from_device_euler_stds"][0, :].tolist() odo.roadTransformTransStd = outputs["road_transform_stds"][0, :3].tolist() diff --git a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/bulk_transport.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/bulk_transport.cpython-312-aarch64-linux-gnu.so index df0ee109a..d0d27eb79 100755 Binary files a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/bulk_transport.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/bulk_transport.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/ffs_holder.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/ffs_holder.cpython-312-aarch64-linux-gnu.so index 8d73db59b..c906ed22a 100755 Binary files a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/ffs_holder.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/ffs_holder.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/mac_client.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/mac_client.cpython-312-aarch64-linux-gnu.so index 792dea995..13355aeba 100755 Binary files a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/mac_client.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/mac_client.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/mac_protocol.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/mac_protocol.cpython-312-aarch64-linux-gnu.so index adfe15cf6..2eeda697e 100755 Binary files a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/mac_protocol.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/mac_protocol.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/maciqmodeld.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/maciqmodeld.cpython-312-aarch64-linux-gnu.so index 5c00696b1..e76f8c727 100755 Binary files a/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/maciqmodeld.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_emac_private/python/iqpilot_private/emac/maciqmodeld.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_model_selector_private/manifest.json b/artifacts/iqpilot_model_selector_private/manifest.json index 5a3918714..7e9210c54 100644 --- a/artifacts/iqpilot_model_selector_private/manifest.json +++ b/artifacts/iqpilot_model_selector_private/manifest.json @@ -176,8 +176,8 @@ }, "python/iqpilot_private/models/__init__.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "aec72c78d58c37afb1b57bea4a29d322032fffdfa59deabdc85b4322b5ca3787", - "size": 67616 + "sha256": "665a6a5163899f37bb7e41fd42fe79ecd77e50496285b60c6555971b8337f463", + "size": 67568 }, "python/iqpilot_private/models/__init__.py": { "mode": 420, @@ -186,38 +186,38 @@ }, "python/iqpilot_private/models/big_catalog.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "30a25ebd3b37e2307c3a80ae0fea70b314ab71427d313ba5e2d540c4ba7658ed", - "size": 133840 + "sha256": "8a63da11107132869d7ea4e391197ca8bde2d13d6d92b09a83484503910a75d5", + "size": 133856 }, "python/iqpilot_private/models/egpu_model.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "e8cb29388e31f636d19f916d5a1d32f38c38113f5fa882344d4effceb6e37d85", - "size": 68112 + "sha256": "7090be17ce2063905fc364ee925384708895150f4d6eef642a94b941d3c6c88d", + "size": 68096 }, "python/iqpilot_private/models/emac_model_meta.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "b7938d9521352d5c1fa6b0d7ff8f3f11062e33bcc0d9a72ffb0edfb525423b6e", - "size": 68264 + "sha256": "c2691e7a3e77e78d20d21cbf0d0bc4d59fd294935c7ebd0cc7225b0d77619914", + "size": 134032 }, "python/iqpilot_private/models/fetcher.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "dad0c3c3a73338647da25dead17da0db6cebb24527bc9db381cd16753741f676", + "sha256": "d085741bb6a7d2a94d616d53e78e0ae76d381ca926017646ec33931375fb5963", "size": 136200 }, "python/iqpilot_private/models/git_auth.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "ce815034dd8bdadb79131e0b51013a9f9772c4421dfb96b62431d84125089ad2", - "size": 68056 + "sha256": "951ecc3665d6a2232f50ca3002f7f84753789ecd1adfc06cc85884b42c47e05c", + "size": 68032 }, "python/iqpilot_private/models/helpers.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "798843f52120210c19da5b6c98723ca15d782ea9cd445cc8f96009471990d618", - "size": 137944 + "sha256": "8670d22574d59c9b2f43c0fa047967a3236fc4eb0ca315a61fe0c9f2636d886a", + "size": 203512 }, "python/iqpilot_private/models/manager.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "96be19ef4f59b87e44092c61f70676468617365923c4c8b91cf7e0b88cc62c05", - "size": 340000 + "sha256": "c0fcfd5193cd11e52f22d8c804ace3b436f49aaa6655689c2f1903931544a977", + "size": 339976 }, "runtime": { "entries": { @@ -228,13 +228,13 @@ } }, "signatures": { - "python/iqpilot_private/models/__init__.cpython-312-aarch64-linux-gnu.so": "CHPHmtjVAGTdtbWnwE5awrEKFJHs06YK4Gao9IKVaHZYXyj5WAc/d4t7hOKM3lm2/UfBaraTdVTdeSOij3dpCQ==", - "python/iqpilot_private/models/big_catalog.cpython-312-aarch64-linux-gnu.so": "Ekiv6tp3mDx+7Z4lNI+byVomzjShe93UkYQEOhYwl6kHlpxN06A3IqV8y5pwlJII4ZpE5yYEX9qp+VMXsdm9Aw==", - "python/iqpilot_private/models/egpu_model.cpython-312-aarch64-linux-gnu.so": "njYujmFBsfewILpjLI0nUN34rqzMNITattpewwxE4LuTcdkAgihQ3w/S/aYetSJzUtV/SH9mk26DhMciwn8KAw==", - "python/iqpilot_private/models/emac_model_meta.cpython-312-aarch64-linux-gnu.so": "zE2s6oQ3YqanaFG4RMNPydekiblRQVBk7QEJ5G30W2thGqzWt+1BW+75XdwaCigw//rINxKHbt3Neu5rub7PAw==", - "python/iqpilot_private/models/fetcher.cpython-312-aarch64-linux-gnu.so": "hBKd/smbmwEszsGjU7FP2RNVmrINBpU4NPZMGDjEHAF7Rx1WBF49+pH1s0k571RBqdtqN7nya2HCnKKO0tHUBw==", - "python/iqpilot_private/models/git_auth.cpython-312-aarch64-linux-gnu.so": "eKa9qfsfNNaSQpqggWSGw5YV/6cJk5iJcmhY+N/v3xdFvEMfCsIf+N3BhP0S3ZDO5T2CeE/I/Xc+1QbZh7oNDQ==", - "python/iqpilot_private/models/helpers.cpython-312-aarch64-linux-gnu.so": "k4BcKQAua+1YSC6P8jVEu2wBrI+WL8Bb5kKQbOnBYn/lupnrA96vMRYu4XVVDLGBoIqK8L7K/PYCYxu9Cx4RDA==", - "python/iqpilot_private/models/manager.cpython-312-aarch64-linux-gnu.so": "+53NsV73jkF/1x9Bzsw99oZRhVBtqlQTeXaPfHydTAssd2V3UMO+BWqagtGbVG5qIOcgjaNweNExGu+Abo7iDA==" + "python/iqpilot_private/models/__init__.cpython-312-aarch64-linux-gnu.so": "BaGn+mLXPAGLqnVJhDUt8C2ZEm1E9+MUCPoOnJhQGQybFOr36MuoubfpEgPoy1993Tm4IGD3pZASyFefJNXtBQ==", + "python/iqpilot_private/models/big_catalog.cpython-312-aarch64-linux-gnu.so": "DfeUTDggp3zRuVHoECcYdCliGhB1A/BdQoicWHddyTS4YptXxaow5Rads9qnmRIiBpSgR8d0vH9fwNxpQl0aBw==", + "python/iqpilot_private/models/egpu_model.cpython-312-aarch64-linux-gnu.so": "9sIFDj6iIVEUE+lxa3Ryk/djxgiPMu78MM/WQdjYfpVQNv2OQ7IkBu121iNa5XIv/CTFMl1G6KGTWO5/Qm9iBw==", + "python/iqpilot_private/models/emac_model_meta.cpython-312-aarch64-linux-gnu.so": "CjvP1I4QBJu6zRW75XHEUWX6F6Wks9xtnuu1hdjv/V2Vw11Vf+Wa8zCztpKBgMx3dzbQ/p++xpTf5p7TCoMyAA==", + "python/iqpilot_private/models/fetcher.cpython-312-aarch64-linux-gnu.so": "WNq4sNwhPeu7NuW+hj1UOv1lAiQN2k8lPwImfeS7vFLY0G+pUBpnCVhD49SmjMmPyfCoxJkxD+wdhogPT2u6DQ==", + "python/iqpilot_private/models/git_auth.cpython-312-aarch64-linux-gnu.so": "FJ7yptMwvQxz5kB6XLjNJKBDy3+jrwWsPe/KBa8ki/e6uNavH63Umu18z5e6aY4AYp9D8z0pBOt5lk1X+bFvBg==", + "python/iqpilot_private/models/helpers.cpython-312-aarch64-linux-gnu.so": "9sX2Peumx+BT3G+LRIbPtcs42mULnRiXJMbQq3esj7yfaGsbf3l5XQ/9BDr8U/A6aFWfatOYSwbFD37ZGdLxCg==", + "python/iqpilot_private/models/manager.cpython-312-aarch64-linux-gnu.so": "uyUgRSqgfhMcboJeDLTF1vAuw6thTLubkKp4wsn3i3VFAGkLzE0fEkhzoRo1TSn8hkb787kNQs+Z/woCPxi5AQ==" } } diff --git a/artifacts/iqpilot_model_selector_private/manifest.json.sig b/artifacts/iqpilot_model_selector_private/manifest.json.sig index 09517d18c..0c712184a 100644 --- a/artifacts/iqpilot_model_selector_private/manifest.json.sig +++ b/artifacts/iqpilot_model_selector_private/manifest.json.sig @@ -1 +1 @@ -8t0c8OQ6AY5JlVXqGQkiF2rlj3kN3MIwGHVz4TOgaudkW7XegnRhUqngcpNo5C74wFDKNGWsvXOJ4WtIiIrfCg== +aZ2PpZxlTDJ1Nffu+hFtfKK0qyUkkllomgYgTX69J4YU4/aODiwBvJDwHZ6+1nlvv4fDA10s7SPNxwwP9j0OBA== diff --git a/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/__init__.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/__init__.cpython-312-aarch64-linux-gnu.so index 147259b81..20382dc61 100755 Binary files a/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/__init__.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/__init__.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/big_catalog.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/big_catalog.cpython-312-aarch64-linux-gnu.so index a8cd85cc0..d3018cfde 100755 Binary files a/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/big_catalog.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/big_catalog.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/egpu_model.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/egpu_model.cpython-312-aarch64-linux-gnu.so index 033ae101f..5f4a6a621 100755 Binary files a/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/egpu_model.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/egpu_model.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/emac_model_meta.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/emac_model_meta.cpython-312-aarch64-linux-gnu.so index 24bc620b5..9710587a4 100755 Binary files a/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/emac_model_meta.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/emac_model_meta.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/fetcher.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/fetcher.cpython-312-aarch64-linux-gnu.so index 450526348..3b763ab31 100755 Binary files a/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/fetcher.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/fetcher.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/git_auth.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/git_auth.cpython-312-aarch64-linux-gnu.so index 695c881f5..5b939661b 100755 Binary files a/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/git_auth.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/git_auth.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/helpers.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/helpers.cpython-312-aarch64-linux-gnu.so index fa3e70ce6..5f67a7413 100755 Binary files a/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/helpers.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/helpers.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/manager.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/manager.cpython-312-aarch64-linux-gnu.so index 057766128..53e81b991 100755 Binary files a/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/manager.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_model_selector_private/python/iqpilot_private/models/manager.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/manifest.json b/artifacts/iqpilot_navd_private/manifest.json index 147c4a99c..146a9618d 100644 --- a/artifacts/iqpilot_navd_private/manifest.json +++ b/artifacts/iqpilot_navd_private/manifest.json @@ -186,8 +186,8 @@ }, "python/iqpilot_private/navd/__init__.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "6e6de2f3270ad097c9b847fa10e833bac6b8eaab8ddad955603d163474a3c846", - "size": 67616 + "sha256": "10896807faa5044f6d42807fb7e5efefc6ef64243edea9da5639332964e1cb19", + "size": 67568 }, "python/iqpilot_private/navd/__init__.py": { "mode": 420, @@ -196,123 +196,128 @@ }, "python/iqpilot_private/navd/alpr_matcher.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "516370d0603f5134955826a3d8e9fea8ec0a9d27c116ad05af149a5c7ac15bcc", - "size": 269936 + "sha256": "5faf834f012075671a390de2fe4ebb09f9c7d4c05406fa89407aa9e011e9d38c", + "size": 269896 }, "python/iqpilot_private/navd/amap_client.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "dc8f27970c61a3b60c383ea69804896ee356d76c8bf7af5532a9338525fbc956", - "size": 202040 + "sha256": "a8361fe53878b61d30d430d0b0488eaabe1641e11b7e584e1ad3566370e55085", + "size": 202088 }, "python/iqpilot_private/navd/event_builder.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "96eb02a86cab08d557f8df0adebd2cc72232b9348e9896acd9b71784a86b42d5", - "size": 136960 + "sha256": "47c673a898e6ceb321f01eff980250bbc85ddd058a8161098e8e91cb02f8f4a6", + "size": 136928 }, "python/iqpilot_private/navd/helpers.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "8fb8cc47f47971c530a68ccd81b9b5d9fc8ce82cdd1270967fa845399009e519", - "size": 135960 + "sha256": "55a8b9eb2e17f9baa1a851919d3ce908b69004bfbd09591985195af2da4cc40c", + "size": 135928 }, "python/iqpilot_private/navd/incident_feed.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "b49f7ce7e9a33777ffa896a95fc4a5580988b4966d5a9330efd8c79a5116be91", - "size": 135584 + "sha256": "115b57594d411fde87f66d0d030cd5de043bf8d986274dfb8fa7007b8f752c87", + "size": 135496 }, "python/iqpilot_private/navd/iqmapd.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "747ae769bb35650dcd16b94a0a6260213373e352ede88bc1e57f114f27761d5a", - "size": 135632 + "sha256": "90c8b38b5c0a328c9ccce27292f8399546a237cc72caf837ffa4c1a55a529c47", + "size": 135600 }, "python/iqpilot_private/navd/long_decel.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "eae425cd9bf60286fff4b980c6057351cb940f28981556269f05022258d80f0c", - "size": 69752 + "sha256": "6d80f03b5a4da8083d4b7f2d4b165748556230859bcdb96c2ff5164aa5500b6c", + "size": 135256 }, "python/iqpilot_private/navd/mapbox_client.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "0fc4356fe57a11538e4a248dc803ceee61781d7c700640f78241a2d57cbb4574", - "size": 68144 + "sha256": "a6809b5c118c603706e6b709597a29daa2345fd53d736526f6a055a009ad70ac", + "size": 68128 }, "python/iqpilot_private/navd/nav_cameras.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "92521da14a5bf334324f32315b13773d37d5f7d209d4bad6d62afc12ab5d1705", - "size": 203056 + "sha256": "05f7b0433be88afdae23a68f7acd92ff0c8ce6b04d83fc46ad2233c3df51dea0", + "size": 203024 }, "python/iqpilot_private/navd/nav_turn_signals.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "67454e461abb76c7a3053a7f728baa0beb30fba235639a0a2a927a9c80443a4a", - "size": 135560 + "sha256": "96414985cacbd85d02f69473b84ff8215fbf959996ca1f1f0dfdf7c77503c9cc", + "size": 135536 + }, + "python/iqpilot_private/navd/navbridge_source.cpython-312-aarch64-linux-gnu.so": { + "mode": 493, + "sha256": "8bd53fba3f00e3f8320f873e72b3665f22b6065ee10425d270167b21d2348ad9", + "size": 136576 }, "python/iqpilot_private/navd/navd.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "9e0d5e929bfcd960fdba11804d1f70848ba40a68a65093c025a6d48171d0b2cc", - "size": 797392 + "sha256": "d395b00b81da1acdab40d6033b5ccf084effcc6531978af63d568d4ba17ee894", + "size": 862920 }, "python/iqpilot_private/navd/navincidentd.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "33d40decd32e8cfe3f9a267ebfccf48e8bfc67bf9609206ef230a9566bf5581d", - "size": 135344 + "sha256": "43bdd7f93c317f26bfa9203953b3a35bf91bd0475dc3777aa5fc3e991216c3f4", + "size": 135464 }, "python/iqpilot_private/navd/navrenderd.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "edf0d16511686ed3d4d7d6bf2b6b44fd8d484af348dab0eb415999656eb1d0af", - "size": 135584 + "sha256": "4678f2e256e0fd2b01d4441af848056b173d7d2d6c8ba590ad32b8e23ee8591e", + "size": 135552 }, "python/iqpilot_private/navd/osm_cameras.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "b11bec6f1b49f169f218a87467781b6d62d64c367e0c3df5356341adce8c3f6b", - "size": 202384 + "sha256": "52e4d03639c9d9be88209ab2e4a1f0f23c0adf81631983248f7d069d46cf61a5", + "size": 267936 }, "python/iqpilot_private/navd/reroute.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "d38218a6787234730ed39bdb04c00ab0778b1b56eefcedcb9ecfb31346d36378", - "size": 136216 + "sha256": "cb066c1e5637b8a6b60b44753b6a0855a04ce7f5771464d71fc9da245de4a56e", + "size": 136224 }, "python/iqpilot_private/navd/road_incidents.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "f89f69e128b02eebc31b4c3702d62e12747f837863ad390026ea5004e506ea7c", - "size": 203136 + "sha256": "2e226e29757151bc3cf350a933f6e8f402d7149b0b9e66b82ac9cb721cadef8e", + "size": 203096 }, "python/iqpilot_private/navd/route_manager.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "311926ffa2b4474320411240e6656ee676ce8b61d1cea444c34cd9520113a6a6", - "size": 943640 + "sha256": "2b12153db93198ec46c268384cfbd65a9ae526faa584274987ed8a289531547c", + "size": 1009128 }, "python/iqpilot_private/navd/runtime_common.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "dc08b2e6bf7be3fe0b4a7ccdfceab6c434317e7626efd9b40ea5bf15739647ba", - "size": 135760 + "sha256": "6ba9e9ae810a4e283a8ad544e1f42e899e2e98939754f9b88ffc21f320a8514f", + "size": 135752 }, "python/iqpilot_private/navd/traffic.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "f47146eddd7c8b499359d411150533c0e28e80851096d076ee8552a4d45175d9", - "size": 69720 + "sha256": "0e233af11a3c07d6469e221b5f02cebee4addfe1706d635f8ed7624eb16ff908", + "size": 69688 }, "python/iqpilot_private/navd/traffic_sources.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "98845f8be1fd44009acf88fe685f6985ffb996d5d508858bdbb3edd2984a5146", - "size": 135968 + "sha256": "8485347d40907cd0e654b93e1e872dffd156278c3868c640f7d2e51884d52a00", + "size": 135944 }, "python/iqpilot_private/navd/traffic_writer.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "15aba494968b9673987d2d0168d797bfbd307046555cb89efa2378acc8bb042a", - "size": 136936 + "sha256": "c8b907c51c69c7950bc99ff577ddf4473dbb42f90e53252e3dd325df2a4f9ed3", + "size": 136944 }, "python/iqpilot_private/navd/turn_desire.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "715f94a985599a983750affa5bf36e1fc2e6502871f1af7de553f9aaf29028cb", - "size": 69768 + "sha256": "c13b5fdec4a8d4a33dbd7c25d9ffba30f6faffa1d286438d80c4d9a615b31145", + "size": 135280 }, "python/iqpilot_private/navd/valhalla_process.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "2658d1a9f08f49e1294a3c26be733170ac7943970a79ee2969d9404cd4b55758", - "size": 204072 + "sha256": "695322ac198a75121f05989387bd32a733f18921f01f373d45e22f7ec839e8a5", + "size": 204064 }, "python/iqpilot_private/navd/web_server.cpython-312-aarch64-linux-gnu.so": { "mode": 493, - "sha256": "d03bf4d8d7d1547c5fcd085dea2ff78f8071e04e51e7f4d002f7ba23b431038e", - "size": 201400 + "sha256": "24d967c264e1b879b0517da9cd6fddefdc4787efe6a52adcd2429efaac2db3db", + "size": 201368 }, "runtime": { "entries": { @@ -351,30 +356,31 @@ } }, "signatures": { - "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": "5K4w4dDRtts8QvxBAXL0qrYofb/bg9PV/rKn/GrVmtAVDMd0DhAiKAugoxkhl8n4JviFY8ZmsHwWBrQPIMdkAA==", - "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": "dQnA8CCeRMXqiARr/Kzf2x736DuaT1/ALC8ZLDZep2/nY2IJ7StZeZ8DwOBuRPRK8KJ5HNU424QMZkVzQcDnBg==", - "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": "MJ/i1ZvGb3bYBVxKvT/zBk43CM/XT37GZa6la52Tfmqp9mrx6oz98PpvLZMgJ+18J4lSdMf2uGuJ2IHx5wWTAQ==", - "python/iqpilot_private/navd/iqmapd.cpython-312-aarch64-linux-gnu.so": "+ULQz9iDSDBtYRYSVVWz63TImB3DizGV2oFER6pmNttfJ6vA4SBVToxKV1YjHAebdMiSrTBrEkgPd5K4unE0Bg==", - "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": "vqQRU0t5AS/oUs1JWxZlwHC5mrpaaHD10jgQCLzDGUL4Yv1aFHWAoM6KfFdUldmdSG1d4e6VGu+Y2bMdBIwAAw==", - "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": "WQOzntcyeraddagnvnxAwH/ciLFMztjfEhg07HFHy+++XJPCSGctdaxlgPWX6xq9kiE7aEkcTsW2CwOwYo3tDw==", - "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": "LBV8K1SPj+bN8idsPR/3B24grXQYRNarYsCUbVaRdkfORuib70gRlGz4KtyOyYT/vpCU4iuDhnSRsd4ltH4RAg==", - "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": "jjmBJtLWRVkPsO4n7/N/pDVD9jrC4SCMm0lIT/P8HCzsMhIIAkXhRAMGKdl1kYDxK8VMGRMMF7eoiCKEFPq2AA==", - "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": "J/I+XcODFE7LKvtyImt/Dw8fh2uvQeEhZ1IWx2IHZPH8sXhuVGVQIECVFGQJGfsckjzoUpgZq8AYNReRF62sBw==", - "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": "/5mYKn9um2aBLipkFsEptfM3sOId3SKkV8AHXGslWdH9Evp2ll8XENvirAX5tV1X35WslGYIybK3Xv3cZ4o8DQ==", - "python/iqpilot_private/navd/traffic.cpython-312-aarch64-linux-gnu.so": "kfl1Mm7G3CguQGtUvDutvbd4StDnKr0pW7ojLn6gydVTyxEiD/VAEFfTKBK/CAyUcw3eeX5+U8Qq2+6o0zEUBA==", - "python/iqpilot_private/navd/traffic_sources.cpython-312-aarch64-linux-gnu.so": "SzicVJ2/F8aMjcOHVCmEeJ952a+JPL8NLI6wsVkA2f5xiOSKMdynvcf7EgvrvBA4bgTRUGOmtpoqzMiCcNh2AA==", - "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==" + "python/iqpilot_private/navd/__init__.cpython-312-aarch64-linux-gnu.so": "3zeWvLW0gfxiEeHYfOO7atzH0V9/YxbbPpLV6cdokoSP+UlxRJUrMTkJiNCiLBzXuhnNbEhj0Y6q9dLK8QNDDw==", + "python/iqpilot_private/navd/alpr_matcher.cpython-312-aarch64-linux-gnu.so": "1vJWjDPECvOrFe5UfWFN3rFeZSfO3Te9o3Xj0ue1Q+2Zt+gMkvaXgOZG3DNfbs7yaZ2yheabOhKRdwvwHGumCA==", + "python/iqpilot_private/navd/amap_client.cpython-312-aarch64-linux-gnu.so": "6IWRbqN7iDaCKDPQ3Ho6cEhWrP0Tp6f5nKoo5sXEEAtYfUJVZADBHXY7Qk5MszNoa13Sn+8H2eE0imUwjGUtDA==", + "python/iqpilot_private/navd/event_builder.cpython-312-aarch64-linux-gnu.so": "gakLE/auDWpkOm9vOzHryjZm5dAIln/GbASMoFl4iMiMRVmFmBjdV0uyY6bkVDKPVHX6FRr65f1yuJbF1d09DA==", + "python/iqpilot_private/navd/helpers.cpython-312-aarch64-linux-gnu.so": "yOqbMSdUVZSlHAiw08Yb+vSyEr2YoHBsSIWtFQa1RqoSmLbeLUeFpTiuczVaW/HtCNeZZU8mJYXWyTUM1N0xCQ==", + "python/iqpilot_private/navd/incident_feed.cpython-312-aarch64-linux-gnu.so": "8uEYXTWYXVzhDctzoEBbSc5wJ0mqX8qAe9DuXeKgfmpPsM6rR8jHpjHiyjkLAAPorWDRVN3a5W3iyH2u2tD6Cw==", + "python/iqpilot_private/navd/iqmapd.cpython-312-aarch64-linux-gnu.so": "+kTCQnh0TKGtTVl/XqtKJfrFDVJloVVhsUmt793WbvaULUK9aAJmtaEJRvTNV/DiOjYGdgL1texfnBw3x3CkDw==", + "python/iqpilot_private/navd/long_decel.cpython-312-aarch64-linux-gnu.so": "oFJS3s2xxAmMxBpLAiaFklhstR8719Ah/GtUy+YMPdaDZBP6TYLIe89aqmPjW7LUHagkmxsJogppJXl3YtFUAg==", + "python/iqpilot_private/navd/mapbox_client.cpython-312-aarch64-linux-gnu.so": "rsDD81jJXWuvS+IYSDwKVZy/C2lvnmmEh+wYucqLuUg64BIW5Q8YpdtRM9Z++fYpSut90FeYHtrIJsAavTmOAA==", + "python/iqpilot_private/navd/nav_cameras.cpython-312-aarch64-linux-gnu.so": "5CiNWqZqmmiNfnj1plhm67WEF5PXkPGr6dMsVui4VplsrVwaWCSQYJ4ywPHlsoUeX+c4FoCX7HJSNqwxjn5IBg==", + "python/iqpilot_private/navd/nav_turn_signals.cpython-312-aarch64-linux-gnu.so": "dkNKNQEHnq0Wzw/Usmwf/qNxN72cpBZBnPHRKN1ZEq5nExMqrrraTe6bn+EWM2yo1hMsXsep5JPpNGxpqqusBQ==", + "python/iqpilot_private/navd/navbridge_source.cpython-312-aarch64-linux-gnu.so": "0PDFbzaD2KoWZRAP6I38SKdUG0T11j86Ue27RgjziWLAPuxDSd6ogJPbTuPxKLV6pBIASN6y1KU3Cf4BLOkKBg==", + "python/iqpilot_private/navd/navd.cpython-312-aarch64-linux-gnu.so": "WikwGS5js59suyyzVj90X0dYz6I+wBb7N/KHRGkD4kYEX59jP8hAK+MlLsUAr9Vbmss131S8z5inlifsCjN4BA==", + "python/iqpilot_private/navd/navincidentd.cpython-312-aarch64-linux-gnu.so": "LOnh9gEJeT8leh4xo0gabomCwTOo1Xhp2oALjrsL0Ij1MCur9bLl5QE33iFVcomQr8jGH0iw7Vq1vXDMlIRuBg==", + "python/iqpilot_private/navd/navrenderd.cpython-312-aarch64-linux-gnu.so": "KthwWou6yvP+17m4g/3PGY7aPTKKjUqLT8KTtsiTr8/y3Le6YTntbn680C1hJU/xKm1j+IcnAomDw7wdma1PDA==", + "python/iqpilot_private/navd/osm_cameras.cpython-312-aarch64-linux-gnu.so": "cdd78rET10BlVNmGXsNJgYpbS9VCSNEB5HJQ9krzeMu05ikqVnI7vHA/zlxmuHHFiHnZyAN00c16mEmgf62dDw==", + "python/iqpilot_private/navd/reroute.cpython-312-aarch64-linux-gnu.so": "QyrJUPOGnI39p3n24ZCKdHG+MI/bqIvBwUdFyGO527eqHVVWJyinfneK+X7vARV+HLwxqO5bBcgwqHLdi9enAQ==", + "python/iqpilot_private/navd/road_incidents.cpython-312-aarch64-linux-gnu.so": "YkM9q3yJaDmYhExd3Te/7tpFQXXrt+/82M0QRZrVxjKRKOxrR7xu3jdjXQIT67I6WxpHzsNIFhnzX2Bl2/9eBQ==", + "python/iqpilot_private/navd/route_manager.cpython-312-aarch64-linux-gnu.so": "+Uu9KthRwOh5+YJaj1/SD/QuSOfEuT0d4CwO//wB7sCueUKsVx7+CcyAC5T2YB8bRN+42NJDn8pQeA9JcrPoDg==", + "python/iqpilot_private/navd/runtime_common.cpython-312-aarch64-linux-gnu.so": "BoQYpXsWgO+RdUhI5HL4WSk8La2HJ8V8DSFWvAylCaDNWJX3yaClso603Nf0CcKd1MDycb8J33hiHvJSd7R7AQ==", + "python/iqpilot_private/navd/traffic.cpython-312-aarch64-linux-gnu.so": "5+ip8rEk+Upsvyp2tlfdVhmIdQnlamloY1SCuwFzkSM39y+W9tvo4r7JTeb5pcMiUijmwK54m4Rvx0XWvxz5AA==", + "python/iqpilot_private/navd/traffic_sources.cpython-312-aarch64-linux-gnu.so": "WtPKZHGDG8iQj7q1UsXw6jTXxJsWLfNaw9kfJ3huWYjxWcHz0K7ibJ5JzEGSc5l5u3LdRkt6/aZHlBMrDPBaBA==", + "python/iqpilot_private/navd/traffic_writer.cpython-312-aarch64-linux-gnu.so": "VVFiWnkiwn7nwhq+6q3aYsnxMW1GLdfaGB/a/h8JV46OoSn0NOTVA72jPYlzs0d4bacEN+IgMAelCjnMlqiBBA==", + "python/iqpilot_private/navd/turn_desire.cpython-312-aarch64-linux-gnu.so": "upuJWa/0B6du9cu3JwdzK1cSqSAORKfvd6ir7sh/oWSRPEhkxyjPmo9/uoNw4Qeq2zoh3iKkV2udK5gue/PzCQ==", + "python/iqpilot_private/navd/valhalla_process.cpython-312-aarch64-linux-gnu.so": "DXSI5ljQTXPHV+QvQCQu1+oOfLKcPXMkx7qx6id0NTFPHI/M5KIooBYKgJjbN4abl+mzUXKrtOmGF/y3f0lwDw==", + "python/iqpilot_private/navd/web_server.cpython-312-aarch64-linux-gnu.so": "h4bQodknw1y0emCI3aJYviy3kzaQH8hElJMFmpS/sMvvC+sCHfOGUo+8BK+T7JGZ9/VzNXBzP8RKkHG5cAf0Cg==" } } diff --git a/artifacts/iqpilot_navd_private/manifest.json.sig b/artifacts/iqpilot_navd_private/manifest.json.sig index bb7022006..1cd57d4f4 100644 --- a/artifacts/iqpilot_navd_private/manifest.json.sig +++ b/artifacts/iqpilot_navd_private/manifest.json.sig @@ -1 +1 @@ -NH/aexXGu1jWh6ks/x7lbVEUX9VZPhETrwkIozXSjmPR2isUyVlaZppveq23NB7BeIQTJuS/+KAuZ/pbL/kaDQ== +kmjHw5sbr1uhbckWG6FoCjTR0idPL+RGlQ19Wri9phayqsni9P3V2rqLDUPeZ0ds+CRqMb378Jgghj6eJ6gxCQ== diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/__init__.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/__init__.cpython-312-aarch64-linux-gnu.so index 8c01230a6..51a6fa753 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/__init__.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/__init__.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/alpr_matcher.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/alpr_matcher.cpython-312-aarch64-linux-gnu.so index a65bd05a8..76cd3a52e 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/alpr_matcher.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/alpr_matcher.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/amap_client.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/amap_client.cpython-312-aarch64-linux-gnu.so index fb6dfc4dc..538117876 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/amap_client.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/amap_client.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/event_builder.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/event_builder.cpython-312-aarch64-linux-gnu.so index bd35becf7..8cdf95127 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/event_builder.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/event_builder.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/helpers.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/helpers.cpython-312-aarch64-linux-gnu.so index 6dfe5daa2..7ea4bb95a 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/helpers.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/helpers.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/incident_feed.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/incident_feed.cpython-312-aarch64-linux-gnu.so index ab4e17737..ccd477f85 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/incident_feed.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/incident_feed.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/iqmapd.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/iqmapd.cpython-312-aarch64-linux-gnu.so index 975d09ef3..d895a49f9 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/iqmapd.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/iqmapd.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/long_decel.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/long_decel.cpython-312-aarch64-linux-gnu.so index da7445b64..1b78dd316 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/long_decel.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/long_decel.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/mapbox_client.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/mapbox_client.cpython-312-aarch64-linux-gnu.so index 30d3aa23d..797c8ed72 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/mapbox_client.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/mapbox_client.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/nav_cameras.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/nav_cameras.cpython-312-aarch64-linux-gnu.so index cf2872da8..efbaa657b 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/nav_cameras.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/nav_cameras.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/nav_turn_signals.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/nav_turn_signals.cpython-312-aarch64-linux-gnu.so index 5c2ad19d0..743c91630 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/nav_turn_signals.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/nav_turn_signals.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/navbridge_source.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/navbridge_source.cpython-312-aarch64-linux-gnu.so new file mode 100755 index 000000000..950c6ffb5 Binary files /dev/null and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/navbridge_source.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/navd.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/navd.cpython-312-aarch64-linux-gnu.so index 9b1c09f73..ddd9a89df 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/navd.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/navd.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/navincidentd.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/navincidentd.cpython-312-aarch64-linux-gnu.so index 46dfa6cc6..d4cc31602 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/navincidentd.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/navincidentd.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/navrenderd.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/navrenderd.cpython-312-aarch64-linux-gnu.so index f772bb920..d8020b7d2 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/navrenderd.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/navrenderd.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/osm_cameras.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/osm_cameras.cpython-312-aarch64-linux-gnu.so index e1a1e021e..c3104666e 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/osm_cameras.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/osm_cameras.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/reroute.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/reroute.cpython-312-aarch64-linux-gnu.so index b60412bbe..9f07771d3 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/reroute.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/reroute.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/road_incidents.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/road_incidents.cpython-312-aarch64-linux-gnu.so index 3782626d8..e0d587bb9 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/road_incidents.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/road_incidents.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/route_manager.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/route_manager.cpython-312-aarch64-linux-gnu.so index f231af450..b522b7a1e 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/route_manager.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/route_manager.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/runtime_common.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/runtime_common.cpython-312-aarch64-linux-gnu.so index 23397d0f0..15a0c3a12 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/runtime_common.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/runtime_common.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/traffic.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/traffic.cpython-312-aarch64-linux-gnu.so index 2c4cdc159..1995b9f60 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/traffic.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/traffic.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/traffic_sources.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/traffic_sources.cpython-312-aarch64-linux-gnu.so index bc22c99b7..e1b385c44 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/traffic_sources.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/traffic_sources.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/traffic_writer.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/traffic_writer.cpython-312-aarch64-linux-gnu.so index 1a0992dd7..b9c4bbe4c 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/traffic_writer.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/traffic_writer.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/turn_desire.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/turn_desire.cpython-312-aarch64-linux-gnu.so index 8b5f80ba2..11fccb337 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/turn_desire.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/turn_desire.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/valhalla_process.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/valhalla_process.cpython-312-aarch64-linux-gnu.so index ba2de2caa..946608bb7 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/valhalla_process.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/valhalla_process.cpython-312-aarch64-linux-gnu.so differ diff --git a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/web_server.cpython-312-aarch64-linux-gnu.so b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/web_server.cpython-312-aarch64-linux-gnu.so index 78a84d4ea..39a94a77a 100755 Binary files a/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/web_server.cpython-312-aarch64-linux-gnu.so and b/artifacts/iqpilot_navd_private/python/iqpilot_private/navd/web_server.cpython-312-aarch64-linux-gnu.so differ diff --git a/iqpilot/common/params_keys.h b/iqpilot/common/params_keys.h index 73188a9cd..44ec73f94 100644 --- a/iqpilot/common/params_keys.h +++ b/iqpilot/common/params_keys.h @@ -238,6 +238,7 @@ inline static std::unordered_map keys = { {"IQEmacEnabled", {PERSISTENT, BOOL, "0"}}, {"IQEmacHost", {PERSISTENT, STRING}}, {"IQEmacModel", {PERSISTENT, STRING}}, + {"IQEmacSmallModel", {PERSISTENT, BOOL, "0"}}, {"IQEmacCatalogCache", {PERSISTENT, STRING}}, {"MacModelDownloadProgress", {CLEAR_ON_MANAGER_START, STRING, "1.0"}}, {"MacModelStatus", {CLEAR_ON_MANAGER_START, STRING}}, @@ -315,6 +316,7 @@ inline static std::unordered_map keys = { {"IQEmacEnabled", {PERSISTENT, BOOL, "0"}}, {"IQEmacHost", {PERSISTENT, STRING}}, {"IQEmacModel", {PERSISTENT, STRING}}, + {"IQEmacSmallModel", {PERSISTENT, BOOL, "0"}}, {"IQEmacCatalogCache", {PERSISTENT, JSON}}, {"IQEgpuDisabled", {PERSISTENT, BOOL, "0"}}, {"IQEgpuEnabled", {PERSISTENT, BOOL, "0"}}, @@ -359,6 +361,14 @@ inline static std::unordered_map keys = { // iqpilot model params {"CameraOffset", {PERSISTENT, FLOAT, "0.0"}}, + {"IQAndroidNav", {PERSISTENT, BOOL, "0"}}, + {"IQAndroidNavStatus", {PERSISTENT, STRING}}, + // "waze" or "maps": exactly one runs, the other is disabled outright. + {"IQAndroidNavApp", {PERSISTENT, STRING, "waze"}}, + // Consumed by androidd to sign the container in once, then cleared: the credential is + // never meant to survive a manager restart or reach a log. + {"IQAndroidNavEmail", {CLEAR_ON_MANAGER_START | DONT_LOG, STRING}}, + {"IQAndroidNavPassword", {CLEAR_ON_MANAGER_START | DONT_LOG, STRING}}, {"IQLiveSteerDelay", {PERSISTENT, BOOL, "1"}}, {"IQLateralAccelSlew", {PERSISTENT, BOOL, "0"}}, {"IQLateralCurvatureLookahead", {PERSISTENT, BOOL, "0"}}, diff --git a/iqpilot/selfdrive/controls/controlsd.py b/iqpilot/selfdrive/controls/controlsd.py index 9a6f43ff4..3fed782d3 100755 --- a/iqpilot/selfdrive/controls/controlsd.py +++ b/iqpilot/selfdrive/controls/controlsd.py @@ -235,6 +235,7 @@ class Controls(IQControlsLayer): actuators = CC.actuators actuators.longControlState = self.LoC.long_control_state + actuators.speed = float(max(long_plan.speeds, default=0.0)) if not CC.latActive: self.LaC.reset() diff --git a/iqpilot/selfdrive/iqmodeld/modeld_selector.py b/iqpilot/selfdrive/iqmodeld/modeld_selector.py index a6a9151ae..636b985b9 100644 --- a/iqpilot/selfdrive/iqmodeld/modeld_selector.py +++ b/iqpilot/selfdrive/iqmodeld/modeld_selector.py @@ -63,6 +63,11 @@ def resolve_model_name(params, keys) -> str: from iqpilot.selfdrive.iqmodeld.egpu_model import DEFAULT_EGPU_MODEL, resolve_egpu_model resolved = resolve_egpu_model(params, allow_refresh=False) return resolved["key"] if resolved else DEFAULT_EGPU_MODEL + if params.get_bool("IQEmacSmallModel"): + from iqpilot.selfdrive.iqmodeld.models.helpers import get_active_bundle + bundle = get_active_bundle(params) + if bundle is not None and (bundle.internalName or bundle.displayName): + return bundle.internalName or bundle.displayName name = params.get("IQEmacModel") or b"lebrowski" return name.decode() if isinstance(name, bytes) else name @@ -168,7 +173,7 @@ def _patch_and_send(pm: PubMaster, payload: dict, frame_drop_perc: float, select if mismatch is None: mismatch = source_lag > 0 - big = payload.get("source") in BIG_SOURCES + big = bool(payload.get("big", payload.get("source") in BIG_SOURCES)) model_msg = log_from_bytes(msgs["modelV2"]).as_builder() if mismatch: model_msg.modelV2.frameId = target diff --git a/iqpilot/selfdrive/iqmodeld/tests/test_egpu_worker.py b/iqpilot/selfdrive/iqmodeld/tests/test_egpu_worker.py index 96fae1a8b..04889a533 100644 --- a/iqpilot/selfdrive/iqmodeld/tests/test_egpu_worker.py +++ b/iqpilot/selfdrive/iqmodeld/tests/test_egpu_worker.py @@ -272,6 +272,23 @@ class TestChannelContract: assert sent["modelV2"].modelV2.frameDropPerc == 0.0 assert sent["cameraOdometry"].valid + def test_selector_big_flag_follows_payload_then_source(self): + from iqpilot.selfdrive.iqmodeld.modeld_selector import _patch_and_send + + sent = {} + + class PM: + def send(self, service, msg): + sent[service] = msg + + payload = make_big_channel_payload(42, True, 0.03, 25.0, self._real_msgs()) + _patch_and_send(PM(), payload, frame_drop_perc=0.0, selector_dropped=0, target=42, source_lag=0) + assert sent["modelV2"].modelV2.big and sent["drivingModelData"].drivingModelData.big + + small_on_mac = {**make_big_channel_payload(43, True, 0.03, 25.0, self._real_msgs()), "source": "mac_big", "big": False} + _patch_and_send(PM(), small_on_mac, frame_drop_perc=0.0, selector_dropped=0, target=43, source_lag=0) + assert not sent["modelV2"].modelV2.big and not sent["drivingModelData"].drivingModelData.big + def test_selector_lag_patches_frame_id(self): from iqpilot.selfdrive.iqmodeld.modeld_selector import _patch_and_send diff --git a/iqpilot/selfdrive/longitudinal_settings.py b/iqpilot/selfdrive/longitudinal_settings.py index 9041f8b5a..c42d346bc 100644 --- a/iqpilot/selfdrive/longitudinal_settings.py +++ b/iqpilot/selfdrive/longitudinal_settings.py @@ -9,6 +9,7 @@ LONGITUDINAL_MODE_STOCK = 0 LONGITUDINAL_MODE_CHILL = 1 LONGITUDINAL_MODE_DYNAMIC = 2 LONGITUDINAL_MODE_PILOT = 3 +IQ_LONGITUDINAL_MODES = (LONGITUDINAL_MODE_CHILL, LONGITUDINAL_MODE_DYNAMIC, LONGITUDINAL_MODE_PILOT) PERSONALITY_AGGRESSIVE = log.LongitudinalPersonality.schema.enumerants["aggressive"] PERSONALITY_STANDARD = log.LongitudinalPersonality.schema.enumerants["standard"] @@ -60,6 +61,20 @@ def apply_longitudinal_mode(params, mode: int) -> None: raise ValueError(f"invalid longitudinal mode: {mode}") +def longitudinal_mode_needs_cycle(previous: int, mode: int) -> bool: + return (previous == LONGITUDINAL_MODE_STOCK) != (mode == LONGITUDINAL_MODE_STOCK) + + +def next_longitudinal_mode(current: int, onroad: bool, iq_modes_available: bool) -> int: + if onroad: + order = list(IQ_LONGITUDINAL_MODES) + else: + order = [LONGITUDINAL_MODE_STOCK] + (list(IQ_LONGITUDINAL_MODES) if iq_modes_available else []) + if current not in order: + return current if onroad else order[0] + return order[(order.index(current) + 1) % len(order)] + + def get_follow_distance_state(params) -> tuple[int | None, bool]: mode = get_longitudinal_mode(params) if mode == LONGITUDINAL_MODE_STOCK: diff --git a/iqpilot/selfdrive/selfdrived/tests/test_longitudinal_settings.py b/iqpilot/selfdrive/selfdrived/tests/test_longitudinal_settings.py index 7c57338da..81fefa403 100644 --- a/iqpilot/selfdrive/selfdrived/tests/test_longitudinal_settings.py +++ b/iqpilot/selfdrive/selfdrived/tests/test_longitudinal_settings.py @@ -7,6 +7,7 @@ import pytest from iqpilot.selfdrive.longitudinal_settings import ( LONGITUDINAL_MODE_CHILL, LONGITUDINAL_MODE_DYNAMIC, + LONGITUDINAL_MODE_PILOT, LONGITUDINAL_MODE_STOCK, PERSONALITY_AGGRESSIVE, PERSONALITY_RELAXED, @@ -16,6 +17,8 @@ from iqpilot.selfdrive.longitudinal_settings import ( get_follow_distance_state, get_longitudinal_mode, get_runtime_personality, + longitudinal_mode_needs_cycle, + next_longitudinal_mode, set_valid_personality, ) @@ -108,3 +111,31 @@ def test_dynamic_and_pilot_enable_valid_personality_selection(): params.values["IQDynamicMode"] = False assert get_follow_distance_state(params) == (PERSONALITY_STANDARD, True) + + +def test_onroad_cycles_only_between_iq_modes(): + assert next_longitudinal_mode(LONGITUDINAL_MODE_CHILL, True, True) == LONGITUDINAL_MODE_DYNAMIC + assert next_longitudinal_mode(LONGITUDINAL_MODE_DYNAMIC, True, True) == LONGITUDINAL_MODE_PILOT + assert next_longitudinal_mode(LONGITUDINAL_MODE_PILOT, True, True) == LONGITUDINAL_MODE_CHILL + + +def test_onroad_stock_acc_is_locked(): + assert next_longitudinal_mode(LONGITUDINAL_MODE_STOCK, True, True) == LONGITUDINAL_MODE_STOCK + assert next_longitudinal_mode(LONGITUDINAL_MODE_STOCK, True, False) == LONGITUDINAL_MODE_STOCK + + +def test_offroad_cycles_through_stock_acc(): + assert next_longitudinal_mode(LONGITUDINAL_MODE_PILOT, False, True) == LONGITUDINAL_MODE_STOCK + assert next_longitudinal_mode(LONGITUDINAL_MODE_STOCK, False, True) == LONGITUDINAL_MODE_CHILL + + +def test_offroad_without_iq_modes_only_offers_stock_acc(): + assert next_longitudinal_mode(LONGITUDINAL_MODE_STOCK, False, False) == LONGITUDINAL_MODE_STOCK + assert next_longitudinal_mode(LONGITUDINAL_MODE_PILOT, False, False) == LONGITUDINAL_MODE_STOCK + + +def test_cycle_only_when_crossing_stock_boundary(): + assert longitudinal_mode_needs_cycle(LONGITUDINAL_MODE_STOCK, LONGITUDINAL_MODE_CHILL) + assert longitudinal_mode_needs_cycle(LONGITUDINAL_MODE_PILOT, LONGITUDINAL_MODE_STOCK) + assert not longitudinal_mode_needs_cycle(LONGITUDINAL_MODE_CHILL, LONGITUDINAL_MODE_PILOT) + assert not longitudinal_mode_needs_cycle(LONGITUDINAL_MODE_DYNAMIC, LONGITUDINAL_MODE_CHILL) diff --git a/iqpilot/selfdrive/ui/mici/layouts/settings/iq_widgets.py b/iqpilot/selfdrive/ui/mici/layouts/settings/iq_widgets.py index c48e7c42f..20b6ca42e 100644 --- a/iqpilot/selfdrive/ui/mici/layouts/settings/iq_widgets.py +++ b/iqpilot/selfdrive/ui/mici/layouts/settings/iq_widgets.py @@ -6,13 +6,17 @@ from iqpilot.common.params import Params, UnknownKeyName from iqpilot.selfdrive.longitudinal_settings import ( LONGITUDINAL_MODE_DYNAMIC, LONGITUDINAL_MODE_PILOT, + LONGITUDINAL_MODE_STOCK, PERSONALITY_VALUES, apply_longitudinal_mode, get_follow_distance_state, get_longitudinal_mode, + longitudinal_mode_needs_cycle, + next_longitudinal_mode, set_valid_personality, ) from iqpilot.selfdrive.ui.mici.widgets.stock_button import BigButton, BigMultiToggle, BigToggle, BigParamControl +from iqpilot.selfdrive.ui.ui_state import ui_state from iqpilot.system.ui.lib.multilang import tr @@ -138,24 +142,48 @@ class IQModeSelector(BigMultiToggle): super().__init__(tr("IQ Mode"), self._display_options) self._params = Params() self._mode_callback = mode_callback + self._mode = LONGITUDINAL_MODE_STOCK + self._iq_modes_available = False self.refresh() + self.set_enabled(lambda: self._next() != self._mode) def _index(self) -> int: return get_longitudinal_mode(self._params) def is_dynamic(self) -> bool: - return self._index() == 2 + return self._mode == LONGITUDINAL_MODE_DYNAMIC + + def _toyota_factory_long_forced(self) -> bool: + cp = ui_state.CP + return bool(cp is not None and cp.brand == "toyota" and self._params.get_bool("IQToyotaFactoryLong")) + + def _read_iq_modes_available(self) -> bool: + cp = ui_state.CP + alpha_available = bool(cp is not None and cp.alphaLongitudinalAvailable) + return alpha_available or self._params.get_bool("AlphaLongitudinalEnabled") or self._toyota_factory_long_forced() + + def _next(self) -> int: + return next_longitudinal_mode(self._mode, ui_state.is_onroad(), self._iq_modes_available) def refresh(self): - self.set_value(self._display_options[self._index()]) + self._mode = self._index() + self._iq_modes_available = self._read_iq_modes_available() + self.set_value(self._display_options[self._mode]) def _apply(self, idx: int): + previous = self._mode + toyota_forced = self._toyota_factory_long_forced() apply_longitudinal_mode(self._params, idx) - self._params.put_bool("OnroadCycleRequested", True) + if idx != LONGITUDINAL_MODE_STOCK and toyota_forced: + self._params.put_bool("IQToyotaFactoryLong", False) + if longitudinal_mode_needs_cycle(previous, idx) or (idx != LONGITUDINAL_MODE_STOCK and toyota_forced): + self._params.put_bool("OnroadCycleRequested", True) def _handle_mouse_release(self, mouse_pos): - nxt = (self._index() + 1) % len(self.OPTIONS) + nxt = self._next() + if nxt == self._mode: + return self._apply(nxt) - self.set_value(self._display_options[nxt]) + self.refresh() if self._mode_callback: self._mode_callback() diff --git a/iqpilot/selfdrive/ui/mici/layouts/settings/models.py b/iqpilot/selfdrive/ui/mici/layouts/settings/models.py index d0ce457c0..b3348412b 100644 --- a/iqpilot/selfdrive/ui/mici/layouts/settings/models.py +++ b/iqpilot/selfdrive/ui/mici/layouts/settings/models.py @@ -128,6 +128,8 @@ class ModelsLayoutMici(NavScroller): self._big = BigButton(tr("big model")) self._big.set_click_callback(self._show_big_models) + self._small_on_mac = BigParamControl(tr("active model on eMac"), "IQEmacSmallModel", toggle_callback=self._small_on_mac_toggled) + self._cancel = BigButton(tr("stop download")) self._cancel.set_click_callback(self._cancel_model_request) self._cancel.set_visible(self._is_downloading) @@ -158,7 +160,8 @@ class ModelsLayoutMici(NavScroller): self._lane_speed = MappedParamToggle(tr("lane turn speed"), "IQLaneTurnValue", [tr("slow"), tr("normal"), tr("fast")], _LANE_TURN_VALUES) self._lane_speed.set_visible(lambda: self._lane_turn._checked) - self._main_items = [self._current, self._big, self._cancel, self._supercombo, self._vision, self._policy, self._redownload, self._refresh, self._clear, + self._main_items = [self._current, self._big, self._small_on_mac, self._cancel, self._supercombo, self._vision, self._policy, + self._redownload, self._refresh, self._clear, self._steer_delay, self._sw_delay, self._lane_turn, self._lane_speed] self._scroller.add_widgets(self._main_items) @@ -394,9 +397,28 @@ class ModelsLayoutMici(NavScroller): except (TypeError, ValueError): return None + def _small_on_mac_toggled(self, checked: bool) -> None: + p = ui_state.params + if checked: + p.put_bool("IQEmacEnabled", True) + else: + p.put_bool("IQEmacEnabled", bool(p.get("IQEmacModel"))) + + def _small_on_mac_value(self) -> str: + try: + active = self.model_manager.activeBundle + name = _display_model_name(active) if active and active.ref else "" + except Exception: + name = "" + return f"{name} ({tr('eMac')})" if name else tr("active model") + def _big_model_value(self) -> str: p = ui_state.params dock = bool(getattr(ui_state.sm["deviceState"], "egpuDockPresent", False)) + if p.get_bool("IQEmacEnabled") and p.get_bool("IQEmacSmallModel"): + progress = self._big_setup_progress() + value = self._small_on_mac_value() + return f"{value} {int(progress * 100)}%" if progress is not None and progress < 1.0 else value if not p.get_bool("IQEmacEnabled") and not dock: return tr("Off") key = p.get("IQEmacModel") @@ -577,5 +599,5 @@ class ModelsLayoutMici(NavScroller): def show_event(self): super().show_event() - for w in (self._steer_delay, self._sw_delay, self._lane_turn, self._lane_speed): + for w in (self._steer_delay, self._sw_delay, self._lane_turn, self._lane_speed, self._small_on_mac): w.refresh() diff --git a/iqpilot/system/android/__init__.py b/iqpilot/system/android/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/iqpilot/system/android/androidd.py b/iqpilot/system/android/androidd.py new file mode 100644 index 000000000..404ced7c2 --- /dev/null +++ b/iqpilot/system/android/androidd.py @@ -0,0 +1,200 @@ +# Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos +from __future__ import annotations + +import json +import os +import socket +import subprocess +import time + +from iqpilot.cereal import messaging +from iqpilot.common.params import Params +from iqpilot.common.realtime import Ratekeeper +from iqpilot.common.swaglog import cloudlog + +ANDROID_ROOT = "/data/android" +HEADLESS = f"{ANDROID_ROOT}/waydroid_headless.sh" +TRIM = f"{ANDROID_ROOT}/android_trim.sh" +GUARD = f"{ANDROID_ROOT}/android_guard.sh" +LXC_ATTACH = f"{ANDROID_ROOT}/root/usr/bin/lxc-attach" +LD = f"{ANDROID_ROOT}/root/usr/lib/aarch64-linux-gnu" + +# Waze's launcher is FreeMapAppActivity; there is no com.waze.MainActivity, and asking for +# one fails with "Activity class does not exist" rather than anything that names the problem. +NAV_APPS = { + "waze": ("com.waze", "com.waze/.FreeMapAppActivity"), + "maps": ("com.google.android.apps.maps", "com.google.android.apps.maps/com.google.android.maps.MapsActivity"), +} +BRIDGE_HOST = "192.168.240.112" +BRIDGE_PORT = 8099 +GPS_SOURCES = ["iqLiveLocation", "liveLocationKalman", "gpsLocationExternal", "gpsLocation"] +PROVIDERS = ("gps", "fused", "network") +GPS_INTERVAL_S = 0.5 + + +def attach(*args: str, timeout: float = 10.0) -> subprocess.CompletedProcess: + cmd = ["sudo", "-n", "env", f"LD_LIBRARY_PATH={LD}", LXC_ATTACH, + "-P", "/var/lib/waydroid/lxc", "-n", "waydroid", "--", *args] + return subprocess.run(cmd, capture_output=True, text=True, timeout=timeout, check=False) + + +def container_booted() -> bool: + try: + return attach("/system/bin/getprop", "sys.boot_completed", timeout=8).stdout.strip() == "1" + except (subprocess.SubprocessError, OSError): + return False + + +def bring_up() -> None: + # AGNOS mounts / read-only, so no unit file can be installed; a transient unit is the only + # way the compositor and lxc-start survive this process exiting. + subprocess.run(["sudo", "-n", "systemd-run", "--unit=iq-android", "--service-type=oneshot", + "--remain-after-exit", HEADLESS, "up"], + capture_output=True, text=True, timeout=120, check=False) + + +def start_guard() -> None: + subprocess.run(["sudo", "-n", "systemd-run", "--unit=iq-android-guard", GUARD], + capture_output=True, text=True, timeout=30, check=False) + + +def trim(nav_app: str) -> None: + subprocess.run(["sudo", "-n", "env", f"ANDROID_NAV_APP={nav_app}", TRIM], + capture_output=True, timeout=240, check=False) + + +def enable_mock_location() -> None: + # Wiped by every container restart, and the package form does not cover uid 0: without the + # --uid form every injection fails with SecurityException and the apps just say "no GPS". + attach("/system/bin/cmd", "appops", "set", "--uid", "0", "android:mock_location", "allow") + for p in PROVIDERS: + attach("/system/bin/cmd", "location", "providers", "add-test-provider", p) + attach("/system/bin/cmd", "location", "providers", "set-test-provider-enabled", p, "true") + # The a11y tree is only updated while the display is awake; asleep it emits nothing at all. + attach("/system/bin/svc", "power", "stayon", "true") + + +def inject(lat: float, lon: float) -> None: + for p in PROVIDERS: + attach("/system/bin/cmd", "location", "providers", "set-test-provider-location", p, + "--location", f"{lat:.6f},{lon:.6f}", "--accuracy", "4", timeout=6) + + +def read_position(sm: messaging.SubMaster) -> tuple[float, float] | None: + for src in GPS_SOURCES: + if src not in sm.data or not sm.valid.get(src, False): + continue + msg = sm[src] + for lat_a, lon_a in (("latitude", "longitude"), ("lat", "lon")): + lat = getattr(msg, lat_a, None) + lon = getattr(msg, lon_a, None) + if lat is not None and lon is not None and (lat or lon): + return float(lat), float(lon) + return None + + +class AndroidNavDaemon: + def __init__(self) -> None: + self.params = Params() + self.sources = [s for s in GPS_SOURCES if s in messaging.SERVICE_LIST] + self.sm = messaging.SubMaster(self.sources) if self.sources else None + self.last_inject = 0.0 + self.up = False + + def status(self, text: str) -> None: + self.params.put("IQAndroidNavStatus", text) + + def sign_in(self) -> None: + email = self.params.get("IQAndroidNavEmail", encoding="utf8") + password = self.params.get("IQAndroidNavPassword", encoding="utf8") + if not email or not password: + return + try: + with socket.create_connection((BRIDGE_HOST, BRIDGE_PORT), timeout=10) as s: + s.sendall(json.dumps({"cmd": "signin", "email": email, "password": password}).encode() + b"\n") + self.status("sign-in requested") + except OSError: + cloudlog.exception("androidd: sign-in request failed") + self.status("sign-in failed") + finally: + # Never let the credential outlive the one use it was handed over for. + self.params.remove("IQAndroidNavEmail") + self.params.remove("IQAndroidNavPassword") + + def nav_app(self) -> str: + value = self.params.get("IQAndroidNavApp", encoding="utf8") or "waze" + return value if value in NAV_APPS else "waze" + + def enforce_single_app(self, nav_app: str) -> None: + for name, (pkg, _) in NAV_APPS.items(): + if name != nav_app: + attach("/system/bin/am", "force-stop", pkg) + + def ensure_app_running(self, nav_app: str) -> None: + pkg, component = NAV_APPS[nav_app] + if attach("/system/bin/pidof", pkg, timeout=8).stdout.strip(): + return + attach("/system/bin/am", "start", "-n", component, timeout=20) + + def ensure_up(self) -> None: + if container_booted(): + if not self.up: + nav_app = self.nav_app() + enable_mock_location() + trim(nav_app) + self.enforce_single_app(nav_app) + start_guard() + self.status(f"running:{nav_app}") + self.up = True + return + self.up = False + self.status("starting") + bring_up() + + def step(self) -> None: + if not self.params.get_bool("IQAndroidNav"): + if self.up: + subprocess.run(["sudo", "-n", "systemctl", "stop", "iq-android", "iq-android-guard"], + capture_output=True, timeout=60, check=False) + self.up = False + self.status("disabled") + return + + self.ensure_up() + if not self.up: + return + + self.sign_in() + self.ensure_app_running(self.nav_app()) + + if self.sm is None: + return + self.sm.update(0) + now = time.monotonic() + if now - self.last_inject < GPS_INTERVAL_S: + return + position = read_position(self.sm) + if position is not None: + self.last_inject = now + try: + inject(*position) + except subprocess.SubprocessError: + cloudlog.exception("androidd: location inject failed") + + +def main() -> None: + if not os.path.exists(HEADLESS): + cloudlog.warning("androidd: android stack not staged, exiting") + return + daemon = AndroidNavDaemon() + rk = Ratekeeper(2.0, print_delay_threshold=None) + while True: + try: + daemon.step() + except Exception: + cloudlog.exception("androidd: step failed") + rk.keep_time() + + +if __name__ == "__main__": + main() diff --git a/iqpilot/system/manager/process_config.py b/iqpilot/system/manager/process_config.py index be81b4942..3f84ddf00 100644 --- a/iqpilot/system/manager/process_config.py +++ b/iqpilot/system/manager/process_config.py @@ -67,6 +67,9 @@ def qcomgps(started: bool, params: Params, CP: car.CarParams) -> bool: def always_run(started: bool, params: Params, CP: car.CarParams) -> bool: return True +def android_nav(started: bool, params: Params, CP: car.CarParams) -> bool: + return params.get_bool("IQAndroidNav") + def only_onroad(started: bool, params: Params, CP: car.CarParams) -> bool: return started @@ -176,6 +179,7 @@ procs = [ PythonProcess("journald", "iqpilot.system.journald", only_onroad, platform.system() != "Darwin"), PythonProcess("micd", "iqpilot.system.micd", or_(iscar, livestream)), PythonProcess("timed", "iqpilot.system.timed", always_run, enabled=not PC), + PythonProcess("androidd", "iqpilot.system.android.androidd", android_nav, enabled=TICI, restart_if_crash=True), PythonProcess("dmonitoringmodeld", "iqpilot.selfdrive.dmonitoringmodeld.dmonitoringmodeld", driver_monitoring, enabled=not PC), diff --git a/iqpilot/tools/cabana/SConscript b/iqpilot/tools/cabana/SConscript index 721455d7a..d1b7279eb 100644 --- a/iqpilot/tools/cabana/SConscript +++ b/iqpilot/tools/cabana/SConscript @@ -1,10 +1,6 @@ import os import sys -venv_site_packages = os.path.join(Dir("#").abspath, ".venv", "lib", "python3.12", "site-packages") -if os.path.isdir(venv_site_packages) and venv_site_packages not in sys.path: - sys.path.insert(0, venv_site_packages) - import imgui import iqdbc import libusb diff --git a/iqpilot/tools/cabana/streams/replaystream.cc b/iqpilot/tools/cabana/streams/replaystream.cc index 504620e8d..1287a94f1 100644 --- a/iqpilot/tools/cabana/streams/replaystream.cc +++ b/iqpilot/tools/cabana/streams/replaystream.cc @@ -49,7 +49,7 @@ void ReplayStream::mergeSegments() { } bool ReplayStream::loadRoute(const std::string &route, const std::string &data_dir, uint32_t replay_flags, bool auto_source) { - replay.reset(new Replay(route, {"can", "narrowRoadEncodeIdx", "cabinEncodeIdx", "wideRoadEncodeIdx", "carParams"}, + replay.reset(new Replay(route, {"can", "roadEncodeIdx", "driverEncodeIdx", "wideRoadEncodeIdx", "carParams"}, {}, nullptr, replay_flags, data_dir, auto_source)); replay->setSegmentCacheLimit(settings.max_cached_minutes); replay->installEventFilter([this](const Event *event) { return eventFilter(event); }); diff --git a/iqpilot/tools/cabana/test_cabana_konn3kt.py b/iqpilot/tools/cabana/test_cabana_konn3kt.py index 4fb9ac4c3..e73030c64 100644 --- a/iqpilot/tools/cabana/test_cabana_konn3kt.py +++ b/iqpilot/tools/cabana/test_cabana_konn3kt.py @@ -90,3 +90,16 @@ class TestFrontendRemoval: def test_imgui_frontend_is_present(self): assert (CABANA_DIR / "ui" / "app.cc").is_file() assert (CABANA_DIR / "ui" / "main.cc").is_file() + + def test_stream_selector_stays_in_main_window(self): + app = read("ui/app.cc") + assert "io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable" not in app + + +class TestReplayVideo: + def test_iqpilot_camera_index_services_are_replayed(self): + source = read("streams/replaystream.cc") + for service in ("roadEncodeIdx", "driverEncodeIdx", "wideRoadEncodeIdx"): + assert f'"{service}"' in source + assert '"narrowRoadEncodeIdx"' not in source + assert '"cabinEncodeIdx"' not in source diff --git a/iqpilot/tools/cabana/ui/app.cc b/iqpilot/tools/cabana/ui/app.cc index 9eb2944d7..2f20f74db 100644 --- a/iqpilot/tools/cabana/ui/app.cc +++ b/iqpilot/tools/cabana/ui/app.cc @@ -144,8 +144,6 @@ public: ImPlot::CreateContext(); ImGuiIO &io = ImGui::GetIO(); io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; - io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; - io.ConfigViewportsNoDecoration = false; io.IniFilename = nullptr; io.LogFilename = nullptr; if (!ImGui_ImplGlfw_InitForOpenGL(window, true)) { diff --git a/iqpilot/tools/cabana/ui/dialogs/streamselector.cc b/iqpilot/tools/cabana/ui/dialogs/streamselector.cc index 4aa3c8960..584af2ec3 100644 --- a/iqpilot/tools/cabana/ui/dialogs/streamselector.cc +++ b/iqpilot/tools/cabana/ui/dialogs/streamselector.cc @@ -15,19 +15,19 @@ #include "tools/cabana/utils/util.h" void OpenReplayWidget::draw() { - ImGui::AlignTextToFramePadding(); + ImGui::TextDisabled("Replay a local or Konn3kt route with optional camera streams."); + ImGui::Spacing(); ImGui::TextUnformatted("Route"); - ImGui::SameLine(); - ImGui::SetNextItemWidth(-250.0f); + ImGui::SetNextItemWidth(-1.0f); inputText("##route", &route_, "Enter route name or browse for local/remote route"); - ImGui::SameLine(); - if (ImGui::Button("Remote route...")) { + const float route_button_width = (ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ItemSpacing.x) * 0.5f; + if (ImGui::Button("Browse Konn3kt routes", ImVec2(route_button_width, 34.0f))) { routes_dialog_.open(utils::guarded(alive_, [this](bool accepted, const std::string &route) { if (accepted) route_ = route; })); } ImGui::SameLine(); - if (ImGui::Button("Local route...")) { + if (ImGui::Button("Choose local route", ImVec2(-1.0f, 34.0f))) { FileDialog::getExistingDirectory("Open Local Route", settings.last_route_dir, utils::guarded(alive_, [this](const std::string &dir) { if (!dir.empty()) { route_ = dir; @@ -35,6 +35,8 @@ void OpenReplayWidget::draw() { } })); } + ImGui::Spacing(); + ImGui::SeparatorText("Camera streams"); checkBox("Road camera", &cameras_[0]); ImGui::SameLine(); checkBox("Driver camera", &cameras_[1]); @@ -126,6 +128,8 @@ void OpenPandaWidget::buildConfigForm() { } void OpenPandaWidget::draw() { + ImGui::TextDisabled("Connect directly to a Panda and configure each CAN bus."); + ImGui::Spacing(); if (already_connected_) { ImGui::Text("Already connected to %s.", can->routeName().c_str()); ImGui::TextUnformatted("Close the current connection via [File menu -> Close Stream] before connecting to another Panda."); @@ -184,6 +188,8 @@ std::unique_ptr OpenPandaWidget::open() { } void OpenDeviceWidget::draw() { + ImGui::TextDisabled("Connect to a running IQ.Pilot instance or a local message queue."); + ImGui::Spacing(); ImGui::RadioButton("MSGQ", &mode_, 0); ImGui::RadioButton("ZMQ", &mode_, 1); ImGui::RadioButton("Bridge", &mode_, 2); @@ -226,6 +232,8 @@ void OpenSocketCanWidget::refreshDevices() { } void OpenSocketCanWidget::draw() { + ImGui::TextDisabled("Read CAN traffic from a Linux SocketCAN interface."); + ImGui::Spacing(); ImGui::AlignTextToFramePadding(); ImGui::TextUnformatted("Device"); ImGui::SameLine(); @@ -248,7 +256,6 @@ std::unique_ptr OpenSocketCanWidget::open() { void StreamSelector::open(Callback on_done) { on_done_ = std::move(on_done); open_ = true; - popup_.reset(); first_frame_ = true; dbc_file_.clear(); widgets_.clear(); @@ -264,32 +271,65 @@ void StreamSelector::open(Callback on_done) { void StreamSelector::draw() { if (!open_) return; - if (!beginDialog("Open stream", &popup_, ImVec2(640.0f, 0.0f))) return; + const ImGuiViewport *viewport = ImGui::GetMainViewport(); + ImGui::SetNextWindowPos(viewport->WorkPos); + ImGui::SetNextWindowSize(viewport->WorkSize); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); + const ImGuiWindowFlags page_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoDocking; + if (!ImGui::Begin("##stream_selector_page", nullptr, page_flags)) { + ImGui::End(); + ImGui::PopStyleVar(2); + return; + } + ImGui::PopStyleVar(2); + + const ImVec2 available = ImGui::GetContentRegionAvail(); + const ImVec2 card_size(std::clamp(available.x - 80.0f, 680.0f, 920.0f), + std::clamp(available.y - 80.0f, 470.0f, 570.0f)); + ImGui::SetCursorPos(ImVec2(std::max(24.0f, (available.x - card_size.x) * 0.5f), + std::max(24.0f, (available.y - card_size.y) * 0.5f))); + ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 12.0f); + ImGui::PushStyleVar(ImGuiStyleVar_ChildBorderSize, 1.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(28.0f, 24.0f)); + ImGui::BeginChild("##stream_selector_card", card_size, ImGuiChildFlags_Borders, ImGuiWindowFlags_NoScrollbar); + ImGui::PopStyleVar(3); + + ImGui::PushFont(boldFont(), 26.0f); + ImGui::TextUnformatted("Open Cabana"); + ImGui::PopFont(); + ImGui::TextDisabled("Choose a data source to inspect CAN traffic, signals, and video."); + ImGui::Spacing(); + ImGui::Spacing(); AbstractOpenStreamWidget *current = nullptr; + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(16.0f, 7.0f)); if (ImGui::BeginTabBar("streams")) { for (auto &w : widgets_) { ImGuiTabItemFlags tab_flags = (first_frame_ && w == widgets_.front()) ? ImGuiTabItemFlags_SetSelected : 0; if (ImGui::BeginTabItem(w->title(), nullptr, tab_flags)) { current = w.get(); - ImGui::BeginChild("tab", ImVec2(0, 130.0f)); + const float content_height = std::max(170.0f, card_size.y - 300.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(18.0f, 16.0f)); + ImGui::BeginChild("tab", ImVec2(0, content_height), ImGuiChildFlags_Borders); w->draw(); ImGui::EndChild(); + ImGui::PopStyleVar(); ImGui::EndTabItem(); } } ImGui::EndTabBar(); } + ImGui::PopStyleVar(); first_frame_ = false; - ImGui::AlignTextToFramePadding(); - ImGui::TextUnformatted("dbc File"); - ImGui::SameLine(); - ImGui::SetNextItemWidth(-90.0f); + ImGui::SeparatorText("DBC file"); + ImGui::SetNextItemWidth(-120.0f); inputText("##dbc", &dbc_file_, "Choose a dbc file to open", ImGuiInputTextFlags_ReadOnly); ImGui::SameLine(); - if (ImGui::Button("Browse...")) { + if (ImGui::Button("Browse...", ImVec2(-1.0f, 0.0f))) { FileDialog::getOpenFileName("Open File", settings.last_dir, ".dbc", [this](const std::string &fn) { if (!fn.empty()) { dbc_file_ = fn; @@ -302,7 +342,13 @@ void StreamSelector::draw() { bool accepted = false, rejected = false; std::unique_ptr stream; bool open_clicked = false; - dialogButtons("Open", &open_clicked, &rejected, current != nullptr && current->openEnabled()); + const float open_width = 180.0f; + if (ImGui::Button("Cancel", ImVec2(100.0f, 38.0f))) rejected = true; + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetContentRegionMax().x - open_width); + ImGui::BeginDisabled(current == nullptr || !current->openEnabled()); + if (ImGui::Button("Open source", ImVec2(open_width, 38.0f))) open_clicked = true; + ImGui::EndDisabled(); if (open_clicked) { if (stream = current->open(); stream) accepted = true; } @@ -312,8 +358,8 @@ void StreamSelector::draw() { FileDialog::draw(); MessageBox::draw(); - if (accepted || rejected) ImGui::CloseCurrentPopup(); - ImGui::EndPopup(); + ImGui::EndChild(); + ImGui::End(); if (accepted || rejected) { open_ = false; widgets_.clear(); diff --git a/iqpilot/tools/cabana/ui/dialogs/streamselector.h b/iqpilot/tools/cabana/ui/dialogs/streamselector.h index c7a043e87..502250917 100644 --- a/iqpilot/tools/cabana/ui/dialogs/streamselector.h +++ b/iqpilot/tools/cabana/ui/dialogs/streamselector.h @@ -98,7 +98,6 @@ public: private: bool open_ = false; - PopupOwner popup_; bool first_frame_ = false; std::string dbc_file_; std::vector> widgets_; diff --git a/iqpilot/tools/lib/tests/test_caching.py b/iqpilot/tools/lib/tests/test_caching.py index 8e4989adb..82db8ef28 100644 --- a/iqpilot/tools/lib/tests/test_caching.py +++ b/iqpilot/tools/lib/tests/test_caching.py @@ -44,6 +44,20 @@ def host(): class TestFileDownload: + def test_head_connection_released(self, monkeypatch): + class Response: + status = 200 + headers = {"content-length": "4"} + released = False + + def release_conn(self): + self.released = True + + response = Response() + monkeypatch.setattr(URLFile, "_request", lambda self, method, url, headers=None: response) + assert URLFile("https://example.com/test").get_length_online() == 4 + assert response.released + def test_pipeline_defaults(self, host): # TODO: parameterize the defaults so we don't rely on hard-coded values in xx diff --git a/iqpilot/tools/lib/url_file.py b/iqpilot/tools/lib/url_file.py index 5200bb019..4276e7f0b 100644 --- a/iqpilot/tools/lib/url_file.py +++ b/iqpilot/tools/lib/url_file.py @@ -128,10 +128,13 @@ class URLFile: def get_length_online(self) -> int: response = self._request('HEAD', self._url) - if not (200 <= response.status <= 299): - return -1 - length = response.headers.get('content-length', 0) - return int(length) + try: + if not (200 <= response.status <= 299): + return -1 + length = response.headers.get('content-length', 0) + return int(length) + finally: + response.release_conn() def get_length(self) -> int: if self._length is not None: diff --git a/iqpilot/tools/test_tools_local_route.py b/iqpilot/tools/test_tools_local_route.py index 4dd324580..54ffd2576 100644 --- a/iqpilot/tools/test_tools_local_route.py +++ b/iqpilot/tools/test_tools_local_route.py @@ -40,6 +40,36 @@ def write_rlog(path: Path, n_frames: int = 200): f.write(msg.to_bytes()) +def write_video_rlog(path: Path, n_frames: int): + with open(path, "wb") as f: + cp = messaging.new_message('carParams') + cp.logMonoTime = 1_000_000_000 + cp.carParams.carFingerprint = "TOYOTA_RAV4_TSS2" + cp.carParams.brand = "toyota" + f.write(cp.to_bytes()) + + for i in range(n_frames): + timestamp = 1_000_000_000 + i * 50_000_000 + msg = messaging.new_message('can', 1) + msg.logMonoTime = timestamp + msg.can[0].address = 0x1D2 + msg.can[0].src = 0 + msg.can[0].dat = bytes([i % 256] * 8) + f.write(msg.to_bytes()) + + idx = messaging.new_message('roadEncodeIdx') + idx.logMonoTime = timestamp + idx.roadEncodeIdx.frameId = i + idx.roadEncodeIdx.type = 'fullHEVC' + idx.roadEncodeIdx.encodeId = i + idx.roadEncodeIdx.segmentNum = 0 + idx.roadEncodeIdx.segmentId = i + idx.roadEncodeIdx.segmentIdEncode = i + idx.roadEncodeIdx.timestampSof = timestamp + idx.roadEncodeIdx.timestampEof = timestamp + 10_000_000 + f.write(idx.to_bytes()) + + @pytest.fixture(scope="module") def local_route(tmp_path_factory): data_dir = tmp_path_factory.mktemp("routes") @@ -50,6 +80,25 @@ def local_route(tmp_path_factory): return data_dir +@pytest.fixture(scope="module") +def local_video_route(tmp_path_factory): + data_dir = tmp_path_factory.mktemp("video_routes") + seg_dir = data_dir / f"{DONGLE_ID}|{TIMESTAMP}--0" + seg_dir.mkdir() + frame_count = 20 + result = subprocess.run([ + "ffmpeg", "-hide_banner", "-loglevel", "error", "-f", "lavfi", + "-i", "testsrc=size=320x180:rate=20", "-frames:v", str(frame_count), + "-pix_fmt", "yuv420p", "-c:v", "libx265", "-preset", "ultrafast", + "-x265-params", "pools=1:frame-threads=1:log-level=error", "-f", "hevc", + str(seg_dir / "fcamera.hevc"), + ], capture_output=True, text=True) + if result.returncode != 0: + pytest.skip(result.stderr) + write_video_rlog(seg_dir / "rlog", frame_count) + return data_dir + + def run(cmd, timeout=180): return subprocess.run(cmd, capture_output=True, text=True, timeout=timeout, env=os.environ.copy(), cwd=TOOLS_DIR.parent) @@ -62,6 +111,33 @@ def cabana_command(*args): return command +def cabana_output_until(args, expected, timeout=60): + master, slave = pty.openpty() + proc = subprocess.Popen(cabana_command(*args), stdout=slave, stderr=slave, + env=os.environ.copy(), cwd=TOOLS_DIR.parent) + os.close(slave) + output = bytearray() + deadline = time.monotonic() + timeout + try: + while time.monotonic() < deadline: + ready, _, _ = select.select([master], [], [], min(1, deadline - time.monotonic())) + if not ready: + if proc.poll() is not None: + break + continue + try: + output.extend(os.read(master, 4096)) + except OSError: + break + if expected.encode() in output: + break + finally: + proc.kill() + proc.wait() + os.close(master) + return output.decode(errors="replace") + + def test_jotpluggler_renders_a_local_route(local_route, tmp_path): assert JOTPLUGGLER_BIN.exists(), "jotpluggler not built" out = tmp_path / "plot.png" @@ -74,38 +150,20 @@ def test_jotpluggler_renders_a_local_route(local_route, tmp_path): def test_cabana_loads_a_local_route(local_route): assert CABANA_BIN.exists(), "cabana not built" - master, slave = pty.openpty() - proc = subprocess.Popen(cabana_command("--data_dir", str(local_route), "--no-vipc", ROUTE), - stdout=slave, stderr=slave, - env=os.environ.copy(), cwd=TOOLS_DIR.parent) - os.close(slave) loaded = f"loaded route {ROUTE} with 2 valid segments" - output = bytearray() - deadline = time.monotonic() + 60 - try: - while time.monotonic() < deadline: - ready, _, _ = select.select([master], [], [], min(1, deadline - time.monotonic())) - if not ready: - if proc.poll() is not None: - break - continue - try: - output.extend(os.read(master, 4096)) - except OSError: - break - if loaded.encode() in output: - break - finally: - proc.kill() - proc.wait() - os.close(master) - - out = output.decode(errors="replace") + out = cabana_output_until(("--data_dir", str(local_route), "--no-vipc", ROUTE), loaded) assert "failed to load route" not in out, out assert "invalid route format" not in out, out assert loaded in out, out +def test_cabana_replays_local_video(local_video_route): + expected = "camera[0] vipc send #1" + out = cabana_output_until(("--data_dir", str(local_video_route), ROUTE), expected) + assert "failed to get frame" not in out, out + assert expected in out, out + + def test_replay_logreader_reports_load_stats(local_route): assert shutil.which("python3") is not None header = (TOOLS_DIR / "replay" / "logreader.h").read_text() diff --git a/iqpilot/ui/layouts/settings/iq_panels.py b/iqpilot/ui/layouts/settings/iq_panels.py index bb06fa680..1fbabb412 100644 --- a/iqpilot/ui/layouts/settings/iq_panels.py +++ b/iqpilot/ui/layouts/settings/iq_panels.py @@ -70,7 +70,7 @@ from iqpilot.system.ui.iqwidgets.widgets.list_view import ( Spacer, ) from iqpilot.system.ui.iqwidgets.widgets.list_view import IQListItem -from iqpilot.system.ui.iqwidgets.widgets.list_view import IQListItem, IQMultipleButtonAction, IQToggleAction, IQLineSeparator +from iqpilot.system.ui.iqwidgets.widgets.list_view import IQListItem, IQMultipleButtonAction, IQToggleAction, IQLineSeparator, toggle_item_iq from iqpilot.system.ui.iqwidgets.widgets.list_view import button_item, toggle_item from iqpilot.system.ui.iqwidgets.widgets.list_view import NoticeModal from iqpilot.system.ui.iqwidgets.widgets.list_view import PickerDialog, PickerItem, PickerGroup @@ -1655,6 +1655,14 @@ class ModelsLayout(Widget): ) self.big_model_item.action_item.set_value(self._big_model_value()) + self.small_on_mac_item = toggle_item_iq( + lambda: tr("Active Model on eMac"), + tr("Run the selected small model on the Mac instead of a big model."), + initial_state=ui_state.params.get_bool("IQEmacSmallModel"), + callback=self._on_small_on_mac_toggled, + param="IQEmacSmallModel", + ) + self.supercombo_label = progress_item(tr("Combined Model")) self.vision_label = progress_item(tr("Vision Weights")) self.policy_label = progress_item(tr("Policy Weights")) @@ -1671,7 +1679,7 @@ class ModelsLayout(Widget): self.redownload_item = button_item(lambda: tr("Redownload Current Model"), lambda: tr("REDOWNLOAD"), "", self._redownload_model) self.cancel_download_item = button_item(tr("Stop Download"), tr("Cancel"), "", self._cancel_model_request) - self.items = [self.current_model_item, self.big_model_item, self.cancel_download_item, self.supercombo_label, self.vision_label, + self.items = [self.current_model_item, self.big_model_item, self.small_on_mac_item, self.cancel_download_item, self.supercombo_label, self.vision_label, self.policy_label, self.redownload_item, self.refresh_item, self.clear_cache_item] def _is_downloading(self): @@ -1921,10 +1929,18 @@ class ModelsLayout(Widget): get_folders_fn=self._get_folders, on_exit=self._on_model_selected) gui_app.set_modal_overlay(self.model_dialog, callback=self._on_model_selected) + def _on_small_on_mac_toggled(self, state: bool) -> None: + p = ui_state.params + p.put_bool("IQEmacSmallModel", bool(state)) + p.put_bool("IQEmacEnabled", True if state else bool(p.get("IQEmacModel"))) + self.big_model_item.action_item.set_value(self._big_model_value()) + @staticmethod def _big_model_value() -> str: if not ui_state.params.get_bool("IQEmacEnabled"): return tr("Off") + if ui_state.params.get_bool("IQEmacSmallModel"): + return tr("Active model (eMac)") key = ui_state.params.get("IQEmacModel") key = key.decode() if isinstance(key, bytes) else (key or "") return _big_model_label(key) if key in [n for n, _ in _big_model_options()] else tr("Off") diff --git a/iqpilot/ui/onroad/emac_status.py b/iqpilot/ui/onroad/emac_status.py index efcb65955..19b13cee5 100644 --- a/iqpilot/ui/onroad/emac_status.py +++ b/iqpilot/ui/onroad/emac_status.py @@ -2,6 +2,7 @@ Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos/ """ +import math import time import pyray as rl @@ -17,6 +18,9 @@ from iqpilot.system.ui.widgets import Widget _POLL_S = 1.0 _FONT_SIZE = 70 +_ICON_H = 76 +_ICONS = {"MAC": ("mac", 62 / 46), "GPU": ("egpu", 1.0)} +_GREY = rl.Color(165, 165, 170, 235) class EmacStatusRenderer(Widget): @@ -27,6 +31,21 @@ class EmacStatusRenderer(Widget): self._last_poll = 0.0 self._label = "" self._state = SourceState.HIDDEN + self._icons: dict[str, dict[str, rl.Texture]] = {} + + def _icon_set(self, label: str) -> dict[str, rl.Texture] | None: + spec = _ICONS.get(label) + if spec is None: + return None + if label not in self._icons: + base, aspect = spec + w = int(_ICON_H * aspect) + self._icons[label] = { + "base": gui_app.texture(f"icons_mici/{base}.png", w, _ICON_H), + "green": gui_app.texture(f"icons_mici/{base}_green.png", w, _ICON_H), + "orange": gui_app.texture(f"icons_mici/{base}_orange.png", int(w * 1.26), _ICON_H), + } + return self._icons[label] def update(self): now = time.monotonic() @@ -38,7 +57,25 @@ class EmacStatusRenderer(Widget): def _render(self, rect: rl.Rectangle): if self._state == SourceState.HIDDEN: return - size = measure_text_cached(self._font, self._label, _FONT_SIZE) - x = rect.x + UI_BORDER_SIZE + BTN_SIZE // 2 - size.x / 2 - y = rect.y + rect.height / 2 - size.y / 2 - draw_source_label(self._font, self._label, self._state, rl.Vector2(x, y), _FONT_SIZE) + icons = self._icon_set(self._label) + if icons is None: + size = measure_text_cached(self._font, self._label, _FONT_SIZE) + x = rect.x + UI_BORDER_SIZE + BTN_SIZE // 2 - size.x / 2 + y = rect.y + rect.height / 2 - size.y / 2 + draw_source_label(self._font, self._label, self._state, rl.Vector2(x, y), _FONT_SIZE) + return + if self._state == SourceState.ACTIVE: + tex, tint = icons["green"], rl.Color(255, 255, 255, 255) + elif self._state == SourceState.FAILED: + tex, tint = icons["orange"], rl.Color(255, 255, 255, 255) + elif self._state == SourceState.CROSSED: + tex, tint = icons["base"], rl.Color(255, 255, 255, 165) + else: + pulse = 0.35 + 0.65 * (0.5 - 0.5 * math.cos(rl.get_time() * 6.0)) + tex, tint = icons["base"], rl.Color(_GREY.r, _GREY.g, _GREY.b, int(_GREY.a * pulse)) + x = int(rect.x + UI_BORDER_SIZE + BTN_SIZE // 2 - tex.width / 2) + y = int(rect.y + rect.height / 2 - tex.height / 2) + rl.draw_texture(tex, x, y, tint) + if self._state == SourceState.CROSSED: + cy = y + tex.height // 2 + rl.draw_line_ex(rl.Vector2(x - 4, cy), rl.Vector2(x + tex.width + 4, cy), 4, rl.Color(255, 255, 255, 165))