From e798caa3e5c44ed5aa7e480101a052d59612ad95 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 11 Jun 2024 22:55:42 -0700 Subject: [PATCH 01/30] qlog_size.py: more accurate msg size breakdown (#32723) * grouping changes outcome * clean up * clean up * clean up * clean up * clean up --- selfdrive/debug/internal/qlog_size.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/selfdrive/debug/internal/qlog_size.py b/selfdrive/debug/internal/qlog_size.py index 0b816604a..2d17a1ee2 100755 --- a/selfdrive/debug/internal/qlog_size.py +++ b/selfdrive/debug/internal/qlog_size.py @@ -6,6 +6,7 @@ from collections import defaultdict import matplotlib.pyplot as plt from openpilot.tools.lib.logreader import LogReader +from tqdm import tqdm MIN_SIZE = 0.5 # Percent size of total to show as separate entry @@ -15,19 +16,23 @@ def make_pie(msgs, typ): for m in msgs: msgs_by_type[m.which()].append(m.as_builder().to_bytes()) - length_by_type = {k: len(b"".join(v)) for k, v in msgs_by_type.items()} - compressed_length_by_type = {k: len(bz2.compress(b"".join(v))) for k, v in msgs_by_type.items()} - - total = sum(compressed_length_by_type.values()) + total = len(bz2.compress(b"".join([m.as_builder().to_bytes() for m in msgs]))) uncompressed_total = len(b"".join([m.as_builder().to_bytes() for m in msgs])) + length_by_type = {k: len(b"".join(v)) for k, v in msgs_by_type.items()} + # calculate compressed size by calculating diff when removed from the segment + compressed_length_by_type = {} + for k in tqdm(msgs_by_type.keys(), desc="Compressing"): + compressed_length_by_type[k] = total - len(bz2.compress(b"".join([m.as_builder().to_bytes() for m in msgs if m.which() != k]))) + sizes = sorted(compressed_length_by_type.items(), key=lambda kv: kv[1]) print("name - comp. size (uncomp. size)") for (name, sz) in sizes: print(f"{name:<22} - {sz / 1024:.2f} kB ({length_by_type[name] / 1024:.2f} kB)") print() - print(f"{typ} - Total {total / 1024:.2f} kB") + print(f"{typ} - Real total {total / 1024:.2f} kB") + print(f"{typ} - Breakdown total {sum(compressed_length_by_type.values()) / 1024:.2f} kB") print(f"{typ} - Uncompressed total {uncompressed_total / 1024 / 1024:.2f} MB") sizes_large = [(k, sz) for (k, sz) in sizes if sz >= total * MIN_SIZE / 100] From 8065b454c9dd57f1c61ac1a9e8475e694bb38bf1 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Wed, 12 Jun 2024 16:48:09 +0800 Subject: [PATCH 02/30] pandad: removed the redundant .c_str() call (#32724) Removed the redundant .c_str() call --- selfdrive/pandad/panda_comms.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/pandad/panda_comms.cc b/selfdrive/pandad/panda_comms.cc index 4e8a0a27b..59908f0cd 100644 --- a/selfdrive/pandad/panda_comms.cc +++ b/selfdrive/pandad/panda_comms.cc @@ -120,7 +120,7 @@ std::vector PandaUsbHandle::list() { libusb_close(handle); if (ret < 0) { goto finish; } - serials.push_back(std::string((char *)desc_serial, ret).c_str()); + serials.push_back(std::string((char *)desc_serial, ret)); } } From c64bca97bac68462a63b47d33aedf869d21ac97e Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Thu, 13 Jun 2024 05:20:06 +0800 Subject: [PATCH 03/30] logreader.py: optimize event loading and sorting in _LogFileReader (#32729) * improve logfilereader * less changes --- tools/lib/logreader.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/lib/logreader.py b/tools/lib/logreader.py index 669c1520d..48a04b28d 100755 --- a/tools/lib/logreader.py +++ b/tools/lib/logreader.py @@ -46,15 +46,15 @@ class _LogFileReader: ents = capnp_log.Event.read_multiple_bytes(dat) - _ents = [] + self._ents = [] try: for e in ents: - _ents.append(e) + self._ents.append(e) except capnp.KjException: warnings.warn("Corrupted events detected", RuntimeWarning, stacklevel=1) - self._ents = list(sorted(_ents, key=lambda x: x.logMonoTime) if sort_by_time else _ents) - self._ts = [x.logMonoTime for x in self._ents] + if sort_by_time: + self._ents.sort(key=lambda x: x.logMonoTime) def __iter__(self) -> Iterator[capnp._DynamicStructReader]: for ent in self._ents: From 7dbf60b4bce04a071eafcbc3eb0815e968e401be Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 12 Jun 2024 17:16:30 -0700 Subject: [PATCH 04/30] controlsd: exit on any exception (#32730) * exit on any exception * finally so we don't catch --- selfdrive/controls/controlsd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 4f5bd1940..aeeb3489b 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -835,7 +835,7 @@ class Controls: while True: self.step() self.rk.monitor_time() - except SystemExit: + finally: e.set() t.join() From 742a3a94e39440706c8ccff7ad1dcdce506a0c8a Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 12 Jun 2024 19:26:34 -0700 Subject: [PATCH 05/30] Hyundai: add note about fwdRadar FW (#32733) comment --- selfdrive/car/hyundai/fingerprints.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/selfdrive/car/hyundai/fingerprints.py b/selfdrive/car/hyundai/fingerprints.py index d115283dd..c3d3dcd03 100644 --- a/selfdrive/car/hyundai/fingerprints.py +++ b/selfdrive/car/hyundai/fingerprints.py @@ -2,6 +2,9 @@ from cereal import car from openpilot.selfdrive.car.hyundai.values import CAR +# The existence of SCC or RDR in the fwdRadar FW usually determines the radar's function, +# i.e. if it sends the SCC messages or if another ECU like the camera or ADAS Driving ECU does + Ecu = car.CarParams.Ecu FINGERPRINTS = { From 4539c973491bedabb4cd6cf8791d090987c56629 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 12 Jun 2024 19:36:26 -0700 Subject: [PATCH 06/30] Improve ECU address finder script (#32734) * put pandad in good state * obd option * fix * it's rx --- selfdrive/car/ecu_addrs.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/selfdrive/car/ecu_addrs.py b/selfdrive/car/ecu_addrs.py index e7a9fbcf2..756cd7f96 100755 --- a/selfdrive/car/ecu_addrs.py +++ b/selfdrive/car/ecu_addrs.py @@ -71,25 +71,35 @@ def get_ecu_addrs(logcan: messaging.SubSocket, sendcan: messaging.PubSocket, que if __name__ == "__main__": import argparse + from openpilot.common.params import Params + from openpilot.selfdrive.car.fw_versions import set_obd_multiplexing parser = argparse.ArgumentParser(description='Get addresses of all ECUs') parser.add_argument('--debug', action='store_true') parser.add_argument('--bus', type=int, default=1) + parser.add_argument('--no-obd', action='store_true') parser.add_argument('--timeout', type=float, default=1.0) args = parser.parse_args() logcan = messaging.sub_sock('can') sendcan = messaging.pub_sock('sendcan') - time.sleep(1.0) + # Set up params for pandad + params = Params() + params.remove("FirmwareQueryDone") + params.put_bool("IsOnroad", False) + time.sleep(0.2) # thread is 10 Hz + params.put_bool("IsOnroad", True) + + set_obd_multiplexing(params, not args.no_obd) print("Getting ECU addresses ...") ecu_addrs = get_all_ecu_addrs(logcan, sendcan, args.bus, args.timeout, debug=args.debug) print() - print("Found ECUs on addresses:") + print("Found ECUs on rx addresses:") for addr, subaddr, _ in ecu_addrs: - msg = f" 0x{hex(addr)}" + msg = f" {hex(addr)}" if subaddr is not None: msg += f" (sub-address: {hex(subaddr)})" print(msg) From 04a93dd849461df7a3496706c6172d95e83149c9 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 12 Jun 2024 21:14:23 -0700 Subject: [PATCH 07/30] add zstd Python library (#32731) * add zstd * fix * uploader * logreader: zst support * caps * only logreader --- poetry.lock | 103 +++++++++++++++++++++++++++++++++++++++-- pyproject.toml | 1 + tools/lib/logreader.py | 8 +++- 3 files changed, 106 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 7e772276e..c5f372173 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2730,6 +2730,7 @@ optional = false python-versions = ">=3.6" files = [ {file = "opencv-python-4.10.0.82.tar.gz", hash = "sha256:dbc021eaa310c4145c47cd648cb973db69bb5780d6e635386cd53d3ea76bd2d5"}, + {file = "opencv_python-4.10.0.82-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:5f78652339957ec24b80a782becfb32f822d2008a865512121fad8c3ce233e9a"}, {file = "opencv_python-4.10.0.82-cp37-abi3-macosx_12_0_x86_64.whl", hash = "sha256:e6be19a0615aa8c4e0d34e0c7b133e26e386f4b7e9b557b69479104ab2c133ec"}, {file = "opencv_python-4.10.0.82-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b49e530f7fd86f671514b39ffacdf5d14ceb073bc79d0de46bbb6b0cad78eaf"}, {file = "opencv_python-4.10.0.82-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955c5ce8ac90c9e4636ad7f5c0d9c75b80abbe347182cfd09b0e3eec6e50472c"}, @@ -2751,6 +2752,7 @@ optional = false python-versions = ">=3.6" files = [ {file = "opencv-python-headless-4.10.0.82.tar.gz", hash = "sha256:de9e742c1b9540816fbd115b0b03841d41ed0c65566b0d7a5371f98b131b7e6d"}, + {file = "opencv_python_headless-4.10.0.82-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:a09ed50ba21cc5bf5d436cb0e784ad09c692d6b1d1454252772f6c8f2c7b4088"}, {file = "opencv_python_headless-4.10.0.82-cp37-abi3-macosx_12_0_x86_64.whl", hash = "sha256:977a5fd21e1fe0d3d2134887db4441f8725abeae95150126302f31fcd9f548fa"}, {file = "opencv_python_headless-4.10.0.82-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db4ec6755838b0be12510bfc9ffb014779c612418f11f4f7e6f505c36124a3aa"}, {file = "opencv_python_headless-4.10.0.82-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10a37fa5276967ecf6eb297295b16b28b7a2eb3b568ca0ee469fb1a5954de298"}, @@ -3459,8 +3461,6 @@ files = [ {file = "pygame-2.5.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e24d05184e4195fe5ebcdce8b18ecb086f00182b9ae460a86682d312ce8d31f"}, {file = "pygame-2.5.2-cp311-cp311-win32.whl", hash = "sha256:f02c1c7505af18d426d355ac9872bd5c916b27f7b0fe224749930662bea47a50"}, {file = "pygame-2.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:6d58c8cf937815d3b7cdc0fa9590c5129cb2c9658b72d00e8a4568dea2ff1d42"}, - {file = "pygame-2.5.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1a2a43802bb5e89ce2b3b775744e78db4f9a201bf8d059b946c61722840ceea8"}, - {file = "pygame-2.5.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1c289f2613c44fe70a1e40769de4a49c5ab5a29b9376f1692bb1a15c9c1c9bfa"}, {file = "pygame-2.5.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:074aa6c6e110c925f7f27f00c7733c6303407edc61d738882985091d1eb2ef17"}, {file = "pygame-2.5.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe0228501ec616779a0b9c4299e837877783e18df294dd690b9ab0eed3d8aaab"}, {file = "pygame-2.5.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31648d38ecdc2335ffc0e38fb18a84b3339730521505dac68514f83a1092e3f4"}, @@ -7020,7 +7020,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -8009,7 +8008,103 @@ files = [ doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] +[[package]] +name = "zstd" +version = "1.5.5.1" +description = "ZSTD Bindings for Python" +optional = false +python-versions = "*" +files = [ + {file = "zstd-1.5.5.1-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:555779789bc75cd05089c3ba857f45a0a8c4b87d45e5ced02fec77fa8719237a"}, + {file = "zstd-1.5.5.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:86496bd4830cdb7b4b05a9ce6ce2baee87d327ff90845da4ee308452bfbbed4e"}, + {file = "zstd-1.5.5.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:b487c2e67ed42a4e0d47997d209f4456b01b334023083ef61873f79577c84c62"}, + {file = "zstd-1.5.5.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:45ccd45a5b681088fca1a863ca9236ded5112b8011f1d5bf69e908f5eb32023a"}, + {file = "zstd-1.5.5.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:8403fe84207d8b0c7b17bca6c4caad431ac765b1b9b626ad9fae4bb93a64a9d8"}, + {file = "zstd-1.5.5.1-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:0ab979c6357b8927f0c025ea2f72f25e15d03ce17a8a6c1789e2d5b108bf39ae"}, + {file = "zstd-1.5.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:98cbee6c1b2fe85f02fd475d885f98363c63bc64eebc249d7eb7469a0ff70283"}, + {file = "zstd-1.5.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9962714b89641301029f3832bdf07c20f60b9e64e39e8d7b6253451a82b54f5c"}, + {file = "zstd-1.5.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f59cc92d71537f8082306f75aa403ddb4a4a1069a39f104525673110e4d23f7"}, + {file = "zstd-1.5.5.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:569f13d0c926ddafceebce8ac73baddfc2bd9cbbbbc922b6b3073338cc43dae6"}, + {file = "zstd-1.5.5.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ba530c44f252016acc6ef906d7d2070c1ad0cfe835c498fdcd37493e4772ac6e"}, + {file = "zstd-1.5.5.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8ee3496ed8fff3add6c6e658b207f18d96474c3db0c28ab7a69623380b1a0a8c"}, + {file = "zstd-1.5.5.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:530d69bea2791cde8afa7fe988f3a37c3ba37015f6a1d5593c0500f089f3090e"}, + {file = "zstd-1.5.5.1-cp310-cp310-win32.whl", hash = "sha256:cf179e51f447b6a7ff47e449fcb98fb5fe15aedcc90401697cf7c93dd6e4434e"}, + {file = "zstd-1.5.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:5f5e6e0805d710d7509c8d175a467eb89c631a4142b1a630ceeb8e3e3138d152"}, + {file = "zstd-1.5.5.1-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:022f935a8666e08f0fff6204938a84d9fe4fcd8235a205787275933a07a164fb"}, + {file = "zstd-1.5.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3d15a2d18dac8bcafdde52fdf5d40ecae1f73b7de19b171f42339d2e51346d0"}, + {file = "zstd-1.5.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45b9c67989f50ba63ffa0c50c9eaa037c2d14abacb0813e838ad705135245b4b"}, + {file = "zstd-1.5.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97da6a842ba7e4acf8bba7c596057143ee39b3c4a467196c2096d460e44accd6"}, + {file = "zstd-1.5.5.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2dafd492fb8ee4ae04c81ab00f5f137860e7071f611335dd4cdb1c38bd8f11bc"}, + {file = "zstd-1.5.5.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9ee83e0bcbfd776200b026b3b9e86c6c86b8f414749f58d87c85dcf456b27066"}, + {file = "zstd-1.5.5.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ae2fd4bc8ea772a7b5f1acd1cac9e34bb9cd8fcde191f170092fdeea779a3a12"}, + {file = "zstd-1.5.5.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:edea52a0109f48fd46f4763689d3d356dcafd20ddf6789c559a1bd2e62b40a32"}, + {file = "zstd-1.5.5.1-cp311-cp311-win32.whl", hash = "sha256:88410481209520298ec4430e0d1d57e004c45e0b27c3035674fb182ccd2d8b7b"}, + {file = "zstd-1.5.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:dce18aaefbacf8b133367be86beec670baf68c0420bfcca49be08dbdbf933db6"}, + {file = "zstd-1.5.5.1-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:634dc632f7cf87e95dabf74dcf682e3507bd5cb9dd1bcdb81f92a6521aab0bd2"}, + {file = "zstd-1.5.5.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:608414eb75ead573891d97a1e529848b8f31749d21a440e80838548a19d8c0e6"}, + {file = "zstd-1.5.5.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:384128f7a731e3f45da49976591cec03fc4079e70653df10d9ea43a1d3b49d50"}, + {file = "zstd-1.5.5.1-cp35-cp35m-win32.whl", hash = "sha256:4bce254174ef05cea01021d67e18489d5d08db1168e758b62ecee121572a52a9"}, + {file = "zstd-1.5.5.1-cp35-cp35m-win_amd64.whl", hash = "sha256:3f0ff81232b49d7eb4f4d9e6f92443c9d242c139ad98ffedac0e889568f900ce"}, + {file = "zstd-1.5.5.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:a871df41b801a260cc849c2c76f300ebb9d286c4b7a1fd6ce45fe0c91340b767"}, + {file = "zstd-1.5.5.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5a53860dbfbea281eb690ce09cae28967cf1df8e6d7560e4a8bf5b9fcb258147"}, + {file = "zstd-1.5.5.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:a37cbc0580fdfd66c8b3ec65f9af00a4a34e9781b54dfb89f04d301dc375c90a"}, + {file = "zstd-1.5.5.1-cp36-cp36m-win32.whl", hash = "sha256:5531b683539ae1f7b2ad23dacee8a73e5d7eaa6702ea8df5a24bd3318647dee1"}, + {file = "zstd-1.5.5.1-cp36-cp36m-win_amd64.whl", hash = "sha256:eeaff418269b41eee8c7971fbba9d32d07d3f6aa26f962a72aff725071096a1b"}, + {file = "zstd-1.5.5.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:8bd6a9050de8bbe844447348372ca17d01bc05207619f6a5d448567d111b5cd9"}, + {file = "zstd-1.5.5.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2ece3d20ef357370584f304407fbd1e4ff9c231209320e08a889b8e3725d56e"}, + {file = "zstd-1.5.5.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:687f9e03dc9f9b8803840425bb23bf6bc700888b4860afcf43c4f238102752d2"}, + {file = "zstd-1.5.5.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a649daac9c8f1b37d29f2b3d0a43f134061659b54877fe4b0da6df2965dc91f"}, + {file = "zstd-1.5.5.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:bddc7e3c3ce31c01fe1edaa7c03c0b9e71eadf4ce1609746d32f86d95a0449e6"}, + {file = "zstd-1.5.5.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:12bf8e04add8bb84f9fe9117f3de6d9394eade6a5a82fe4d6bd95914fc6ef423"}, + {file = "zstd-1.5.5.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9e6a15fa4d2e65c5902ab2a4e41279ac126cb371ce6c3c75ad5789bb20dd1f54"}, + {file = "zstd-1.5.5.1-cp37-cp37m-win32.whl", hash = "sha256:a1c269243a4321beb948635b544ccbe6390846358ace620fd000ab7099011d9c"}, + {file = "zstd-1.5.5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:91366e36773241cb4b049a32f4495d33dd274df1eea5b55396f5f3984a3de22e"}, + {file = "zstd-1.5.5.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:d3ce2cb310690994274d133ea7f269dd4b81799fdbce158690556209723d7d4e"}, + {file = "zstd-1.5.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e0c87bfbfa9d852f79c90bcd7426c3ba46cf3285e6984013636d4fc854ba9230"}, + {file = "zstd-1.5.5.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce6d829d515f272fddb3a87e1a5f32cc0f1a7b0cba24d360c89f4a165b74b"}, + {file = "zstd-1.5.5.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e05f81f346213b23ed1b12d84fc1f72e65eacd8978e1e88facf185c82bd3d053"}, + {file = "zstd-1.5.5.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43ec66c4c3a76351c672c6ef9f0ff3412fca9ede0a56d18dddaf6418a93faef8"}, + {file = "zstd-1.5.5.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:58e554e91e0d49f4f2b2df390cdd0f64aa9b6fd5f4dcb208c094bfd079b30f3a"}, + {file = "zstd-1.5.5.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:883c6d3b6f5574e1765ca97f4b6a41b69094a41be56175552faebc0e0e43b65e"}, + {file = "zstd-1.5.5.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d52b6932cab5419c434bccfea3e5640e755369fc9eeb51e3d17e15bf8e8cb103"}, + {file = "zstd-1.5.5.1-cp38-cp38-win32.whl", hash = "sha256:dcaf44270ec88552e969be4dd3359b34aa3065663ccd8168a257c78f150a356c"}, + {file = "zstd-1.5.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:627f12cb7035723c8f3d8d4cefcad6d950ed9cba33fd3eb46bae04ccab479234"}, + {file = "zstd-1.5.5.1-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:c0dab132c1a5a7cc838a7c3e4e380ad153b9d7bd1fadafabf6cfeb780b916201"}, + {file = "zstd-1.5.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d4ab0a5dd9a41d3b083304beee7ada40ee36431acbeb75132032f4fe5cf0490a"}, + {file = "zstd-1.5.5.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f6e38f496d287020658c6b4cdb5e815ecc6998889bd0f1f9ab0825f2e3d74ef"}, + {file = "zstd-1.5.5.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0096c8ee0ed4bfe406bc961019f55552109e19771bfd3eb32d2af56ea27085c"}, + {file = "zstd-1.5.5.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a0f1527728c50b6aa8f04b47a07580f0ae13cfc6c6d9c96bb0bdf5259487559"}, + {file = "zstd-1.5.5.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6a64e420c904063c5c3de53c00ec0993ebc0a48cebbef97dc6c768562c5abab5"}, + {file = "zstd-1.5.5.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:03444e357b7632c64480a81ce7095242dab9d7f8aed317326563ef6c663263eb"}, + {file = "zstd-1.5.5.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:88b9a10f80d2b87bf8cc1a1fc20a815ed92b5eefdc15cbe8062021f0b5a26a10"}, + {file = "zstd-1.5.5.1-cp39-cp39-win32.whl", hash = "sha256:c91cc1606eb8b3a6fed11faaef4c6e55f1133d70cf0db0c829a2cf9c2ac1dfd9"}, + {file = "zstd-1.5.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:f462e2ebf26dcbfc2c8dddd6b5c56859683f0b77edb8f268e637f7d390a58f74"}, + {file = "zstd-1.5.5.1-pp27-pypy_73-macosx_10_14_x86_64.whl", hash = "sha256:c63f916732e3e309e49ec95e7a0af5d37ff1321f3df2aac10e507bd2b56fceda"}, + {file = "zstd-1.5.5.1-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:50d4850d758bb033df50722cc13ed913b2afcd5385250be4f3ffb79a26b319c3"}, + {file = "zstd-1.5.5.1-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:0412d666515e78a91ada7e2d78e9dd6b25ddda1b41623b145b99653275c7f3ce"}, + {file = "zstd-1.5.5.1-pp36-pypy36_pp73-macosx_10_14_x86_64.whl", hash = "sha256:0ea91f74869a3cdcb2dde08f8f30ee3da72782c5d1737afed9c703232815864e"}, + {file = "zstd-1.5.5.1-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:477548897dc2b8b595af7bec5f0f55dcba8e9a282335f687cc663b52b171357b"}, + {file = "zstd-1.5.5.1-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:c518938b57a56001ee04dcf79a432152f5bd431416f3b22819ba959bc6054d89"}, + {file = "zstd-1.5.5.1-pp36-pypy36_pp73-win32.whl", hash = "sha256:894a8fe0228d5e24dc286a8d98eb0ce2883f8e2e57f3b7e7619ebdb67967120a"}, + {file = "zstd-1.5.5.1-pp37-pypy37_pp73-macosx_10_14_x86_64.whl", hash = "sha256:42ec0a4ae9bedd9909fa4f580f3c800469da1b631faeaa94f204e1b66c767fa2"}, + {file = "zstd-1.5.5.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d56dedaa04ab8ecc23492972b12e0bf8529f64c9bceb28c11f43c2369c9768b3"}, + {file = "zstd-1.5.5.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5b060770d796e4c01f5848b345c3cea8a177ab4e7cd95a1963a355042d429e1"}, + {file = "zstd-1.5.5.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fea04805ef6e1cb93d6e5d6bbc7a03bc75a5c733fd352d5aaa81109986fdf1ef"}, + {file = "zstd-1.5.5.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:405c28a35756e57a434bbd7ed29dc5e6490cd2fc2118cbf78b60eaebd134f5e9"}, + {file = "zstd-1.5.5.1-pp38-pypy38_pp73-macosx_10_14_x86_64.whl", hash = "sha256:c42e630443b01a891277426365a51a2aa630b059ce675992c70c1928d30eccb4"}, + {file = "zstd-1.5.5.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1520d23f24f26cdfbcdb4dc86947446b8f694838bfce728d7fc4b3492397357c"}, + {file = "zstd-1.5.5.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f4730737f63cf802321743ded6acc85e747e7f5587c5ba2e51a760bf009f7de"}, + {file = "zstd-1.5.5.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9f8c014395e89ad7f67ffe873c0fa1d8e9b4dea8b1801d24e8d9ccd8259858d"}, + {file = "zstd-1.5.5.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5d9ba4f6af0945809bfa3387c6a1208a22937a876521b9ec347e7183d623311b"}, + {file = "zstd-1.5.5.1-pp39-pypy39_pp73-macosx_10_14_x86_64.whl", hash = "sha256:04dfd9f46b0b0b1bc413884fe028b726febcb726d4f66e3cf8afc00c2d9026bf"}, + {file = "zstd-1.5.5.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:af52436a2eb5caa925d95461973984cb34d472a963b6be1c0a9f2dfbafad096f"}, + {file = "zstd-1.5.5.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610928b888a2e7ae9d2018ffa814859d47ec4ba75f89a1188ab4eb9232636ee5"}, + {file = "zstd-1.5.5.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee3c9feea99c7f4ff43129a885da056b5aa0cde3f7876bf6397bfb9433f44352"}, + {file = "zstd-1.5.5.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c6ac9768eeb3c6b530db93de2fec9b363776075dc8a00ee4049612ba5397ca8e"}, + {file = "zstd-1.5.5.1.tar.gz", hash = "sha256:1ef980abf0e1e072b028d2d76ef95b476632651c96225cf30b619c6eef625672"}, +] + [metadata] lock-version = "2.0" python-versions = ">=3.11, <3.13" -content-hash = "b5c62b81368f0e972fbcf0dbb88746f3ae930ebdc171ad004c926f3588d1f244" +content-hash = "877bf9463a547f2e1b11d057f20504459e75cf21b5f0dab341d6205a4de1f54c" diff --git a/pyproject.toml b/pyproject.toml index 7b780c87f..edc515771 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -187,6 +187,7 @@ tabulate = "*" types-requests = "*" types-tabulate = "*" tqdm = "*" +zstd = "*" # this is only pinned since 5.15.11 is broken pyqt5 = { version = "==5.15.2", markers = "platform_machine == 'x86_64'" } # no aarch64 wheels for macOS/linux diff --git a/tools/lib/logreader.py b/tools/lib/logreader.py index 48a04b28d..2430f1542 100755 --- a/tools/lib/logreader.py +++ b/tools/lib/logreader.py @@ -10,6 +10,7 @@ import sys import tqdm import urllib.parse import warnings +import zstd from collections.abc import Callable, Iterable, Iterator from urllib.parse import parse_qs, urlparse @@ -34,8 +35,8 @@ class _LogFileReader: ext = None if not dat: _, ext = os.path.splitext(urllib.parse.urlparse(fn).path) - if ext not in ('', '.bz2'): - # old rlogs weren't bz2 compressed + if ext not in ('', '.bz2', '.zst'): + # old rlogs weren't compressed raise Exception(f"unknown extension {ext}") with FileReader(fn) as f: @@ -43,6 +44,9 @@ class _LogFileReader: if ext == ".bz2" or dat.startswith(b'BZh9'): dat = bz2.decompress(dat) + elif ext == ".zst" or dat.startswith(b'\x28\xB5\x2F\xFD'): + # https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#zstandard-frames + dat = zstd.decompress(dat) ents = capnp_log.Event.read_multiple_bytes(dat) From f449ed144ea47d8d5f558254c9c4cf04e959fbee Mon Sep 17 00:00:00 2001 From: markalan020 Date: Thu, 13 Jun 2024 03:55:52 -0400 Subject: [PATCH 08/30] Hyundai: add fwdCamera FW for Ioniq 5 2024 (US) (#32623) * Update fingerprints.py Add Support for 2024 Hyundai Ioniq 5 * docs --------- Co-authored-by: Shane Smiskol --- docs/CARS.md | 4 ++-- selfdrive/car/hyundai/fingerprints.py | 1 + selfdrive/car/hyundai/values.py | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/CARS.md b/docs/CARS.md index 3b163dcee..2feabb557 100644 --- a/docs/CARS.md +++ b/docs/CARS.md @@ -91,8 +91,8 @@ A supported vehicle is one that just works when you install a comma device. All |Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|Stock|19 mph|37 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Hyundai J connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|i30 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai E connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Ioniq 5 (Southeast Asia only) 2022-23[5](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai Q connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Hyundai|Ioniq 5 (with HDA II) 2022-23[5](#footnotes)|Highway Driving Assist II|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai Q connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Hyundai|Ioniq 5 (without HDA II) 2022-23[5](#footnotes)|Highway Driving Assist|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai K connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Hyundai|Ioniq 5 (with HDA II) 2022-24[5](#footnotes)|Highway Driving Assist II|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai Q connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Hyundai|Ioniq 5 (without HDA II) 2022-24[5](#footnotes)|Highway Driving Assist|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai K connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Ioniq 6 (with HDA II) 2023-24[5](#footnotes)|Highway Driving Assist II|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai P connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Ioniq Electric 2019|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai C connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Ioniq Electric 2020|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai H connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| diff --git a/selfdrive/car/hyundai/fingerprints.py b/selfdrive/car/hyundai/fingerprints.py index c3d3dcd03..b1e50f835 100644 --- a/selfdrive/car/hyundai/fingerprints.py +++ b/selfdrive/car/hyundai/fingerprints.py @@ -998,6 +998,7 @@ FW_VERSIONS = { b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.03 99211-GI010 220401', b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.05 99211-GI010 220614', b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.06 99211-GI010 230110', + b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.00 99211-GI100 230915', ], }, CAR.HYUNDAI_IONIQ_6: { diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index c489ea004..b6f8da218 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -307,8 +307,8 @@ class CAR(Platforms): HYUNDAI_IONIQ_5 = HyundaiCanFDPlatformConfig( [ HyundaiCarDocs("Hyundai Ioniq 5 (Southeast Asia only) 2022-23", "All", car_parts=CarParts.common([CarHarness.hyundai_q])), - HyundaiCarDocs("Hyundai Ioniq 5 (without HDA II) 2022-23", "Highway Driving Assist", car_parts=CarParts.common([CarHarness.hyundai_k])), - HyundaiCarDocs("Hyundai Ioniq 5 (with HDA II) 2022-23", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_q])), + HyundaiCarDocs("Hyundai Ioniq 5 (without HDA II) 2022-24", "Highway Driving Assist", car_parts=CarParts.common([CarHarness.hyundai_k])), + HyundaiCarDocs("Hyundai Ioniq 5 (with HDA II) 2022-24", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_q])), ], CarSpecs(mass=1948, wheelbase=2.97, steerRatio=14.26, tireStiffnessFactor=0.65), flags=HyundaiFlags.EV, From 0319379431732ec3855fc7a60ddaa7e5ddb30def Mon Sep 17 00:00:00 2001 From: Mustafa Akcanca Date: Thu, 13 Jun 2024 11:06:45 +0300 Subject: [PATCH 09/30] Hyundai docs: change Ioniq 5 Southeast Asia only to Non-US only (#32701) * Update values.py * ev6 too is probably the same --------- Co-authored-by: Shane Smiskol --- docs/CARS.md | 4 ++-- selfdrive/car/hyundai/values.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/CARS.md b/docs/CARS.md index 2feabb557..c0b6e1546 100644 --- a/docs/CARS.md +++ b/docs/CARS.md @@ -90,7 +90,7 @@ A supported vehicle is one that just works when you install a comma device. All |Hyundai|Elantra Hybrid 2021-23|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai K connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|Stock|19 mph|37 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Hyundai J connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|i30 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai E connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Hyundai|Ioniq 5 (Southeast Asia only) 2022-23[5](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai Q connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Hyundai|Ioniq 5 (Non-US only) 2022-23[5](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai Q connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Ioniq 5 (with HDA II) 2022-24[5](#footnotes)|Highway Driving Assist II|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai Q connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Ioniq 5 (without HDA II) 2022-24[5](#footnotes)|Highway Driving Assist|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai K connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Ioniq 6 (with HDA II) 2023-24[5](#footnotes)|Highway Driving Assist II|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai P connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| @@ -127,7 +127,7 @@ A supported vehicle is one that just works when you install a comma device. All |Kia|Carnival 2022-24[5](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai A connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Kia|Carnival (China only) 2023[5](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai K connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Kia|Ceed 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai E connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Kia|EV6 (Southeast Asia only) 2022-24[5](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai P connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Kia|EV6 (Non-US only) 2022-24[5](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai P connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Kia|EV6 (with HDA II) 2022-24[5](#footnotes)|Highway Driving Assist II|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai P connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Kia|EV6 (without HDA II) 2022-24[5](#footnotes)|Highway Driving Assist|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai L connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Kia|Forte 2019-21|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|6 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Hyundai G connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index b6f8da218..f34c45f77 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -306,7 +306,7 @@ class CAR(Platforms): ) HYUNDAI_IONIQ_5 = HyundaiCanFDPlatformConfig( [ - HyundaiCarDocs("Hyundai Ioniq 5 (Southeast Asia only) 2022-23", "All", car_parts=CarParts.common([CarHarness.hyundai_q])), + HyundaiCarDocs("Hyundai Ioniq 5 (Non-US only) 2022-23", "All", car_parts=CarParts.common([CarHarness.hyundai_q])), HyundaiCarDocs("Hyundai Ioniq 5 (without HDA II) 2022-24", "Highway Driving Assist", car_parts=CarParts.common([CarHarness.hyundai_k])), HyundaiCarDocs("Hyundai Ioniq 5 (with HDA II) 2022-24", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_q])), ], @@ -478,7 +478,7 @@ class CAR(Platforms): ) KIA_EV6 = HyundaiCanFDPlatformConfig( [ - HyundaiCarDocs("Kia EV6 (Southeast Asia only) 2022-24", "All", car_parts=CarParts.common([CarHarness.hyundai_p])), + HyundaiCarDocs("Kia EV6 (Non-US only) 2022-24", "All", car_parts=CarParts.common([CarHarness.hyundai_p])), HyundaiCarDocs("Kia EV6 (without HDA II) 2022-24", "Highway Driving Assist", car_parts=CarParts.common([CarHarness.hyundai_l])), HyundaiCarDocs("Kia EV6 (with HDA II) 2022-24", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_p])) ], From 06828f1e80435fbc3a27781b096e3e2bbc86da69 Mon Sep 17 00:00:00 2001 From: Mustafa Akcanca Date: Thu, 13 Jun 2024 11:08:03 +0300 Subject: [PATCH 10/30] Hyundai: add fwdCamera FW for Ioniq 5 2024 (EUR) (#32648) * Update fingerprints.py Adding FW fingerprints for Ioniq 5 2024 EU, non-HDA, fwd camera * bump my! --------- Co-authored-by: Shane Smiskol --- docs/CARS.md | 2 +- selfdrive/car/hyundai/fingerprints.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/CARS.md b/docs/CARS.md index c0b6e1546..43bd8a8b3 100644 --- a/docs/CARS.md +++ b/docs/CARS.md @@ -90,7 +90,7 @@ A supported vehicle is one that just works when you install a comma device. All |Hyundai|Elantra Hybrid 2021-23|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai K connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|Stock|19 mph|37 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Hyundai J connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|i30 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai E connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| -|Hyundai|Ioniq 5 (Non-US only) 2022-23[5](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai Q connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| +|Hyundai|Ioniq 5 (Non-US only) 2022-24[5](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai Q connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Ioniq 5 (with HDA II) 2022-24[5](#footnotes)|Highway Driving Assist II|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai Q connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Ioniq 5 (without HDA II) 2022-24[5](#footnotes)|Highway Driving Assist|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai K connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| |Hyundai|Ioniq 6 (with HDA II) 2023-24[5](#footnotes)|Highway Driving Assist II|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai P connector
- 1 RJ45 cable (7 ft)
- 1 comma 3X
- 1 comma power v2
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
|| diff --git a/selfdrive/car/hyundai/fingerprints.py b/selfdrive/car/hyundai/fingerprints.py index b1e50f835..e489a3cf6 100644 --- a/selfdrive/car/hyundai/fingerprints.py +++ b/selfdrive/car/hyundai/fingerprints.py @@ -999,6 +999,7 @@ FW_VERSIONS = { b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.05 99211-GI010 220614', b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.06 99211-GI010 230110', b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.00 99211-GI100 230915', + b'\xf1\x00NE1 MFC AT EUR LHD 1.00 1.00 99211-GI100 230915', ], }, CAR.HYUNDAI_IONIQ_6: { From 4708332abee61116e13da7a4a186ca1b77511dd9 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Thu, 13 Jun 2024 01:39:17 -0700 Subject: [PATCH 11/30] Update docs --- selfdrive/car/hyundai/values.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index f34c45f77..8cb29c803 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -306,7 +306,7 @@ class CAR(Platforms): ) HYUNDAI_IONIQ_5 = HyundaiCanFDPlatformConfig( [ - HyundaiCarDocs("Hyundai Ioniq 5 (Non-US only) 2022-23", "All", car_parts=CarParts.common([CarHarness.hyundai_q])), + HyundaiCarDocs("Hyundai Ioniq 5 (Non-US only) 2022-24", "All", car_parts=CarParts.common([CarHarness.hyundai_q])), HyundaiCarDocs("Hyundai Ioniq 5 (without HDA II) 2022-24", "Highway Driving Assist", car_parts=CarParts.common([CarHarness.hyundai_k])), HyundaiCarDocs("Hyundai Ioniq 5 (with HDA II) 2022-24", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_q])), ], From f08137f6182d2667803ac6e75e86fb605d0a8b1c Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Thu, 13 Jun 2024 10:29:57 -0700 Subject: [PATCH 12/30] pandad: update test thresholds --- selfdrive/pandad/tests/test_pandad_spi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/selfdrive/pandad/tests/test_pandad_spi.py b/selfdrive/pandad/tests/test_pandad_spi.py index 11e20e72c..9c5990cd3 100644 --- a/selfdrive/pandad/tests/test_pandad_spi.py +++ b/selfdrive/pandad/tests/test_pandad_spi.py @@ -84,8 +84,8 @@ class TestBoarddSpi: ps = m.peripheralState assert ps.pandaType == "tres" assert 4000 < ps.voltage < 14000 - assert 100 < ps.current < 1000 - assert ps.fanSpeedRpm < 8000 + assert 50 < ps.current < 1000 + assert ps.fanSpeedRpm < 10000 time.sleep(0.5) et = time.monotonic() - st From 9ffd973be9bdfe1be1097f9a2618ba76991616e4 Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Thu, 13 Jun 2024 13:41:32 -0700 Subject: [PATCH 13/30] Separate python dep into groups (#32739) * split * only zstd --- poetry.lock | 21 +++++++++------- pyproject.toml | 68 +++++++++++++++++++++++++++----------------------- 2 files changed, 49 insertions(+), 40 deletions(-) diff --git a/poetry.lock b/poetry.lock index c5f372173..16fb764d5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. [[package]] name = "aiohttp" @@ -1074,18 +1074,18 @@ files = [ [[package]] name = "filelock" -version = "3.14.0" +version = "3.15.1" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"}, - {file = "filelock-3.14.0.tar.gz", hash = "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"}, + {file = "filelock-3.15.1-py3-none-any.whl", hash = "sha256:71b3102950e91dfc1bb4209b64be4dc8854f40e5f534428d8684f953ac847fac"}, + {file = "filelock-3.15.1.tar.gz", hash = "sha256:58a2549afdf9e02e10720eaa4d4470f56386d7a6f72edd7d0596337af8ed7ad8"}, ] [package.extras] docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] typing = ["typing-extensions (>=4.8)"] [[package]] @@ -2740,8 +2740,8 @@ files = [ [package.dependencies] numpy = [ - {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, {version = ">=1.23.5", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, + {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, ] [[package]] @@ -2762,8 +2762,8 @@ files = [ [package.dependencies] numpy = [ - {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, {version = ">=1.23.5", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, + {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, ] [[package]] @@ -2927,8 +2927,8 @@ files = [ [package.dependencies] numpy = [ - {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, {version = ">=1.23.2", markers = "python_version == \"3.11\""}, + {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, ] python-dateutil = ">=2.8.2" pytz = ">=2020.1" @@ -3461,6 +3461,8 @@ files = [ {file = "pygame-2.5.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e24d05184e4195fe5ebcdce8b18ecb086f00182b9ae460a86682d312ce8d31f"}, {file = "pygame-2.5.2-cp311-cp311-win32.whl", hash = "sha256:f02c1c7505af18d426d355ac9872bd5c916b27f7b0fe224749930662bea47a50"}, {file = "pygame-2.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:6d58c8cf937815d3b7cdc0fa9590c5129cb2c9658b72d00e8a4568dea2ff1d42"}, + {file = "pygame-2.5.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1a2a43802bb5e89ce2b3b775744e78db4f9a201bf8d059b946c61722840ceea8"}, + {file = "pygame-2.5.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1c289f2613c44fe70a1e40769de4a49c5ab5a29b9376f1692bb1a15c9c1c9bfa"}, {file = "pygame-2.5.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:074aa6c6e110c925f7f27f00c7733c6303407edc61d738882985091d1eb2ef17"}, {file = "pygame-2.5.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe0228501ec616779a0b9c4299e837877783e18df294dd690b9ab0eed3d8aaab"}, {file = "pygame-2.5.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31648d38ecdc2335ffc0e38fb18a84b3339730521505dac68514f83a1092e3f4"}, @@ -7020,6 +7022,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -8107,4 +8110,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = ">=3.11, <3.13" -content-hash = "877bf9463a547f2e1b11d057f20504459e75cf21b5f0dab341d6205a4de1f54c" +content-hash = "51f233c6af3795be4fd3f54b7b462777bc65f547de0821c0de7ac0c3c056b0a6" diff --git a/pyproject.toml b/pyproject.toml index edc515771..e46f7d51a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -139,35 +139,17 @@ psutil = "*" timezonefinder = "*" # just used for nav ETA pycryptodome = "*" # used in updated/casync, panda, body, and a test -[tool.poetry.group.dev.dependencies] -av = "*" -azure-identity = "*" -azure-storage-blob = "*" -breathe = "*" -control = "*" -coverage = "*" -dictdiffer = "*" -flaky = "*" -hypothesis = "~6.47" -inputs = "*" +[tool.poetry.group.docs.dependencies] Jinja2 = "*" -lru-dict = "*" -matplotlib = "*" -metadrive-simulator = { git = "https://github.com/commaai/metadrive.git", branch = "python3.12", markers = "platform_machine != 'aarch64'" } # no linux/aarch64 wheels for certain dependencies -mpld3 = "*" +sphinx = "*" +sphinx-rtd-theme = "*" +sphinx-sitemap = "*" + +[tool.poetry.group.testing.dependencies] +coverage = "*" +hypothesis = "~6.47" mypy = "*" -myst-parser = "*" -natsort = "*" -opencv-python-headless = "*" -parameterized = "^0.8" -#pprofile = "*" -polyline = "*" pre-commit = "*" -pyautogui = "*" -pyopencl = { version = "*", markers = "platform_machine != 'aarch64'" } # broken on arm64 -pygame = "*" -pywinctl = "*" -pyprof2calltree = "*" pytest = "*" pytest-cov = "*" pytest-cpp = "*" @@ -178,16 +160,40 @@ pytest-randomly = "*" pytest-asyncio = "*" pytest-mock = "*" pytest-repeat = "*" -rerun-sdk = "*" ruff = "*" -sphinx = "*" -sphinx-rtd-theme = "*" -sphinx-sitemap = "*" + +[tool.poetry.group.tools.dependencies] +zstd = "*" + +[tool.poetry.group.dev.dependencies] +av = "*" +azure-identity = "*" +azure-storage-blob = "*" +breathe = "*" +control = "*" +dictdiffer = "*" +flaky = "*" +inputs = "*" +lru-dict = "*" +matplotlib = "*" +metadrive-simulator = { git = "https://github.com/commaai/metadrive.git", branch = "python3.12", markers = "platform_machine != 'aarch64'" } # no linux/aarch64 wheels for certain dependencies +mpld3 = "*" +myst-parser = "*" +natsort = "*" +opencv-python-headless = "*" +parameterized = "^0.8" +#pprofile = "*" +polyline = "*" +pyautogui = "*" +pygame = "*" +pyopencl = { version = "*", markers = "platform_machine != 'aarch64'" } # broken on arm64 +pywinctl = "*" +pyprof2calltree = "*" +rerun-sdk = "*" tabulate = "*" types-requests = "*" types-tabulate = "*" tqdm = "*" -zstd = "*" # this is only pinned since 5.15.11 is broken pyqt5 = { version = "==5.15.2", markers = "platform_machine == 'x86_64'" } # no aarch64 wheels for macOS/linux From 6552d4ecb87211b91310ca5d7a7bcb918df36021 Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Thu, 13 Jun 2024 14:46:19 -0700 Subject: [PATCH 14/30] Move zstd to normal deps (#32741) move zstd --- poetry.lock | 2 +- pyproject.toml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index 16fb764d5..2467d6be2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -8110,4 +8110,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = ">=3.11, <3.13" -content-hash = "51f233c6af3795be4fd3f54b7b462777bc65f547de0821c0de7ac0c3c056b0a6" +content-hash = "83dbbf76ea5f3e1022233a164d6f342706ebf64ad8bbbf742a55d5f49474d863" diff --git a/pyproject.toml b/pyproject.toml index e46f7d51a..5353b3988 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -139,6 +139,9 @@ psutil = "*" timezonefinder = "*" # just used for nav ETA pycryptodome = "*" # used in updated/casync, panda, body, and a test +#logreader +zstd = "*" + [tool.poetry.group.docs.dependencies] Jinja2 = "*" sphinx = "*" @@ -162,9 +165,6 @@ pytest-mock = "*" pytest-repeat = "*" ruff = "*" -[tool.poetry.group.tools.dependencies] -zstd = "*" - [tool.poetry.group.dev.dependencies] av = "*" azure-identity = "*" From 3ede1e2a7c850622beef2549315f320aa018105a Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Thu, 13 Jun 2024 22:37:00 -0700 Subject: [PATCH 15/30] LogReader: improve error messages (#32747) * better error messages * clean up --- tools/lib/logreader.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/lib/logreader.py b/tools/lib/logreader.py index 2430f1542..737ef4615 100755 --- a/tools/lib/logreader.py +++ b/tools/lib/logreader.py @@ -166,7 +166,8 @@ def get_invalid_files(files): def check_source(source: Source, *args) -> LogPaths: files = source(*args) - assert next(get_invalid_files(files), False) is False + assert len(files) > 0, "No files on source" + assert not any(get_invalid_files(files)), f"Invalid files: {files}" return files @@ -175,7 +176,7 @@ def auto_source(sr: SegmentRange, mode=ReadMode.RLOG) -> LogPaths: return comma_car_segments_source(sr, mode) SOURCES: list[Source] = [internal_source, openpilotci_source, comma_api_source, comma_car_segments_source,] - exceptions = [] + exceptions = {} # for automatic fallback modes, auto_source needs to first check if rlogs exist for any source if mode in [ReadMode.AUTO, ReadMode.AUTO_INTERACTIVE]: @@ -190,9 +191,10 @@ def auto_source(sr: SegmentRange, mode=ReadMode.RLOG) -> LogPaths: try: return check_source(source, sr, mode) except Exception as e: - exceptions.append(e) + exceptions[source.__name__] = e - raise Exception(f"auto_source could not find any valid source, exceptions for sources: {exceptions}") + raise Exception("auto_source could not find any valid source, exceptions for sources:\n - " + + "\n - ".join([f"{k}: {repr(v)}" for k, v in exceptions.items()])) def parse_useradmin(identifier: str): From a0bbc005b62f1e6183ce4fd167e78b4fedb06df0 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Thu, 13 Jun 2024 22:43:24 -0700 Subject: [PATCH 16/30] LogReader: support reading zst logs from Azure (#32745) * staging api * other stuff * ugh this should really not be duplicated, we already check the max segnum in Route class * better error message!! * more better * clean up * clean up * breaks again --- tools/lib/route.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/lib/route.py b/tools/lib/route.py index d5fd41108..5734d1c74 100644 --- a/tools/lib/route.py +++ b/tools/lib/route.py @@ -9,7 +9,7 @@ from openpilot.tools.lib.auth_config import get_token from openpilot.tools.lib.api import CommaApi from openpilot.tools.lib.helpers import RE -QLOG_FILENAMES = ['qlog', 'qlog.bz2'] +QLOG_FILENAMES = ['qlog', 'qlog.bz2', 'qlog.zst'] QCAMERA_FILENAMES = ['qcamera.ts'] LOG_FILENAMES = ['rlog', 'rlog.bz2', 'raw_log.bz2'] CAMERA_FILENAMES = ['fcamera.hevc', 'video.hevc'] From d5ce4b308588f2bd4eee300110ddcd66e787a110 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Thu, 13 Jun 2024 23:19:32 -0700 Subject: [PATCH 17/30] SegmentRange: remove timestamp (#32750) * add deprecation warning * remove timestamp * Update logreader.py --- tools/lib/logreader.py | 2 +- tools/lib/route.py | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/tools/lib/logreader.py b/tools/lib/logreader.py index 737ef4615..0f7ae0dba 100755 --- a/tools/lib/logreader.py +++ b/tools/lib/logreader.py @@ -135,7 +135,7 @@ def internal_source(sr: SegmentRange, mode: ReadMode) -> LogPaths: raise InternalUnavailableException def get_internal_url(sr: SegmentRange, seg, file): - return f"cd:/{sr.dongle_id}/{sr.timestamp}/{seg}/{file}.bz2" + return f"cd:/{sr.dongle_id}/{sr.log_id}/{seg}/{file}.bz2" rlog_paths = [get_internal_url(sr, seg, "rlog") for seg in sr.seg_idxs] qlog_paths = [get_internal_url(sr, seg, "qlog") for seg in sr.seg_idxs] diff --git a/tools/lib/route.py b/tools/lib/route.py index 5734d1c74..6ff5d1920 100644 --- a/tools/lib/route.py +++ b/tools/lib/route.py @@ -260,10 +260,6 @@ class SegmentRange: def dongle_id(self) -> str: return self.m.group("dongle_id") - @property - def timestamp(self) -> str: - return self.m.group("timestamp") - @property def log_id(self) -> str: return self.m.group("log_id") From 38529c5057a6146768a71654a05e5c552695d805 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Fri, 14 Jun 2024 14:38:02 +0800 Subject: [PATCH 18/30] cabana: Fix visibility issue for a single data point in series (#32749) Fix visibility issue for a single data point in series --- tools/cabana/chart/chart.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/cabana/chart/chart.cc b/tools/cabana/chart/chart.cc index fcf171a85..c8537845b 100644 --- a/tools/cabana/chart/chart.cc +++ b/tools/cabana/chart/chart.cc @@ -277,7 +277,7 @@ void ChartView::updateSeriesPoints() { } ((QScatterSeries *)s.series)->setMarkerSize(size); } else { - s.series->setPointsVisible(pixels_per_point > 20); + s.series->setPointsVisible(num_points == 1 || pixels_per_point > 20); } } } From bc303df6a0a4a9d52a2e92e5976b6c7aa5138b95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harald=20Sch=C3=A4fer?= Date: Fri, 14 Jun 2024 00:08:58 -0700 Subject: [PATCH 19/30] long control: new API (#32706) * Simplify long control * Seperate * Rename * Try new api for toyota * rm v_pid everywhere * No speed in reset * 0 is better default * unassigned variable * Update other cars * Update gm * SIMPLIFY * simplify more * fix API boundry * Fix stopping bug * Small fixes * Update ref --- cereal/car.capnp | 4 +- cereal/log.capnp | 8 +- selfdrive/car/ford/interface.py | 4 - selfdrive/car/gm/interface.py | 12 +-- selfdrive/car/honda/interface.py | 8 +- selfdrive/car/hyundai/interface.py | 4 - selfdrive/car/interfaces.py | 6 +- selfdrive/car/subaru/interface.py | 5 -- selfdrive/car/tesla/interface.py | 5 -- selfdrive/car/tests/test_car_interfaces.py | 1 - selfdrive/car/toyota/interface.py | 21 ++--- selfdrive/car/volkswagen/interface.py | 2 - selfdrive/controls/controlsd.py | 6 +- selfdrive/controls/lib/drive_helpers.py | 10 --- selfdrive/controls/lib/longcontrol.py | 78 +++++-------------- .../controls/lib/longitudinal_planner.py | 33 +++++++- selfdrive/test/process_replay/ref_commit | 2 +- tools/replay/ui.py | 1 - 18 files changed, 74 insertions(+), 136 deletions(-) diff --git a/cereal/car.capnp b/cereal/car.capnp index 7f3f64c91..c17e1c063 100644 --- a/cereal/car.capnp +++ b/cereal/car.capnp @@ -541,8 +541,8 @@ struct CarParams { kiBP @2 :List(Float32); kiV @3 :List(Float32); kf @6 :Float32; - deadzoneBP @4 :List(Float32); - deadzoneV @5 :List(Float32); + deadzoneBPDEPRECATED @4 :List(Float32); + deadzoneVDEPRECATED @5 :List(Float32); } struct LateralINDITuning { diff --git a/cereal/log.capnp b/cereal/log.capnp index 67c6f836a..3c720d452 100644 --- a/cereal/log.capnp +++ b/cereal/log.capnp @@ -698,7 +698,6 @@ struct ControlsState @0x97ff69c53601abf1 { personality @66 :LongitudinalPersonality; longControlState @30 :Car.CarControl.Actuators.LongControlState; - vPid @2 :Float32; vTargetLead @3 :Float32; vCruise @22 :Float32; # actual set speed vCruiseCluster @63 :Float32; # set speed to display in the UI @@ -866,6 +865,7 @@ struct ControlsState @0x97ff69c53601abf1 { canMonoTimesDEPRECATED @21 :List(UInt64); desiredCurvatureRateDEPRECATED @62 :Float32; canErrorCounterDEPRECATED @57 :UInt32; + vPidDEPRECATED @2 :Float32; } # All SI units and in device frame @@ -1060,6 +1060,11 @@ struct LongitudinalPlan @0xe00b5b3eba12876c { accels @32 :List(Float32); speeds @33 :List(Float32); jerks @34 :List(Float32); + aTarget @18 :Float32; + shouldStop @37: Bool; + allowThrottle @38: Bool; + allowBrake @39: Bool; + solverExecutionTime @35 :Float32; @@ -1076,7 +1081,6 @@ struct LongitudinalPlan @0xe00b5b3eba12876c { aCruiseDEPRECATED @17 :Float32; vTargetDEPRECATED @3 :Float32; vTargetFutureDEPRECATED @14 :Float32; - aTargetDEPRECATED @18 :Float32; vStartDEPRECATED @26 :Float32; aStartDEPRECATED @27 :Float32; vMaxDEPRECATED @20 :Float32; diff --git a/selfdrive/car/ford/interface.py b/selfdrive/car/ford/interface.py index 2ef5d427e..54cf86510 100644 --- a/selfdrive/car/ford/interface.py +++ b/selfdrive/car/ford/interface.py @@ -22,10 +22,6 @@ class CarInterface(CarInterfaceBase): ret.steerActuatorDelay = 0.2 ret.steerLimitTimer = 1.0 - ret.longitudinalTuning.kpBP = [0.] - ret.longitudinalTuning.kpV = [0.5] - ret.longitudinalTuning.kiV = [0.] - CAN = CanBus(fingerprint=fingerprint) cfgs = [get_safety_config(car.CarParams.SafetyModel.ford)] if CAN.main >= 4: diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py index 2e194b12f..5ea2b1989 100755 --- a/selfdrive/car/gm/interface.py +++ b/selfdrive/car/gm/interface.py @@ -94,11 +94,7 @@ class CarInterface(CarInterfaceBase): else: ret.transmissionType = TransmissionType.automatic - ret.longitudinalTuning.deadzoneBP = [0.] - ret.longitudinalTuning.deadzoneV = [0.15] - - ret.longitudinalTuning.kpBP = [5., 35.] - ret.longitudinalTuning.kiBP = [0.] + ret.longitudinalTuning.kiBP = [5., 35.] if candidate in CAMERA_ACC_CAR: ret.experimentalLongitudinalAvailable = True @@ -110,8 +106,7 @@ class CarInterface(CarInterfaceBase): ret.minSteerSpeed = 10 * CV.KPH_TO_MS # Tuning for experimental long - ret.longitudinalTuning.kpV = [2.0, 1.5] - ret.longitudinalTuning.kiV = [0.72] + ret.longitudinalTuning.kiV = [2.0, 1.5] ret.stoppingDecelRate = 2.0 # reach brake quickly after enabling ret.vEgoStopping = 0.25 ret.vEgoStarting = 0.25 @@ -131,8 +126,7 @@ class CarInterface(CarInterfaceBase): ret.minSteerSpeed = 7 * CV.MPH_TO_MS # Tuning - ret.longitudinalTuning.kpV = [2.4, 1.5] - ret.longitudinalTuning.kiV = [0.36] + ret.longitudinalTuning.kiV = [2.4, 1.5] # These cars have been put into dashcam only due to both a lack of users and test coverage. # These cars likely still work fine. Once a user confirms each car works and a test route is diff --git a/selfdrive/car/honda/interface.py b/selfdrive/car/honda/interface.py index 43a4454b9..fdcba8bb8 100755 --- a/selfdrive/car/honda/interface.py +++ b/selfdrive/car/honda/interface.py @@ -72,17 +72,13 @@ class CarInterface(CarInterfaceBase): ret.lateralTuning.pid.kf = 0.00006 # conservative feed-forward if candidate in HONDA_BOSCH: - ret.longitudinalTuning.kpV = [0.25] - ret.longitudinalTuning.kiV = [0.05] ret.longitudinalActuatorDelay = 0.5 # s if candidate in HONDA_BOSCH_RADARLESS: ret.stopAccel = CarControllerParams.BOSCH_ACCEL_MIN # stock uses -4.0 m/s^2 once stopped but limited by safety model else: # default longitudinal tuning for all hondas - ret.longitudinalTuning.kpBP = [0., 5., 35.] - ret.longitudinalTuning.kpV = [1.2, 0.8, 0.5] - ret.longitudinalTuning.kiBP = [0., 35.] - ret.longitudinalTuning.kiV = [0.18, 0.12] + ret.longitudinalTuning.kiBP = [0., 5., 35.] + ret.longitudinalTuning.kiV = [1.2, 0.8, 0.5] eps_modified = False for fw in car_fw: diff --git a/selfdrive/car/hyundai/interface.py b/selfdrive/car/hyundai/interface.py index 0ba4dcb5e..ecedf3fd7 100644 --- a/selfdrive/car/hyundai/interface.py +++ b/selfdrive/car/hyundai/interface.py @@ -80,12 +80,8 @@ class CarInterface(CarInterfaceBase): # *** longitudinal control *** if candidate in CANFD_CAR: - ret.longitudinalTuning.kpV = [0.1] - ret.longitudinalTuning.kiV = [0.0] ret.experimentalLongitudinalAvailable = candidate not in (CANFD_UNSUPPORTED_LONGITUDINAL_CAR | CANFD_RADAR_SCC_CAR) else: - ret.longitudinalTuning.kpV = [0.5] - ret.longitudinalTuning.kiV = [0.0] ret.experimentalLongitudinalAvailable = candidate not in (UNSUPPORTED_LONGITUDINAL_CAR | CAMERA_SCC_CAR) ret.openpilotLongitudinalControl = experimental_long and ret.experimentalLongitudinalAvailable ret.pcmCruise = not ret.openpilotLongitudinalControl diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index 5eac6062a..e5762ed52 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -202,13 +202,11 @@ class CarInterfaceBase(ABC): ret.vEgoStopping = 0.5 ret.vEgoStarting = 0.5 ret.stoppingControl = True - ret.longitudinalTuning.deadzoneBP = [0.] - ret.longitudinalTuning.deadzoneV = [0.] ret.longitudinalTuning.kf = 1. ret.longitudinalTuning.kpBP = [0.] - ret.longitudinalTuning.kpV = [1.] + ret.longitudinalTuning.kpV = [0.] ret.longitudinalTuning.kiBP = [0.] - ret.longitudinalTuning.kiV = [1.] + ret.longitudinalTuning.kiV = [0.] # TODO estimate car specific lag, use .15s for now ret.longitudinalActuatorDelay = 0.15 ret.steerLimitTimer = 1.0 diff --git a/selfdrive/car/subaru/interface.py b/selfdrive/car/subaru/interface.py index 1aa4bd95e..cb0093437 100644 --- a/selfdrive/car/subaru/interface.py +++ b/selfdrive/car/subaru/interface.py @@ -91,11 +91,6 @@ class CarInterface(CarInterfaceBase): ret.flags |= SubaruFlags.DISABLE_EYESIGHT.value if ret.openpilotLongitudinalControl: - ret.longitudinalTuning.kpBP = [0., 5., 35.] - ret.longitudinalTuning.kpV = [0.8, 1.0, 1.5] - ret.longitudinalTuning.kiBP = [0., 35.] - ret.longitudinalTuning.kiV = [0.54, 0.36] - ret.stoppingControl = True ret.safetyConfigs[0].safetyParam |= Panda.FLAG_SUBARU_LONG diff --git a/selfdrive/car/tesla/interface.py b/selfdrive/car/tesla/interface.py index 09de10b54..deb0e0023 100755 --- a/selfdrive/car/tesla/interface.py +++ b/selfdrive/car/tesla/interface.py @@ -18,11 +18,6 @@ class CarInterface(CarInterfaceBase): ret.steerControlType = car.CarParams.SteerControlType.angle - # Set kP and kI to 0 over the whole speed range to have the planner accel as actuator command - ret.longitudinalTuning.kpBP = [0] - ret.longitudinalTuning.kpV = [0] - ret.longitudinalTuning.kiBP = [0] - ret.longitudinalTuning.kiV = [0] ret.longitudinalActuatorDelay = 0.5 # s ret.radarTimeStep = (1.0 / 8) # 8Hz diff --git a/selfdrive/car/tests/test_car_interfaces.py b/selfdrive/car/tests/test_car_interfaces.py index 19096c23e..a6f74d685 100644 --- a/selfdrive/car/tests/test_car_interfaces.py +++ b/selfdrive/car/tests/test_car_interfaces.py @@ -75,7 +75,6 @@ class TestCarInterfaces: # Longitudinal sanity checks assert len(car_params.longitudinalTuning.kpV) == len(car_params.longitudinalTuning.kpBP) assert len(car_params.longitudinalTuning.kiV) == len(car_params.longitudinalTuning.kiBP) - assert len(car_params.longitudinalTuning.deadzoneV) == len(car_params.longitudinalTuning.deadzoneBP) # Lateral sanity checks if car_params.steerControlType != car.CarParams.SteerControlType.angle: diff --git a/selfdrive/car/toyota/interface.py b/selfdrive/car/toyota/interface.py index 3ea05f9fe..98f63597e 100644 --- a/selfdrive/car/toyota/interface.py +++ b/selfdrive/car/toyota/interface.py @@ -142,22 +142,15 @@ class CarInterface(CarInterfaceBase): ret.minEnableSpeed = -1. if stop_and_go else MIN_ACC_SPEED tune = ret.longitudinalTuning - tune.deadzoneBP = [0., 9.] - tune.deadzoneV = [.0, .15] if candidate in TSS2_CAR: - tune.kpBP = [0., 5., 20.] - tune.kpV = [1.3, 1.0, 0.7] - tune.kiBP = [0., 5., 12., 20., 27.] - tune.kiV = [.35, .23, .20, .17, .1] - if candidate in TSS2_CAR: - ret.vEgoStopping = 0.25 - ret.vEgoStarting = 0.25 - ret.stoppingDecelRate = 0.3 # reach stopping target smoothly + tune.kpV = [0.0] + tune.kiV = [0.5] + ret.vEgoStopping = 0.25 + ret.vEgoStarting = 0.25 + ret.stoppingDecelRate = 0.3 # reach stopping target smoothly else: - tune.kpBP = [0., 5., 35.] - tune.kiBP = [0., 35.] - tune.kpV = [3.6, 2.4, 1.5] - tune.kiV = [0.54, 0.36] + tune.kiBP = [0., 5., 35.] + tune.kiV = [3.6, 2.4, 1.5] return ret diff --git a/selfdrive/car/volkswagen/interface.py b/selfdrive/car/volkswagen/interface.py index 91cd300e9..77e56875b 100644 --- a/selfdrive/car/volkswagen/interface.py +++ b/selfdrive/car/volkswagen/interface.py @@ -96,8 +96,6 @@ class CarInterface(CarInterfaceBase): ret.stopAccel = -0.55 ret.vEgoStarting = 0.1 ret.vEgoStopping = 0.5 - ret.longitudinalTuning.kpV = [0.1] - ret.longitudinalTuning.kiV = [0.0] ret.autoResumeSng = ret.minEnableSpeed == -1 return ret diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index aeeb3489b..f147766c9 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -563,13 +563,12 @@ class Controls: if not CC.latActive: self.LaC.reset() if not CC.longActive: - self.LoC.reset(v_pid=CS.vEgo) + self.LoC.reset() if not self.joystick_mode: # accel PID loop pid_accel_limits = self.CI.get_pid_accel_limits(self.CP, CS.vEgo, self.v_cruise_helper.v_cruise_kph * CV.KPH_TO_MS) - t_since_plan = (self.sm.frame - self.sm.recv_frame['longitudinalPlan']) * DT_CTRL - actuators.accel = self.LoC.update(CC.longActive, CS, long_plan, pid_accel_limits, t_since_plan) + actuators.accel = self.LoC.update(CC.longActive, CS, long_plan.aTarget, long_plan.shouldStop, pid_accel_limits) # Steering PID loop and lateral MPC self.desired_curvature = clip_curvature(CS.vEgo, self.desired_curvature, model_v2.action.desiredCurvature) @@ -752,7 +751,6 @@ class Controls: controlsState.state = self.state controlsState.engageable = not self.events.contains(ET.NO_ENTRY) controlsState.longControlState = self.LoC.long_control_state - controlsState.vPid = float(self.LoC.v_pid) controlsState.vCruise = float(self.v_cruise_helper.v_cruise_kph) controlsState.vCruiseCluster = float(self.v_cruise_helper.v_cruise_cluster_kph) controlsState.upAccelCmd = float(self.LoC.pid.p) diff --git a/selfdrive/controls/lib/drive_helpers.py b/selfdrive/controls/lib/drive_helpers.py index 6a5b22f68..cfc6374a1 100644 --- a/selfdrive/controls/lib/drive_helpers.py +++ b/selfdrive/controls/lib/drive_helpers.py @@ -141,16 +141,6 @@ class VCruiseHelper: self.v_cruise_cluster_kph = self.v_cruise_kph -def apply_deadzone(error, deadzone): - if error > deadzone: - error -= deadzone - elif error < - deadzone: - error += deadzone - else: - error = 0. - return error - - def apply_center_deadzone(error, deadzone): if (error > - deadzone) and (error < deadzone): error = 0. diff --git a/selfdrive/controls/lib/longcontrol.py b/selfdrive/controls/lib/longcontrol.py index a619c4763..e4841c705 100644 --- a/selfdrive/controls/lib/longcontrol.py +++ b/selfdrive/controls/lib/longcontrol.py @@ -1,7 +1,7 @@ from cereal import car -from openpilot.common.numpy_fast import clip, interp +from openpilot.common.numpy_fast import clip from openpilot.common.realtime import DT_CTRL -from openpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N, apply_deadzone +from openpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N from openpilot.selfdrive.controls.lib.pid import PIDController from openpilot.selfdrive.modeld.constants import ModelConstants @@ -10,18 +10,10 @@ CONTROL_N_T_IDX = ModelConstants.T_IDXS[:CONTROL_N] LongCtrlState = car.CarControl.Actuators.LongControlState -def long_control_state_trans(CP, active, long_control_state, v_ego, v_target, - v_target_1sec, brake_pressed, cruise_standstill): - accelerating = v_target_1sec > v_target - planned_stop = (v_target < CP.vEgoStopping and - v_target_1sec < CP.vEgoStopping and - not accelerating) - stay_stopped = (v_ego < CP.vEgoStopping and - (brake_pressed or cruise_standstill)) - stopping_condition = planned_stop or stay_stopped - - starting_condition = (v_target_1sec > CP.vEgoStarting and - accelerating and +def long_control_state_trans(CP, active, long_control_state, v_ego, + should_stop, brake_pressed, cruise_standstill): + stopping_condition = should_stop + starting_condition = (not should_stop and not cruise_standstill and not brake_pressed) started_condition = v_ego > CP.vEgoStarting @@ -34,7 +26,6 @@ def long_control_state_trans(CP, active, long_control_state, v_ego, v_target, long_control_state = LongCtrlState.pid if stopping_condition: long_control_state = LongCtrlState.stopping - elif long_control_state == LongCtrlState.stopping: if starting_condition and CP.startingState: long_control_state = LongCtrlState.starting @@ -49,78 +40,45 @@ def long_control_state_trans(CP, active, long_control_state, v_ego, v_target, return long_control_state - class LongControl: def __init__(self, CP): self.CP = CP - self.long_control_state = LongCtrlState.off # initialized to off + self.long_control_state = LongCtrlState.off self.pid = PIDController((CP.longitudinalTuning.kpBP, CP.longitudinalTuning.kpV), (CP.longitudinalTuning.kiBP, CP.longitudinalTuning.kiV), k_f=CP.longitudinalTuning.kf, rate=1 / DT_CTRL) - self.v_pid = 0.0 self.last_output_accel = 0.0 - def reset(self, v_pid): - """Reset PID controller and change setpoint""" + def reset(self): self.pid.reset() - self.v_pid = v_pid - def update(self, active, CS, long_plan, accel_limits, t_since_plan): + def update(self, active, CS, a_target, should_stop, accel_limits): """Update longitudinal control. This updates the state machine and runs a PID loop""" - # Interp control trajectory - speeds = long_plan.speeds - if len(speeds) == CONTROL_N: - v_target_now = interp(t_since_plan, CONTROL_N_T_IDX, speeds) - a_target_now = interp(t_since_plan, CONTROL_N_T_IDX, long_plan.accels) - - v_target = interp(self.CP.longitudinalActuatorDelay + t_since_plan, CONTROL_N_T_IDX, speeds) - a_target = 2 * (v_target - v_target_now) / self.CP.longitudinalActuatorDelay - a_target_now - - v_target_1sec = interp(self.CP.longitudinalActuatorDelay + t_since_plan + 1.0, CONTROL_N_T_IDX, speeds) - else: - v_target = 0.0 - v_target_now = 0.0 - v_target_1sec = 0.0 - a_target = 0.0 - self.pid.neg_limit = accel_limits[0] self.pid.pos_limit = accel_limits[1] - output_accel = self.last_output_accel self.long_control_state = long_control_state_trans(self.CP, active, self.long_control_state, CS.vEgo, - v_target, v_target_1sec, CS.brakePressed, + should_stop, CS.brakePressed, CS.cruiseState.standstill) - if self.long_control_state == LongCtrlState.off: - self.reset(CS.vEgo) + self.reset() output_accel = 0. elif self.long_control_state == LongCtrlState.stopping: + output_accel = self.last_output_accel if output_accel > self.CP.stopAccel: output_accel = min(output_accel, 0.0) output_accel -= self.CP.stoppingDecelRate * DT_CTRL - self.reset(CS.vEgo) + self.reset() elif self.long_control_state == LongCtrlState.starting: output_accel = self.CP.startAccel - self.reset(CS.vEgo) + self.reset() - elif self.long_control_state == LongCtrlState.pid: - self.v_pid = v_target_now - - # Toyota starts braking more when it thinks you want to stop - # Freeze the integrator so we don't accelerate to compensate, and don't allow positive acceleration - # TODO too complex, needs to be simplified and tested on toyotas - prevent_overshoot = not self.CP.stoppingControl and CS.vEgo < 1.5 and v_target_1sec < 0.7 and v_target_1sec < self.v_pid - deadzone = interp(CS.vEgo, self.CP.longitudinalTuning.deadzoneBP, self.CP.longitudinalTuning.deadzoneV) - freeze_integrator = prevent_overshoot - - error = self.v_pid - CS.vEgo - error_deadzone = apply_deadzone(error, deadzone) - output_accel = self.pid.update(error_deadzone, speed=CS.vEgo, - feedforward=a_target, - freeze_integrator=freeze_integrator) + else: # LongCtrlState.pid + error = a_target - CS.aEgo + output_accel = self.pid.update(error, speed=CS.vEgo, + feedforward=a_target) self.last_output_accel = clip(output_accel, accel_limits[0], accel_limits[1]) - return self.last_output_accel diff --git a/selfdrive/controls/lib/longitudinal_planner.py b/selfdrive/controls/lib/longitudinal_planner.py index ff5f901b5..8772fadb4 100755 --- a/selfdrive/controls/lib/longitudinal_planner.py +++ b/selfdrive/controls/lib/longitudinal_planner.py @@ -19,6 +19,7 @@ LON_MPC_STEP = 0.2 # first step is 0.2s A_CRUISE_MIN = -1.2 A_CRUISE_MAX_VALS = [1.6, 1.2, 0.8, 0.6] A_CRUISE_MAX_BP = [0., 10.0, 25., 40.] +CONTROL_N_T_IDX = ModelConstants.T_IDXS[:CONTROL_N] # Lookup table for turns _A_TOTAL_MAX_V = [1.7, 3.2] @@ -34,7 +35,6 @@ def limit_accel_in_turns(v_ego, angle_steers, a_target, CP): This function returns a limited long acceleration allowed, depending on the existing lateral acceleration this should avoid accelerating when losing the target in turns """ - # FIXME: This function to calculate lateral accel is incorrect and should use the VehicleModel # The lookup table for turns should also be updated if we do this a_total_max = interp(v_ego, _A_TOTAL_MAX_BP, _A_TOTAL_MAX_V) @@ -44,6 +44,26 @@ def limit_accel_in_turns(v_ego, angle_steers, a_target, CP): return [a_target[0], min(a_target[1], a_x_allowed)] +def get_accel_from_plan(CP, long_plan): + speeds = long_plan.speeds + if len(speeds) == CONTROL_N: + v_target_now = interp(DT_MDL, CONTROL_N_T_IDX, speeds) + a_target_now = interp(DT_MDL, CONTROL_N_T_IDX, long_plan.accels) + + v_target = interp(CP.longitudinalActuatorDelay + DT_MDL, CONTROL_N_T_IDX, speeds) + a_target = 2 * (v_target - v_target_now) / CP.longitudinalActuatorDelay - a_target_now + + v_target_1sec = interp(CP.longitudinalActuatorDelay + DT_MDL + 1.0, CONTROL_N_T_IDX, speeds) + else: + v_target = 0.0 + v_target_now = 0.0 + v_target_1sec = 0.0 + a_target = 0.0 + should_stop = (v_target < CP.vEgoStopping and + v_target_1sec < CP.vEgoStopping) + return a_target, should_stop + + class LongitudinalPlanner: def __init__(self, CP, init_v=0.0, init_a=0.0, dt=DT_MDL): self.CP = CP @@ -142,9 +162,14 @@ class LongitudinalPlanner: plan_send.valid = sm.all_checks(service_list=['carState', 'controlsState']) + longitudinalPlan = plan_send.longitudinalPlan longitudinalPlan.modelMonoTime = sm.logMonoTime['modelV2'] longitudinalPlan.processingDelay = (plan_send.logMonoTime / 1e9) - sm.logMonoTime['modelV2'] + longitudinalPlan.solverExecutionTime = self.mpc.solve_time + + longitudinalPlan.allowBrake = True + longitudinalPlan.allowThrottle = True longitudinalPlan.speeds = self.v_desired_trajectory.tolist() longitudinalPlan.accels = self.a_desired_trajectory.tolist() @@ -154,6 +179,10 @@ class LongitudinalPlanner: longitudinalPlan.longitudinalPlanSource = self.mpc.source longitudinalPlan.fcw = self.fcw - longitudinalPlan.solverExecutionTime = self.mpc.solve_time + a_target, should_stop = get_accel_from_plan(self.CP, longitudinalPlan) + longitudinalPlan.aTarget = a_target + longitudinalPlan.shouldStop = should_stop + longitudinalPlan.allowBrake = True + longitudinalPlan.allowThrottle = True pm.send('longitudinalPlan', plan_send) diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 227202839..96161a42d 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -6438bd5edad674c2de3c7e2d126271cb2576383d +8737e368e17f859291164286feb4246e00c0b4a5 diff --git a/tools/replay/ui.py b/tools/replay/ui.py index a790f14ff..b1fe70ef3 100755 --- a/tools/replay/ui.py +++ b/tools/replay/ui.py @@ -158,7 +158,6 @@ def ui_thread(addr): # TODO brake is deprecated plot_arr[-1, name_to_arr_idx['computer_brake']] = clip(-sm['carControl'].actuators.accel/4.0, 0.0, 1.0) plot_arr[-1, name_to_arr_idx['v_ego']] = sm['carState'].vEgo - plot_arr[-1, name_to_arr_idx['v_pid']] = sm['controlsState'].vPid plot_arr[-1, name_to_arr_idx['v_cruise']] = sm['carState'].cruiseState.speed plot_arr[-1, name_to_arr_idx['a_ego']] = sm['carState'].aEgo From 68e22faa296d335f2d497c52339f536f761602c3 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Fri, 14 Jun 2024 00:29:59 -0700 Subject: [PATCH 20/30] LogReader: revert broken check it returns files OR None --- tools/lib/logreader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/lib/logreader.py b/tools/lib/logreader.py index 0f7ae0dba..e524a152f 100755 --- a/tools/lib/logreader.py +++ b/tools/lib/logreader.py @@ -167,7 +167,7 @@ def get_invalid_files(files): def check_source(source: Source, *args) -> LogPaths: files = source(*args) assert len(files) > 0, "No files on source" - assert not any(get_invalid_files(files)), f"Invalid files: {files}" + assert next(get_invalid_files(files), False) is False, "Some files are invalid" return files From b45caf403366ed4161516e49b9e433805d9de6c4 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Fri, 14 Jun 2024 01:12:19 -0700 Subject: [PATCH 21/30] LogReader: try zst on internal source (#32751) * internal source list files like azure api * messy but works * no limit * simpler * clean up * clean up * clean up * that's obvious * better * we need to unfortunately return a url, so best to take a naive approach for now * todo * fix * clean up --- tools/lib/logreader.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/lib/logreader.py b/tools/lib/logreader.py index e524a152f..98c10941b 100755 --- a/tools/lib/logreader.py +++ b/tools/lib/logreader.py @@ -130,12 +130,12 @@ def comma_api_source(sr: SegmentRange, mode: ReadMode) -> LogPaths: return apply_strategy(mode, rlog_paths, qlog_paths, valid_file=valid_file) -def internal_source(sr: SegmentRange, mode: ReadMode) -> LogPaths: +def internal_source(sr: SegmentRange, mode: ReadMode, file_ext: str = "bz2") -> LogPaths: if not internal_source_available(): raise InternalUnavailableException def get_internal_url(sr: SegmentRange, seg, file): - return f"cd:/{sr.dongle_id}/{sr.log_id}/{seg}/{file}.bz2" + return f"cd:/{sr.dongle_id}/{sr.log_id}/{seg}/{file}.{file_ext}" rlog_paths = [get_internal_url(sr, seg, "rlog") for seg in sr.seg_idxs] qlog_paths = [get_internal_url(sr, seg, "qlog") for seg in sr.seg_idxs] @@ -143,6 +143,10 @@ def internal_source(sr: SegmentRange, mode: ReadMode) -> LogPaths: return apply_strategy(mode, rlog_paths, qlog_paths) +def internal_source_zst(sr: SegmentRange, mode: ReadMode, file_ext: str = "zst") -> LogPaths: + return internal_source(sr, mode, file_ext) + + def openpilotci_source(sr: SegmentRange, mode: ReadMode) -> LogPaths: rlog_paths = [get_url(sr.route_name, seg, "rlog") for seg in sr.seg_idxs] qlog_paths = [get_url(sr.route_name, seg, "qlog") for seg in sr.seg_idxs] @@ -175,7 +179,7 @@ def auto_source(sr: SegmentRange, mode=ReadMode.RLOG) -> LogPaths: if mode == ReadMode.SANITIZED: return comma_car_segments_source(sr, mode) - SOURCES: list[Source] = [internal_source, openpilotci_source, comma_api_source, comma_car_segments_source,] + SOURCES: list[Source] = [internal_source, internal_source_zst, openpilotci_source, comma_api_source, comma_car_segments_source,] exceptions = {} # for automatic fallback modes, auto_source needs to first check if rlogs exist for any source From 02ed9c584c7d04d53d3c0f0955e95ab2a58de5de Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Sun, 16 Jun 2024 12:20:15 -0700 Subject: [PATCH 22/30] sim: remove docker script --- tools/sim/start_openpilot_docker.sh | 37 ----------------------------- 1 file changed, 37 deletions(-) delete mode 100755 tools/sim/start_openpilot_docker.sh diff --git a/tools/sim/start_openpilot_docker.sh b/tools/sim/start_openpilot_docker.sh deleted file mode 100755 index 3dce66057..000000000 --- a/tools/sim/start_openpilot_docker.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" -cd $DIR - -OPENPILOT_DIR="/tmp/openpilot" -if ! [[ -z "$MOUNT_OPENPILOT" ]]; then - OPENPILOT_DIR="$(dirname $(dirname $DIR))" - EXTRA_ARGS="-v $OPENPILOT_DIR:$OPENPILOT_DIR -e PYTHONPATH=$OPENPILOT_DIR:$PYTHONPATH" -fi - -if [[ "$CI" ]]; then - CMD="CI=1 ${OPENPILOT_DIR}/tools/sim/tests/test_metadrive_integration.py" -else - # expose X to the container - xhost +local:root - - docker pull ghcr.io/commaai/openpilot-sim:latest - CMD="./tmux_script.sh $*" - EXTRA_ARGS="${EXTRA_ARGS} -it" -fi - -docker kill openpilot_client || true -docker run --net=host\ - --name openpilot_client \ - --rm \ - --gpus all \ - --device=/dev/dri:/dev/dri \ - --device=/dev/input:/dev/input \ - -v /tmp/.X11-unix:/tmp/.X11-unix \ - --shm-size 1G \ - -e DISPLAY=$DISPLAY \ - -e QT_X11_NO_MITSHM=1 \ - -w "$OPENPILOT_DIR/tools/sim" \ - $EXTRA_ARGS \ - ghcr.io/commaai/openpilot-sim:latest \ - /bin/bash -c "$CMD" From 865b98a5c45335dcdf736ab38e89b5a1dcde2d59 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Mon, 17 Jun 2024 03:32:45 +0800 Subject: [PATCH 23/30] cabana: avoid dead locks and improve responsiveness (#32740) avoid dead locks and improve responsive --- tools/cabana/chart/chart.cc | 2 +- tools/cabana/chart/chartswidget.cc | 24 ++++--- tools/cabana/chart/chartswidget.h | 16 ++--- tools/cabana/mainwin.cc | 1 - tools/cabana/streams/abstractstream.cc | 22 ++++++- tools/cabana/streams/abstractstream.h | 8 ++- tools/cabana/streams/replaystream.cc | 7 +- tools/cabana/streams/replaystream.h | 3 - tools/cabana/videowidget.cc | 23 ++++--- tools/cabana/videowidget.h | 8 +-- tools/replay/camera.cc | 1 - tools/replay/logreader.cc | 6 +- tools/replay/replay.cc | 88 +++++++++++++++----------- tools/replay/replay.h | 11 ++-- tools/replay/util.cc | 36 ++++------- tools/replay/util.h | 2 +- 16 files changed, 135 insertions(+), 123 deletions(-) diff --git a/tools/cabana/chart/chart.cc b/tools/cabana/chart/chart.cc index c8537845b..7a056c767 100644 --- a/tools/cabana/chart/chart.cc +++ b/tools/cabana/chart/chart.cc @@ -513,7 +513,7 @@ void ChartView::mouseReleaseEvent(QMouseEvent *event) { // no rubber dragged, seek to mouse position can->seekTo(min); } else if (rubber->width() > 10 && (max - min) > MIN_ZOOM_SECONDS) { - charts_widget->zoom_undo_stack->push(new ZoomCommand(charts_widget, {min, max})); + charts_widget->zoom_undo_stack->push(new ZoomCommand({min, max})); } else { viewport()->update(); } diff --git a/tools/cabana/chart/chartswidget.cc b/tools/cabana/chart/chartswidget.cc index a7bdd7464..59c188afb 100644 --- a/tools/cabana/chart/chartswidget.cc +++ b/tools/cabana/chart/chartswidget.cc @@ -103,6 +103,8 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QFrame(parent) { QObject::connect(dbc(), &DBCManager::DBCFileChanged, this, &ChartsWidget::removeAll); QObject::connect(can, &AbstractStream::eventsMerged, this, &ChartsWidget::eventsMerged); QObject::connect(can, &AbstractStream::msgsReceived, this, &ChartsWidget::updateState); + QObject::connect(can, &AbstractStream::seeking, this, &ChartsWidget::updateState); + QObject::connect(can, &AbstractStream::timeRangeChanged, this, &ChartsWidget::timeRangeChanged); QObject::connect(range_slider, &QSlider::valueChanged, this, &ChartsWidget::setMaxChartRange); QObject::connect(new_plot_btn, &QToolButton::clicked, this, &ChartsWidget::newChart); QObject::connect(remove_all_btn, &QToolButton::clicked, this, &ChartsWidget::removeAll); @@ -159,16 +161,13 @@ void ChartsWidget::eventsMerged(const MessageEventsMap &new_events) { } } -void ChartsWidget::setZoom(double min, double max) { - zoomed_range = {min, max}; - is_zoomed = zoomed_range != display_range; +void ChartsWidget::timeRangeChanged(const std::optional> &time_range) { updateToolBar(); updateState(); - emit rangeChanged(min, max, is_zoomed); } void ChartsWidget::zoomReset() { - setZoom(display_range.first, display_range.second); + can->setTimeRange(std::nullopt); zoom_undo_stack->clear(); } @@ -186,8 +185,9 @@ void ChartsWidget::showValueTip(double sec) { void ChartsWidget::updateState() { if (charts.isEmpty()) return; + const auto &time_range = can->timeRange(); const double cur_sec = can->currentSec(); - if (!is_zoomed) { + if (!time_range.has_value()) { double pos = (cur_sec - display_range.first) / std::max(1.0, max_chart_range); if (pos < 0 || pos > 0.8) { display_range.first = std::max(0.0, cur_sec - max_chart_range * 0.1); @@ -195,13 +195,9 @@ void ChartsWidget::updateState() { double max_sec = std::min(display_range.first + max_chart_range, can->totalSeconds()); display_range.first = std::max(0.0, max_sec - max_chart_range); display_range.second = display_range.first + max_chart_range; - } else if (cur_sec < (zoomed_range.first - 0.1) || cur_sec >= zoomed_range.second) { - // loop in zoomed range - QTimer::singleShot(0, [ts = zoomed_range.first]() { can->seekTo(ts);}); - return; } - const auto &range = is_zoomed ? zoomed_range : display_range; + const auto &range = time_range ? *time_range : display_range; for (auto c : charts) { c->updatePlot(cur_sec, range.first, range.second); } @@ -217,12 +213,14 @@ void ChartsWidget::updateToolBar() { title_label->setText(tr("Charts: %1").arg(charts.size())); columns_action->setText(tr("Column: %1").arg(column_count)); range_lb->setText(utils::formatSeconds(max_chart_range)); + + bool is_zoomed = can->timeRange().has_value(); range_lb_action->setVisible(!is_zoomed); range_slider_action->setVisible(!is_zoomed); undo_zoom_action->setVisible(is_zoomed); redo_zoom_action->setVisible(is_zoomed); reset_zoom_action->setVisible(is_zoomed); - reset_zoom_btn->setText(is_zoomed ? tr("%1-%2").arg(zoomed_range.first, 0, 'f', 2).arg(zoomed_range.second, 0, 'f', 2) : ""); + reset_zoom_btn->setText(is_zoomed ? tr("%1-%2").arg(can->timeRange()->first, 0, 'f', 2).arg(can->timeRange()->second, 0, 'f', 2) : ""); remove_all_btn->setEnabled(!charts.isEmpty()); dock_btn->setIcon(docking ? "arrow-up-right-square" : "arrow-down-left-square"); dock_btn->setToolTip(docking ? tr("Undock charts") : tr("Dock charts")); @@ -252,7 +250,7 @@ ChartView *ChartsWidget::findChart(const MessageId &id, const cabana::Signal *si } ChartView *ChartsWidget::createChart() { - auto chart = new ChartView(is_zoomed ? zoomed_range : display_range, this); + auto chart = new ChartView(can->timeRange().value_or(display_range), this); chart->setFixedHeight(settings.chart_height); chart->setMinimumWidth(CHART_MIN_WIDTH); chart->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); diff --git a/tools/cabana/chart/chartswidget.h b/tools/cabana/chart/chartswidget.h index a39b4d73a..a9ac05db2 100644 --- a/tools/cabana/chart/chartswidget.h +++ b/tools/cabana/chart/chartswidget.h @@ -46,11 +46,10 @@ public: public slots: void setColumnCount(int n); void removeAll(); - void setZoom(double min, double max); + void timeRangeChanged(const std::optional> &time_range); signals: void dock(bool floating); - void rangeChanged(double min, double max, bool is_zommed); void seriesChanged(); private: @@ -102,9 +101,7 @@ private: ChartsContainer *charts_container; QScrollArea *charts_scroll; uint32_t max_chart_range = 0; - bool is_zoomed = false; std::pair display_range; - std::pair zoomed_range; QAction *columns_action; int column_count = 1; int current_column_count = 0; @@ -119,12 +116,11 @@ private: class ZoomCommand : public QUndoCommand { public: - ZoomCommand(ChartsWidget *charts, std::pair range) : charts(charts), range(range), QUndoCommand() { - prev_range = charts->is_zoomed ? charts->zoomed_range : charts->display_range; + ZoomCommand(std::pair range) : range(range), QUndoCommand() { + prev_range = can->timeRange(); setText(QObject::tr("Zoom to %1-%2").arg(range.first, 0, 'f', 2).arg(range.second, 0, 'f', 2)); } - void undo() override { charts->setZoom(prev_range.first, prev_range.second); } - void redo() override { charts->setZoom(range.first, range.second); } - ChartsWidget *charts; - std::pair prev_range, range; + void undo() override { can->setTimeRange(prev_range); } + void redo() override { can->setTimeRange(range); } + std::optional> prev_range, range; }; diff --git a/tools/cabana/mainwin.cc b/tools/cabana/mainwin.cc index e6c9b49ca..d099fcec9 100644 --- a/tools/cabana/mainwin.cc +++ b/tools/cabana/mainwin.cc @@ -192,7 +192,6 @@ void MainWindow::createDockWidgets() { video_splitter = new QSplitter(Qt::Vertical, this); video_widget = new VideoWidget(this); video_splitter->addWidget(video_widget); - QObject::connect(charts_widget, &ChartsWidget::rangeChanged, video_widget, &VideoWidget::updateTimeRange); video_splitter->addWidget(charts_container); video_splitter->setStretchFactor(1, 1); diff --git a/tools/cabana/streams/abstractstream.cc b/tools/cabana/streams/abstractstream.cc index 2e6ca9662..2584106ce 100644 --- a/tools/cabana/streams/abstractstream.cc +++ b/tools/cabana/streams/abstractstream.cc @@ -92,13 +92,23 @@ void AbstractStream::updateLastMessages() { std::set msgs; { std::lock_guard lk(mutex_); + double max_sec = 0; for (const auto &id : new_msgs_) { const auto &can_data = messages_[id]; - current_sec_ = std::max(current_sec_, can_data.ts); + max_sec = std::max(max_sec, can_data.ts); last_msgs[id] = can_data; sources.insert(id.source); } - msgs = std::move(new_msgs_); + + if (!new_msgs_.empty()) { + msgs = std::move(new_msgs_); + current_sec_ = max_sec; + } + } + + if (time_range_ && (current_sec_ < time_range_->first || current_sec_ >= time_range_->second)) { + seekTo(time_range_->first); + return; } if (sources.size() != prev_src_size) { @@ -108,6 +118,14 @@ void AbstractStream::updateLastMessages() { emit msgsReceived(&msgs, prev_msg_size != last_msgs.size()); } +void AbstractStream::setTimeRange(const std::optional> &range) { + time_range_ = range; + if (time_range_ && (current_sec_ < time_range_->first || current_sec_ >= time_range_->second)) { + seekTo(time_range_->first); + } + emit timeRangeChanged(time_range_); +} + void AbstractStream::updateEvent(const MessageId &id, double sec, const uint8_t *data, uint8_t size) { std::lock_guard lk(mutex_); messages_[id].compute(id, data, size, sec, getSpeed(), masks_[id]); diff --git a/tools/cabana/streams/abstractstream.h b/tools/cabana/streams/abstractstream.h index cfd423b36..822dd03d8 100644 --- a/tools/cabana/streams/abstractstream.h +++ b/tools/cabana/streams/abstractstream.h @@ -3,8 +3,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -77,6 +79,8 @@ public: virtual double getSpeed() { return 1; } virtual bool isPaused() const { return false; } virtual void pause(bool pause) {} + void setTimeRange(const std::optional> &range); + const std::optional> &timeRange() const { return time_range_; } inline const std::unordered_map &lastMessages() const { return last_msgs; } inline const MessageEventsMap &eventsMap() const { return events_; } @@ -91,8 +95,9 @@ public: signals: void paused(); void resume(); - void seekingTo(double sec); + void seeking(double sec); void seekedTo(double sec); + void timeRangeChanged(const std::optional> &range); void streamStarted(); void eventsMerged(const MessageEventsMap &events_map); void msgsReceived(const std::set *new_msgs, bool has_new_ids); @@ -110,6 +115,7 @@ protected: std::vector all_events_; double current_sec_ = 0; + std::optional> time_range_; uint64_t lastest_event_ts = 0; private: diff --git a/tools/cabana/streams/replaystream.cc b/tools/cabana/streams/replaystream.cc index 5fda6b048..5d4925a67 100644 --- a/tools/cabana/streams/replaystream.cc +++ b/tools/cabana/streams/replaystream.cc @@ -53,9 +53,9 @@ bool ReplayStream::loadRoute(const QString &route, const QString &data_dir, uint {}, nullptr, replay_flags, data_dir, this)); replay->setSegmentCacheLimit(settings.max_cached_minutes); replay->installEventFilter(event_filter, this); + QObject::connect(replay.get(), &Replay::seeking, this, &AbstractStream::seeking); QObject::connect(replay.get(), &Replay::seekedTo, this, &AbstractStream::seekedTo); QObject::connect(replay.get(), &Replay::segmentsMerged, this, &ReplayStream::mergeSegments); - QObject::connect(replay.get(), &Replay::qLogLoaded, this, &ReplayStream::qLogLoaded, Qt::QueuedConnection); return replay->load(); } @@ -92,12 +92,7 @@ bool ReplayStream::eventFilter(const Event *event) { } void ReplayStream::seekTo(double ts) { - // Update timestamp and notify receivers of the time change. current_sec_ = ts; - std::set new_msgs; - msgsReceived(&new_msgs, false); - - // Seek to the specified timestamp replay->seekTo(std::max(double(0), ts), false); } diff --git a/tools/cabana/streams/replaystream.h b/tools/cabana/streams/replaystream.h index 049ccddaf..ced78680d 100644 --- a/tools/cabana/streams/replaystream.h +++ b/tools/cabana/streams/replaystream.h @@ -34,9 +34,6 @@ public: void pause(bool pause) override; static AbstractOpenStreamWidget *widget(AbstractStream **stream); -signals: - void qLogLoaded(int segnum, std::shared_ptr qlog); - private: void mergeSegments(); std::unique_ptr replay = nullptr; diff --git a/tools/cabana/videowidget.cc b/tools/cabana/videowidget.cc index 7fca45c39..d2f78babc 100644 --- a/tools/cabana/videowidget.cc +++ b/tools/cabana/videowidget.cc @@ -38,6 +38,8 @@ VideoWidget::VideoWidget(QWidget *parent) : QFrame(parent) { QObject::connect(can, &AbstractStream::paused, this, &VideoWidget::updatePlayBtnState); QObject::connect(can, &AbstractStream::resume, this, &VideoWidget::updatePlayBtnState); QObject::connect(can, &AbstractStream::msgsReceived, this, &VideoWidget::updateState); + QObject::connect(can, &AbstractStream::seeking, this, &VideoWidget::updateState); + QObject::connect(can, &AbstractStream::timeRangeChanged, this, &VideoWidget::timeRangeChanged); updatePlayBtnState(); setWhatsThis(tr(R"( @@ -150,14 +152,16 @@ QWidget *VideoWidget::createCameraWidget() { setMaximumTime(can->totalSeconds()); QObject::connect(slider, &QSlider::sliderReleased, [this]() { can->seekTo(slider->currentSecond()); }); - QObject::connect(slider, &Slider::updateMaximumTime, this, &VideoWidget::setMaximumTime, Qt::QueuedConnection); QObject::connect(can, &AbstractStream::eventsMerged, this, [this]() { slider->update(); }); - QObject::connect(static_cast(can), &ReplayStream::qLogLoaded, slider, &Slider::parseQLog); QObject::connect(cam_widget, &CameraWidget::clicked, []() { can->pause(!can->isPaused()); }); QObject::connect(cam_widget, &CameraWidget::vipcAvailableStreamsUpdated, this, &VideoWidget::vipcAvailableStreamsUpdated); QObject::connect(camera_tab, &QTabBar::currentChanged, [this](int index) { if (index != -1) cam_widget->setStreamType((VisionStreamType)camera_tab->tabData(index).toInt()); }); + + auto replay = static_cast(can)->getReplay(); + QObject::connect(replay, &Replay::qLogLoaded, slider, &Slider::parseQLog, Qt::QueuedConnection); + QObject::connect(replay, &Replay::totalSecondsUpdated, this, &VideoWidget::setMaximumTime, Qt::QueuedConnection); return w; } @@ -198,13 +202,13 @@ void VideoWidget::setMaximumTime(double sec) { slider->setTimeRange(0, sec); } -void VideoWidget::updateTimeRange(double min, double max, bool is_zoomed) { +void VideoWidget::timeRangeChanged(const std::optional> &time_range) { if (can->liveStreaming()) { - skip_to_end_btn->setEnabled(!is_zoomed); + skip_to_end_btn->setEnabled(!time_range.has_value()); return; } - is_zoomed ? slider->setTimeRange(min, max) - : slider->setTimeRange(0, maximum_time); + time_range ? slider->setTimeRange(time_range->first, time_range->second) + : slider->setTimeRange(0, maximum_time); } QString VideoWidget::formatTime(double sec, bool include_milliseconds) { @@ -255,12 +259,7 @@ void Slider::setTimeRange(double min, double max) { setRange(min * factor, max * factor); } -void Slider::parseQLog(int segnum, std::shared_ptr qlog) { - const auto &segments = qobject_cast(can)->route()->segments(); - if (segments.size() > 0 && segnum == segments.rbegin()->first && !qlog->events.empty()) { - emit updateMaximumTime(qlog->events.back().mono_time / 1e9 - can->routeStartTime()); - } - +void Slider::parseQLog(std::shared_ptr qlog) { std::mutex mutex; QtConcurrent::blockingMap(qlog->events.cbegin(), qlog->events.cend(), [&mutex, this](const Event &e) { if (e.which == cereal::Event::Which::THUMBNAIL) { diff --git a/tools/cabana/videowidget.h b/tools/cabana/videowidget.h index b2039e09a..7bd55cbce 100644 --- a/tools/cabana/videowidget.h +++ b/tools/cabana/videowidget.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -40,13 +41,10 @@ public: void setTimeRange(double min, double max); AlertInfo alertInfo(double sec); QPixmap thumbnail(double sec); - void parseQLog(int segnum, std::shared_ptr qlog); + void parseQLog(std::shared_ptr qlog); const double factor = 1000.0; -signals: - void updateMaximumTime(double); - private: void mousePressEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override; @@ -63,11 +61,11 @@ class VideoWidget : public QFrame { public: VideoWidget(QWidget *parnet = nullptr); - void updateTimeRange(double min, double max, bool is_zommed); void setMaximumTime(double sec); protected: QString formatTime(double sec, bool include_milliseconds = false); + void timeRangeChanged(const std::optional> &time_range); void updateState(); void updatePlayBtnState(); QWidget *createCameraWidget(); diff --git a/tools/replay/camera.cc b/tools/replay/camera.cc index 9e711149c..b6d4ddc3a 100644 --- a/tools/replay/camera.cc +++ b/tools/replay/camera.cc @@ -60,7 +60,6 @@ void CameraServer::cameraThread(Camera &cam) { capnp::FlatArrayMessageReader reader(event->data); auto evt = reader.getRoot(); auto eidx = capnp::AnyStruct::Reader(evt).getPointerSection()[0].getAs(); - if (eidx.getType() != cereal::EncodeIndex::Type::FULL_H_E_V_C) continue; int segment_id = eidx.getSegmentId(); uint32_t frame_id = eidx.getFrameId(); diff --git a/tools/replay/logreader.cc b/tools/replay/logreader.cc index 0f1638145..9b726e067 100644 --- a/tools/replay/logreader.cc +++ b/tools/replay/logreader.cc @@ -42,10 +42,10 @@ bool LogReader::load(const char *data, size_t size, std::atomic *abort) { evt.which == cereal::Event::DRIVER_ENCODE_IDX || evt.which == cereal::Event::WIDE_ROAD_ENCODE_IDX) { auto idx = capnp::AnyStruct::Reader(event).getPointerSection()[0].getAs(); - if (uint64_t sof = idx.getTimestampSof()) { - mono_time = sof; + if (idx.getType() == cereal::EncodeIndex::Type::FULL_H_E_V_C) { + uint64_t sof = idx.getTimestampSof(); + events.emplace_back(which, sof ? sof : mono_time, event_data, idx.getSegmentNum()); } - events.emplace_back(which, mono_time, event_data, idx.getSegmentNum()); } } } catch (const kj::Exception &e) { diff --git a/tools/replay/replay.cc b/tools/replay/replay.cc index 861643718..c5ad2aa54 100644 --- a/tools/replay/replay.cc +++ b/tools/replay/replay.cc @@ -55,11 +55,11 @@ void Replay::stop() { rInfo("shutdown: in progress..."); if (stream_thread_ != nullptr) { exit_ = true; - paused_ = true; + pauseStreamThread(); stream_cv_.notify_one(); stream_thread_->quit(); stream_thread_->wait(); - delete stream_thread_; + stream_thread_->deleteLater(); stream_thread_ = nullptr; } timeline_future.waitForFinished(); @@ -104,28 +104,40 @@ void Replay::updateEvents(const std::function &update_events_function) { void Replay::seekTo(double seconds, bool relative) { updateEvents([&]() { - seeking_to_seconds_ = relative ? seconds + currentSeconds() : seconds; - seeking_to_seconds_ = std::max(double(0.0), seeking_to_seconds_); - int target_segment = (int)seeking_to_seconds_ / 60; + double target_time = relative ? seconds + currentSeconds() : seconds; + target_time = std::max(double(0.0), target_time); + int target_segment = (int)target_time / 60; if (segments_.count(target_segment) == 0) { - rWarning("can't seek to %d s segment %d is invalid", (int)seeking_to_seconds_, target_segment); + rWarning("Can't seek to %d s segment %d is invalid", (int)target_time, target_segment); return true; } - rInfo("seeking to %d s, segment %d", (int)seeking_to_seconds_, target_segment); + rInfo("Seeking to %d s, segment %d", (int)target_time, target_segment); current_segment_ = target_segment; - cur_mono_time_ = route_start_ts_ + seeking_to_seconds_ * 1e9; - bool segment_merged = isSegmentMerged(target_segment); - if (segment_merged) { - emit seekedTo(seeking_to_seconds_); - // Reset seeking_to_seconds_ to indicate completion of seek - seeking_to_seconds_ = -1; - } - return segment_merged; + cur_mono_time_ = route_start_ts_ + target_time * 1e9; + seeking_to_ = target_time; + return false; }); + + checkSeekProgress(); updateSegmentsCache(); } +void Replay::checkSeekProgress() { + if (seeking_to_) { + auto it = segments_.find(int(*seeking_to_ / 60)); + if (it != segments_.end() && it->second && it->second->isLoaded()) { + emit seekedTo(*seeking_to_); + seeking_to_ = std::nullopt; + // wake up stream thread + updateEvents([]() { return true; }); + } else { + // Emit signal indicating the ongoing seek operation + emit seeking(*seeking_to_); + } + } +} + void Replay::seekToFlag(FindFlag flag) { if (auto next = find(flag)) { seekTo(*next - 2, false); // seek to 2 seconds before next @@ -150,8 +162,9 @@ void Replay::buildTimeline() { const auto &route_segments = route_->segments(); for (auto it = route_segments.cbegin(); it != route_segments.cend() && !exit_; ++it) { std::shared_ptr log(new LogReader()); - if (!log->load(it->second.qlog.toStdString(), &exit_, !hasFlag(REPLAY_FLAG_NO_FILE_CACHE), 0, 3)) continue; + if (!log->load(it->second.qlog.toStdString(), &exit_, !hasFlag(REPLAY_FLAG_NO_FILE_CACHE), 0, 3) || log->events.empty()) continue; + std::vector> timeline; for (const Event &e : log->events) { if (e.which == cereal::Event::Which::CONTROLS_STATE) { capnp::FlatArrayMessageReader reader(e.data); @@ -160,7 +173,6 @@ void Replay::buildTimeline() { if (engaged != cs.getEnabled()) { if (engaged) { - std::lock_guard lk(timeline_lock); timeline.push_back({toSeconds(engaged_begin), toSeconds(e.mono_time), TimelineType::Engaged}); } engaged_begin = e.mono_time; @@ -169,7 +181,6 @@ void Replay::buildTimeline() { if (alert_type != cs.getAlertType().cStr() || alert_status != cs.getAlertStatus()) { if (!alert_type.empty() && alert_size != cereal::ControlsState::AlertSize::NONE) { - std::lock_guard lk(timeline_lock); timeline.push_back({toSeconds(alert_begin), toSeconds(e.mono_time), timeline_types[(int)alert_status]}); } alert_begin = e.mono_time; @@ -178,12 +189,20 @@ void Replay::buildTimeline() { alert_status = cs.getAlertStatus(); } } else if (e.which == cereal::Event::Which::USER_FLAG) { - std::lock_guard lk(timeline_lock); timeline.push_back({toSeconds(e.mono_time), toSeconds(e.mono_time), TimelineType::UserFlag}); } } - std::sort(timeline.begin(), timeline.end(), [](auto &l, auto &r) { return std::get<2>(l) < std::get<2>(r); }); - emit qLogLoaded(it->first, log); + + { + std::lock_guard lk(timeline_lock); + timeline_.insert(timeline_.end(), timeline.begin(), timeline.end()); + std::sort(timeline_.begin(), timeline_.end(), [](auto &l, auto &r) { return std::get<2>(l) < std::get<2>(r); }); + } + + if (it->first == route_segments.rbegin()->first) { + emit totalSecondsUpdated(toSeconds(log->events.back().mono_time)); + } + emit qLogLoaded(log); } } @@ -260,14 +279,13 @@ void Replay::updateSegmentsCache() { const auto &cur_segment = cur->second; if (stream_thread_ == nullptr && cur_segment->isLoaded()) { startStream(cur_segment.get()); - emit streamStarted(); } } void Replay::loadSegmentInRange(SegmentMap::iterator begin, SegmentMap::iterator cur, SegmentMap::iterator end) { - auto loadNext = [this](auto begin, auto end) { - auto it = std::find_if(begin, end, [](const auto &seg_it) { return !seg_it.second || !seg_it.second->isLoaded(); }); - if (it != end && !it->second) { + auto loadNextSegment = [this](auto first, auto last) { + auto it = std::find_if(first, last, [](const auto &seg_it) { return !seg_it.second || !seg_it.second->isLoaded(); }); + if (it != last && !it->second) { rDebug("loading segment %d...", it->first); it->second = std::make_unique(it->first, route_->at(it->first), flags_, filters_); QObject::connect(it->second.get(), &Segment::loadFinished, this, &Replay::segmentLoadFinished); @@ -276,9 +294,9 @@ void Replay::loadSegmentInRange(SegmentMap::iterator begin, SegmentMap::iterator return false; }; - // Load forward segments, then try reverse - if (!loadNext(cur, end)) { - loadNext(std::make_reverse_iterator(cur), segments_.rend()); + // Try loading forward segments, then reverse segments + if (!loadNextSegment(cur, end)) { + loadNextSegment(std::make_reverse_iterator(cur), std::make_reverse_iterator(begin)); } } @@ -316,15 +334,10 @@ void Replay::mergeSegments(const SegmentMap::iterator &begin, const SegmentMap:: updateEvents([&]() { events_.swap(new_events); merged_segments_ = segments_to_merge; - // Check if seeking is in progress - int target_segment = int(seeking_to_seconds_ / 60); - if (seeking_to_seconds_ >= 0 && segments_to_merge.count(target_segment) > 0) { - emit seekedTo(seeking_to_seconds_); - seeking_to_seconds_ = -1; // Reset seeking_to_seconds_ to indicate completion of seek - } // Wake up the stream thread if the current segment is loaded or invalid. - return isSegmentMerged(current_segment_) || (segments_.count(current_segment_) == 0); + return !seeking_to_ && (isSegmentMerged(current_segment_) || (segments_.count(current_segment_) == 0)); }); + checkSeekProgress(); } void Replay::startStream(const Segment *cur_segment) { @@ -379,6 +392,7 @@ void Replay::startStream(const Segment *cur_segment) { stream_thread_->start(); timeline_future = QtConcurrent::run(this, &Replay::buildTimeline); + emit streamStarted(); } void Replay::publishMessage(const Event *e) { @@ -473,6 +487,7 @@ std::vector::const_iterator Replay::publishEvents(std::vector::con // Skip events if socket is not present if (!sockets_[evt.which]) continue; + cur_mono_time_ = evt.mono_time; const uint64_t current_nanos = nanos_since_boot(); const int64_t time_diff = (evt.mono_time - evt_start_ts) / speed_ - (current_nanos - loop_start_ts); @@ -484,12 +499,11 @@ std::vector::const_iterator Replay::publishEvents(std::vector::con loop_start_ts = current_nanos; prev_replay_speed = speed_; } else if (time_diff > 0) { - precise_nano_sleep(time_diff); + precise_nano_sleep(time_diff, paused_); } if (paused_) break; - cur_mono_time_ = evt.mono_time; if (evt.eidx_segnum == -1) { publishMessage(&evt); } else if (camera_server_) { diff --git a/tools/replay/replay.h b/tools/replay/replay.h index 4adbc14df..8b51ab054 100644 --- a/tools/replay/replay.h +++ b/tools/replay/replay.h @@ -85,14 +85,16 @@ public: inline const std::string &carFingerprint() const { return car_fingerprint_; } inline const std::vector> getTimeline() { std::lock_guard lk(timeline_lock); - return timeline; + return timeline_; } signals: void streamStarted(); void segmentsMerged(); + void seeking(double sec); void seekedTo(double sec); - void qLogLoaded(int segnum, std::shared_ptr qlog); + void qLogLoaded(std::shared_ptr qlog); + void totalSecondsUpdated(double sec); protected slots: void segmentLoadFinished(bool success); @@ -112,6 +114,7 @@ protected: void publishMessage(const Event *e); void publishFrame(const Event *e); void buildTimeline(); + void checkSeekProgress(); inline bool isSegmentMerged(int n) const { return merged_segments_.count(n) > 0; } pthread_t stream_thread_id = 0; @@ -120,7 +123,7 @@ protected: bool user_paused_ = false; std::condition_variable stream_cv_; std::atomic current_segment_ = 0; - double seeking_to_seconds_ = -1; + std::optional seeking_to_; SegmentMap segments_; // the following variables must be protected with stream_lock_ std::atomic exit_ = false; @@ -143,7 +146,7 @@ protected: std::mutex timeline_lock; QFuture timeline_future; - std::vector> timeline; + std::vector> timeline_; std::string car_fingerprint_; std::atomic speed_ = 1.0; replayEventFilter event_filter = nullptr; diff --git a/tools/replay/util.cc b/tools/replay/util.cc index c8203fd79..a08b3b3d5 100644 --- a/tools/replay/util.cc +++ b/tools/replay/util.cc @@ -318,33 +318,23 @@ std::string decompressBZ2(const std::byte *in, size_t in_size, std::atomic return {}; } -void precise_nano_sleep(int64_t nanoseconds) { -#ifdef __APPLE__ - const long estimate_ns = 1 * 1e6; // 1ms - struct timespec req = {.tv_nsec = estimate_ns}; - uint64_t start_sleep = nanos_since_boot(); - while (nanoseconds > estimate_ns) { - nanosleep(&req, nullptr); - uint64_t end_sleep = nanos_since_boot(); - nanoseconds -= (end_sleep - start_sleep); - start_sleep = end_sleep; - } - // spin wait - if (nanoseconds > 0) { - while ((nanos_since_boot() - start_sleep) <= nanoseconds) { - std::this_thread::yield(); - } - } -#else +void precise_nano_sleep(int64_t nanoseconds, std::atomic &should_exit) { struct timespec req, rem; - - req.tv_sec = nanoseconds / 1e9; - req.tv_nsec = nanoseconds % (int64_t)1e9; - while (clock_nanosleep(CLOCK_MONOTONIC, 0, &req, &rem) && errno == EINTR) { + req.tv_sec = nanoseconds / 1000000000; + req.tv_nsec = nanoseconds % 1000000000; + while (!should_exit) { +#ifdef __APPLE_ + int ret = nanosleep(&req, &rem); + if (ret == 0 || errno != EINTR) + break; +#else + int ret = clock_nanosleep(CLOCK_MONOTONIC, 0, &req, &rem); + if (ret == 0 || ret != EINTR) + break; +#endif // Retry sleep if interrupted by a signal req = rem; } -#endif } std::string sha256(const std::string &str) { diff --git a/tools/replay/util.h b/tools/replay/util.h index 750c13355..97516e181 100644 --- a/tools/replay/util.h +++ b/tools/replay/util.h @@ -37,7 +37,7 @@ private: }; std::string sha256(const std::string &str); -void precise_nano_sleep(int64_t nanoseconds); +void precise_nano_sleep(int64_t nanoseconds, std::atomic &should_exit); std::string decompressBZ2(const std::string &in, std::atomic *abort = nullptr); std::string decompressBZ2(const std::byte *in, size_t in_size, std::atomic *abort = nullptr); std::string getUrlWithoutQuery(const std::string &url); From b99fe718ecfbc6044cb5fa53f34e077b9d9a2a4f Mon Sep 17 00:00:00 2001 From: commaci-public <60409688+commaci-public@users.noreply.github.com> Date: Mon, 17 Jun 2024 09:26:22 -0700 Subject: [PATCH 24/30] [bot] Update Python packages and pre-commit hooks (#32770) Update Python packages and pre-commit hooks Co-authored-by: Vehicle Researcher --- .pre-commit-config.yaml | 4 +-- poetry.lock | 56 ++++++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 61b782364..d47630cda 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -33,7 +33,7 @@ repos: - -L bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie,preints,whit,indexIn - --builtins clear,rare,informal,usage,code,names,en-GB_to_en-US - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.4.8 + rev: v0.4.9 hooks: - id: ruff exclude: '^(third_party/)|(msgq/)|(panda/)|(rednose/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)|(teleoprtc/)|(teleoprtc_repo/)' @@ -98,6 +98,6 @@ repos: args: - --lock - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.28.4 + rev: 0.28.5 hooks: - id: check-github-workflows diff --git a/poetry.lock b/poetry.lock index 2467d6be2..13d082763 100644 --- a/poetry.lock +++ b/poetry.lock @@ -7219,28 +7219,28 @@ docs = ["furo (==2024.4.27)", "pyenchant (==3.2.2)", "sphinx (==7.1.2)", "sphinx [[package]] name = "ruff" -version = "0.4.8" +version = "0.4.9" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.4.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7663a6d78f6adb0eab270fa9cf1ff2d28618ca3a652b60f2a234d92b9ec89066"}, - {file = "ruff-0.4.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:eeceb78da8afb6de0ddada93112869852d04f1cd0f6b80fe464fd4e35c330913"}, - {file = "ruff-0.4.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aad360893e92486662ef3be0a339c5ca3c1b109e0134fcd37d534d4be9fb8de3"}, - {file = "ruff-0.4.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:284c2e3f3396fb05f5f803c9fffb53ebbe09a3ebe7dda2929ed8d73ded736deb"}, - {file = "ruff-0.4.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7354f921e3fbe04d2a62d46707e569f9315e1a613307f7311a935743c51a764"}, - {file = "ruff-0.4.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:72584676164e15a68a15778fd1b17c28a519e7a0622161eb2debdcdabdc71883"}, - {file = "ruff-0.4.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9678d5c9b43315f323af2233a04d747409d1e3aa6789620083a82d1066a35199"}, - {file = "ruff-0.4.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704977a658131651a22b5ebeb28b717ef42ac6ee3b11e91dc87b633b5d83142b"}, - {file = "ruff-0.4.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d05f8d6f0c3cce5026cecd83b7a143dcad503045857bc49662f736437380ad45"}, - {file = "ruff-0.4.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6ea874950daca5697309d976c9afba830d3bf0ed66887481d6bca1673fc5b66a"}, - {file = "ruff-0.4.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fc95aac2943ddf360376be9aa3107c8cf9640083940a8c5bd824be692d2216dc"}, - {file = "ruff-0.4.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:384154a1c3f4bf537bac69f33720957ee49ac8d484bfc91720cc94172026ceed"}, - {file = "ruff-0.4.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e9d5ce97cacc99878aa0d084c626a15cd21e6b3d53fd6f9112b7fc485918e1fa"}, - {file = "ruff-0.4.8-py3-none-win32.whl", hash = "sha256:6d795d7639212c2dfd01991259460101c22aabf420d9b943f153ab9d9706e6a9"}, - {file = "ruff-0.4.8-py3-none-win_amd64.whl", hash = "sha256:e14a3a095d07560a9d6769a72f781d73259655919d9b396c650fc98a8157555d"}, - {file = "ruff-0.4.8-py3-none-win_arm64.whl", hash = "sha256:14019a06dbe29b608f6b7cbcec300e3170a8d86efaddb7b23405cb7f7dcaf780"}, - {file = "ruff-0.4.8.tar.gz", hash = "sha256:16d717b1d57b2e2fd68bd0bf80fb43931b79d05a7131aa477d66fc40fbd86268"}, + {file = "ruff-0.4.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b262ed08d036ebe162123170b35703aaf9daffecb698cd367a8d585157732991"}, + {file = "ruff-0.4.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:98ec2775fd2d856dc405635e5ee4ff177920f2141b8e2d9eb5bd6efd50e80317"}, + {file = "ruff-0.4.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4555056049d46d8a381f746680db1c46e67ac3b00d714606304077682832998e"}, + {file = "ruff-0.4.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e91175fbe48f8a2174c9aad70438fe9cb0a5732c4159b2a10a3565fea2d94cde"}, + {file = "ruff-0.4.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e8e7b95673f22e0efd3571fb5b0cf71a5eaaa3cc8a776584f3b2cc878e46bff"}, + {file = "ruff-0.4.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2d45ddc6d82e1190ea737341326ecbc9a61447ba331b0a8962869fcada758505"}, + {file = "ruff-0.4.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:78de3fdb95c4af084087628132336772b1c5044f6e710739d440fc0bccf4d321"}, + {file = "ruff-0.4.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:06b60f91bfa5514bb689b500a25ba48e897d18fea14dce14b48a0c40d1635893"}, + {file = "ruff-0.4.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88bffe9c6a454bf8529f9ab9091c99490578a593cc9f9822b7fc065ee0712a06"}, + {file = "ruff-0.4.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:673bddb893f21ab47a8334c8e0ea7fd6598ecc8e698da75bcd12a7b9d0a3206e"}, + {file = "ruff-0.4.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8c1aff58c31948cc66d0b22951aa19edb5af0a3af40c936340cd32a8b1ab7438"}, + {file = "ruff-0.4.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:784d3ec9bd6493c3b720a0b76f741e6c2d7d44f6b2be87f5eef1ae8cc1d54c84"}, + {file = "ruff-0.4.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:732dd550bfa5d85af8c3c6cbc47ba5b67c6aed8a89e2f011b908fc88f87649db"}, + {file = "ruff-0.4.9-py3-none-win32.whl", hash = "sha256:8064590fd1a50dcf4909c268b0e7c2498253273309ad3d97e4a752bb9df4f521"}, + {file = "ruff-0.4.9-py3-none-win_amd64.whl", hash = "sha256:e0a22c4157e53d006530c902107c7f550b9233e9706313ab57b892d7197d8e52"}, + {file = "ruff-0.4.9-py3-none-win_arm64.whl", hash = "sha256:5d5460f789ccf4efd43f265a58538a2c24dbce15dbf560676e430375f20a8198"}, + {file = "ruff-0.4.9.tar.gz", hash = "sha256:f1cb0828ac9533ba0135d148d214e284711ede33640465e706772645483427e3"}, ] [[package]] @@ -7727,19 +7727,23 @@ widechars = ["wcwidth"] [[package]] name = "timezonefinder" -version = "6.5.0" +version = "6.5.2" description = "python package for finding the timezone of any point on earth (coordinates) offline" optional = false -python-versions = ">=3.8,<4" +python-versions = "<4,>=3.8" files = [ - {file = "timezonefinder-6.5.0-cp38-cp38-manylinux_2_35_x86_64.whl", hash = "sha256:3c70e1ea468ecac11272aa0a727450fd7cf43039ae2a2c62f7900a0a42efb6d6"}, - {file = "timezonefinder-6.5.0.tar.gz", hash = "sha256:7afdb1516927e7766deb6da80c8bd66734a44ba3d898038fe73aef1e9cd39bb0"}, + {file = "timezonefinder-6.5.2-cp310-cp310-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea7ca91f25d988d69efeae020ed828534ed01f6687646a50e464d82da4704b30"}, + {file = "timezonefinder-6.5.2-cp311-cp311-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4a3bca9933ea165380d54b336227def58e62682968437cd44223a065ecff7e9"}, + {file = "timezonefinder-6.5.2-cp312-cp312-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ac4ef31d379c7ba54710462857bea36a9630ea23550ffb15550322e6988efbd"}, + {file = "timezonefinder-6.5.2-cp38-cp38-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:524ab145a2f4ce5101e52308868ecd9da0cdcc2cb3024c13356616b41a685fd6"}, + {file = "timezonefinder-6.5.2-cp39-cp39-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b93927a4996a5c01f0628eb6858c61b2a7f9f49e02c07bed2a95e96a8dc1b65e"}, + {file = "timezonefinder-6.5.2.tar.gz", hash = "sha256:3279e67d5b1b9a54d1a16f3bd4234169f14e2b90c0f58ed37bcfa7303645d610"}, ] [package.dependencies] cffi = ">=1.15.1,<2" h3 = ">=3.7.6,<4" -numpy = {version = ">=1.23,<2", markers = "python_version >= \"3.9\""} +numpy = {version = ">=1.23,<3", markers = "python_version >= \"3.9\""} setuptools = ">=65.5" [package.extras] @@ -7826,13 +7830,13 @@ files = [ [[package]] name = "urllib3" -version = "2.2.1" +version = "2.2.2" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, - {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, + {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, + {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, ] [package.extras] From a99816a08b3c30b72283a4a7b77415349a539c33 Mon Sep 17 00:00:00 2001 From: commaci-public <60409688+commaci-public@users.noreply.github.com> Date: Mon, 17 Jun 2024 09:26:34 -0700 Subject: [PATCH 25/30] [bot] Bump submodules (#32769) bump submodules Co-authored-by: Vehicle Researcher --- panda | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda b/panda index faa180266..7287ff0cb 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit faa18026692f7714ee537261fe649dafe4882579 +Subproject commit 7287ff0cbf3ab405a670405f2faca419d524387d From ab96d12f2ee7bc80af3203b732be05a46894a610 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Mon, 17 Jun 2024 09:43:36 -0700 Subject: [PATCH 26/30] more fetch depth --- release/check-submodules.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/check-submodules.sh b/release/check-submodules.sh index bff8d7a28..5305cecd3 100755 --- a/release/check-submodules.sh +++ b/release/check-submodules.sh @@ -1,7 +1,7 @@ #!/bin/bash while read hash submodule ref; do - git -C $submodule fetch --depth 2000 origin master + git -C $submodule fetch --depth 3000 origin master git -C $submodule branch -r --contains $hash | grep "origin/master" if [ "$?" -eq 0 ]; then echo "$submodule ok" From 54da59c1feb917896538ce8aa22bf4f12af20824 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Tue, 18 Jun 2024 03:44:31 +0800 Subject: [PATCH 27/30] cabana: improved error messaging (#32768) * check user authenrication * Update tools/cabana/streams/replaystream.cc --------- Co-authored-by: Adeeb Shihadeh --- tools/cabana/streams/replaystream.cc | 27 +++++++++++++++++++++++---- tools/replay/replay.h | 1 + tools/replay/route.cc | 3 +++ tools/replay/route.h | 10 ++++++++++ 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/tools/cabana/streams/replaystream.cc b/tools/cabana/streams/replaystream.cc index 5d4925a67..bdb9ebb01 100644 --- a/tools/cabana/streams/replaystream.cc +++ b/tools/cabana/streams/replaystream.cc @@ -56,7 +56,28 @@ bool ReplayStream::loadRoute(const QString &route, const QString &data_dir, uint QObject::connect(replay.get(), &Replay::seeking, this, &AbstractStream::seeking); QObject::connect(replay.get(), &Replay::seekedTo, this, &AbstractStream::seekedTo); QObject::connect(replay.get(), &Replay::segmentsMerged, this, &ReplayStream::mergeSegments); - return replay->load(); + bool success = replay->load(); + if (!success) { + if (replay->lastRouteError() == RouteLoadError::AccessDenied) { + auto auth_content = util::read_file(util::getenv("HOME") + "/.comma/auth.json"); + QString message; + if (auth_content.empty()) { + message = "Authentication Required. Please run the following command to authenticate:\n\n" + "python tools/lib/auth.py\n\n" + "This will grant access to routes from your comma account."; + } else { + message = tr("Access Denied. You do not have permission to access route:\n\n%1\n\n" + "This is likely a private route.").arg(route); + } + QMessageBox::warning(nullptr, tr("Access Denied"), message); + } else if (replay->lastRouteError() == RouteLoadError::NetworkError) { + QMessageBox::warning(nullptr, tr("Network Error"), + tr("Unable to load the route:\n\n %1.\n\nPlease check your network connection and try again.").arg(route)); + } else { + QMessageBox::warning(nullptr, tr("Route Load Failed"), tr("Failed to load route: '%1'").arg(route)); + } + } + return success; } void ReplayStream::start() { @@ -144,7 +165,7 @@ OpenReplayWidget::OpenReplayWidget(AbstractStream **stream) : AbstractOpenStream bool OpenReplayWidget::open() { QString route = route_edit->text(); QString data_dir; - if (int idx = route.lastIndexOf('/'); idx != -1) { + if (int idx = route.lastIndexOf('/'); idx != -1 && util::file_exists(route.toStdString())) { data_dir = route.mid(0, idx + 1); route = route.mid(idx + 1); } @@ -161,8 +182,6 @@ bool OpenReplayWidget::open() { if (replay_stream->loadRoute(route, data_dir, flags)) { *stream = replay_stream.release(); - } else { - QMessageBox::warning(nullptr, tr("Warning"), tr("Failed to load route: '%1'").arg(route)); } } return *stream != nullptr; diff --git a/tools/replay/replay.h b/tools/replay/replay.h index 8b51ab054..7e1815ede 100644 --- a/tools/replay/replay.h +++ b/tools/replay/replay.h @@ -53,6 +53,7 @@ public: uint32_t flags = REPLAY_FLAG_NONE, QString data_dir = "", QObject *parent = 0); ~Replay(); bool load(); + RouteLoadError lastRouteError() const { return route_->lastError(); } void start(int seconds = 0); void stop(); void pause(bool pause); diff --git a/tools/replay/route.cc b/tools/replay/route.cc index e8e73459e..18c962abd 100644 --- a/tools/replay/route.cc +++ b/tools/replay/route.cc @@ -74,7 +74,10 @@ bool Route::loadFromServer(int retries) { return loadFromJson(result); } else if (err == QNetworkReply::ContentAccessDenied || err == QNetworkReply::AuthenticationRequiredError) { rWarning(">> Unauthorized. Authenticate with tools/lib/auth.py <<"); + err_ = RouteLoadError::AccessDenied; return false; + } else { + err_ = RouteLoadError::NetworkError; } rWarning("Retrying %d/%d", i, retries); util::sleep_for(3000); diff --git a/tools/replay/route.h b/tools/replay/route.h index f95649780..acc73d509 100644 --- a/tools/replay/route.h +++ b/tools/replay/route.h @@ -12,6 +12,14 @@ #include "tools/replay/logreader.h" #include "tools/replay/util.h" +enum class RouteLoadError { + None, + AccessDenied, + NetworkError, + FileNotFound, + UnknownError +}; + struct RouteIdentifier { QString dongle_id; QString timestamp; @@ -33,6 +41,7 @@ class Route { public: Route(const QString &route, const QString &data_dir = {}); bool load(); + RouteLoadError lastError() const { return err_; } inline const QString &name() const { return route_.str; } inline const QDateTime datetime() const { return date_time_; } inline const QString &dir() const { return data_dir_; } @@ -50,6 +59,7 @@ protected: QString data_dir_; std::map segments_; QDateTime date_time_; + RouteLoadError err_ = RouteLoadError::None; }; class Segment : public QObject { From 3de6ee5ee316980f2dfea5e59c7369ac1f0a83df Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Mon, 17 Jun 2024 13:24:04 -0700 Subject: [PATCH 28/30] cabana: include optional (#32772) optional --- tools/cabana/videowidget.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/cabana/videowidget.h b/tools/cabana/videowidget.h index 7bd55cbce..ac34c6600 100644 --- a/tools/cabana/videowidget.h +++ b/tools/cabana/videowidget.h @@ -2,6 +2,7 @@ #include #include +#include #include #include From cb63f101cadec4f2ce4362b3df849a1d2adf9e56 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Mon, 17 Jun 2024 19:18:20 -0700 Subject: [PATCH 29/30] Toyota: remove smartDSU support (#32777) --- selfdrive/car/tests/routes.py | 1 - selfdrive/car/toyota/carstate.py | 17 +++----------- selfdrive/car/toyota/interface.py | 37 +++++++++---------------------- selfdrive/car/toyota/values.py | 4 +--- 4 files changed, 14 insertions(+), 45 deletions(-) diff --git a/selfdrive/car/tests/routes.py b/selfdrive/car/tests/routes.py index dd3a8f633..b1156f0e8 100755 --- a/selfdrive/car/tests/routes.py +++ b/selfdrive/car/tests/routes.py @@ -225,7 +225,6 @@ routes = [ CarTestRoute("cd9cff4b0b26c435|2021-05-13--15-12-39", TOYOTA.TOYOTA_CHR), CarTestRoute("57858ede0369a261|2021-05-18--20-34-20", TOYOTA.TOYOTA_CHR), # hybrid CarTestRoute("ea8fbe72b96a185c|2023-02-08--15-11-46", TOYOTA.TOYOTA_CHR_TSS2), - CarTestRoute("ea8fbe72b96a185c|2023-02-22--09-20-34", TOYOTA.TOYOTA_CHR_TSS2), # openpilot longitudinal, with smartDSU CarTestRoute("6719965b0e1d1737|2023-02-09--22-44-05", TOYOTA.TOYOTA_CHR_TSS2), # hybrid CarTestRoute("6719965b0e1d1737|2023-08-29--06-40-05", TOYOTA.TOYOTA_CHR_TSS2), # hybrid, openpilot longitudinal, radar disabled CarTestRoute("14623aae37e549f3|2021-10-24--01-20-49", TOYOTA.TOYOTA_PRIUS_V), diff --git a/selfdrive/car/toyota/carstate.py b/selfdrive/car/toyota/carstate.py index 8315f24ae..a596881c3 100644 --- a/selfdrive/car/toyota/carstate.py +++ b/selfdrive/car/toyota/carstate.py @@ -132,8 +132,7 @@ class CarState(CarStateBase): cp_acc = cp_cam if self.CP.carFingerprint in (TSS2_CAR - RADAR_ACC_CAR) else cp if self.CP.carFingerprint in TSS2_CAR and not self.CP.flags & ToyotaFlags.DISABLE_RADAR.value: - if not (self.CP.flags & ToyotaFlags.SMART_DSU.value): - self.acc_type = cp_acc.vl["ACC_CONTROL"]["ACC_TYPE"] + self.acc_type = cp_acc.vl["ACC_CONTROL"]["ACC_TYPE"] ret.stockFcw = bool(cp_acc.vl["PCS_HUD"]["FCW"]) # some TSS2 cars have low speed lockout permanently set, so ignore on those cars @@ -167,13 +166,11 @@ class CarState(CarStateBase): if self.CP.carFingerprint not in UNSUPPORTED_DSU_CAR: self.pcm_follow_distance = cp.vl["PCM_CRUISE_2"]["PCM_FOLLOW_DISTANCE"] - if self.CP.carFingerprint in (TSS2_CAR - RADAR_ACC_CAR) or (self.CP.flags & ToyotaFlags.SMART_DSU and not self.CP.flags & ToyotaFlags.RADAR_CAN_FILTER): + if self.CP.carFingerprint in (TSS2_CAR - RADAR_ACC_CAR): # distance button is wired to the ACC module (camera or radar) self.prev_distance_button = self.distance_button if self.CP.carFingerprint in (TSS2_CAR - RADAR_ACC_CAR): self.distance_button = cp_acc.vl["ACC_CONTROL"]["DISTANCE"] - else: - self.distance_button = cp.vl["SDSU"]["FD_BUTTON"] return ret @@ -208,12 +205,9 @@ class CarState(CarStateBase): messages.append(("BSM", 1)) if CP.carFingerprint in RADAR_ACC_CAR and not CP.flags & ToyotaFlags.DISABLE_RADAR.value: - if not CP.flags & ToyotaFlags.SMART_DSU.value: - messages += [ - ("ACC_CONTROL", 33), - ] messages += [ ("PCS_HUD", 1), + ("ACC_CONTROL", 33), ] if CP.carFingerprint not in (TSS2_CAR - RADAR_ACC_CAR) and not CP.enableDsu and not CP.flags & ToyotaFlags.DISABLE_RADAR.value: @@ -221,11 +215,6 @@ class CarState(CarStateBase): ("PRE_COLLISION", 33), ] - if CP.flags & ToyotaFlags.SMART_DSU and not CP.flags & ToyotaFlags.RADAR_CAN_FILTER: - messages += [ - ("SDSU", 100), - ] - return CANParser(DBC[CP.carFingerprint]["pt"], messages, 0) @staticmethod diff --git a/selfdrive/car/toyota/interface.py b/selfdrive/car/toyota/interface.py index 98f63597e..6487257bb 100644 --- a/selfdrive/car/toyota/interface.py +++ b/selfdrive/car/toyota/interface.py @@ -44,18 +44,9 @@ class CarInterface(CarInterfaceBase): stop_and_go = candidate in TSS2_CAR - # Detect smartDSU, which intercepts ACC_CMD from the DSU (or radar) allowing openpilot to send it - # 0x2AA is sent by a similar device which intercepts the radar instead of DSU on NO_DSU_CARs - if 0x2FF in fingerprint[0] or (0x2AA in fingerprint[0] and candidate in NO_DSU_CAR): - ret.flags |= ToyotaFlags.SMART_DSU.value - - if 0x2AA in fingerprint[0] and candidate in NO_DSU_CAR: - ret.flags |= ToyotaFlags.RADAR_CAN_FILTER.value - # In TSS2 cars, the camera does long control found_ecus = [fw.ecu for fw in car_fw] - ret.enableDsu = len(found_ecus) > 0 and Ecu.dsu not in found_ecus and candidate not in (NO_DSU_CAR | UNSUPPORTED_DSU_CAR) \ - and not (ret.flags & ToyotaFlags.SMART_DSU) + ret.enableDsu = len(found_ecus) > 0 and Ecu.dsu not in found_ecus and candidate not in (NO_DSU_CAR | UNSUPPORTED_DSU_CAR) if candidate == CAR.TOYOTA_PRIUS: stop_and_go = True @@ -98,7 +89,7 @@ class CarInterface(CarInterfaceBase): # TODO: these models can do stop and go, but unclear if it requires sDSU or unplugging DSU. # For now, don't list stop and go functionality in the docs if ret.flags & ToyotaFlags.SNG_WITHOUT_DSU: - stop_and_go = stop_and_go or bool(ret.flags & ToyotaFlags.SMART_DSU.value) or (ret.enableDsu and not docs) + stop_and_go = stop_and_go or (ret.enableDsu and not docs) ret.centerToFront = ret.wheelbase * 0.44 @@ -110,28 +101,20 @@ class CarInterface(CarInterfaceBase): # TODO: make an adas dbc file for dsu-less models ret.radarUnavailable = DBC[candidate]['radar'] is None or candidate in (NO_DSU_CAR - TSS2_CAR) - # if the smartDSU is detected, openpilot can send ACC_CONTROL and the smartDSU will block it from the DSU or radar. # since we don't yet parse radar on TSS2/TSS-P radar-based ACC cars, gate longitudinal behind experimental toggle - use_sdsu = bool(ret.flags & ToyotaFlags.SMART_DSU) if candidate in (RADAR_ACC_CAR | NO_DSU_CAR): - ret.experimentalLongitudinalAvailable = use_sdsu or candidate in RADAR_ACC_CAR + ret.experimentalLongitudinalAvailable = candidate in RADAR_ACC_CAR - if not use_sdsu: - # Disabling radar is only supported on TSS2 radar-ACC cars - if experimental_long and candidate in RADAR_ACC_CAR: - ret.flags |= ToyotaFlags.DISABLE_RADAR.value - else: - use_sdsu = use_sdsu and experimental_long + # Disabling radar is only supported on TSS2 radar-ACC cars + if experimental_long and candidate in RADAR_ACC_CAR: + ret.flags |= ToyotaFlags.DISABLE_RADAR.value # openpilot longitudinal enabled by default: - # - non-(TSS2 radar ACC cars) w/ smartDSU installed # - cars w/ DSU disconnected # - TSS2 cars with camera sending ACC_CONTROL where we can block it # openpilot longitudinal behind experimental long toggle: - # - TSS2 radar ACC cars w/ smartDSU installed - # - TSS2 radar ACC cars w/o smartDSU installed (disables radar) - # - TSS-P DSU-less cars w/ CAN filter installed (no radar parser yet) - ret.openpilotLongitudinalControl = use_sdsu or ret.enableDsu or candidate in (TSS2_CAR - RADAR_ACC_CAR) or bool(ret.flags & ToyotaFlags.DISABLE_RADAR.value) + # - TSS2 radar ACC cars (disables radar) + ret.openpilotLongitudinalControl = ret.enableDsu or candidate in (TSS2_CAR - RADAR_ACC_CAR) or bool(ret.flags & ToyotaFlags.DISABLE_RADAR.value) ret.autoResumeSng = ret.openpilotLongitudinalControl and candidate in NO_STOP_TIMER_CAR if not ret.openpilotLongitudinalControl: @@ -156,7 +139,7 @@ class CarInterface(CarInterfaceBase): @staticmethod def init(CP, logcan, sendcan): - # disable radar if alpha longitudinal toggled on radar-ACC car without CAN filter/smartDSU + # disable radar if alpha longitudinal toggled on radar-ACC car if CP.flags & ToyotaFlags.DISABLE_RADAR.value: communication_control = bytes([uds.SERVICE_TYPE.COMMUNICATION_CONTROL, uds.CONTROL_TYPE.ENABLE_RX_DISABLE_TX, uds.MESSAGE_TYPE.NORMAL]) disable_ecu(logcan, sendcan, bus=0, addr=0x750, sub_addr=0xf, com_cont_req=communication_control) @@ -165,7 +148,7 @@ class CarInterface(CarInterfaceBase): def _update(self, c): ret = self.CS.update(self.cp, self.cp_cam) - if self.CP.carFingerprint in (TSS2_CAR - RADAR_ACC_CAR) or (self.CP.flags & ToyotaFlags.SMART_DSU and not self.CP.flags & ToyotaFlags.RADAR_CAN_FILTER): + if self.CP.carFingerprint in (TSS2_CAR - RADAR_ACC_CAR): ret.buttonEvents = create_button_events(self.CS.distance_button, self.CS.prev_distance_button, {1: ButtonType.gapAdjustCruise}) # events diff --git a/selfdrive/car/toyota/values.py b/selfdrive/car/toyota/values.py index 2e781ad0a..8022e8b3a 100644 --- a/selfdrive/car/toyota/values.py +++ b/selfdrive/car/toyota/values.py @@ -44,9 +44,7 @@ class CarControllerParams: class ToyotaFlags(IntFlag): # Detected flags HYBRID = 1 - SMART_DSU = 2 DISABLE_RADAR = 4 - RADAR_CAN_FILTER = 1024 # Static flags TSS2 = 8 @@ -56,7 +54,7 @@ class ToyotaFlags(IntFlag): # these cars use the Lane Tracing Assist (LTA) message for lateral control ANGLE_CONTROL = 128 NO_STOP_TIMER = 256 - # these cars are speculated to allow stop and go when the DSU is unplugged or disabled with sDSU + # these cars are speculated to allow stop and go when the DSU is unplugged SNG_WITHOUT_DSU = 512 From 5c4ea14a3cb7bcb443fbee8c5b1d52c10788c9e8 Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Mon, 17 Jun 2024 20:30:32 -0700 Subject: [PATCH 30/30] Ubuntu 24.04 (#32624) * noble build * workflow * symlink * map only for noble * sym * add qt to cppcheck * cppcheck noreturn in non void funct * get kaitai header * kaitai header * syntax * try new pyopencl * try this version * install lsb-core manually * support old 20.04 lsb-core * try arm * try latest pyopencl * revert * use pocl icd * no lock * no arm pyopencl * new intel opencl runtime * pin filelock * undo * glsl version * new version * build test * remove test * new metadrive * remove glsl restrictions * * Update .github/workflows/tools_tests.yaml Co-authored-by: Adeeb Shihadeh * cache * new cache --------- Co-authored-by: Adeeb Shihadeh --- .devcontainer/Dockerfile | 4 +- .github/workflows/setup/action.yaml | 2 +- .github/workflows/tools_tests.yaml | 28 ++++++++++++-- .pre-commit-config.yaml | 2 + Dockerfile.openpilot_base | 37 +++++++++++-------- SConstruct | 2 + poetry.lock | 6 +-- pyproject.toml | 2 +- selfdrive/navd/SConscript | 4 +- selfdrive/ui/SConscript | 4 +- selfdrive/ui/qt/maps/map_helpers.cc | 8 ++-- .../x86_64/lib/libQMapLibre.so.3.0.0 | 4 +- tools/README.md | 6 +-- tools/profiling/snapdragon/README.md | 2 +- tools/webcam/README.md | 2 +- 15 files changed, 71 insertions(+), 42 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index af67bdbe5..1115c375d 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,11 +1,11 @@ FROM ghcr.io/commaai/openpilot-base:latest -RUN apt update && apt install -y vim net-tools usbutils htop ripgrep tmux wget mesa-utils xvfb libxtst6 libxv1 libglu1-mesa libegl1-mesa gdb bash-completion +RUN apt update && apt install -y vim net-tools usbutils htop ripgrep tmux wget mesa-utils xvfb libxtst6 libxv1 libglu1-mesa gdb bash-completion RUN pip install ipython jupyter jupyterlab RUN cd /tmp && \ ARCH=$(arch | sed s/aarch64/arm64/ | sed s/x86_64/amd64/) && \ - curl -L -o virtualgl.deb "https://downloads.sourceforge.net/project/virtualgl/3.1/virtualgl_3.1_$ARCH.deb" && \ + curl -L -o virtualgl.deb "https://github.com/VirtualGL/virtualgl/releases/download/3.1.1/virtualgl_3.1.1_$ARCH.deb" && \ dpkg -i virtualgl.deb RUN usermod -aG video batman diff --git a/.github/workflows/setup/action.yaml b/.github/workflows/setup/action.yaml index 970d62030..701675942 100644 --- a/.github/workflows/setup/action.yaml +++ b/.github/workflows/setup/action.yaml @@ -60,4 +60,4 @@ runs: find . -type f -not -executable -not -perm 644 -exec chmod 644 {} \; # build our docker image - shell: bash - run: eval ${{ env.BUILD }} \ No newline at end of file + run: eval ${{ env.BUILD }} diff --git a/.github/workflows/tools_tests.yaml b/.github/workflows/tools_tests.yaml index c2f7d86e6..9a26ca9a2 100644 --- a/.github/workflows/tools_tests.yaml +++ b/.github/workflows/tools_tests.yaml @@ -39,12 +39,13 @@ jobs: source selfdrive/test/setup_vsound.sh && \ CI=1 pytest tools/sim/tests/test_metadrive_bridge.py" - test_python311: - name: test python3.11 support - runs-on: ubuntu-latest - timeout-minutes: 5 + test_compatibility: + name: test 20.04 + 3.11 + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Installing ubuntu dependencies run: INSTALL_EXTRA_PACKAGES=no tools/install_ubuntu_dependencies.sh - name: Installing python @@ -57,6 +58,25 @@ jobs: run: pip install poetry==1.7.0 - name: Installing python dependencies run: poetry install --no-cache --no-root + - name: git LFS + run: git lfs pull + - run: echo "CACHE_COMMIT_DATE=$(git log -1 --pretty='format:%cd' --date=format:'%Y-%m-%d-%H:%M')" >> $GITHUB_ENV + - name: Getting scons cache + uses: 'actions/cache@v4' + with: + path: /tmp/scons_cache + key: scons-${{ runner.arch }}-ubuntu2004-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }} + restore-keys: | + scons-${{ runner.arch }}-ubuntu2004-${{ env.CACHE_COMMIT_DATE }} + scons-${{ runner.arch }}-ubuntu2004 + - name: Building openpilot + run: poetry run scons -u -j$(nproc) + - name: Saving scons cache + uses: actions/cache/save@v4 + if: github.ref == 'refs/heads/master' + with: + path: /tmp/scons_cache + key: scons-${{ runner.arch }}-ubuntu2004-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }} devcontainer: name: devcontainer diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d47630cda..ecde9fe77 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -62,6 +62,8 @@ repos: - --quiet - --force - -j8 + - --library=qt + - --include=third_party/kaitai/kaitaistream.h - repo: https://github.com/cpplint/cpplint rev: 1.6.1 hooks: diff --git a/Dockerfile.openpilot_base b/Dockerfile.openpilot_base index 45b29bdcb..7228d16ef 100644 --- a/Dockerfile.openpilot_base +++ b/Dockerfile.openpilot_base @@ -1,4 +1,4 @@ -FROM ubuntu:20.04 +FROM ubuntu:24.04 ENV PYTHONUNBUFFERED 1 @@ -15,7 +15,7 @@ ENV LC_ALL en_US.UTF-8 COPY tools/install_ubuntu_dependencies.sh /tmp/tools/ RUN INSTALL_EXTRA_PACKAGES=no /tmp/tools/install_ubuntu_dependencies.sh && \ rm -rf /var/lib/apt/lists/* /tmp/* && \ - cd /usr/lib/gcc/arm-none-eabi/9.2.1 && \ + cd /usr/lib/gcc/arm-none-eabi/* && \ rm -rf arm/ thumb/nofp thumb/v6* thumb/v8* thumb/v7+fp thumb/v7-r+fp.sp # Add OpenCL @@ -30,23 +30,28 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gcc-arm-none-eabi \ tmux \ vim \ - lsb-core \ libx11-6 \ + wget \ && rm -rf /var/lib/apt/lists/* -ARG INTEL_DRIVER=l_opencl_p_18.1.0.015.tgz -ARG INTEL_DRIVER_URL=https://registrationcenter-download.intel.com/akdlm/irc_nas/vcp/15532 -RUN mkdir -p /tmp/opencl-driver-intel - -RUN cd /tmp/opencl-driver-intel && \ - echo INTEL_DRIVER is $INTEL_DRIVER && \ - curl -O $INTEL_DRIVER_URL/$INTEL_DRIVER && \ - tar -xzf $INTEL_DRIVER && \ - for i in $(basename $INTEL_DRIVER .tgz)/rpm/*.rpm; do alien --to-deb $i; done && \ - dpkg -i *.deb && \ - rm -rf $INTEL_DRIVER $(basename $INTEL_DRIVER .tgz) *.deb && \ +RUN mkdir -p /tmp/opencl-driver-intel && \ + cd /tmp/opencl-driver-intel && \ + wget https://github.com/intel/llvm/releases/download/2024-WW14/oclcpuexp-2024.17.3.0.09_rel.tar.gz && \ + wget https://github.com/oneapi-src/oneTBB/releases/download/v2021.12.0/oneapi-tbb-2021.12.0-lin.tgz && \ + mkdir -p /opt/intel/oclcpuexp_2024.17.3.0.09_rel && \ + cd /opt/intel/oclcpuexp_2024.17.3.0.09_rel && \ + tar -zxvf /tmp/opencl-driver-intel/oclcpuexp-2024.17.3.0.09_rel.tar.gz && \ mkdir -p /etc/OpenCL/vendors && \ - echo /opt/intel/opencl_compilers_and_libraries_18.1.0.015/linux/compiler/lib/intel64_lin/libintelocl.so > /etc/OpenCL/vendors/intel.icd && \ + echo /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64/libintelocl.so > /etc/OpenCL/vendors/intel_expcpu.icd && \ + cd /opt/intel && \ + tar -zxvf /tmp/opencl-driver-intel/oneapi-tbb-2021.12.0-lin.tgz && \ + ln -s /opt/intel/oneapi-tbb-2021.12.0/lib/intel64/gcc4.8/libtbb.so /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 && \ + ln -s /opt/intel/oneapi-tbb-2021.12.0/lib/intel64/gcc4.8/libtbbmalloc.so /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 && \ + ln -s /opt/intel/oneapi-tbb-2021.12.0/lib/intel64/gcc4.8/libtbb.so.12 /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 && \ + ln -s /opt/intel/oneapi-tbb-2021.12.0/lib/intel64/gcc4.8/libtbbmalloc.so.2 /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 && \ + mkdir -p /etc/ld.so.conf.d && \ + echo /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 > /etc/ld.so.conf.d/libintelopenclexp.conf && \ + ldconfig -f /etc/ld.so.conf.d/libintelopenclexp.conf && \ cd / && \ rm -rf /tmp/opencl-driver-intel @@ -57,7 +62,7 @@ ENV QTWEBENGINE_DISABLE_SANDBOX 1 RUN dbus-uuidgen > /etc/machine-id ARG USER=batman -ARG USER_UID=1000 +ARG USER_UID=1001 RUN useradd -m -s /bin/bash -u $USER_UID $USER RUN usermod -aG sudo $USER RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers diff --git a/SConstruct b/SConstruct index 944d650d7..f53d8fb7d 100644 --- a/SConstruct +++ b/SConstruct @@ -14,6 +14,8 @@ SCons.Warnings.warningAsException(True) TICI = os.path.isfile('/TICI') AGNOS = TICI +UBUNTU_FOCAL = int(subprocess.check_output('[ -f /etc/os-release ] && . /etc/os-release && [ "$ID" = "ubuntu" ] && [ "$VERSION_ID" = "20.04" ] && echo 1 || echo 0', shell=True, encoding='utf-8').rstrip()) +Export('UBUNTU_FOCAL') Decider('MD5-timestamp') diff --git a/poetry.lock b/poetry.lock index 13d082763..58fa7dee6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2270,8 +2270,8 @@ ros = ["zmq"] [package.source] type = "git" url = "https://github.com/commaai/metadrive.git" -reference = "python3.12" -resolved_reference = "0823c7491a1ab870bcd53d10a41e985a3ad1b968" +reference = "anisotropic_off" +resolved_reference = "1606c844345f98aa79f76177856e328edc6ec428" [[package]] name = "mouseinfo" @@ -8114,4 +8114,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = ">=3.11, <3.13" -content-hash = "83dbbf76ea5f3e1022233a164d6f342706ebf64ad8bbbf742a55d5f49474d863" +content-hash = "32df734a6ad6ad6a665c94c41cd0e3643a48174904faaf6f21c5c84f350f3cec" diff --git a/pyproject.toml b/pyproject.toml index 5353b3988..374b0f46c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -176,7 +176,7 @@ flaky = "*" inputs = "*" lru-dict = "*" matplotlib = "*" -metadrive-simulator = { git = "https://github.com/commaai/metadrive.git", branch = "python3.12", markers = "platform_machine != 'aarch64'" } # no linux/aarch64 wheels for certain dependencies +metadrive-simulator = { git = "https://github.com/commaai/metadrive.git", branch = "anisotropic_off", markers = "platform_machine != 'aarch64'" } # no linux/aarch64 wheels for certain dependencies mpld3 = "*" myst-parser = "*" natsort = "*" diff --git a/selfdrive/navd/SConscript b/selfdrive/navd/SConscript index 295e8127d..378e76249 100644 --- a/selfdrive/navd/SConscript +++ b/selfdrive/navd/SConscript @@ -1,4 +1,4 @@ -Import('qt_env', 'arch', 'common', 'messaging', 'visionipc', 'transformations') +Import('qt_env', 'arch', 'common', 'messaging', 'visionipc', 'transformations', 'UBUNTU_FOCAL') map_env = qt_env.Clone() libs = ['qt_widgets', 'qt_util', 'QMapLibre', common, messaging, visionipc, transformations, @@ -6,7 +6,7 @@ libs = ['qt_widgets', 'qt_util', 'QMapLibre', common, messaging, visionipc, tran if arch == 'larch64': libs.append(':libEGL_mesa.so.0') -if arch in ['larch64', 'aarch64', 'x86_64']: +if arch in ['larch64', 'aarch64', 'x86_64'] and not UBUNTU_FOCAL: if arch == 'x86_64': rpath = Dir(f"#third_party/maplibre-native-qt/{arch}/lib").srcnode().abspath map_env["RPATH"] += [rpath, ] diff --git a/selfdrive/ui/SConscript b/selfdrive/ui/SConscript index e181cb9ab..e4fb32586 100644 --- a/selfdrive/ui/SConscript +++ b/selfdrive/ui/SConscript @@ -1,6 +1,6 @@ import os import json -Import('qt_env', 'arch', 'common', 'messaging', 'visionipc', 'transformations') +Import('qt_env', 'arch', 'common', 'messaging', 'visionipc', 'transformations', 'UBUNTU_FOCAL') base_libs = [common, messaging, visionipc, transformations, 'm', 'OpenCL', 'ssl', 'crypto', 'pthread'] + qt_env["LIBS"] @@ -8,7 +8,7 @@ base_libs = [common, messaging, visionipc, transformations, if arch == 'larch64': base_libs.append('EGL') -maps = arch in ['larch64', 'aarch64', 'x86_64'] +maps = arch in ['larch64', 'aarch64', 'x86_64'] and not UBUNTU_FOCAL if arch == "Darwin": del base_libs[base_libs.index('OpenCL')] diff --git a/selfdrive/ui/qt/maps/map_helpers.cc b/selfdrive/ui/qt/maps/map_helpers.cc index 16923f7a4..50e140116 100644 --- a/selfdrive/ui/qt/maps/map_helpers.cc +++ b/selfdrive/ui/qt/maps/map_helpers.cc @@ -143,11 +143,11 @@ std::pair map_format_distance(float d, bool is_metric) { d = std::max(d, 0.0f); if (is_metric) { - return (d > 500) ? std::pair{round_distance(d / 1000), QObject::tr("km")} - : std::pair{QString::number(50 * std::nearbyint(d / 50)), QObject::tr("m")}; + return (d > 500) ? std::pair(round_distance(d / 1000), QObject::tr("km")) + : std::pair(QString::number(50 * std::nearbyint(d / 50)), QObject::tr("m")); } else { float feet = d * METER_TO_FOOT; - return (feet > 500) ? std::pair{round_distance(d * METER_TO_MILE), QObject::tr("mi")} - : std::pair{QString::number(50 * std::nearbyint(d / 50)), QObject::tr("ft")}; + return (feet > 500) ? std::pair(round_distance(d * METER_TO_MILE), QObject::tr("mi")) + : std::pair(QString::number(50 * std::nearbyint(d / 50)), QObject::tr("ft")); } } diff --git a/third_party/maplibre-native-qt/x86_64/lib/libQMapLibre.so.3.0.0 b/third_party/maplibre-native-qt/x86_64/lib/libQMapLibre.so.3.0.0 index f2fcf107b..e49d321c7 100755 --- a/third_party/maplibre-native-qt/x86_64/lib/libQMapLibre.so.3.0.0 +++ b/third_party/maplibre-native-qt/x86_64/lib/libQMapLibre.so.3.0.0 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b718e4ea770105893dc41f64be36f806586a9471e2bb9d18d5ad97e906434548 -size 11000296 +oid sha256:d62e192aa7806302ed79866d9e3c51efc4bc315a6fdfe0e58e448dac5b279098 +size 11549728 diff --git a/tools/README.md b/tools/README.md index 361a27ded..f465ea123 100644 --- a/tools/README.md +++ b/tools/README.md @@ -2,11 +2,11 @@ ## System Requirements -openpilot is developed and tested on **Ubuntu 20.04**, which is the primary development target aside from the [supported embedded hardware](https://github.com/commaai/openpilot#running-on-a-dedicated-device-in-a-car). +openpilot is developed and tested on **Ubuntu 24.04**, which is the primary development target aside from the [supported embedded hardware](https://github.com/commaai/openpilot#running-on-a-dedicated-device-in-a-car). Running natively on any other system is not recommended and will require modifications. On Windows you can use WSL, and on macOS or incompatible Linux systems, it is recommended to use the dev containers. -## Native setup on Ubuntu 20.04 +## Native setup on Ubuntu 24.04 **1. Clone openpilot** @@ -55,7 +55,7 @@ GUI apps like `ui` or `cabana` can also run inside the container by leveraging X [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/about) should provide a similar experience to native Ubuntu. [WSL 2](https://docs.microsoft.com/en-us/windows/wsl/compare-versions) specifically has been reported by several users to be a seamless experience. -Follow [these instructions](https://docs.microsoft.com/en-us/windows/wsl/install) to setup the WSL and install the `Ubuntu-20.04` distribution. Once your Ubuntu WSL environment is setup, follow the Linux setup instructions to finish setting up your environment. See [these instructions](https://learn.microsoft.com/en-us/windows/wsl/tutorials/gui-apps) for running GUI apps. +Follow [these instructions](https://docs.microsoft.com/en-us/windows/wsl/install) to setup the WSL and install the `Ubuntu-24.04` distribution. Once your Ubuntu WSL environment is setup, follow the Linux setup instructions to finish setting up your environment. See [these instructions](https://learn.microsoft.com/en-us/windows/wsl/tutorials/gui-apps) for running GUI apps. **NOTE**: If you are running WSL and any GUIs are failing (segfaulting or other strange issues) even after following the steps above, you may need to enable software rendering with `LIBGL_ALWAYS_SOFTWARE=1`, e.g. `LIBGL_ALWAYS_SOFTWARE=1 selfdrive/ui/ui`. diff --git a/tools/profiling/snapdragon/README.md b/tools/profiling/snapdragon/README.md index 664814b61..f56ca182a 100644 --- a/tools/profiling/snapdragon/README.md +++ b/tools/profiling/snapdragon/README.md @@ -3,7 +3,7 @@ snapdragon profiler * download from https://developer.qualcomm.com/software/snapdragon-profiler/tools-archive (need a qc developer account) - * choose v2021.5 (verified working with 20.04 dev environment) + * choose v2021.5 (verified working with 24.04 dev environment) * unzip to selfdrive/debug/profiling/snapdragon/SnapdragonProfiler * run ```./setup-profiler.sh``` * run ```./setup-agnos.sh``` diff --git a/tools/webcam/README.md b/tools/webcam/README.md index 7334d87b3..c756069bb 100644 --- a/tools/webcam/README.md +++ b/tools/webcam/README.md @@ -1,7 +1,7 @@ # Run openpilot with webcam on PC What's needed: -- Ubuntu 20.04 +- Ubuntu 24.04 - GPU (recommended) - Two USB webcams, at least 720p and 78 degrees FOV (e.g. Logitech C920/C615) - [Car harness](https://comma.ai/shop/products/comma-car-harness) with black panda to connect to your car