From b501ad4d5103887fd1bc9c8a02bcfc6d1bbf80ce Mon Sep 17 00:00:00 2001 From: Comma Device Date: Sun, 24 Aug 2025 00:48:54 +0000 Subject: [PATCH 001/159] nice encoder debugging script --- system/loggerd/tests/vidc_debug.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100755 system/loggerd/tests/vidc_debug.sh diff --git a/system/loggerd/tests/vidc_debug.sh b/system/loggerd/tests/vidc_debug.sh new file mode 100755 index 0000000000..7471f2ab08 --- /dev/null +++ b/system/loggerd/tests/vidc_debug.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -e + +cd /sys/kernel/debug/tracing +echo "" > trace +echo 1 > tracing_on +echo 1 > /sys/kernel/debug/tracing/events/msm_vidc/enable + +echo 0xff > /sys/module/videobuf2_core/parameters/debug +echo 0x7fffffff > /sys/kernel/debug/msm_vidc/debug_level +echo 0xff > /sys/devices/platform/soc/aa00000.qcom,vidc/video4linux/video33/dev_debug + +cat /sys/kernel/debug/tracing/trace_pipe From aea467ff02ca68988d0e82824e9ec18fd5c459f5 Mon Sep 17 00:00:00 2001 From: commaci-public <60409688+commaci-public@users.noreply.github.com> Date: Mon, 25 Aug 2025 11:43:49 -0700 Subject: [PATCH 002/159] [bot] Update Python packages (#36053) * Update Python packages * bump --------- Co-authored-by: Vehicle Researcher Co-authored-by: Shane Smiskol --- opendbc_repo | 2 +- selfdrive/test/process_replay/ref_commit | 2 +- tinygrad_repo | 2 +- uv.lock | 184 ++++++++++++----------- 4 files changed, 99 insertions(+), 91 deletions(-) diff --git a/opendbc_repo b/opendbc_repo index 43006b9a41..0fe56bc289 160000 --- a/opendbc_repo +++ b/opendbc_repo @@ -1 +1 @@ -Subproject commit 43006b9a41e233325cb7cbcb6ff40de0234217a0 +Subproject commit 0fe56bc289d72d2f278e9c085f2ada6ecb13e688 diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index a4297096c0..8e4ff1e2a8 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -6d3219bca9f66a229b38a5382d301a92b0147edb \ No newline at end of file +209b47bea61e145cf2d27eb3ab650c97bcd1d33f \ No newline at end of file diff --git a/tinygrad_repo b/tinygrad_repo index c30a113b2a..e146418f65 160000 --- a/tinygrad_repo +++ b/tinygrad_repo @@ -1 +1 @@ -Subproject commit c30a113b2a876cabaea1049601fea3a0b758c5b1 +Subproject commit e146418f6566301ffe8ebea093c0081409241c8d diff --git a/uv.lock b/uv.lock index 7cfaceed97..7010cdfb83 100644 --- a/uv.lock +++ b/uv.lock @@ -763,40 +763,48 @@ wheels = [ [[package]] name = "lxml" -version = "6.0.0" +version = "6.0.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c5/ed/60eb6fa2923602fba988d9ca7c5cdbd7cf25faa795162ed538b527a35411/lxml-6.0.0.tar.gz", hash = "sha256:032e65120339d44cdc3efc326c9f660f5f7205f3a535c1fdbf898b29ea01fb72", size = 4096938, upload-time = "2025-06-26T16:28:19.373Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8f/bd/f9d01fd4132d81c6f43ab01983caea69ec9614b913c290a26738431a015d/lxml-6.0.1.tar.gz", hash = "sha256:2b3a882ebf27dd026df3801a87cf49ff791336e0f94b0fad195db77e01240690", size = 4070214, upload-time = "2025-08-22T10:37:53.525Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/23/828d4cc7da96c611ec0ce6147bbcea2fdbde023dc995a165afa512399bbf/lxml-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4ee56288d0df919e4aac43b539dd0e34bb55d6a12a6562038e8d6f3ed07f9e36", size = 8438217, upload-time = "2025-06-26T16:25:34.349Z" }, - { url = "https://files.pythonhosted.org/packages/f1/33/5ac521212c5bcb097d573145d54b2b4a3c9766cda88af5a0e91f66037c6e/lxml-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b8dd6dd0e9c1992613ccda2bcb74fc9d49159dbe0f0ca4753f37527749885c25", size = 4590317, upload-time = "2025-06-26T16:25:38.103Z" }, - { url = "https://files.pythonhosted.org/packages/2b/2e/45b7ca8bee304c07f54933c37afe7dd4d39ff61ba2757f519dcc71bc5d44/lxml-6.0.0-cp311-cp311-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:d7ae472f74afcc47320238b5dbfd363aba111a525943c8a34a1b657c6be934c3", size = 5221628, upload-time = "2025-06-26T16:25:40.878Z" }, - { url = "https://files.pythonhosted.org/packages/32/23/526d19f7eb2b85da1f62cffb2556f647b049ebe2a5aa8d4d41b1fb2c7d36/lxml-6.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5592401cdf3dc682194727c1ddaa8aa0f3ddc57ca64fd03226a430b955eab6f6", size = 4949429, upload-time = "2025-06-28T18:47:20.046Z" }, - { url = "https://files.pythonhosted.org/packages/ac/cc/f6be27a5c656a43a5344e064d9ae004d4dcb1d3c9d4f323c8189ddfe4d13/lxml-6.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:58ffd35bd5425c3c3b9692d078bf7ab851441434531a7e517c4984d5634cd65b", size = 5087909, upload-time = "2025-06-28T18:47:22.834Z" }, - { url = "https://files.pythonhosted.org/packages/3b/e6/8ec91b5bfbe6972458bc105aeb42088e50e4b23777170404aab5dfb0c62d/lxml-6.0.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f720a14aa102a38907c6d5030e3d66b3b680c3e6f6bc95473931ea3c00c59967", size = 5031713, upload-time = "2025-06-26T16:25:43.226Z" }, - { url = "https://files.pythonhosted.org/packages/33/cf/05e78e613840a40e5be3e40d892c48ad3e475804db23d4bad751b8cadb9b/lxml-6.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c2a5e8d207311a0170aca0eb6b160af91adc29ec121832e4ac151a57743a1e1e", size = 5232417, upload-time = "2025-06-26T16:25:46.111Z" }, - { url = "https://files.pythonhosted.org/packages/ac/8c/6b306b3e35c59d5f0b32e3b9b6b3b0739b32c0dc42a295415ba111e76495/lxml-6.0.0-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:2dd1cc3ea7e60bfb31ff32cafe07e24839df573a5e7c2d33304082a5019bcd58", size = 4681443, upload-time = "2025-06-26T16:25:48.837Z" }, - { url = "https://files.pythonhosted.org/packages/59/43/0bd96bece5f7eea14b7220476835a60d2b27f8e9ca99c175f37c085cb154/lxml-6.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2cfcf84f1defed7e5798ef4f88aa25fcc52d279be731ce904789aa7ccfb7e8d2", size = 5074542, upload-time = "2025-06-26T16:25:51.65Z" }, - { url = "https://files.pythonhosted.org/packages/e2/3d/32103036287a8ca012d8518071f8852c68f2b3bfe048cef2a0202eb05910/lxml-6.0.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:a52a4704811e2623b0324a18d41ad4b9fabf43ce5ff99b14e40a520e2190c851", size = 4729471, upload-time = "2025-06-26T16:25:54.571Z" }, - { url = "https://files.pythonhosted.org/packages/ca/a8/7be5d17df12d637d81854bd8648cd329f29640a61e9a72a3f77add4a311b/lxml-6.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c16304bba98f48a28ae10e32a8e75c349dd742c45156f297e16eeb1ba9287a1f", size = 5256285, upload-time = "2025-06-26T16:25:56.997Z" }, - { url = "https://files.pythonhosted.org/packages/cd/d0/6cb96174c25e0d749932557c8d51d60c6e292c877b46fae616afa23ed31a/lxml-6.0.0-cp311-cp311-win32.whl", hash = "sha256:f8d19565ae3eb956d84da3ef367aa7def14a2735d05bd275cd54c0301f0d0d6c", size = 3612004, upload-time = "2025-06-26T16:25:59.11Z" }, - { url = "https://files.pythonhosted.org/packages/ca/77/6ad43b165dfc6dead001410adeb45e88597b25185f4479b7ca3b16a5808f/lxml-6.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:b2d71cdefda9424adff9a3607ba5bbfc60ee972d73c21c7e3c19e71037574816", size = 4003470, upload-time = "2025-06-26T16:26:01.655Z" }, - { url = "https://files.pythonhosted.org/packages/a0/bc/4c50ec0eb14f932a18efc34fc86ee936a66c0eb5f2fe065744a2da8a68b2/lxml-6.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:8a2e76efbf8772add72d002d67a4c3d0958638696f541734304c7f28217a9cab", size = 3682477, upload-time = "2025-06-26T16:26:03.808Z" }, - { url = "https://files.pythonhosted.org/packages/89/c3/d01d735c298d7e0ddcedf6f028bf556577e5ab4f4da45175ecd909c79378/lxml-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78718d8454a6e928470d511bf8ac93f469283a45c354995f7d19e77292f26108", size = 8429515, upload-time = "2025-06-26T16:26:06.776Z" }, - { url = "https://files.pythonhosted.org/packages/06/37/0e3eae3043d366b73da55a86274a590bae76dc45aa004b7042e6f97803b1/lxml-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:84ef591495ffd3f9dcabffd6391db7bb70d7230b5c35ef5148354a134f56f2be", size = 4601387, upload-time = "2025-06-26T16:26:09.511Z" }, - { url = "https://files.pythonhosted.org/packages/a3/28/e1a9a881e6d6e29dda13d633885d13acb0058f65e95da67841c8dd02b4a8/lxml-6.0.0-cp312-cp312-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:2930aa001a3776c3e2601cb8e0a15d21b8270528d89cc308be4843ade546b9ab", size = 5228928, upload-time = "2025-06-26T16:26:12.337Z" }, - { url = "https://files.pythonhosted.org/packages/9a/55/2cb24ea48aa30c99f805921c1c7860c1f45c0e811e44ee4e6a155668de06/lxml-6.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:219e0431ea8006e15005767f0351e3f7f9143e793e58519dc97fe9e07fae5563", size = 4952289, upload-time = "2025-06-28T18:47:25.602Z" }, - { url = "https://files.pythonhosted.org/packages/31/c0/b25d9528df296b9a3306ba21ff982fc5b698c45ab78b94d18c2d6ae71fd9/lxml-6.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bd5913b4972681ffc9718bc2d4c53cde39ef81415e1671ff93e9aa30b46595e7", size = 5111310, upload-time = "2025-06-28T18:47:28.136Z" }, - { url = "https://files.pythonhosted.org/packages/e9/af/681a8b3e4f668bea6e6514cbcb297beb6de2b641e70f09d3d78655f4f44c/lxml-6.0.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:390240baeb9f415a82eefc2e13285016f9c8b5ad71ec80574ae8fa9605093cd7", size = 5025457, upload-time = "2025-06-26T16:26:15.068Z" }, - { url = "https://files.pythonhosted.org/packages/99/b6/3a7971aa05b7be7dfebc7ab57262ec527775c2c3c5b2f43675cac0458cad/lxml-6.0.0-cp312-cp312-manylinux_2_27_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d6e200909a119626744dd81bae409fc44134389e03fbf1d68ed2a55a2fb10991", size = 5657016, upload-time = "2025-07-03T19:19:06.008Z" }, - { url = "https://files.pythonhosted.org/packages/69/f8/693b1a10a891197143c0673fcce5b75fc69132afa81a36e4568c12c8faba/lxml-6.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ca50bd612438258a91b5b3788c6621c1f05c8c478e7951899f492be42defc0da", size = 5257565, upload-time = "2025-06-26T16:26:17.906Z" }, - { url = "https://files.pythonhosted.org/packages/a8/96/e08ff98f2c6426c98c8964513c5dab8d6eb81dadcd0af6f0c538ada78d33/lxml-6.0.0-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:c24b8efd9c0f62bad0439283c2c795ef916c5a6b75f03c17799775c7ae3c0c9e", size = 4713390, upload-time = "2025-06-26T16:26:20.292Z" }, - { url = "https://files.pythonhosted.org/packages/a8/83/6184aba6cc94d7413959f6f8f54807dc318fdcd4985c347fe3ea6937f772/lxml-6.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:afd27d8629ae94c5d863e32ab0e1d5590371d296b87dae0a751fb22bf3685741", size = 5066103, upload-time = "2025-06-26T16:26:22.765Z" }, - { url = "https://files.pythonhosted.org/packages/ee/01/8bf1f4035852d0ff2e36a4d9aacdbcc57e93a6cd35a54e05fa984cdf73ab/lxml-6.0.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:54c4855eabd9fc29707d30141be99e5cd1102e7d2258d2892314cf4c110726c3", size = 4791428, upload-time = "2025-06-26T16:26:26.461Z" }, - { url = "https://files.pythonhosted.org/packages/29/31/c0267d03b16954a85ed6b065116b621d37f559553d9339c7dcc4943a76f1/lxml-6.0.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c907516d49f77f6cd8ead1322198bdfd902003c3c330c77a1c5f3cc32a0e4d16", size = 5678523, upload-time = "2025-07-03T19:19:09.837Z" }, - { url = "https://files.pythonhosted.org/packages/5c/f7/5495829a864bc5f8b0798d2b52a807c89966523140f3d6fa3a58ab6720ea/lxml-6.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:36531f81c8214e293097cd2b7873f178997dae33d3667caaae8bdfb9666b76c0", size = 5281290, upload-time = "2025-06-26T16:26:29.406Z" }, - { url = "https://files.pythonhosted.org/packages/79/56/6b8edb79d9ed294ccc4e881f4db1023af56ba451909b9ce79f2a2cd7c532/lxml-6.0.0-cp312-cp312-win32.whl", hash = "sha256:690b20e3388a7ec98e899fd54c924e50ba6693874aa65ef9cb53de7f7de9d64a", size = 3613495, upload-time = "2025-06-26T16:26:31.588Z" }, - { url = "https://files.pythonhosted.org/packages/0b/1e/cc32034b40ad6af80b6fd9b66301fc0f180f300002e5c3eb5a6110a93317/lxml-6.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:310b719b695b3dd442cdfbbe64936b2f2e231bb91d998e99e6f0daf991a3eba3", size = 4014711, upload-time = "2025-06-26T16:26:33.723Z" }, - { url = "https://files.pythonhosted.org/packages/55/10/dc8e5290ae4c94bdc1a4c55865be7e1f31dfd857a88b21cbba68b5fea61b/lxml-6.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:8cb26f51c82d77483cdcd2b4a53cda55bbee29b3c2f3ddeb47182a2a9064e4eb", size = 3674431, upload-time = "2025-06-26T16:26:35.959Z" }, + { url = "https://files.pythonhosted.org/packages/29/c8/262c1d19339ef644cdc9eb5aad2e85bd2d1fa2d7c71cdef3ede1a3eed84d/lxml-6.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c6acde83f7a3d6399e6d83c1892a06ac9b14ea48332a5fbd55d60b9897b9570a", size = 8422719, upload-time = "2025-08-22T10:32:24.848Z" }, + { url = "https://files.pythonhosted.org/packages/e5/d4/1b0afbeb801468a310642c3a6f6704e53c38a4a6eb1ca6faea013333e02f/lxml-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0d21c9cacb6a889cbb8eeb46c77ef2c1dd529cde10443fdeb1de847b3193c541", size = 4575763, upload-time = "2025-08-22T10:32:27.057Z" }, + { url = "https://files.pythonhosted.org/packages/5b/c1/8db9b5402bf52ceb758618313f7423cd54aea85679fcf607013707d854a8/lxml-6.0.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:847458b7cd0d04004895f1fb2cca8e7c0f8ec923c49c06b7a72ec2d48ea6aca2", size = 4943244, upload-time = "2025-08-22T10:32:28.847Z" }, + { url = "https://files.pythonhosted.org/packages/e7/78/838e115358dd2369c1c5186080dd874a50a691fb5cd80db6afe5e816e2c6/lxml-6.0.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1dc13405bf315d008fe02b1472d2a9d65ee1c73c0a06de5f5a45e6e404d9a1c0", size = 5081725, upload-time = "2025-08-22T10:32:30.666Z" }, + { url = "https://files.pythonhosted.org/packages/c7/b6/bdcb3a3ddd2438c5b1a1915161f34e8c85c96dc574b0ef3be3924f36315c/lxml-6.0.1-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70f540c229a8c0a770dcaf6d5af56a5295e0fc314fc7ef4399d543328054bcea", size = 5021238, upload-time = "2025-08-22T10:32:32.49Z" }, + { url = "https://files.pythonhosted.org/packages/73/e5/1bfb96185dc1a64c7c6fbb7369192bda4461952daa2025207715f9968205/lxml-6.0.1-cp311-cp311-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:d2f73aef768c70e8deb8c4742fca4fd729b132fda68458518851c7735b55297e", size = 5343744, upload-time = "2025-08-22T10:32:34.385Z" }, + { url = "https://files.pythonhosted.org/packages/a2/ae/df3ea9ebc3c493b9c6bdc6bd8c554ac4e147f8d7839993388aab57ec606d/lxml-6.0.1-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e7f4066b85a4fa25ad31b75444bd578c3ebe6b8ed47237896341308e2ce923c3", size = 5223477, upload-time = "2025-08-22T10:32:36.256Z" }, + { url = "https://files.pythonhosted.org/packages/37/b3/65e1e33600542c08bc03a4c5c9c306c34696b0966a424a3be6ffec8038ed/lxml-6.0.1-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:0cce65db0cd8c750a378639900d56f89f7d6af11cd5eda72fde054d27c54b8ce", size = 4676626, upload-time = "2025-08-22T10:32:38.793Z" }, + { url = "https://files.pythonhosted.org/packages/7a/46/ee3ed8f3a60e9457d7aea46542d419917d81dbfd5700fe64b2a36fb5ef61/lxml-6.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c372d42f3eee5844b69dcab7b8d18b2f449efd54b46ac76970d6e06b8e8d9a66", size = 5066042, upload-time = "2025-08-22T10:32:41.134Z" }, + { url = "https://files.pythonhosted.org/packages/9c/b9/8394538e7cdbeb3bfa36bc74924be1a4383e0bb5af75f32713c2c4aa0479/lxml-6.0.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:2e2b0e042e1408bbb1c5f3cfcb0f571ff4ac98d8e73f4bf37c5dd179276beedd", size = 4724714, upload-time = "2025-08-22T10:32:43.94Z" }, + { url = "https://files.pythonhosted.org/packages/b3/21/3ef7da1ea2a73976c1a5a311d7cde5d379234eec0968ee609517714940b4/lxml-6.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:cc73bb8640eadd66d25c5a03175de6801f63c535f0f3cf50cac2f06a8211f420", size = 5247376, upload-time = "2025-08-22T10:32:46.263Z" }, + { url = "https://files.pythonhosted.org/packages/26/7d/0980016f124f00c572cba6f4243e13a8e80650843c66271ee692cddf25f3/lxml-6.0.1-cp311-cp311-win32.whl", hash = "sha256:7c23fd8c839708d368e406282d7953cee5134f4592ef4900026d84566d2b4c88", size = 3609499, upload-time = "2025-08-22T10:32:48.156Z" }, + { url = "https://files.pythonhosted.org/packages/b1/08/28440437521f265eff4413eb2a65efac269c4c7db5fd8449b586e75d8de2/lxml-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:2516acc6947ecd3c41a4a4564242a87c6786376989307284ddb115f6a99d927f", size = 4036003, upload-time = "2025-08-22T10:32:50.662Z" }, + { url = "https://files.pythonhosted.org/packages/7b/dc/617e67296d98099213a505d781f04804e7b12923ecd15a781a4ab9181992/lxml-6.0.1-cp311-cp311-win_arm64.whl", hash = "sha256:cb46f8cfa1b0334b074f40c0ff94ce4d9a6755d492e6c116adb5f4a57fb6ad96", size = 3679662, upload-time = "2025-08-22T10:32:52.739Z" }, + { url = "https://files.pythonhosted.org/packages/b0/a9/82b244c8198fcdf709532e39a1751943a36b3e800b420adc739d751e0299/lxml-6.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c03ac546adaabbe0b8e4a15d9ad815a281afc8d36249c246aecf1aaad7d6f200", size = 8422788, upload-time = "2025-08-22T10:32:56.612Z" }, + { url = "https://files.pythonhosted.org/packages/c9/8d/1ed2bc20281b0e7ed3e6c12b0a16e64ae2065d99be075be119ba88486e6d/lxml-6.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:33b862c7e3bbeb4ba2c96f3a039f925c640eeba9087a4dc7a572ec0f19d89392", size = 4593547, upload-time = "2025-08-22T10:32:59.016Z" }, + { url = "https://files.pythonhosted.org/packages/76/53/d7fd3af95b72a3493bf7fbe842a01e339d8f41567805cecfecd5c71aa5ee/lxml-6.0.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7a3ec1373f7d3f519de595032d4dcafae396c29407cfd5073f42d267ba32440d", size = 4948101, upload-time = "2025-08-22T10:33:00.765Z" }, + { url = "https://files.pythonhosted.org/packages/9d/51/4e57cba4d55273c400fb63aefa2f0d08d15eac021432571a7eeefee67bed/lxml-6.0.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:03b12214fb1608f4cffa181ec3d046c72f7e77c345d06222144744c122ded870", size = 5108090, upload-time = "2025-08-22T10:33:03.108Z" }, + { url = "https://files.pythonhosted.org/packages/f6/6e/5f290bc26fcc642bc32942e903e833472271614e24d64ad28aaec09d5dae/lxml-6.0.1-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:207ae0d5f0f03b30f95e649a6fa22aa73f5825667fee9c7ec6854d30e19f2ed8", size = 5021791, upload-time = "2025-08-22T10:33:06.972Z" }, + { url = "https://files.pythonhosted.org/packages/13/d4/2e7551a86992ece4f9a0f6eebd4fb7e312d30f1e372760e2109e721d4ce6/lxml-6.0.1-cp312-cp312-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:32297b09ed4b17f7b3f448de87a92fb31bb8747496623483788e9f27c98c0f00", size = 5358861, upload-time = "2025-08-22T10:33:08.967Z" }, + { url = "https://files.pythonhosted.org/packages/8a/5f/cb49d727fc388bf5fd37247209bab0da11697ddc5e976ccac4826599939e/lxml-6.0.1-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7e18224ea241b657a157c85e9cac82c2b113ec90876e01e1f127312006233756", size = 5652569, upload-time = "2025-08-22T10:33:10.815Z" }, + { url = "https://files.pythonhosted.org/packages/ca/b8/66c1ef8c87ad0f958b0a23998851e610607c74849e75e83955d5641272e6/lxml-6.0.1-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a07a994d3c46cd4020c1ea566345cf6815af205b1e948213a4f0f1d392182072", size = 5252262, upload-time = "2025-08-22T10:33:12.673Z" }, + { url = "https://files.pythonhosted.org/packages/1a/ef/131d3d6b9590e64fdbb932fbc576b81fcc686289da19c7cb796257310e82/lxml-6.0.1-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:2287fadaa12418a813b05095485c286c47ea58155930cfbd98c590d25770e225", size = 4710309, upload-time = "2025-08-22T10:33:14.952Z" }, + { url = "https://files.pythonhosted.org/packages/bc/3f/07f48ae422dce44902309aa7ed386c35310929dc592439c403ec16ef9137/lxml-6.0.1-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b4e597efca032ed99f418bd21314745522ab9fa95af33370dcee5533f7f70136", size = 5265786, upload-time = "2025-08-22T10:33:16.721Z" }, + { url = "https://files.pythonhosted.org/packages/11/c7/125315d7b14ab20d9155e8316f7d287a4956098f787c22d47560b74886c4/lxml-6.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9696d491f156226decdd95d9651c6786d43701e49f32bf23715c975539aa2b3b", size = 5062272, upload-time = "2025-08-22T10:33:18.478Z" }, + { url = "https://files.pythonhosted.org/packages/8b/c3/51143c3a5fc5168a7c3ee626418468ff20d30f5a59597e7b156c1e61fba8/lxml-6.0.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e4e3cd3585f3c6f87cdea44cda68e692cc42a012f0131d25957ba4ce755241a7", size = 4786955, upload-time = "2025-08-22T10:33:20.34Z" }, + { url = "https://files.pythonhosted.org/packages/11/86/73102370a420ec4529647b31c4a8ce8c740c77af3a5fae7a7643212d6f6e/lxml-6.0.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:45cbc92f9d22c28cd3b97f8d07fcefa42e569fbd587dfdac76852b16a4924277", size = 5673557, upload-time = "2025-08-22T10:33:22.282Z" }, + { url = "https://files.pythonhosted.org/packages/d7/2d/aad90afaec51029aef26ef773b8fd74a9e8706e5e2f46a57acd11a421c02/lxml-6.0.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:f8c9bcfd2e12299a442fba94459adf0b0d001dbc68f1594439bfa10ad1ecb74b", size = 5254211, upload-time = "2025-08-22T10:33:24.15Z" }, + { url = "https://files.pythonhosted.org/packages/63/01/c9e42c8c2d8b41f4bdefa42ab05448852e439045f112903dd901b8fbea4d/lxml-6.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1e9dc2b9f1586e7cd77753eae81f8d76220eed9b768f337dc83a3f675f2f0cf9", size = 5275817, upload-time = "2025-08-22T10:33:26.007Z" }, + { url = "https://files.pythonhosted.org/packages/bc/1f/962ea2696759abe331c3b0e838bb17e92224f39c638c2068bf0d8345e913/lxml-6.0.1-cp312-cp312-win32.whl", hash = "sha256:987ad5c3941c64031f59c226167f55a04d1272e76b241bfafc968bdb778e07fb", size = 3610889, upload-time = "2025-08-22T10:33:28.169Z" }, + { url = "https://files.pythonhosted.org/packages/41/e2/22c86a990b51b44442b75c43ecb2f77b8daba8c4ba63696921966eac7022/lxml-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:abb05a45394fd76bf4a60c1b7bec0e6d4e8dfc569fc0e0b1f634cd983a006ddc", size = 4010925, upload-time = "2025-08-22T10:33:29.874Z" }, + { url = "https://files.pythonhosted.org/packages/b2/21/dc0c73325e5eb94ef9c9d60dbb5dcdcb2e7114901ea9509735614a74e75a/lxml-6.0.1-cp312-cp312-win_arm64.whl", hash = "sha256:c4be29bce35020d8579d60aa0a4e95effd66fcfce31c46ffddf7e5422f73a299", size = 3671922, upload-time = "2025-08-22T10:33:31.535Z" }, + { url = "https://files.pythonhosted.org/packages/41/37/41961f53f83ded57b37e65e4f47d1c6c6ef5fd02cb1d6ffe028ba0efa7d4/lxml-6.0.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b556aaa6ef393e989dac694b9c95761e32e058d5c4c11ddeef33f790518f7a5e", size = 3903412, upload-time = "2025-08-22T10:37:40.758Z" }, + { url = "https://files.pythonhosted.org/packages/3d/47/8631ea73f3dc776fb6517ccde4d5bd5072f35f9eacbba8c657caa4037a69/lxml-6.0.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:64fac7a05ebb3737b79fd89fe5a5b6c5546aac35cfcfd9208eb6e5d13215771c", size = 4224810, upload-time = "2025-08-22T10:37:42.839Z" }, + { url = "https://files.pythonhosted.org/packages/3d/b8/39ae30ca3b1516729faeef941ed84bf8f12321625f2644492ed8320cb254/lxml-6.0.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:038d3c08babcfce9dc89aaf498e6da205efad5b7106c3b11830a488d4eadf56b", size = 4329221, upload-time = "2025-08-22T10:37:45.223Z" }, + { url = "https://files.pythonhosted.org/packages/9c/ea/048dea6cdfc7a72d40ae8ed7e7d23cf4a6b6a6547b51b492a3be50af0e80/lxml-6.0.1-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:445f2cee71c404ab4259bc21e20339a859f75383ba2d7fb97dfe7c163994287b", size = 4270228, upload-time = "2025-08-22T10:37:47.276Z" }, + { url = "https://files.pythonhosted.org/packages/6b/d4/c2b46e432377c45d611ae2f669aa47971df1586c1a5240675801d0f02bac/lxml-6.0.1-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e352d8578e83822d70bea88f3d08b9912528e4c338f04ab707207ab12f4b7aac", size = 4416077, upload-time = "2025-08-22T10:37:49.822Z" }, + { url = "https://files.pythonhosted.org/packages/b6/db/8f620f1ac62cf32554821b00b768dd5957ac8e3fd051593532be5b40b438/lxml-6.0.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:51bd5d1a9796ca253db6045ab45ca882c09c071deafffc22e06975b7ace36300", size = 3518127, upload-time = "2025-08-22T10:37:51.66Z" }, ] [[package]] @@ -4452,38 +4460,38 @@ wheels = [ [[package]] name = "pyzmq" -version = "27.0.1" +version = "27.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "implementation_name == 'pypy'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/30/5f/557d2032a2f471edbcc227da724c24a1c05887b5cda1e3ae53af98b9e0a5/pyzmq-27.0.1.tar.gz", hash = "sha256:45c549204bc20e7484ffd2555f6cf02e572440ecf2f3bdd60d4404b20fddf64b", size = 281158, upload-time = "2025-08-03T05:05:40.352Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/66/159f38d184f08b5f971b467f87b1ab142ab1320d5200825c824b32b84b66/pyzmq-27.0.2.tar.gz", hash = "sha256:b398dd713b18de89730447347e96a0240225e154db56e35b6bb8447ffdb07798", size = 281440, upload-time = "2025-08-21T04:23:26.334Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/18/a8e0da6ababbe9326116fb1c890bf1920eea880e8da621afb6bc0f39a262/pyzmq-27.0.1-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:9729190bd770314f5fbba42476abf6abe79a746eeda11d1d68fd56dd70e5c296", size = 1332721, upload-time = "2025-08-03T05:03:15.237Z" }, - { url = "https://files.pythonhosted.org/packages/75/a4/9431ba598651d60ebd50dc25755402b770322cf8432adcc07d2906e53a54/pyzmq-27.0.1-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:696900ef6bc20bef6a242973943574f96c3f97d2183c1bd3da5eea4f559631b1", size = 908249, upload-time = "2025-08-03T05:03:16.933Z" }, - { url = "https://files.pythonhosted.org/packages/f0/7a/e624e1793689e4e685d2ee21c40277dd4024d9d730af20446d88f69be838/pyzmq-27.0.1-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f96a63aecec22d3f7fdea3c6c98df9e42973f5856bb6812c3d8d78c262fee808", size = 668649, upload-time = "2025-08-03T05:03:18.49Z" }, - { url = "https://files.pythonhosted.org/packages/6c/29/0652a39d4e876e0d61379047ecf7752685414ad2e253434348246f7a2a39/pyzmq-27.0.1-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c512824360ea7490390566ce00bee880e19b526b312b25cc0bc30a0fe95cb67f", size = 856601, upload-time = "2025-08-03T05:03:20.194Z" }, - { url = "https://files.pythonhosted.org/packages/36/2d/8d5355d7fc55bb6e9c581dd74f58b64fa78c994079e3a0ea09b1b5627cde/pyzmq-27.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dfb2bb5e0f7198eaacfb6796fb0330afd28f36d985a770745fba554a5903595a", size = 1657750, upload-time = "2025-08-03T05:03:22.055Z" }, - { url = "https://files.pythonhosted.org/packages/ab/f4/cd032352d5d252dc6f5ee272a34b59718ba3af1639a8a4ef4654f9535cf5/pyzmq-27.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4f6886c59ba93ffde09b957d3e857e7950c8fe818bd5494d9b4287bc6d5bc7f1", size = 2034312, upload-time = "2025-08-03T05:03:23.578Z" }, - { url = "https://files.pythonhosted.org/packages/e4/1a/c050d8b6597200e97a4bd29b93c769d002fa0b03083858227e0376ad59bc/pyzmq-27.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b99ea9d330e86ce1ff7f2456b33f1bf81c43862a5590faf4ef4ed3a63504bdab", size = 1893632, upload-time = "2025-08-03T05:03:25.167Z" }, - { url = "https://files.pythonhosted.org/packages/6a/29/173ce21d5097e7fcf284a090e8beb64fc683c6582b1f00fa52b1b7e867ce/pyzmq-27.0.1-cp311-cp311-win32.whl", hash = "sha256:571f762aed89025ba8cdcbe355fea56889715ec06d0264fd8b6a3f3fa38154ed", size = 566587, upload-time = "2025-08-03T05:03:26.769Z" }, - { url = "https://files.pythonhosted.org/packages/53/ab/22bd33e7086f0a2cc03a5adabff4bde414288bb62a21a7820951ef86ec20/pyzmq-27.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:ee16906c8025fa464bea1e48128c048d02359fb40bebe5333103228528506530", size = 632873, upload-time = "2025-08-03T05:03:28.685Z" }, - { url = "https://files.pythonhosted.org/packages/90/14/3e59b4a28194285ceeff725eba9aa5ba8568d1cb78aed381dec1537c705a/pyzmq-27.0.1-cp311-cp311-win_arm64.whl", hash = "sha256:ba068f28028849da725ff9185c24f832ccf9207a40f9b28ac46ab7c04994bd41", size = 558918, upload-time = "2025-08-03T05:03:30.085Z" }, - { url = "https://files.pythonhosted.org/packages/0e/9b/c0957041067c7724b310f22c398be46399297c12ed834c3bc42200a2756f/pyzmq-27.0.1-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:af7ebce2a1e7caf30c0bb64a845f63a69e76a2fadbc1cac47178f7bb6e657bdd", size = 1305432, upload-time = "2025-08-03T05:03:32.177Z" }, - { url = "https://files.pythonhosted.org/packages/8e/55/bd3a312790858f16b7def3897a0c3eb1804e974711bf7b9dcb5f47e7f82c/pyzmq-27.0.1-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:8f617f60a8b609a13099b313e7e525e67f84ef4524b6acad396d9ff153f6e4cd", size = 895095, upload-time = "2025-08-03T05:03:33.918Z" }, - { url = "https://files.pythonhosted.org/packages/20/50/fc384631d8282809fb1029a4460d2fe90fa0370a0e866a8318ed75c8d3bb/pyzmq-27.0.1-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d59dad4173dc2a111f03e59315c7bd6e73da1a9d20a84a25cf08325b0582b1a", size = 651826, upload-time = "2025-08-03T05:03:35.818Z" }, - { url = "https://files.pythonhosted.org/packages/7e/0a/2356305c423a975000867de56888b79e44ec2192c690ff93c3109fd78081/pyzmq-27.0.1-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f5b6133c8d313bde8bd0d123c169d22525300ff164c2189f849de495e1344577", size = 839751, upload-time = "2025-08-03T05:03:37.265Z" }, - { url = "https://files.pythonhosted.org/packages/d7/1b/81e95ad256ca7e7ccd47f5294c1c6da6e2b64fbace65b84fe8a41470342e/pyzmq-27.0.1-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:58cca552567423f04d06a075f4b473e78ab5bdb906febe56bf4797633f54aa4e", size = 1641359, upload-time = "2025-08-03T05:03:38.799Z" }, - { url = "https://files.pythonhosted.org/packages/50/63/9f50ec965285f4e92c265c8f18344e46b12803666d8b73b65d254d441435/pyzmq-27.0.1-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:4b9d8e26fb600d0d69cc9933e20af08552e97cc868a183d38a5c0d661e40dfbb", size = 2020281, upload-time = "2025-08-03T05:03:40.338Z" }, - { url = "https://files.pythonhosted.org/packages/02/4a/19e3398d0dc66ad2b463e4afa1fc541d697d7bc090305f9dfb948d3dfa29/pyzmq-27.0.1-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2329f0c87f0466dce45bba32b63f47018dda5ca40a0085cc5c8558fea7d9fc55", size = 1877112, upload-time = "2025-08-03T05:03:42.012Z" }, - { url = "https://files.pythonhosted.org/packages/bf/42/c562e9151aa90ed1d70aac381ea22a929d6b3a2ce4e1d6e2e135d34fd9c6/pyzmq-27.0.1-cp312-abi3-win32.whl", hash = "sha256:57bb92abdb48467b89c2d21da1ab01a07d0745e536d62afd2e30d5acbd0092eb", size = 558177, upload-time = "2025-08-03T05:03:43.979Z" }, - { url = "https://files.pythonhosted.org/packages/40/96/5c50a7d2d2b05b19994bf7336b97db254299353dd9b49b565bb71b485f03/pyzmq-27.0.1-cp312-abi3-win_amd64.whl", hash = "sha256:ff3f8757570e45da7a5bedaa140489846510014f7a9d5ee9301c61f3f1b8a686", size = 618923, upload-time = "2025-08-03T05:03:45.438Z" }, - { url = "https://files.pythonhosted.org/packages/13/33/1ec89c8f21c89d21a2eaff7def3676e21d8248d2675705e72554fb5a6f3f/pyzmq-27.0.1-cp312-abi3-win_arm64.whl", hash = "sha256:df2c55c958d3766bdb3e9d858b911288acec09a9aab15883f384fc7180df5bed", size = 552358, upload-time = "2025-08-03T05:03:46.887Z" }, - { url = "https://files.pythonhosted.org/packages/b4/1a/49f66fe0bc2b2568dd4280f1f520ac8fafd73f8d762140e278d48aeaf7b9/pyzmq-27.0.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7fb0ee35845bef1e8c4a152d766242164e138c239e3182f558ae15cb4a891f94", size = 835949, upload-time = "2025-08-03T05:05:13.798Z" }, - { url = "https://files.pythonhosted.org/packages/49/94/443c1984b397eab59b14dd7ae8bc2ac7e8f32dbc646474453afcaa6508c4/pyzmq-27.0.1-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:f379f11e138dfd56c3f24a04164f871a08281194dd9ddf656a278d7d080c8ad0", size = 799875, upload-time = "2025-08-03T05:05:15.632Z" }, - { url = "https://files.pythonhosted.org/packages/30/f1/fd96138a0f152786a2ba517e9c6a8b1b3516719e412a90bb5d8eea6b660c/pyzmq-27.0.1-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b978c0678cffbe8860ec9edc91200e895c29ae1ac8a7085f947f8e8864c489fb", size = 567403, upload-time = "2025-08-03T05:05:17.326Z" }, - { url = "https://files.pythonhosted.org/packages/16/57/34e53ef2b55b1428dac5aabe3a974a16c8bda3bf20549ba500e3ff6cb426/pyzmq-27.0.1-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7ebccf0d760bc92a4a7c751aeb2fef6626144aace76ee8f5a63abeb100cae87f", size = 747032, upload-time = "2025-08-03T05:05:19.074Z" }, - { url = "https://files.pythonhosted.org/packages/81/b7/769598c5ae336fdb657946950465569cf18803140fe89ce466d7f0a57c11/pyzmq-27.0.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:77fed80e30fa65708546c4119840a46691290efc231f6bfb2ac2a39b52e15811", size = 544566, upload-time = "2025-08-03T05:05:20.798Z" }, + { url = "https://files.pythonhosted.org/packages/42/73/034429ab0f4316bf433eb6c20c3f49d1dc13b2ed4e4d951b283d300a0f35/pyzmq-27.0.2-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:063845960df76599ad4fad69fa4d884b3ba38304272104fdcd7e3af33faeeb1d", size = 1333169, upload-time = "2025-08-21T04:21:12.483Z" }, + { url = "https://files.pythonhosted.org/packages/35/02/c42b3b526eb03a570c889eea85a5602797f800a50ba8b09ddbf7db568b78/pyzmq-27.0.2-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:845a35fb21b88786aeb38af8b271d41ab0967985410f35411a27eebdc578a076", size = 909176, upload-time = "2025-08-21T04:21:13.835Z" }, + { url = "https://files.pythonhosted.org/packages/1b/35/a1c0b988fabbdf2dc5fe94b7c2bcfd61e3533e5109297b8e0daf1d7a8d2d/pyzmq-27.0.2-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:515d20b5c3c86db95503faa989853a8ab692aab1e5336db011cd6d35626c4cb1", size = 668972, upload-time = "2025-08-21T04:21:15.315Z" }, + { url = "https://files.pythonhosted.org/packages/a0/63/908ac865da32ceaeecea72adceadad28ca25b23a2ca5ff018e5bff30116f/pyzmq-27.0.2-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:862aedec0b0684a5050cdb5ec13c2da96d2f8dffda48657ed35e312a4e31553b", size = 856962, upload-time = "2025-08-21T04:21:16.652Z" }, + { url = "https://files.pythonhosted.org/packages/2f/5a/90b3cc20b65cdf9391896fcfc15d8db21182eab810b7ea05a2986912fbe2/pyzmq-27.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2cb5bcfc51c7a4fce335d3bc974fd1d6a916abbcdd2b25f6e89d37b8def25f57", size = 1657712, upload-time = "2025-08-21T04:21:18.666Z" }, + { url = "https://files.pythonhosted.org/packages/c4/3c/32a5a80f9be4759325b8d7b22ce674bb87e586b4c80c6a9d77598b60d6f0/pyzmq-27.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:38ff75b2a36e3a032e9fef29a5871e3e1301a37464e09ba364e3c3193f62982a", size = 2035054, upload-time = "2025-08-21T04:21:20.073Z" }, + { url = "https://files.pythonhosted.org/packages/13/61/71084fe2ff2d7dc5713f8740d735336e87544845dae1207a8e2e16d9af90/pyzmq-27.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7a5709abe8d23ca158a9d0a18c037f4193f5b6afeb53be37173a41e9fb885792", size = 1894010, upload-time = "2025-08-21T04:21:21.96Z" }, + { url = "https://files.pythonhosted.org/packages/cb/6b/77169cfb13b696e50112ca496b2ed23c4b7d8860a1ec0ff3e4b9f9926221/pyzmq-27.0.2-cp311-cp311-win32.whl", hash = "sha256:47c5dda2018c35d87be9b83de0890cb92ac0791fd59498847fc4eca6ff56671d", size = 566819, upload-time = "2025-08-21T04:21:23.31Z" }, + { url = "https://files.pythonhosted.org/packages/37/cd/86c4083e0f811f48f11bc0ddf1e7d13ef37adfd2fd4f78f2445f1cc5dec0/pyzmq-27.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:f54ca3e98f8f4d23e989c7d0edcf9da7a514ff261edaf64d1d8653dd5feb0a8b", size = 633264, upload-time = "2025-08-21T04:21:24.761Z" }, + { url = "https://files.pythonhosted.org/packages/a0/69/5b8bb6a19a36a569fac02153a9e083738785892636270f5f68a915956aea/pyzmq-27.0.2-cp311-cp311-win_arm64.whl", hash = "sha256:2ef3067cb5b51b090fb853f423ad7ed63836ec154374282780a62eb866bf5768", size = 559316, upload-time = "2025-08-21T04:21:26.1Z" }, + { url = "https://files.pythonhosted.org/packages/68/69/b3a729e7b03e412bee2b1823ab8d22e20a92593634f664afd04c6c9d9ac0/pyzmq-27.0.2-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:5da05e3c22c95e23bfc4afeee6ff7d4be9ff2233ad6cb171a0e8257cd46b169a", size = 1305910, upload-time = "2025-08-21T04:21:27.609Z" }, + { url = "https://files.pythonhosted.org/packages/15/b7/f6a6a285193d489b223c340b38ee03a673467cb54914da21c3d7849f1b10/pyzmq-27.0.2-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4e4520577971d01d47e2559bb3175fce1be9103b18621bf0b241abe0a933d040", size = 895507, upload-time = "2025-08-21T04:21:29.005Z" }, + { url = "https://files.pythonhosted.org/packages/17/e6/c4ed2da5ef9182cde1b1f5d0051a986e76339d71720ec1a00be0b49275ad/pyzmq-27.0.2-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56d7de7bf73165b90bd25a8668659ccb134dd28449116bf3c7e9bab5cf8a8ec9", size = 652670, upload-time = "2025-08-21T04:21:30.71Z" }, + { url = "https://files.pythonhosted.org/packages/0e/66/d781ab0636570d32c745c4e389b1c6b713115905cca69ab6233508622edd/pyzmq-27.0.2-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:340e7cddc32f147c6c00d116a3f284ab07ee63dbd26c52be13b590520434533c", size = 840581, upload-time = "2025-08-21T04:21:32.008Z" }, + { url = "https://files.pythonhosted.org/packages/a6/df/f24790caf565d72544f5c8d8500960b9562c1dc848d6f22f3c7e122e73d4/pyzmq-27.0.2-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ba95693f9df8bb4a9826464fb0fe89033936f35fd4a8ff1edff09a473570afa0", size = 1641931, upload-time = "2025-08-21T04:21:33.371Z" }, + { url = "https://files.pythonhosted.org/packages/65/65/77d27b19fc5e845367f9100db90b9fce924f611b14770db480615944c9c9/pyzmq-27.0.2-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:ca42a6ce2d697537da34f77a1960d21476c6a4af3e539eddb2b114c3cf65a78c", size = 2021226, upload-time = "2025-08-21T04:21:35.301Z" }, + { url = "https://files.pythonhosted.org/packages/5b/65/1ed14421ba27a4207fa694772003a311d1142b7f543179e4d1099b7eb746/pyzmq-27.0.2-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3e44e665d78a07214b2772ccbd4b9bcc6d848d7895f1b2d7653f047b6318a4f6", size = 1878047, upload-time = "2025-08-21T04:21:36.749Z" }, + { url = "https://files.pythonhosted.org/packages/dd/dc/e578549b89b40dc78a387ec471c2a360766690c0a045cd8d1877d401012d/pyzmq-27.0.2-cp312-abi3-win32.whl", hash = "sha256:272d772d116615397d2be2b1417b3b8c8bc8671f93728c2f2c25002a4530e8f6", size = 558757, upload-time = "2025-08-21T04:21:38.2Z" }, + { url = "https://files.pythonhosted.org/packages/b5/89/06600980aefcc535c758414da969f37a5194ea4cdb73b745223f6af3acfb/pyzmq-27.0.2-cp312-abi3-win_amd64.whl", hash = "sha256:734be4f44efba0aa69bf5f015ed13eb69ff29bf0d17ea1e21588b095a3147b8e", size = 619281, upload-time = "2025-08-21T04:21:39.909Z" }, + { url = "https://files.pythonhosted.org/packages/30/84/df8a5c089552d17c9941d1aea4314b606edf1b1622361dae89aacedc6467/pyzmq-27.0.2-cp312-abi3-win_arm64.whl", hash = "sha256:41f0bd56d9279392810950feb2785a419c2920bbf007fdaaa7f4a07332ae492d", size = 552680, upload-time = "2025-08-21T04:21:41.571Z" }, + { url = "https://files.pythonhosted.org/packages/c7/60/027d0032a1e3b1aabcef0e309b9ff8a4099bdd5a60ab38b36a676ff2bd7b/pyzmq-27.0.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:e297784aea724294fe95e442e39a4376c2f08aa4fae4161c669f047051e31b02", size = 836007, upload-time = "2025-08-21T04:23:00.447Z" }, + { url = "https://files.pythonhosted.org/packages/25/20/2ed1e6168aaea323df9bb2c451309291f53ba3af372ffc16edd4ce15b9e5/pyzmq-27.0.2-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:e3659a79ded9745bc9c2aef5b444ac8805606e7bc50d2d2eb16dc3ab5483d91f", size = 799932, upload-time = "2025-08-21T04:23:02.052Z" }, + { url = "https://files.pythonhosted.org/packages/fd/25/5c147307de546b502c9373688ce5b25dc22288d23a1ebebe5d587bf77610/pyzmq-27.0.2-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3dba49ff037d02373a9306b58d6c1e0be031438f822044e8767afccfdac4c6b", size = 567459, upload-time = "2025-08-21T04:23:03.593Z" }, + { url = "https://files.pythonhosted.org/packages/71/06/0dc56ffc615c8095cd089c9b98ce5c733e990f09ce4e8eea4aaf1041a532/pyzmq-27.0.2-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de84e1694f9507b29e7b263453a2255a73e3d099d258db0f14539bad258abe41", size = 747088, upload-time = "2025-08-21T04:23:05.334Z" }, + { url = "https://files.pythonhosted.org/packages/06/f6/4a50187e023b8848edd3f0a8e197b1a7fb08d261d8c60aae7cb6c3d71612/pyzmq-27.0.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f0944d65ba2b872b9fcece08411d6347f15a874c775b4c3baae7f278550da0fb", size = 544639, upload-time = "2025-08-21T04:23:07.279Z" }, ] [[package]] @@ -4524,7 +4532,7 @@ wheels = [ [[package]] name = "requests" -version = "2.32.4" +version = "2.32.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -4532,21 +4540,21 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, ] [[package]] name = "ruamel-yaml" -version = "0.18.14" +version = "0.18.15" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "ruamel-yaml-clib", marker = "platform_python_implementation == 'CPython'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/39/87/6da0df742a4684263261c253f00edd5829e6aca970fff69e75028cccc547/ruamel.yaml-0.18.14.tar.gz", hash = "sha256:7227b76aaec364df15936730efbf7d72b30c0b79b1d578bbb8e3dcb2d81f52b7", size = 145511, upload-time = "2025-06-09T08:51:09.828Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3e/db/f3950f5e5031b618aae9f423a39bf81a55c148aecd15a34527898e752cf4/ruamel.yaml-0.18.15.tar.gz", hash = "sha256:dbfca74b018c4c3fba0b9cc9ee33e53c371194a9000e694995e620490fd40700", size = 146865, upload-time = "2025-08-19T11:15:10.694Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/af/6d/6fe4805235e193aad4aaf979160dd1f3c487c57d48b810c816e6e842171b/ruamel.yaml-0.18.14-py3-none-any.whl", hash = "sha256:710ff198bb53da66718c7db27eec4fbcc9aa6ca7204e4c1df2f282b6fe5eb6b2", size = 118570, upload-time = "2025-06-09T08:51:06.348Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e5/f2a0621f1781b76a38194acae72f01e37b1941470407345b6e8653ad7640/ruamel.yaml-0.18.15-py3-none-any.whl", hash = "sha256:148f6488d698b7a5eded5ea793a025308b25eca97208181b6a026037f391f701", size = 119702, upload-time = "2025-08-19T11:15:07.696Z" }, ] [[package]] @@ -4586,28 +4594,28 @@ wheels = [ [[package]] name = "ruff" -version = "0.12.9" +version = "0.12.10" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4a/45/2e403fa7007816b5fbb324cb4f8ed3c7402a927a0a0cb2b6279879a8bfdc/ruff-0.12.9.tar.gz", hash = "sha256:fbd94b2e3c623f659962934e52c2bea6fc6da11f667a427a368adaf3af2c866a", size = 5254702, upload-time = "2025-08-14T16:08:55.2Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/eb/8c073deb376e46ae767f4961390d17545e8535921d2f65101720ed8bd434/ruff-0.12.10.tar.gz", hash = "sha256:189ab65149d11ea69a2d775343adf5f49bb2426fc4780f65ee33b423ad2e47f9", size = 5310076, upload-time = "2025-08-21T18:23:22.595Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ad/20/53bf098537adb7b6a97d98fcdebf6e916fcd11b2e21d15f8c171507909cc/ruff-0.12.9-py3-none-linux_armv6l.whl", hash = "sha256:fcebc6c79fcae3f220d05585229463621f5dbf24d79fdc4936d9302e177cfa3e", size = 11759705, upload-time = "2025-08-14T16:08:12.968Z" }, - { url = "https://files.pythonhosted.org/packages/20/4d/c764ee423002aac1ec66b9d541285dd29d2c0640a8086c87de59ebbe80d5/ruff-0.12.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aed9d15f8c5755c0e74467731a007fcad41f19bcce41cd75f768bbd687f8535f", size = 12527042, upload-time = "2025-08-14T16:08:16.54Z" }, - { url = "https://files.pythonhosted.org/packages/8b/45/cfcdf6d3eb5fc78a5b419e7e616d6ccba0013dc5b180522920af2897e1be/ruff-0.12.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5b15ea354c6ff0d7423814ba6d44be2807644d0c05e9ed60caca87e963e93f70", size = 11724457, upload-time = "2025-08-14T16:08:18.686Z" }, - { url = "https://files.pythonhosted.org/packages/72/e6/44615c754b55662200c48bebb02196dbb14111b6e266ab071b7e7297b4ec/ruff-0.12.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d596c2d0393c2502eaabfef723bd74ca35348a8dac4267d18a94910087807c53", size = 11949446, upload-time = "2025-08-14T16:08:21.059Z" }, - { url = "https://files.pythonhosted.org/packages/fd/d1/9b7d46625d617c7df520d40d5ac6cdcdf20cbccb88fad4b5ecd476a6bb8d/ruff-0.12.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1b15599931a1a7a03c388b9c5df1bfa62be7ede6eb7ef753b272381f39c3d0ff", size = 11566350, upload-time = "2025-08-14T16:08:23.433Z" }, - { url = "https://files.pythonhosted.org/packages/59/20/b73132f66f2856bc29d2d263c6ca457f8476b0bbbe064dac3ac3337a270f/ruff-0.12.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3d02faa2977fb6f3f32ddb7828e212b7dd499c59eb896ae6c03ea5c303575756", size = 13270430, upload-time = "2025-08-14T16:08:25.837Z" }, - { url = "https://files.pythonhosted.org/packages/a2/21/eaf3806f0a3d4c6be0a69d435646fba775b65f3f2097d54898b0fd4bb12e/ruff-0.12.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:17d5b6b0b3a25259b69ebcba87908496e6830e03acfb929ef9fd4c58675fa2ea", size = 14264717, upload-time = "2025-08-14T16:08:27.907Z" }, - { url = "https://files.pythonhosted.org/packages/d2/82/1d0c53bd37dcb582b2c521d352fbf4876b1e28bc0d8894344198f6c9950d/ruff-0.12.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:72db7521860e246adbb43f6ef464dd2a532ef2ef1f5dd0d470455b8d9f1773e0", size = 13684331, upload-time = "2025-08-14T16:08:30.352Z" }, - { url = "https://files.pythonhosted.org/packages/3b/2f/1c5cf6d8f656306d42a686f1e207f71d7cebdcbe7b2aa18e4e8a0cb74da3/ruff-0.12.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a03242c1522b4e0885af63320ad754d53983c9599157ee33e77d748363c561ce", size = 12739151, upload-time = "2025-08-14T16:08:32.55Z" }, - { url = "https://files.pythonhosted.org/packages/47/09/25033198bff89b24d734e6479e39b1968e4c992e82262d61cdccaf11afb9/ruff-0.12.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fc83e4e9751e6c13b5046d7162f205d0a7bac5840183c5beebf824b08a27340", size = 12954992, upload-time = "2025-08-14T16:08:34.816Z" }, - { url = "https://files.pythonhosted.org/packages/52/8e/d0dbf2f9dca66c2d7131feefc386523404014968cd6d22f057763935ab32/ruff-0.12.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:881465ed56ba4dd26a691954650de6ad389a2d1fdb130fe51ff18a25639fe4bb", size = 12899569, upload-time = "2025-08-14T16:08:36.852Z" }, - { url = "https://files.pythonhosted.org/packages/a0/bd/b614d7c08515b1428ed4d3f1d4e3d687deffb2479703b90237682586fa66/ruff-0.12.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:43f07a3ccfc62cdb4d3a3348bf0588358a66da756aa113e071b8ca8c3b9826af", size = 11751983, upload-time = "2025-08-14T16:08:39.314Z" }, - { url = "https://files.pythonhosted.org/packages/58/d6/383e9f818a2441b1a0ed898d7875f11273f10882f997388b2b51cb2ae8b5/ruff-0.12.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:07adb221c54b6bba24387911e5734357f042e5669fa5718920ee728aba3cbadc", size = 11538635, upload-time = "2025-08-14T16:08:41.297Z" }, - { url = "https://files.pythonhosted.org/packages/20/9c/56f869d314edaa9fc1f491706d1d8a47747b9d714130368fbd69ce9024e9/ruff-0.12.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f5cd34fabfdea3933ab85d72359f118035882a01bff15bd1d2b15261d85d5f66", size = 12534346, upload-time = "2025-08-14T16:08:43.39Z" }, - { url = "https://files.pythonhosted.org/packages/bd/4b/d8b95c6795a6c93b439bc913ee7a94fda42bb30a79285d47b80074003ee7/ruff-0.12.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f6be1d2ca0686c54564da8e7ee9e25f93bdd6868263805f8c0b8fc6a449db6d7", size = 13017021, upload-time = "2025-08-14T16:08:45.889Z" }, - { url = "https://files.pythonhosted.org/packages/c7/c1/5f9a839a697ce1acd7af44836f7c2181cdae5accd17a5cb85fcbd694075e/ruff-0.12.9-py3-none-win32.whl", hash = "sha256:cc7a37bd2509974379d0115cc5608a1a4a6c4bff1b452ea69db83c8855d53f93", size = 11734785, upload-time = "2025-08-14T16:08:48.062Z" }, - { url = "https://files.pythonhosted.org/packages/fa/66/cdddc2d1d9a9f677520b7cfc490d234336f523d4b429c1298de359a3be08/ruff-0.12.9-py3-none-win_amd64.whl", hash = "sha256:6fb15b1977309741d7d098c8a3cb7a30bc112760a00fb6efb7abc85f00ba5908", size = 12840654, upload-time = "2025-08-14T16:08:50.158Z" }, - { url = "https://files.pythonhosted.org/packages/ac/fd/669816bc6b5b93b9586f3c1d87cd6bc05028470b3ecfebb5938252c47a35/ruff-0.12.9-py3-none-win_arm64.whl", hash = "sha256:63c8c819739d86b96d500cce885956a1a48ab056bbcbc61b747ad494b2485089", size = 11949623, upload-time = "2025-08-14T16:08:52.233Z" }, + { url = "https://files.pythonhosted.org/packages/24/e7/560d049d15585d6c201f9eeacd2fd130def3741323e5ccf123786e0e3c95/ruff-0.12.10-py3-none-linux_armv6l.whl", hash = "sha256:8b593cb0fb55cc8692dac7b06deb29afda78c721c7ccfed22db941201b7b8f7b", size = 11935161, upload-time = "2025-08-21T18:22:26.965Z" }, + { url = "https://files.pythonhosted.org/packages/d1/b0/ad2464922a1113c365d12b8f80ed70fcfb39764288ac77c995156080488d/ruff-0.12.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ebb7333a45d56efc7c110a46a69a1b32365d5c5161e7244aaf3aa20ce62399c1", size = 12660884, upload-time = "2025-08-21T18:22:30.925Z" }, + { url = "https://files.pythonhosted.org/packages/d7/f1/97f509b4108d7bae16c48389f54f005b62ce86712120fd8b2d8e88a7cb49/ruff-0.12.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d59e58586829f8e4a9920788f6efba97a13d1fa320b047814e8afede381c6839", size = 11872754, upload-time = "2025-08-21T18:22:34.035Z" }, + { url = "https://files.pythonhosted.org/packages/12/ad/44f606d243f744a75adc432275217296095101f83f966842063d78eee2d3/ruff-0.12.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:822d9677b560f1fdeab69b89d1f444bf5459da4aa04e06e766cf0121771ab844", size = 12092276, upload-time = "2025-08-21T18:22:36.764Z" }, + { url = "https://files.pythonhosted.org/packages/06/1f/ed6c265e199568010197909b25c896d66e4ef2c5e1c3808caf461f6f3579/ruff-0.12.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:37b4a64f4062a50c75019c61c7017ff598cb444984b638511f48539d3a1c98db", size = 11734700, upload-time = "2025-08-21T18:22:39.822Z" }, + { url = "https://files.pythonhosted.org/packages/63/c5/b21cde720f54a1d1db71538c0bc9b73dee4b563a7dd7d2e404914904d7f5/ruff-0.12.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c6f4064c69d2542029b2a61d39920c85240c39837599d7f2e32e80d36401d6e", size = 13468783, upload-time = "2025-08-21T18:22:42.559Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/39369e6ac7f2a1848f22fb0b00b690492f20811a1ac5c1fd1d2798329263/ruff-0.12.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:059e863ea3a9ade41407ad71c1de2badfbe01539117f38f763ba42a1206f7559", size = 14436642, upload-time = "2025-08-21T18:22:45.612Z" }, + { url = "https://files.pythonhosted.org/packages/e3/03/5da8cad4b0d5242a936eb203b58318016db44f5c5d351b07e3f5e211bb89/ruff-0.12.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1bef6161e297c68908b7218fa6e0e93e99a286e5ed9653d4be71e687dff101cf", size = 13859107, upload-time = "2025-08-21T18:22:48.886Z" }, + { url = "https://files.pythonhosted.org/packages/19/19/dd7273b69bf7f93a070c9cec9494a94048325ad18fdcf50114f07e6bf417/ruff-0.12.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4f1345fbf8fb0531cd722285b5f15af49b2932742fc96b633e883da8d841896b", size = 12886521, upload-time = "2025-08-21T18:22:51.567Z" }, + { url = "https://files.pythonhosted.org/packages/c0/1d/b4207ec35e7babaee62c462769e77457e26eb853fbdc877af29417033333/ruff-0.12.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f68433c4fbc63efbfa3ba5db31727db229fa4e61000f452c540474b03de52a9", size = 13097528, upload-time = "2025-08-21T18:22:54.609Z" }, + { url = "https://files.pythonhosted.org/packages/ff/00/58f7b873b21114456e880b75176af3490d7a2836033779ca42f50de3b47a/ruff-0.12.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:141ce3d88803c625257b8a6debf4a0473eb6eed9643a6189b68838b43e78165a", size = 13080443, upload-time = "2025-08-21T18:22:57.413Z" }, + { url = "https://files.pythonhosted.org/packages/12/8c/9e6660007fb10189ccb78a02b41691288038e51e4788bf49b0a60f740604/ruff-0.12.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f3fc21178cd44c98142ae7590f42ddcb587b8e09a3b849cbc84edb62ee95de60", size = 11896759, upload-time = "2025-08-21T18:23:00.473Z" }, + { url = "https://files.pythonhosted.org/packages/67/4c/6d092bb99ea9ea6ebda817a0e7ad886f42a58b4501a7e27cd97371d0ba54/ruff-0.12.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7d1a4e0bdfafcd2e3e235ecf50bf0176f74dd37902f241588ae1f6c827a36c56", size = 11701463, upload-time = "2025-08-21T18:23:03.211Z" }, + { url = "https://files.pythonhosted.org/packages/59/80/d982c55e91df981f3ab62559371380616c57ffd0172d96850280c2b04fa8/ruff-0.12.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:e67d96827854f50b9e3e8327b031647e7bcc090dbe7bb11101a81a3a2cbf1cc9", size = 12691603, upload-time = "2025-08-21T18:23:06.935Z" }, + { url = "https://files.pythonhosted.org/packages/ad/37/63a9c788bbe0b0850611669ec6b8589838faf2f4f959647f2d3e320383ae/ruff-0.12.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ae479e1a18b439c59138f066ae79cc0f3ee250712a873d00dbafadaad9481e5b", size = 13164356, upload-time = "2025-08-21T18:23:10.225Z" }, + { url = "https://files.pythonhosted.org/packages/47/d4/1aaa7fb201a74181989970ebccd12f88c0fc074777027e2a21de5a90657e/ruff-0.12.10-py3-none-win32.whl", hash = "sha256:9de785e95dc2f09846c5e6e1d3a3d32ecd0b283a979898ad427a9be7be22b266", size = 11896089, upload-time = "2025-08-21T18:23:14.232Z" }, + { url = "https://files.pythonhosted.org/packages/ad/14/2ad38fd4037daab9e023456a4a40ed0154e9971f8d6aed41bdea390aabd9/ruff-0.12.10-py3-none-win_amd64.whl", hash = "sha256:7837eca8787f076f67aba2ca559cefd9c5cbc3a9852fd66186f4201b87c1563e", size = 13004616, upload-time = "2025-08-21T18:23:17.422Z" }, + { url = "https://files.pythonhosted.org/packages/24/3c/21cf283d67af33a8e6ed242396863af195a8a6134ec581524fd22b9811b6/ruff-0.12.10-py3-none-win_arm64.whl", hash = "sha256:cc138cc06ed9d4bfa9d667a65af7172b47840e1a98b02ce7011c391e54635ffc", size = 12074225, upload-time = "2025-08-21T18:23:20.137Z" }, ] [[package]] @@ -4824,11 +4832,11 @@ wheels = [ [[package]] name = "typing-extensions" -version = "4.14.1" +version = "4.15.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" }, + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, ] [[package]] From 1d74a97ba65b9b9ea074ef870ab70907be33918c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harald=20Sch=C3=A4fer?= Date: Mon, 25 Aug 2025 13:50:10 -0700 Subject: [PATCH 003/159] torqued: apply offset (#36005) * torqued: apply latAccelOffset to torque control feed forward * test learned latAccelOffset captures roll compensation bias on straight road driving, when the device is not flush in roll relative to the car * test correct torqued latAccelOffset parameter convergence --------- Co-authored-by: felsager --- selfdrive/controls/lib/latcontrol_torque.py | 6 +- .../tests/test_torqued_lat_accel_offset.py | 71 +++++++++++++++++++ selfdrive/test/process_replay/ref_commit | 2 +- 3 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 selfdrive/controls/tests/test_torqued_lat_accel_offset.py diff --git a/selfdrive/controls/lib/latcontrol_torque.py b/selfdrive/controls/lib/latcontrol_torque.py index dffe85c473..5a2814e089 100644 --- a/selfdrive/controls/lib/latcontrol_torque.py +++ b/selfdrive/controls/lib/latcontrol_torque.py @@ -52,10 +52,8 @@ class LatControlTorque(LatControl): actual_curvature = -VM.calc_curvature(math.radians(CS.steeringAngleDeg - params.angleOffsetDeg), CS.vEgo, params.roll) roll_compensation = params.roll * ACCELERATION_DUE_TO_GRAVITY curvature_deadzone = abs(VM.calc_curvature(math.radians(self.steering_angle_deadzone_deg), CS.vEgo, 0.0)) - desired_lateral_accel = desired_curvature * CS.vEgo ** 2 - # desired rate is the desired rate of change in the setpoint, not the absolute desired curvature - # desired_lateral_jerk = desired_curvature_rate * CS.vEgo ** 2 + desired_lateral_accel = desired_curvature * CS.vEgo ** 2 actual_lateral_accel = actual_curvature * CS.vEgo ** 2 lateral_accel_deadzone = curvature_deadzone * CS.vEgo ** 2 @@ -67,6 +65,8 @@ class LatControlTorque(LatControl): # do error correction in lateral acceleration space, convert at end to handle non-linear torque responses correctly pid_log.error = float(setpoint - measurement) ff = gravity_adjusted_lateral_accel + # latAccelOffset corrects roll compensation bias from device roll misalignment relative to car roll + ff -= self.torque_params.latAccelOffset ff += get_friction(desired_lateral_accel - actual_lateral_accel, lateral_accel_deadzone, FRICTION_THRESHOLD, self.torque_params) freeze_integrator = steer_limited_by_safety or CS.steeringPressed or CS.vEgo < 5 diff --git a/selfdrive/controls/tests/test_torqued_lat_accel_offset.py b/selfdrive/controls/tests/test_torqued_lat_accel_offset.py new file mode 100644 index 0000000000..5ba9980020 --- /dev/null +++ b/selfdrive/controls/tests/test_torqued_lat_accel_offset.py @@ -0,0 +1,71 @@ +import numpy as np +from cereal import car, messaging +from opendbc.car import ACCELERATION_DUE_TO_GRAVITY +from opendbc.car import structs +from opendbc.car.lateral import get_friction, FRICTION_THRESHOLD +from openpilot.common.realtime import DT_MDL +from openpilot.selfdrive.locationd.torqued import TorqueEstimator, MIN_BUCKET_POINTS, POINTS_PER_BUCKET, STEER_BUCKET_BOUNDS + +np.random.seed(0) + +LA_ERR_STD = 1.0 +INPUT_NOISE_STD = 0.1 +V_EGO = 30.0 + +WARMUP_BUCKET_POINTS = (1.5*MIN_BUCKET_POINTS).astype(int) +STRAIGHT_ROAD_LA_BOUNDS = (0.02, 0.03) + +ROLL_BIAS_DEG = 1.0 +ROLL_COMPENSATION_BIAS = ACCELERATION_DUE_TO_GRAVITY*float(np.sin(np.deg2rad(ROLL_BIAS_DEG))) +TORQUE_TUNE = structs.CarParams.LateralTorqueTuning(latAccelFactor=2.0, latAccelOffset=0.0, friction=0.2) +TORQUE_TUNE_BIASED = structs.CarParams.LateralTorqueTuning(latAccelFactor=2.0, latAccelOffset=-ROLL_COMPENSATION_BIAS, friction=0.2) + + +def generate_inputs(torque_tune, la_err_std, input_noise_std=None): + rng = np.random.default_rng(0) + steer_torques = np.concat([rng.uniform(bnd[0], bnd[1], pts) for bnd, pts in zip(STEER_BUCKET_BOUNDS, WARMUP_BUCKET_POINTS, strict=True)]) + la_errs = rng.normal(scale=la_err_std, size=steer_torques.size) + frictions = np.array([get_friction(la_err, 0.0, FRICTION_THRESHOLD, torque_tune) for la_err in la_errs]) + lat_accels = torque_tune.latAccelFactor*steer_torques + torque_tune.latAccelOffset + frictions + if input_noise_std is not None: + steer_torques += rng.normal(scale=input_noise_std, size=steer_torques.size) + lat_accels += rng.normal(scale=input_noise_std, size=steer_torques.size) + return steer_torques, lat_accels + +def get_warmed_up_estimator(steer_torques, lat_accels): + est = TorqueEstimator(car.CarParams()) + for steer_torque, lat_accel in zip(steer_torques, lat_accels, strict=True): + est.filtered_points.add_point(steer_torque, lat_accel) + return est + +def simulate_straight_road_msgs(est): + carControl = messaging.new_message('carControl').carControl + carOutput = messaging.new_message('carOutput').carOutput + carState = messaging.new_message('carState').carState + livePose = messaging.new_message('livePose').livePose + carControl.latActive = True + carState.vEgo = V_EGO + carState.steeringPressed = False + ts = DT_MDL*np.arange(2*POINTS_PER_BUCKET) + steer_torques = np.concat((np.linspace(-0.03, -0.02, POINTS_PER_BUCKET), np.linspace(0.02, 0.03, POINTS_PER_BUCKET))) + lat_accels = TORQUE_TUNE.latAccelFactor * steer_torques + for t, steer_torque, lat_accel in zip(ts, steer_torques, lat_accels, strict=True): + carOutput.actuatorsOutput.torque = float(-steer_torque) + livePose.orientationNED.x = float(np.deg2rad(ROLL_BIAS_DEG)) + livePose.angularVelocityDevice.z = float(lat_accel / V_EGO) + for which, msg in (('carControl', carControl), ('carOutput', carOutput), ('carState', carState), ('livePose', livePose)): + est.handle_log(t, which, msg) + +def test_estimated_offset(): + steer_torques, lat_accels = generate_inputs(TORQUE_TUNE_BIASED, la_err_std=LA_ERR_STD, input_noise_std=INPUT_NOISE_STD) + est = get_warmed_up_estimator(steer_torques, lat_accels) + msg = est.get_msg() + # TODO add lataccelfactor and friction check when we have more accurate estimates + assert abs(msg.liveTorqueParameters.latAccelOffsetRaw - TORQUE_TUNE_BIASED.latAccelOffset) < 0.03 + +def test_straight_road_roll_bias(): + steer_torques, lat_accels = generate_inputs(TORQUE_TUNE, la_err_std=LA_ERR_STD, input_noise_std=INPUT_NOISE_STD) + est = get_warmed_up_estimator(steer_torques, lat_accels) + simulate_straight_road_msgs(est) + msg = est.get_msg() + assert (msg.liveTorqueParameters.latAccelOffsetRaw < -0.05) and np.isfinite(msg.liveTorqueParameters.latAccelOffsetRaw) diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 8e4ff1e2a8..7d21526144 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -209b47bea61e145cf2d27eb3ab650c97bcd1d33f \ No newline at end of file +866f2cb1f0e49b2cb7115aa8131164b3a75fb2c5 \ No newline at end of file From c4a7f25b626886f9143d0e9bae1eaa37a9083538 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Mon, 25 Aug 2025 15:17:37 -0700 Subject: [PATCH 004/159] raylib: refactor NetworkManager constants (#36056) * new file * import * and this --- system/ui/lib/networkmanager.py | 44 +++++++++++++++++++++++++++++++++ system/ui/lib/wifi_manager.py | 27 ++++---------------- 2 files changed, 49 insertions(+), 22 deletions(-) create mode 100644 system/ui/lib/networkmanager.py diff --git a/system/ui/lib/networkmanager.py b/system/ui/lib/networkmanager.py new file mode 100644 index 0000000000..07b5d42f4b --- /dev/null +++ b/system/ui/lib/networkmanager.py @@ -0,0 +1,44 @@ +from enum import IntEnum + + +# NetworkManager device states +class NMDeviceState(IntEnum): + UNKNOWN = 0 + DISCONNECTED = 30 + PREPARE = 40 + STATE_CONFIG = 50 + NEED_AUTH = 60 + IP_CONFIG = 70 + ACTIVATED = 100 + DEACTIVATING = 110 + + +# NetworkManager constants +NM = "org.freedesktop.NetworkManager" +NM_PATH = '/org/freedesktop/NetworkManager' +NM_IFACE = 'org.freedesktop.NetworkManager' +NM_ACCESS_POINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint' +NM_SETTINGS_PATH = '/org/freedesktop/NetworkManager/Settings' +NM_SETTINGS_IFACE = 'org.freedesktop.NetworkManager.Settings' +NM_CONNECTION_IFACE = 'org.freedesktop.NetworkManager.Settings.Connection' +NM_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless' +NM_PROPERTIES_IFACE = 'org.freedesktop.DBus.Properties' +NM_DEVICE_IFACE = "org.freedesktop.NetworkManager.Device" + +NM_DEVICE_TYPE_WIFI = 2 +NM_DEVICE_TYPE_MODEM = 8 +NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT = 8 +NM_DEVICE_STATE_REASON_NEW_ACTIVATION = 60 + +# https://developer.gnome.org/NetworkManager/1.26/nm-dbus-types.html#NM80211ApFlags +NM_802_11_AP_FLAGS_NONE = 0x0 +NM_802_11_AP_FLAGS_PRIVACY = 0x1 +NM_802_11_AP_FLAGS_WPS = 0x2 + +# https://developer.gnome.org/NetworkManager/1.26/nm-dbus-types.html#NM80211ApSecurityFlags +NM_802_11_AP_SEC_PAIR_WEP40 = 0x00000001 +NM_802_11_AP_SEC_PAIR_WEP104 = 0x00000002 +NM_802_11_AP_SEC_GROUP_WEP40 = 0x00000010 +NM_802_11_AP_SEC_GROUP_WEP104 = 0x00000020 +NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100 +NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200 diff --git a/system/ui/lib/wifi_manager.py b/system/ui/lib/wifi_manager.py index 4cb741bc95..7bd292fa43 100644 --- a/system/ui/lib/wifi_manager.py +++ b/system/ui/lib/wifi_manager.py @@ -14,6 +14,11 @@ from dbus_next import BusType, Variant, Message from dbus_next.errors import DBusError from dbus_next.constants import MessageType +from openpilot.system.ui.lib.networkmanager import (NM, NM_PATH, NM_IFACE, NM_SETTINGS_PATH, NM_SETTINGS_IFACE, + NM_CONNECTION_IFACE, NM_WIRELESS_IFACE, NM_PROPERTIES_IFACE, + NM_DEVICE_IFACE, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT, + NMDeviceState) + try: from openpilot.common.params import Params except ImportError: @@ -23,32 +28,10 @@ from openpilot.common.swaglog import cloudlog T = TypeVar("T") -# NetworkManager constants -NM = "org.freedesktop.NetworkManager" -NM_PATH = '/org/freedesktop/NetworkManager' -NM_IFACE = 'org.freedesktop.NetworkManager' -NM_SETTINGS_PATH = '/org/freedesktop/NetworkManager/Settings' -NM_SETTINGS_IFACE = 'org.freedesktop.NetworkManager.Settings' -NM_CONNECTION_IFACE = 'org.freedesktop.NetworkManager.Settings.Connection' -NM_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless' -NM_PROPERTIES_IFACE = 'org.freedesktop.DBus.Properties' -NM_DEVICE_IFACE = "org.freedesktop.NetworkManager.Device" - -NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT = 8 - TETHERING_IP_ADDRESS = "192.168.43.1" DEFAULT_TETHERING_PASSWORD = "swagswagcomma" -# NetworkManager device states -class NMDeviceState(IntEnum): - DISCONNECTED = 30 - PREPARE = 40 - NEED_AUTH = 60 - IP_CONFIG = 70 - ACTIVATED = 100 - - class SecurityType(IntEnum): OPEN = 0 WPA = 1 From e89c6b3b88569916a47067e56cd51d0fbc96e549 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Mon, 25 Aug 2025 15:23:14 -0700 Subject: [PATCH 005/159] raylib: remove redundant networking class (#36057) remove a class --- selfdrive/ui/layouts/network.py | 17 ----------------- selfdrive/ui/layouts/settings/settings.py | 8 ++++++-- 2 files changed, 6 insertions(+), 19 deletions(-) delete mode 100644 selfdrive/ui/layouts/network.py diff --git a/selfdrive/ui/layouts/network.py b/selfdrive/ui/layouts/network.py deleted file mode 100644 index 856be26e97..0000000000 --- a/selfdrive/ui/layouts/network.py +++ /dev/null @@ -1,17 +0,0 @@ -import pyray as rl -from openpilot.system.ui.lib.wifi_manager import WifiManagerWrapper -from openpilot.system.ui.widgets import Widget -from openpilot.system.ui.widgets.network import WifiManagerUI - - -class NetworkLayout(Widget): - def __init__(self): - super().__init__() - self.wifi_manager = WifiManagerWrapper() - self.wifi_ui = WifiManagerUI(self.wifi_manager) - - def _render(self, rect: rl.Rectangle): - self.wifi_ui.render(rect) - - def shutdown(self): - self.wifi_manager.shutdown() diff --git a/selfdrive/ui/layouts/settings/settings.py b/selfdrive/ui/layouts/settings/settings.py index 674e5005f4..7d2a23576e 100644 --- a/selfdrive/ui/layouts/settings/settings.py +++ b/selfdrive/ui/layouts/settings/settings.py @@ -2,7 +2,6 @@ import pyray as rl from dataclasses import dataclass from enum import IntEnum from collections.abc import Callable -from openpilot.selfdrive.ui.layouts.network import NetworkLayout from openpilot.selfdrive.ui.layouts.settings.developer import DeveloperLayout from openpilot.selfdrive.ui.layouts.settings.device import DeviceLayout from openpilot.selfdrive.ui.layouts.settings.firehose import FirehoseLayout @@ -10,7 +9,9 @@ from openpilot.selfdrive.ui.layouts.settings.software import SoftwareLayout from openpilot.selfdrive.ui.layouts.settings.toggles import TogglesLayout from openpilot.system.ui.lib.application import gui_app, FontWeight, MousePos from openpilot.system.ui.lib.text_measure import measure_text_cached +from openpilot.system.ui.lib.wifi_manager import WifiManagerWrapper from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.network import WifiManagerUI # Settings close button SETTINGS_CLOSE_TEXT = "×" @@ -53,9 +54,12 @@ class SettingsLayout(Widget): self._current_panel = PanelType.DEVICE # Panel configuration + self.wifi_manager = WifiManagerWrapper() + self.wifi_ui = WifiManagerUI(self.wifi_manager) + self._panels = { PanelType.DEVICE: PanelInfo("Device", DeviceLayout()), - PanelType.NETWORK: PanelInfo("Network", NetworkLayout()), + PanelType.NETWORK: PanelInfo("Network", self.wifi_ui), PanelType.TOGGLES: PanelInfo("Toggles", TogglesLayout()), PanelType.SOFTWARE: PanelInfo("Software", SoftwareLayout()), PanelType.FIREHOSE: PanelInfo("Firehose", FirehoseLayout()), From 15fcbf24f1b2f1ecc920eb48e39dbeb2c0747e59 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Mon, 25 Aug 2025 15:52:13 -0700 Subject: [PATCH 006/159] raylib home ui: show/hide events (#36058) * it's a widget * proper events * bottom --- selfdrive/ui/layouts/main.py | 12 +++++++++--- selfdrive/ui/layouts/settings/settings.py | 14 ++++++++++---- system/ui/widgets/__init__.py | 7 +++++++ 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/selfdrive/ui/layouts/main.py b/selfdrive/ui/layouts/main.py index 3ab8525d33..777d2f4c3f 100644 --- a/selfdrive/ui/layouts/main.py +++ b/selfdrive/ui/layouts/main.py @@ -63,14 +63,20 @@ class MainLayout(Widget): # Don't hide sidebar from interactive timeout if self._current_mode != MainState.ONROAD: self._sidebar.set_visible(False) - self._current_mode = MainState.ONROAD + self._set_current_layout(MainState.ONROAD) else: - self._current_mode = MainState.HOME + self._set_current_layout(MainState.HOME) self._sidebar.set_visible(True) + def _set_current_layout(self, layout: MainState): + if layout != self._current_mode: + self._layouts[self._current_mode].hide_event() + self._current_mode = layout + self._layouts[self._current_mode].show_event() + def open_settings(self, panel_type: PanelType): self._layouts[MainState.SETTINGS].set_current_panel(panel_type) - self._current_mode = MainState.SETTINGS + self._set_current_layout(MainState.SETTINGS) self._sidebar.set_visible(False) def _on_settings_clicked(self): diff --git a/selfdrive/ui/layouts/settings/settings.py b/selfdrive/ui/layouts/settings/settings.py index 7d2a23576e..fe35ea094a 100644 --- a/selfdrive/ui/layouts/settings/settings.py +++ b/selfdrive/ui/layouts/settings/settings.py @@ -44,7 +44,7 @@ class PanelType(IntEnum): @dataclass class PanelInfo: name: str - instance: object + instance: Widget button_rect: rl.Rectangle = rl.Rectangle(0, 0, 0, 0) @@ -153,8 +153,14 @@ class SettingsLayout(Widget): def set_current_panel(self, panel_type: PanelType): if panel_type != self._current_panel: + self._panels[self._current_panel].instance.hide_event() self._current_panel = panel_type + self._panels[self._current_panel].instance.show_event() - def close_settings(self): - if self._close_callback: - self._close_callback() + def show_event(self): + super().show_event() + self._panels[self._current_panel].instance.show_event() + + def hide_event(self): + super().hide_event() + self._panels[self._current_panel].instance.hide_event() diff --git a/system/ui/widgets/__init__.py b/system/ui/widgets/__init__.py index d45f48ac38..cca2cec7ad 100644 --- a/system/ui/widgets/__init__.py +++ b/system/ui/widgets/__init__.py @@ -129,3 +129,10 @@ class Widget(abc.ABC): def _handle_mouse_release(self, mouse_pos: MousePos) -> bool: """Optionally handle mouse release events.""" return False + + def show_event(self): + """Optionally handle show event. Parent must manually call this""" + + def hide_event(self): + """Optionally handle hide event. Parent must manually call this""" + From 2dc0f97c933cf4c684aeb1ac95faa752f9790e3b Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Mon, 25 Aug 2025 22:29:14 -0700 Subject: [PATCH 007/159] raylib: fix slow Toggles panel first load (#36061) fix slow load on toggles page --- system/ui/widgets/list_view.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/ui/widgets/list_view.py b/system/ui/widgets/list_view.py index e871eef0a1..a8d81a8ba2 100644 --- a/system/ui/widgets/list_view.py +++ b/system/ui/widgets/list_view.py @@ -213,6 +213,7 @@ class ListItem(Widget): self.set_rect(rl.Rectangle(0, 0, ITEM_BASE_WIDTH, ITEM_BASE_HEIGHT)) self._font = gui_app.font(FontWeight.NORMAL) + self._icon_texture = gui_app.texture(os.path.join("icons", self.icon), ICON_SIZE, ICON_SIZE) if self.icon else None # Cached properties for performance self._prev_max_width: int = 0 @@ -261,8 +262,7 @@ class ListItem(Widget): if self.title: # Draw icon if present if self.icon: - icon_texture = gui_app.texture(os.path.join("icons", self.icon), ICON_SIZE, ICON_SIZE) - rl.draw_texture(icon_texture, int(content_x), int(self._rect.y + (ITEM_BASE_HEIGHT - icon_texture.width) // 2), rl.WHITE) + rl.draw_texture(self._icon_texture, int(content_x), int(self._rect.y + (ITEM_BASE_HEIGHT - self._icon_texture.width) // 2), rl.WHITE) text_x += ICON_SIZE + ITEM_PADDING # Draw main text From 7a2f2ddf32236fd497a6539ce7898a6cd915ca19 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Mon, 25 Aug 2025 22:30:09 -0700 Subject: [PATCH 008/159] raylib: speed up network panel first load (#36062) * debug * debug * clean up --- system/ui/widgets/network.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/system/ui/widgets/network.py b/system/ui/widgets/network.py index 0bb759a919..2ecfd36be7 100644 --- a/system/ui/widgets/network.py +++ b/system/ui/widgets/network.py @@ -44,6 +44,7 @@ class WifiManagerUI(Widget): self.btn_width: int = 200 self.scroll_panel = GuiScrollPanel() self.keyboard = Keyboard(max_text_size=MAX_PASSWORD_LENGTH, min_text_size=MIN_PASSWORD_LENGTH, show_password_toggle=True) + self._load_icons() self._networks: list[NetworkInfo] = [] self._networks_buttons: dict[str, Button] = {} @@ -64,6 +65,10 @@ class WifiManagerUI(Widget): self.wifi_manager.start() self.wifi_manager.connect() + def _load_icons(self): + for icon in STRENGTH_ICONS + ["icons/checkmark.png", "icons/circled_slash.png", "icons/lock_closed.png"]: + gui_app.texture(icon, ICON_SIZE, ICON_SIZE) + def _render(self, rect: rl.Rectangle): with self._lock: if not self._networks: From a70e4c3074accd67146ffa62905cc9722a9dfe60 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Mon, 25 Aug 2025 22:30:27 -0700 Subject: [PATCH 009/159] raylib: rm debug print --- selfdrive/ui/lib/prime_state.py | 1 - 1 file changed, 1 deletion(-) diff --git a/selfdrive/ui/lib/prime_state.py b/selfdrive/ui/lib/prime_state.py index da2ff899dd..a1b2472f30 100644 --- a/selfdrive/ui/lib/prime_state.py +++ b/selfdrive/ui/lib/prime_state.py @@ -25,7 +25,6 @@ class PrimeType(IntEnum): @lru_cache(maxsize=1) def get_token(dongle_id: str, t: int): - print('getting token') return Api(dongle_id).get_token(expiry_hours=TOKEN_EXPIRY_HOURS) From 5359f6d35464448491e1d036d6970ee67addc821 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 26 Aug 2025 01:23:59 -0700 Subject: [PATCH 010/159] raylib: clean up networking (#36039) * stasj * remove one of many classes * clean up and fix * clean up * stash/draft: oh this is sick * so epic * some clean up * what the fuck, it doesn't even use these * more epic initializers + make it kind of work * so simple, wonder if we should further 2x reduce line count * i've never ever seen this pattern b4, rm * remove bs add niceness * minor organization * set security type and support listing and rming conns * forget and connect * jeepney is actually pretty good, it's 2x faster to get wifi device (0.005s to 0.002s) * temp * do blocking add in worker thread * add jeepney * lets finish with python-dbus first then evaluate - revert jeepney This reverts commit 7de04b11c2285c298bb1ec907782026c795ab207. and * safe wrap * missing * saved connections * set rest of callbacks * skip hidden APs, simplify _running * add state management * either wrong password or disconnected for now * i can't believe we didn't check this... * disable button if unsupported!!! * hide/show event no lag hopefully yayay * fix hide event * remove old wifi manager * cache wifi device path + some clean up * more clean up * more clean up * temp disable blocking prime thread * hackily get device path once * ok * debug * fix open networks * debug * clean up * all threads wait for device path, and user functions dont ever attempt to get, just skip * same place * helper * Revert "helper" This reverts commit e237d9a720915fb6bd67c539123d3e2d9d582ce1. * organize? * Revert "organize?" This reverts commit 3aca3e5d629c947711ade88799febeb3f61eda87. * c word is a bad word * rk monitor debug for now * nothing crazy * improve checkmark responsiveness * when forgetting: this is correct, but feels unresponsive * this feels good * need these two to keep forgetting and activating responsive * sort by connected, strength, then name * handle non-critical race condition * log more * unused * oh jubilee is sick you can block on signals!! * proof of concept to see if works on device whoiops * so sucking fick * ah this is not generic, it's a filter on the return vals * flip around to not drop * oh thank god * fix * stash * atomic replace * clean up * add old to keep track of what's moved over * these are already moved * so much junk * so much junk * more * tethering wasn't used so we can ignore that for now * no params now * rm duplicate imports * not used anymore * move get wifi device over to jeepney! ~no additional lines * request scan w/ keepney * get_conns * _connection_by_ssid_jeepney is 2x faster (0.01 vs 0.02s) * do forget and activate * _update_networks matches! * rm old update_networks * replace connect_to_network, about same time (yes i removed thread call) * no more python-dbus!k * doesn't hurt * AP.from_dbus: actually handle incorrect paths w/ jeep + more efficient single call * properly handle errors * it's jeepney now * less state * using the thread safe router passes a race condition test that conn failed! * bad to copy from old wifimanager * fix conn usage * clean up * curious if locks are lagging * not for now * Revert "curious if locks are lagging" This reverts commit 085dd185b083f5905a4e71ba3e8c0565175e04aa. * clean up _monitor_state * remove tests * clean up dataclasses * sort * lint: okay fine it can be non by virtue of exiting right at the perfect time * some network clean up * some wifi manager clean up * this is handled * stop can be called manually, from deleting wifimanager, or exiting python. some protection * its not mutable anymore * scan on enter * clean up * back * lint * catch dbus fail to connect catch dbus fail to connect --- pyproject.toml | 2 +- selfdrive/ui/layouts/settings/settings.py | 8 +- system/ui/lib/wifi_manager.py | 970 ++++++++-------------- system/ui/setup.py | 5 +- system/ui/updater.py | 5 +- system/ui/widgets/network.py | 58 +- uv.lock | 22 +- 7 files changed, 385 insertions(+), 685 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7103163458..556b78009d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -101,8 +101,8 @@ dev = [ "av", "azure-identity", "azure-storage-blob", - "dbus-next", "dictdiffer", + "jeepney", "matplotlib", "opencv-python-headless", "parameterized >=0.8, <0.9", diff --git a/selfdrive/ui/layouts/settings/settings.py b/selfdrive/ui/layouts/settings/settings.py index fe35ea094a..a731a9158c 100644 --- a/selfdrive/ui/layouts/settings/settings.py +++ b/selfdrive/ui/layouts/settings/settings.py @@ -9,7 +9,7 @@ from openpilot.selfdrive.ui.layouts.settings.software import SoftwareLayout from openpilot.selfdrive.ui.layouts.settings.toggles import TogglesLayout from openpilot.system.ui.lib.application import gui_app, FontWeight, MousePos from openpilot.system.ui.lib.text_measure import measure_text_cached -from openpilot.system.ui.lib.wifi_manager import WifiManagerWrapper +from openpilot.system.ui.lib.wifi_manager import WifiManager from openpilot.system.ui.widgets import Widget from openpilot.system.ui.widgets.network import WifiManagerUI @@ -54,12 +54,12 @@ class SettingsLayout(Widget): self._current_panel = PanelType.DEVICE # Panel configuration - self.wifi_manager = WifiManagerWrapper() - self.wifi_ui = WifiManagerUI(self.wifi_manager) + wifi_manager = WifiManager() + wifi_manager.set_active(False) self._panels = { PanelType.DEVICE: PanelInfo("Device", DeviceLayout()), - PanelType.NETWORK: PanelInfo("Network", self.wifi_ui), + PanelType.NETWORK: PanelInfo("Network", WifiManagerUI(wifi_manager)), PanelType.TOGGLES: PanelInfo("Toggles", TogglesLayout()), PanelType.SOFTWARE: PanelInfo("Software", SoftwareLayout()), PanelType.FIREHOSE: PanelInfo("Firehose", FirehoseLayout()), diff --git a/system/ui/lib/wifi_manager.py b/system/ui/lib/wifi_manager.py index 7bd292fa43..96940c2b3b 100644 --- a/system/ui/lib/wifi_manager.py +++ b/system/ui/lib/wifi_manager.py @@ -1,35 +1,35 @@ -import asyncio -import concurrent.futures -import copy +import atexit import threading import time import uuid from collections.abc import Callable from dataclasses import dataclass from enum import IntEnum -from typing import TypeVar +from typing import Any -from dbus_next.aio import MessageBus -from dbus_next import BusType, Variant, Message -from dbus_next.errors import DBusError -from dbus_next.constants import MessageType +from jeepney import DBusAddress, new_method_call +from jeepney.bus_messages import MatchRule, message_bus +from jeepney.io.blocking import open_dbus_connection as open_dbus_connection_blocking +from jeepney.io.threading import DBusRouter, open_dbus_connection as open_dbus_connection_threading +from jeepney.low_level import MessageType +from jeepney.wrappers import Properties -from openpilot.system.ui.lib.networkmanager import (NM, NM_PATH, NM_IFACE, NM_SETTINGS_PATH, NM_SETTINGS_IFACE, - NM_CONNECTION_IFACE, NM_WIRELESS_IFACE, NM_PROPERTIES_IFACE, - NM_DEVICE_IFACE, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT, - NMDeviceState) - -try: - from openpilot.common.params import Params -except ImportError: - # Params/Cythonized modules are not available in zipapp - Params = None from openpilot.common.swaglog import cloudlog - -T = TypeVar("T") +from openpilot.system.ui.lib.networkmanager import (NM, NM_WIRELESS_IFACE, NM_802_11_AP_SEC_PAIR_WEP40, + NM_802_11_AP_SEC_PAIR_WEP104, NM_802_11_AP_SEC_GROUP_WEP40, + NM_802_11_AP_SEC_GROUP_WEP104, NM_802_11_AP_SEC_KEY_MGMT_PSK, + NM_802_11_AP_SEC_KEY_MGMT_802_1X, NM_802_11_AP_FLAGS_NONE, + NM_802_11_AP_FLAGS_PRIVACY, NM_802_11_AP_FLAGS_WPS, + NM_PATH, NM_IFACE, NM_ACCESS_POINT_IFACE, NM_SETTINGS_PATH, + NM_SETTINGS_IFACE, NM_CONNECTION_IFACE, NM_DEVICE_IFACE, + NM_DEVICE_TYPE_WIFI, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT, + NM_DEVICE_STATE_REASON_NEW_ACTIVATION, + NMDeviceState) TETHERING_IP_ADDRESS = "192.168.43.1" DEFAULT_TETHERING_PASSWORD = "swagswagcomma" +SIGNAL_QUEUE_SIZE = 10 +SCAN_PERIOD_SECONDS = 10 class SecurityType(IntEnum): @@ -40,673 +40,377 @@ class SecurityType(IntEnum): UNSUPPORTED = 4 -@dataclass -class NetworkInfo: +def get_security_type(flags: int, wpa_flags: int, rsn_flags: int) -> SecurityType: + wpa_props = wpa_flags | rsn_flags + + # obtained by looking at flags of networks in the office as reported by an Android phone + supports_wpa = (NM_802_11_AP_SEC_PAIR_WEP40 | NM_802_11_AP_SEC_PAIR_WEP104 | NM_802_11_AP_SEC_GROUP_WEP40 | + NM_802_11_AP_SEC_GROUP_WEP104 | NM_802_11_AP_SEC_KEY_MGMT_PSK) + + if (flags == NM_802_11_AP_FLAGS_NONE) or ((flags & NM_802_11_AP_FLAGS_WPS) and not (wpa_props & supports_wpa)): + return SecurityType.OPEN + elif (flags & NM_802_11_AP_FLAGS_PRIVACY) and (wpa_props & supports_wpa) and not (wpa_props & NM_802_11_AP_SEC_KEY_MGMT_802_1X): + return SecurityType.WPA + else: + cloudlog.warning(f"Unsupported network! flags: {flags}, wpa_flags: {wpa_flags}, rsn_flags: {rsn_flags}") + return SecurityType.UNSUPPORTED + + +@dataclass(frozen=True) +class Network: ssid: str strength: int is_connected: bool security_type: SecurityType - path: str + is_saved: bool + + @classmethod + def from_dbus(cls, ssid: str, aps: list["AccessPoint"], is_saved: bool) -> "Network": + # we only want to show the strongest AP for each Network/SSID + strongest_ap = max(aps, key=lambda ap: ap.strength) + is_connected = any(ap.is_connected for ap in aps) + security_type = get_security_type(strongest_ap.flags, strongest_ap.wpa_flags, strongest_ap.rsn_flags) + + return cls( + ssid=ssid, + strength=strongest_ap.strength, + is_connected=is_connected and is_saved, + security_type=security_type, + is_saved=is_saved, + ) + + +@dataclass(frozen=True) +class AccessPoint: + ssid: str bssid: str - is_saved: bool = False - # saved_path: str + strength: int + is_connected: bool + flags: int + wpa_flags: int + rsn_flags: int + ap_path: str + @classmethod + def from_dbus(cls, ap_props: dict[str, tuple[str, Any]], ap_path: str, active_ap_path: str) -> "AccessPoint": + ssid = bytes(ap_props['Ssid'][1]).decode("utf-8", "replace") + bssid = str(ap_props['HwAddress'][1]) + strength = int(ap_props['Strength'][1]) + flags = int(ap_props['Flags'][1]) + wpa_flags = int(ap_props['WpaFlags'][1]) + rsn_flags = int(ap_props['RsnFlags'][1]) -@dataclass -class WifiManagerCallbacks: - need_auth: Callable[[str], None] | None = None - activated: Callable[[], None] | None = None - forgotten: Callable[[str], None] | None = None - networks_updated: Callable[[list[NetworkInfo]], None] | None = None - connection_failed: Callable[[str, str], None] | None = None # Added for error feedback + return cls( + ssid=ssid, + bssid=bssid, + strength=strength, + is_connected=ap_path == active_ap_path, + flags=flags, + wpa_flags=wpa_flags, + rsn_flags=rsn_flags, + ap_path=ap_path, + ) class WifiManager: - def __init__(self, callbacks): - self.callbacks: WifiManagerCallbacks = callbacks - self.networks: list[NetworkInfo] = [] - self.bus: MessageBus = None - self.device_path: str = "" - self.device_proxy = None - self.saved_connections: dict[str, str] = {} - self.active_ap_path: str = "" - self.scan_task: asyncio.Task | None = None - # Set tethering ssid as "weedle" + first 4 characters of a dongle id - self._tethering_ssid = "weedle" - if Params is not None: - dongle_id = Params().get("DongleId") - if dongle_id: - self._tethering_ssid += "-" + dongle_id[:4] - self.running: bool = True - self._current_connection_ssid: str | None = None + def __init__(self): + self._networks = [] # a network can be comprised of multiple APs + self._active = True # used to not run when not in settings + self._exit = False - async def connect(self) -> None: - """Connect to the DBus system bus.""" + # DBus connections try: - self.bus = await MessageBus(bus_type=BusType.SYSTEM).connect() - while not await self._find_wifi_device(): - await asyncio.sleep(1) + self._router_main = DBusRouter(open_dbus_connection_threading(bus="SYSTEM")) # used by scanner / general method calls + self._conn_monitor = open_dbus_connection_blocking(bus="SYSTEM") # used by state monitor thread + self._nm = DBusAddress(NM_PATH, bus_name=NM, interface=NM_IFACE) + except FileNotFoundError: + cloudlog.exception("Failed to connect to system D-Bus") + self._exit = True - await self._setup_signals(self.device_path) - self.active_ap_path = await self.get_active_access_point() - await self.add_tethering_connection(self._tethering_ssid, DEFAULT_TETHERING_PASSWORD) - self.saved_connections = await self._get_saved_connections() - self.scan_task = asyncio.create_task(self._periodic_scan()) - except DBusError as e: - cloudlog.error(f"Failed to connect to DBus: {e}") - raise - except Exception as e: - cloudlog.error(f"Unexpected error during connect: {e}") - raise + # Store wifi device path + self._wifi_device: str | None = None - async def shutdown(self) -> None: - self.running = False - if self.scan_task: - self.scan_task.cancel() - try: - await self.scan_task - except asyncio.CancelledError: - pass - if self.bus: - self.bus.disconnect() + # State + self._connecting_to_ssid: str = "" + self._last_network_update: float = 0.0 - async def _request_scan(self) -> None: - try: - interface = self.device_proxy.get_interface(NM_WIRELESS_IFACE) - await interface.call_request_scan({}) - except DBusError as e: - cloudlog.warning(f"Scan request failed: {str(e)}") + # Callbacks + # TODO: implement a callback queue to avoid blocking UI thread + self._need_auth: Callable[[str], None] | None = None + self._activated: Callable[[], None] | None = None + self._forgotten: Callable[[str], None] | None = None + self._networks_updated: Callable[[list[Network]], None] | None = None + self._disconnected: Callable[[], None] | None = None - async def get_active_access_point(self): - try: - props_iface = self.device_proxy.get_interface(NM_PROPERTIES_IFACE) - ap_path = await props_iface.call_get(NM_WIRELESS_IFACE, 'ActiveAccessPoint') - return ap_path.value - except DBusError as e: - cloudlog.error(f"Error fetching active access point: {str(e)}") - return '' + self._lock = threading.Lock() - async def forget_connection(self, ssid: str) -> bool: - path = self.saved_connections.get(ssid) - if not path: - return False + self._scan_thread = threading.Thread(target=self._network_scanner, daemon=True) + self._scan_thread.start() - try: - nm_iface = await self._get_interface(NM, path, NM_CONNECTION_IFACE) - await nm_iface.call_delete() + self._state_thread = threading.Thread(target=self._monitor_state, daemon=True) + self._state_thread.start() - if self._current_connection_ssid == ssid: - self._current_connection_ssid = None + atexit.register(self.stop) - if ssid in self.saved_connections: - del self.saved_connections[ssid] + def set_callbacks(self, need_auth: Callable[[str], None], + activated: Callable[[], None] | None, + forgotten: Callable[[str], None], + networks_updated: Callable[[list[Network]], None], + disconnected: Callable[[], None]): + self._need_auth = need_auth + self._activated = activated + self._forgotten = forgotten + self._networks_updated = networks_updated + self._disconnected = disconnected - for network in self.networks: - if network.ssid == ssid: - network.is_saved = False - network.is_connected = False + def set_active(self, active: bool): + self._active = active + + # Scan immediately if we haven't scanned in a while + if active and time.monotonic() - self._last_network_update > SCAN_PERIOD_SECONDS / 2: + self._last_network_update = 0.0 + + def _monitor_state(self): + device_path = self._wait_for_wifi_device() + if device_path is None: + return + + rule = MatchRule( + type="signal", + interface=NM_DEVICE_IFACE, + member="StateChanged", + path=device_path, + ) + + # Filter for StateChanged signal + self._conn_monitor.send_and_get_reply(message_bus.AddMatch(rule)) + + with self._conn_monitor.filter(rule, bufsize=SIGNAL_QUEUE_SIZE) as q: + while not self._exit: + # TODO: always run, and ensure callbacks don't block UI thread + if not self._active: + time.sleep(1) + continue + + # Block until a matching signal arrives + try: + msg = self._conn_monitor.recv_until_filtered(q, timeout=1) + except TimeoutError: + continue + + new_state, previous_state, change_reason = msg.body + + # BAD PASSWORD + if new_state == NMDeviceState.NEED_AUTH and change_reason == NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT and len(self._connecting_to_ssid): + self.forget_connection(self._connecting_to_ssid, block=True) + if self._need_auth is not None: + self._need_auth(self._connecting_to_ssid) + self._connecting_to_ssid = "" + + elif new_state == NMDeviceState.ACTIVATED: + if self._activated is not None: + self._update_networks() + self._activated() + self._connecting_to_ssid = "" + + elif new_state == NMDeviceState.DISCONNECTED and change_reason != NM_DEVICE_STATE_REASON_NEW_ACTIVATION: + self._connecting_to_ssid = "" + if self._disconnected is not None: + self._disconnected() + + def _network_scanner(self): + self._wait_for_wifi_device() + + while not self._exit: + if self._active: + if time.monotonic() - self._last_network_update > SCAN_PERIOD_SECONDS: + # Scan for networks every 10 seconds + # TODO: should update when scan is complete (PropertiesChanged), but this is more than good enough for now + self._update_networks() + self._request_scan() + self._last_network_update = time.monotonic() + time.sleep(1 / 2.) + + def _wait_for_wifi_device(self) -> str | None: + with self._lock: + device_path: str | None = None + while not self._exit: + device_path = self._get_wifi_device() + if device_path is not None: break + time.sleep(1) + return device_path - # Notify UI of forgotten connection - if self.callbacks.networks_updated: - self.callbacks.networks_updated(copy.deepcopy(self.networks)) + def _get_wifi_device(self) -> str | None: + if self._wifi_device is not None: + return self._wifi_device - return True - except DBusError as e: - cloudlog.error(f"Failed to delete connection for SSID: {ssid}. Error: {e}") - return False + device_paths = self._router_main.send_and_get_reply(new_method_call(self._nm, 'GetDevices')).body[0] + for device_path in device_paths: + dev_addr = DBusAddress(device_path, bus_name=NM, interface=NM_DEVICE_IFACE) + dev_type = self._router_main.send_and_get_reply(Properties(dev_addr).get('DeviceType')).body[0][1] - async def activate_connection(self, ssid: str) -> bool: - connection_path = self.saved_connections.get(ssid) - if not connection_path: - return False - try: - nm_iface = await self._get_interface(NM, NM_PATH, NM_IFACE) - await nm_iface.call_activate_connection(connection_path, self.device_path, "/") - return True - except DBusError as e: - cloudlog.error(f"Failed to activate connection {ssid}: {str(e)}") - return False + if dev_type == NM_DEVICE_TYPE_WIFI: + self._wifi_device = device_path + break - async def connect_to_network(self, ssid: str, password: str = None, bssid: str = None, is_hidden: bool = False) -> None: - """Connect to a selected Wi-Fi network.""" - try: - self._current_connection_ssid = ssid + return self._wifi_device - if ssid in self.saved_connections: - # Forget old connection if new password provided - if password: - await self.forget_connection(ssid) - await asyncio.sleep(0.2) # NetworkManager delay - else: - # Just activate existing connection - await self.activate_connection(ssid) - return + def _get_connections(self) -> list[str]: + settings_addr = DBusAddress(NM_SETTINGS_PATH, bus_name=NM, interface=NM_SETTINGS_IFACE) + return list(self._router_main.send_and_get_reply(new_method_call(settings_addr, 'ListConnections')).body[0]) + + def _connection_by_ssid(self, ssid: str, known_connections: list[str] | None = None) -> str | None: + for conn_path in known_connections or self._get_connections(): + conn_addr = DBusAddress(conn_path, bus_name=NM, interface=NM_CONNECTION_IFACE) + reply = self._router_main.send_and_get_reply(new_method_call(conn_addr, "GetSettings")) + + # ignore connections removed during iteration (need auth, etc.) + if reply.header.message_type == MessageType.error: + cloudlog.warning(f"Failed to get connection properties for {conn_path}") + continue + + settings = reply.body[0] + if "802-11-wireless" in settings and settings['802-11-wireless']['ssid'][1].decode("utf-8", "replace") == ssid: + return conn_path + return None + + def connect_to_network(self, ssid: str, password: str): + def worker(): + # Clear all connections that may already exist to the network we are connecting to + self._connecting_to_ssid = ssid + self.forget_connection(ssid, block=True) + + is_hidden = False connection = { 'connection': { - 'type': Variant('s', '802-11-wireless'), - 'uuid': Variant('s', str(uuid.uuid4())), - 'id': Variant('s', f'openpilot connection {ssid}'), - 'autoconnect-retries': Variant('i', 0), + 'type': ('s', '802-11-wireless'), + 'uuid': ('s', str(uuid.uuid4())), + 'id': ('s', f'openpilot connection {ssid}'), + 'autoconnect-retries': ('i', 0), }, '802-11-wireless': { - 'ssid': Variant('ay', ssid.encode('utf-8')), - 'hidden': Variant('b', is_hidden), - 'mode': Variant('s', 'infrastructure'), + 'ssid': ('ay', ssid.encode("utf-8")), + 'hidden': ('b', is_hidden), + 'mode': ('s', 'infrastructure'), }, 'ipv4': { - 'method': Variant('s', 'auto'), - 'dns-priority': Variant('i', 600), + 'method': ('s', 'auto'), + 'dns-priority': ('i', 600), }, - 'ipv6': {'method': Variant('s', 'ignore')}, + 'ipv6': {'method': ('s', 'ignore')}, } - if bssid: - connection['802-11-wireless']['bssid'] = Variant('ay', bssid.encode('utf-8')) - if password: connection['802-11-wireless-security'] = { - 'key-mgmt': Variant('s', 'wpa-psk'), - 'auth-alg': Variant('s', 'open'), - 'psk': Variant('s', password), + 'key-mgmt': ('s', 'wpa-psk'), + 'auth-alg': ('s', 'open'), + 'psk': ('s', password), } - nm_iface = await self._get_interface(NM, NM_PATH, NM_IFACE) - await nm_iface.call_add_and_activate_connection(connection, self.device_path, "/") - except Exception as e: - self._current_connection_ssid = None - cloudlog.error(f"Error connecting to network: {e}") - # Notify UI of failure - if self.callbacks.connection_failed: - self.callbacks.connection_failed(ssid, str(e)) + settings_addr = DBusAddress(NM_SETTINGS_PATH, bus_name=NM, interface=NM_SETTINGS_IFACE) + self._router_main.send_and_get_reply(new_method_call(settings_addr, 'AddConnection', 'a{sa{sv}}', (connection,))) + self.activate_connection(ssid, block=True) - def is_saved(self, ssid: str) -> bool: - return ssid in self.saved_connections + threading.Thread(target=worker, daemon=True).start() - async def _find_wifi_device(self) -> bool: - nm_iface = await self._get_interface(NM, NM_PATH, NM_IFACE) - devices = await nm_iface.get_devices() + def forget_connection(self, ssid: str, block: bool = False): + def worker(): + conn_path = self._connection_by_ssid(ssid) + if conn_path is not None: + conn_addr = DBusAddress(conn_path, bus_name=NM, interface=NM_CONNECTION_IFACE) + self._router_main.send_and_get_reply(new_method_call(conn_addr, 'Delete')) - for device_path in devices: - device = await self.bus.introspect(NM, device_path) - device_proxy = self.bus.get_proxy_object(NM, device_path, device) - device_interface = device_proxy.get_interface(NM_DEVICE_IFACE) - device_type = await device_interface.get_device_type() # type: ignore[attr-defined] - if device_type == 2: # Wi-Fi device - self.device_path = device_path - self.device_proxy = device_proxy - return True + if self._forgotten is not None: + self._update_networks() + self._forgotten(ssid) - return False + if block: + worker() + else: + threading.Thread(target=worker, daemon=True).start() - async def add_tethering_connection(self, ssid: str, password: str = "12345678") -> bool: - """Create a WiFi tethering connection.""" - if len(password) < 8: - print("Tethering password must be at least 8 characters") - return False + def activate_connection(self, ssid: str, block: bool = False): + def worker(): + conn_path = self._connection_by_ssid(ssid) + if conn_path is not None: + if self._wifi_device is None: + cloudlog.warning("No WiFi device found") + return - try: - # First, check if a hotspot connection already exists - settings_iface = await self._get_interface(NM, NM_SETTINGS_PATH, NM_SETTINGS_IFACE) - connection_paths = await settings_iface.call_list_connections() + self._connecting_to_ssid = ssid + self._router_main.send(new_method_call(self._nm, 'ActivateConnection', 'ooo', + (conn_path, self._wifi_device, "/"))) - # Look for an existing hotspot connection - for path in connection_paths: - try: - settings = await self._get_connection_settings(path) - conn_type = settings.get('connection', {}).get('type', Variant('s', '')).value - wifi_mode = settings.get('802-11-wireless', {}).get('mode', Variant('s', '')).value + if block: + worker() + else: + threading.Thread(target=worker, daemon=True).start() - if conn_type == '802-11-wireless' and wifi_mode == 'ap': - # Extract the SSID to check - connection_ssid = self._extract_ssid(settings) - if connection_ssid == ssid: - return True - except DBusError: + def _request_scan(self): + if self._wifi_device is None: + cloudlog.warning("No WiFi device found") + return + + wifi_addr = DBusAddress(self._wifi_device, bus_name=NM, interface=NM_WIRELESS_IFACE) + reply = self._router_main.send_and_get_reply(new_method_call(wifi_addr, 'RequestScan', 'a{sv}', ({},))) + + if reply.header.message_type == MessageType.error: + cloudlog.warning(f"Failed to request scan: {reply}") + + def _update_networks(self): + if self._wifi_device is None: + cloudlog.warning("No WiFi device found") + return + + # returns '/' if no active AP + wifi_addr = DBusAddress(self._wifi_device, NM, interface=NM_WIRELESS_IFACE) + active_ap_path = self._router_main.send_and_get_reply(Properties(wifi_addr).get('ActiveAccessPoint')).body[0][1] + ap_paths = self._router_main.send_and_get_reply(new_method_call(wifi_addr, 'GetAllAccessPoints')).body[0] + + aps: dict[str, list[AccessPoint]] = {} + + for ap_path in ap_paths: + ap_addr = DBusAddress(ap_path, NM, interface=NM_ACCESS_POINT_IFACE) + ap_props = self._router_main.send_and_get_reply(Properties(ap_addr).get_all()) + + # some APs have been seen dropping off during iteration + if ap_props.header.message_type == MessageType.error: + cloudlog.warning(f"Failed to get AP properties for {ap_path}") + continue + + try: + ap = AccessPoint.from_dbus(ap_props.body[0], ap_path, active_ap_path) + if ap.ssid == "": continue - connection = { - 'connection': { - 'id': Variant('s', 'Hotspot'), - 'uuid': Variant('s', str(uuid.uuid4())), - 'type': Variant('s', '802-11-wireless'), - 'interface-name': Variant('s', 'wlan0'), - 'autoconnect': Variant('b', False), - }, - '802-11-wireless': { - 'band': Variant('s', 'bg'), - 'mode': Variant('s', 'ap'), - 'ssid': Variant('ay', ssid.encode('utf-8')), - }, - '802-11-wireless-security': { - 'group': Variant('as', ['ccmp']), - 'key-mgmt': Variant('s', 'wpa-psk'), - 'pairwise': Variant('as', ['ccmp']), - 'proto': Variant('as', ['rsn']), - 'psk': Variant('s', password), - }, - 'ipv4': { - 'method': Variant('s', 'shared'), - 'address-data': Variant('aa{sv}', [{'address': Variant('s', TETHERING_IP_ADDRESS), 'prefix': Variant('u', 24)}]), - 'gateway': Variant('s', TETHERING_IP_ADDRESS), - 'never-default': Variant('b', True), - }, - 'ipv6': { - 'method': Variant('s', 'ignore'), - }, - } + if ap.ssid not in aps: + aps[ap.ssid] = [] - settings_iface = await self._get_interface(NM, NM_SETTINGS_PATH, NM_SETTINGS_IFACE) - new_connection = await settings_iface.call_add_connection(connection) - print(f"Added tethering connection with path: {new_connection}") - return True - except DBusError as e: - print(f"Failed to add tethering connection: {e}") - return False - except Exception as e: - print(f"Unexpected error adding tethering connection: {e}") - return False + aps[ap.ssid].append(ap) + except Exception: + # catch all for parsing errors + cloudlog.exception(f"Failed to parse AP properties for {ap_path}") - async def get_tethering_password(self) -> str: - """Get the current tethering password.""" - try: - hotspot_path = self.saved_connections.get(self._tethering_ssid) - if hotspot_path: - conn_iface = await self._get_interface(NM, hotspot_path, NM_CONNECTION_IFACE) - secrets = await conn_iface.call_get_secrets('802-11-wireless-security') - if secrets and '802-11-wireless-security' in secrets: - psk = secrets.get('802-11-wireless-security', {}).get('psk', Variant('s', '')).value - return str(psk) if psk is not None else "" - return "" - except DBusError as e: - print(f"Failed to get tethering password: {e}") - return "" - except Exception as e: - print(f"Unexpected error getting tethering password: {e}") - return "" + known_connections = self._get_connections() + networks = [Network.from_dbus(ssid, ap_list, self._connection_by_ssid(ssid, known_connections) is not None) + for ssid, ap_list in aps.items()] + networks.sort(key=lambda n: (-n.is_connected, -n.strength, n.ssid.lower())) + self._networks = networks - async def set_tethering_password(self, password: str) -> bool: - """Set the tethering password.""" - if len(password) < 8: - cloudlog.error("Tethering password must be at least 8 characters") - return False + if self._networks_updated is not None: + self._networks_updated(self._networks) - try: - hotspot_path = self.saved_connections.get(self._tethering_ssid) - if not hotspot_path: - print("No hotspot connection found") - return False + def __del__(self): + self.stop() - # Update the connection settings with new password - settings = await self._get_connection_settings(hotspot_path) - if '802-11-wireless-security' not in settings: - settings['802-11-wireless-security'] = {} - settings['802-11-wireless-security']['psk'] = Variant('s', password) + def stop(self): + if not self._exit: + self._exit = True + self._scan_thread.join() + self._state_thread.join() - # Apply changes - conn_iface = await self._get_interface(NM, hotspot_path, NM_CONNECTION_IFACE) - await conn_iface.call_update(settings) - - # Check if connection is active and restart if needed - is_active = False - nm_iface = await self._get_interface(NM, NM_PATH, NM_IFACE) - active_connections = await nm_iface.get_active_connections() - - for conn_path in active_connections: - props_iface = await self._get_interface(NM, conn_path, NM_PROPERTIES_IFACE) - conn_id_path = await props_iface.call_get('org.freedesktop.NetworkManager.Connection.Active', 'Connection') - if conn_id_path.value == hotspot_path: - is_active = True - await nm_iface.call_deactivate_connection(conn_path) - break - - if is_active: - await nm_iface.call_activate_connection(hotspot_path, self.device_path, "/") - - print("Tethering password updated successfully") - return True - except DBusError as e: - print(f"Failed to set tethering password: {e}") - return False - except Exception as e: - print(f"Unexpected error setting tethering password: {e}") - return False - - async def is_tethering_active(self) -> bool: - """Check if tethering is active for the specified SSID.""" - try: - hotspot_path = self.saved_connections.get(self._tethering_ssid) - if not hotspot_path: - return False - - nm_iface = await self._get_interface(NM, NM_PATH, NM_IFACE) - active_connections = await nm_iface.get_active_connections() - - for conn_path in active_connections: - props_iface = await self._get_interface(NM, conn_path, NM_PROPERTIES_IFACE) - conn_id_path = await props_iface.call_get('org.freedesktop.NetworkManager.Connection.Active', 'Connection') - - if conn_id_path.value == hotspot_path: - return True - - return False - except Exception: - return False - - async def _periodic_scan(self): - while self.running: - try: - await self._request_scan() - await asyncio.sleep(30) - except asyncio.CancelledError: - break - except DBusError as e: - cloudlog.error(f"Scan failed: {e}") - await asyncio.sleep(5) - - async def _setup_signals(self, device_path: str) -> None: - rules = [ - f"type='signal',interface='{NM_PROPERTIES_IFACE}',member='PropertiesChanged',path='{device_path}'", - f"type='signal',interface='{NM_DEVICE_IFACE}',member='StateChanged',path='{device_path}'", - f"type='signal',interface='{NM_SETTINGS_IFACE}',member='NewConnection',path='{NM_SETTINGS_PATH}'", - f"type='signal',interface='{NM_SETTINGS_IFACE}',member='ConnectionRemoved',path='{NM_SETTINGS_PATH}'", - ] - for rule in rules: - await self._add_match_rule(rule) - - # Set up signal handlers - self.device_proxy.get_interface(NM_PROPERTIES_IFACE).on_properties_changed(self._on_properties_changed) - self.device_proxy.get_interface(NM_DEVICE_IFACE).on_state_changed(self._on_state_changed) - - settings_iface = await self._get_interface(NM, NM_SETTINGS_PATH, NM_SETTINGS_IFACE) - settings_iface.on_new_connection(self._on_new_connection) - settings_iface.on_connection_removed(self._on_connection_removed) - - def _on_properties_changed(self, interface: str, changed: dict, invalidated: list): - if interface == NM_WIRELESS_IFACE and 'LastScan' in changed: - asyncio.create_task(self._refresh_networks()) - elif interface == NM_WIRELESS_IFACE and "ActiveAccessPoint" in changed: - new_ap_path = changed["ActiveAccessPoint"].value - if self.active_ap_path != new_ap_path: - self.active_ap_path = new_ap_path - - def _on_state_changed(self, new_state: int, old_state: int, reason: int): - if new_state == NMDeviceState.ACTIVATED: - if self.callbacks.activated: - self.callbacks.activated() - self._current_connection_ssid = None - asyncio.create_task(self._refresh_networks()) - elif new_state in (NMDeviceState.DISCONNECTED, NMDeviceState.NEED_AUTH): - for network in self.networks: - network.is_connected = False - - # BAD PASSWORD - if new_state == NMDeviceState.NEED_AUTH and reason == NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT and self.callbacks.need_auth: - if self._current_connection_ssid: - asyncio.create_task(self.forget_connection(self._current_connection_ssid)) - self.callbacks.need_auth(self._current_connection_ssid) - else: - # Try to find the network from active_ap_path - for network in self.networks: - if network.path == self.active_ap_path: - asyncio.create_task(self.forget_connection(network.ssid)) - self.callbacks.need_auth(network.ssid) - break - else: - # Couldn't identify the network that needs auth - cloudlog.error("Network needs authentication but couldn't identify which one") - - def _on_new_connection(self, path: str) -> None: - """Callback for NewConnection signal.""" - asyncio.create_task(self._add_saved_connection(path)) - - def _on_connection_removed(self, path: str) -> None: - """Callback for ConnectionRemoved signal.""" - for ssid, p in list(self.saved_connections.items()): - if path == p: - del self.saved_connections[ssid] - - if self.callbacks.forgotten: - self.callbacks.forgotten(ssid) - break - - async def _add_saved_connection(self, path: str) -> None: - """Add a new saved connection to the dictionary.""" - try: - settings = await self._get_connection_settings(path) - if ssid := self._extract_ssid(settings): - self.saved_connections[ssid] = path - except DBusError as e: - cloudlog.error(f"Failed to add connection {path}: {e}") - - def _extract_ssid(self, settings: dict) -> str | None: - """Extract SSID from connection settings.""" - ssid_variant = settings.get('802-11-wireless', {}).get('ssid', Variant('ay', b'')).value - return bytes(ssid_variant).decode('utf-8') if ssid_variant else None - - async def _add_match_rule(self, rule): - """Add a match rule on the bus.""" - reply = await self.bus.call( - Message( - message_type=MessageType.METHOD_CALL, - destination='org.freedesktop.DBus', - interface="org.freedesktop.DBus", - path='/org/freedesktop/DBus', - member='AddMatch', - signature='s', - body=[rule], - ) - ) - - assert reply.message_type == MessageType.METHOD_RETURN - return reply - - async def _refresh_networks(self): - """Get a list of available networks via NetworkManager.""" - wifi_iface = self.device_proxy.get_interface(NM_WIRELESS_IFACE) - access_points = await wifi_iface.get_access_points() - self.active_ap_path = await self.get_active_access_point() - network_dict = {} - for ap_path in access_points: - try: - props_iface = await self._get_interface(NM, ap_path, NM_PROPERTIES_IFACE) - properties = await props_iface.call_get_all('org.freedesktop.NetworkManager.AccessPoint') - ssid_variant = properties['Ssid'].value - ssid = bytes(ssid_variant).decode('utf-8') - if not ssid: - continue - - bssid = properties.get('HwAddress', Variant('s', '')).value - strength = properties['Strength'].value - flags = properties['Flags'].value - wpa_flags = properties['WpaFlags'].value - rsn_flags = properties['RsnFlags'].value - - # May be multiple access points for each SSID. Use first for ssid - # and security type, then update the rest using all APs - if ssid not in network_dict: - network_dict[ssid] = NetworkInfo( - ssid=ssid, - strength=0, - security_type=self._get_security_type(flags, wpa_flags, rsn_flags), - path="", - bssid="", - is_connected=False, - is_saved=ssid in self.saved_connections - ) - - existing_network = network_dict.get(ssid) - if existing_network.strength < strength: - existing_network.strength = strength - existing_network.path = ap_path - existing_network.bssid = bssid - if self.active_ap_path == ap_path: - existing_network.is_connected = self._current_connection_ssid != ssid - - except DBusError as e: - cloudlog.error(f"Error fetching networks: {e}") - except Exception as e: - cloudlog.error({e}) - - self.networks = sorted( - network_dict.values(), - key=lambda network: ( - not network.is_connected, - -network.strength, # Higher signal strength first - network.ssid.lower(), - ), - ) - - if self.callbacks.networks_updated: - self.callbacks.networks_updated(copy.deepcopy(self.networks)) - - async def _get_connection_settings(self, path): - """Fetch connection settings for a specific connection path.""" - try: - settings = await self._get_interface(NM, path, NM_CONNECTION_IFACE) - return await settings.call_get_settings() - except DBusError as e: - cloudlog.error(f"Failed to get settings for {path}: {str(e)}") - return {} - - async def _process_chunk(self, paths_chunk): - """Process a chunk of connection paths.""" - tasks = [self._get_connection_settings(path) for path in paths_chunk] - return await asyncio.gather(*tasks, return_exceptions=True) - - async def _get_saved_connections(self) -> dict[str, str]: - try: - settings_iface = await self._get_interface(NM, NM_SETTINGS_PATH, NM_SETTINGS_IFACE) - connection_paths = await settings_iface.call_list_connections() - saved_ssids: dict[str, str] = {} - batch_size = 20 - for i in range(0, len(connection_paths), batch_size): - chunk = connection_paths[i : i + batch_size] - results = await self._process_chunk(chunk) - for path, config in zip(chunk, results, strict=True): - if isinstance(config, dict) and '802-11-wireless' in config: - if ssid := self._extract_ssid(config): - saved_ssids[ssid] = path - return saved_ssids - except DBusError as e: - cloudlog.error(f"Error fetching saved connections: {str(e)}") - return {} - - async def _get_interface(self, bus_name: str, path: str, name: str): - introspection = await self.bus.introspect(bus_name, path) - proxy = self.bus.get_proxy_object(bus_name, path, introspection) - return proxy.get_interface(name) - - def _get_security_type(self, flags: int, wpa_flags: int, rsn_flags: int) -> SecurityType: - """Determine the security type based on flags.""" - if flags == 0 and not (wpa_flags or rsn_flags): - return SecurityType.OPEN - if rsn_flags & 0x200: # SAE (WPA3 Personal) - # TODO: support WPA3 - return SecurityType.UNSUPPORTED - if rsn_flags: # RSN indicates WPA2 or higher - return SecurityType.WPA2 - if wpa_flags: # WPA flags indicate WPA - return SecurityType.WPA - return SecurityType.UNSUPPORTED - - -class WifiManagerWrapper: - def __init__(self): - self._manager: WifiManager | None = None - self._callbacks: WifiManagerCallbacks = WifiManagerCallbacks() - - self._thread = threading.Thread(target=self._run, daemon=True) - self._loop: asyncio.EventLoop | None = None - self._running = False - - def set_callbacks(self, callbacks: WifiManagerCallbacks): - self._callbacks = callbacks - - def start(self) -> None: - if not self._running: - self._thread.start() - while self._thread is not None and not self._running: - time.sleep(0.1) - - def _run(self): - self._loop = asyncio.new_event_loop() - asyncio.set_event_loop(self._loop) - - try: - self._manager = WifiManager(self._callbacks) - self._running = True - self._loop.run_forever() - except Exception as e: - cloudlog.error(f"Error in WifiManagerWrapper thread: {e}") - finally: - if self._loop.is_running(): - self._loop.stop() - self._running = False - - def shutdown(self) -> None: - if self._running: - if self._manager is not None and self._loop: - shutdown_future = asyncio.run_coroutine_threadsafe(self._manager.shutdown(), self._loop) - shutdown_future.result(timeout=3.0) - - if self._loop and self._loop.is_running(): - self._loop.call_soon_threadsafe(self._loop.stop) - if self._thread and self._thread.is_alive(): - self._thread.join(timeout=2.0) - self._running = False - - def is_saved(self, ssid: str) -> bool: - """Check if a network is saved.""" - return self._run_coroutine_sync(lambda manager: manager.is_saved(ssid), default=False) - - def connect(self): - """Connect to DBus and start Wi-Fi scanning.""" - if not self._manager: - return - self._run_coroutine(self._manager.connect()) - - def forget_connection(self, ssid: str): - """Forget a saved Wi-Fi connection.""" - if not self._manager: - return - self._run_coroutine(self._manager.forget_connection(ssid)) - - def activate_connection(self, ssid: str): - """Activate an existing Wi-Fi connection.""" - if not self._manager: - return - self._run_coroutine(self._manager.activate_connection(ssid)) - - def connect_to_network(self, ssid: str, password: str = None, bssid: str = None, is_hidden: bool = False): - """Connect to a Wi-Fi network.""" - if not self._manager: - return - self._run_coroutine(self._manager.connect_to_network(ssid, password, bssid, is_hidden)) - - def _run_coroutine(self, coro): - """Run a coroutine in the async thread.""" - if not self._running or not self._loop: - cloudlog.error("WifiManager thread is not running") - return - asyncio.run_coroutine_threadsafe(coro, self._loop) - - def _run_coroutine_sync(self, func: Callable[[WifiManager], T], default: T) -> T: - """Run a function synchronously in the async thread.""" - if not self._running or not self._loop or not self._manager: - return default - future = concurrent.futures.Future[T]() - - def wrapper(manager: WifiManager) -> None: - try: - future.set_result(func(manager)) - except Exception as e: - future.set_exception(e) - - try: - self._loop.call_soon_threadsafe(wrapper, self._manager) - return future.result(timeout=1.0) - except Exception as e: - cloudlog.error(f"WifiManagerWrapper property access failed: {e}") - return default + self._router_main.close() + self._router_main.conn.close() + self._conn_monitor.close() diff --git a/system/ui/setup.py b/system/ui/setup.py index 800ca7662c..a985e783be 100755 --- a/system/ui/setup.py +++ b/system/ui/setup.py @@ -19,7 +19,7 @@ from openpilot.system.ui.widgets import Widget from openpilot.system.ui.widgets.button import Button, ButtonStyle, ButtonRadio from openpilot.system.ui.widgets.keyboard import Keyboard from openpilot.system.ui.widgets.label import Label, TextAlignment -from openpilot.system.ui.widgets.network import WifiManagerUI, WifiManagerWrapper +from openpilot.system.ui.widgets.network import WifiManagerUI, WifiManager NetworkType = log.DeviceState.NetworkType @@ -72,8 +72,7 @@ class Setup(Widget): self.download_url = "" self.download_progress = 0 self.download_thread = None - self.wifi_manager = WifiManagerWrapper() - self.wifi_ui = WifiManagerUI(self.wifi_manager) + self.wifi_ui = WifiManagerUI(WifiManager()) self.keyboard = Keyboard() self.selected_radio = None self.warning = gui_app.texture("icons/warning.png", 150, 150) diff --git a/system/ui/updater.py b/system/ui/updater.py index 31799d3628..b3cdc82cf5 100755 --- a/system/ui/updater.py +++ b/system/ui/updater.py @@ -7,7 +7,7 @@ from enum import IntEnum from openpilot.system.hardware import HARDWARE from openpilot.system.ui.lib.application import gui_app, FontWeight -from openpilot.system.ui.lib.wifi_manager import WifiManagerWrapper +from openpilot.system.ui.lib.wifi_manager import WifiManager from openpilot.system.ui.widgets import Widget from openpilot.system.ui.widgets.button import gui_button, ButtonStyle from openpilot.system.ui.widgets.label import gui_text_box, gui_label @@ -43,8 +43,7 @@ class Updater(Widget): self.show_reboot_button = False self.process = None self.update_thread = None - self.wifi_manager = WifiManagerWrapper() - self.wifi_manager_ui = WifiManagerUI(self.wifi_manager) + self.wifi_manager_ui = WifiManagerUI(WifiManager()) def install_update(self): self.current_screen = Screen.PROGRESS diff --git a/system/ui/widgets/network.py b/system/ui/widgets/network.py index 2ecfd36be7..6f5a00015b 100644 --- a/system/ui/widgets/network.py +++ b/system/ui/widgets/network.py @@ -6,7 +6,7 @@ from typing import cast import pyray as rl from openpilot.system.ui.lib.application import gui_app from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel -from openpilot.system.ui.lib.wifi_manager import NetworkInfo, WifiManagerCallbacks, WifiManagerWrapper, SecurityType +from openpilot.system.ui.lib.wifi_manager import WifiManager, SecurityType, Network from openpilot.system.ui.widgets import Widget from openpilot.system.ui.widgets.button import ButtonStyle, Button from openpilot.system.ui.widgets.confirm_dialog import ConfirmDialog @@ -36,34 +36,35 @@ class UIState(IntEnum): class WifiManagerUI(Widget): - def __init__(self, wifi_manager: WifiManagerWrapper): + def __init__(self, wifi_manager: WifiManager): super().__init__() + self.wifi_manager = wifi_manager self.state: UIState = UIState.IDLE - self._state_network: NetworkInfo | None = None # for CONNECTING / NEEDS_AUTH / SHOW_FORGET_CONFIRM / FORGETTING + self._state_network: Network | None = None # for CONNECTING / NEEDS_AUTH / SHOW_FORGET_CONFIRM / FORGETTING self._password_retry: bool = False # for NEEDS_AUTH self.btn_width: int = 200 self.scroll_panel = GuiScrollPanel() self.keyboard = Keyboard(max_text_size=MAX_PASSWORD_LENGTH, min_text_size=MIN_PASSWORD_LENGTH, show_password_toggle=True) self._load_icons() - self._networks: list[NetworkInfo] = [] + self._networks: list[Network] = [] self._networks_buttons: dict[str, Button] = {} self._forget_networks_buttons: dict[str, Button] = {} self._lock = Lock() - self.wifi_manager = wifi_manager self._confirm_dialog = ConfirmDialog("", "Forget", "Cancel") - self.wifi_manager.set_callbacks( - WifiManagerCallbacks( - need_auth=self._on_need_auth, - activated=self._on_activated, - forgotten=self._on_forgotten, - networks_updated=self._on_network_updated, - connection_failed=self._on_connection_failed - ) - ) - self.wifi_manager.start() - self.wifi_manager.connect() + self.wifi_manager.set_callbacks(need_auth=self._on_need_auth, + activated=self._on_activated, + forgotten=self._on_forgotten, + networks_updated=self._on_network_updated, + disconnected=self._on_disconnected) + + def show_event(self): + # start/stop scanning when widget is visible + self.wifi_manager.set_active(True) + + def hide_event(self): + self.wifi_manager.set_active(False) def _load_icons(self): for icon in STRENGTH_ICONS + ["icons/checkmark.png", "icons/circled_slash.png", "icons/lock_closed.png"]: @@ -78,7 +79,7 @@ class WifiManagerUI(Widget): if self.state == UIState.NEEDS_AUTH and self._state_network: self.keyboard.set_title("Wrong password" if self._password_retry else "Enter password", f"for {self._state_network.ssid}") self.keyboard.reset() - gui_app.set_modal_overlay(self.keyboard, lambda result: self._on_password_entered(cast(NetworkInfo, self._state_network), result)) + gui_app.set_modal_overlay(self.keyboard, lambda result: self._on_password_entered(cast(Network, self._state_network), result)) elif self.state == UIState.SHOW_FORGET_CONFIRM and self._state_network: self._confirm_dialog.set_text(f'Forget Wi-Fi Network "{self._state_network.ssid}"?') self._confirm_dialog.reset() @@ -86,7 +87,7 @@ class WifiManagerUI(Widget): else: self._draw_network_list(rect) - def _on_password_entered(self, network: NetworkInfo, result: int): + def _on_password_entered(self, network: Network, result: int): if result == 1: password = self.keyboard.text self.keyboard.clear() @@ -121,7 +122,7 @@ class WifiManagerUI(Widget): rl.end_scissor_mode() - def _draw_network_item(self, rect, network: NetworkInfo, clicked: bool): + def _draw_network_item(self, rect, network: Network, clicked: bool): spacing = 50 ssid_rect = rl.Rectangle(rect.x, rect.y, rect.width - self.btn_width * 2, ITEM_HEIGHT) signal_icon_rect = rl.Rectangle(rect.x + rect.width - ICON_SIZE, rect.y + (ITEM_HEIGHT - ICON_SIZE) / 2, ICON_SIZE, ICON_SIZE) @@ -174,10 +175,10 @@ class WifiManagerUI(Widget): self.state = UIState.SHOW_FORGET_CONFIRM self._state_network = network - def _draw_status_icon(self, rect, network: NetworkInfo): + def _draw_status_icon(self, rect, network: Network): """Draw the status icon based on network's connection state""" icon_file = None - if network.is_connected: + if network.is_connected and self.state != UIState.CONNECTING: icon_file = "icons/checkmark.png" elif network.security_type == SecurityType.UNSUPPORTED: icon_file = "icons/circled_slash.png" @@ -191,12 +192,12 @@ class WifiManagerUI(Widget): icon_rect = rl.Vector2(rect.x, rect.y + (ICON_SIZE - texture.height) / 2) rl.draw_texture_v(texture, icon_rect, rl.WHITE) - def _draw_signal_strength_icon(self, rect: rl.Rectangle, network: NetworkInfo): + def _draw_signal_strength_icon(self, rect: rl.Rectangle, network: Network): """Draw the Wi-Fi signal strength icon based on network's signal strength""" strength_level = max(0, min(3, round(network.strength / 33.0))) rl.draw_texture_v(gui_app.texture(STRENGTH_ICONS[strength_level], ICON_SIZE, ICON_SIZE), rl.Vector2(rect.x, rect.y), rl.WHITE) - def connect_to_network(self, network: NetworkInfo, password=''): + def connect_to_network(self, network: Network, password=''): self.state = UIState.CONNECTING self._state_network = network if network.is_saved and not password: @@ -204,13 +205,12 @@ class WifiManagerUI(Widget): else: self.wifi_manager.connect_to_network(network.ssid, password) - def forget_network(self, network: NetworkInfo): + def forget_network(self, network: Network): self.state = UIState.FORGETTING self._state_network = network - network.is_saved = False self.wifi_manager.forget_connection(network.ssid) - def _on_network_updated(self, networks: list[NetworkInfo]): + def _on_network_updated(self, networks: list[Network]): with self._lock: self._networks = networks for n in self._networks: @@ -237,7 +237,7 @@ class WifiManagerUI(Widget): if self.state == UIState.FORGETTING: self.state = UIState.IDLE - def _on_connection_failed(self, ssid: str, error: str): + def _on_disconnected(self): with self._lock: if self.state == UIState.CONNECTING: self.state = UIState.IDLE @@ -245,13 +245,11 @@ class WifiManagerUI(Widget): def main(): gui_app.init_window("Wi-Fi Manager") - wifi_manager = WifiManagerWrapper() - wifi_ui = WifiManagerUI(wifi_manager) + wifi_ui = WifiManagerUI(WifiManager()) for _ in gui_app.render(): wifi_ui.render(rl.Rectangle(50, 50, gui_app.width - 100, gui_app.height - 100)) - wifi_manager.shutdown() gui_app.close() diff --git a/uv.lock b/uv.lock index 7010cdfb83..72c3d2f8e2 100644 --- a/uv.lock +++ b/uv.lock @@ -442,15 +442,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/56/c8/46ac27096684f33e27dab749ef43c6b0119c6a0d852971eaefb73256dc4c/cython-3.1.3-py3-none-any.whl", hash = "sha256:d13025b34f72f77bf7f65c1cd628914763e6c285f4deb934314c922b91e6be5a", size = 1225725, upload-time = "2025-08-13T06:19:09.593Z" }, ] -[[package]] -name = "dbus-next" -version = "0.2.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ce/45/6a40fbe886d60a8c26f480e7d12535502b5ba123814b3b9a0b002ebca198/dbus_next-0.2.3.tar.gz", hash = "sha256:f4eae26909332ada528c0a3549dda8d4f088f9b365153952a408e28023a626a5", size = 71112, upload-time = "2021-07-25T22:11:28.398Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/fc/c0a3f4c4eaa5a22fbef91713474666e13d0ea2a69c84532579490a9f2cc8/dbus_next-0.2.3-py3-none-any.whl", hash = "sha256:58948f9aff9db08316734c0be2a120f6dc502124d9642f55e90ac82ffb16a18b", size = 57885, upload-time = "2021-07-25T22:11:25.466Z" }, -] - [[package]] name = "dictdiffer" version = "0.9.0" @@ -690,6 +681,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/15/aa/0aca39a37d3c7eb941ba736ede56d689e7be91cab5d9ca846bde3999eba6/isodate-0.7.2-py3-none-any.whl", hash = "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15", size = 22320, upload-time = "2024-10-08T23:04:09.501Z" }, ] +[[package]] +name = "jeepney" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/6f/357efd7602486741aa73ffc0617fb310a29b588ed0fd69c2399acbb85b0c/jeepney-0.9.0.tar.gz", hash = "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732", size = 106758, upload-time = "2025-02-27T18:51:01.684Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b2/a3/e137168c9c44d18eff0376253da9f1e9234d0239e0ee230d2fee6cea8e55/jeepney-0.9.0-py3-none-any.whl", hash = "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683", size = 49010, upload-time = "2025-02-27T18:51:00.104Z" }, +] + [[package]] name = "jinja2" version = "3.1.6" @@ -1241,8 +1241,8 @@ dev = [ { name = "av" }, { name = "azure-identity" }, { name = "azure-storage-blob" }, - { name = "dbus-next" }, { name = "dictdiffer" }, + { name = "jeepney" }, { name = "matplotlib" }, { name = "opencv-python-headless" }, { name = "parameterized" }, @@ -1294,11 +1294,11 @@ requires-dist = [ { name = "codespell", marker = "extra == 'testing'" }, { name = "crcmod" }, { name = "cython" }, - { name = "dbus-next", marker = "extra == 'dev'" }, { name = "dictdiffer", marker = "extra == 'dev'" }, { name = "future-fstrings" }, { name = "hypothesis", marker = "extra == 'testing'", specifier = "==6.47.*" }, { name = "inputs" }, + { name = "jeepney", marker = "extra == 'dev'" }, { name = "jinja2", marker = "extra == 'docs'" }, { name = "json-rpc" }, { name = "libusb1" }, From 23b4aaf2a5e3008bf230cfaa86027b1ccbaedbb7 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 26 Aug 2025 03:25:01 -0700 Subject: [PATCH 011/159] raylib networking: remove locking on UI thread (#36063) * use callback queue to make this thread safe and remove locks (which lag ui thread?) * woah this works * no more lock! * always run signal handler and store callbacks, like qt * debug * more * okay not for now * combine _get_connections and _connection_by_ssid, closer to qt and not an explosion of GetSettings dbus calls * debug * try this * skip * len * skip hidden networks * actually slower * stash * back to 8929f37d495a524d4a996d66b82d4a947fbf4f1c * clean up --- system/ui/lib/wifi_manager.py | 26 ++++++++----- system/ui/widgets/network.py | 72 ++++++++++++++++------------------- 2 files changed, 50 insertions(+), 48 deletions(-) diff --git a/system/ui/lib/wifi_manager.py b/system/ui/lib/wifi_manager.py index 96940c2b3b..58181157c0 100644 --- a/system/ui/lib/wifi_manager.py +++ b/system/ui/lib/wifi_manager.py @@ -133,12 +133,12 @@ class WifiManager: # State self._connecting_to_ssid: str = "" self._last_network_update: float = 0.0 + self._callback_queue: list[Callable] = [] # Callbacks - # TODO: implement a callback queue to avoid blocking UI thread self._need_auth: Callable[[str], None] | None = None self._activated: Callable[[], None] | None = None - self._forgotten: Callable[[str], None] | None = None + self._forgotten: Callable[[], None] | None = None self._networks_updated: Callable[[list[Network]], None] | None = None self._disconnected: Callable[[], None] | None = None @@ -154,7 +154,7 @@ class WifiManager: def set_callbacks(self, need_auth: Callable[[str], None], activated: Callable[[], None] | None, - forgotten: Callable[[str], None], + forgotten: Callable[[], None], networks_updated: Callable[[list[Network]], None], disconnected: Callable[[], None]): self._need_auth = need_auth @@ -163,6 +163,15 @@ class WifiManager: self._networks_updated = networks_updated self._disconnected = disconnected + def _enqueue_callback(self, cb: Callable, *args): + self._callback_queue.append(lambda: cb(*args)) + + def process_callbacks(self): + # Call from UI thread to run any pending callbacks + to_run, self._callback_queue = self._callback_queue, [] + for cb in to_run: + cb() + def set_active(self, active: bool): self._active = active @@ -187,7 +196,6 @@ class WifiManager: with self._conn_monitor.filter(rule, bufsize=SIGNAL_QUEUE_SIZE) as q: while not self._exit: - # TODO: always run, and ensure callbacks don't block UI thread if not self._active: time.sleep(1) continue @@ -204,19 +212,19 @@ class WifiManager: if new_state == NMDeviceState.NEED_AUTH and change_reason == NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT and len(self._connecting_to_ssid): self.forget_connection(self._connecting_to_ssid, block=True) if self._need_auth is not None: - self._need_auth(self._connecting_to_ssid) + self._enqueue_callback(self._need_auth, self._connecting_to_ssid) self._connecting_to_ssid = "" elif new_state == NMDeviceState.ACTIVATED: if self._activated is not None: self._update_networks() - self._activated() + self._enqueue_callback(self._activated) self._connecting_to_ssid = "" elif new_state == NMDeviceState.DISCONNECTED and change_reason != NM_DEVICE_STATE_REASON_NEW_ACTIVATION: self._connecting_to_ssid = "" if self._disconnected is not None: - self._disconnected() + self._enqueue_callback(self._disconnected) def _network_scanner(self): self._wait_for_wifi_device() @@ -324,7 +332,7 @@ class WifiManager: if self._forgotten is not None: self._update_networks() - self._forgotten(ssid) + self._enqueue_callback(self._forgotten) if block: worker() @@ -400,7 +408,7 @@ class WifiManager: self._networks = networks if self._networks_updated is not None: - self._networks_updated(self._networks) + self._enqueue_callback(self._networks_updated, self._networks) def __del__(self): self.stop() diff --git a/system/ui/widgets/network.py b/system/ui/widgets/network.py index 6f5a00015b..3e6317a49c 100644 --- a/system/ui/widgets/network.py +++ b/system/ui/widgets/network.py @@ -1,6 +1,5 @@ from enum import IntEnum from functools import partial -from threading import Lock from typing import cast import pyray as rl @@ -50,7 +49,6 @@ class WifiManagerUI(Widget): self._networks: list[Network] = [] self._networks_buttons: dict[str, Button] = {} self._forget_networks_buttons: dict[str, Button] = {} - self._lock = Lock() self._confirm_dialog = ConfirmDialog("", "Forget", "Cancel") self.wifi_manager.set_callbacks(need_auth=self._on_need_auth, @@ -71,21 +69,22 @@ class WifiManagerUI(Widget): gui_app.texture(icon, ICON_SIZE, ICON_SIZE) def _render(self, rect: rl.Rectangle): - with self._lock: - if not self._networks: - gui_label(rect, "Scanning Wi-Fi networks...", 72, alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER) - return + self.wifi_manager.process_callbacks() - if self.state == UIState.NEEDS_AUTH and self._state_network: - self.keyboard.set_title("Wrong password" if self._password_retry else "Enter password", f"for {self._state_network.ssid}") - self.keyboard.reset() - gui_app.set_modal_overlay(self.keyboard, lambda result: self._on_password_entered(cast(Network, self._state_network), result)) - elif self.state == UIState.SHOW_FORGET_CONFIRM and self._state_network: - self._confirm_dialog.set_text(f'Forget Wi-Fi Network "{self._state_network.ssid}"?') - self._confirm_dialog.reset() - gui_app.set_modal_overlay(self._confirm_dialog, callback=lambda result: self.on_forgot_confirm_finished(self._state_network, result)) - else: - self._draw_network_list(rect) + if not self._networks: + gui_label(rect, "Scanning Wi-Fi networks...", 72, alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER) + return + + if self.state == UIState.NEEDS_AUTH and self._state_network: + self.keyboard.set_title("Wrong password" if self._password_retry else "Enter password", f"for {self._state_network.ssid}") + self.keyboard.reset() + gui_app.set_modal_overlay(self.keyboard, lambda result: self._on_password_entered(cast(Network, self._state_network), result)) + elif self.state == UIState.SHOW_FORGET_CONFIRM and self._state_network: + self._confirm_dialog.set_text(f'Forget Wi-Fi Network "{self._state_network.ssid}"?') + self._confirm_dialog.reset() + gui_app.set_modal_overlay(self._confirm_dialog, callback=lambda result: self.on_forgot_confirm_finished(self._state_network, result)) + else: + self._draw_network_list(rect) def _on_password_entered(self, network: Network, result: int): if result == 1: @@ -211,36 +210,31 @@ class WifiManagerUI(Widget): self.wifi_manager.forget_connection(network.ssid) def _on_network_updated(self, networks: list[Network]): - with self._lock: - self._networks = networks - for n in self._networks: - self._networks_buttons[n.ssid] = Button(n.ssid, partial(self._networks_buttons_callback, n), font_size=55, text_alignment=TextAlignment.LEFT, - button_style=ButtonStyle.NO_EFFECT) - self._forget_networks_buttons[n.ssid] = Button("Forget", partial(self._forget_networks_buttons_callback, n), button_style=ButtonStyle.FORGET_WIFI, - font_size=45) + self._networks = networks + for n in self._networks: + self._networks_buttons[n.ssid] = Button(n.ssid, partial(self._networks_buttons_callback, n), font_size=55, text_alignment=TextAlignment.LEFT, + button_style=ButtonStyle.NO_EFFECT) + self._forget_networks_buttons[n.ssid] = Button("Forget", partial(self._forget_networks_buttons_callback, n), button_style=ButtonStyle.FORGET_WIFI, + font_size=45) def _on_need_auth(self, ssid): - with self._lock: - network = next((n for n in self._networks if n.ssid == ssid), None) - if network: - self.state = UIState.NEEDS_AUTH - self._state_network = network - self._password_retry = True + network = next((n for n in self._networks if n.ssid == ssid), None) + if network: + self.state = UIState.NEEDS_AUTH + self._state_network = network + self._password_retry = True def _on_activated(self): - with self._lock: - if self.state == UIState.CONNECTING: - self.state = UIState.IDLE + if self.state == UIState.CONNECTING: + self.state = UIState.IDLE - def _on_forgotten(self, ssid): - with self._lock: - if self.state == UIState.FORGETTING: - self.state = UIState.IDLE + def _on_forgotten(self): + if self.state == UIState.FORGETTING: + self.state = UIState.IDLE def _on_disconnected(self): - with self._lock: - if self.state == UIState.CONNECTING: - self.state = UIState.IDLE + if self.state == UIState.CONNECTING: + self.state = UIState.IDLE def main(): From 8059106caee2500bdc8186fd9ce3ea9d36a352f9 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 26 Aug 2025 03:33:08 -0700 Subject: [PATCH 012/159] raylib networking: reduce DBus calls (#36065) * this reduces getsettings calls from n*n to n * these are combined now * same check --- system/ui/lib/wifi_manager.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/system/ui/lib/wifi_manager.py b/system/ui/lib/wifi_manager.py index 58181157c0..418c418d01 100644 --- a/system/ui/lib/wifi_manager.py +++ b/system/ui/lib/wifi_manager.py @@ -264,12 +264,12 @@ class WifiManager: return self._wifi_device - def _get_connections(self) -> list[str]: + def _get_connections(self) -> dict[str, str]: settings_addr = DBusAddress(NM_SETTINGS_PATH, bus_name=NM, interface=NM_SETTINGS_IFACE) - return list(self._router_main.send_and_get_reply(new_method_call(settings_addr, 'ListConnections')).body[0]) + known_connections = self._router_main.send_and_get_reply(new_method_call(settings_addr, 'ListConnections')).body[0] - def _connection_by_ssid(self, ssid: str, known_connections: list[str] | None = None) -> str | None: - for conn_path in known_connections or self._get_connections(): + conns: dict[str, str] = {} + for conn_path in known_connections: conn_addr = DBusAddress(conn_path, bus_name=NM, interface=NM_CONNECTION_IFACE) reply = self._router_main.send_and_get_reply(new_method_call(conn_addr, "GetSettings")) @@ -279,9 +279,11 @@ class WifiManager: continue settings = reply.body[0] - if "802-11-wireless" in settings and settings['802-11-wireless']['ssid'][1].decode("utf-8", "replace") == ssid: - return conn_path - return None + if "802-11-wireless" in settings: + ssid = settings['802-11-wireless']['ssid'][1].decode("utf-8", "replace") + if ssid != "": + conns[ssid] = conn_path + return conns def connect_to_network(self, ssid: str, password: str): def worker(): @@ -325,7 +327,7 @@ class WifiManager: def forget_connection(self, ssid: str, block: bool = False): def worker(): - conn_path = self._connection_by_ssid(ssid) + conn_path = self._get_connections().get(ssid, None) if conn_path is not None: conn_addr = DBusAddress(conn_path, bus_name=NM, interface=NM_CONNECTION_IFACE) self._router_main.send_and_get_reply(new_method_call(conn_addr, 'Delete')) @@ -341,7 +343,7 @@ class WifiManager: def activate_connection(self, ssid: str, block: bool = False): def worker(): - conn_path = self._connection_by_ssid(ssid) + conn_path = self._get_connections().get(ssid, None) if conn_path is not None: if self._wifi_device is None: cloudlog.warning("No WiFi device found") @@ -402,8 +404,7 @@ class WifiManager: cloudlog.exception(f"Failed to parse AP properties for {ap_path}") known_connections = self._get_connections() - networks = [Network.from_dbus(ssid, ap_list, self._connection_by_ssid(ssid, known_connections) is not None) - for ssid, ap_list in aps.items()] + networks = [Network.from_dbus(ssid, ap_list, ssid in known_connections) for ssid, ap_list in aps.items()] networks.sort(key=lambda n: (-n.is_connected, -n.strength, n.ssid.lower())) self._networks = networks From ec254074d12b2d8c1446d82e9762b739709952aa Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 26 Aug 2025 03:51:45 -0700 Subject: [PATCH 013/159] raylib: prevent Firehose from blocking UI (#36067) * stop blocking ui thread for 1s!! * rm * whoopsiedaisy whoopsiedaisy * meh --- selfdrive/ui/layouts/settings/firehose.py | 6 +++--- selfdrive/ui/lib/api_helpers.py | 14 ++++++++++++++ selfdrive/ui/lib/prime_state.py | 15 +++------------ 3 files changed, 20 insertions(+), 15 deletions(-) create mode 100644 selfdrive/ui/lib/api_helpers.py diff --git a/selfdrive/ui/layouts/settings/firehose.py b/selfdrive/ui/layouts/settings/firehose.py index 74a8f317d5..b3db1fa5f0 100644 --- a/selfdrive/ui/layouts/settings/firehose.py +++ b/selfdrive/ui/layouts/settings/firehose.py @@ -2,7 +2,7 @@ import pyray as rl import time import threading -from openpilot.common.api import Api, api_get +from openpilot.common.api import api_get from openpilot.common.params import Params from openpilot.common.swaglog import cloudlog from openpilot.selfdrive.ui.ui_state import ui_state @@ -11,7 +11,7 @@ from openpilot.system.ui.lib.application import gui_app, FontWeight from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel from openpilot.system.ui.lib.wrap_text import wrap_text from openpilot.system.ui.widgets import Widget - +from openpilot.selfdrive.ui.lib.api_helpers import get_token TITLE = "Firehose Mode" DESCRIPTION = ( @@ -163,7 +163,7 @@ class FirehoseLayout(Widget): dongle_id = self.params.get("DongleId") if not dongle_id or dongle_id == UNREGISTERED_DONGLE_ID: return - identity_token = Api(dongle_id).get_token() + identity_token = get_token(dongle_id) response = api_get(f"v1/devices/{dongle_id}/firehose_stats", access_token=identity_token) if response.status_code == 200: data = response.json() diff --git a/selfdrive/ui/lib/api_helpers.py b/selfdrive/ui/lib/api_helpers.py new file mode 100644 index 0000000000..b83efedb60 --- /dev/null +++ b/selfdrive/ui/lib/api_helpers.py @@ -0,0 +1,14 @@ +import time +from functools import lru_cache +from openpilot.common.api import Api + +TOKEN_EXPIRY_HOURS = 2 + + +@lru_cache(maxsize=1) +def _get_token(dongle_id: str, t: int): + return Api(dongle_id).get_token(expiry_hours=TOKEN_EXPIRY_HOURS) + + +def get_token(dongle_id: str): + return _get_token(dongle_id, int(time.monotonic() / (TOKEN_EXPIRY_HOURS / 2 * 60 * 60))) diff --git a/selfdrive/ui/lib/prime_state.py b/selfdrive/ui/lib/prime_state.py index a1b2472f30..be2132c1b7 100644 --- a/selfdrive/ui/lib/prime_state.py +++ b/selfdrive/ui/lib/prime_state.py @@ -2,14 +2,12 @@ from enum import IntEnum import os import threading import time -from functools import lru_cache -from openpilot.common.api import Api, api_get +from openpilot.common.api import api_get from openpilot.common.params import Params from openpilot.common.swaglog import cloudlog from openpilot.system.athena.registration import UNREGISTERED_DONGLE_ID - -TOKEN_EXPIRY_HOURS = 2 +from openpilot.selfdrive.ui.lib.api_helpers import get_token class PrimeType(IntEnum): @@ -23,11 +21,6 @@ class PrimeType(IntEnum): PURPLE = 5, -@lru_cache(maxsize=1) -def get_token(dongle_id: str, t: int): - return Api(dongle_id).get_token(expiry_hours=TOKEN_EXPIRY_HOURS) - - class PrimeState: FETCH_INTERVAL = 5.0 # seconds between API calls API_TIMEOUT = 10.0 # seconds for API requests @@ -57,15 +50,13 @@ class PrimeState: return try: - identity_token = get_token(dongle_id, int(time.monotonic() / (TOKEN_EXPIRY_HOURS / 2 * 60 * 60))) + identity_token = get_token(dongle_id) response = api_get(f"v1.1/devices/{dongle_id}", timeout=self.API_TIMEOUT, access_token=identity_token) if response.status_code == 200: data = response.json() is_paired = data.get("is_paired", False) prime_type = data.get("prime_type", 0) self.set_type(PrimeType(prime_type) if is_paired else PrimeType.UNPAIRED) - elif response.status_code == 401: - get_token.cache_clear() except Exception as e: cloudlog.error(f"Failed to fetch prime status: {e}") From 4cd76f4966c091a0fdb9df7dce9cfb966ed132d7 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 26 Aug 2025 03:55:05 -0700 Subject: [PATCH 014/159] raylib networking: prevent concurrently updating networks (#36066) * dont run by multiple threads at the same time! * this doesn't work since we rely on is_connected * Revert "this doesn't work since we rely on is_connected" This reverts commit 7455b2fe831bf5c9524e8ee71a9966de32a9755a. --- system/ui/lib/wifi_manager.py | 63 ++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/system/ui/lib/wifi_manager.py b/system/ui/lib/wifi_manager.py index 418c418d01..af9ae943ea 100644 --- a/system/ui/lib/wifi_manager.py +++ b/system/ui/lib/wifi_manager.py @@ -370,46 +370,47 @@ class WifiManager: cloudlog.warning(f"Failed to request scan: {reply}") def _update_networks(self): - if self._wifi_device is None: - cloudlog.warning("No WiFi device found") - return + with self._lock: + if self._wifi_device is None: + cloudlog.warning("No WiFi device found") + return - # returns '/' if no active AP - wifi_addr = DBusAddress(self._wifi_device, NM, interface=NM_WIRELESS_IFACE) - active_ap_path = self._router_main.send_and_get_reply(Properties(wifi_addr).get('ActiveAccessPoint')).body[0][1] - ap_paths = self._router_main.send_and_get_reply(new_method_call(wifi_addr, 'GetAllAccessPoints')).body[0] + # returns '/' if no active AP + wifi_addr = DBusAddress(self._wifi_device, NM, interface=NM_WIRELESS_IFACE) + active_ap_path = self._router_main.send_and_get_reply(Properties(wifi_addr).get('ActiveAccessPoint')).body[0][1] + ap_paths = self._router_main.send_and_get_reply(new_method_call(wifi_addr, 'GetAllAccessPoints')).body[0] - aps: dict[str, list[AccessPoint]] = {} + aps: dict[str, list[AccessPoint]] = {} - for ap_path in ap_paths: - ap_addr = DBusAddress(ap_path, NM, interface=NM_ACCESS_POINT_IFACE) - ap_props = self._router_main.send_and_get_reply(Properties(ap_addr).get_all()) + for ap_path in ap_paths: + ap_addr = DBusAddress(ap_path, NM, interface=NM_ACCESS_POINT_IFACE) + ap_props = self._router_main.send_and_get_reply(Properties(ap_addr).get_all()) - # some APs have been seen dropping off during iteration - if ap_props.header.message_type == MessageType.error: - cloudlog.warning(f"Failed to get AP properties for {ap_path}") - continue - - try: - ap = AccessPoint.from_dbus(ap_props.body[0], ap_path, active_ap_path) - if ap.ssid == "": + # some APs have been seen dropping off during iteration + if ap_props.header.message_type == MessageType.error: + cloudlog.warning(f"Failed to get AP properties for {ap_path}") continue - if ap.ssid not in aps: - aps[ap.ssid] = [] + try: + ap = AccessPoint.from_dbus(ap_props.body[0], ap_path, active_ap_path) + if ap.ssid == "": + continue - aps[ap.ssid].append(ap) - except Exception: - # catch all for parsing errors - cloudlog.exception(f"Failed to parse AP properties for {ap_path}") + if ap.ssid not in aps: + aps[ap.ssid] = [] - known_connections = self._get_connections() - networks = [Network.from_dbus(ssid, ap_list, ssid in known_connections) for ssid, ap_list in aps.items()] - networks.sort(key=lambda n: (-n.is_connected, -n.strength, n.ssid.lower())) - self._networks = networks + aps[ap.ssid].append(ap) + except Exception: + # catch all for parsing errors + cloudlog.exception(f"Failed to parse AP properties for {ap_path}") - if self._networks_updated is not None: - self._enqueue_callback(self._networks_updated, self._networks) + known_connections = self._get_connections() + networks = [Network.from_dbus(ssid, ap_list, ssid in known_connections) for ssid, ap_list in aps.items()] + networks.sort(key=lambda n: (-n.is_connected, -n.strength, n.ssid.lower())) + self._networks = networks + + if self._networks_updated is not None: + self._enqueue_callback(self._networks_updated, self._networks) def __del__(self): self.stop() From 8450f9f3330221caa89f38807c916f35fcbae615 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Tue, 26 Aug 2025 09:57:08 -0700 Subject: [PATCH 015/159] update: more migration --- system/updated/updated.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/system/updated/updated.py b/system/updated/updated.py index 11928bc24c..d1e745ec1a 100755 --- a/system/updated/updated.py +++ b/system/updated/updated.py @@ -243,7 +243,13 @@ class Updater: if b is None: b = self.get_branch(BASEDIR) b = { - ("tici", "release3"): "release-tici" + ("tici", "release3"): "release-tici", + ("tici", "release3-staging"): "release-tici", + ("tici", "master"): "master-tici", + ("tici", "nightly"): "release-tici", + ("tici", "nightly-dev"): "release-tici", + + ("tizi", "release3"): "release-tizi", }.get((HARDWARE.get_device_type(), b), b) return b From 8ee3c7b485a07250ae6caf341cb9daa02a31e26d Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Tue, 26 Aug 2025 11:52:58 -0700 Subject: [PATCH 016/159] add back dbus-next --- pyproject.toml | 1 + uv.lock | 23 +++++++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 556b78009d..7d6516c0fb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -101,6 +101,7 @@ dev = [ "av", "azure-identity", "azure-storage-blob", + "dbus-next", # TODO: remove once we moved everything to jeepney "dictdiffer", "jeepney", "matplotlib", diff --git a/uv.lock b/uv.lock index 72c3d2f8e2..95a60715b5 100644 --- a/uv.lock +++ b/uv.lock @@ -442,6 +442,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/56/c8/46ac27096684f33e27dab749ef43c6b0119c6a0d852971eaefb73256dc4c/cython-3.1.3-py3-none-any.whl", hash = "sha256:d13025b34f72f77bf7f65c1cd628914763e6c285f4deb934314c922b91e6be5a", size = 1225725, upload-time = "2025-08-13T06:19:09.593Z" }, ] +[[package]] +name = "dbus-next" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ce/45/6a40fbe886d60a8c26f480e7d12535502b5ba123814b3b9a0b002ebca198/dbus_next-0.2.3.tar.gz", hash = "sha256:f4eae26909332ada528c0a3549dda8d4f088f9b365153952a408e28023a626a5", size = 71112, upload-time = "2021-07-25T22:11:28.398Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/fc/c0a3f4c4eaa5a22fbef91713474666e13d0ea2a69c84532579490a9f2cc8/dbus_next-0.2.3-py3-none-any.whl", hash = "sha256:58948f9aff9db08316734c0be2a120f6dc502124d9642f55e90ac82ffb16a18b", size = 57885, upload-time = "2021-07-25T22:11:25.466Z" }, +] + [[package]] name = "dictdiffer" version = "0.9.0" @@ -1241,6 +1250,7 @@ dev = [ { name = "av" }, { name = "azure-identity" }, { name = "azure-storage-blob" }, + { name = "dbus-next" }, { name = "dictdiffer" }, { name = "jeepney" }, { name = "matplotlib" }, @@ -1294,6 +1304,7 @@ requires-dist = [ { name = "codespell", marker = "extra == 'testing'" }, { name = "crcmod" }, { name = "cython" }, + { name = "dbus-next", marker = "extra == 'dev'" }, { name = "dictdiffer", marker = "extra == 'dev'" }, { name = "future-fstrings" }, { name = "hypothesis", marker = "extra == 'testing'", specifier = "==6.47.*" }, @@ -1467,11 +1478,11 @@ wheels = [ [[package]] name = "platformdirs" -version = "4.3.8" +version = "4.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362, upload-time = "2025-05-07T22:47:42.121Z" } +sdist = { url = "https://files.pythonhosted.org/packages/23/e8/21db9c9987b0e728855bd57bff6984f67952bea55d6f75e055c46b5383e8/platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf", size = 21634, upload-time = "2025-08-26T14:32:04.268Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567, upload-time = "2025-05-07T22:47:40.376Z" }, + { url = "https://files.pythonhosted.org/packages/40/4b/2028861e724d3bd36227adfa20d3fd24c3fc6d52032f4a93c133be5d17ce/platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85", size = 18654, upload-time = "2025-08-26T14:32:02.735Z" }, ] [[package]] @@ -4629,15 +4640,15 @@ wheels = [ [[package]] name = "sentry-sdk" -version = "2.35.0" +version = "2.35.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/31/83/055dc157b719651ef13db569bb8cf2103df11174478649735c1b2bf3f6bc/sentry_sdk-2.35.0.tar.gz", hash = "sha256:5ea58d352779ce45d17bc2fa71ec7185205295b83a9dbb5707273deb64720092", size = 343014, upload-time = "2025-08-14T17:11:20.223Z" } +sdist = { url = "https://files.pythonhosted.org/packages/72/75/6223b9ffa0bf5a79ece08055469be73c18034e46ed082742a0899cc58351/sentry_sdk-2.35.1.tar.gz", hash = "sha256:241b41e059632fe1f7c54ae6e1b93af9456aebdfc297be9cf7ecfd6da5167e8e", size = 343145, upload-time = "2025-08-26T08:23:32.429Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/3d/742617a7c644deb0c1628dcf6bb2d2165ab7c6aab56fe5222758994007f8/sentry_sdk-2.35.0-py2.py3-none-any.whl", hash = "sha256:6e0c29b9a5d34de8575ffb04d289a987ff3053cf2c98ede445bea995e3830263", size = 363806, upload-time = "2025-08-14T17:11:18.29Z" }, + { url = "https://files.pythonhosted.org/packages/62/1f/5feb6c42cc30126e9574eabc28139f8c626b483a47c537f648d133628df0/sentry_sdk-2.35.1-py2.py3-none-any.whl", hash = "sha256:13b6d6cfdae65d61fe1396a061cf9113b20f0ec1bcb257f3826b88f01bb55720", size = 363887, upload-time = "2025-08-26T08:23:30.335Z" }, ] [[package]] From f5d67b5eee14b3f7a0f31cee875338f4cc88b46a Mon Sep 17 00:00:00 2001 From: Jaume Balust Date: Tue, 26 Aug 2025 16:23:24 -0600 Subject: [PATCH 017/159] cereal: fix frequency precision by changing from int to float (#36060) --- cereal/messaging/socketmaster.cc | 2 +- cereal/services.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cereal/messaging/socketmaster.cc b/cereal/messaging/socketmaster.cc index 1a7a48980e..7f7e2795c4 100644 --- a/cereal/messaging/socketmaster.cc +++ b/cereal/messaging/socketmaster.cc @@ -33,7 +33,7 @@ MessageContext message_context; struct SubMaster::SubMessage { std::string name; SubSocket *socket = nullptr; - int freq = 0; + float freq = 0.0f; bool updated = false, alive = false, valid = false, ignore_alive; uint64_t rcv_time = 0, rcv_frame = 0; void *allocated_msg_reader = nullptr; diff --git a/cereal/services.py b/cereal/services.py index a4c7463f20..edeca412ce 100755 --- a/cereal/services.py +++ b/cereal/services.py @@ -109,12 +109,12 @@ def build_header(): h += "#include \n" h += "#include \n" - h += "struct service { std::string name; bool should_log; int frequency; int decimation; };\n" + h += "struct service { std::string name; bool should_log; float frequency; int decimation; };\n" h += "static std::map services = {\n" for k, v in SERVICE_LIST.items(): should_log = "true" if v.should_log else "false" decimation = -1 if v.decimation is None else v.decimation - h += ' { "%s", {"%s", %s, %d, %d}},\n' % \ + h += ' { "%s", {"%s", %s, %f, %d}},\n' % \ (k, k, should_log, v.frequency, decimation) h += "};\n" From 82582576587c9c6d89ccf85f7bd306f23be396a2 Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Tue, 26 Aug 2025 15:34:34 -0700 Subject: [PATCH 018/159] ci: modernize test onroad (#36059) * start * fix * better * more * test * Revert "test" This reverts commit 17066ac123668cb7280cf85e3f21a3043b4785b0. * remove --- Jenkinsfile | 9 ++++----- selfdrive/test/test_onroad.py | 17 +++-------------- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 0905abd6da..f0c0cf1370 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -178,7 +178,7 @@ node { try { if (env.BRANCH_NAME == 'devel-staging') { - deviceStage("build release3-staging", "tici-needs-can", [], [ + deviceStage("build release3-staging", "tizi-needs-can", [], [ step("build release3-staging", "RELEASE_BRANCH=release3-staging $SOURCE_DIR/release/build_release.sh"), ]) } @@ -186,12 +186,12 @@ node { if (env.BRANCH_NAME == '__nightly') { parallel ( 'nightly': { - deviceStage("build nightly", "tici-needs-can", [], [ + deviceStage("build nightly", "tizi-needs-can", [], [ step("build nightly", "RELEASE_BRANCH=nightly $SOURCE_DIR/release/build_release.sh"), ]) }, 'nightly-dev': { - deviceStage("build nightly-dev", "tici-needs-can", [], [ + deviceStage("build nightly-dev", "tizi-needs-can", [], [ step("build nightly-dev", "PANDA_DEBUG_BUILD=1 RELEASE_BRANCH=nightly-dev $SOURCE_DIR/release/build_release.sh"), ]) }, @@ -200,9 +200,8 @@ node { if (!env.BRANCH_NAME.matches(excludeRegex)) { parallel ( - // tici tests 'onroad tests': { - deviceStage("onroad", "tici-needs-can", ["UNSAFE=1"], [ + deviceStage("onroad", "tizi-needs-can", ["UNSAFE=1"], [ step("build openpilot", "cd system/manager && ./build.py"), step("check dirty", "release/check-dirty.sh"), step("onroad tests", "pytest selfdrive/test/test_onroad.py -s", [timeout: 60]), diff --git a/selfdrive/test/test_onroad.py b/selfdrive/test/test_onroad.py index 0149653c84..3cb1af10df 100644 --- a/selfdrive/test/test_onroad.py +++ b/selfdrive/test/test_onroad.py @@ -18,7 +18,6 @@ from openpilot.common.timeout import Timeout from openpilot.common.params import Params from openpilot.selfdrive.selfdrived.events import EVENTS, ET from openpilot.selfdrive.test.helpers import set_params_enabled, release_only -from openpilot.system.hardware import HARDWARE from openpilot.system.hardware.hw import Paths from openpilot.tools.lib.logreader import LogReader from openpilot.tools.lib.log_time_series import msgs_to_time_series @@ -33,7 +32,7 @@ CPU usage budget TEST_DURATION = 25 LOG_OFFSET = 8 -MAX_TOTAL_CPU = 280. # total for all 8 cores +MAX_TOTAL_CPU = 287. # total for all 8 cores PROCS = { # Baseline CPU usage by process "selfdrive.controls.controlsd": 16.0, @@ -67,20 +66,10 @@ PROCS = { "system.statsd": 1.0, "system.loggerd.uploader": 15.0, "system.loggerd.deleter": 1.0, + "./pandad": 19.0, + "system.qcomgpsd.qcomgpsd": 1.0, } -PROCS.update({ - "tici": { - "./pandad": 5.0, - "./ubloxd": 1.0, - "system.ubloxd.pigeond": 6.0, - }, - "tizi": { - "./pandad": 19.0, - "system.qcomgpsd.qcomgpsd": 1.0, - } -}.get(HARDWARE.get_device_type(), {})) - TIMINGS = { # rtols: max/min, rsd "can": [2.5, 0.35], From ea6677c464f74b429ccb2dd4e367b1e6ef4a3cdd Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Tue, 26 Aug 2025 17:16:57 -0700 Subject: [PATCH 019/159] AGNOS 13 (#36069) * staging * prod --- launch_env.sh | 2 +- system/hardware/tici/agnos.json | 28 ++++++------- system/hardware/tici/all-partitions.json | 52 ++++++++++++------------ 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/launch_env.sh b/launch_env.sh index 4c011c6ac0..7124b360f8 100755 --- a/launch_env.sh +++ b/launch_env.sh @@ -7,7 +7,7 @@ export OPENBLAS_NUM_THREADS=1 export VECLIB_MAXIMUM_THREADS=1 if [ -z "$AGNOS_VERSION" ]; then - export AGNOS_VERSION="12.8" + export AGNOS_VERSION="13" fi export STAGING_ROOT="/data/safe_staging" diff --git a/system/hardware/tici/agnos.json b/system/hardware/tici/agnos.json index 941a4956bf..b252a8110e 100644 --- a/system/hardware/tici/agnos.json +++ b/system/hardware/tici/agnos.json @@ -23,14 +23,14 @@ }, { "name": "abl", - "url": "https://commadist.azureedge.net/agnosupdate/abl-32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6.img.xz", - "hash": "32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6", - "hash_raw": "32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6", + "url": "https://commadist.azureedge.net/agnosupdate/abl-556bbb4ed1c671402b217bd2f3c07edce4f88b0bbd64e92241b82e396aa9ebee.img.xz", + "hash": "556bbb4ed1c671402b217bd2f3c07edce4f88b0bbd64e92241b82e396aa9ebee", + "hash_raw": "556bbb4ed1c671402b217bd2f3c07edce4f88b0bbd64e92241b82e396aa9ebee", "size": 274432, "sparse": false, "full_check": true, "has_ab": true, - "ondevice_hash": "32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6" + "ondevice_hash": "556bbb4ed1c671402b217bd2f3c07edce4f88b0bbd64e92241b82e396aa9ebee" }, { "name": "aop", @@ -56,28 +56,28 @@ }, { "name": "boot", - "url": "https://commadist.azureedge.net/agnosupdate/boot-0191529aa97d90d1fa04b472d80230b777606459e1e1e9e2323c9519839827b4.img.xz", - "hash": "0191529aa97d90d1fa04b472d80230b777606459e1e1e9e2323c9519839827b4", - "hash_raw": "0191529aa97d90d1fa04b472d80230b777606459e1e1e9e2323c9519839827b4", + "url": "https://commadist.azureedge.net/agnosupdate/boot-3e26a0d330a1be1614a5c25cae238ca5d01c1be90802ad296c805c3bcbad0e7a.img.xz", + "hash": "3e26a0d330a1be1614a5c25cae238ca5d01c1be90802ad296c805c3bcbad0e7a", + "hash_raw": "3e26a0d330a1be1614a5c25cae238ca5d01c1be90802ad296c805c3bcbad0e7a", "size": 18515968, "sparse": false, "full_check": true, "has_ab": true, - "ondevice_hash": "492ae27f569e8db457c79d0e358a7a6297d1a1c685c2b1ae6deba7315d3a6cb0" + "ondevice_hash": "41d693d7e752c04210b4f8d68015d2367ee83e1cd54cc7b0aca3b79b4855e6b1" }, { "name": "system", - "url": "https://commadist.azureedge.net/agnosupdate/system-e0007afa5d1026671c1943d44bb7f7ad26259f673392dd00a03073a2870df087.img.xz", - "hash": "1468d50b7ad0fda0f04074755d21e786e3b1b6ca5dd5b17eb2608202025e6126", - "hash_raw": "e0007afa5d1026671c1943d44bb7f7ad26259f673392dd00a03073a2870df087", + "url": "https://commadist.azureedge.net/agnosupdate/system-4d0c7005e242fc757adbefd43b44ab2e78be53ca5145fceb160cc32ecf8d6cc3.img.xz", + "hash": "3596cd5d8a51dabcdd75c29f9317ca3dad9036b1083630ad719eaf584fdb1ce9", + "hash_raw": "4d0c7005e242fc757adbefd43b44ab2e78be53ca5145fceb160cc32ecf8d6cc3", "size": 5368709120, "sparse": true, "full_check": false, "has_ab": true, - "ondevice_hash": "242aa5adad1c04e1398e00e2440d1babf962022eb12b89adf2e60ee3068946e7", + "ondevice_hash": "32cdbc0ce176e0ea92944e53be875c12374512fa09b6041e42e683519d36591e", "alt": { - "hash": "e0007afa5d1026671c1943d44bb7f7ad26259f673392dd00a03073a2870df087", - "url": "https://commadist.azureedge.net/agnosupdate/system-e0007afa5d1026671c1943d44bb7f7ad26259f673392dd00a03073a2870df087.img", + "hash": "4d0c7005e242fc757adbefd43b44ab2e78be53ca5145fceb160cc32ecf8d6cc3", + "url": "https://commadist.azureedge.net/agnosupdate/system-4d0c7005e242fc757adbefd43b44ab2e78be53ca5145fceb160cc32ecf8d6cc3.img", "size": 5368709120 } } diff --git a/system/hardware/tici/all-partitions.json b/system/hardware/tici/all-partitions.json index 5891e2748a..8bc6680b98 100644 --- a/system/hardware/tici/all-partitions.json +++ b/system/hardware/tici/all-partitions.json @@ -152,14 +152,14 @@ }, { "name": "abl", - "url": "https://commadist.azureedge.net/agnosupdate/abl-32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6.img.xz", - "hash": "32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6", - "hash_raw": "32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6", + "url": "https://commadist.azureedge.net/agnosupdate/abl-556bbb4ed1c671402b217bd2f3c07edce4f88b0bbd64e92241b82e396aa9ebee.img.xz", + "hash": "556bbb4ed1c671402b217bd2f3c07edce4f88b0bbd64e92241b82e396aa9ebee", + "hash_raw": "556bbb4ed1c671402b217bd2f3c07edce4f88b0bbd64e92241b82e396aa9ebee", "size": 274432, "sparse": false, "full_check": true, "has_ab": true, - "ondevice_hash": "32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6" + "ondevice_hash": "556bbb4ed1c671402b217bd2f3c07edce4f88b0bbd64e92241b82e396aa9ebee" }, { "name": "aop", @@ -339,62 +339,62 @@ }, { "name": "boot", - "url": "https://commadist.azureedge.net/agnosupdate/boot-0191529aa97d90d1fa04b472d80230b777606459e1e1e9e2323c9519839827b4.img.xz", - "hash": "0191529aa97d90d1fa04b472d80230b777606459e1e1e9e2323c9519839827b4", - "hash_raw": "0191529aa97d90d1fa04b472d80230b777606459e1e1e9e2323c9519839827b4", + "url": "https://commadist.azureedge.net/agnosupdate/boot-3e26a0d330a1be1614a5c25cae238ca5d01c1be90802ad296c805c3bcbad0e7a.img.xz", + "hash": "3e26a0d330a1be1614a5c25cae238ca5d01c1be90802ad296c805c3bcbad0e7a", + "hash_raw": "3e26a0d330a1be1614a5c25cae238ca5d01c1be90802ad296c805c3bcbad0e7a", "size": 18515968, "sparse": false, "full_check": true, "has_ab": true, - "ondevice_hash": "492ae27f569e8db457c79d0e358a7a6297d1a1c685c2b1ae6deba7315d3a6cb0" + "ondevice_hash": "41d693d7e752c04210b4f8d68015d2367ee83e1cd54cc7b0aca3b79b4855e6b1" }, { "name": "system", - "url": "https://commadist.azureedge.net/agnosupdate/system-e0007afa5d1026671c1943d44bb7f7ad26259f673392dd00a03073a2870df087.img.xz", - "hash": "1468d50b7ad0fda0f04074755d21e786e3b1b6ca5dd5b17eb2608202025e6126", - "hash_raw": "e0007afa5d1026671c1943d44bb7f7ad26259f673392dd00a03073a2870df087", + "url": "https://commadist.azureedge.net/agnosupdate/system-4d0c7005e242fc757adbefd43b44ab2e78be53ca5145fceb160cc32ecf8d6cc3.img.xz", + "hash": "3596cd5d8a51dabcdd75c29f9317ca3dad9036b1083630ad719eaf584fdb1ce9", + "hash_raw": "4d0c7005e242fc757adbefd43b44ab2e78be53ca5145fceb160cc32ecf8d6cc3", "size": 5368709120, "sparse": true, "full_check": false, "has_ab": true, - "ondevice_hash": "242aa5adad1c04e1398e00e2440d1babf962022eb12b89adf2e60ee3068946e7", + "ondevice_hash": "32cdbc0ce176e0ea92944e53be875c12374512fa09b6041e42e683519d36591e", "alt": { - "hash": "e0007afa5d1026671c1943d44bb7f7ad26259f673392dd00a03073a2870df087", - "url": "https://commadist.azureedge.net/agnosupdate/system-e0007afa5d1026671c1943d44bb7f7ad26259f673392dd00a03073a2870df087.img", + "hash": "4d0c7005e242fc757adbefd43b44ab2e78be53ca5145fceb160cc32ecf8d6cc3", + "url": "https://commadist.azureedge.net/agnosupdate/system-4d0c7005e242fc757adbefd43b44ab2e78be53ca5145fceb160cc32ecf8d6cc3.img", "size": 5368709120 } }, { "name": "userdata_90", - "url": "https://commadist.azureedge.net/agnosupdate/userdata_90-602d5103cba97e1b07f76508d5febb47cfc4463a7e31bd20e461b55c801feb0a.img.xz", - "hash": "6a11d448bac50467791809339051eed2894aae971c37bf6284b3b972a99ba3ac", - "hash_raw": "602d5103cba97e1b07f76508d5febb47cfc4463a7e31bd20e461b55c801feb0a", + "url": "https://commadist.azureedge.net/agnosupdate/userdata_90-a3695e6b4bade3dd9c2711cd92e93e9ac7744207c2af03b78f0b9a17e89d357f.img.xz", + "hash": "eeb50afb13973d7e54013fdb3ce0f4f396b8608c8325442966cad6b67e39a8d9", + "hash_raw": "a3695e6b4bade3dd9c2711cd92e93e9ac7744207c2af03b78f0b9a17e89d357f", "size": 96636764160, "sparse": true, "full_check": true, "has_ab": false, - "ondevice_hash": "e014d92940a696bf8582807259820ab73948b950656ed83a45da738f26083705" + "ondevice_hash": "537088b516805b32b1b4ad176e7f3fc6bc828e296398ce65cbf5f6150fb1a26f" }, { "name": "userdata_89", - "url": "https://commadist.azureedge.net/agnosupdate/userdata_89-4d7f6d12a5557eb6e3cbff9a4cd595677456fdfddcc879eddcea96a43a9d8b48.img.xz", - "hash": "748e31a5fc01fc256c012e359c3382d1f98cce98feafe8ecc0fca3e47caef116", - "hash_raw": "4d7f6d12a5557eb6e3cbff9a4cd595677456fdfddcc879eddcea96a43a9d8b48", + "url": "https://commadist.azureedge.net/agnosupdate/userdata_89-cbe9979b42b265c9e25a50e876faf5b592fe175aeb5936f2a97b345a6d4e53f5.img.xz", + "hash": "9456a8b117736e6f8eb35cc97fc62ddc8255f38a1be5959a6911498d6aaee08d", + "hash_raw": "cbe9979b42b265c9e25a50e876faf5b592fe175aeb5936f2a97b345a6d4e53f5", "size": 95563022336, "sparse": true, "full_check": true, "has_ab": false, - "ondevice_hash": "c181b93050787adcfef730c086bcb780f28508d84e6376d9b80d37e5dc02b55e" + "ondevice_hash": "9e7293cf9a377cb2f3477698e7143e6085a42f7355d7eace5bf9e590992941a8" }, { "name": "userdata_30", - "url": "https://commadist.azureedge.net/agnosupdate/userdata_30-80a76c8e56bbd7536fd5e87e8daa12984e2960db4edeb1f83229b2baeecc4668.img.xz", - "hash": "09ff390e639e4373d772e1688d05a5ac77a573463ed1deeff86390686fa686f9", - "hash_raw": "80a76c8e56bbd7536fd5e87e8daa12984e2960db4edeb1f83229b2baeecc4668", + "url": "https://commadist.azureedge.net/agnosupdate/userdata_30-0b25bb660f1c0c4475fc22a32a51cd32bb980f55b95069e6ab56dd8e47f00c31.img.xz", + "hash": "6c5c98c0fec64355ead5dfc9c1902653b4ea9a071e7b968d1ccd36565082f6b7", + "hash_raw": "0b25bb660f1c0c4475fc22a32a51cd32bb980f55b95069e6ab56dd8e47f00c31", "size": 32212254720, "sparse": true, "full_check": true, "has_ab": false, - "ondevice_hash": "2c01ab470c02121c721ff6afc25582437e821686207f3afef659387afb69c507" + "ondevice_hash": "42b5c09a36866d9a52e78b038901669d5bebb02176c498ce11618f200bdfe6b5" } ] \ No newline at end of file From f40f7f9ecee7a51dcc9f07b9337247e9bc2592c0 Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Tue, 26 Aug 2025 21:45:49 -0700 Subject: [PATCH 020/159] Revert "torqued: apply offset (#36005)" This reverts commit 1d74a97ba65b9b9ea074ef870ab70907be33918c. --- selfdrive/controls/lib/latcontrol_torque.py | 6 +- .../tests/test_torqued_lat_accel_offset.py | 71 ------------------- selfdrive/test/process_replay/ref_commit | 2 +- 3 files changed, 4 insertions(+), 75 deletions(-) delete mode 100644 selfdrive/controls/tests/test_torqued_lat_accel_offset.py diff --git a/selfdrive/controls/lib/latcontrol_torque.py b/selfdrive/controls/lib/latcontrol_torque.py index 5a2814e089..dffe85c473 100644 --- a/selfdrive/controls/lib/latcontrol_torque.py +++ b/selfdrive/controls/lib/latcontrol_torque.py @@ -52,8 +52,10 @@ class LatControlTorque(LatControl): actual_curvature = -VM.calc_curvature(math.radians(CS.steeringAngleDeg - params.angleOffsetDeg), CS.vEgo, params.roll) roll_compensation = params.roll * ACCELERATION_DUE_TO_GRAVITY curvature_deadzone = abs(VM.calc_curvature(math.radians(self.steering_angle_deadzone_deg), CS.vEgo, 0.0)) - desired_lateral_accel = desired_curvature * CS.vEgo ** 2 + + # desired rate is the desired rate of change in the setpoint, not the absolute desired curvature + # desired_lateral_jerk = desired_curvature_rate * CS.vEgo ** 2 actual_lateral_accel = actual_curvature * CS.vEgo ** 2 lateral_accel_deadzone = curvature_deadzone * CS.vEgo ** 2 @@ -65,8 +67,6 @@ class LatControlTorque(LatControl): # do error correction in lateral acceleration space, convert at end to handle non-linear torque responses correctly pid_log.error = float(setpoint - measurement) ff = gravity_adjusted_lateral_accel - # latAccelOffset corrects roll compensation bias from device roll misalignment relative to car roll - ff -= self.torque_params.latAccelOffset ff += get_friction(desired_lateral_accel - actual_lateral_accel, lateral_accel_deadzone, FRICTION_THRESHOLD, self.torque_params) freeze_integrator = steer_limited_by_safety or CS.steeringPressed or CS.vEgo < 5 diff --git a/selfdrive/controls/tests/test_torqued_lat_accel_offset.py b/selfdrive/controls/tests/test_torqued_lat_accel_offset.py deleted file mode 100644 index 5ba9980020..0000000000 --- a/selfdrive/controls/tests/test_torqued_lat_accel_offset.py +++ /dev/null @@ -1,71 +0,0 @@ -import numpy as np -from cereal import car, messaging -from opendbc.car import ACCELERATION_DUE_TO_GRAVITY -from opendbc.car import structs -from opendbc.car.lateral import get_friction, FRICTION_THRESHOLD -from openpilot.common.realtime import DT_MDL -from openpilot.selfdrive.locationd.torqued import TorqueEstimator, MIN_BUCKET_POINTS, POINTS_PER_BUCKET, STEER_BUCKET_BOUNDS - -np.random.seed(0) - -LA_ERR_STD = 1.0 -INPUT_NOISE_STD = 0.1 -V_EGO = 30.0 - -WARMUP_BUCKET_POINTS = (1.5*MIN_BUCKET_POINTS).astype(int) -STRAIGHT_ROAD_LA_BOUNDS = (0.02, 0.03) - -ROLL_BIAS_DEG = 1.0 -ROLL_COMPENSATION_BIAS = ACCELERATION_DUE_TO_GRAVITY*float(np.sin(np.deg2rad(ROLL_BIAS_DEG))) -TORQUE_TUNE = structs.CarParams.LateralTorqueTuning(latAccelFactor=2.0, latAccelOffset=0.0, friction=0.2) -TORQUE_TUNE_BIASED = structs.CarParams.LateralTorqueTuning(latAccelFactor=2.0, latAccelOffset=-ROLL_COMPENSATION_BIAS, friction=0.2) - - -def generate_inputs(torque_tune, la_err_std, input_noise_std=None): - rng = np.random.default_rng(0) - steer_torques = np.concat([rng.uniform(bnd[0], bnd[1], pts) for bnd, pts in zip(STEER_BUCKET_BOUNDS, WARMUP_BUCKET_POINTS, strict=True)]) - la_errs = rng.normal(scale=la_err_std, size=steer_torques.size) - frictions = np.array([get_friction(la_err, 0.0, FRICTION_THRESHOLD, torque_tune) for la_err in la_errs]) - lat_accels = torque_tune.latAccelFactor*steer_torques + torque_tune.latAccelOffset + frictions - if input_noise_std is not None: - steer_torques += rng.normal(scale=input_noise_std, size=steer_torques.size) - lat_accels += rng.normal(scale=input_noise_std, size=steer_torques.size) - return steer_torques, lat_accels - -def get_warmed_up_estimator(steer_torques, lat_accels): - est = TorqueEstimator(car.CarParams()) - for steer_torque, lat_accel in zip(steer_torques, lat_accels, strict=True): - est.filtered_points.add_point(steer_torque, lat_accel) - return est - -def simulate_straight_road_msgs(est): - carControl = messaging.new_message('carControl').carControl - carOutput = messaging.new_message('carOutput').carOutput - carState = messaging.new_message('carState').carState - livePose = messaging.new_message('livePose').livePose - carControl.latActive = True - carState.vEgo = V_EGO - carState.steeringPressed = False - ts = DT_MDL*np.arange(2*POINTS_PER_BUCKET) - steer_torques = np.concat((np.linspace(-0.03, -0.02, POINTS_PER_BUCKET), np.linspace(0.02, 0.03, POINTS_PER_BUCKET))) - lat_accels = TORQUE_TUNE.latAccelFactor * steer_torques - for t, steer_torque, lat_accel in zip(ts, steer_torques, lat_accels, strict=True): - carOutput.actuatorsOutput.torque = float(-steer_torque) - livePose.orientationNED.x = float(np.deg2rad(ROLL_BIAS_DEG)) - livePose.angularVelocityDevice.z = float(lat_accel / V_EGO) - for which, msg in (('carControl', carControl), ('carOutput', carOutput), ('carState', carState), ('livePose', livePose)): - est.handle_log(t, which, msg) - -def test_estimated_offset(): - steer_torques, lat_accels = generate_inputs(TORQUE_TUNE_BIASED, la_err_std=LA_ERR_STD, input_noise_std=INPUT_NOISE_STD) - est = get_warmed_up_estimator(steer_torques, lat_accels) - msg = est.get_msg() - # TODO add lataccelfactor and friction check when we have more accurate estimates - assert abs(msg.liveTorqueParameters.latAccelOffsetRaw - TORQUE_TUNE_BIASED.latAccelOffset) < 0.03 - -def test_straight_road_roll_bias(): - steer_torques, lat_accels = generate_inputs(TORQUE_TUNE, la_err_std=LA_ERR_STD, input_noise_std=INPUT_NOISE_STD) - est = get_warmed_up_estimator(steer_torques, lat_accels) - simulate_straight_road_msgs(est) - msg = est.get_msg() - assert (msg.liveTorqueParameters.latAccelOffsetRaw < -0.05) and np.isfinite(msg.liveTorqueParameters.latAccelOffsetRaw) diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 7d21526144..8e4ff1e2a8 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -866f2cb1f0e49b2cb7115aa8131164b3a75fb2c5 \ No newline at end of file +209b47bea61e145cf2d27eb3ab650c97bcd1d33f \ No newline at end of file From b976135d2f3c2ea7c28bf6b92084068f38c7d108 Mon Sep 17 00:00:00 2001 From: felsager <76905857+felsager@users.noreply.github.com> Date: Wed, 27 Aug 2025 13:06:01 -0700 Subject: [PATCH 021/159] torqued: apply offset (with more robust unit test) (#36075) * torqued: apply latAccelOffset to torque control feed forward * test learned latAccelOffset captures roll compensation bias on straight road driving, when the device is not flush in roll relative to the car * test correct torqued latAccelOffset parameter convergence --- selfdrive/controls/lib/latcontrol_torque.py | 6 +- .../tests/test_torqued_lat_accel_offset.py | 70 +++++++++++++++++++ selfdrive/test/process_replay/ref_commit | 2 +- 3 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 selfdrive/controls/tests/test_torqued_lat_accel_offset.py diff --git a/selfdrive/controls/lib/latcontrol_torque.py b/selfdrive/controls/lib/latcontrol_torque.py index dffe85c473..5a2814e089 100644 --- a/selfdrive/controls/lib/latcontrol_torque.py +++ b/selfdrive/controls/lib/latcontrol_torque.py @@ -52,10 +52,8 @@ class LatControlTorque(LatControl): actual_curvature = -VM.calc_curvature(math.radians(CS.steeringAngleDeg - params.angleOffsetDeg), CS.vEgo, params.roll) roll_compensation = params.roll * ACCELERATION_DUE_TO_GRAVITY curvature_deadzone = abs(VM.calc_curvature(math.radians(self.steering_angle_deadzone_deg), CS.vEgo, 0.0)) - desired_lateral_accel = desired_curvature * CS.vEgo ** 2 - # desired rate is the desired rate of change in the setpoint, not the absolute desired curvature - # desired_lateral_jerk = desired_curvature_rate * CS.vEgo ** 2 + desired_lateral_accel = desired_curvature * CS.vEgo ** 2 actual_lateral_accel = actual_curvature * CS.vEgo ** 2 lateral_accel_deadzone = curvature_deadzone * CS.vEgo ** 2 @@ -67,6 +65,8 @@ class LatControlTorque(LatControl): # do error correction in lateral acceleration space, convert at end to handle non-linear torque responses correctly pid_log.error = float(setpoint - measurement) ff = gravity_adjusted_lateral_accel + # latAccelOffset corrects roll compensation bias from device roll misalignment relative to car roll + ff -= self.torque_params.latAccelOffset ff += get_friction(desired_lateral_accel - actual_lateral_accel, lateral_accel_deadzone, FRICTION_THRESHOLD, self.torque_params) freeze_integrator = steer_limited_by_safety or CS.steeringPressed or CS.vEgo < 5 diff --git a/selfdrive/controls/tests/test_torqued_lat_accel_offset.py b/selfdrive/controls/tests/test_torqued_lat_accel_offset.py new file mode 100644 index 0000000000..84389856b6 --- /dev/null +++ b/selfdrive/controls/tests/test_torqued_lat_accel_offset.py @@ -0,0 +1,70 @@ +import numpy as np +from cereal import car, messaging +from opendbc.car import ACCELERATION_DUE_TO_GRAVITY +from opendbc.car import structs +from opendbc.car.lateral import get_friction, FRICTION_THRESHOLD +from openpilot.common.realtime import DT_MDL +from openpilot.selfdrive.locationd.torqued import TorqueEstimator, MIN_BUCKET_POINTS, POINTS_PER_BUCKET, STEER_BUCKET_BOUNDS + +np.random.seed(0) + +LA_ERR_STD = 1.0 +INPUT_NOISE_STD = 0.08 +V_EGO = 30.0 + +WARMUP_BUCKET_POINTS = (1.5*MIN_BUCKET_POINTS).astype(int) +STRAIGHT_ROAD_LA_BOUNDS = (0.02, 0.03) + +ROLL_BIAS_DEG = 2.0 +ROLL_COMPENSATION_BIAS = ACCELERATION_DUE_TO_GRAVITY*float(np.sin(np.deg2rad(ROLL_BIAS_DEG))) +TORQUE_TUNE = structs.CarParams.LateralTorqueTuning(latAccelFactor=2.0, latAccelOffset=0.0, friction=0.2) +TORQUE_TUNE_BIASED = structs.CarParams.LateralTorqueTuning(latAccelFactor=2.0, latAccelOffset=-ROLL_COMPENSATION_BIAS, friction=0.2) + +def generate_inputs(torque_tune, la_err_std, input_noise_std=None): + rng = np.random.default_rng(0) + steer_torques = np.concat([rng.uniform(bnd[0], bnd[1], pts) for bnd, pts in zip(STEER_BUCKET_BOUNDS, WARMUP_BUCKET_POINTS, strict=True)]) + la_errs = rng.normal(scale=la_err_std, size=steer_torques.size) + frictions = np.array([get_friction(la_err, 0.0, FRICTION_THRESHOLD, torque_tune) for la_err in la_errs]) + lat_accels = torque_tune.latAccelFactor*steer_torques + torque_tune.latAccelOffset + frictions + if input_noise_std is not None: + steer_torques += rng.normal(scale=input_noise_std, size=steer_torques.size) + lat_accels += rng.normal(scale=input_noise_std, size=steer_torques.size) + return steer_torques, lat_accels + +def get_warmed_up_estimator(steer_torques, lat_accels): + est = TorqueEstimator(car.CarParams()) + for steer_torque, lat_accel in zip(steer_torques, lat_accels, strict=True): + est.filtered_points.add_point(steer_torque, lat_accel) + return est + +def simulate_straight_road_msgs(est): + carControl = messaging.new_message('carControl').carControl + carOutput = messaging.new_message('carOutput').carOutput + carState = messaging.new_message('carState').carState + livePose = messaging.new_message('livePose').livePose + carControl.latActive = True + carState.vEgo = V_EGO + carState.steeringPressed = False + ts = DT_MDL*np.arange(2*POINTS_PER_BUCKET) + steer_torques = np.concat((np.linspace(-0.03, -0.02, POINTS_PER_BUCKET), np.linspace(0.02, 0.03, POINTS_PER_BUCKET))) + lat_accels = TORQUE_TUNE.latAccelFactor * steer_torques + for t, steer_torque, lat_accel in zip(ts, steer_torques, lat_accels, strict=True): + carOutput.actuatorsOutput.torque = float(-steer_torque) + livePose.orientationNED.x = float(np.deg2rad(ROLL_BIAS_DEG)) + livePose.angularVelocityDevice.z = float(lat_accel / V_EGO) + for which, msg in (('carControl', carControl), ('carOutput', carOutput), ('carState', carState), ('livePose', livePose)): + est.handle_log(t, which, msg) + +def test_estimated_offset(): + steer_torques, lat_accels = generate_inputs(TORQUE_TUNE_BIASED, la_err_std=LA_ERR_STD, input_noise_std=INPUT_NOISE_STD) + est = get_warmed_up_estimator(steer_torques, lat_accels) + msg = est.get_msg() + # TODO add lataccelfactor and friction check when we have more accurate estimates + assert abs(msg.liveTorqueParameters.latAccelOffsetRaw - TORQUE_TUNE_BIASED.latAccelOffset) < 0.1 + +def test_straight_road_roll_bias(): + steer_torques, lat_accels = generate_inputs(TORQUE_TUNE, la_err_std=LA_ERR_STD, input_noise_std=INPUT_NOISE_STD) + est = get_warmed_up_estimator(steer_torques, lat_accels) + simulate_straight_road_msgs(est) + msg = est.get_msg() + assert (msg.liveTorqueParameters.latAccelOffsetRaw < -0.05) and np.isfinite(msg.liveTorqueParameters.latAccelOffsetRaw) diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 8e4ff1e2a8..e1133061f5 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -209b47bea61e145cf2d27eb3ab650c97bcd1d33f \ No newline at end of file +4c677a3ebcbd3d4faa3de98e3fb9c0bb83b47926 \ No newline at end of file From 375dfe16a80c60c52934bf998de9be2c3b21ec59 Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Wed, 27 Aug 2025 13:39:21 -0700 Subject: [PATCH 022/159] jenkins: remove bmx device --- Jenkinsfile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index f0c0cf1370..76f7f2cea4 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -249,10 +249,6 @@ node { step("build", "cd system/manager && ./build.py"), step("test sensord", "pytest system/sensord/tests/test_sensord.py"), ]) - deviceStage("BMX + LSM", "tici-bmx-lsm", ["UNSAFE=1"], [ - step("build", "cd system/manager && ./build.py"), - step("test sensord", "pytest system/sensord/tests/test_sensord.py"), - ]) }, 'replay': { deviceStage("model-replay", "tici-replay", ["UNSAFE=1"], [ From f8ff156869f4abc64c595dc2a442071df4c8543d Mon Sep 17 00:00:00 2001 From: ZwX1616 Date: Wed, 27 Aug 2025 13:48:23 -0700 Subject: [PATCH 023/159] modeld: desire->desire_pulse (#36076) consistent naming --- selfdrive/modeld/modeld.py | 12 ++++++------ selfdrive/modeld/models/driving_policy.onnx | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/selfdrive/modeld/modeld.py b/selfdrive/modeld/modeld.py index 8bc8bf01ab..6e09f40e22 100755 --- a/selfdrive/modeld/modeld.py +++ b/selfdrive/modeld/modeld.py @@ -106,7 +106,7 @@ class ModelState: # policy inputs self.numpy_inputs = { - 'desire': np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.DESIRE_LEN), dtype=np.float32), + 'desire_pulse': np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.DESIRE_LEN), dtype=np.float32), 'traffic_convention': np.zeros((1, ModelConstants.TRAFFIC_CONVENTION_LEN), dtype=np.float32), 'features_buffer': np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32), } @@ -131,13 +131,13 @@ class ModelState: def run(self, bufs: dict[str, VisionBuf], transforms: dict[str, np.ndarray], inputs: dict[str, np.ndarray], prepare_only: bool) -> dict[str, np.ndarray] | None: # Model decides when action is completed, so desire input is just a pulse triggered on rising edge - inputs['desire'][0] = 0 - new_desire = np.where(inputs['desire'] - self.prev_desire > .99, inputs['desire'], 0) - self.prev_desire[:] = inputs['desire'] + inputs['desire_pulse'][0] = 0 + new_desire = np.where(inputs['desire_pulse'] - self.prev_desire > .99, inputs['desire_pulse'], 0) + self.prev_desire[:] = inputs['desire_pulse'] self.full_desire[0,:-1] = self.full_desire[0,1:] self.full_desire[0,-1] = new_desire - self.numpy_inputs['desire'][:] = self.full_desire.reshape((1,ModelConstants.INPUT_HISTORY_BUFFER_LEN,ModelConstants.TEMPORAL_SKIP,-1)).max(axis=2) + self.numpy_inputs['desire_pulse'][:] = self.full_desire.reshape((1,ModelConstants.INPUT_HISTORY_BUFFER_LEN,ModelConstants.TEMPORAL_SKIP,-1)).max(axis=2) self.numpy_inputs['traffic_convention'][:] = inputs['traffic_convention'] imgs_cl = {name: self.frames[name].prepare(bufs[name], transforms[name].flatten()) for name in self.vision_input_names} @@ -313,7 +313,7 @@ def main(demo=False): bufs = {name: buf_extra if 'big' in name else buf_main for name in model.vision_input_names} transforms = {name: model_transform_extra if 'big' in name else model_transform_main for name in model.vision_input_names} inputs:dict[str, np.ndarray] = { - 'desire': vec_desire, + 'desire_pulse': vec_desire, 'traffic_convention': traffic_convention, } diff --git a/selfdrive/modeld/models/driving_policy.onnx b/selfdrive/modeld/models/driving_policy.onnx index 867a0d3b9b..eb6bd7b8a4 100644 --- a/selfdrive/modeld/models/driving_policy.onnx +++ b/selfdrive/modeld/models/driving_policy.onnx @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:04b763fb71efe57a8a4c4168a8043ecd58939015026ded0dc755ded6905ac251 -size 12343523 +oid sha256:72e98a95541f200bd2faeae8d718997483696fd4801fc7d718c167b05854707d +size 12343535 From a3fcde2ae8d0d6442a739e6a271b3c1fb8f70146 Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Wed, 27 Aug 2025 14:19:23 -0700 Subject: [PATCH 024/159] jenkins: tizi-replay --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 76f7f2cea4..dd420fdeb1 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -251,7 +251,7 @@ node { ]) }, 'replay': { - deviceStage("model-replay", "tici-replay", ["UNSAFE=1"], [ + deviceStage("model-replay", "tizi-replay", ["UNSAFE=1"], [ step("build", "cd system/manager && ./build.py", [diffPaths: ["selfdrive/modeld/", "tinygrad_repo", "selfdrive/test/process_replay/model_replay.py"]]), step("model replay", "selfdrive/test/process_replay/model_replay.py", [diffPaths: ["selfdrive/modeld/", "tinygrad_repo", "selfdrive/test/process_replay/model_replay.py"]]), ]) From b309bf417355ee891dd9d0b2e828f1cefdb89da0 Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Wed, 27 Aug 2025 14:26:56 -0700 Subject: [PATCH 025/159] jenkins: sensord device --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index dd420fdeb1..8eb113e87d 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -245,7 +245,7 @@ node { ]) }, 'sensord': { - deviceStage("LSM + MMC", "tici-lsmc", ["UNSAFE=1"], [ + deviceStage("LSM + MMC", "tizi-lsmc", ["UNSAFE=1"], [ step("build", "cd system/manager && ./build.py"), step("test sensord", "pytest system/sensord/tests/test_sensord.py"), ]) From 2aa7648bb87d45e47b3db7ae58262a722b4b39e2 Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Wed, 27 Aug 2025 14:29:39 -0700 Subject: [PATCH 026/159] jenkins: remove ar device --- Jenkinsfile | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 8eb113e87d..54dff318d9 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -223,13 +223,6 @@ node { step("test pandad loopback", "pytest selfdrive/pandad/tests/test_pandad_loopback.py"), ]) }, - 'camerad AR0231': { - deviceStage("AR0231", "tici-ar0231", ["UNSAFE=1"], [ - step("build", "cd system/manager && ./build.py"), - step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 60]), - step("test exposure", "pytest system/camerad/test/test_exposure.py"), - ]) - }, 'camerad OX03C10': { deviceStage("OX03C10", "tici-ox03c10", ["UNSAFE=1"], [ step("build", "cd system/manager && ./build.py"), From a254a05df057e5ad8ea3650de553eef4d6804852 Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Wed, 27 Aug 2025 14:39:02 -0700 Subject: [PATCH 027/159] jenkins: replace tici-common (#36073) * common * remove * test * Revert "test" This reverts commit 2c76a8f818e42e0af1d4540dede3595fe0d59ed9. * Reapply "test" This reverts commit d9974dd8564d0699dcfa3aac0ffb2dca33f3b47d. * Revert "Reapply "test"" This reverts commit 2377c6ab20df5dd06886f3dd9a0be07abfce9df6. * tizi bounds --- Jenkinsfile | 3 +-- system/hardware/tici/tests/test_power_draw.py | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 54dff318d9..6c4e01854f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -208,12 +208,11 @@ node { ]) }, 'HW + Unit Tests': { - deviceStage("tici-hardware", "tici-common", ["UNSAFE=1"], [ + deviceStage("tizi-hardware", "tizi-common", ["UNSAFE=1"], [ step("build", "cd system/manager && ./build.py"), step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py", [diffPaths: ["panda", "selfdrive/pandad/"]]), step("test power draw", "pytest -s system/hardware/tici/tests/test_power_draw.py"), step("test encoder", "LD_LIBRARY_PATH=/usr/local/lib pytest system/loggerd/tests/test_encoder.py", [diffPaths: ["system/loggerd/"]]), - step("test pigeond", "pytest system/ubloxd/tests/test_pigeond.py", [diffPaths: ["system/ubloxd/"]]), step("test manager", "pytest system/manager/test/test_manager.py"), ]) }, diff --git a/system/hardware/tici/tests/test_power_draw.py b/system/hardware/tici/tests/test_power_draw.py index db0fab884c..46b45460b5 100644 --- a/system/hardware/tici/tests/test_power_draw.py +++ b/system/hardware/tici/tests/test_power_draw.py @@ -32,8 +32,8 @@ class Proc: PROCS = [ Proc(['camerad'], 1.75, msgs=['roadCameraState', 'wideRoadCameraState', 'driverCameraState']), - Proc(['modeld'], 1.12, atol=0.2, msgs=['modelV2']), - Proc(['dmonitoringmodeld'], 0.6, msgs=['driverStateV2']), + Proc(['modeld'], 1.24, atol=0.2, msgs=['modelV2']), + Proc(['dmonitoringmodeld'], 0.7, msgs=['driverStateV2']), Proc(['encoderd'], 0.23, msgs=[]), ] From 1d8dc8a69a188285e65595d83224e54d497178dc Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Wed, 27 Aug 2025 15:11:58 -0700 Subject: [PATCH 028/159] camerad: remove AR0231 (#36070) --- system/camerad/SConscript | 2 +- system/camerad/cameras/spectra.cc | 3 +- system/camerad/sensors/ar0231.cc | 136 ---------------------- system/camerad/sensors/ar0231_registers.h | 121 ------------------- system/camerad/sensors/sensor.h | 12 -- 5 files changed, 2 insertions(+), 272 deletions(-) delete mode 100644 system/camerad/sensors/ar0231.cc delete mode 100644 system/camerad/sensors/ar0231_registers.h diff --git a/system/camerad/SConscript b/system/camerad/SConscript index fe5cf87b78..734f748a2a 100644 --- a/system/camerad/SConscript +++ b/system/camerad/SConscript @@ -4,7 +4,7 @@ libs = [common, 'OpenCL', messaging, visionipc, gpucommon] if arch != "Darwin": camera_obj = env.Object(['cameras/camera_qcom2.cc', 'cameras/camera_common.cc', 'cameras/spectra.cc', - 'cameras/cdm.cc', 'sensors/ar0231.cc', 'sensors/ox03c10.cc', 'sensors/os04c10.cc']) + 'cameras/cdm.cc', 'sensors/ox03c10.cc', 'sensors/os04c10.cc']) env.Program('camerad', ['main.cc', camera_obj], LIBS=libs) if GetOption("extras") and arch == "x86_64": diff --git a/system/camerad/cameras/spectra.cc b/system/camerad/cameras/spectra.cc index 47ae9061f4..caf7871573 100644 --- a/system/camerad/cameras/spectra.cc +++ b/system/camerad/cameras/spectra.cc @@ -1004,8 +1004,7 @@ bool SpectraCamera::openSensor() { }; // Figure out which sensor we have - if (!init_sensor_lambda(new AR0231) && - !init_sensor_lambda(new OX03C10) && + if (!init_sensor_lambda(new OX03C10) && !init_sensor_lambda(new OS04C10)) { LOGE("** sensor %d FAILED bringup, disabling", cc.camera_num); enabled = false; diff --git a/system/camerad/sensors/ar0231.cc b/system/camerad/sensors/ar0231.cc deleted file mode 100644 index e4ae29f079..0000000000 --- a/system/camerad/sensors/ar0231.cc +++ /dev/null @@ -1,136 +0,0 @@ -#include -#include - -#include "system/camerad/sensors/sensor.h" - -namespace { - -const size_t AR0231_REGISTERS_HEIGHT = 2; -// TODO: this extra height is universal and doesn't apply per camera -const size_t AR0231_STATS_HEIGHT = 2 + 8; - -const float sensor_analog_gains_AR0231[] = { - 1.0 / 8.0, 2.0 / 8.0, 2.0 / 7.0, 3.0 / 7.0, // 0, 1, 2, 3 - 3.0 / 6.0, 4.0 / 6.0, 4.0 / 5.0, 5.0 / 5.0, // 4, 5, 6, 7 - 5.0 / 4.0, 6.0 / 4.0, 6.0 / 3.0, 7.0 / 3.0, // 8, 9, 10, 11 - 7.0 / 2.0, 8.0 / 2.0, 8.0 / 1.0}; // 12, 13, 14, 15 = bypass - -} // namespace - -AR0231::AR0231() { - image_sensor = cereal::FrameData::ImageSensor::AR0231; - bayer_pattern = CAM_ISP_PATTERN_BAYER_GRGRGR; - pixel_size_mm = 0.003; - data_word = true; - frame_width = 1928; - frame_height = 1208; - frame_stride = (frame_width * 12 / 8) + 4; - extra_height = AR0231_REGISTERS_HEIGHT + AR0231_STATS_HEIGHT; - - registers_offset = 0; - frame_offset = AR0231_REGISTERS_HEIGHT; - stats_offset = AR0231_REGISTERS_HEIGHT + frame_height; - - start_reg_array.assign(std::begin(start_reg_array_ar0231), std::end(start_reg_array_ar0231)); - init_reg_array.assign(std::begin(init_array_ar0231), std::end(init_array_ar0231)); - probe_reg_addr = 0x3000; - probe_expected_data = 0x354; - bits_per_pixel = 12; - mipi_format = CAM_FORMAT_MIPI_RAW_12; - frame_data_type = 0x12; // Changing stats to 0x2C doesn't work, so change pixels to 0x12 instead - mclk_frequency = 19200000; //Hz - - readout_time_ns = 22850000; - - dc_gain_factor = 2.5; - dc_gain_min_weight = 0; - dc_gain_max_weight = 1; - dc_gain_on_grey = 0.2; - dc_gain_off_grey = 0.3; - exposure_time_min = 2; // with HDR, fastest ss - exposure_time_max = 0x0855; // with HDR, slowest ss, 40ms - analog_gain_min_idx = 0x1; // 0.25x - analog_gain_rec_idx = 0x6; // 0.8x - analog_gain_max_idx = 0xD; // 4.0x - analog_gain_cost_delta = 0; - analog_gain_cost_low = 0.1; - analog_gain_cost_high = 5.0; - for (int i = 0; i <= analog_gain_max_idx; i++) { - sensor_analog_gains[i] = sensor_analog_gains_AR0231[i]; - } - min_ev = exposure_time_min * sensor_analog_gains[analog_gain_min_idx]; - max_ev = exposure_time_max * dc_gain_factor * sensor_analog_gains[analog_gain_max_idx]; - target_grey_factor = 1.0; - - black_level = 168; - color_correct_matrix = { - 0x000000af, 0x00000ff9, 0x00000fd8, - 0x00000fbc, 0x000000bb, 0x00000009, - 0x00000fb6, 0x00000fe0, 0x000000ea, - }; - for (int i = 0; i < 65; i++) { - float fx = i / 64.0; - const float gamma_k = 0.75; - const float gamma_b = 0.125; - const float mp = 0.01; // ideally midpoint should be adaptive - const float rk = 9 - 100*mp; - // poly approximation for s curve - fx = (fx > mp) ? - ((rk * (fx-mp) * (1-(gamma_k*mp+gamma_b)) * (1+1/(rk*(1-mp))) / (1+rk*(fx-mp))) + gamma_k*mp + gamma_b) : - ((rk * (fx-mp) * (gamma_k*mp+gamma_b) * (1+1/(rk*mp)) / (1-rk*(fx-mp))) + gamma_k*mp + gamma_b); - gamma_lut_rgb.push_back((uint32_t)(fx*1023.0 + 0.5)); - } - prepare_gamma_lut(); - linearization_lut = { - 0x02000000, 0x02000000, 0x02000000, 0x02000000, - 0x020007ff, 0x020007ff, 0x020007ff, 0x020007ff, - 0x02000bff, 0x02000bff, 0x02000bff, 0x02000bff, - 0x020017ff, 0x020017ff, 0x020017ff, 0x020017ff, - 0x02001bff, 0x02001bff, 0x02001bff, 0x02001bff, - 0x020023ff, 0x020023ff, 0x020023ff, 0x020023ff, - 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, - 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, - 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, - }; - linearization_pts = {0x07ff0bff, 0x17ff1bff, 0x23ff3fff, 0x3fff3fff}; - vignetting_lut = { - 0x00eaa755, 0x00cf2679, 0x00bc05e0, 0x00acc566, 0x00a1450a, 0x009984cc, 0x0095a4ad, 0x009584ac, 0x009944ca, 0x00a0c506, 0x00ac0560, 0x00bb25d9, 0x00ce2671, 0x00e90748, 0x01112889, 0x014a2a51, 0x01984cc2, - 0x00db06d8, 0x00c30618, 0x00afe57f, 0x00a0a505, 0x009524a9, 0x008d646b, 0x0089844c, 0x0089644b, 0x008d2469, 0x0094a4a5, 0x009fe4ff, 0x00af0578, 0x00c20610, 0x00d986cc, 0x00fda7ed, 0x01320990, 0x017aebd7, - 0x00d1868c, 0x00baa5d5, 0x00a7853c, 0x009844c2, 0x008cc466, 0x0085a42d, 0x0083641b, 0x0083641b, 0x0085842c, 0x008c4462, 0x0097a4bd, 0x00a6c536, 0x00b9a5cd, 0x00d06683, 0x00f1678b, 0x01226913, 0x0167ab3d, - 0x00cd0668, 0x00b625b1, 0x00a30518, 0x0093c49e, 0x00884442, 0x00830418, 0x0080e407, 0x0080c406, 0x0082e417, 0x0087c43e, 0x00932499, 0x00a22511, 0x00b525a9, 0x00cbe65f, 0x00eb0758, 0x011a68d3, 0x015daaed, - 0x00cc4662, 0x00b565ab, 0x00a24512, 0x00930498, 0x0087843c, 0x0082a415, 0x00806403, 0x00806403, 0x00828414, 0x00870438, 0x00926493, 0x00a1850c, 0x00b465a3, 0x00cb2659, 0x00ea2751, 0x011928c9, 0x015c2ae1, - 0x00cf667b, 0x00b885c4, 0x00a5652b, 0x009624b1, 0x008aa455, 0x00846423, 0x00822411, 0x00822411, 0x00844422, 0x008a2451, 0x009564ab, 0x00a48524, 0x00b785bc, 0x00ce4672, 0x00ee6773, 0x011e88f4, 0x0162eb17, - 0x00d6c6b6, 0x00bf65fb, 0x00ac4562, 0x009d04e8, 0x0091848c, 0x0089c44e, 0x00862431, 0x00860430, 0x0089844c, 0x00910488, 0x009c64e3, 0x00ab655b, 0x00be65f3, 0x00d566ab, 0x00f847c2, 0x012b2959, 0x01726b93, - 0x00e3e71f, 0x00ca0650, 0x00b705b8, 0x00a7a53d, 0x009c24e1, 0x009484a4, 0x00908484, 0x00908484, 0x009424a1, 0x009bc4de, 0x00a70538, 0x00b625b1, 0x00c90648, 0x00e26713, 0x0108e847, 0x013fe9ff, 0x018bcc5e, - 0x00f807c0, 0x00d966cb, 0x00c5862c, 0x00b625b1, 0x00aaa555, 0x00a30518, 0x009f04f8, 0x009f04f8, 0x00a2a515, 0x00aa2551, 0x00b585ac, 0x00c4a625, 0x00d846c2, 0x00f647b2, 0x0121a90d, 0x015e4af2, 0x01b8cdc6, - 0x011548aa, 0x00f1678b, 0x00d886c4, 0x00c86643, 0x00bce5e7, 0x00b545aa, 0x00b1658b, 0x00b1458a, 0x00b505a8, 0x00bc85e4, 0x00c7c63e, 0x00d786bc, 0x00efe77f, 0x0113489a, 0x0144ea27, 0x01888c44, 0x01fdcfee, - 0x013e49f2, 0x0113e89f, 0x00f5a7ad, 0x00e0c706, 0x00d30698, 0x00cb665b, 0x00c7663b, 0x00c7663b, 0x00cb0658, 0x00d2a695, 0x00dfe6ff, 0x00f467a3, 0x01122891, 0x013be9df, 0x01750ba8, 0x01cfae7d, 0x025912c8, - 0x01766bb3, 0x01446a23, 0x011fc8fe, 0x0105e82f, 0x00f467a3, 0x00e9874c, 0x00e46723, 0x00e44722, 0x00e92749, 0x00f3a79d, 0x0104c826, 0x011e48f2, 0x01424a12, 0x01738b9c, 0x01bf6dfb, 0x023611b0, 0x02ced676, - 0x01cf8e7c, 0x01866c33, 0x015aaad5, 0x013ae9d7, 0x01250928, 0x011768bb, 0x0110a885, 0x01108884, 0x0116e8b7, 0x01242921, 0x0139a9cd, 0x0158eac7, 0x01840c20, 0x01cb0e58, 0x0233719b, 0x02b9d5ce, 0x03645b22, - }; -} - -std::vector AR0231::getExposureRegisters(int exposure_time, int new_exp_g, bool dc_gain_enabled) const { - uint16_t analog_gain_reg = 0xFF00 | (new_exp_g << 4) | new_exp_g; - return { - {0x3366, analog_gain_reg}, - {0x3362, (uint16_t)(dc_gain_enabled ? 0x1 : 0x0)}, - {0x3012, (uint16_t)exposure_time}, - }; -} - -int AR0231::getSlaveAddress(int port) const { - assert(port >= 0 && port <= 2); - return (int[]){0x20, 0x30, 0x20}[port]; -} - -float AR0231::getExposureScore(float desired_ev, int exp_t, int exp_g_idx, float exp_gain, int gain_idx) const { - // Cost of ev diff - float score = std::abs(desired_ev - (exp_t * exp_gain)) * 10; - // Cost of absolute gain - float m = exp_g_idx > analog_gain_rec_idx ? analog_gain_cost_high : analog_gain_cost_low; - score += std::abs(exp_g_idx - (int)analog_gain_rec_idx) * m; - // Cost of changing gain - score += std::abs(exp_g_idx - gain_idx) * (score + 1.0) / 10.0; - return score; -} diff --git a/system/camerad/sensors/ar0231_registers.h b/system/camerad/sensors/ar0231_registers.h deleted file mode 100644 index e0872a673a..0000000000 --- a/system/camerad/sensors/ar0231_registers.h +++ /dev/null @@ -1,121 +0,0 @@ -#pragma once - -const struct i2c_random_wr_payload start_reg_array_ar0231[] = {{0x301A, 0x91C}}; -const struct i2c_random_wr_payload stop_reg_array_ar0231[] = {{0x301A, 0x918}}; - -const struct i2c_random_wr_payload init_array_ar0231[] = { - {0x301A, 0x0018}, // RESET_REGISTER - - // **NOTE**: if this is changed, readout_time_ns must be updated in the Sensor config - - // CLOCK Settings - // input clock is 19.2 / 2 * 0x37 = 528 MHz - // pixclk is 528 / 6 = 88 MHz - // full roll time is 1000/(PIXCLK/(LINE_LENGTH_PCK*FRAME_LENGTH_LINES)) = 39.99 ms - // img roll time is 1000/(PIXCLK/(LINE_LENGTH_PCK*Y_OUTPUT_CONTROL)) = 22.85 ms - {0x302A, 0x0006}, // VT_PIX_CLK_DIV - {0x302C, 0x0001}, // VT_SYS_CLK_DIV - {0x302E, 0x0002}, // PRE_PLL_CLK_DIV - {0x3030, 0x0037}, // PLL_MULTIPLIER - {0x3036, 0x000C}, // OP_PIX_CLK_DIV - {0x3038, 0x0001}, // OP_SYS_CLK_DIV - - // FORMAT - {0x3040, 0xC000}, // READ_MODE - {0x3004, 0x0000}, // X_ADDR_START_ - {0x3008, 0x0787}, // X_ADDR_END_ - {0x3002, 0x0000}, // Y_ADDR_START_ - {0x3006, 0x04B7}, // Y_ADDR_END_ - {0x3032, 0x0000}, // SCALING_MODE - {0x30A2, 0x0001}, // X_ODD_INC_ - {0x30A6, 0x0001}, // Y_ODD_INC_ - {0x3402, 0x0788}, // X_OUTPUT_CONTROL - {0x3404, 0x04B8}, // Y_OUTPUT_CONTROL - {0x3064, 0x1982}, // SMIA_TEST - {0x30BA, 0x11F2}, // DIGITAL_CTRL - - // Enable external trigger and disable GPIO outputs - {0x30CE, 0x0120}, // SLAVE_SH_SYNC_MODE | FRAME_START_MODE - {0x340A, 0xE0}, // GPIO3_INPUT_DISABLE | GPIO2_INPUT_DISABLE | GPIO1_INPUT_DISABLE - {0x340C, 0x802}, // GPIO_HIDRV_EN | GPIO0_ISEL=2 - - // Readout timing - {0x300C, 0x0672}, // LINE_LENGTH_PCK (valid for 3-exposure HDR) - {0x300A, 0x0855}, // FRAME_LENGTH_LINES - {0x3042, 0x0000}, // EXTRA_DELAY - - // Readout Settings - {0x31AE, 0x0204}, // SERIAL_FORMAT, 4-lane MIPI - {0x31AC, 0x0C0C}, // DATA_FORMAT_BITS, 12 -> 12 - {0x3342, 0x1212}, // MIPI_F1_PDT_EDT - {0x3346, 0x1212}, // MIPI_F2_PDT_EDT - {0x334A, 0x1212}, // MIPI_F3_PDT_EDT - {0x334E, 0x1212}, // MIPI_F4_PDT_EDT - {0x3344, 0x0011}, // MIPI_F1_VDT_VC - {0x3348, 0x0111}, // MIPI_F2_VDT_VC - {0x334C, 0x0211}, // MIPI_F3_VDT_VC - {0x3350, 0x0311}, // MIPI_F4_VDT_VC - {0x31B0, 0x0053}, // FRAME_PREAMBLE - {0x31B2, 0x003B}, // LINE_PREAMBLE - {0x301A, 0x001C}, // RESET_REGISTER - - // Noise Corrections - {0x3092, 0x0C24}, // ROW_NOISE_CONTROL - {0x337A, 0x0C80}, // DBLC_SCALE0 - {0x3370, 0x03B1}, // DBLC - {0x3044, 0x0400}, // DARK_CONTROL - - // Enable temperature sensor - {0x30B4, 0x0007}, // TEMPSENS0_CTRL_REG - {0x30B8, 0x0007}, // TEMPSENS1_CTRL_REG - - // Enable dead pixel correction using - // the 1D line correction scheme - {0x31E0, 0x0003}, - - // HDR Settings - {0x3082, 0x0004}, // OPERATION_MODE_CTRL - {0x3238, 0x0444}, // EXPOSURE_RATIO - - {0x1008, 0x0361}, // FINE_INTEGRATION_TIME_MIN - {0x100C, 0x0589}, // FINE_INTEGRATION_TIME2_MIN - {0x100E, 0x07B1}, // FINE_INTEGRATION_TIME3_MIN - {0x1010, 0x0139}, // FINE_INTEGRATION_TIME4_MIN - - // TODO: do these have to be lower than LINE_LENGTH_PCK? - {0x3014, 0x08CB}, // FINE_INTEGRATION_TIME_ - {0x321E, 0x0894}, // FINE_INTEGRATION_TIME2 - - {0x31D0, 0x0000}, // COMPANDING, no good in 10 bit? - {0x33DA, 0x0000}, // COMPANDING - {0x318E, 0x0200}, // PRE_HDR_GAIN_EN - - // DLO Settings - {0x3100, 0x4000}, // DLO_CONTROL0 - {0x3280, 0x0CCC}, // T1 G1 - {0x3282, 0x0CCC}, // T1 R - {0x3284, 0x0CCC}, // T1 B - {0x3286, 0x0CCC}, // T1 G2 - {0x3288, 0x0FA0}, // T2 G1 - {0x328A, 0x0FA0}, // T2 R - {0x328C, 0x0FA0}, // T2 B - {0x328E, 0x0FA0}, // T2 G2 - - // Initial Gains - {0x3022, 0x0001}, // GROUPED_PARAMETER_HOLD_ - {0x3366, 0xFF77}, // ANALOG_GAIN (1x) - - {0x3060, 0x3333}, // ANALOG_COLOR_GAIN - - {0x3362, 0x0000}, // DC GAIN - - {0x305A, 0x00F8}, // red gain - {0x3058, 0x0122}, // blue gain - {0x3056, 0x009A}, // g1 gain - {0x305C, 0x009A}, // g2 gain - - {0x3022, 0x0000}, // GROUPED_PARAMETER_HOLD_ - - // Initial Integration Time - {0x3012, 0x0005}, -}; diff --git a/system/camerad/sensors/sensor.h b/system/camerad/sensors/sensor.h index d4be3cf036..96aa8b604f 100644 --- a/system/camerad/sensors/sensor.h +++ b/system/camerad/sensors/sensor.h @@ -10,7 +10,6 @@ #include "media/cam_sensor.h" #include "cereal/gen/cpp/log.capnp.h" -#include "system/camerad/sensors/ar0231_registers.h" #include "system/camerad/sensors/ox03c10_registers.h" #include "system/camerad/sensors/os04c10_registers.h" @@ -88,17 +87,6 @@ public: }; }; -class AR0231 : public SensorInfo { -public: - AR0231(); - std::vector getExposureRegisters(int exposure_time, int new_exp_g, bool dc_gain_enabled) const override; - float getExposureScore(float desired_ev, int exp_t, int exp_g_idx, float exp_gain, int gain_idx) const override; - int getSlaveAddress(int port) const override; - -private: - mutable std::map> ar0231_register_lut; -}; - class OX03C10 : public SensorInfo { public: OX03C10(); From bb06468eadc230fc59315539b81626046acfc09c Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Wed, 27 Aug 2025 16:41:57 -0700 Subject: [PATCH 029/159] safety standards for forks (#36077) standards for forks --- docs/SAFETY.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/docs/SAFETY.md b/docs/SAFETY.md index 18a450a395..25815e3372 100644 --- a/docs/SAFETY.md +++ b/docs/SAFETY.md @@ -16,7 +16,7 @@ industry standards of safety for Level 2 Driver Assistance Systems. In particula ISO26262 guidelines, including those from [pertinent documents](https://www.nhtsa.gov/sites/nhtsa.dot.gov/files/documents/13498a_812_573_alcsystemreport.pdf) released by NHTSA. In addition, we impose strict coding guidelines (like [MISRA C : 2012](https://www.misra.org.uk/what-is-misra/)) on parts of openpilot that are safety relevant. We also perform software-in-the-loop, -hardware-in-the-loop and in-vehicle tests before each software release. +hardware-in-the-loop, and in-vehicle tests before each software release. Following Hazard and Risk Analysis and FMEA, at a very high level, we have designed openpilot ensuring two main safety requirements. @@ -29,8 +29,18 @@ ensuring two main safety requirements. For additional safety implementation details, refer to [panda safety model](https://github.com/commaai/panda#safety-model). For vehicle specific implementation of the safety concept, refer to [opendbc/safety/safety](https://github.com/commaai/opendbc/tree/master/opendbc/safety/safety). -**Extra note**: comma.ai strongly discourages the use of openpilot forks with safety code either missing or - not fully meeting the above requirements. +[^1]: For these actuator limits we observe ISO11270 and ISO15622. Lateral limits described there translate to 0.9 seconds of maximum actuation to achieve a 1m lateral deviation. -[^1]: For these actuator limits we observe ISO11270 and ISO15622. Lateral limits described there translate to 0.9 seconds of maximum actuation to achieve a 1m lateral deviation. +--- +### Forks of openpilot + +* Do not disable or nerf [driver monitoring](https://github.com/commaai/openpilot/tree/master/selfdrive/monitoring) +* Do not disable or nerf [excessive actuation checks](https://github.com/commaai/openpilot/tree/master/selfdrive/selfdrived/helpers.py) +* If your fork modifies any of the code in `opendbc/safety/`: + * your fork cannot use the openpilot trademark + * your fork must preserve the full [safety test suite](https://github.com/commaai/opendbc/tree/master/opendbc/safety/tests) and all tests must pass, including any new coverage required by the fork's changes + +Failure to comply with these standards will get you and your users banned from comma.ai servers. + +**comma.ai strongly discourages the use of openpilot forks with safety code either missing or not fully meeting the above requirements.** From a2c5fca787de19a84b47eb8123ac1c46b980dd0e Mon Sep 17 00:00:00 2001 From: ZwX1616 Date: Wed, 27 Aug 2025 17:54:53 -0700 Subject: [PATCH 030/159] modeld input queues class (#36072) * move from xx * no get_single * stupid name * thats fine * desire_pulse * 1less * desire->desire_pulse * simplify * reduce copies * more less --- selfdrive/modeld/constants.py | 9 +-- selfdrive/modeld/fill_model_msg.py | 2 +- selfdrive/modeld/modeld.py | 88 +++++++++++++++++++++++------- 3 files changed, 73 insertions(+), 26 deletions(-) diff --git a/selfdrive/modeld/constants.py b/selfdrive/modeld/constants.py index 5ca0a86bc8..ff7e1d8600 100644 --- a/selfdrive/modeld/constants.py +++ b/selfdrive/modeld/constants.py @@ -13,12 +13,9 @@ class ModelConstants: META_T_IDXS = [2., 4., 6., 8., 10.] # model inputs constants - MODEL_FREQ = 20 - HISTORY_FREQ = 5 - HISTORY_LEN_SECONDS = 5 - TEMPORAL_SKIP = MODEL_FREQ // HISTORY_FREQ - FULL_HISTORY_BUFFER_LEN = MODEL_FREQ * HISTORY_LEN_SECONDS - INPUT_HISTORY_BUFFER_LEN = HISTORY_FREQ * HISTORY_LEN_SECONDS + N_FRAMES = 2 + MODEL_RUN_FREQ = 20 + MODEL_CONTEXT_FREQ = 5 # "model_trained_fps" FEATURE_LEN = 512 diff --git a/selfdrive/modeld/fill_model_msg.py b/selfdrive/modeld/fill_model_msg.py index a2b54b420e..82c4c92b1d 100644 --- a/selfdrive/modeld/fill_model_msg.py +++ b/selfdrive/modeld/fill_model_msg.py @@ -149,7 +149,7 @@ def fill_model_msg(base_msg: capnp._DynamicStructBuilder, extended_msg: capnp._D meta.hardBrakePredicted = hard_brake_predicted.item() # confidence - if vipc_frame_id % (2*ModelConstants.MODEL_FREQ) == 0: + if vipc_frame_id % (2*ModelConstants.MODEL_RUN_FREQ) == 0: # any disengage prob brake_disengage_probs = net_output_data['meta'][0,Meta.BRAKE_DISENGAGE] gas_disengage_probs = net_output_data['meta'][0,Meta.GAS_DISENGAGE] diff --git a/selfdrive/modeld/modeld.py b/selfdrive/modeld/modeld.py index 6e09f40e22..e08fc30c2e 100755 --- a/selfdrive/modeld/modeld.py +++ b/selfdrive/modeld/modeld.py @@ -77,6 +77,64 @@ class FrameMeta: if vipc is not None: self.frame_id, self.timestamp_sof, self.timestamp_eof = vipc.frame_id, vipc.timestamp_sof, vipc.timestamp_eof +class InputQueues: + def __init__ (self, model_fps, env_fps, n_frames_input): + assert env_fps % model_fps == 0 + assert env_fps >= model_fps + self.model_fps = model_fps + self.env_fps = env_fps + self.n_frames_input = n_frames_input + + self.dtypes = {} + self.shapes = {} + self.q = {} + + def update_dtypes_and_shapes(self, input_dtypes, input_shapes) -> None: + self.dtypes.update(input_dtypes) + if self.env_fps == self.model_fps: + self.shapes.update(input_shapes) + else: + for k in input_shapes: + shape = list(input_shapes[k]) + if 'img' in k: + n_channels = shape[1] // self.n_frames_input + shape[1] = (self.env_fps // self.model_fps + (self.n_frames_input - 1)) * n_channels + else: + shape[1] = (self.env_fps // self.model_fps) * shape[1] + self.shapes[k] = tuple(shape) + + def reset(self) -> None: + self.q = {k: np.zeros(self.shapes[k], dtype=self.dtypes[k]) for k in self.dtypes.keys()} + + def enqueue(self, inputs:dict[str, np.ndarray]) -> None: + for k in inputs.keys(): + if inputs[k].dtype != self.dtypes[k]: + raise ValueError(f'supplied input <{k}({inputs[k].dtype})> has wrong dtype, expected {self.dtypes[k]}') + input_shape = list(self.shapes[k]) + input_shape[1] = -1 + single_input = inputs[k].reshape(tuple(input_shape)) + sz = single_input.shape[1] + self.q[k][:,:-sz] = self.q[k][:,sz:] + self.q[k][:,-sz:] = single_input + + def get(self, *names) -> dict[str, np.ndarray]: + if self.env_fps == self.model_fps: + return {k: self.q[k] for k in names} + else: + out = {} + for k in names: + shape = self.shapes[k] + if 'img' in k: + n_channels = shape[1] // (self.env_fps // self.model_fps + (self.n_frames_input - 1)) + out[k] = np.concatenate([self.q[k][:, s:s+n_channels] for s in np.linspace(0, shape[1] - n_channels, self.n_frames_input, dtype=int)], axis=1) + elif 'pulse' in k: + # any pulse within interval counts + out[k] = self.q[k].reshape((shape[0], shape[1] * self.model_fps // self.env_fps, self.env_fps // self.model_fps, -1)).max(axis=2) + else: + idxs = np.arange(-1, -shape[1], -self.env_fps // self.model_fps)[::-1] + out[k] = self.q[k][:, idxs] + return out + class ModelState: frames: dict[str, DrivingModelFrame] inputs: dict[str, np.ndarray] @@ -97,19 +155,15 @@ class ModelState: self.policy_output_slices = policy_metadata['output_slices'] policy_output_size = policy_metadata['output_shapes']['outputs'][1] - self.frames = {name: DrivingModelFrame(context, ModelConstants.TEMPORAL_SKIP) for name in self.vision_input_names} + self.frames = {name: DrivingModelFrame(context, ModelConstants.MODEL_RUN_FREQ//ModelConstants.MODEL_CONTEXT_FREQ) for name in self.vision_input_names} self.prev_desire = np.zeros(ModelConstants.DESIRE_LEN, dtype=np.float32) - self.full_features_buffer = np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32) - self.full_desire = np.zeros((1, ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.DESIRE_LEN), dtype=np.float32) - self.temporal_idxs = slice(-1-(ModelConstants.TEMPORAL_SKIP*(ModelConstants.INPUT_HISTORY_BUFFER_LEN-1)), None, ModelConstants.TEMPORAL_SKIP) - # policy inputs - self.numpy_inputs = { - 'desire_pulse': np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.DESIRE_LEN), dtype=np.float32), - 'traffic_convention': np.zeros((1, ModelConstants.TRAFFIC_CONVENTION_LEN), dtype=np.float32), - 'features_buffer': np.zeros((1, ModelConstants.INPUT_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32), - } + self.numpy_inputs = {k: np.zeros(self.policy_input_shapes[k], dtype=np.float32) for k in self.policy_input_shapes} + self.full_input_queues = InputQueues(ModelConstants.MODEL_CONTEXT_FREQ, ModelConstants.MODEL_RUN_FREQ, ModelConstants.N_FRAMES) + for k in ['desire_pulse', 'features_buffer']: + self.full_input_queues.update_dtypes_and_shapes({k: self.numpy_inputs[k].dtype}, {k: self.numpy_inputs[k].shape}) + self.full_input_queues.reset() # img buffers are managed in openCL transform code self.vision_inputs: dict[str, Tensor] = {} @@ -135,11 +189,6 @@ class ModelState: new_desire = np.where(inputs['desire_pulse'] - self.prev_desire > .99, inputs['desire_pulse'], 0) self.prev_desire[:] = inputs['desire_pulse'] - self.full_desire[0,:-1] = self.full_desire[0,1:] - self.full_desire[0,-1] = new_desire - self.numpy_inputs['desire_pulse'][:] = self.full_desire.reshape((1,ModelConstants.INPUT_HISTORY_BUFFER_LEN,ModelConstants.TEMPORAL_SKIP,-1)).max(axis=2) - - self.numpy_inputs['traffic_convention'][:] = inputs['traffic_convention'] imgs_cl = {name: self.frames[name].prepare(bufs[name], transforms[name].flatten()) for name in self.vision_input_names} if TICI and not USBGPU: @@ -158,9 +207,10 @@ class ModelState: self.vision_output = self.vision_run(**self.vision_inputs).contiguous().realize().uop.base.buffer.numpy() vision_outputs_dict = self.parser.parse_vision_outputs(self.slice_outputs(self.vision_output, self.vision_output_slices)) - self.full_features_buffer[0,:-1] = self.full_features_buffer[0,1:] - self.full_features_buffer[0,-1] = vision_outputs_dict['hidden_state'][0, :] - self.numpy_inputs['features_buffer'][:] = self.full_features_buffer[0, self.temporal_idxs] + self.full_input_queues.enqueue({'features_buffer': vision_outputs_dict['hidden_state'], 'desire_pulse': new_desire}) + for k in ['desire_pulse', 'features_buffer']: + self.numpy_inputs[k][:] = self.full_input_queues.get(k)[k] + self.numpy_inputs['traffic_convention'][:] = inputs['traffic_convention'] self.policy_output = self.policy_run(**self.policy_inputs).contiguous().realize().uop.base.buffer.numpy() policy_outputs_dict = self.parser.parse_policy_outputs(self.slice_outputs(self.policy_output, self.policy_output_slices)) @@ -218,7 +268,7 @@ def main(demo=False): params = Params() # setup filter to track dropped frames - frame_dropped_filter = FirstOrderFilter(0., 10., 1. / ModelConstants.MODEL_FREQ) + frame_dropped_filter = FirstOrderFilter(0., 10., 1. / ModelConstants.MODEL_RUN_FREQ) frame_id = 0 last_vipc_frame_id = 0 run_count = 0 From 93f7925c4d4a535e18da5cf6a7d49f7382eca1a4 Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Wed, 27 Aug 2025 18:36:10 -0700 Subject: [PATCH 031/159] jenkins: tizi ox --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 6c4e01854f..cba09e19f3 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -223,7 +223,7 @@ node { ]) }, 'camerad OX03C10': { - deviceStage("OX03C10", "tici-ox03c10", ["UNSAFE=1"], [ + deviceStage("OX03C10", "tizi-ox03c10", ["UNSAFE=1"], [ step("build", "cd system/manager && ./build.py"), step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 60]), step("test exposure", "pytest system/camerad/test/test_exposure.py"), From 7a19a110011900b0c0bc6dd6d9d8176ffef856f8 Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Wed, 27 Aug 2025 18:46:50 -0700 Subject: [PATCH 032/159] jenkins: tizi loopback device --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index cba09e19f3..3e9da05632 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -217,7 +217,7 @@ node { ]) }, 'loopback': { - deviceStage("loopback", "tici-loopback", ["UNSAFE=1"], [ + deviceStage("loopback", "tizi-loopback", ["UNSAFE=1"], [ step("build openpilot", "cd system/manager && ./build.py"), step("test pandad loopback", "pytest selfdrive/pandad/tests/test_pandad_loopback.py"), ]) From 63961dec45c634f478fec88e180c928e6f9709d4 Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Wed, 27 Aug 2025 19:04:16 -0700 Subject: [PATCH 033/159] jenkins: run pandad test once --- Jenkinsfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 3e9da05632..f3a63d3dec 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -253,7 +253,6 @@ node { step("build openpilot", "cd system/manager && ./build.py"), step("test pandad loopback", "SINGLE_PANDA=1 pytest selfdrive/pandad/tests/test_pandad_loopback.py"), step("test pandad spi", "pytest selfdrive/pandad/tests/test_pandad_spi.py"), - step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py", [diffPaths: ["panda", "selfdrive/pandad/"]]), step("test amp", "pytest system/hardware/tici/tests/test_amplifier.py"), // TODO: enable once new AGNOS is available // step("test esim", "pytest system/hardware/tici/tests/test_esim.py"), From 3e2549f2b8675ce482200e06855857122f3583e3 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Thu, 28 Aug 2025 08:19:39 -0700 Subject: [PATCH 034/159] remove tici-specific code (#36078) * remove tici-specific code * lil more * update those --- README.md | 6 +++--- common/params_keys.h | 1 - docs/CONTRIBUTING.md | 2 +- docs/how-to/connect-to-comma.md | 8 ++++---- docs/how-to/replay-a-drive.md | 2 +- docs/how-to/turn-the-speed-blue.md | 2 +- mkdocs.yml | 2 +- selfdrive/pandad/pandad.py | 5 ----- selfdrive/pandad/tests/bootstub.panda.bin | Bin 15732 -> 0 bytes selfdrive/pandad/tests/test_pandad.py | 6 +----- selfdrive/pandad/tests/test_pandad_spi.py | 3 --- selfdrive/selfdrived/alerts_offroad.json | 4 ---- selfdrive/selfdrived/selfdrived.py | 10 +--------- selfdrive/ui/tests/test_ui/run.py | 2 +- selfdrive/ui/ui.cc | 3 +-- selfdrive/ui/ui_state.py | 5 +---- system/camerad/cameras/hw.h | 2 +- system/hardware/hardwared.py | 7 ------- system/hardware/tici/amplifier.py | 12 ------------ system/hardware/tici/hardware.py | 15 +++++---------- system/hardware/tici/pins.py | 5 ----- system/ui/reset.py | 5 ----- system/updated/updated.py | 6 ------ 23 files changed, 22 insertions(+), 91 deletions(-) delete mode 100755 selfdrive/pandad/tests/bootstub.panda.bin diff --git a/README.md b/README.md index f3af58f85b..9f1819afbf 100644 --- a/README.md +++ b/README.md @@ -42,10 +42,10 @@ Using openpilot in a car ------ To use openpilot in a car, you need four things: -1. **Supported Device:** a comma 3/3X, available at [comma.ai/shop](https://comma.ai/shop/comma-3x). -2. **Software:** The setup procedure for the comma 3/3X allows users to enter a URL for custom software. Use the URL `openpilot.comma.ai` to install the release version. +1. **Supported Device:** a comma 3X, available at [comma.ai/shop](https://comma.ai/shop/comma-3x). +2. **Software:** The setup procedure for the comma 3X allows users to enter a URL for custom software. Use the URL `openpilot.comma.ai` to install the release version. 3. **Supported Car:** Ensure that you have one of [the 275+ supported cars](docs/CARS.md). -4. **Car Harness:** You will also need a [car harness](https://comma.ai/shop/car-harness) to connect your comma 3/3X to your car. +4. **Car Harness:** You will also need a [car harness](https://comma.ai/shop/car-harness) to connect your comma 3X to your car. We have detailed instructions for [how to install the harness and device in a car](https://comma.ai/setup). Note that it's possible to run openpilot on [other hardware](https://blog.comma.ai/self-driving-car-for-free/), although it's not plug-and-play. diff --git a/common/params_keys.h b/common/params_keys.h index c54600462c..211b4d550b 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -94,7 +94,6 @@ inline static std::unordered_map keys = { {"Offroad_NeosUpdate", {CLEAR_ON_MANAGER_START, JSON}}, {"Offroad_NoFirmware", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}}, {"Offroad_Recalibration", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}}, - {"Offroad_StorageMissing", {CLEAR_ON_MANAGER_START, JSON}}, {"Offroad_TemperatureTooHigh", {CLEAR_ON_MANAGER_START, JSON}}, {"Offroad_UnregisteredHardware", {CLEAR_ON_MANAGER_START, JSON}}, {"Offroad_UpdateFailed", {CLEAR_ON_MANAGER_START, JSON}}, diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 154734b7fc..7583095eaf 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -39,7 +39,7 @@ All of these are examples of good PRs: ### First contribution [Projects / openpilot bounties](https://github.com/orgs/commaai/projects/26/views/1?pane=info) is the best place to get started and goes in-depth on what's expected when working on a bounty. -There's lot of bounties that don't require a comma 3/3X or a car. +There's lot of bounties that don't require a comma 3X or a car. ## Pull Requests diff --git a/docs/how-to/connect-to-comma.md b/docs/how-to/connect-to-comma.md index cbaccaae6a..5f02e11599 100644 --- a/docs/how-to/connect-to-comma.md +++ b/docs/how-to/connect-to-comma.md @@ -1,11 +1,11 @@ -# connect to a comma 3/3X +# connect to a comma 3X -A comma 3/3X is a normal [Linux](https://github.com/commaai/agnos-builder) computer that exposes [SSH](https://wiki.archlinux.org/title/Secure_Shell) and a [serial console](https://wiki.archlinux.org/title/Working_with_the_serial_console). +A comma 3X is a normal [Linux](https://github.com/commaai/agnos-builder) computer that exposes [SSH](https://wiki.archlinux.org/title/Secure_Shell) and a [serial console](https://wiki.archlinux.org/title/Working_with_the_serial_console). ## Serial Console On both the comma three and 3X, the serial console is accessible from the main OBD-C port. -Connect the comma 3/3X to your computer with a normal USB C cable, or use a [comma serial](https://comma.ai/shop/comma-serial) for steady 12V power. +Connect the comma 3X to your computer with a normal USB C cable, or use a [comma serial](https://comma.ai/shop/comma-serial) for steady 12V power. On the comma three, the serial console is exposed through a UART-to-USB chip, and `tools/scripts/serial.sh` can be used to connect. @@ -45,7 +45,7 @@ In order to use ADB on your device, you'll need to perform the following steps u * Here's an example command for connecting to your device using its tethered connection: `adb connect 192.168.43.1:5555` > [!NOTE] -> The default port for ADB is 5555 on the comma 3/3X. +> The default port for ADB is 5555 on the comma 3X. For more info on ADB, see the [Android Debug Bridge (ADB) documentation](https://developer.android.com/tools/adb). diff --git a/docs/how-to/replay-a-drive.md b/docs/how-to/replay-a-drive.md index 084b6bf825..b0db36a46f 100644 --- a/docs/how-to/replay-a-drive.md +++ b/docs/how-to/replay-a-drive.md @@ -8,7 +8,7 @@ Replaying is a critical tool for openpilot development and debugging. Just run `tools/replay/replay --demo`. ## Replaying CAN data -*Hardware required: jungle and comma 3/3X* +*Hardware required: jungle and comma 3X* 1. Connect your PC to a jungle. 2. diff --git a/docs/how-to/turn-the-speed-blue.md b/docs/how-to/turn-the-speed-blue.md index 13b3b03e80..eb6e75afa2 100644 --- a/docs/how-to/turn-the-speed-blue.md +++ b/docs/how-to/turn-the-speed-blue.md @@ -3,7 +3,7 @@ In 30 minutes, we'll get an openpilot development environment set up on your computer and make some changes to openpilot's UI. -And if you have a comma 3/3X, we'll deploy the change to your device for testing. +And if you have a comma 3X, we'll deploy the change to your device for testing. ## 1. Set up your development environment diff --git a/mkdocs.yml b/mkdocs.yml index a66d1c76d4..550f807aca 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -21,7 +21,7 @@ nav: - What is openpilot?: getting-started/what-is-openpilot.md - How-to: - Turn the speed blue: how-to/turn-the-speed-blue.md - - Connect to a comma 3/3X: how-to/connect-to-comma.md + - Connect to a comma 3X: how-to/connect-to-comma.md # - Make your first pull request: how-to/make-first-pr.md #- Replay a drive: how-to/replay-a-drive.md - Concepts: diff --git a/selfdrive/pandad/pandad.py b/selfdrive/pandad/pandad.py index 4e49813f5d..d75af283f2 100755 --- a/selfdrive/pandad/pandad.py +++ b/selfdrive/pandad/pandad.py @@ -85,11 +85,6 @@ def main() -> None: cloudlog.event("pandad.flash_and_connect", count=count) params.remove("PandaSignatures") - # TODO: remove this in the next AGNOS - # wait until USB is up before counting - if time.monotonic() < 60.: - no_internal_panda_count = 0 - # Handle missing internal panda if no_internal_panda_count > 0: if no_internal_panda_count == 3: diff --git a/selfdrive/pandad/tests/bootstub.panda.bin b/selfdrive/pandad/tests/bootstub.panda.bin deleted file mode 100755 index 43db5370613b9a3966790c2a14f5e121907a5ade..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15732 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 pandad # - plus some buffer print("startup times", ts, sum(ts) / len(ts)) - assert 0.1 < (sum(ts)/len(ts)) < (0.7 if self.spi else 5.0) + assert 0.1 < (sum(ts)/len(ts)) < 0.7 def test_protocol_version_check(self): - if not self.spi: - pytest.skip("SPI test") # flash old fw fn = os.path.join(HERE, "bootstub.panda_h7_spiv0.bin") self._flash_bootstub_and_test(fn, expect_mismatch=True) diff --git a/selfdrive/pandad/tests/test_pandad_spi.py b/selfdrive/pandad/tests/test_pandad_spi.py index 9f7cc3b029..da4b181993 100644 --- a/selfdrive/pandad/tests/test_pandad_spi.py +++ b/selfdrive/pandad/tests/test_pandad_spi.py @@ -6,7 +6,6 @@ import random import cereal.messaging as messaging from cereal.services import SERVICE_LIST -from openpilot.system.hardware import HARDWARE from openpilot.selfdrive.test.helpers import with_processes from openpilot.selfdrive.pandad.tests.test_pandad_loopback import setup_pandad, send_random_can_messages @@ -16,8 +15,6 @@ JUNGLE_SPAM = "JUNGLE_SPAM" in os.environ class TestBoarddSpi: @classmethod def setup_class(cls): - if HARDWARE.get_device_type() == 'tici': - pytest.skip("only for spi pandas") os.environ['STARTED'] = '1' os.environ['SPI_ERR_PROB'] = '0.001' if not JUNGLE_SPAM: diff --git a/selfdrive/selfdrived/alerts_offroad.json b/selfdrive/selfdrived/alerts_offroad.json index 42aca22008..3d97135f60 100644 --- a/selfdrive/selfdrived/alerts_offroad.json +++ b/selfdrive/selfdrived/alerts_offroad.json @@ -29,10 +29,6 @@ "text": "Device failed to register with the comma.ai backend. It will not connect or upload to comma.ai servers, and receives no support from comma.ai. If this is a device purchased at comma.ai/shop, open a ticket at https://comma.ai/support.", "severity": 1 }, - "Offroad_StorageMissing": { - "text": "NVMe drive not mounted.", - "severity": 1 - }, "Offroad_CarUnrecognized": { "text": "openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai.", "severity": 0 diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index cf22040e84..e9c62fe327 100755 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -21,7 +21,6 @@ from openpilot.selfdrive.selfdrived.helpers import ExcessiveActuationCheck from openpilot.selfdrive.selfdrived.state import StateMachine from openpilot.selfdrive.selfdrived.alertmanager import AlertManager, set_offroad_alert -from openpilot.system.hardware import HARDWARE from openpilot.system.version import get_build_metadata REPLAY = "REPLAY" in os.environ @@ -122,13 +121,6 @@ class SelfdriveD: self.state_machine = StateMachine() self.rk = Ratekeeper(100, print_delay_threshold=None) - # some comma three with NVMe experience NVMe dropouts mid-drive that - # cause loggerd to crash on write, so ignore it only on that platform - self.ignored_processes = set() - nvme_expected = os.path.exists('/dev/nvme0n1') or (not os.path.isfile("/persist/comma/living-in-the-moment")) - if HARDWARE.get_device_type() == 'tici' and nvme_expected: - self.ignored_processes = {'loggerd', } - # Determine startup event self.startup_event = EventName.startup if build_metadata.openpilot.comma_remote and build_metadata.tested_channel else EventName.startupMaster if not car_recognized: @@ -299,7 +291,7 @@ class SelfdriveD: if not_running != self.not_running_prev: cloudlog.event("process_not_running", not_running=not_running, error=True) self.not_running_prev = not_running - if self.sm.recv_frame['managerState'] and (not_running - self.ignored_processes): + if self.sm.recv_frame['managerState'] and not_running: self.events.add(EventName.processNotRunning) else: if not SIMULATION and not self.rk.lagging: diff --git a/selfdrive/ui/tests/test_ui/run.py b/selfdrive/ui/tests/test_ui/run.py index 422183c5d5..32aead0b4f 100755 --- a/selfdrive/ui/tests/test_ui/run.py +++ b/selfdrive/ui/tests/test_ui/run.py @@ -29,7 +29,7 @@ UI_DELAY = 0.1 # may be slower on CI? TEST_ROUTE = "a2a0ccea32023010|2023-07-27--13-01-19" STREAMS: list[tuple[VisionStreamType, CameraConfig, bytes]] = [] -OFFROAD_ALERTS = ['Offroad_StorageMissing', 'Offroad_IsTakingSnapshot'] +OFFROAD_ALERTS = ['Offroad_IsTakingSnapshot', ] DATA: dict[str, capnp.lib.capnp._DynamicStructBuilder] = dict.fromkeys( ["carParams", "deviceState", "pandaStates", "controlsState", "selfdriveState", "liveCalibration", "modelV2", "radarState", "driverMonitoringState", "carState", diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 4f8bd7ddfc..9ec61b9b81 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -54,8 +54,7 @@ static void update_state(UIState *s) { } if (sm.updated("wideRoadCameraState")) { auto cam_state = sm["wideRoadCameraState"].getWideRoadCameraState(); - float scale = (cam_state.getSensor() == cereal::FrameData::ImageSensor::AR0231) ? 6.0f : 1.0f; - scene.light_sensor = std::max(100.0f - scale * cam_state.getExposureValPercent(), 0.0f); + scene.light_sensor = std::max(100.0f - cam_state.getExposureValPercent(), 0.0f); } else if (!sm.allAliveAndValid({"wideRoadCameraState"})) { scene.light_sensor = -1; } diff --git a/selfdrive/ui/ui_state.py b/selfdrive/ui/ui_state.py index c2bb5f77a4..c4a2c0ca11 100644 --- a/selfdrive/ui/ui_state.py +++ b/selfdrive/ui/ui_state.py @@ -105,10 +105,7 @@ class UIState: # Handle wide road camera state updates if self.sm.updated["wideRoadCameraState"]: cam_state = self.sm["wideRoadCameraState"] - - # Scale factor based on sensor type - scale = 6.0 if cam_state.sensor == 'ar0231' else 1.0 - self.light_sensor = max(100.0 - scale * cam_state.exposureValPercent, 0.0) + self.light_sensor = max(100.0 - cam_state.exposureValPercent, 0.0) elif not self.sm.alive["wideRoadCameraState"] or not self.sm.valid["wideRoadCameraState"]: self.light_sensor = -1 diff --git a/system/camerad/cameras/hw.h b/system/camerad/cameras/hw.h index d299627ce9..f20a1b3ade 100644 --- a/system/camerad/cameras/hw.h +++ b/system/camerad/cameras/hw.h @@ -13,7 +13,7 @@ typedef enum { ISP_BPS_PROCESSED, // fully processed image through the BPS } SpectraOutputType; -// For the comma 3/3X three camera platform +// For the comma 3X three camera platform struct CameraConfig { int camera_num; diff --git a/system/hardware/hardwared.py b/system/hardware/hardwared.py index fad93601da..1048acfe0a 100755 --- a/system/hardware/hardwared.py +++ b/system/hardware/hardwared.py @@ -6,7 +6,6 @@ import struct import threading import time from collections import OrderedDict, namedtuple -from pathlib import Path import psutil @@ -334,12 +333,6 @@ def hardware_thread(end_event, hw_queue) -> None: # to make a different decision in your software startup_conditions["registered_device"] = PC or (params.get("DongleId") != UNREGISTERED_DONGLE_ID) - # TODO: this should move to TICI.initialize_hardware, but we currently can't import params there - if TICI and HARDWARE.get_device_type() == "tici": - if not os.path.isfile("/persist/comma/living-in-the-moment"): - if not Path("/data/media").is_mount(): - set_offroad_alert_if_changed("Offroad_StorageMissing", True) - # Handle offroad/onroad transition should_start = all(onroad_conditions.values()) if started_ts is None: diff --git a/system/hardware/tici/amplifier.py b/system/hardware/tici/amplifier.py index f6b29ec0ce..bfdcc6ddaf 100755 --- a/system/hardware/tici/amplifier.py +++ b/system/hardware/tici/amplifier.py @@ -61,18 +61,6 @@ BASE_CONFIG = [ ] CONFIGS = { - "tici": [ - AmpConfig("Right speaker output from right DAC", 0b1, 0x2C, 0, 0b11111111), - AmpConfig("Right Speaker Mixer Gain", 0b00, 0x2D, 2, 0b00001100), - AmpConfig("Right speaker output volume", 0x1c, 0x3E, 0, 0b00011111), - AmpConfig("DAI2 EQ enable", 0b1, 0x49, 1, 0b00000010), - - *configs_from_eq_params(0x84, EQParams(0x274F, 0xC0FF, 0x3BF9, 0x0B3C, 0x1656)), - *configs_from_eq_params(0x8E, EQParams(0x1009, 0xC6BF, 0x2952, 0x1C97, 0x30DF)), - *configs_from_eq_params(0x98, EQParams(0x0F75, 0xCBE5, 0x0ED2, 0x2528, 0x3E42)), - *configs_from_eq_params(0xA2, EQParams(0x091F, 0x3D4C, 0xCE11, 0x1266, 0x2807)), - *configs_from_eq_params(0xAC, EQParams(0x0A9E, 0x3F20, 0xE573, 0x0A8B, 0x3A3B)), - ], "tizi": [ AmpConfig("Left speaker output from left DAC", 0b1, 0x2B, 0, 0b11111111), AmpConfig("Right speaker output from right DAC", 0b1, 0x2C, 0, 0b11111111), diff --git a/system/hardware/tici/hardware.py b/system/hardware/tici/hardware.py index 35f9916c31..6a9b98af82 100644 --- a/system/hardware/tici/hardware.py +++ b/system/hardware/tici/hardware.py @@ -425,9 +425,6 @@ class Tici(HardwareBase): # pandad core affine_irq(3, "spi_geni") # SPI - if "tici" in self.get_device_type(): - affine_irq(3, "xhci-hcd:usb3") # aux panda USB (or potentially anything else on USB) - affine_irq(3, "xhci-hcd:usb1") # internal panda USB (also modem) try: pid = subprocess.check_output(["pgrep", "-f", "spi0"], encoding='utf8').strip() subprocess.call(["sudo", "chrt", "-f", "-p", "1", pid]) @@ -446,22 +443,20 @@ class Tici(HardwareBase): cmds = [] - if self.get_device_type() in ("tici", "tizi"): + if self.get_device_type() in ("tizi", ): # clear out old blue prime initial APN os.system('mmcli -m any --3gpp-set-initial-eps-bearer-settings="apn="') cmds += [ + # SIM hot swap + 'AT+QSIMDET=1,0', + 'AT+QSIMSTAT=1', + # configure modem as data-centric 'AT+QNVW=5280,0,"0102000000000000"', 'AT+QNVFW="/nv/item_files/ims/IMS_enable",00', 'AT+QNVFW="/nv/item_files/modem/mmode/ue_usage_setting",01', ] - if self.get_device_type() == "tizi": - # SIM hot swap, not routed on tici - cmds += [ - 'AT+QSIMDET=1,0', - 'AT+QSIMSTAT=1', - ] elif manufacturer == 'Cavli Inc.': cmds += [ 'AT^SIMSWAP=1', # use SIM slot, instead of internal eSIM diff --git a/system/hardware/tici/pins.py b/system/hardware/tici/pins.py index 747278d1ec..bdbea591fb 100644 --- a/system/hardware/tici/pins.py +++ b/system/hardware/tici/pins.py @@ -1,5 +1,3 @@ -# TODO: these are also defined in a header - # GPIO pin definitions class GPIO: # both GPIO_STM_RST_N and GPIO_LTE_RST_N are misnamed, they are high to reset @@ -26,7 +24,4 @@ class GPIO: CAM2_RSTN = 12 # Sensor interrupts - BMX055_ACCEL_INT = 21 - BMX055_GYRO_INT = 23 - BMX055_MAGN_INT = 87 LSM_INT = 84 diff --git a/system/ui/reset.py b/system/ui/reset.py index b1bf5a6b6a..a5cf1731dc 100755 --- a/system/ui/reset.py +++ b/system/ui/reset.py @@ -13,7 +13,6 @@ from openpilot.system.ui.widgets import Widget from openpilot.system.ui.widgets.button import Button, ButtonStyle from openpilot.system.ui.widgets.label import gui_label, gui_text_box -NVME = "/dev/nvme0n1" USERDATA = "/dev/disk/by-partlabel/userdata" TIMEOUT = 3*60 @@ -49,10 +48,6 @@ class Reset(Widget): if PC: return - # Best effort to wipe NVME - os.system(f"sudo umount {NVME}") - os.system(f"yes | sudo mkfs.ext4 {NVME}") - # Removing data and formatting rm = os.system("sudo rm -rf /data/*") os.system(f"sudo umount {USERDATA}") diff --git a/system/updated/updated.py b/system/updated/updated.py index d1e745ec1a..a80a663ec9 100755 --- a/system/updated/updated.py +++ b/system/updated/updated.py @@ -243,12 +243,6 @@ class Updater: if b is None: b = self.get_branch(BASEDIR) b = { - ("tici", "release3"): "release-tici", - ("tici", "release3-staging"): "release-tici", - ("tici", "master"): "master-tici", - ("tici", "nightly"): "release-tici", - ("tici", "nightly-dev"): "release-tici", - ("tizi", "release3"): "release-tizi", }.get((HARDWARE.get_device_type(), b), b) return b From 9fcac06297ebf9357d8b1fbf5a3ab573e9733190 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Thu, 28 Aug 2025 11:49:31 -0700 Subject: [PATCH 035/159] op.sh: fix switch on fresh install --- tools/op.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/op.sh b/tools/op.sh index e83b46b2d2..54ff8e97e9 100755 --- a/tools/op.sh +++ b/tools/op.sh @@ -365,6 +365,7 @@ function op_switch() { fi BRANCH="$1" + git config --replace-all remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" git fetch "$REMOTE" "$BRANCH" git checkout -f FETCH_HEAD git checkout -B "$BRANCH" --track "$REMOTE"/"$BRANCH" From 76e91da3adb48777fe10b8933172e43c19e02691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20R=C4=85czy?= Date: Thu, 28 Aug 2025 22:11:20 +0200 Subject: [PATCH 036/159] process_replay: use LiveParametersV2 in custom params (#36080) Fill LiveParametersV2 in get_custom_params_from_lr --- selfdrive/test/process_replay/process_replay.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/test/process_replay/process_replay.py b/selfdrive/test/process_replay/process_replay.py index 56a0fdb61a..1144b7955e 100755 --- a/selfdrive/test/process_replay/process_replay.py +++ b/selfdrive/test/process_replay/process_replay.py @@ -591,7 +591,7 @@ def get_custom_params_from_lr(lr: LogIterable, initial_state: str = "first") -> if len(live_calibration) > 0: custom_params["CalibrationParams"] = live_calibration[msg_index].as_builder().to_bytes() if len(live_parameters) > 0: - custom_params["LiveParameters"] = live_parameters[msg_index].as_builder().to_bytes() + custom_params["LiveParametersV2"] = live_parameters[msg_index].as_builder().to_bytes() if len(live_torque_parameters) > 0: custom_params["LiveTorqueParameters"] = live_torque_parameters[msg_index].as_builder().to_bytes() From c990515eaff7e638514b7073b863f494ecf534e4 Mon Sep 17 00:00:00 2001 From: YassineYousfi Date: Fri, 29 Aug 2025 14:16:52 -0700 Subject: [PATCH 037/159] update RELEASES.md for 0.10.1 --- RELEASES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index dacf0eaa17..d89ee24628 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,5 +1,9 @@ Version 0.10.1 (2025-09-08) ======================== +* New driving model + * World Model: removed global localization inputs + * World Model: 2x the number of parameters + * World Model: trained on 4x the number of segments * Record driving feedback using LKAS button * Honda City 2023 support thanks to drFritz! From 67fd6c80dd64d0c0168c6109c1d0a0e6dae54472 Mon Sep 17 00:00:00 2001 From: commaci-public <60409688+commaci-public@users.noreply.github.com> Date: Mon, 1 Sep 2025 09:37:18 -0700 Subject: [PATCH 038/159] [bot] Update Python packages (#36090) * Update Python packages * no more stall --------- Co-authored-by: Vehicle Researcher Co-authored-by: Adeeb Shihadeh --- cereal/log.capnp | 2 +- opendbc_repo | 2 +- panda | 2 +- selfdrive/pandad/pandad.cc | 1 - tinygrad_repo | 2 +- uv.lock | 172 +++++++++++++++++++++---------------- 6 files changed, 101 insertions(+), 80 deletions(-) diff --git a/cereal/log.capnp b/cereal/log.capnp index e756843562..b98c1f5242 100644 --- a/cereal/log.capnp +++ b/cereal/log.capnp @@ -585,7 +585,6 @@ struct PandaState @0xa7649e2575e4591e { heartbeatLost @22 :Bool; interruptLoad @25 :Float32; fanPower @28 :UInt8; - fanStallCount @34 :UInt8; spiErrorCount @33 :UInt16; @@ -714,6 +713,7 @@ struct PandaState @0xa7649e2575e4591e { usbPowerModeDEPRECATED @12 :PeripheralState.UsbPowerModeDEPRECATED; safetyParamDEPRECATED @20 :Int16; safetyParam2DEPRECATED @26 :UInt32; + fanStallCountDEPRECATED @34 :UInt8; } struct PeripheralState { diff --git a/opendbc_repo b/opendbc_repo index 0fe56bc289..ac6122e272 160000 --- a/opendbc_repo +++ b/opendbc_repo @@ -1 +1 @@ -Subproject commit 0fe56bc289d72d2f278e9c085f2ada6ecb13e688 +Subproject commit ac6122e272e0dc040d5abf3bde6fca4e034a7ef7 diff --git a/panda b/panda index 3dc2138623..819fa5854e 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit 3dc21386239e3073a623156b75901aa302340d6c +Subproject commit 819fa5854e2e75da7f982f7d06be69c61793d6e1 diff --git a/selfdrive/pandad/pandad.cc b/selfdrive/pandad/pandad.cc index faaeb15319..8289df5491 100644 --- a/selfdrive/pandad/pandad.cc +++ b/selfdrive/pandad/pandad.cc @@ -152,7 +152,6 @@ void fill_panda_state(cereal::PandaState::Builder &ps, cereal::PandaState::Panda ps.setHarnessStatus(cereal::PandaState::HarnessStatus(health.car_harness_status_pkt)); ps.setInterruptLoad(health.interrupt_load_pkt); ps.setFanPower(health.fan_power); - ps.setFanStallCount(health.fan_stall_count); ps.setSafetyRxChecksInvalid((bool)(health.safety_rx_checks_invalid_pkt)); ps.setSpiErrorCount(health.spi_error_count_pkt); ps.setSbu1Voltage(health.sbu1_voltage_mV / 1000.0f); diff --git a/tinygrad_repo b/tinygrad_repo index e146418f65..965ea59b16 160000 --- a/tinygrad_repo +++ b/tinygrad_repo @@ -1 +1 @@ -Subproject commit e146418f6566301ffe8ebea093c0081409241c8d +Subproject commit 965ea59b16679793b8f48368ac24c4a0ef587e71 diff --git a/uv.lock b/uv.lock index 95a60715b5..e1678029cf 100644 --- a/uv.lock +++ b/uv.lock @@ -510,27 +510,27 @@ wheels = [ [[package]] name = "fonttools" -version = "4.59.1" +version = "4.59.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/11/7f/29c9c3fe4246f6ad96fee52b88d0dc3a863c7563b0afc959e36d78b965dc/fonttools-4.59.1.tar.gz", hash = "sha256:74995b402ad09822a4c8002438e54940d9f1ecda898d2bb057729d7da983e4cb", size = 3534394, upload-time = "2025-08-14T16:28:14.266Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/a5/fba25f9fbdab96e26dedcaeeba125e5f05a09043bf888e0305326e55685b/fonttools-4.59.2.tar.gz", hash = "sha256:e72c0749b06113f50bcb80332364c6be83a9582d6e3db3fe0b280f996dc2ef22", size = 3540889, upload-time = "2025-08-27T16:40:30.97Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/34/62/9667599561f623d4a523cc9eb4f66f3b94b6155464110fa9aebbf90bbec7/fonttools-4.59.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4909cce2e35706f3d18c54d3dcce0414ba5e0fb436a454dffec459c61653b513", size = 2778815, upload-time = "2025-08-14T16:26:28.484Z" }, - { url = "https://files.pythonhosted.org/packages/8f/78/cc25bcb2ce86033a9df243418d175e58f1956a35047c685ef553acae67d6/fonttools-4.59.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:efbec204fa9f877641747f2d9612b2b656071390d7a7ef07a9dbf0ecf9c7195c", size = 2341631, upload-time = "2025-08-14T16:26:30.396Z" }, - { url = "https://files.pythonhosted.org/packages/a4/cc/fcbb606dd6871f457ac32f281c20bcd6cc77d9fce77b5a4e2b2afab1f500/fonttools-4.59.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39dfd42cc2dc647b2c5469bc7a5b234d9a49e72565b96dd14ae6f11c2c59ef15", size = 5022222, upload-time = "2025-08-14T16:26:32.447Z" }, - { url = "https://files.pythonhosted.org/packages/61/96/c0b1cf2b74d08eb616a80dbf5564351fe4686147291a25f7dce8ace51eb3/fonttools-4.59.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b11bc177a0d428b37890825d7d025040d591aa833f85f8d8878ed183354f47df", size = 4966512, upload-time = "2025-08-14T16:26:34.621Z" }, - { url = "https://files.pythonhosted.org/packages/a4/26/51ce2e3e0835ffc2562b1b11d1fb9dafd0aca89c9041b64a9e903790a761/fonttools-4.59.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b9b4c35b3be45e5bc774d3fc9608bbf4f9a8d371103b858c80edbeed31dd5aa", size = 5001645, upload-time = "2025-08-14T16:26:36.876Z" }, - { url = "https://files.pythonhosted.org/packages/36/11/ef0b23f4266349b6d5ccbd1a07b7adc998d5bce925792aa5d1ec33f593e3/fonttools-4.59.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:01158376b8a418a0bae9625c476cebfcfcb5e6761e9d243b219cd58341e7afbb", size = 5113777, upload-time = "2025-08-14T16:26:39.002Z" }, - { url = "https://files.pythonhosted.org/packages/d0/da/b398fe61ef433da0a0472cdb5d4399124f7581ffe1a31b6242c91477d802/fonttools-4.59.1-cp311-cp311-win32.whl", hash = "sha256:cf7c5089d37787387123f1cb8f1793a47c5e1e3d1e4e7bfbc1cc96e0f925eabe", size = 2215076, upload-time = "2025-08-14T16:26:41.196Z" }, - { url = "https://files.pythonhosted.org/packages/94/bd/e2624d06ab94e41c7c77727b2941f1baed7edb647e63503953e6888020c9/fonttools-4.59.1-cp311-cp311-win_amd64.whl", hash = "sha256:c866eef7a0ba320486ade6c32bfc12813d1a5db8567e6904fb56d3d40acc5116", size = 2262779, upload-time = "2025-08-14T16:26:43.483Z" }, - { url = "https://files.pythonhosted.org/packages/ac/fe/6e069cc4cb8881d164a9bd956e9df555bc62d3eb36f6282e43440200009c/fonttools-4.59.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:43ab814bbba5f02a93a152ee61a04182bb5809bd2bc3609f7822e12c53ae2c91", size = 2769172, upload-time = "2025-08-14T16:26:45.729Z" }, - { url = "https://files.pythonhosted.org/packages/b9/98/ec4e03f748fefa0dd72d9d95235aff6fef16601267f4a2340f0e16b9330f/fonttools-4.59.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4f04c3ffbfa0baafcbc550657cf83657034eb63304d27b05cff1653b448ccff6", size = 2337281, upload-time = "2025-08-14T16:26:47.921Z" }, - { url = "https://files.pythonhosted.org/packages/8b/b1/890360a7e3d04a30ba50b267aca2783f4c1364363797e892e78a4f036076/fonttools-4.59.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d601b153e51a5a6221f0d4ec077b6bfc6ac35bfe6c19aeaa233d8990b2b71726", size = 4909215, upload-time = "2025-08-14T16:26:49.682Z" }, - { url = "https://files.pythonhosted.org/packages/8a/ec/2490599550d6c9c97a44c1e36ef4de52d6acf742359eaa385735e30c05c4/fonttools-4.59.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c735e385e30278c54f43a0d056736942023c9043f84ee1021eff9fd616d17693", size = 4951958, upload-time = "2025-08-14T16:26:51.616Z" }, - { url = "https://files.pythonhosted.org/packages/d1/40/bd053f6f7634234a9b9805ff8ae4f32df4f2168bee23cafd1271ba9915a9/fonttools-4.59.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1017413cdc8555dce7ee23720da490282ab7ec1cf022af90a241f33f9a49afc4", size = 4894738, upload-time = "2025-08-14T16:26:53.836Z" }, - { url = "https://files.pythonhosted.org/packages/ac/a1/3cd12a010d288325a7cfcf298a84825f0f9c29b01dee1baba64edfe89257/fonttools-4.59.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5c6d8d773470a5107052874341ed3c487c16ecd179976d81afed89dea5cd7406", size = 5045983, upload-time = "2025-08-14T16:26:56.153Z" }, - { url = "https://files.pythonhosted.org/packages/a2/af/8a2c3f6619cc43cf87951405337cc8460d08a4e717bb05eaa94b335d11dc/fonttools-4.59.1-cp312-cp312-win32.whl", hash = "sha256:2a2d0d33307f6ad3a2086a95dd607c202ea8852fa9fb52af9b48811154d1428a", size = 2203407, upload-time = "2025-08-14T16:26:58.165Z" }, - { url = "https://files.pythonhosted.org/packages/8e/f2/a19b874ddbd3ebcf11d7e25188ef9ac3f68b9219c62263acb34aca8cde05/fonttools-4.59.1-cp312-cp312-win_amd64.whl", hash = "sha256:0b9e4fa7eaf046ed6ac470f6033d52c052481ff7a6e0a92373d14f556f298dc0", size = 2251561, upload-time = "2025-08-14T16:27:00.646Z" }, - { url = "https://files.pythonhosted.org/packages/0f/64/9d606e66d498917cd7a2ff24f558010d42d6fd4576d9dd57f0bd98333f5a/fonttools-4.59.1-py3-none-any.whl", hash = "sha256:647db657073672a8330608970a984d51573557f328030566521bc03415535042", size = 1130094, upload-time = "2025-08-14T16:28:12.048Z" }, + { url = "https://files.pythonhosted.org/packages/f8/53/742fcd750ae0bdc74de4c0ff923111199cc2f90a4ee87aaddad505b6f477/fonttools-4.59.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:511946e8d7ea5c0d6c7a53c4cb3ee48eda9ab9797cd9bf5d95829a398400354f", size = 2774961, upload-time = "2025-08-27T16:38:47.536Z" }, + { url = "https://files.pythonhosted.org/packages/57/2a/976f5f9fa3b4dd911dc58d07358467bec20e813d933bc5d3db1a955dd456/fonttools-4.59.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8e5e2682cf7be766d84f462ba8828d01e00c8751a8e8e7ce12d7784ccb69a30d", size = 2344690, upload-time = "2025-08-27T16:38:49.723Z" }, + { url = "https://files.pythonhosted.org/packages/c1/8f/b7eefc274fcf370911e292e95565c8253b0b87c82a53919ab3c795a4f50e/fonttools-4.59.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5729e12a982dba3eeae650de48b06f3b9ddb51e9aee2fcaf195b7d09a96250e2", size = 5026910, upload-time = "2025-08-27T16:38:51.904Z" }, + { url = "https://files.pythonhosted.org/packages/69/95/864726eaa8f9d4e053d0c462e64d5830ec7c599cbdf1db9e40f25ca3972e/fonttools-4.59.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c52694eae5d652361d59ecdb5a2246bff7cff13b6367a12da8499e9df56d148d", size = 4971031, upload-time = "2025-08-27T16:38:53.676Z" }, + { url = "https://files.pythonhosted.org/packages/24/4c/b8c4735ebdea20696277c70c79e0de615dbe477834e5a7c2569aa1db4033/fonttools-4.59.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f1f1bbc23ba1312bd8959896f46f667753b90216852d2a8cfa2d07e0cb234144", size = 5006112, upload-time = "2025-08-27T16:38:55.69Z" }, + { url = "https://files.pythonhosted.org/packages/3b/23/f9ea29c292aa2fc1ea381b2e5621ac436d5e3e0a5dee24ffe5404e58eae8/fonttools-4.59.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1a1bfe5378962825dabe741720885e8b9ae9745ec7ecc4a5ec1f1ce59a6062bf", size = 5117671, upload-time = "2025-08-27T16:38:58.984Z" }, + { url = "https://files.pythonhosted.org/packages/ba/07/cfea304c555bf06e86071ff2a3916bc90f7c07ec85b23bab758d4908c33d/fonttools-4.59.2-cp311-cp311-win32.whl", hash = "sha256:e937790f3c2c18a1cbc7da101550a84319eb48023a715914477d2e7faeaba570", size = 2218157, upload-time = "2025-08-27T16:39:00.75Z" }, + { url = "https://files.pythonhosted.org/packages/d7/de/35d839aa69db737a3f9f3a45000ca24721834d40118652a5775d5eca8ebb/fonttools-4.59.2-cp311-cp311-win_amd64.whl", hash = "sha256:9836394e2f4ce5f9c0a7690ee93bd90aa1adc6b054f1a57b562c5d242c903104", size = 2265846, upload-time = "2025-08-27T16:39:02.453Z" }, + { url = "https://files.pythonhosted.org/packages/ba/3d/1f45db2df51e7bfa55492e8f23f383d372200be3a0ded4bf56a92753dd1f/fonttools-4.59.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:82906d002c349cad647a7634b004825a7335f8159d0d035ae89253b4abf6f3ea", size = 2769711, upload-time = "2025-08-27T16:39:04.423Z" }, + { url = "https://files.pythonhosted.org/packages/29/df/cd236ab32a8abfd11558f296e064424258db5edefd1279ffdbcfd4fd8b76/fonttools-4.59.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a10c1bd7644dc58f8862d8ba0cf9fb7fef0af01ea184ba6ce3f50ab7dfe74d5a", size = 2340225, upload-time = "2025-08-27T16:39:06.143Z" }, + { url = "https://files.pythonhosted.org/packages/98/12/b6f9f964fe6d4b4dd4406bcbd3328821c3de1f909ffc3ffa558fe72af48c/fonttools-4.59.2-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:738f31f23e0339785fd67652a94bc69ea49e413dfdb14dcb8c8ff383d249464e", size = 4912766, upload-time = "2025-08-27T16:39:08.138Z" }, + { url = "https://files.pythonhosted.org/packages/73/78/82bde2f2d2c306ef3909b927363170b83df96171f74e0ccb47ad344563cd/fonttools-4.59.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ec99f9bdfee9cdb4a9172f9e8fd578cce5feb231f598909e0aecf5418da4f25", size = 4955178, upload-time = "2025-08-27T16:39:10.094Z" }, + { url = "https://files.pythonhosted.org/packages/92/77/7de766afe2d31dda8ee46d7e479f35c7d48747e558961489a2d6e3a02bd4/fonttools-4.59.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0476ea74161322e08c7a982f83558a2b81b491509984523a1a540baf8611cc31", size = 4897898, upload-time = "2025-08-27T16:39:12.087Z" }, + { url = "https://files.pythonhosted.org/packages/c5/77/ce0e0b905d62a06415fda9f2b2e109a24a5db54a59502b769e9e297d2242/fonttools-4.59.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:95922a922daa1f77cc72611747c156cfb38030ead72436a2c551d30ecef519b9", size = 5049144, upload-time = "2025-08-27T16:39:13.84Z" }, + { url = "https://files.pythonhosted.org/packages/d9/ea/870d93aefd23fff2e07cbeebdc332527868422a433c64062c09d4d5e7fe6/fonttools-4.59.2-cp312-cp312-win32.whl", hash = "sha256:39ad9612c6a622726a6a130e8ab15794558591f999673f1ee7d2f3d30f6a3e1c", size = 2206473, upload-time = "2025-08-27T16:39:15.854Z" }, + { url = "https://files.pythonhosted.org/packages/61/c4/e44bad000c4a4bb2e9ca11491d266e857df98ab6d7428441b173f0fe2517/fonttools-4.59.2-cp312-cp312-win_amd64.whl", hash = "sha256:980fd7388e461b19a881d35013fec32c713ffea1fc37aef2f77d11f332dfd7da", size = 2254706, upload-time = "2025-08-27T16:39:17.893Z" }, + { url = "https://files.pythonhosted.org/packages/65/a4/d2f7be3c86708912c02571db0b550121caab8cd88a3c0aacb9cfa15ea66e/fonttools-4.59.2-py3-none-any.whl", hash = "sha256:8bd0f759020e87bb5d323e6283914d9bf4ae35a7307dafb2cbd1e379e720ad37", size = 1132315, upload-time = "2025-08-27T16:40:28.984Z" }, ] [[package]] @@ -855,7 +855,7 @@ wheels = [ [[package]] name = "matplotlib" -version = "3.10.5" +version = "3.10.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "contourpy" }, @@ -868,25 +868,25 @@ dependencies = [ { name = "pyparsing" }, { name = "python-dateutil" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/43/91/f2939bb60b7ebf12478b030e0d7f340247390f402b3b189616aad790c366/matplotlib-3.10.5.tar.gz", hash = "sha256:352ed6ccfb7998a00881692f38b4ca083c691d3e275b4145423704c34c909076", size = 34804044, upload-time = "2025-07-31T18:09:33.805Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a0/59/c3e6453a9676ffba145309a73c462bb407f4400de7de3f2b41af70720a3c/matplotlib-3.10.6.tar.gz", hash = "sha256:ec01b645840dd1996df21ee37f208cd8ba57644779fa20464010638013d3203c", size = 34804264, upload-time = "2025-08-30T00:14:25.137Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/aa/c7/1f2db90a1d43710478bb1e9b57b162852f79234d28e4f48a28cc415aa583/matplotlib-3.10.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:dcfc39c452c6a9f9028d3e44d2d721484f665304857188124b505b2c95e1eecf", size = 8239216, upload-time = "2025-07-31T18:07:51.947Z" }, - { url = "https://files.pythonhosted.org/packages/82/6d/ca6844c77a4f89b1c9e4d481c412e1d1dbabf2aae2cbc5aa2da4a1d6683e/matplotlib-3.10.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:903352681b59f3efbf4546985142a9686ea1d616bb054b09a537a06e4b892ccf", size = 8102130, upload-time = "2025-07-31T18:07:53.65Z" }, - { url = "https://files.pythonhosted.org/packages/1d/1e/5e187a30cc673a3e384f3723e5f3c416033c1d8d5da414f82e4e731128ea/matplotlib-3.10.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:080c3676a56b8ee1c762bcf8fca3fe709daa1ee23e6ef06ad9f3fc17332f2d2a", size = 8666471, upload-time = "2025-07-31T18:07:55.304Z" }, - { url = "https://files.pythonhosted.org/packages/03/c0/95540d584d7d645324db99a845ac194e915ef75011a0d5e19e1b5cee7e69/matplotlib-3.10.5-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4b4984d5064a35b6f66d2c11d668565f4389b1119cc64db7a4c1725bc11adffc", size = 9500518, upload-time = "2025-07-31T18:07:57.199Z" }, - { url = "https://files.pythonhosted.org/packages/ba/2e/e019352099ea58b4169adb9c6e1a2ad0c568c6377c2b677ee1f06de2adc7/matplotlib-3.10.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3967424121d3a46705c9fa9bdb0931de3228f13f73d7bb03c999c88343a89d89", size = 9552372, upload-time = "2025-07-31T18:07:59.41Z" }, - { url = "https://files.pythonhosted.org/packages/b7/81/3200b792a5e8b354f31f4101ad7834743ad07b6d620259f2059317b25e4d/matplotlib-3.10.5-cp311-cp311-win_amd64.whl", hash = "sha256:33775bbeb75528555a15ac29396940128ef5613cf9a2d31fb1bfd18b3c0c0903", size = 8100634, upload-time = "2025-07-31T18:08:01.801Z" }, - { url = "https://files.pythonhosted.org/packages/52/46/a944f6f0c1f5476a0adfa501969d229ce5ae60cf9a663be0e70361381f89/matplotlib-3.10.5-cp311-cp311-win_arm64.whl", hash = "sha256:c61333a8e5e6240e73769d5826b9a31d8b22df76c0778f8480baf1b4b01c9420", size = 7978880, upload-time = "2025-07-31T18:08:03.407Z" }, - { url = "https://files.pythonhosted.org/packages/66/1e/c6f6bcd882d589410b475ca1fc22e34e34c82adff519caf18f3e6dd9d682/matplotlib-3.10.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:00b6feadc28a08bd3c65b2894f56cf3c94fc8f7adcbc6ab4516ae1e8ed8f62e2", size = 8253056, upload-time = "2025-07-31T18:08:05.385Z" }, - { url = "https://files.pythonhosted.org/packages/53/e6/d6f7d1b59413f233793dda14419776f5f443bcccb2dfc84b09f09fe05dbe/matplotlib-3.10.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee98a5c5344dc7f48dc261b6ba5d9900c008fc12beb3fa6ebda81273602cc389", size = 8110131, upload-time = "2025-07-31T18:08:07.293Z" }, - { url = "https://files.pythonhosted.org/packages/66/2b/bed8a45e74957549197a2ac2e1259671cd80b55ed9e1fe2b5c94d88a9202/matplotlib-3.10.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a17e57e33de901d221a07af32c08870ed4528db0b6059dce7d7e65c1122d4bea", size = 8669603, upload-time = "2025-07-31T18:08:09.064Z" }, - { url = "https://files.pythonhosted.org/packages/7e/a7/315e9435b10d057f5e52dfc603cd353167ae28bb1a4e033d41540c0067a4/matplotlib-3.10.5-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97b9d6443419085950ee4a5b1ee08c363e5c43d7176e55513479e53669e88468", size = 9508127, upload-time = "2025-07-31T18:08:10.845Z" }, - { url = "https://files.pythonhosted.org/packages/7f/d9/edcbb1f02ca99165365d2768d517898c22c6040187e2ae2ce7294437c413/matplotlib-3.10.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ceefe5d40807d29a66ae916c6a3915d60ef9f028ce1927b84e727be91d884369", size = 9566926, upload-time = "2025-07-31T18:08:13.186Z" }, - { url = "https://files.pythonhosted.org/packages/3b/d9/6dd924ad5616c97b7308e6320cf392c466237a82a2040381163b7500510a/matplotlib-3.10.5-cp312-cp312-win_amd64.whl", hash = "sha256:c04cba0f93d40e45b3c187c6c52c17f24535b27d545f757a2fffebc06c12b98b", size = 8107599, upload-time = "2025-07-31T18:08:15.116Z" }, - { url = "https://files.pythonhosted.org/packages/0e/f3/522dc319a50f7b0279fbe74f86f7a3506ce414bc23172098e8d2bdf21894/matplotlib-3.10.5-cp312-cp312-win_arm64.whl", hash = "sha256:a41bcb6e2c8e79dc99c5511ae6f7787d2fb52efd3d805fff06d5d4f667db16b2", size = 7978173, upload-time = "2025-07-31T18:08:21.518Z" }, - { url = "https://files.pythonhosted.org/packages/dc/d6/e921be4e1a5f7aca5194e1f016cb67ec294548e530013251f630713e456d/matplotlib-3.10.5-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:160e125da27a749481eaddc0627962990f6029811dbeae23881833a011a0907f", size = 8233224, upload-time = "2025-07-31T18:09:27.512Z" }, - { url = "https://files.pythonhosted.org/packages/ec/74/a2b9b04824b9c349c8f1b2d21d5af43fa7010039427f2b133a034cb09e59/matplotlib-3.10.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ac3d50760394d78a3c9be6b28318fe22b494c4fcf6407e8fd4794b538251899b", size = 8098539, upload-time = "2025-07-31T18:09:29.629Z" }, - { url = "https://files.pythonhosted.org/packages/fc/66/cd29ebc7f6c0d2a15d216fb572573e8fc38bd5d6dec3bd9d7d904c0949f7/matplotlib-3.10.5-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6c49465bf689c4d59d174d0c7795fb42a21d4244d11d70e52b8011987367ac61", size = 8672192, upload-time = "2025-07-31T18:09:31.407Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/5d3665aa44c49005aaacaa68ddea6fcb27345961cd538a98bb0177934ede/matplotlib-3.10.6-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:905b60d1cb0ee604ce65b297b61cf8be9f4e6cfecf95a3fe1c388b5266bc8f4f", size = 8257527, upload-time = "2025-08-30T00:12:45.31Z" }, + { url = "https://files.pythonhosted.org/packages/8c/af/30ddefe19ca67eebd70047dabf50f899eaff6f3c5e6a1a7edaecaf63f794/matplotlib-3.10.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7bac38d816637343e53d7185d0c66677ff30ffb131044a81898b5792c956ba76", size = 8119583, upload-time = "2025-08-30T00:12:47.236Z" }, + { url = "https://files.pythonhosted.org/packages/d3/29/4a8650a3dcae97fa4f375d46efcb25920d67b512186f8a6788b896062a81/matplotlib-3.10.6-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:942a8de2b5bfff1de31d95722f702e2966b8a7e31f4e68f7cd963c7cd8861cf6", size = 8692682, upload-time = "2025-08-30T00:12:48.781Z" }, + { url = "https://files.pythonhosted.org/packages/aa/d3/b793b9cb061cfd5d42ff0f69d1822f8d5dbc94e004618e48a97a8373179a/matplotlib-3.10.6-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a3276c85370bc0dfca051ec65c5817d1e0f8f5ce1b7787528ec8ed2d524bbc2f", size = 9521065, upload-time = "2025-08-30T00:12:50.602Z" }, + { url = "https://files.pythonhosted.org/packages/f7/c5/53de5629f223c1c66668d46ac2621961970d21916a4bc3862b174eb2a88f/matplotlib-3.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9df5851b219225731f564e4b9e7f2ac1e13c9e6481f941b5631a0f8e2d9387ce", size = 9576888, upload-time = "2025-08-30T00:12:52.92Z" }, + { url = "https://files.pythonhosted.org/packages/fc/8e/0a18d6d7d2d0a2e66585032a760d13662e5250c784d53ad50434e9560991/matplotlib-3.10.6-cp311-cp311-win_amd64.whl", hash = "sha256:abb5d9478625dd9c9eb51a06d39aae71eda749ae9b3138afb23eb38824026c7e", size = 8115158, upload-time = "2025-08-30T00:12:54.863Z" }, + { url = "https://files.pythonhosted.org/packages/07/b3/1a5107bb66c261e23b9338070702597a2d374e5aa7004b7adfc754fbed02/matplotlib-3.10.6-cp311-cp311-win_arm64.whl", hash = "sha256:886f989ccfae63659183173bb3fced7fd65e9eb793c3cc21c273add368536951", size = 7992444, upload-time = "2025-08-30T00:12:57.067Z" }, + { url = "https://files.pythonhosted.org/packages/ea/1a/7042f7430055d567cc3257ac409fcf608599ab27459457f13772c2d9778b/matplotlib-3.10.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:31ca662df6a80bd426f871105fdd69db7543e28e73a9f2afe80de7e531eb2347", size = 8272404, upload-time = "2025-08-30T00:12:59.112Z" }, + { url = "https://files.pythonhosted.org/packages/a9/5d/1d5f33f5b43f4f9e69e6a5fe1fb9090936ae7bc8e2ff6158e7a76542633b/matplotlib-3.10.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1678bb61d897bb4ac4757b5ecfb02bfb3fddf7f808000fb81e09c510712fda75", size = 8128262, upload-time = "2025-08-30T00:13:01.141Z" }, + { url = "https://files.pythonhosted.org/packages/67/c3/135fdbbbf84e0979712df58e5e22b4f257b3f5e52a3c4aacf1b8abec0d09/matplotlib-3.10.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:56cd2d20842f58c03d2d6e6c1f1cf5548ad6f66b91e1e48f814e4fb5abd1cb95", size = 8697008, upload-time = "2025-08-30T00:13:03.24Z" }, + { url = "https://files.pythonhosted.org/packages/9c/be/c443ea428fb2488a3ea7608714b1bd85a82738c45da21b447dc49e2f8e5d/matplotlib-3.10.6-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:662df55604a2f9a45435566d6e2660e41efe83cd94f4288dfbf1e6d1eae4b0bb", size = 9530166, upload-time = "2025-08-30T00:13:05.951Z" }, + { url = "https://files.pythonhosted.org/packages/a9/35/48441422b044d74034aea2a3e0d1a49023f12150ebc58f16600132b9bbaf/matplotlib-3.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:08f141d55148cd1fc870c3387d70ca4df16dee10e909b3b038782bd4bda6ea07", size = 9593105, upload-time = "2025-08-30T00:13:08.356Z" }, + { url = "https://files.pythonhosted.org/packages/45/c3/994ef20eb4154ab84cc08d033834555319e4af970165e6c8894050af0b3c/matplotlib-3.10.6-cp312-cp312-win_amd64.whl", hash = "sha256:590f5925c2d650b5c9d813c5b3b5fc53f2929c3f8ef463e4ecfa7e052044fb2b", size = 8122784, upload-time = "2025-08-30T00:13:10.367Z" }, + { url = "https://files.pythonhosted.org/packages/57/b8/5c85d9ae0e40f04e71bedb053aada5d6bab1f9b5399a0937afb5d6b02d98/matplotlib-3.10.6-cp312-cp312-win_arm64.whl", hash = "sha256:f44c8d264a71609c79a78d50349e724f5d5fc3684ead7c2a473665ee63d868aa", size = 7992823, upload-time = "2025-08-30T00:13:12.24Z" }, + { url = "https://files.pythonhosted.org/packages/12/bb/02c35a51484aae5f49bd29f091286e7af5f3f677a9736c58a92b3c78baeb/matplotlib-3.10.6-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f2d684c3204fa62421bbf770ddfebc6b50130f9cad65531eeba19236d73bb488", size = 8252296, upload-time = "2025-08-30T00:14:19.49Z" }, + { url = "https://files.pythonhosted.org/packages/7d/85/41701e3092005aee9a2445f5ee3904d9dbd4a7df7a45905ffef29b7ef098/matplotlib-3.10.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:6f4a69196e663a41d12a728fab8751177215357906436804217d6d9cf0d4d6cf", size = 8116749, upload-time = "2025-08-30T00:14:21.344Z" }, + { url = "https://files.pythonhosted.org/packages/16/53/8d8fa0ea32a8c8239e04d022f6c059ee5e1b77517769feccd50f1df43d6d/matplotlib-3.10.6-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d6ca6ef03dfd269f4ead566ec6f3fb9becf8dab146fb999022ed85ee9f6b3eb", size = 8693933, upload-time = "2025-08-30T00:14:22.942Z" }, ] [[package]] @@ -990,6 +990,27 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9f/d4/029f984e8d3f3b6b726bd33cafc473b75e9e44c0f7e80a5b29abc466bdea/mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134", size = 9521, upload-time = "2023-11-20T17:51:08.587Z" }, ] +[[package]] +name = "ml-dtypes" +version = "0.5.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/a7/aad060393123cfb383956dca68402aff3db1e1caffd5764887ed5153f41b/ml_dtypes-0.5.3.tar.gz", hash = "sha256:95ce33057ba4d05df50b1f3cfefab22e351868a843b3b15a46c65836283670c9", size = 692316, upload-time = "2025-07-29T18:39:19.454Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/f1/720cb1409b5d0c05cff9040c0e9fba73fa4c67897d33babf905d5d46a070/ml_dtypes-0.5.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4a177b882667c69422402df6ed5c3428ce07ac2c1f844d8a1314944651439458", size = 667412, upload-time = "2025-07-29T18:38:25.275Z" }, + { url = "https://files.pythonhosted.org/packages/6a/d5/05861ede5d299f6599f86e6bc1291714e2116d96df003cfe23cc54bcc568/ml_dtypes-0.5.3-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9849ce7267444c0a717c80c6900997de4f36e2815ce34ac560a3edb2d9a64cd2", size = 4964606, upload-time = "2025-07-29T18:38:27.045Z" }, + { url = "https://files.pythonhosted.org/packages/db/dc/72992b68de367741bfab8df3b3fe7c29f982b7279d341aa5bf3e7ef737ea/ml_dtypes-0.5.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c3f5ae0309d9f888fd825c2e9d0241102fadaca81d888f26f845bc8c13c1e4ee", size = 4938435, upload-time = "2025-07-29T18:38:29.193Z" }, + { url = "https://files.pythonhosted.org/packages/81/1c/d27a930bca31fb07d975a2d7eaf3404f9388114463b9f15032813c98f893/ml_dtypes-0.5.3-cp311-cp311-win_amd64.whl", hash = "sha256:58e39349d820b5702bb6f94ea0cb2dc8ec62ee81c0267d9622067d8333596a46", size = 206334, upload-time = "2025-07-29T18:38:30.687Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d8/6922499effa616012cb8dc445280f66d100a7ff39b35c864cfca019b3f89/ml_dtypes-0.5.3-cp311-cp311-win_arm64.whl", hash = "sha256:66c2756ae6cfd7f5224e355c893cfd617fa2f747b8bbd8996152cbdebad9a184", size = 157584, upload-time = "2025-07-29T18:38:32.187Z" }, + { url = "https://files.pythonhosted.org/packages/0d/eb/bc07c88a6ab002b4635e44585d80fa0b350603f11a2097c9d1bfacc03357/ml_dtypes-0.5.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:156418abeeda48ea4797db6776db3c5bdab9ac7be197c1233771e0880c304057", size = 663864, upload-time = "2025-07-29T18:38:33.777Z" }, + { url = "https://files.pythonhosted.org/packages/cf/89/11af9b0f21b99e6386b6581ab40fb38d03225f9de5f55cf52097047e2826/ml_dtypes-0.5.3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1db60c154989af253f6c4a34e8a540c2c9dce4d770784d426945e09908fbb177", size = 4951313, upload-time = "2025-07-29T18:38:36.45Z" }, + { url = "https://files.pythonhosted.org/packages/d8/a9/b98b86426c24900b0c754aad006dce2863df7ce0bb2bcc2c02f9cc7e8489/ml_dtypes-0.5.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1b255acada256d1fa8c35ed07b5f6d18bc21d1556f842fbc2d5718aea2cd9e55", size = 4928805, upload-time = "2025-07-29T18:38:38.29Z" }, + { url = "https://files.pythonhosted.org/packages/50/c1/85e6be4fc09c6175f36fb05a45917837f30af9a5146a5151cb3a3f0f9e09/ml_dtypes-0.5.3-cp312-cp312-win_amd64.whl", hash = "sha256:da65e5fd3eea434ccb8984c3624bc234ddcc0d9f4c81864af611aaebcc08a50e", size = 208182, upload-time = "2025-07-29T18:38:39.72Z" }, + { url = "https://files.pythonhosted.org/packages/9e/17/cf5326d6867be057f232d0610de1458f70a8ce7b6290e4b4a277ea62b4cd/ml_dtypes-0.5.3-cp312-cp312-win_arm64.whl", hash = "sha256:8bb9cd1ce63096567f5f42851f5843b5a0ea11511e50039a7649619abfb4ba6d", size = 161560, upload-time = "2025-07-29T18:38:41.072Z" }, +] + [[package]] name = "mouseinfo" version = "0.1.3" @@ -1164,27 +1185,28 @@ wheels = [ [[package]] name = "onnx" -version = "1.18.0" +version = "1.19.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "ml-dtypes" }, { name = "numpy" }, { name = "protobuf" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3d/60/e56e8ec44ed34006e6d4a73c92a04d9eea6163cc12440e35045aec069175/onnx-1.18.0.tar.gz", hash = "sha256:3d8dbf9e996629131ba3aa1afd1d8239b660d1f830c6688dd7e03157cccd6b9c", size = 12563009, upload-time = "2025-05-12T22:03:09.626Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5b/bf/b0a63ee9f3759dcd177b28c6f2cb22f2aecc6d9b3efecaabc298883caa5f/onnx-1.19.0.tar.gz", hash = "sha256:aa3f70b60f54a29015e41639298ace06adf1dd6b023b9b30f1bca91bb0db9473", size = 11949859, upload-time = "2025-08-27T02:34:27.107Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/3a/a336dac4db1eddba2bf577191e5b7d3e4c26fcee5ec518a5a5b11d13540d/onnx-1.18.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:735e06d8d0cf250dc498f54038831401063c655a8d6e5975b2527a4e7d24be3e", size = 18281831, upload-time = "2025-05-12T22:02:06.429Z" }, - { url = "https://files.pythonhosted.org/packages/02/3a/56475a111120d1e5d11939acbcbb17c92198c8e64a205cd68e00bdfd8a1f/onnx-1.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:73160799472e1a86083f786fecdf864cf43d55325492a9b5a1cfa64d8a523ecc", size = 17424359, upload-time = "2025-05-12T22:02:09.866Z" }, - { url = "https://files.pythonhosted.org/packages/cf/03/5eb5e9ef446ed9e78c4627faf3c1bc25e0f707116dd00e9811de232a8df5/onnx-1.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6acafb3823238bbe8f4340c7ac32fb218689442e074d797bee1c5c9a02fdae75", size = 17586006, upload-time = "2025-05-12T22:02:13.217Z" }, - { url = "https://files.pythonhosted.org/packages/b0/4e/70943125729ce453271a6e46bb847b4a612496f64db6cbc6cb1f49f41ce1/onnx-1.18.0-cp311-cp311-win32.whl", hash = "sha256:4c8c4bbda760c654e65eaffddb1a7de71ec02e60092d33f9000521f897c99be9", size = 15734988, upload-time = "2025-05-12T22:02:16.561Z" }, - { url = "https://files.pythonhosted.org/packages/44/b0/435fd764011911e8f599e3361f0f33425b1004662c1ea33a0ad22e43db2d/onnx-1.18.0-cp311-cp311-win_amd64.whl", hash = "sha256:a5810194f0f6be2e58c8d6dedc6119510df7a14280dd07ed5f0f0a85bd74816a", size = 15849576, upload-time = "2025-05-12T22:02:19.569Z" }, - { url = "https://files.pythonhosted.org/packages/6c/f0/9e31f4b4626d60f1c034f71b411810bc9fafe31f4e7dd3598effd1b50e05/onnx-1.18.0-cp311-cp311-win_arm64.whl", hash = "sha256:aa1b7483fac6cdec26922174fc4433f8f5c2f239b1133c5625063bb3b35957d0", size = 15822961, upload-time = "2025-05-12T22:02:22.735Z" }, - { url = "https://files.pythonhosted.org/packages/a7/fe/16228aca685392a7114625b89aae98b2dc4058a47f0f467a376745efe8d0/onnx-1.18.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:521bac578448667cbb37c50bf05b53c301243ede8233029555239930996a625b", size = 18285770, upload-time = "2025-05-12T22:02:26.116Z" }, - { url = "https://files.pythonhosted.org/packages/1e/77/ba50a903a9b5e6f9be0fa50f59eb2fca4a26ee653375408fbc72c3acbf9f/onnx-1.18.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4da451bf1c5ae381f32d430004a89f0405bc57a8471b0bddb6325a5b334aa40", size = 17421291, upload-time = "2025-05-12T22:02:29.645Z" }, - { url = "https://files.pythonhosted.org/packages/11/23/25ec2ba723ac62b99e8fed6d7b59094dadb15e38d4c007331cc9ae3dfa5f/onnx-1.18.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99afac90b4cdb1471432203c3c1f74e16549c526df27056d39f41a9a47cfb4af", size = 17584084, upload-time = "2025-05-12T22:02:32.789Z" }, - { url = "https://files.pythonhosted.org/packages/6a/4d/2c253a36070fb43f340ff1d2c450df6a9ef50b938adcd105693fee43c4ee/onnx-1.18.0-cp312-cp312-win32.whl", hash = "sha256:ee159b41a3ae58d9c7341cf432fc74b96aaf50bd7bb1160029f657b40dc69715", size = 15734892, upload-time = "2025-05-12T22:02:35.527Z" }, - { url = "https://files.pythonhosted.org/packages/e8/92/048ba8fafe6b2b9a268ec2fb80def7e66c0b32ab2cae74de886981f05a27/onnx-1.18.0-cp312-cp312-win_amd64.whl", hash = "sha256:102c04edc76b16e9dfeda5a64c1fccd7d3d2913b1544750c01d38f1ac3c04e05", size = 15850336, upload-time = "2025-05-12T22:02:38.545Z" }, - { url = "https://files.pythonhosted.org/packages/a1/66/bbc4ffedd44165dcc407a51ea4c592802a5391ce3dc94aa5045350f64635/onnx-1.18.0-cp312-cp312-win_arm64.whl", hash = "sha256:911b37d724a5d97396f3c2ef9ea25361c55cbc9aa18d75b12a52b620b67145af", size = 15823802, upload-time = "2025-05-12T22:02:42.037Z" }, + { url = "https://files.pythonhosted.org/packages/db/5c/b959b17608cfb6ccf6359b39fe56a5b0b7d965b3d6e6a3c0add90812c36e/onnx-1.19.0-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:206f00c47b85b5c7af79671e3307147407991a17994c26974565aadc9e96e4e4", size = 18312580, upload-time = "2025-08-27T02:33:03.081Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ee/ac052bbbc832abe0debb784c2c57f9582444fb5f51d63c2967fd04432444/onnx-1.19.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4d7bee94abaac28988b50da675ae99ef8dd3ce16210d591fbd0b214a5930beb3", size = 18029165, upload-time = "2025-08-27T02:33:05.771Z" }, + { url = "https://files.pythonhosted.org/packages/5c/c9/8687ba0948d46fd61b04e3952af9237883bbf8f16d716e7ed27e688d73b8/onnx-1.19.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7730b96b68c0c354bbc7857961bb4909b9aaa171360a8e3708d0a4c749aaadeb", size = 18202125, upload-time = "2025-08-27T02:33:09.325Z" }, + { url = "https://files.pythonhosted.org/packages/e2/16/6249c013e81bd689f46f96c7236d7677f1af5dd9ef22746716b48f10e506/onnx-1.19.0-cp311-cp311-win32.whl", hash = "sha256:7cb7a3ad8059d1a0dfdc5e0a98f71837d82002e441f112825403b137227c2c97", size = 16332738, upload-time = "2025-08-27T02:33:12.448Z" }, + { url = "https://files.pythonhosted.org/packages/6a/28/34a1e2166e418c6a78e5c82e66f409d9da9317832f11c647f7d4e23846a6/onnx-1.19.0-cp311-cp311-win_amd64.whl", hash = "sha256:d75452a9be868bd30c3ef6aa5991df89bbfe53d0d90b2325c5e730fbd91fff85", size = 16452303, upload-time = "2025-08-27T02:33:15.176Z" }, + { url = "https://files.pythonhosted.org/packages/e6/b7/639664626e5ba8027860c4d2a639ee02b37e9c322215c921e9222513c3aa/onnx-1.19.0-cp311-cp311-win_arm64.whl", hash = "sha256:23c7959370d7b3236f821e609b0af7763cff7672a758e6c1fc877bac099e786b", size = 16425340, upload-time = "2025-08-27T02:33:17.78Z" }, + { url = "https://files.pythonhosted.org/packages/0d/94/f56f6ca5e2f921b28c0f0476705eab56486b279f04e1d568ed64c14e7764/onnx-1.19.0-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:61d94e6498ca636756f8f4ee2135708434601b2892b7c09536befb19bc8ca007", size = 18322331, upload-time = "2025-08-27T02:33:20.373Z" }, + { url = "https://files.pythonhosted.org/packages/c8/00/8cc3f3c40b54b28f96923380f57c9176872e475face726f7d7a78bd74098/onnx-1.19.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:224473354462f005bae985c72028aaa5c85ab11de1b71d55b06fdadd64a667dd", size = 18027513, upload-time = "2025-08-27T02:33:23.44Z" }, + { url = "https://files.pythonhosted.org/packages/61/90/17c4d2566fd0117a5e412688c9525f8950d467f477fbd574e6b32bc9cb8d/onnx-1.19.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1ae475c85c89bc4d1f16571006fd21a3e7c0e258dd2c091f6e8aafb083d1ed9b", size = 18202278, upload-time = "2025-08-27T02:33:26.103Z" }, + { url = "https://files.pythonhosted.org/packages/bc/6e/a9383d9cf6db4ac761a129b081e9fa5d0cd89aad43cf1e3fc6285b915c7d/onnx-1.19.0-cp312-cp312-win32.whl", hash = "sha256:323f6a96383a9cdb3960396cffea0a922593d221f3929b17312781e9f9b7fb9f", size = 16333080, upload-time = "2025-08-27T02:33:28.559Z" }, + { url = "https://files.pythonhosted.org/packages/a7/2e/3ff480a8c1fa7939662bdc973e41914add2d4a1f2b8572a3c39c2e4982e5/onnx-1.19.0-cp312-cp312-win_amd64.whl", hash = "sha256:50220f3499a499b1a15e19451a678a58e22ad21b34edf2c844c6ef1d9febddc2", size = 16453927, upload-time = "2025-08-27T02:33:31.177Z" }, + { url = "https://files.pythonhosted.org/packages/57/37/ad500945b1b5c154fe9d7b826b30816ebd629d10211ea82071b5bcc30aa4/onnx-1.19.0-cp312-cp312-win_arm64.whl", hash = "sha256:efb768299580b786e21abe504e1652ae6189f0beed02ab087cd841cb4bb37e43", size = 16426022, upload-time = "2025-08-27T02:33:33.515Z" }, ] [[package]] @@ -4605,28 +4627,28 @@ wheels = [ [[package]] name = "ruff" -version = "0.12.10" +version = "0.12.11" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3b/eb/8c073deb376e46ae767f4961390d17545e8535921d2f65101720ed8bd434/ruff-0.12.10.tar.gz", hash = "sha256:189ab65149d11ea69a2d775343adf5f49bb2426fc4780f65ee33b423ad2e47f9", size = 5310076, upload-time = "2025-08-21T18:23:22.595Z" } +sdist = { url = "https://files.pythonhosted.org/packages/de/55/16ab6a7d88d93001e1ae4c34cbdcfb376652d761799459ff27c1dc20f6fa/ruff-0.12.11.tar.gz", hash = "sha256:c6b09ae8426a65bbee5425b9d0b82796dbb07cb1af045743c79bfb163001165d", size = 5347103, upload-time = "2025-08-28T13:59:08.87Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/24/e7/560d049d15585d6c201f9eeacd2fd130def3741323e5ccf123786e0e3c95/ruff-0.12.10-py3-none-linux_armv6l.whl", hash = "sha256:8b593cb0fb55cc8692dac7b06deb29afda78c721c7ccfed22db941201b7b8f7b", size = 11935161, upload-time = "2025-08-21T18:22:26.965Z" }, - { url = "https://files.pythonhosted.org/packages/d1/b0/ad2464922a1113c365d12b8f80ed70fcfb39764288ac77c995156080488d/ruff-0.12.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ebb7333a45d56efc7c110a46a69a1b32365d5c5161e7244aaf3aa20ce62399c1", size = 12660884, upload-time = "2025-08-21T18:22:30.925Z" }, - { url = "https://files.pythonhosted.org/packages/d7/f1/97f509b4108d7bae16c48389f54f005b62ce86712120fd8b2d8e88a7cb49/ruff-0.12.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d59e58586829f8e4a9920788f6efba97a13d1fa320b047814e8afede381c6839", size = 11872754, upload-time = "2025-08-21T18:22:34.035Z" }, - { url = "https://files.pythonhosted.org/packages/12/ad/44f606d243f744a75adc432275217296095101f83f966842063d78eee2d3/ruff-0.12.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:822d9677b560f1fdeab69b89d1f444bf5459da4aa04e06e766cf0121771ab844", size = 12092276, upload-time = "2025-08-21T18:22:36.764Z" }, - { url = "https://files.pythonhosted.org/packages/06/1f/ed6c265e199568010197909b25c896d66e4ef2c5e1c3808caf461f6f3579/ruff-0.12.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:37b4a64f4062a50c75019c61c7017ff598cb444984b638511f48539d3a1c98db", size = 11734700, upload-time = "2025-08-21T18:22:39.822Z" }, - { url = "https://files.pythonhosted.org/packages/63/c5/b21cde720f54a1d1db71538c0bc9b73dee4b563a7dd7d2e404914904d7f5/ruff-0.12.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c6f4064c69d2542029b2a61d39920c85240c39837599d7f2e32e80d36401d6e", size = 13468783, upload-time = "2025-08-21T18:22:42.559Z" }, - { url = "https://files.pythonhosted.org/packages/02/9e/39369e6ac7f2a1848f22fb0b00b690492f20811a1ac5c1fd1d2798329263/ruff-0.12.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:059e863ea3a9ade41407ad71c1de2badfbe01539117f38f763ba42a1206f7559", size = 14436642, upload-time = "2025-08-21T18:22:45.612Z" }, - { url = "https://files.pythonhosted.org/packages/e3/03/5da8cad4b0d5242a936eb203b58318016db44f5c5d351b07e3f5e211bb89/ruff-0.12.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1bef6161e297c68908b7218fa6e0e93e99a286e5ed9653d4be71e687dff101cf", size = 13859107, upload-time = "2025-08-21T18:22:48.886Z" }, - { url = "https://files.pythonhosted.org/packages/19/19/dd7273b69bf7f93a070c9cec9494a94048325ad18fdcf50114f07e6bf417/ruff-0.12.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4f1345fbf8fb0531cd722285b5f15af49b2932742fc96b633e883da8d841896b", size = 12886521, upload-time = "2025-08-21T18:22:51.567Z" }, - { url = "https://files.pythonhosted.org/packages/c0/1d/b4207ec35e7babaee62c462769e77457e26eb853fbdc877af29417033333/ruff-0.12.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f68433c4fbc63efbfa3ba5db31727db229fa4e61000f452c540474b03de52a9", size = 13097528, upload-time = "2025-08-21T18:22:54.609Z" }, - { url = "https://files.pythonhosted.org/packages/ff/00/58f7b873b21114456e880b75176af3490d7a2836033779ca42f50de3b47a/ruff-0.12.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:141ce3d88803c625257b8a6debf4a0473eb6eed9643a6189b68838b43e78165a", size = 13080443, upload-time = "2025-08-21T18:22:57.413Z" }, - { url = "https://files.pythonhosted.org/packages/12/8c/9e6660007fb10189ccb78a02b41691288038e51e4788bf49b0a60f740604/ruff-0.12.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f3fc21178cd44c98142ae7590f42ddcb587b8e09a3b849cbc84edb62ee95de60", size = 11896759, upload-time = "2025-08-21T18:23:00.473Z" }, - { url = "https://files.pythonhosted.org/packages/67/4c/6d092bb99ea9ea6ebda817a0e7ad886f42a58b4501a7e27cd97371d0ba54/ruff-0.12.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7d1a4e0bdfafcd2e3e235ecf50bf0176f74dd37902f241588ae1f6c827a36c56", size = 11701463, upload-time = "2025-08-21T18:23:03.211Z" }, - { url = "https://files.pythonhosted.org/packages/59/80/d982c55e91df981f3ab62559371380616c57ffd0172d96850280c2b04fa8/ruff-0.12.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:e67d96827854f50b9e3e8327b031647e7bcc090dbe7bb11101a81a3a2cbf1cc9", size = 12691603, upload-time = "2025-08-21T18:23:06.935Z" }, - { url = "https://files.pythonhosted.org/packages/ad/37/63a9c788bbe0b0850611669ec6b8589838faf2f4f959647f2d3e320383ae/ruff-0.12.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ae479e1a18b439c59138f066ae79cc0f3ee250712a873d00dbafadaad9481e5b", size = 13164356, upload-time = "2025-08-21T18:23:10.225Z" }, - { url = "https://files.pythonhosted.org/packages/47/d4/1aaa7fb201a74181989970ebccd12f88c0fc074777027e2a21de5a90657e/ruff-0.12.10-py3-none-win32.whl", hash = "sha256:9de785e95dc2f09846c5e6e1d3a3d32ecd0b283a979898ad427a9be7be22b266", size = 11896089, upload-time = "2025-08-21T18:23:14.232Z" }, - { url = "https://files.pythonhosted.org/packages/ad/14/2ad38fd4037daab9e023456a4a40ed0154e9971f8d6aed41bdea390aabd9/ruff-0.12.10-py3-none-win_amd64.whl", hash = "sha256:7837eca8787f076f67aba2ca559cefd9c5cbc3a9852fd66186f4201b87c1563e", size = 13004616, upload-time = "2025-08-21T18:23:17.422Z" }, - { url = "https://files.pythonhosted.org/packages/24/3c/21cf283d67af33a8e6ed242396863af195a8a6134ec581524fd22b9811b6/ruff-0.12.10-py3-none-win_arm64.whl", hash = "sha256:cc138cc06ed9d4bfa9d667a65af7172b47840e1a98b02ce7011c391e54635ffc", size = 12074225, upload-time = "2025-08-21T18:23:20.137Z" }, + { url = "https://files.pythonhosted.org/packages/d6/a2/3b3573e474de39a7a475f3fbaf36a25600bfeb238e1a90392799163b64a0/ruff-0.12.11-py3-none-linux_armv6l.whl", hash = "sha256:93fce71e1cac3a8bf9200e63a38ac5c078f3b6baebffb74ba5274fb2ab276065", size = 11979885, upload-time = "2025-08-28T13:58:26.654Z" }, + { url = "https://files.pythonhosted.org/packages/76/e4/235ad6d1785a2012d3ded2350fd9bc5c5af8c6f56820e696b0118dfe7d24/ruff-0.12.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b8e33ac7b28c772440afa80cebb972ffd823621ded90404f29e5ab6d1e2d4b93", size = 12742364, upload-time = "2025-08-28T13:58:30.256Z" }, + { url = "https://files.pythonhosted.org/packages/2c/0d/15b72c5fe6b1e402a543aa9d8960e0a7e19dfb079f5b0b424db48b7febab/ruff-0.12.11-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d69fb9d4937aa19adb2e9f058bc4fbfe986c2040acb1a4a9747734834eaa0bfd", size = 11920111, upload-time = "2025-08-28T13:58:33.677Z" }, + { url = "https://files.pythonhosted.org/packages/3e/c0/f66339d7893798ad3e17fa5a1e587d6fd9806f7c1c062b63f8b09dda6702/ruff-0.12.11-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:411954eca8464595077a93e580e2918d0a01a19317af0a72132283e28ae21bee", size = 12160060, upload-time = "2025-08-28T13:58:35.74Z" }, + { url = "https://files.pythonhosted.org/packages/03/69/9870368326db26f20c946205fb2d0008988aea552dbaec35fbacbb46efaa/ruff-0.12.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a2c0a2e1a450f387bf2c6237c727dd22191ae8c00e448e0672d624b2bbd7fb0", size = 11799848, upload-time = "2025-08-28T13:58:38.051Z" }, + { url = "https://files.pythonhosted.org/packages/25/8c/dd2c7f990e9b3a8a55eee09d4e675027d31727ce33cdb29eab32d025bdc9/ruff-0.12.11-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ca4c3a7f937725fd2413c0e884b5248a19369ab9bdd850b5781348ba283f644", size = 13536288, upload-time = "2025-08-28T13:58:40.046Z" }, + { url = "https://files.pythonhosted.org/packages/7a/30/d5496fa09aba59b5e01ea76775a4c8897b13055884f56f1c35a4194c2297/ruff-0.12.11-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4d1df0098124006f6a66ecf3581a7f7e754c4df7644b2e6704cd7ca80ff95211", size = 14490633, upload-time = "2025-08-28T13:58:42.285Z" }, + { url = "https://files.pythonhosted.org/packages/9b/2f/81f998180ad53445d403c386549d6946d0748e536d58fce5b5e173511183/ruff-0.12.11-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a8dd5f230efc99a24ace3b77e3555d3fbc0343aeed3fc84c8d89e75ab2ff793", size = 13888430, upload-time = "2025-08-28T13:58:44.641Z" }, + { url = "https://files.pythonhosted.org/packages/87/71/23a0d1d5892a377478c61dbbcffe82a3476b050f38b5162171942a029ef3/ruff-0.12.11-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4dc75533039d0ed04cd33fb8ca9ac9620b99672fe7ff1533b6402206901c34ee", size = 12913133, upload-time = "2025-08-28T13:58:47.039Z" }, + { url = "https://files.pythonhosted.org/packages/80/22/3c6cef96627f89b344c933781ed38329bfb87737aa438f15da95907cbfd5/ruff-0.12.11-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4fc58f9266d62c6eccc75261a665f26b4ef64840887fc6cbc552ce5b29f96cc8", size = 13169082, upload-time = "2025-08-28T13:58:49.157Z" }, + { url = "https://files.pythonhosted.org/packages/05/b5/68b3ff96160d8b49e8dd10785ff3186be18fd650d356036a3770386e6c7f/ruff-0.12.11-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:5a0113bd6eafd545146440225fe60b4e9489f59eb5f5f107acd715ba5f0b3d2f", size = 13139490, upload-time = "2025-08-28T13:58:51.593Z" }, + { url = "https://files.pythonhosted.org/packages/59/b9/050a3278ecd558f74f7ee016fbdf10591d50119df8d5f5da45a22c6afafc/ruff-0.12.11-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:0d737b4059d66295c3ea5720e6efc152623bb83fde5444209b69cd33a53e2000", size = 11958928, upload-time = "2025-08-28T13:58:53.943Z" }, + { url = "https://files.pythonhosted.org/packages/f9/bc/93be37347db854806904a43b0493af8d6873472dfb4b4b8cbb27786eb651/ruff-0.12.11-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:916fc5defee32dbc1fc1650b576a8fed68f5e8256e2180d4d9855aea43d6aab2", size = 11764513, upload-time = "2025-08-28T13:58:55.976Z" }, + { url = "https://files.pythonhosted.org/packages/7a/a1/1471751e2015a81fd8e166cd311456c11df74c7e8769d4aabfbc7584c7ac/ruff-0.12.11-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c984f07d7adb42d3ded5be894fb4007f30f82c87559438b4879fe7aa08c62b39", size = 12745154, upload-time = "2025-08-28T13:58:58.16Z" }, + { url = "https://files.pythonhosted.org/packages/68/ab/2542b14890d0f4872dd81b7b2a6aed3ac1786fae1ce9b17e11e6df9e31e3/ruff-0.12.11-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e07fbb89f2e9249f219d88331c833860489b49cdf4b032b8e4432e9b13e8a4b9", size = 13227653, upload-time = "2025-08-28T13:59:00.276Z" }, + { url = "https://files.pythonhosted.org/packages/22/16/2fbfc61047dbfd009c58a28369a693a1484ad15441723be1cd7fe69bb679/ruff-0.12.11-py3-none-win32.whl", hash = "sha256:c792e8f597c9c756e9bcd4d87cf407a00b60af77078c96f7b6366ea2ce9ba9d3", size = 11944270, upload-time = "2025-08-28T13:59:02.347Z" }, + { url = "https://files.pythonhosted.org/packages/08/a5/34276984705bfe069cd383101c45077ee029c3fe3b28225bf67aa35f0647/ruff-0.12.11-py3-none-win_amd64.whl", hash = "sha256:a3283325960307915b6deb3576b96919ee89432ebd9c48771ca12ee8afe4a0fd", size = 13046600, upload-time = "2025-08-28T13:59:04.751Z" }, + { url = "https://files.pythonhosted.org/packages/84/a8/001d4a7c2b37623a3fd7463208267fb906df40ff31db496157549cfd6e72/ruff-0.12.11-py3-none-win_arm64.whl", hash = "sha256:bae4d6e6a2676f8fb0f98b74594a048bae1b944aab17e9f5d504062303c6dbea", size = 12135290, upload-time = "2025-08-28T13:59:06.933Z" }, ] [[package]] @@ -4640,15 +4662,15 @@ wheels = [ [[package]] name = "sentry-sdk" -version = "2.35.1" +version = "2.35.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/72/75/6223b9ffa0bf5a79ece08055469be73c18034e46ed082742a0899cc58351/sentry_sdk-2.35.1.tar.gz", hash = "sha256:241b41e059632fe1f7c54ae6e1b93af9456aebdfc297be9cf7ecfd6da5167e8e", size = 343145, upload-time = "2025-08-26T08:23:32.429Z" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/79/0ecb942f3f1ad26c40c27f81ff82392d85c01d26a45e3c72c2b37807e680/sentry_sdk-2.35.2.tar.gz", hash = "sha256:e9e8f3c795044beb59f2c8f4c6b9b0f9779e5e604099882df05eec525e782cc6", size = 343377, upload-time = "2025-09-01T11:00:58.633Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/62/1f/5feb6c42cc30126e9574eabc28139f8c626b483a47c537f648d133628df0/sentry_sdk-2.35.1-py2.py3-none-any.whl", hash = "sha256:13b6d6cfdae65d61fe1396a061cf9113b20f0ec1bcb257f3826b88f01bb55720", size = 363887, upload-time = "2025-08-26T08:23:30.335Z" }, + { url = "https://files.pythonhosted.org/packages/c0/91/a43308dc82a0e32d80cd0dfdcfca401ecbd0f431ab45f24e48bb97b7800d/sentry_sdk-2.35.2-py2.py3-none-any.whl", hash = "sha256:38c98e3cbb620dd3dd80a8d6e39c753d453dd41f8a9df581b0584c19a52bc926", size = 363975, upload-time = "2025-09-01T11:00:56.574Z" }, ] [[package]] From 355499a8deec8f54fa1668c88a88853e71c4d9a0 Mon Sep 17 00:00:00 2001 From: Trey Moen <50057480+greatgitsby@users.noreply.github.com> Date: Wed, 3 Sep 2025 11:31:48 -0700 Subject: [PATCH 039/159] feat(esim): hotswap (#36096) feat(esim): device hw reboot modem --- system/hardware/tici/hardware.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/system/hardware/tici/hardware.py b/system/hardware/tici/hardware.py index 6a9b98af82..13a30ae011 100644 --- a/system/hardware/tici/hardware.py +++ b/system/hardware/tici/hardware.py @@ -498,6 +498,14 @@ class Tici(HardwareBase): os.system(f"sudo cp {tf.name} {dest}") os.system(f"sudo nmcli con load {dest}") + def reboot_modem(self): + modem = self.get_modem() + for state in (0, 1): + try: + modem.Command(f'AT+CFUN={state}', math.ceil(TIMEOUT), dbus_interface=MM_MODEM, timeout=TIMEOUT) + except Exception: + pass + def get_networks(self): r = {} From 6a4f685d0491d089151cc93e3267cf6c258b9f65 Mon Sep 17 00:00:00 2001 From: Trey Moen <50057480+greatgitsby@users.noreply.github.com> Date: Wed, 3 Sep 2025 11:34:03 -0700 Subject: [PATCH 040/159] feat(esim): bootstrap (#36094) * bootstrap * more * fix * simple * moar * clarify --------- Co-authored-by: Comma Device --- system/hardware/base.py | 7 +++++++ system/hardware/esim.py | 27 ++++++++++++++++++++++++++- system/hardware/tici/esim.py | 29 +++++++++++++++++++++++++++++ system/hardware/tici/hardware.py | 2 +- 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/system/hardware/base.py b/system/hardware/base.py index b457ea4e17..ce97bf294d 100644 --- a/system/hardware/base.py +++ b/system/hardware/base.py @@ -65,6 +65,10 @@ class ThermalConfig: return ret class LPABase(ABC): + @abstractmethod + def bootstrap(self) -> None: + pass + @abstractmethod def list_profiles(self) -> list[Profile]: pass @@ -89,6 +93,9 @@ class LPABase(ABC): def switch_profile(self, iccid: str) -> None: pass + def is_comma_profile(self, iccid: str) -> bool: + return any(iccid.startswith(prefix) for prefix in ('8985235',)) + class HardwareBase(ABC): @staticmethod def get_cmdline() -> dict[str, str]: diff --git a/system/hardware/esim.py b/system/hardware/esim.py index 58ead6593f..909ad41e03 100755 --- a/system/hardware/esim.py +++ b/system/hardware/esim.py @@ -3,10 +3,32 @@ import argparse import time from openpilot.system.hardware import HARDWARE +from openpilot.system.hardware.base import LPABase + + +def bootstrap(lpa: LPABase) -> None: + print('┌──────────────────────────────────────────────────────────────────────────────┐') + print('│ WARNING, PLEASE READ BEFORE PROCEEDING │') + print('│ │') + print('│ this is an irreversible operation that will remove the comma-provisioned │') + print('│ profile. │') + print('│ │') + print('│ after this operation, you must purchase a new eSIM from comma in order to │') + print('│ use the comma prime subscription again. │') + print('└──────────────────────────────────────────────────────────────────────────────┘') + print() + for severity in ('sure', '100% sure'): + print(f'are you {severity} you want to proceed? (y/N) ', end='') + confirm = input() + if confirm != 'y': + print('aborting') + exit(0) + lpa.bootstrap() if __name__ == '__main__': parser = argparse.ArgumentParser(prog='esim.py', description='manage eSIM profiles on your comma device', epilog='comma.ai') + parser.add_argument('--bootstrap', action='store_true', help='bootstrap the eUICC (required before downloading profiles)') parser.add_argument('--backend', choices=['qmi', 'at'], default='qmi', help='use the specified backend, defaults to qmi') parser.add_argument('--switch', metavar='iccid', help='switch to profile') parser.add_argument('--delete', metavar='iccid', help='delete profile (warning: this cannot be undone)') @@ -16,7 +38,10 @@ if __name__ == '__main__': mutated = False lpa = HARDWARE.get_sim_lpa() - if args.switch: + if args.bootstrap: + bootstrap(lpa) + mutated = True + elif args.switch: lpa.switch_profile(args.switch) mutated = True elif args.delete: diff --git a/system/hardware/tici/esim.py b/system/hardware/tici/esim.py index b489286f50..391ba45531 100644 --- a/system/hardware/tici/esim.py +++ b/system/hardware/tici/esim.py @@ -40,6 +40,7 @@ class TiciLPA(LPABase): self._process_notifications() def download_profile(self, qr: str, nickname: str | None = None) -> None: + self._check_bootstrapped() msgs = self._invoke('profile', 'download', '-a', qr) self._validate_successful(msgs) new_profile = next((m for m in msgs if m['payload']['message'] == 'es8p_meatadata_parse'), None) @@ -54,6 +55,7 @@ class TiciLPA(LPABase): self._validate_successful(self._invoke('profile', 'nickname', iccid, nickname)) def switch_profile(self, iccid: str) -> None: + self._check_bootstrapped() self._validate_profile_exists(iccid) latest = self.get_active_profile() if latest and latest.iccid == iccid: @@ -61,6 +63,33 @@ class TiciLPA(LPABase): self._validate_successful(self._invoke('profile', 'enable', iccid)) self._process_notifications() + def bootstrap(self) -> None: + """ + find all comma-provisioned profiles and delete them. they conflict with user-provisioned profiles + and must be deleted. + + **note**: this is a **very** destructive operation. you **must** purchase a new comma SIM in order + to use comma prime again. + """ + if self._is_bootstrapped(): + return + + for p in self.list_profiles(): + if self.is_comma_profile(p.iccid): + self._disable_profile(p.iccid) + self.delete_profile(p.iccid) + + def _disable_profile(self, iccid: str) -> None: + self._validate_successful(self._invoke('profile', 'disable', iccid)) + self._process_notifications() + + def _check_bootstrapped(self) -> None: + assert self._is_bootstrapped(), 'eUICC is not bootstrapped, please bootstrap before performing this operation' + + def _is_bootstrapped(self) -> bool: + """ check if any comma provisioned profiles are on the eUICC """ + return not any(self.is_comma_profile(iccid) for iccid in (p.iccid for p in self.list_profiles())) + def _invoke(self, *cmd: str): proc = subprocess.Popen(['sudo', '-E', 'lpac'] + list(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=self.env) try: diff --git a/system/hardware/tici/hardware.py b/system/hardware/tici/hardware.py index 13a30ae011..0f50acdc38 100644 --- a/system/hardware/tici/hardware.py +++ b/system/hardware/tici/hardware.py @@ -487,7 +487,7 @@ class Tici(HardwareBase): # eSIM prime dest = "/etc/NetworkManager/system-connections/esim.nmconnection" - if sim_id.startswith('8985235') and not os.path.exists(dest): + if self.get_sim_lpa().is_comma_profile(sim_id) and not os.path.exists(dest): with open(Path(__file__).parent/'esim.nmconnection') as f, tempfile.NamedTemporaryFile(mode='w') as tf: dat = f.read() dat = dat.replace("sim-id=", f"sim-id={sim_id}") From a5044302a290cbb31a2e69a3a0e5bb769193d5b8 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 3 Sep 2025 16:06:41 -0700 Subject: [PATCH 041/159] auto source: auto source --- tools/auto_source.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/auto_source.py b/tools/auto_source.py index 401929a9ad..bef6a43e53 100755 --- a/tools/auto_source.py +++ b/tools/auto_source.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 import sys -from openpilot.tools.lib.logreader import LogReader +from openpilot.tools.lib.logreader import LogReader, ReadMode def main(): @@ -9,7 +9,7 @@ def main(): sys.exit(1) log_path = sys.argv[1] - lr = LogReader(log_path, sort_by_time=True) + lr = LogReader(log_path, default_mode=ReadMode.AUTO, sort_by_time=True) print("\n".join(lr.logreader_identifiers)) From ef870d5533917bf7db080029fb18e20ac02d0cc9 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Thu, 4 Sep 2025 18:11:44 -0700 Subject: [PATCH 042/159] bump opendbc (#36103) * bump * update refs --- opendbc_repo | 2 +- selfdrive/test/process_replay/ref_commit | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/opendbc_repo b/opendbc_repo index ac6122e272..f85a5575ba 160000 --- a/opendbc_repo +++ b/opendbc_repo @@ -1 +1 @@ -Subproject commit ac6122e272e0dc040d5abf3bde6fca4e034a7ef7 +Subproject commit f85a5575ba6b7e14329fdfa6a3f5d3427f00cab0 diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index e1133061f5..a833fadb94 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -4c677a3ebcbd3d4faa3de98e3fb9c0bb83b47926 \ No newline at end of file +afcab1abb62b9d5678342956cced4712f44e909e \ No newline at end of file From 2b7707ecf6f5a1759a88722460834a42a0e7bb17 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Thu, 4 Sep 2025 18:20:43 -0700 Subject: [PATCH 043/159] Deduplicate car interface test (#36101) deduplicate test car interfaces --- opendbc_repo | 2 +- selfdrive/car/tests/test_car_interfaces.py | 45 ++-------------------- 2 files changed, 4 insertions(+), 43 deletions(-) diff --git a/opendbc_repo b/opendbc_repo index f85a5575ba..7afc25d8d4 160000 --- a/opendbc_repo +++ b/opendbc_repo @@ -1 +1 @@ -Subproject commit f85a5575ba6b7e14329fdfa6a3f5d3427f00cab0 +Subproject commit 7afc25d8d4096bb31e25c0b7ae0b961ea05f5394 diff --git a/selfdrive/car/tests/test_car_interfaces.py b/selfdrive/car/tests/test_car_interfaces.py index 5c4729ee9a..c40443d7e7 100644 --- a/selfdrive/car/tests/test_car_interfaces.py +++ b/selfdrive/car/tests/test_car_interfaces.py @@ -1,15 +1,12 @@ import os -import math import hypothesis.strategies as st from hypothesis import Phase, given, settings from parameterized import parameterized from cereal import car from opendbc.car import DT_CTRL -from opendbc.car.car_helpers import interfaces from opendbc.car.structs import CarParams -from opendbc.car.tests.test_car_interfaces import get_fuzzy_car_interface_args -from opendbc.car.fw_versions import FW_VERSIONS, FW_QUERY_CONFIGS +from opendbc.car.tests.test_car_interfaces import get_fuzzy_car_interface from opendbc.car.mock.values import CAR as MOCK from opendbc.car.values import PLATFORMS from openpilot.selfdrive.controls.lib.latcontrol_angle import LatControlAngle @@ -18,11 +15,6 @@ from openpilot.selfdrive.controls.lib.latcontrol_torque import LatControlTorque from openpilot.selfdrive.controls.lib.longcontrol import LongControl from openpilot.selfdrive.test.fuzzy_generation import FuzzyGenerator -ALL_ECUS = {ecu for ecus in FW_VERSIONS.values() for ecu in ecus.keys()} -ALL_ECUS |= {ecu for config in FW_QUERY_CONFIGS.values() for ecu in config.extra_ecus} - -ALL_REQUESTS = {tuple(r.request) for config in FW_QUERY_CONFIGS.values() for r in config.requests} - MAX_EXAMPLES = int(os.environ.get('MAX_EXAMPLES', '60')) @@ -34,39 +26,8 @@ class TestCarInterfaces: phases=(Phase.reuse, Phase.generate, Phase.shrink)) @given(data=st.data()) def test_car_interfaces(self, car_name, data): - CarInterface = interfaces[car_name] - - args = get_fuzzy_car_interface_args(data.draw) - - car_params = CarInterface.get_params(car_name, args['fingerprints'], args['car_fw'], - alpha_long=args['alpha_long'], is_release=False, docs=False) - car_params = car_params.as_reader() - car_interface = CarInterface(car_params) - assert car_params - assert car_interface - - assert car_params.mass > 1 - assert car_params.wheelbase > 0 - # centerToFront is center of gravity to front wheels, assert a reasonable range - assert car_params.wheelbase * 0.3 < car_params.centerToFront < car_params.wheelbase * 0.7 - assert car_params.maxLateralAccel > 0 - - # 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) - - # Lateral sanity checks - if car_params.steerControlType != CarParams.SteerControlType.angle: - tune = car_params.lateralTuning - if tune.which() == 'pid': - if car_name != MOCK.MOCK: - assert not math.isnan(tune.pid.kf) and tune.pid.kf > 0 - assert len(tune.pid.kpV) > 0 and len(tune.pid.kpV) == len(tune.pid.kpBP) - assert len(tune.pid.kiV) > 0 and len(tune.pid.kiV) == len(tune.pid.kiBP) - - elif tune.which() == 'torque': - assert not math.isnan(tune.torque.kf) and tune.torque.kf > 0 - assert not math.isnan(tune.torque.friction) and tune.torque.friction > 0 + car_interface = get_fuzzy_car_interface(car_name, data.draw) + car_params = car_interface.CP.as_reader() cc_msg = FuzzyGenerator.get_random_msg(data.draw, car.CarControl, real_floats=True) # Run car interface From f0f04d4b5b752be1e0b12bac33dbca830bcf6815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harald=20Sch=C3=A4fer?= Date: Thu, 4 Sep 2025 18:51:29 -0700 Subject: [PATCH 044/159] Firehose model (#36087) 816ce390-c41a-42fa-a5df-f393cbe2dcc4/400 --- selfdrive/modeld/models/driving_policy.onnx | 2 +- selfdrive/modeld/models/driving_vision.onnx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/selfdrive/modeld/models/driving_policy.onnx b/selfdrive/modeld/models/driving_policy.onnx index eb6bd7b8a4..7b87846748 100644 --- a/selfdrive/modeld/models/driving_policy.onnx +++ b/selfdrive/modeld/models/driving_policy.onnx @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:72e98a95541f200bd2faeae8d718997483696fd4801fc7d718c167b05854707d +oid sha256:ebb38a934d6472c061cc6010f46d9720ca132d631a47e585a893bdd41ade2419 size 12343535 diff --git a/selfdrive/modeld/models/driving_vision.onnx b/selfdrive/modeld/models/driving_vision.onnx index ce0dc927e7..4b4fa05df8 100644 --- a/selfdrive/modeld/models/driving_vision.onnx +++ b/selfdrive/modeld/models/driving_vision.onnx @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e66bb8d53eced3786ed71a59b55ffc6810944cb217f0518621cc76303260a1ef +oid sha256:befac016a247b7ad5dc5b55d339d127774ed7bd2b848f1583f72aa4caee37781 size 46271991 From 1f1efec4c9b80a0be60498b38651954b127357f3 Mon Sep 17 00:00:00 2001 From: pencilpusher <83676301+jakethesnake420@users.noreply.github.com> Date: Fri, 5 Sep 2025 18:05:06 -0500 Subject: [PATCH 045/159] replay: C3/C3X hardware decoder (#35821) * bump msgq * add third_party/linux/include/media/msm_vidc.h * add sde_rotator hw interface * add msm_vidc hw decoder interface * update SConscript to build qcom decoder and rotator * use qcom decoder in replay framereader * decode directly to NV12 with the correct stride without using the hw rotator * bump msgq back to master * don't compile rotator * cleanup * works now but much to simplify * rm signals * rm header --------- Co-authored-by: Test User Co-authored-by: Adeeb Shihadeh --- tools/replay/SConscript | 2 +- tools/replay/framereader.cc | 65 ++++++- tools/replay/framereader.h | 27 ++- tools/replay/qcom_decoder.cc | 346 +++++++++++++++++++++++++++++++++++ tools/replay/qcom_decoder.h | 88 +++++++++ 5 files changed, 515 insertions(+), 13 deletions(-) create mode 100644 tools/replay/qcom_decoder.cc create mode 100644 tools/replay/qcom_decoder.h diff --git a/tools/replay/SConscript b/tools/replay/SConscript index 18849407cf..99c8263a8c 100644 --- a/tools/replay/SConscript +++ b/tools/replay/SConscript @@ -12,7 +12,7 @@ else: base_libs.append('OpenCL') replay_lib_src = ["replay.cc", "consoleui.cc", "camera.cc", "filereader.cc", "logreader.cc", "framereader.cc", - "route.cc", "util.cc", "seg_mgr.cc", "timeline.cc", "api.cc"] + "route.cc", "util.cc", "seg_mgr.cc", "timeline.cc", "api.cc", "qcom_decoder.cc"] replay_lib = replay_env.Library("replay", replay_lib_src, LIBS=base_libs, FRAMEWORKS=base_frameworks) Export('replay_lib') replay_libs = [replay_lib, 'avutil', 'avcodec', 'avformat', 'bz2', 'zstd', 'curl', 'yuv', 'ncurses'] + base_libs diff --git a/tools/replay/framereader.cc b/tools/replay/framereader.cc index ed88626be3..f2b1faf2c4 100644 --- a/tools/replay/framereader.cc +++ b/tools/replay/framereader.cc @@ -8,6 +8,7 @@ #include "common/util.h" #include "third_party/libyuv/include/libyuv.h" #include "tools/replay/util.h" +#include "system/hardware/hw.h" #ifdef __APPLE__ #define HW_DEVICE_TYPE AV_HWDEVICE_TYPE_VIDEOTOOLBOX @@ -37,7 +38,13 @@ struct DecoderManager { return it->second.get(); } - auto decoder = std::make_unique(); + std::unique_ptr decoder; + if (Hardware::TICI() && hw_decoder) { + decoder = std::make_unique(); + } else { + decoder = std::make_unique(); + } + if (!decoder->open(codecpar, hw_decoder)) { decoder.reset(nullptr); } @@ -114,19 +121,19 @@ bool FrameReader::get(int idx, VisionBuf *buf) { // class VideoDecoder -VideoDecoder::VideoDecoder() { +FFmpegVideoDecoder::FFmpegVideoDecoder() { av_frame_ = av_frame_alloc(); hw_frame_ = av_frame_alloc(); } -VideoDecoder::~VideoDecoder() { +FFmpegVideoDecoder::~FFmpegVideoDecoder() { if (hw_device_ctx) av_buffer_unref(&hw_device_ctx); if (decoder_ctx) avcodec_free_context(&decoder_ctx); av_frame_free(&av_frame_); av_frame_free(&hw_frame_); } -bool VideoDecoder::open(AVCodecParameters *codecpar, bool hw_decoder) { +bool FFmpegVideoDecoder::open(AVCodecParameters *codecpar, bool hw_decoder) { const AVCodec *decoder = avcodec_find_decoder(codecpar->codec_id); if (!decoder) return false; @@ -149,7 +156,7 @@ bool VideoDecoder::open(AVCodecParameters *codecpar, bool hw_decoder) { return true; } -bool VideoDecoder::initHardwareDecoder(AVHWDeviceType hw_device_type) { +bool FFmpegVideoDecoder::initHardwareDecoder(AVHWDeviceType hw_device_type) { const AVCodecHWConfig *config = nullptr; for (int i = 0; (config = avcodec_get_hw_config(decoder_ctx->codec, i)) != nullptr; i++) { if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX && config->device_type == hw_device_type) { @@ -175,7 +182,7 @@ bool VideoDecoder::initHardwareDecoder(AVHWDeviceType hw_device_type) { return true; } -bool VideoDecoder::decode(FrameReader *reader, int idx, VisionBuf *buf) { +bool FFmpegVideoDecoder::decode(FrameReader *reader, int idx, VisionBuf *buf) { int current_idx = idx; if (idx != reader->prev_idx + 1) { // seeking to the nearest key frame @@ -219,7 +226,7 @@ bool VideoDecoder::decode(FrameReader *reader, int idx, VisionBuf *buf) { return false; } -AVFrame *VideoDecoder::decodeFrame(AVPacket *pkt) { +AVFrame *FFmpegVideoDecoder::decodeFrame(AVPacket *pkt) { int ret = avcodec_send_packet(decoder_ctx, pkt); if (ret < 0) { rError("Error sending a packet for decoding: %d", ret); @@ -239,7 +246,7 @@ AVFrame *VideoDecoder::decodeFrame(AVPacket *pkt) { return (av_frame_->format == hw_pix_fmt) ? hw_frame_ : av_frame_; } -bool VideoDecoder::copyBuffer(AVFrame *f, VisionBuf *buf) { +bool FFmpegVideoDecoder::copyBuffer(AVFrame *f, VisionBuf *buf) { if (hw_pix_fmt == HW_PIX_FMT) { for (int i = 0; i < height/2; i++) { memcpy(buf->y + (i*2 + 0)*buf->stride, f->data[0] + (i*2 + 0)*f->linesize[0], width); @@ -256,3 +263,45 @@ bool VideoDecoder::copyBuffer(AVFrame *f, VisionBuf *buf) { } return true; } + +bool QcomVideoDecoder::open(AVCodecParameters *codecpar, bool hw_decoder) { + if (codecpar->codec_id != AV_CODEC_ID_HEVC) { + rError("Hardware decoder only supports HEVC codec"); + return false; + } + width = codecpar->width; + height = codecpar->height; + msm_vidc.init(VIDEO_DEVICE, width, height, V4L2_PIX_FMT_HEVC); + return true; +} + +bool QcomVideoDecoder::decode(FrameReader *reader, int idx, VisionBuf *buf) { + int from_idx = idx; + if (idx != reader->prev_idx + 1) { + // seeking to the nearest key frame + for (int i = idx; i >= 0; --i) { + if (reader->packets_info[i].flags & AV_PKT_FLAG_KEY) { + from_idx = i; + break; + } + } + + auto pos = reader->packets_info[from_idx].pos; + int ret = avformat_seek_file(reader->input_ctx, 0, pos, pos, pos, AVSEEK_FLAG_BYTE); + if (ret < 0) { + rError("Failed to seek to byte position %lld: %d", pos, AVERROR(ret)); + return false; + } + } + reader->prev_idx = idx; + bool result = false; + AVPacket pkt; + msm_vidc.avctx = reader->input_ctx; + for (int i = from_idx; i <= idx; ++i) { + if (av_read_frame(reader->input_ctx, &pkt) == 0) { + result = msm_vidc.decodeFrame(&pkt, buf) && (i == idx); + av_packet_unref(&pkt); + } + } + return result; +} diff --git a/tools/replay/framereader.h b/tools/replay/framereader.h index a15847e311..1fb3cdfeb1 100644 --- a/tools/replay/framereader.h +++ b/tools/replay/framereader.h @@ -6,6 +6,7 @@ #include "msgq/visionipc/visionbuf.h" #include "tools/replay/filereader.h" #include "tools/replay/util.h" +#include "tools/replay/qcom_decoder.h" extern "C" { #include @@ -40,11 +41,18 @@ public: class VideoDecoder { public: - VideoDecoder(); - ~VideoDecoder(); - bool open(AVCodecParameters *codecpar, bool hw_decoder); - bool decode(FrameReader *reader, int idx, VisionBuf *buf); + virtual ~VideoDecoder() = default; + virtual bool open(AVCodecParameters *codecpar, bool hw_decoder) = 0; + virtual bool decode(FrameReader *reader, int idx, VisionBuf *buf) = 0; int width = 0, height = 0; +}; + +class FFmpegVideoDecoder : public VideoDecoder { +public: + FFmpegVideoDecoder(); + ~FFmpegVideoDecoder() override; + bool open(AVCodecParameters *codecpar, bool hw_decoder) override; + bool decode(FrameReader *reader, int idx, VisionBuf *buf) override; private: bool initHardwareDecoder(AVHWDeviceType hw_device_type); @@ -56,3 +64,14 @@ private: AVPixelFormat hw_pix_fmt = AV_PIX_FMT_NONE; AVBufferRef *hw_device_ctx = nullptr; }; + +class QcomVideoDecoder : public VideoDecoder { +public: + QcomVideoDecoder() {}; + ~QcomVideoDecoder() override {}; + bool open(AVCodecParameters *codecpar, bool hw_decoder) override; + bool decode(FrameReader *reader, int idx, VisionBuf *buf) override; + +private: + MsmVidc msm_vidc = MsmVidc(); +}; diff --git a/tools/replay/qcom_decoder.cc b/tools/replay/qcom_decoder.cc new file mode 100644 index 0000000000..eb5409daa3 --- /dev/null +++ b/tools/replay/qcom_decoder.cc @@ -0,0 +1,346 @@ +#include "qcom_decoder.h" + +#include +#include "third_party/linux/include/v4l2-controls.h" +#include + + +#include "common/swaglog.h" +#include "common/util.h" + +// echo "0xFFFF" > /sys/kernel/debug/msm_vidc/debug_level + +static void copyBuffer(VisionBuf *src_buf, VisionBuf *dst_buf) { + // Copy Y plane + memcpy(dst_buf->y, src_buf->y, src_buf->height * src_buf->stride); + // Copy UV plane + memcpy(dst_buf->uv, src_buf->uv, src_buf->height / 2 * src_buf->stride); +} + +static void request_buffers(int fd, v4l2_buf_type buf_type, unsigned int count) { + struct v4l2_requestbuffers reqbuf = { + .count = count, + .type = buf_type, + .memory = V4L2_MEMORY_USERPTR + }; + util::safe_ioctl(fd, VIDIOC_REQBUFS, &reqbuf, "VIDIOC_REQBUFS failed"); +} + +MsmVidc::~MsmVidc() { + if (fd > 0) { + close(fd); + } +} + +bool MsmVidc::init(const char* dev, size_t width, size_t height, uint64_t codec) { + LOG("Initializing msm_vidc device %s", dev); + this->w = width; + this->h = height; + this->fd = open(dev, O_RDWR, 0); + if (fd < 0) { + LOGE("failed to open video device %s", dev); + return false; + } + subscribeEvents(); + v4l2_buf_type out_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + setPlaneFormat(out_type, V4L2_PIX_FMT_HEVC); // Also allocates the output buffer + setFPS(FPS); + request_buffers(fd, out_type, OUTPUT_BUFFER_COUNT); + util::safe_ioctl(fd, VIDIOC_STREAMON, &out_type, "VIDIOC_STREAMON OUTPUT failed"); + restartCapture(); + setupPolling(); + + this->initialized = true; + return true; +} + +VisionBuf* MsmVidc::decodeFrame(AVPacket *pkt, VisionBuf *buf) { + assert(initialized && (pkt != nullptr) && (buf != nullptr)); + + this->frame_ready = false; + this->current_output_buf = buf; + bool sent_packet = false; + + while (!this->frame_ready) { + if (!sent_packet) { + int buf_index = getBufferUnlocked(); + if (buf_index >= 0) { + assert(buf_index < out_buf_cnt); + sendPacket(buf_index, pkt); + sent_packet = true; + } + } + + if (poll(pfd, nfds, -1) < 0) { + LOGE("poll() error: %d", errno); + return nullptr; + } + + if (VisionBuf* result = processEvents()) { + return result; + } + } + + return buf; +} + +VisionBuf* MsmVidc::processEvents() { + for (int idx = 0; idx < nfds; idx++) { + short revents = pfd[idx].revents; + if (!revents) continue; + + if (idx == ev[EV_VIDEO]) { + if (revents & (POLLIN | POLLRDNORM)) { + VisionBuf *result = handleCapture(); + if (result == this->current_output_buf) { + this->frame_ready = true; + } + } + if (revents & (POLLOUT | POLLWRNORM)) { + handleOutput(); + } + if (revents & POLLPRI) { + handleEvent(); + } + } else { + LOGE("Unexpected event on fd %d", pfd[idx].fd); + } + } + return nullptr; +} + +VisionBuf* MsmVidc::handleCapture() { + struct v4l2_buffer buf = {0}; + struct v4l2_plane planes[1] = {0}; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + buf.memory = V4L2_MEMORY_USERPTR; + buf.m.planes = planes; + buf.length = 1; + util::safe_ioctl(this->fd, VIDIOC_DQBUF, &buf, "VIDIOC_DQBUF CAPTURE failed"); + + if (this->reconfigure_pending || buf.m.planes[0].bytesused == 0) { + return nullptr; + } + + copyBuffer(&cap_bufs[buf.index], this->current_output_buf); + queueCaptureBuffer(buf.index); + return this->current_output_buf; +} + +bool MsmVidc::subscribeEvents() { + for (uint32_t event : subscriptions) { + struct v4l2_event_subscription sub = { .type = event}; + util::safe_ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub, "VIDIOC_SUBSCRIBE_EVENT failed"); + } + return true; +} + +bool MsmVidc::setPlaneFormat(enum v4l2_buf_type type, uint32_t fourcc) { + struct v4l2_format fmt = {.type = type}; + struct v4l2_pix_format_mplane *pix = &fmt.fmt.pix_mp; + *pix = { + .width = (__u32)this->w, + .height = (__u32)this->h, + .pixelformat = fourcc + }; + util::safe_ioctl(fd, VIDIOC_S_FMT, &fmt, "VIDIOC_S_FMT failed"); + if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + this->out_buf_size = pix->plane_fmt[0].sizeimage; + int ion_size = this->out_buf_size * OUTPUT_BUFFER_COUNT; // Output (input) buffers are ION buffer. + this->out_buf.allocate(ion_size); // mmap rw + for (int i = 0; i < OUTPUT_BUFFER_COUNT; i++) { + this->out_buf_off[i] = i * this->out_buf_size; + this->out_buf_addr[i] = (char *)this->out_buf.addr + this->out_buf_off[i]; + this->out_buf_flag[i] = false; + } + LOGD("Set output buffer size to %d, count %d, addr %p", this->out_buf_size, OUTPUT_BUFFER_COUNT, this->out_buf.addr); + } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + request_buffers(this->fd, type, CAPTURE_BUFFER_COUNT); + util::safe_ioctl(fd, VIDIOC_G_FMT, &fmt, "VIDIOC_G_FMT failed"); + const __u32 y_size = pix->plane_fmt[0].sizeimage; + const __u32 y_stride = pix->plane_fmt[0].bytesperline; + for (int i = 0; i < CAPTURE_BUFFER_COUNT; i++) { + size_t uv_offset = (size_t)y_stride * pix->height; + size_t required = uv_offset + (y_stride * pix->height / 2); // enough for Y + UV. For linear NV12, UV plane starts at y_stride * height. + size_t alloc_size = std::max(y_size, required); + this->cap_bufs[i].allocate(alloc_size); + this->cap_bufs[i].init_yuv(pix->width, pix->height, y_stride, uv_offset); + } + LOGD("Set capture buffer size to %d, count %d, addr %p, extradata size %d", + pix->plane_fmt[0].sizeimage, CAPTURE_BUFFER_COUNT, this->cap_bufs[0].addr, pix->plane_fmt[1].sizeimage); + } + return true; +} + +bool MsmVidc::setFPS(uint32_t fps) { + struct v4l2_streamparm streamparam = { + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + .parm.output.timeperframe = {1, fps} + }; + util::safe_ioctl(fd, VIDIOC_S_PARM, &streamparam, "VIDIOC_S_PARM failed"); + return true; +} + +bool MsmVidc::restartCapture() { + // stop if already initialized + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + if (this->initialized) { + LOGD("Restarting capture, flushing buffers..."); + util::safe_ioctl(this->fd, VIDIOC_STREAMOFF, &type, "VIDIOC_STREAMOFF CAPTURE failed"); + struct v4l2_requestbuffers reqbuf = {.type = type, .memory = V4L2_MEMORY_USERPTR}; + util::safe_ioctl(this->fd, VIDIOC_REQBUFS, &reqbuf, "VIDIOC_REQBUFS failed"); + for (size_t i = 0; i < CAPTURE_BUFFER_COUNT; ++i) { + this->cap_bufs[i].free(); + this->cap_buf_flag[i] = false; // mark as not queued + cap_bufs[i].~VisionBuf(); + new (&cap_bufs[i]) VisionBuf(); + } + } + // setup, start and queue capture buffers + setDBP(); + setPlaneFormat(type, V4L2_PIX_FMT_NV12); + util::safe_ioctl(this->fd, VIDIOC_STREAMON, &type, "VIDIOC_STREAMON CAPTURE failed"); + for (size_t i = 0; i < CAPTURE_BUFFER_COUNT; ++i) { + queueCaptureBuffer(i); + } + + return true; +} + +bool MsmVidc::queueCaptureBuffer(int i) { + struct v4l2_buffer buf = {0}; + struct v4l2_plane planes[1] = {0}; + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + buf.memory = V4L2_MEMORY_USERPTR; + buf.index = i; + buf.m.planes = planes; + buf.length = 1; + // decoded frame plane + planes[0].m.userptr = (unsigned long)this->cap_bufs[i].addr; // no security + planes[0].length = this->cap_bufs[i].len; + planes[0].reserved[0] = this->cap_bufs[i].fd; // ION fd + planes[0].reserved[1] = 0; + planes[0].bytesused = this->cap_bufs[i].len; + planes[0].data_offset = 0; + util::safe_ioctl(this->fd, VIDIOC_QBUF, &buf, "VIDIOC_QBUF failed"); + this->cap_buf_flag[i] = true; // mark as queued + return true; +} + +bool MsmVidc::queueOutputBuffer(int i, size_t size) { + struct v4l2_buffer buf = {0}; + struct v4l2_plane planes[1] = {0}; + + buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + buf.memory = V4L2_MEMORY_USERPTR; + buf.index = i; + buf.m.planes = planes; + buf.length = 1; + // decoded frame plane + planes[0].m.userptr = (unsigned long)this->out_buf_off[i]; // check this + planes[0].length = this->out_buf_size; + planes[0].reserved[0] = this->out_buf.fd; // ION fd + planes[0].reserved[1] = 0; + planes[0].bytesused = size; + planes[0].data_offset = 0; + assert((this->out_buf_off[i] & 0xfff) == 0); // must be 4 KiB aligned + assert(this->out_buf_size % 4096 == 0); // ditto for size + + util::safe_ioctl(this->fd, VIDIOC_QBUF, &buf, "VIDIOC_QBUF failed"); + this->out_buf_flag[i] = true; // mark as queued + return true; +} + +bool MsmVidc::setDBP() { + struct v4l2_ext_control control[2] = {0}; + struct v4l2_ext_controls controls = {0}; + control[0].id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE; + control[0].value = 1; // V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY + control[1].id = V4L2_CID_MPEG_VIDC_VIDEO_DPB_COLOR_FORMAT; + control[1].value = 0; // V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE + controls.count = 2; + controls.ctrl_class = V4L2_CTRL_CLASS_MPEG; + controls.controls = control; + util::safe_ioctl(fd, VIDIOC_S_EXT_CTRLS, &controls, "VIDIOC_S_EXT_CTRLS failed"); + return true; +} + +bool MsmVidc::setupPolling() { + // Initialize poll array + pfd[EV_VIDEO] = {fd, POLLIN | POLLOUT | POLLWRNORM | POLLRDNORM | POLLPRI, 0}; + ev[EV_VIDEO] = EV_VIDEO; + nfds = 1; + return true; +} + +bool MsmVidc::sendPacket(int buf_index, AVPacket *pkt) { + assert(buf_index >= 0 && buf_index < out_buf_cnt); + assert(pkt != nullptr && pkt->data != nullptr && pkt->size > 0); + // Prepare output buffer + memset(this->out_buf_addr[buf_index], 0, this->out_buf_size); + uint8_t * data = (uint8_t *)this->out_buf_addr[buf_index]; + memcpy(data, pkt->data, pkt->size); + queueOutputBuffer(buf_index, pkt->size); + return true; +} + +int MsmVidc::getBufferUnlocked() { + for (int i = 0; i < this->out_buf_cnt; i++) { + if (!out_buf_flag[i]) { + return i; + } + } + return -1; +} + + +bool MsmVidc::handleOutput() { + struct v4l2_buffer buf = {0}; + struct v4l2_plane planes[1]; + buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + buf.memory = V4L2_MEMORY_USERPTR; + buf.m.planes = planes; + buf.length = 1; + util::safe_ioctl(this->fd, VIDIOC_DQBUF, &buf, "VIDIOC_DQBUF OUTPUT failed"); + this->out_buf_flag[buf.index] = false; // mark as not queued + return true; +} + +bool MsmVidc::handleEvent() { + // dequeue event + struct v4l2_event event = {0}; + util::safe_ioctl(this->fd, VIDIOC_DQEVENT, &event, "VIDIOC_DQEVENT failed"); + switch (event.type) { + case V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT: { + unsigned int *ptr = (unsigned int *)event.u.data; + unsigned int height = ptr[0]; + unsigned int width = ptr[1]; + this->w = width; + this->h = height; + LOGD("Port Reconfig received insufficient, new size %ux%u, flushing capture bufs...", width, height); // This is normal + struct v4l2_decoder_cmd dec; + dec.flags = V4L2_QCOM_CMD_FLUSH_CAPTURE; + dec.cmd = V4L2_QCOM_CMD_FLUSH; + util::safe_ioctl(this->fd, VIDIOC_DECODER_CMD, &dec, "VIDIOC_DECODER_CMD FLUSH_CAPTURE failed"); + this->reconfigure_pending = true; + LOGD("Waiting for flush done event to reconfigure capture queue"); + break; + } + + case V4L2_EVENT_MSM_VIDC_FLUSH_DONE: { + unsigned int *ptr = (unsigned int *)event.u.data; + unsigned int flags = ptr[0]; + if (flags & V4L2_QCOM_CMD_FLUSH_CAPTURE) { + if (this->reconfigure_pending) { + this->restartCapture(); + this->reconfigure_pending = false; + } + } + break; + } + default: + break; + } + return true; +} \ No newline at end of file diff --git a/tools/replay/qcom_decoder.h b/tools/replay/qcom_decoder.h new file mode 100644 index 0000000000..1d7522cc70 --- /dev/null +++ b/tools/replay/qcom_decoder.h @@ -0,0 +1,88 @@ +#pragma once + +#include +#include + +#include "msgq/visionipc/visionbuf.h" + +extern "C" { + #include + #include +} + +#define V4L2_EVENT_MSM_VIDC_START (V4L2_EVENT_PRIVATE_START + 0x00001000) +#define V4L2_EVENT_MSM_VIDC_FLUSH_DONE (V4L2_EVENT_MSM_VIDC_START + 1) +#define V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT (V4L2_EVENT_MSM_VIDC_START + 3) +#define V4L2_CID_MPEG_MSM_VIDC_BASE 0x00992000 +#define V4L2_CID_MPEG_VIDC_VIDEO_DPB_COLOR_FORMAT (V4L2_CID_MPEG_MSM_VIDC_BASE + 44) +#define V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE (V4L2_CID_MPEG_MSM_VIDC_BASE + 22) +#define V4L2_QCOM_CMD_FLUSH_CAPTURE (1 << 1) +#define V4L2_QCOM_CMD_FLUSH (4) + +#define VIDEO_DEVICE "/dev/video32" +#define OUTPUT_BUFFER_COUNT 8 +#define CAPTURE_BUFFER_COUNT 8 +#define FPS 20 + + +class MsmVidc { +public: + MsmVidc() = default; + ~MsmVidc(); + + bool init(const char* dev, size_t width, size_t height, uint64_t codec); + VisionBuf* decodeFrame(AVPacket* pkt, VisionBuf* buf); + + AVFormatContext* avctx = nullptr; + int fd = 0; + +private: + bool initialized = false; + bool reconfigure_pending = false; + bool frame_ready = false; + + VisionBuf* current_output_buf = nullptr; + VisionBuf out_buf; // Single input buffer + VisionBuf cap_bufs[CAPTURE_BUFFER_COUNT]; // Capture (output) buffers + + size_t w = 1928, h = 1208; + size_t cap_height = 0, cap_width = 0; + + int cap_buf_size = 0; + int out_buf_size = 0; + + size_t cap_plane_off[CAPTURE_BUFFER_COUNT] = {0}; + size_t cap_plane_stride[CAPTURE_BUFFER_COUNT] = {0}; + bool cap_buf_flag[CAPTURE_BUFFER_COUNT] = {false}; + + size_t out_buf_off[OUTPUT_BUFFER_COUNT] = {0}; + void* out_buf_addr[OUTPUT_BUFFER_COUNT] = {0}; + bool out_buf_flag[OUTPUT_BUFFER_COUNT] = {false}; + const int out_buf_cnt = OUTPUT_BUFFER_COUNT; + + const int subscriptions[2] = { + V4L2_EVENT_MSM_VIDC_FLUSH_DONE, + V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT + }; + + enum { EV_VIDEO, EV_COUNT }; + struct pollfd pfd[EV_COUNT] = {0}; + int ev[EV_COUNT] = {-1}; + int nfds = 0; + + VisionBuf* processEvents(); + bool setupOutput(); + bool subscribeEvents(); + bool setPlaneFormat(v4l2_buf_type type, uint32_t fourcc); + bool setFPS(uint32_t fps); + bool restartCapture(); + bool queueCaptureBuffer(int i); + bool queueOutputBuffer(int i, size_t size); + bool setDBP(); + bool setupPolling(); + bool sendPacket(int buf_index, AVPacket* pkt); + int getBufferUnlocked(); + VisionBuf* handleCapture(); + bool handleOutput(); + bool handleEvent(); +}; From 1033d3d80e5e804f11e0e379849111249c28828f Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Fri, 5 Sep 2025 22:34:04 -0700 Subject: [PATCH 046/159] Desire helper: set lane change direction on entering preLaneChange state (#36074) * set immediately to avoid flash on right lane changes * one function * name * comment --- selfdrive/controls/lib/desire_helper.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/selfdrive/controls/lib/desire_helper.py b/selfdrive/controls/lib/desire_helper.py index 730aaeb8f1..ee4567f1e9 100644 --- a/selfdrive/controls/lib/desire_helper.py +++ b/selfdrive/controls/lib/desire_helper.py @@ -40,6 +40,10 @@ class DesireHelper: self.prev_one_blinker = False self.desire = log.Desire.none + @staticmethod + def get_lane_change_direction(CS): + return LaneChangeDirection.left if CS.leftBlinker else LaneChangeDirection.right + def update(self, carstate, lateral_active, lane_change_prob): v_ego = carstate.vEgo one_blinker = carstate.leftBlinker != carstate.rightBlinker @@ -53,12 +57,13 @@ class DesireHelper: if self.lane_change_state == LaneChangeState.off and one_blinker and not self.prev_one_blinker and not below_lane_change_speed: self.lane_change_state = LaneChangeState.preLaneChange self.lane_change_ll_prob = 1.0 + # Initialize lane change direction to prevent UI alert flicker + self.lane_change_direction = self.get_lane_change_direction(carstate) # LaneChangeState.preLaneChange elif self.lane_change_state == LaneChangeState.preLaneChange: - # Set lane change direction - self.lane_change_direction = LaneChangeDirection.left if \ - carstate.leftBlinker else LaneChangeDirection.right + # Update lane change direction + self.lane_change_direction = self.get_lane_change_direction(carstate) torque_applied = carstate.steeringPressed and \ ((carstate.steeringTorque > 0 and self.lane_change_direction == LaneChangeDirection.left) or From 03e9777c3ff29c9bdaca33facb9eb2bb58df25c6 Mon Sep 17 00:00:00 2001 From: DevTekVE Date: Sat, 6 Sep 2025 21:05:15 +0200 Subject: [PATCH 047/159] Improve debugging for safety (#36055) * feat: add debugging configurations for replay drive and LLDB attachment * Add readme with video demo * clean * docs: update debugging safety documentation with demo link * no need for mp4 then added on PR * Update SConstruct * bump opendbc * updating readme * updating readme * updating readme * is this better / worth it? * final cleanups * hacky. but does it work? * Yep that worked! --------- Co-authored-by: Adeeb Shihadeh --- .vscode/launch.json | 41 +++++++++++++++++++++++++++++++++++++++- docs/DEBUGGING_SAFETY.md | 30 +++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 docs/DEBUGGING_SAFETY.md diff --git a/.vscode/launch.json b/.vscode/launch.json index a6b341d9ea..f090061c42 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -23,6 +23,11 @@ "id": "args", "description": "Arguments to pass to the process", "type": "promptString" + }, + { + "id": "replayArg", + "type": "promptString", + "description": "Enter route or segment to replay." } ], "configurations": [ @@ -40,7 +45,41 @@ "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/${input:cpp_process}", - "cwd": "${workspaceFolder}", + "cwd": "${workspaceFolder}" + }, + { + "name": "Attach LLDB to Replay drive", + "type": "lldb", + "request": "attach", + "pid": "${command:pickMyProcess}", + "initCommands": [ + "script import time; time.sleep(3)" + ] + }, + { + "name": "Replay drive", + "type": "debugpy", + "request": "launch", + "program": "${workspaceFolder}/opendbc/safety/tests/safety_replay/replay_drive.py", + "args": [ + "${input:replayArg}" + ], + "console": "integratedTerminal", + "justMyCode": false, + "env": { + "PYTHONPATH": "${workspaceFolder}" + }, + "subProcess": true, + "stopOnEntry": false + } + ], + "compounds": [ + { + "name": "Replay drive + Safety LLDB", + "configurations": [ + "Replay drive", + "Attach LLDB to Replay drive" + ] } ] } \ No newline at end of file diff --git a/docs/DEBUGGING_SAFETY.md b/docs/DEBUGGING_SAFETY.md new file mode 100644 index 0000000000..cd0a46b446 --- /dev/null +++ b/docs/DEBUGGING_SAFETY.md @@ -0,0 +1,30 @@ +# Debugging Panda Safety with Replay Drive + LLDB + +## 1. Start the debugger in VS Code + +* Select **Replay drive + Safety LLDB**. +* Enter the route or segment when prompted. +[](https://github.com/user-attachments/assets/b0cc320a-083e-46a7-a9f8-ca775bbe5604) + +## 2. Attach LLDB + +* When prompted, pick the running **`replay_drive` process**. +* ⚠️ Attach quickly, or `replay_drive` will start consuming messages. + +> [!TIP] +> Add a Python breakpoint at the start of `replay_drive.py` to pause execution and give yourself time to attach LLDB. + +## 3. Set breakpoints in VS Code +Breakpoints can be set directly in `modes/xxx.h` (or any C file). +No extra LLDB commands are required — just place breakpoints in the editor. + +## 4. Resume execution +Once attached, you can step through both Python (on the replay) and C safety code as CAN logs are replayed. + +> [!NOTE] +> * Use short routes for quicker iteration. +> * Pause `replay_drive` early to avoid wasting log messages. + +## Video + +View a demo of this workflow on the PR that added it: https://github.com/commaai/openpilot/pull/36055#issue-3352911578 \ No newline at end of file From 3a91ae08a9ebc4d051a7c226e6c869c1a81c0d37 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 6 Sep 2025 18:03:16 -0400 Subject: [PATCH 048/159] update: actually detect device type as TICI (#1221) --- system/hardware/hardwared.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/hardware/hardwared.py b/system/hardware/hardwared.py index af01154144..df8ae23ab5 100755 --- a/system/hardware/hardwared.py +++ b/system/hardware/hardwared.py @@ -331,7 +331,7 @@ def hardware_thread(end_event, hw_queue) -> None: # - TIZI, or # - TICI and channel_type is "tici" build_metadata = get_build_metadata() - is_unsupported_combo = TICI and build_metadata.channel_type != "tici" + is_unsupported_combo = TICI and HARDWARE.get_device_type() == "tici" and build_metadata.channel_type != "tici" startup_conditions["not_tici"] = not is_unsupported_combo onroad_conditions["not_tici"] = not is_unsupported_combo set_offroad_alert("Offroad_TiciSupport", is_unsupported_combo, extra_text=build_metadata.channel) From ff4d1923f05ca3978148ba3c8033a3bec9914972 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 6 Sep 2025 18:46:10 -0400 Subject: [PATCH 049/159] tici: fix staging root updates (#1223) --- sunnypilot/system/hardware/c3/launch_env.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sunnypilot/system/hardware/c3/launch_env.sh b/sunnypilot/system/hardware/c3/launch_env.sh index 593aacc078..4c011c6ac0 100755 --- a/sunnypilot/system/hardware/c3/launch_env.sh +++ b/sunnypilot/system/hardware/c3/launch_env.sh @@ -9,3 +9,5 @@ export VECLIB_MAXIMUM_THREADS=1 if [ -z "$AGNOS_VERSION" ]; then export AGNOS_VERSION="12.8" fi + +export STAGING_ROOT="/data/safe_staging" From ff34b8af76e697e56648e93ec716b865679fa925 Mon Sep 17 00:00:00 2001 From: Jason Young <46612682+jyoung8607@users.noreply.github.com> Date: Sun, 7 Sep 2025 11:59:48 -0400 Subject: [PATCH 050/159] selfdrived: disable HUD VisualAlert for belowSteerSpeed events (#36109) --- selfdrive/selfdrived/events.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/selfdrived/events.py b/selfdrive/selfdrived/events.py index 9da7125dd8..d4a00115d4 100755 --- a/selfdrive/selfdrived/events.py +++ b/selfdrive/selfdrived/events.py @@ -243,7 +243,7 @@ def below_steer_speed_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.S f"Steer Unavailable Below {get_display_speed(CP.minSteerSpeed, metric)}", "", AlertStatus.userPrompt, AlertSize.small, - Priority.LOW, VisualAlert.steerRequired, AudibleAlert.prompt, 0.4) + Priority.LOW, VisualAlert.none, AudibleAlert.prompt, 0.4) def calibration_incomplete_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: From 275abc1eb5a8bf4f694280c5408bc62bd3994b9a Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Sun, 7 Sep 2025 11:13:39 -0700 Subject: [PATCH 051/159] Rewrite proclogd in Python (#36110) * Rewrite proclogd in Python * lil more * lil more * Update system/proclogd.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update system/proclogd.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update system/proclogd.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .gitignore | 1 - SConstruct | 1 - pyproject.toml | 1 - selfdrive/test/test_onroad.py | 4 +- system/manager/process_config.py | 2 +- system/proclogd.py | 227 ++++++++++++++++++++++++ system/proclogd/SConscript | 6 - system/proclogd/main.cc | 25 --- system/proclogd/proclog.cc | 239 -------------------------- system/proclogd/proclog.h | 40 ----- system/proclogd/tests/.gitignore | 1 - system/proclogd/tests/test_proclog.cc | 142 --------------- 12 files changed, 230 insertions(+), 459 deletions(-) create mode 100755 system/proclogd.py delete mode 100644 system/proclogd/SConscript delete mode 100644 system/proclogd/main.cc delete mode 100644 system/proclogd/proclog.cc delete mode 100644 system/proclogd/proclog.h delete mode 100644 system/proclogd/tests/.gitignore delete mode 100644 system/proclogd/tests/test_proclog.cc diff --git a/.gitignore b/.gitignore index 8dc8f41de5..c594fb53d3 100644 --- a/.gitignore +++ b/.gitignore @@ -50,7 +50,6 @@ cereal/services.h cereal/gen cereal/messaging/bridge selfdrive/mapd/default_speeds_by_region.json -system/proclogd/proclogd selfdrive/ui/translations/tmp selfdrive/test/longitudinal_maneuvers/out selfdrive/car/tests/cars_dump diff --git a/SConstruct b/SConstruct index 56788e5842..21657ad556 100644 --- a/SConstruct +++ b/SConstruct @@ -341,7 +341,6 @@ SConscript([ if arch != "Darwin": SConscript([ 'system/logcatd/SConscript', - 'system/proclogd/SConscript', ]) if arch == "larch64": diff --git a/pyproject.toml b/pyproject.toml index 7d6516c0fb..3e362556a3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -158,7 +158,6 @@ testpaths = [ "system/camerad", "system/hardware", "system/loggerd", - "system/proclogd", "system/tests", "system/ubloxd", "system/webrtc", diff --git a/selfdrive/test/test_onroad.py b/selfdrive/test/test_onroad.py index 3cb1af10df..26225ef400 100644 --- a/selfdrive/test/test_onroad.py +++ b/selfdrive/test/test_onroad.py @@ -32,7 +32,7 @@ CPU usage budget TEST_DURATION = 25 LOG_OFFSET = 8 -MAX_TOTAL_CPU = 287. # total for all 8 cores +MAX_TOTAL_CPU = 300. # total for all 8 cores PROCS = { # Baseline CPU usage by process "selfdrive.controls.controlsd": 16.0, @@ -56,7 +56,7 @@ PROCS = { "selfdrive.ui.soundd": 3.0, "selfdrive.ui.feedback.feedbackd": 1.0, "selfdrive.monitoring.dmonitoringd": 4.0, - "./proclogd": 2.0, + "system.proclogd": 3.0, "system.logmessaged": 1.0, "system.tombstoned": 0, "./logcatd": 1.0, diff --git a/system/manager/process_config.py b/system/manager/process_config.py index 5758512f2b..e25c0e985f 100644 --- a/system/manager/process_config.py +++ b/system/manager/process_config.py @@ -72,7 +72,7 @@ procs = [ NativeProcess("camerad", "system/camerad", ["./camerad"], driverview, enabled=not WEBCAM), PythonProcess("webcamerad", "tools.webcam.camerad", driverview, enabled=WEBCAM), NativeProcess("logcatd", "system/logcatd", ["./logcatd"], only_onroad, platform.system() != "Darwin"), - NativeProcess("proclogd", "system/proclogd", ["./proclogd"], only_onroad, platform.system() != "Darwin"), + PythonProcess("proclogd", "system.proclogd", only_onroad, enabled=platform.system() != "Darwin"), PythonProcess("micd", "system.micd", iscar), PythonProcess("timed", "system.timed", always_run, enabled=not PC), diff --git a/system/proclogd.py b/system/proclogd.py new file mode 100755 index 0000000000..3279425b7b --- /dev/null +++ b/system/proclogd.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python3 +import os +from typing import NoReturn, TypedDict + +from cereal import messaging +from openpilot.common.realtime import Ratekeeper +from openpilot.common.swaglog import cloudlog + +JIFFY = os.sysconf(os.sysconf_names['SC_CLK_TCK']) +PAGE_SIZE = os.sysconf(os.sysconf_names['SC_PAGE_SIZE']) + + +def _cpu_times() -> list[dict[str, float]]: + cpu_times: list[dict[str, float]] = [] + try: + with open('/proc/stat') as f: + lines = f.readlines()[1:] + for line in lines: + if not line.startswith('cpu') or len(line) < 4 or not line[3].isdigit(): + break + parts = line.split() + cpu_times.append({ + 'cpuNum': int(parts[0][3:]), + 'user': float(parts[1]) / JIFFY, + 'nice': float(parts[2]) / JIFFY, + 'system': float(parts[3]) / JIFFY, + 'idle': float(parts[4]) / JIFFY, + 'iowait': float(parts[5]) / JIFFY, + 'irq': float(parts[6]) / JIFFY, + 'softirq': float(parts[7]) / JIFFY, + }) + except Exception: + cloudlog.exception("failed to read /proc/stat") + return cpu_times + + +def _mem_info() -> dict[str, int]: + keys = ["MemTotal:", "MemFree:", "MemAvailable:", "Buffers:", "Cached:", "Active:", "Inactive:", "Shmem:"] + info: dict[str, int] = dict.fromkeys(keys, 0) + try: + with open('/proc/meminfo') as f: + for line in f: + parts = line.split() + if parts and parts[0] in info: + info[parts[0]] = int(parts[1]) * 1024 + except Exception: + cloudlog.exception("failed to read /proc/meminfo") + return info + + +_STAT_POS = { + 'pid': 1, + 'state': 3, + 'ppid': 4, + 'utime': 14, + 'stime': 15, + 'cutime': 16, + 'cstime': 17, + 'priority': 18, + 'nice': 19, + 'num_threads': 20, + 'starttime': 22, + 'vsize': 23, + 'rss': 24, + 'processor': 39, +} + +class ProcStat(TypedDict): + name: str + pid: int + state: str + ppid: int + utime: int + stime: int + cutime: int + cstime: int + priority: int + nice: int + num_threads: int + starttime: int + vms: int + rss: int + processor: int + + +def _parse_proc_stat(stat: str) -> ProcStat | None: + open_paren = stat.find('(') + close_paren = stat.rfind(')') + if open_paren == -1 or close_paren == -1 or open_paren > close_paren: + return None + name = stat[open_paren + 1:close_paren] + stat = stat[:open_paren] + stat[open_paren:close_paren].replace(' ', '_') + stat[close_paren:] + parts = stat.split() + if len(parts) < 52: + return None + try: + return { + 'name': name, + 'pid': int(parts[_STAT_POS['pid'] - 1]), + 'state': parts[_STAT_POS['state'] - 1][0], + 'ppid': int(parts[_STAT_POS['ppid'] - 1]), + 'utime': int(parts[_STAT_POS['utime'] - 1]), + 'stime': int(parts[_STAT_POS['stime'] - 1]), + 'cutime': int(parts[_STAT_POS['cutime'] - 1]), + 'cstime': int(parts[_STAT_POS['cstime'] - 1]), + 'priority': int(parts[_STAT_POS['priority'] - 1]), + 'nice': int(parts[_STAT_POS['nice'] - 1]), + 'num_threads': int(parts[_STAT_POS['num_threads'] - 1]), + 'starttime': int(parts[_STAT_POS['starttime'] - 1]), + 'vms': int(parts[_STAT_POS['vsize'] - 1]), + 'rss': int(parts[_STAT_POS['rss'] - 1]), + 'processor': int(parts[_STAT_POS['processor'] - 1]), + } + except Exception: + cloudlog.exception("failed to parse /proc//stat") + return None + +class ProcExtra(TypedDict): + pid: int + name: str + exe: str + cmdline: list[str] + + +_proc_cache: dict[int, ProcExtra] = {} + + +def _get_proc_extra(pid: int, name: str) -> ProcExtra: + cache: ProcExtra | None = _proc_cache.get(pid) + if cache is None or cache.get('name') != name: + exe = '' + cmdline: list[str] = [] + try: + exe = os.readlink(f'/proc/{pid}/exe') + except OSError: + pass + try: + with open(f'/proc/{pid}/cmdline', 'rb') as f: + cmdline = [c.decode('utf-8', errors='replace') for c in f.read().split(b'\0') if c] + except OSError: + pass + cache = {'pid': pid, 'name': name, 'exe': exe, 'cmdline': cmdline} + _proc_cache[pid] = cache + return cache + + +def _procs() -> list[ProcStat]: + stats: list[ProcStat] = [] + for pid_str in os.listdir('/proc'): + if not pid_str.isdigit(): + continue + try: + with open(f'/proc/{pid_str}/stat') as f: + stat = f.read() + parsed = _parse_proc_stat(stat) + if parsed is not None: + stats.append(parsed) + except OSError: + continue + return stats + + +def build_proc_log_message(msg) -> None: + pl = msg.procLog + + procs = _procs() + l = pl.init('procs', len(procs)) + for i, r in enumerate(procs): + proc = l[i] + proc.pid = r['pid'] + proc.state = ord(r['state'][0]) + proc.ppid = r['ppid'] + proc.cpuUser = r['utime'] / JIFFY + proc.cpuSystem = r['stime'] / JIFFY + proc.cpuChildrenUser = r['cutime'] / JIFFY + proc.cpuChildrenSystem = r['cstime'] / JIFFY + proc.priority = r['priority'] + proc.nice = r['nice'] + proc.numThreads = r['num_threads'] + proc.startTime = r['starttime'] / JIFFY + proc.memVms = r['vms'] + proc.memRss = r['rss'] * PAGE_SIZE + proc.processor = r['processor'] + proc.name = r['name'] + + extra = _get_proc_extra(r['pid'], r['name']) + proc.exe = extra['exe'] + cmdline = proc.init('cmdline', len(extra['cmdline'])) + for j, arg in enumerate(extra['cmdline']): + cmdline[j] = arg + + cpu_times = _cpu_times() + cpu_list = pl.init('cpuTimes', len(cpu_times)) + for i, ct in enumerate(cpu_times): + cpu = cpu_list[i] + cpu.cpuNum = ct['cpuNum'] + cpu.user = ct['user'] + cpu.nice = ct['nice'] + cpu.system = ct['system'] + cpu.idle = ct['idle'] + cpu.iowait = ct['iowait'] + cpu.irq = ct['irq'] + cpu.softirq = ct['softirq'] + + mem_info = _mem_info() + pl.mem.total = mem_info["MemTotal:"] + pl.mem.free = mem_info["MemFree:"] + pl.mem.available = mem_info["MemAvailable:"] + pl.mem.buffers = mem_info["Buffers:"] + pl.mem.cached = mem_info["Cached:"] + pl.mem.active = mem_info["Active:"] + pl.mem.inactive = mem_info["Inactive:"] + pl.mem.shared = mem_info["Shmem:"] + + +def main() -> NoReturn: + pm = messaging.PubMaster(['procLog']) + rk = Ratekeeper(0.5) + while True: + msg = messaging.new_message('procLog', valid=True) + build_proc_log_message(msg) + pm.send('procLog', msg) + rk.keep_time() + + +if __name__ == '__main__': + main() diff --git a/system/proclogd/SConscript b/system/proclogd/SConscript deleted file mode 100644 index 08814d5ccb..0000000000 --- a/system/proclogd/SConscript +++ /dev/null @@ -1,6 +0,0 @@ -Import('env', 'messaging', 'common') -libs = [messaging, 'pthread', common] -env.Program('proclogd', ['main.cc', 'proclog.cc'], LIBS=libs) - -if GetOption('extras'): - env.Program('tests/test_proclog', ['tests/test_proclog.cc', 'proclog.cc'], LIBS=libs) diff --git a/system/proclogd/main.cc b/system/proclogd/main.cc deleted file mode 100644 index 3f8a889eea..0000000000 --- a/system/proclogd/main.cc +++ /dev/null @@ -1,25 +0,0 @@ - -#include - -#include "common/ratekeeper.h" -#include "common/util.h" -#include "system/proclogd/proclog.h" - -ExitHandler do_exit; - -int main(int argc, char **argv) { - setpriority(PRIO_PROCESS, 0, -15); - - RateKeeper rk("proclogd", 0.5); - PubMaster publisher({"procLog"}); - - while (!do_exit) { - MessageBuilder msg; - buildProcLogMessage(msg); - publisher.send("procLog", msg); - - rk.keepTime(); - } - - return 0; -} diff --git a/system/proclogd/proclog.cc b/system/proclogd/proclog.cc deleted file mode 100644 index 09ab4f559e..0000000000 --- a/system/proclogd/proclog.cc +++ /dev/null @@ -1,239 +0,0 @@ -#include "system/proclogd/proclog.h" - -#include - -#include -#include -#include -#include - -#include "common/swaglog.h" -#include "common/util.h" - -namespace Parser { - -// parse /proc/stat -std::vector cpuTimes(std::istream &stream) { - std::vector cpu_times; - std::string line; - // skip the first line for cpu total - std::getline(stream, line); - while (std::getline(stream, line)) { - if (line.compare(0, 3, "cpu") != 0) break; - - CPUTime t = {}; - std::istringstream iss(line); - if (iss.ignore(3) >> t.id >> t.utime >> t.ntime >> t.stime >> t.itime >> t.iowtime >> t.irqtime >> t.sirqtime) - cpu_times.push_back(t); - } - return cpu_times; -} - -// parse /proc/meminfo -std::unordered_map memInfo(std::istream &stream) { - std::unordered_map mem_info; - std::string line, key; - while (std::getline(stream, line)) { - uint64_t val = 0; - std::istringstream iss(line); - if (iss >> key >> val) { - mem_info[key] = val * 1024; - } - } - return mem_info; -} - -// field position (https://man7.org/linux/man-pages/man5/proc.5.html) -enum StatPos { - pid = 1, - state = 3, - ppid = 4, - utime = 14, - stime = 15, - cutime = 16, - cstime = 17, - priority = 18, - nice = 19, - num_threads = 20, - starttime = 22, - vsize = 23, - rss = 24, - processor = 39, - MAX_FIELD = 52, -}; - -// parse /proc/pid/stat -std::optional procStat(std::string stat) { - // To avoid being fooled by names containing a closing paren, scan backwards. - auto open_paren = stat.find('('); - auto close_paren = stat.rfind(')'); - if (open_paren == std::string::npos || close_paren == std::string::npos || open_paren > close_paren) { - return std::nullopt; - } - - std::string name = stat.substr(open_paren + 1, close_paren - open_paren - 1); - // replace space in name with _ - std::replace(&stat[open_paren], &stat[close_paren], ' ', '_'); - std::istringstream iss(stat); - std::vector v{std::istream_iterator(iss), - std::istream_iterator()}; - try { - if (v.size() != StatPos::MAX_FIELD) { - throw std::invalid_argument("stat"); - } - ProcStat p = { - .name = name, - .pid = stoi(v[StatPos::pid - 1]), - .state = v[StatPos::state - 1][0], - .ppid = stoi(v[StatPos::ppid - 1]), - .utime = stoul(v[StatPos::utime - 1]), - .stime = stoul(v[StatPos::stime - 1]), - .cutime = stol(v[StatPos::cutime - 1]), - .cstime = stol(v[StatPos::cstime - 1]), - .priority = stol(v[StatPos::priority - 1]), - .nice = stol(v[StatPos::nice - 1]), - .num_threads = stol(v[StatPos::num_threads - 1]), - .starttime = stoull(v[StatPos::starttime - 1]), - .vms = stoul(v[StatPos::vsize - 1]), - .rss = stol(v[StatPos::rss - 1]), - .processor = stoi(v[StatPos::processor - 1]), - }; - return p; - } catch (const std::invalid_argument &e) { - LOGE("failed to parse procStat (%s) :%s", e.what(), stat.c_str()); - } catch (const std::out_of_range &e) { - LOGE("failed to parse procStat (%s) :%s", e.what(), stat.c_str()); - } - return std::nullopt; -} - -// return list of PIDs from /proc -std::vector pids() { - std::vector ids; - DIR *d = opendir("/proc"); - assert(d); - char *p_end; - struct dirent *de = NULL; - while ((de = readdir(d))) { - if (de->d_type == DT_DIR) { - int pid = strtol(de->d_name, &p_end, 10); - if (p_end == (de->d_name + strlen(de->d_name))) { - ids.push_back(pid); - } - } - } - closedir(d); - return ids; -} - -// null-delimited cmdline arguments to vector -std::vector cmdline(std::istream &stream) { - std::vector ret; - std::string line; - while (std::getline(stream, line, '\0')) { - if (!line.empty()) { - ret.push_back(line); - } - } - return ret; -} - -const ProcCache &getProcExtraInfo(int pid, const std::string &name) { - static std::unordered_map proc_cache; - ProcCache &cache = proc_cache[pid]; - if (cache.pid != pid || cache.name != name) { - cache.pid = pid; - cache.name = name; - std::string proc_path = "/proc/" + std::to_string(pid); - cache.exe = util::readlink(proc_path + "/exe"); - std::ifstream stream(proc_path + "/cmdline"); - cache.cmdline = cmdline(stream); - } - return cache; -} - -} // namespace Parser - -const double jiffy = sysconf(_SC_CLK_TCK); -const size_t page_size = sysconf(_SC_PAGE_SIZE); - -void buildCPUTimes(cereal::ProcLog::Builder &builder) { - std::ifstream stream("/proc/stat"); - std::vector stats = Parser::cpuTimes(stream); - - auto log_cpu_times = builder.initCpuTimes(stats.size()); - for (int i = 0; i < stats.size(); ++i) { - auto l = log_cpu_times[i]; - const CPUTime &r = stats[i]; - l.setCpuNum(r.id); - l.setUser(r.utime / jiffy); - l.setNice(r.ntime / jiffy); - l.setSystem(r.stime / jiffy); - l.setIdle(r.itime / jiffy); - l.setIowait(r.iowtime / jiffy); - l.setIrq(r.irqtime / jiffy); - l.setSoftirq(r.sirqtime / jiffy); - } -} - -void buildMemInfo(cereal::ProcLog::Builder &builder) { - std::ifstream stream("/proc/meminfo"); - auto mem_info = Parser::memInfo(stream); - - auto mem = builder.initMem(); - mem.setTotal(mem_info["MemTotal:"]); - mem.setFree(mem_info["MemFree:"]); - mem.setAvailable(mem_info["MemAvailable:"]); - mem.setBuffers(mem_info["Buffers:"]); - mem.setCached(mem_info["Cached:"]); - mem.setActive(mem_info["Active:"]); - mem.setInactive(mem_info["Inactive:"]); - mem.setShared(mem_info["Shmem:"]); -} - -void buildProcs(cereal::ProcLog::Builder &builder) { - auto pids = Parser::pids(); - std::vector proc_stats; - proc_stats.reserve(pids.size()); - for (int pid : pids) { - std::string path = "/proc/" + std::to_string(pid) + "/stat"; - if (auto stat = Parser::procStat(util::read_file(path))) { - proc_stats.push_back(*stat); - } - } - - auto procs = builder.initProcs(proc_stats.size()); - for (size_t i = 0; i < proc_stats.size(); i++) { - auto l = procs[i]; - const ProcStat &r = proc_stats[i]; - l.setPid(r.pid); - l.setState(r.state); - l.setPpid(r.ppid); - l.setCpuUser(r.utime / jiffy); - l.setCpuSystem(r.stime / jiffy); - l.setCpuChildrenUser(r.cutime / jiffy); - l.setCpuChildrenSystem(r.cstime / jiffy); - l.setPriority(r.priority); - l.setNice(r.nice); - l.setNumThreads(r.num_threads); - l.setStartTime(r.starttime / jiffy); - l.setMemVms(r.vms); - l.setMemRss((uint64_t)r.rss * page_size); - l.setProcessor(r.processor); - l.setName(r.name); - - const ProcCache &extra_info = Parser::getProcExtraInfo(r.pid, r.name); - l.setExe(extra_info.exe); - auto lcmdline = l.initCmdline(extra_info.cmdline.size()); - for (size_t j = 0; j < lcmdline.size(); j++) { - lcmdline.set(j, extra_info.cmdline[j]); - } - } -} - -void buildProcLogMessage(MessageBuilder &msg) { - auto procLog = msg.initEvent().initProcLog(); - buildProcs(procLog); - buildCPUTimes(procLog); - buildMemInfo(procLog); -} diff --git a/system/proclogd/proclog.h b/system/proclogd/proclog.h deleted file mode 100644 index 49f97cdd36..0000000000 --- a/system/proclogd/proclog.h +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include -#include -#include - -#include "cereal/messaging/messaging.h" - -struct CPUTime { - int id; - unsigned long utime, ntime, stime, itime; - unsigned long iowtime, irqtime, sirqtime; -}; - -struct ProcCache { - int pid; - std::string name, exe; - std::vector cmdline; -}; - -struct ProcStat { - int pid, ppid, processor; - char state; - long cutime, cstime, priority, nice, num_threads, rss; - unsigned long utime, stime, vms; - unsigned long long starttime; - std::string name; -}; - -namespace Parser { - -std::vector pids(); -std::optional procStat(std::string stat); -std::vector cmdline(std::istream &stream); -std::vector cpuTimes(std::istream &stream); -std::unordered_map memInfo(std::istream &stream); -const ProcCache &getProcExtraInfo(int pid, const std::string &name); - -}; // namespace Parser - -void buildProcLogMessage(MessageBuilder &msg); diff --git a/system/proclogd/tests/.gitignore b/system/proclogd/tests/.gitignore deleted file mode 100644 index 5230b1598d..0000000000 --- a/system/proclogd/tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -test_proclog diff --git a/system/proclogd/tests/test_proclog.cc b/system/proclogd/tests/test_proclog.cc deleted file mode 100644 index b86229a499..0000000000 --- a/system/proclogd/tests/test_proclog.cc +++ /dev/null @@ -1,142 +0,0 @@ -#define CATCH_CONFIG_MAIN -#include "catch2/catch.hpp" -#include "common/util.h" -#include "system/proclogd/proclog.h" - -const std::string allowed_states = "RSDTZtWXxKWPI"; - -TEST_CASE("Parser::procStat") { - SECTION("from string") { - const std::string stat_str = - "33012 (code )) S 32978 6620 6620 0 -1 4194368 2042377 0 144 0 24510 11627 0 " - "0 20 0 39 0 53077 830029824 62214 18446744073709551615 94257242783744 94257366235808 " - "140735738643248 0 0 0 0 4098 1073808632 0 0 0 17 2 0 0 2 0 0 94257370858656 94257371248232 " - "94257404952576 140735738648768 140735738648823 140735738648823 140735738650595 0"; - auto stat = Parser::procStat(stat_str); - REQUIRE(stat); - REQUIRE(stat->pid == 33012); - REQUIRE(stat->name == "code )"); - REQUIRE(stat->state == 'S'); - REQUIRE(stat->ppid == 32978); - REQUIRE(stat->utime == 24510); - REQUIRE(stat->stime == 11627); - REQUIRE(stat->cutime == 0); - REQUIRE(stat->cstime == 0); - REQUIRE(stat->priority == 20); - REQUIRE(stat->nice == 0); - REQUIRE(stat->num_threads == 39); - REQUIRE(stat->starttime == 53077); - REQUIRE(stat->vms == 830029824); - REQUIRE(stat->rss == 62214); - REQUIRE(stat->processor == 2); - } - SECTION("all processes") { - std::vector pids = Parser::pids(); - REQUIRE(pids.size() > 1); - for (int pid : pids) { - std::string stat_path = "/proc/" + std::to_string(pid) + "/stat"; - INFO(stat_path); - if (auto stat = Parser::procStat(util::read_file(stat_path))) { - REQUIRE(stat->pid == pid); - REQUIRE(allowed_states.find(stat->state) != std::string::npos); - } else { - REQUIRE(util::file_exists(stat_path) == false); - } - } - } -} - -TEST_CASE("Parser::cpuTimes") { - SECTION("from string") { - std::string stat = - "cpu 0 0 0 0 0 0 0 0 0 0\n" - "cpu0 1 2 3 4 5 6 7 8 9 10\n" - "cpu1 1 2 3 4 5 6 7 8 9 10\n"; - std::istringstream stream(stat); - auto stats = Parser::cpuTimes(stream); - REQUIRE(stats.size() == 2); - for (int i = 0; i < stats.size(); ++i) { - REQUIRE(stats[i].id == i); - REQUIRE(stats[i].utime == 1); - REQUIRE(stats[i].ntime ==2); - REQUIRE(stats[i].stime == 3); - REQUIRE(stats[i].itime == 4); - REQUIRE(stats[i].iowtime == 5); - REQUIRE(stats[i].irqtime == 6); - REQUIRE(stats[i].sirqtime == 7); - } - } - SECTION("all cpus") { - std::istringstream stream(util::read_file("/proc/stat")); - auto stats = Parser::cpuTimes(stream); - REQUIRE(stats.size() == sysconf(_SC_NPROCESSORS_ONLN)); - for (int i = 0; i < stats.size(); ++i) { - REQUIRE(stats[i].id == i); - } - } -} - -TEST_CASE("Parser::memInfo") { - SECTION("from string") { - std::istringstream stream("MemTotal: 1024 kb\nMemFree: 2048 kb\n"); - auto meminfo = Parser::memInfo(stream); - REQUIRE(meminfo["MemTotal:"] == 1024 * 1024); - REQUIRE(meminfo["MemFree:"] == 2048 * 1024); - } - SECTION("from /proc/meminfo") { - std::string require_keys[] = {"MemTotal:", "MemFree:", "MemAvailable:", "Buffers:", "Cached:", "Active:", "Inactive:", "Shmem:"}; - std::istringstream stream(util::read_file("/proc/meminfo")); - auto meminfo = Parser::memInfo(stream); - for (auto &key : require_keys) { - REQUIRE(meminfo.find(key) != meminfo.end()); - REQUIRE(meminfo[key] > 0); - } - } -} - -void test_cmdline(std::string cmdline, const std::vector requires) { - std::stringstream ss; - ss.write(&cmdline[0], cmdline.size()); - auto cmds = Parser::cmdline(ss); - REQUIRE(cmds.size() == requires.size()); - for (int i = 0; i < requires.size(); ++i) { - REQUIRE(cmds[i] == requires[i]); - } -} -TEST_CASE("Parser::cmdline") { - test_cmdline(std::string("a\0b\0c\0", 7), {"a", "b", "c"}); - test_cmdline(std::string("a\0\0c\0", 6), {"a", "c"}); - test_cmdline(std::string("a\0b\0c\0\0\0", 9), {"a", "b", "c"}); -} - -TEST_CASE("buildProcLoggerMessage") { - MessageBuilder msg; - buildProcLogMessage(msg); - - kj::Array buf = capnp::messageToFlatArray(msg); - capnp::FlatArrayMessageReader reader(buf); - auto log = reader.getRoot().getProcLog(); - REQUIRE(log.totalSize().wordCount > 0); - - // test cereal::ProcLog::CPUTimes - auto cpu_times = log.getCpuTimes(); - REQUIRE(cpu_times.size() == sysconf(_SC_NPROCESSORS_ONLN)); - REQUIRE(cpu_times[cpu_times.size() - 1].getCpuNum() == cpu_times.size() - 1); - - // test cereal::ProcLog::Mem - auto mem = log.getMem(); - REQUIRE(mem.getTotal() > 0); - REQUIRE(mem.getShared() > 0); - - // test cereal::ProcLog::Process - auto procs = log.getProcs(); - for (auto p : procs) { - REQUIRE(allowed_states.find(p.getState()) != std::string::npos); - if (p.getPid() == ::getpid()) { - REQUIRE(p.getName() == "test_proclog"); - REQUIRE(p.getState() == 'R'); - REQUIRE_THAT(p.getExe().cStr(), Catch::Matchers::Contains("test_proclog")); - REQUIRE_THAT(p.getCmdline()[0], Catch::Matchers::Contains("test_proclog")); - } - } -} From 608c16007e6580fe746f9a7b18a4e790eae62b12 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Sun, 7 Sep 2025 11:32:44 -0700 Subject: [PATCH 052/159] Rewrite logcatd in Python (#36111) * Add Python logcatd implementation * lil more --- SConstruct | 4 -- selfdrive/test/test_onroad.py | 2 +- system/journald.py | 43 ++++++++++++++++++ system/logcatd/.gitignore | 1 - system/logcatd/SConscript | 3 -- system/logcatd/logcatd_systemd.cc | 75 ------------------------------- system/manager/process_config.py | 2 +- 7 files changed, 45 insertions(+), 85 deletions(-) create mode 100755 system/journald.py delete mode 100644 system/logcatd/.gitignore delete mode 100644 system/logcatd/SConscript delete mode 100644 system/logcatd/logcatd_systemd.cc diff --git a/SConstruct b/SConstruct index 21657ad556..5b13bd635a 100644 --- a/SConstruct +++ b/SConstruct @@ -338,10 +338,6 @@ SConscript([ 'system/ubloxd/SConscript', 'system/loggerd/SConscript', ]) -if arch != "Darwin": - SConscript([ - 'system/logcatd/SConscript', - ]) if arch == "larch64": SConscript(['system/camerad/SConscript']) diff --git a/selfdrive/test/test_onroad.py b/selfdrive/test/test_onroad.py index 26225ef400..b4b9b9dbbe 100644 --- a/selfdrive/test/test_onroad.py +++ b/selfdrive/test/test_onroad.py @@ -59,7 +59,7 @@ PROCS = { "system.proclogd": 3.0, "system.logmessaged": 1.0, "system.tombstoned": 0, - "./logcatd": 1.0, + "system.journald": 1.0, "system.micd": 5.0, "system.timed": 0, "selfdrive.pandad.pandad": 0, diff --git a/system/journald.py b/system/journald.py new file mode 100755 index 0000000000..37158b9251 --- /dev/null +++ b/system/journald.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +import json +import subprocess + +import cereal.messaging as messaging +from openpilot.common.swaglog import cloudlog + + +def main(): + pm = messaging.PubMaster(['androidLog']) + cmd = ['journalctl', '-f', '-o', 'json'] + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, text=True) + assert proc.stdout is not None + try: + for line in proc.stdout: + line = line.strip() + if not line: + continue + try: + kv = json.loads(line) + except json.JSONDecodeError: + cloudlog.exception("failed to parse journalctl output") + continue + + msg = messaging.new_message('androidLog') + entry = msg.androidLog + entry.ts = int(kv.get('__REALTIME_TIMESTAMP', 0)) + entry.message = json.dumps(kv) + if '_PID' in kv: + entry.pid = int(kv['_PID']) + if 'PRIORITY' in kv: + entry.priority = int(kv['PRIORITY']) + if 'SYSLOG_IDENTIFIER' in kv: + entry.tag = kv['SYSLOG_IDENTIFIER'] + + pm.send('androidLog', msg) + finally: + proc.terminate() + proc.wait() + + +if __name__ == '__main__': + main() diff --git a/system/logcatd/.gitignore b/system/logcatd/.gitignore deleted file mode 100644 index c66f7622d9..0000000000 --- a/system/logcatd/.gitignore +++ /dev/null @@ -1 +0,0 @@ -logcatd diff --git a/system/logcatd/SConscript b/system/logcatd/SConscript deleted file mode 100644 index 39c45d1093..0000000000 --- a/system/logcatd/SConscript +++ /dev/null @@ -1,3 +0,0 @@ -Import('env', 'messaging', 'common') - -env.Program('logcatd', 'logcatd_systemd.cc', LIBS=[messaging, common, 'systemd']) diff --git a/system/logcatd/logcatd_systemd.cc b/system/logcatd/logcatd_systemd.cc deleted file mode 100644 index 54b3782132..0000000000 --- a/system/logcatd/logcatd_systemd.cc +++ /dev/null @@ -1,75 +0,0 @@ -#include - -#include -#include -#include -#include - -#include "third_party/json11/json11.hpp" - -#include "cereal/messaging/messaging.h" -#include "common/timing.h" -#include "common/util.h" - -ExitHandler do_exit; -int main(int argc, char *argv[]) { - - PubMaster pm({"androidLog"}); - - sd_journal *journal; - int err = sd_journal_open(&journal, 0); - assert(err >= 0); - err = sd_journal_get_fd(journal); // needed so sd_journal_wait() works properly if files rotate - assert(err >= 0); - err = sd_journal_seek_tail(journal); - assert(err >= 0); - - // workaround for bug https://github.com/systemd/systemd/issues/9934 - // call sd_journal_previous_skip after sd_journal_seek_tail (like journalctl -f does) to makes things work. - sd_journal_previous_skip(journal, 1); - - while (!do_exit) { - err = sd_journal_next(journal); - assert(err >= 0); - - // Wait for new message if we didn't receive anything - if (err == 0) { - err = sd_journal_wait(journal, 1000 * 1000); - assert(err >= 0); - continue; // Try again - } - - uint64_t timestamp = 0; - err = sd_journal_get_realtime_usec(journal, ×tamp); - assert(err >= 0); - - const void *data; - size_t length; - std::map kv; - - SD_JOURNAL_FOREACH_DATA(journal, data, length) { - std::string str((char*)data, length); - - // Split "KEY=VALUE"" on "=" and put in map - std::size_t found = str.find("="); - if (found != std::string::npos) { - kv[str.substr(0, found)] = str.substr(found + 1, std::string::npos); - } - } - - MessageBuilder msg; - - // Build message - auto androidEntry = msg.initEvent().initAndroidLog(); - androidEntry.setTs(timestamp); - androidEntry.setMessage(json11::Json(kv).dump()); - if (kv.count("_PID")) androidEntry.setPid(std::atoi(kv["_PID"].c_str())); - if (kv.count("PRIORITY")) androidEntry.setPriority(std::atoi(kv["PRIORITY"].c_str())); - if (kv.count("SYSLOG_IDENTIFIER")) androidEntry.setTag(kv["SYSLOG_IDENTIFIER"]); - - pm.send("androidLog", msg); - } - - sd_journal_close(journal); - return 0; -} diff --git a/system/manager/process_config.py b/system/manager/process_config.py index e25c0e985f..9ed99d9560 100644 --- a/system/manager/process_config.py +++ b/system/manager/process_config.py @@ -71,8 +71,8 @@ procs = [ NativeProcess("camerad", "system/camerad", ["./camerad"], driverview, enabled=not WEBCAM), PythonProcess("webcamerad", "tools.webcam.camerad", driverview, enabled=WEBCAM), - NativeProcess("logcatd", "system/logcatd", ["./logcatd"], only_onroad, platform.system() != "Darwin"), PythonProcess("proclogd", "system.proclogd", only_onroad, enabled=platform.system() != "Darwin"), + PythonProcess("journald", "system.journald", only_onroad, platform.system() != "Darwin"), PythonProcess("micd", "system.micd", iscar), PythonProcess("timed", "system.timed", always_run, enabled=not PC), From bd73664f4c9dae102daa16ffe1efb6d051f46bd1 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Sun, 7 Sep 2025 12:21:13 -0700 Subject: [PATCH 053/159] add kaitai python package --- pyproject.toml | 4 +++ uv.lock | 77 ++++++++++++++++++++++++++++---------------------- 2 files changed, 48 insertions(+), 33 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3e362556a3..9ed1d8a4cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,6 +36,9 @@ dependencies = [ "pyopenssl < 24.3.0", "pyaudio", + # ubloxd (TODO: just use struct) + "kaitaistruct", + # panda "libusb1", "spidev; platform_system == 'Linux'", @@ -246,6 +249,7 @@ exclude = [ "teleoprtc_repo", "third_party", "*.ipynb", + "generated", ] lint.flake8-implicit-str-concat.allow-multiline = false diff --git a/uv.lock b/uv.lock index e1678029cf..9977ff1bf7 100644 --- a/uv.lock +++ b/uv.lock @@ -622,10 +622,10 @@ name = "gymnasium" version = "1.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cloudpickle" }, - { name = "farama-notifications" }, - { name = "numpy" }, - { name = "typing-extensions" }, + { name = "cloudpickle", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "farama-notifications", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "numpy", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "typing-extensions", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/fd/17/c2a0e15c2cd5a8e788389b280996db927b923410de676ec5c7b2695e9261/gymnasium-1.2.0.tar.gz", hash = "sha256:344e87561012558f603880baf264ebc97f8a5c997a957b0c9f910281145534b0", size = 821142, upload-time = "2025-06-27T08:21:20.262Z" } wheels = [ @@ -720,6 +720,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/94/9e/820c4b086ad01ba7d77369fb8b11470a01fac9b4977f02e18659cf378b6b/json_rpc-1.15.0-py2.py3-none-any.whl", hash = "sha256:4a4668bbbe7116feb4abbd0f54e64a4adcf4b8f648f19ffa0848ad0f6606a9bf", size = 39450, upload-time = "2023-06-11T09:45:47.136Z" }, ] +[[package]] +name = "kaitaistruct" +version = "0.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/04/dd60b9cb65d580ef6cb6eaee975ad1bdd22d46a3f51b07a1e0606710ea88/kaitaistruct-0.10.tar.gz", hash = "sha256:a044dee29173d6afbacf27bcac39daf89b654dd418cfa009ab82d9178a9ae52a", size = 7061, upload-time = "2022-07-09T00:34:06.729Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4e/bf/88ad23efc08708bda9a2647169828e3553bb2093a473801db61f75356395/kaitaistruct-0.10-py2.py3-none-any.whl", hash = "sha256:a97350919adbf37fda881f75e9365e2fb88d04832b7a4e57106ec70119efb235", size = 7013, upload-time = "2022-07-09T00:34:03.905Z" }, +] + [[package]] name = "kiwisolver" version = "1.4.9" @@ -903,22 +912,22 @@ name = "metadrive-simulator" version = "0.4.2.4" source = { url = "https://github.com/commaai/metadrive/releases/download/MetaDrive-minimal-0.4.2.4/metadrive_simulator-0.4.2.4-py3-none-any.whl" } dependencies = [ - { name = "filelock" }, - { name = "gymnasium" }, - { name = "lxml" }, - { name = "matplotlib" }, - { name = "numpy" }, - { name = "opencv-python-headless" }, - { name = "panda3d" }, - { name = "panda3d-gltf" }, - { name = "pillow" }, - { name = "progressbar" }, - { name = "psutil" }, - { name = "pygments" }, - { name = "requests" }, - { name = "shapely" }, - { name = "tqdm" }, - { name = "yapf" }, + { name = "filelock", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "gymnasium", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "lxml", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "matplotlib", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "numpy", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "opencv-python-headless", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "panda3d", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "panda3d-gltf", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "pillow", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "progressbar", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "psutil", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "pygments", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "requests", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "shapely", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "tqdm", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "yapf", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, ] wheels = [ { url = "https://github.com/commaai/metadrive/releases/download/MetaDrive-minimal-0.4.2.4/metadrive_simulator-0.4.2.4-py3-none-any.whl", hash = "sha256:fbf0ea9be67e65cd45d38ff930e3d49f705dd76c9ddbd1e1482e3f87b61efcef" }, @@ -1240,6 +1249,7 @@ dependencies = [ { name = "future-fstrings" }, { name = "inputs" }, { name = "json-rpc" }, + { name = "kaitaistruct" }, { name = "libusb1" }, { name = "numpy" }, { name = "onnx" }, @@ -1334,6 +1344,7 @@ requires-dist = [ { name = "jeepney", marker = "extra == 'dev'" }, { name = "jinja2", marker = "extra == 'docs'" }, { name = "json-rpc" }, + { name = "kaitaistruct" }, { name = "libusb1" }, { name = "matplotlib", marker = "extra == 'dev'" }, { name = "metadrive-simulator", marker = "platform_machine != 'aarch64' and extra == 'tools'", url = "https://github.com/commaai/metadrive/releases/download/MetaDrive-minimal-0.4.2.4/metadrive_simulator-0.4.2.4-py3-none-any.whl" }, @@ -1422,8 +1433,8 @@ name = "panda3d-gltf" version = "0.13" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "panda3d" }, - { name = "panda3d-simplepbr" }, + { name = "panda3d", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "panda3d-simplepbr", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/07/7f/9f18fc3fa843a080acb891af6bcc12262e7bdf1d194a530f7042bebfc81f/panda3d-gltf-0.13.tar.gz", hash = "sha256:d06d373bdd91cf530909b669f43080e599463bbf6d3ef00c3558bad6c6b19675", size = 25573, upload-time = "2021-05-21T05:46:32.738Z" } wheels = [ @@ -1435,8 +1446,8 @@ name = "panda3d-simplepbr" version = "0.13.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "panda3d" }, - { name = "typing-extensions" }, + { name = "panda3d", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "typing-extensions", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0d/be/c4d1ded04c22b357277cf6e6a44c1ab4abb285a700bd1991460460e05b99/panda3d_simplepbr-0.13.1.tar.gz", hash = "sha256:c83766d7c8f47499f365a07fe1dff078fc8b3054c2689bdc8dceabddfe7f1a35", size = 6216055, upload-time = "2025-03-30T16:57:41.087Z" } wheels = [ @@ -4173,9 +4184,9 @@ name = "pyopencl" version = "2025.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy" }, - { name = "platformdirs" }, - { name = "pytools" }, + { name = "numpy", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "platformdirs", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "pytools", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/28/88/0ac460d3e2def08b2ad6345db6a13613815f616bbbd60c6f4bdf774f4c41/pyopencl-2025.1.tar.gz", hash = "sha256:0116736d7f7920f87b8db4b66a03f27b1d930d2e37ddd14518407cc22dd24779", size = 422510, upload-time = "2025-01-22T00:16:58.421Z" } wheels = [ @@ -4351,7 +4362,7 @@ wheels = [ [[package]] name = "pytest-xdist" -version = "3.7.1.dev24+g2b4372bd6" +version = "3.7.1.dev24+g2b4372b" source = { git = "https://github.com/sshane/pytest-xdist?rev=2b4372bd62699fb412c4fe2f95bf9f01bd2018da#2b4372bd62699fb412c4fe2f95bf9f01bd2018da" } dependencies = [ { name = "execnet" }, @@ -4393,9 +4404,9 @@ name = "pytools" version = "2024.1.10" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "platformdirs" }, - { name = "siphash24" }, - { name = "typing-extensions" }, + { name = "platformdirs", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "siphash24", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, + { name = "typing-extensions", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ee/0f/56e109c0307f831b5d598ad73976aaaa84b4d0e98da29a642e797eaa940c/pytools-2024.1.10.tar.gz", hash = "sha256:9af6f4b045212c49be32bb31fe19606c478ee4b09631886d05a32459f4ce0a12", size = 81741, upload-time = "2024-07-17T18:47:38.287Z" } wheels = [ @@ -4719,7 +4730,7 @@ name = "shapely" version = "2.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy" }, + { name = "numpy", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ca/3c/2da625233f4e605155926566c0e7ea8dda361877f48e8b1655e53456f252/shapely-2.1.1.tar.gz", hash = "sha256:500621967f2ffe9642454808009044c21e5b35db89ce69f8a2042c2ffd0e2772", size = 315422, upload-time = "2025-05-19T11:04:41.265Z" } wheels = [ @@ -4948,7 +4959,7 @@ name = "yapf" version = "0.43.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "platformdirs" }, + { name = "platformdirs", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/23/97/b6f296d1e9cc1ec25c7604178b48532fa5901f721bcf1b8d8148b13e5588/yapf-0.43.0.tar.gz", hash = "sha256:00d3aa24bfedff9420b2e0d5d9f5ab6d9d4268e72afbf59bb3fa542781d5218e", size = 254907, upload-time = "2024-11-14T00:11:41.584Z" } wheels = [ From a885111c0ccb466ea75e2d808ac84786287035bf Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Sun, 7 Sep 2025 14:21:14 -0700 Subject: [PATCH 054/159] agnos 13.1 (#36113) --- launch_env.sh | 2 +- system/hardware/tici/agnos.json | 26 ++++++------ system/hardware/tici/all-partitions.json | 50 ++++++++++++------------ 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/launch_env.sh b/launch_env.sh index 7124b360f8..67dd5ee795 100755 --- a/launch_env.sh +++ b/launch_env.sh @@ -7,7 +7,7 @@ export OPENBLAS_NUM_THREADS=1 export VECLIB_MAXIMUM_THREADS=1 if [ -z "$AGNOS_VERSION" ]; then - export AGNOS_VERSION="13" + export AGNOS_VERSION="13.1" fi export STAGING_ROOT="/data/safe_staging" diff --git a/system/hardware/tici/agnos.json b/system/hardware/tici/agnos.json index b252a8110e..d93963cf2c 100644 --- a/system/hardware/tici/agnos.json +++ b/system/hardware/tici/agnos.json @@ -56,29 +56,29 @@ }, { "name": "boot", - "url": "https://commadist.azureedge.net/agnosupdate/boot-3e26a0d330a1be1614a5c25cae238ca5d01c1be90802ad296c805c3bcbad0e7a.img.xz", - "hash": "3e26a0d330a1be1614a5c25cae238ca5d01c1be90802ad296c805c3bcbad0e7a", - "hash_raw": "3e26a0d330a1be1614a5c25cae238ca5d01c1be90802ad296c805c3bcbad0e7a", - "size": 18515968, + "url": "https://commadist.azureedge.net/agnosupdate/boot-b96882012ab6cddda04f440009c798a6cff65977f984b12072e89afa592d86cb.img.xz", + "hash": "b96882012ab6cddda04f440009c798a6cff65977f984b12072e89afa592d86cb", + "hash_raw": "b96882012ab6cddda04f440009c798a6cff65977f984b12072e89afa592d86cb", + "size": 17442816, "sparse": false, "full_check": true, "has_ab": true, - "ondevice_hash": "41d693d7e752c04210b4f8d68015d2367ee83e1cd54cc7b0aca3b79b4855e6b1" + "ondevice_hash": "8ed6c2796be5c5b29d64e6413b8e878d5bd1a3981d15216d2b5e84140cc4ea2a" }, { "name": "system", - "url": "https://commadist.azureedge.net/agnosupdate/system-4d0c7005e242fc757adbefd43b44ab2e78be53ca5145fceb160cc32ecf8d6cc3.img.xz", - "hash": "3596cd5d8a51dabcdd75c29f9317ca3dad9036b1083630ad719eaf584fdb1ce9", - "hash_raw": "4d0c7005e242fc757adbefd43b44ab2e78be53ca5145fceb160cc32ecf8d6cc3", - "size": 5368709120, + "url": "https://commadist.azureedge.net/agnosupdate/system-2b1bb223bf2100376ad5d543bfa4a483f33327b3478ec20ab36048388472c4bc.img.xz", + "hash": "325414e5c9f7516b2bf0fedb6abe6682f717897a6d84ab70d5afe91a59f244e9", + "hash_raw": "2b1bb223bf2100376ad5d543bfa4a483f33327b3478ec20ab36048388472c4bc", + "size": 4718592000, "sparse": true, "full_check": false, "has_ab": true, - "ondevice_hash": "32cdbc0ce176e0ea92944e53be875c12374512fa09b6041e42e683519d36591e", + "ondevice_hash": "79f4f6d0b5b4a416f0f31261b430943a78e37c26d0e226e0ef412fe0eae3c727", "alt": { - "hash": "4d0c7005e242fc757adbefd43b44ab2e78be53ca5145fceb160cc32ecf8d6cc3", - "url": "https://commadist.azureedge.net/agnosupdate/system-4d0c7005e242fc757adbefd43b44ab2e78be53ca5145fceb160cc32ecf8d6cc3.img", - "size": 5368709120 + "hash": "2b1bb223bf2100376ad5d543bfa4a483f33327b3478ec20ab36048388472c4bc", + "url": "https://commadist.azureedge.net/agnosupdate/system-2b1bb223bf2100376ad5d543bfa4a483f33327b3478ec20ab36048388472c4bc.img", + "size": 4718592000 } } ] \ No newline at end of file diff --git a/system/hardware/tici/all-partitions.json b/system/hardware/tici/all-partitions.json index 8bc6680b98..ebffc01dfd 100644 --- a/system/hardware/tici/all-partitions.json +++ b/system/hardware/tici/all-partitions.json @@ -339,62 +339,62 @@ }, { "name": "boot", - "url": "https://commadist.azureedge.net/agnosupdate/boot-3e26a0d330a1be1614a5c25cae238ca5d01c1be90802ad296c805c3bcbad0e7a.img.xz", - "hash": "3e26a0d330a1be1614a5c25cae238ca5d01c1be90802ad296c805c3bcbad0e7a", - "hash_raw": "3e26a0d330a1be1614a5c25cae238ca5d01c1be90802ad296c805c3bcbad0e7a", - "size": 18515968, + "url": "https://commadist.azureedge.net/agnosupdate/boot-b96882012ab6cddda04f440009c798a6cff65977f984b12072e89afa592d86cb.img.xz", + "hash": "b96882012ab6cddda04f440009c798a6cff65977f984b12072e89afa592d86cb", + "hash_raw": "b96882012ab6cddda04f440009c798a6cff65977f984b12072e89afa592d86cb", + "size": 17442816, "sparse": false, "full_check": true, "has_ab": true, - "ondevice_hash": "41d693d7e752c04210b4f8d68015d2367ee83e1cd54cc7b0aca3b79b4855e6b1" + "ondevice_hash": "8ed6c2796be5c5b29d64e6413b8e878d5bd1a3981d15216d2b5e84140cc4ea2a" }, { "name": "system", - "url": "https://commadist.azureedge.net/agnosupdate/system-4d0c7005e242fc757adbefd43b44ab2e78be53ca5145fceb160cc32ecf8d6cc3.img.xz", - "hash": "3596cd5d8a51dabcdd75c29f9317ca3dad9036b1083630ad719eaf584fdb1ce9", - "hash_raw": "4d0c7005e242fc757adbefd43b44ab2e78be53ca5145fceb160cc32ecf8d6cc3", - "size": 5368709120, + "url": "https://commadist.azureedge.net/agnosupdate/system-2b1bb223bf2100376ad5d543bfa4a483f33327b3478ec20ab36048388472c4bc.img.xz", + "hash": "325414e5c9f7516b2bf0fedb6abe6682f717897a6d84ab70d5afe91a59f244e9", + "hash_raw": "2b1bb223bf2100376ad5d543bfa4a483f33327b3478ec20ab36048388472c4bc", + "size": 4718592000, "sparse": true, "full_check": false, "has_ab": true, - "ondevice_hash": "32cdbc0ce176e0ea92944e53be875c12374512fa09b6041e42e683519d36591e", + "ondevice_hash": "79f4f6d0b5b4a416f0f31261b430943a78e37c26d0e226e0ef412fe0eae3c727", "alt": { - "hash": "4d0c7005e242fc757adbefd43b44ab2e78be53ca5145fceb160cc32ecf8d6cc3", - "url": "https://commadist.azureedge.net/agnosupdate/system-4d0c7005e242fc757adbefd43b44ab2e78be53ca5145fceb160cc32ecf8d6cc3.img", - "size": 5368709120 + "hash": "2b1bb223bf2100376ad5d543bfa4a483f33327b3478ec20ab36048388472c4bc", + "url": "https://commadist.azureedge.net/agnosupdate/system-2b1bb223bf2100376ad5d543bfa4a483f33327b3478ec20ab36048388472c4bc.img", + "size": 4718592000 } }, { "name": "userdata_90", - "url": "https://commadist.azureedge.net/agnosupdate/userdata_90-a3695e6b4bade3dd9c2711cd92e93e9ac7744207c2af03b78f0b9a17e89d357f.img.xz", - "hash": "eeb50afb13973d7e54013fdb3ce0f4f396b8608c8325442966cad6b67e39a8d9", - "hash_raw": "a3695e6b4bade3dd9c2711cd92e93e9ac7744207c2af03b78f0b9a17e89d357f", + "url": "https://commadist.azureedge.net/agnosupdate/userdata_90-b3112984d2a8534a83d2ce43d35efdd10c7d163d9699f611f0f72ad9e9cb5af9.img.xz", + "hash": "bea163e6fb6ac6224c7f32619affb5afb834cd859971b0cab6d8297dd0098f0a", + "hash_raw": "b3112984d2a8534a83d2ce43d35efdd10c7d163d9699f611f0f72ad9e9cb5af9", "size": 96636764160, "sparse": true, "full_check": true, "has_ab": false, - "ondevice_hash": "537088b516805b32b1b4ad176e7f3fc6bc828e296398ce65cbf5f6150fb1a26f" + "ondevice_hash": "f4841c6ae3207197886e5efbd50f44cc24822680d7b785fa2d2743c657f23287" }, { "name": "userdata_89", - "url": "https://commadist.azureedge.net/agnosupdate/userdata_89-cbe9979b42b265c9e25a50e876faf5b592fe175aeb5936f2a97b345a6d4e53f5.img.xz", - "hash": "9456a8b117736e6f8eb35cc97fc62ddc8255f38a1be5959a6911498d6aaee08d", - "hash_raw": "cbe9979b42b265c9e25a50e876faf5b592fe175aeb5936f2a97b345a6d4e53f5", + "url": "https://commadist.azureedge.net/agnosupdate/userdata_89-3e63f670e4270474cec96f4da9250ee4e87e3106b0b043b7e82371e1c761e167.img.xz", + "hash": "b5458a29dd7d4a4c9b7ad77b8baa5f804142ac78d97c6668839bf2a650e32518", + "hash_raw": "3e63f670e4270474cec96f4da9250ee4e87e3106b0b043b7e82371e1c761e167", "size": 95563022336, "sparse": true, "full_check": true, "has_ab": false, - "ondevice_hash": "9e7293cf9a377cb2f3477698e7143e6085a42f7355d7eace5bf9e590992941a8" + "ondevice_hash": "1dc10c542d3b019258fc08dc7dfdb49d9abad065e46d030b89bc1a2e0197f526" }, { "name": "userdata_30", - "url": "https://commadist.azureedge.net/agnosupdate/userdata_30-0b25bb660f1c0c4475fc22a32a51cd32bb980f55b95069e6ab56dd8e47f00c31.img.xz", - "hash": "6c5c98c0fec64355ead5dfc9c1902653b4ea9a071e7b968d1ccd36565082f6b7", - "hash_raw": "0b25bb660f1c0c4475fc22a32a51cd32bb980f55b95069e6ab56dd8e47f00c31", + "url": "https://commadist.azureedge.net/agnosupdate/userdata_30-1d3885d4370974e55f0c6f567fd0344fc5ee10db067aa5810fbaf402eadb032c.img.xz", + "hash": "687d178cfc91be5d7e8aa1333405b610fdce01775b8333bd0985b81642b94eea", + "hash_raw": "1d3885d4370974e55f0c6f567fd0344fc5ee10db067aa5810fbaf402eadb032c", "size": 32212254720, "sparse": true, "full_check": true, "has_ab": false, - "ondevice_hash": "42b5c09a36866d9a52e78b038901669d5bebb02176c498ce11618f200bdfe6b5" + "ondevice_hash": "9ddbd1dae6ee7dc919f018364cf2f29dad138c9203c5a49aea0cbb9bf2e137e5" } ] \ No newline at end of file From 8dca43881a9e253158d483dd02a5522563386283 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Sun, 7 Sep 2025 15:40:48 -0700 Subject: [PATCH 055/159] Rewrite ubloxd in Python (#36112) * Rewrite ubloxd in Python * lil more * rm from third_party/ * cleanup * ubx replay * try this * back to kaitai * Revert "ubx replay" This reverts commit 570bd3d25fbabc590379ce0a9f98d30de55cf1b3. --- system/manager/process_config.py | 2 +- system/ubloxd/.gitignore | 2 - system/ubloxd/SConscript | 25 +- system/ubloxd/generated/glonass.cpp | 353 ----------- system/ubloxd/generated/glonass.h | 375 ----------- system/ubloxd/generated/glonass.py | 247 ++++++++ system/ubloxd/generated/gps.cpp | 325 ---------- system/ubloxd/generated/gps.h | 359 ----------- system/ubloxd/generated/gps.py | 193 ++++++ system/ubloxd/generated/ubx.cpp | 424 ------------- system/ubloxd/generated/ubx.h | 484 --------------- system/ubloxd/generated/ubx.py | 273 ++++++++ system/ubloxd/tests/print_gps_stats.py | 20 - system/ubloxd/tests/test_glonass_kaitai.cc | 360 ----------- system/ubloxd/tests/test_glonass_runner.cc | 2 - system/ubloxd/ublox_msg.cc | 530 ---------------- system/ubloxd/ublox_msg.h | 131 ---- system/ubloxd/ubloxd.cc | 62 -- system/ubloxd/ubloxd.py | 519 ++++++++++++++++ third_party/SConscript | 1 - third_party/kaitai/custom_decoder.h | 16 - third_party/kaitai/exceptions.h | 189 ------ third_party/kaitai/kaitaistream.cpp | 689 --------------------- third_party/kaitai/kaitaistream.h | 268 -------- third_party/kaitai/kaitaistruct.h | 20 - 25 files changed, 1241 insertions(+), 4628 deletions(-) delete mode 100644 system/ubloxd/.gitignore delete mode 100644 system/ubloxd/generated/glonass.cpp delete mode 100644 system/ubloxd/generated/glonass.h create mode 100644 system/ubloxd/generated/glonass.py delete mode 100644 system/ubloxd/generated/gps.cpp delete mode 100644 system/ubloxd/generated/gps.h create mode 100644 system/ubloxd/generated/gps.py delete mode 100644 system/ubloxd/generated/ubx.cpp delete mode 100644 system/ubloxd/generated/ubx.h create mode 100644 system/ubloxd/generated/ubx.py delete mode 100755 system/ubloxd/tests/print_gps_stats.py delete mode 100644 system/ubloxd/tests/test_glonass_kaitai.cc delete mode 100644 system/ubloxd/tests/test_glonass_runner.cc delete mode 100644 system/ubloxd/ublox_msg.cc delete mode 100644 system/ubloxd/ublox_msg.h delete mode 100644 system/ubloxd/ubloxd.cc create mode 100755 system/ubloxd/ubloxd.py delete mode 100644 third_party/kaitai/custom_decoder.h delete mode 100644 third_party/kaitai/exceptions.h delete mode 100644 third_party/kaitai/kaitaistream.cpp delete mode 100644 third_party/kaitai/kaitaistream.h delete mode 100644 third_party/kaitai/kaitaistruct.h diff --git a/system/manager/process_config.py b/system/manager/process_config.py index 9ed99d9560..22f159e891 100644 --- a/system/manager/process_config.py +++ b/system/manager/process_config.py @@ -97,7 +97,7 @@ procs = [ PythonProcess("pandad", "selfdrive.pandad.pandad", always_run), PythonProcess("paramsd", "selfdrive.locationd.paramsd", only_onroad), PythonProcess("lagd", "selfdrive.locationd.lagd", only_onroad), - NativeProcess("ubloxd", "system/ubloxd", ["./ubloxd"], ublox, enabled=TICI), + PythonProcess("ubloxd", "system.ubloxd.ubloxd", ublox, enabled=TICI), PythonProcess("pigeond", "system.ubloxd.pigeond", ublox, enabled=TICI), PythonProcess("plannerd", "selfdrive.controls.plannerd", not_long_maneuver), PythonProcess("maneuversd", "tools.longitudinal_maneuvers.maneuversd", long_maneuver), diff --git a/system/ubloxd/.gitignore b/system/ubloxd/.gitignore deleted file mode 100644 index 05263ff67c..0000000000 --- a/system/ubloxd/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -ubloxd -tests/test_glonass_runner diff --git a/system/ubloxd/SConscript b/system/ubloxd/SConscript index ce09e235e6..9eb50760ba 100644 --- a/system/ubloxd/SConscript +++ b/system/ubloxd/SConscript @@ -1,20 +1,11 @@ -Import('env', 'common', 'messaging') - -loc_libs = [messaging, common, 'kaitai', 'pthread'] +Import('env') if GetOption('kaitai'): - generated = Dir('generated').srcnode().abspath - cmd = f"kaitai-struct-compiler --target cpp_stl --outdir {generated} $SOURCES" - env.Command(['generated/ubx.cpp', 'generated/ubx.h'], 'ubx.ksy', cmd) - env.Command(['generated/gps.cpp', 'generated/gps.h'], 'gps.ksy', cmd) - glonass = env.Command(['generated/glonass.cpp', 'generated/glonass.h'], 'glonass.ksy', cmd) - + current_dir = Dir('./generated/').srcnode().abspath + python_cmd = f"kaitai-struct-compiler --target python --outdir {current_dir} $SOURCES" + env.Command(File('./generated/ubx.py'), 'ubx.ksy', python_cmd) + env.Command(File('./generated/gps.py'), 'gps.ksy', python_cmd) + env.Command(File('./generated/glonass.py'), 'glonass.ksy', python_cmd) # kaitai issue: https://github.com/kaitai-io/kaitai_struct/issues/910 - patch = env.Command(None, 'glonass_fix.patch', 'git apply $SOURCES') - env.Depends(patch, glonass) - -glonass_obj = env.Object('generated/glonass.cpp') -env.Program("ubloxd", ["ubloxd.cc", "ublox_msg.cc", "generated/ubx.cpp", "generated/gps.cpp", glonass_obj], LIBS=loc_libs) - -if GetOption('extras'): - env.Program("tests/test_glonass_runner", ['tests/test_glonass_runner.cc', 'tests/test_glonass_kaitai.cc', glonass_obj], LIBS=[loc_libs]) \ No newline at end of file + py_glonass_fix = env.Command(None, File('./generated/glonass.py'), "sed -i 's/self._io.align_to_byte()/# self._io.align_to_byte()/' $SOURCES") + env.Depends(py_glonass_fix, File('./generated/glonass.py')) diff --git a/system/ubloxd/generated/glonass.cpp b/system/ubloxd/generated/glonass.cpp deleted file mode 100644 index cd0f96ab68..0000000000 --- a/system/ubloxd/generated/glonass.cpp +++ /dev/null @@ -1,353 +0,0 @@ -// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild - -#include "glonass.h" - -glonass_t::glonass_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, glonass_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = this; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void glonass_t::_read() { - m_idle_chip = m__io->read_bits_int_be(1); - m_string_number = m__io->read_bits_int_be(4); - //m__io->align_to_byte(); - switch (string_number()) { - case 4: { - m_data = new string_4_t(m__io, this, m__root); - break; - } - case 1: { - m_data = new string_1_t(m__io, this, m__root); - break; - } - case 3: { - m_data = new string_3_t(m__io, this, m__root); - break; - } - case 5: { - m_data = new string_5_t(m__io, this, m__root); - break; - } - case 2: { - m_data = new string_2_t(m__io, this, m__root); - break; - } - default: { - m_data = new string_non_immediate_t(m__io, this, m__root); - break; - } - } - m_hamming_code = m__io->read_bits_int_be(8); - m_pad_1 = m__io->read_bits_int_be(11); - m_superframe_number = m__io->read_bits_int_be(16); - m_pad_2 = m__io->read_bits_int_be(8); - m_frame_number = m__io->read_bits_int_be(8); -} - -glonass_t::~glonass_t() { - _clean_up(); -} - -void glonass_t::_clean_up() { - if (m_data) { - delete m_data; m_data = 0; - } -} - -glonass_t::string_4_t::string_4_t(kaitai::kstream* p__io, glonass_t* p__parent, glonass_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - f_tau_n = false; - f_delta_tau_n = false; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void glonass_t::string_4_t::_read() { - m_tau_n_sign = m__io->read_bits_int_be(1); - m_tau_n_value = m__io->read_bits_int_be(21); - m_delta_tau_n_sign = m__io->read_bits_int_be(1); - m_delta_tau_n_value = m__io->read_bits_int_be(4); - m_e_n = m__io->read_bits_int_be(5); - m_not_used_1 = m__io->read_bits_int_be(14); - m_p4 = m__io->read_bits_int_be(1); - m_f_t = m__io->read_bits_int_be(4); - m_not_used_2 = m__io->read_bits_int_be(3); - m_n_t = m__io->read_bits_int_be(11); - m_n = m__io->read_bits_int_be(5); - m_m = m__io->read_bits_int_be(2); -} - -glonass_t::string_4_t::~string_4_t() { - _clean_up(); -} - -void glonass_t::string_4_t::_clean_up() { -} - -int32_t glonass_t::string_4_t::tau_n() { - if (f_tau_n) - return m_tau_n; - m_tau_n = ((tau_n_sign()) ? ((tau_n_value() * -1)) : (tau_n_value())); - f_tau_n = true; - return m_tau_n; -} - -int32_t glonass_t::string_4_t::delta_tau_n() { - if (f_delta_tau_n) - return m_delta_tau_n; - m_delta_tau_n = ((delta_tau_n_sign()) ? ((delta_tau_n_value() * -1)) : (delta_tau_n_value())); - f_delta_tau_n = true; - return m_delta_tau_n; -} - -glonass_t::string_non_immediate_t::string_non_immediate_t(kaitai::kstream* p__io, glonass_t* p__parent, glonass_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void glonass_t::string_non_immediate_t::_read() { - m_data_1 = m__io->read_bits_int_be(64); - m_data_2 = m__io->read_bits_int_be(8); -} - -glonass_t::string_non_immediate_t::~string_non_immediate_t() { - _clean_up(); -} - -void glonass_t::string_non_immediate_t::_clean_up() { -} - -glonass_t::string_5_t::string_5_t(kaitai::kstream* p__io, glonass_t* p__parent, glonass_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void glonass_t::string_5_t::_read() { - m_n_a = m__io->read_bits_int_be(11); - m_tau_c = m__io->read_bits_int_be(32); - m_not_used = m__io->read_bits_int_be(1); - m_n_4 = m__io->read_bits_int_be(5); - m_tau_gps = m__io->read_bits_int_be(22); - m_l_n = m__io->read_bits_int_be(1); -} - -glonass_t::string_5_t::~string_5_t() { - _clean_up(); -} - -void glonass_t::string_5_t::_clean_up() { -} - -glonass_t::string_1_t::string_1_t(kaitai::kstream* p__io, glonass_t* p__parent, glonass_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - f_x_vel = false; - f_x_accel = false; - f_x = false; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void glonass_t::string_1_t::_read() { - m_not_used = m__io->read_bits_int_be(2); - m_p1 = m__io->read_bits_int_be(2); - m_t_k = m__io->read_bits_int_be(12); - m_x_vel_sign = m__io->read_bits_int_be(1); - m_x_vel_value = m__io->read_bits_int_be(23); - m_x_accel_sign = m__io->read_bits_int_be(1); - m_x_accel_value = m__io->read_bits_int_be(4); - m_x_sign = m__io->read_bits_int_be(1); - m_x_value = m__io->read_bits_int_be(26); -} - -glonass_t::string_1_t::~string_1_t() { - _clean_up(); -} - -void glonass_t::string_1_t::_clean_up() { -} - -int32_t glonass_t::string_1_t::x_vel() { - if (f_x_vel) - return m_x_vel; - m_x_vel = ((x_vel_sign()) ? ((x_vel_value() * -1)) : (x_vel_value())); - f_x_vel = true; - return m_x_vel; -} - -int32_t glonass_t::string_1_t::x_accel() { - if (f_x_accel) - return m_x_accel; - m_x_accel = ((x_accel_sign()) ? ((x_accel_value() * -1)) : (x_accel_value())); - f_x_accel = true; - return m_x_accel; -} - -int32_t glonass_t::string_1_t::x() { - if (f_x) - return m_x; - m_x = ((x_sign()) ? ((x_value() * -1)) : (x_value())); - f_x = true; - return m_x; -} - -glonass_t::string_2_t::string_2_t(kaitai::kstream* p__io, glonass_t* p__parent, glonass_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - f_y_vel = false; - f_y_accel = false; - f_y = false; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void glonass_t::string_2_t::_read() { - m_b_n = m__io->read_bits_int_be(3); - m_p2 = m__io->read_bits_int_be(1); - m_t_b = m__io->read_bits_int_be(7); - m_not_used = m__io->read_bits_int_be(5); - m_y_vel_sign = m__io->read_bits_int_be(1); - m_y_vel_value = m__io->read_bits_int_be(23); - m_y_accel_sign = m__io->read_bits_int_be(1); - m_y_accel_value = m__io->read_bits_int_be(4); - m_y_sign = m__io->read_bits_int_be(1); - m_y_value = m__io->read_bits_int_be(26); -} - -glonass_t::string_2_t::~string_2_t() { - _clean_up(); -} - -void glonass_t::string_2_t::_clean_up() { -} - -int32_t glonass_t::string_2_t::y_vel() { - if (f_y_vel) - return m_y_vel; - m_y_vel = ((y_vel_sign()) ? ((y_vel_value() * -1)) : (y_vel_value())); - f_y_vel = true; - return m_y_vel; -} - -int32_t glonass_t::string_2_t::y_accel() { - if (f_y_accel) - return m_y_accel; - m_y_accel = ((y_accel_sign()) ? ((y_accel_value() * -1)) : (y_accel_value())); - f_y_accel = true; - return m_y_accel; -} - -int32_t glonass_t::string_2_t::y() { - if (f_y) - return m_y; - m_y = ((y_sign()) ? ((y_value() * -1)) : (y_value())); - f_y = true; - return m_y; -} - -glonass_t::string_3_t::string_3_t(kaitai::kstream* p__io, glonass_t* p__parent, glonass_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - f_gamma_n = false; - f_z_vel = false; - f_z_accel = false; - f_z = false; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void glonass_t::string_3_t::_read() { - m_p3 = m__io->read_bits_int_be(1); - m_gamma_n_sign = m__io->read_bits_int_be(1); - m_gamma_n_value = m__io->read_bits_int_be(10); - m_not_used = m__io->read_bits_int_be(1); - m_p = m__io->read_bits_int_be(2); - m_l_n = m__io->read_bits_int_be(1); - m_z_vel_sign = m__io->read_bits_int_be(1); - m_z_vel_value = m__io->read_bits_int_be(23); - m_z_accel_sign = m__io->read_bits_int_be(1); - m_z_accel_value = m__io->read_bits_int_be(4); - m_z_sign = m__io->read_bits_int_be(1); - m_z_value = m__io->read_bits_int_be(26); -} - -glonass_t::string_3_t::~string_3_t() { - _clean_up(); -} - -void glonass_t::string_3_t::_clean_up() { -} - -int32_t glonass_t::string_3_t::gamma_n() { - if (f_gamma_n) - return m_gamma_n; - m_gamma_n = ((gamma_n_sign()) ? ((gamma_n_value() * -1)) : (gamma_n_value())); - f_gamma_n = true; - return m_gamma_n; -} - -int32_t glonass_t::string_3_t::z_vel() { - if (f_z_vel) - return m_z_vel; - m_z_vel = ((z_vel_sign()) ? ((z_vel_value() * -1)) : (z_vel_value())); - f_z_vel = true; - return m_z_vel; -} - -int32_t glonass_t::string_3_t::z_accel() { - if (f_z_accel) - return m_z_accel; - m_z_accel = ((z_accel_sign()) ? ((z_accel_value() * -1)) : (z_accel_value())); - f_z_accel = true; - return m_z_accel; -} - -int32_t glonass_t::string_3_t::z() { - if (f_z) - return m_z; - m_z = ((z_sign()) ? ((z_value() * -1)) : (z_value())); - f_z = true; - return m_z; -} diff --git a/system/ubloxd/generated/glonass.h b/system/ubloxd/generated/glonass.h deleted file mode 100644 index 19867ba22b..0000000000 --- a/system/ubloxd/generated/glonass.h +++ /dev/null @@ -1,375 +0,0 @@ -#ifndef GLONASS_H_ -#define GLONASS_H_ - -// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild - -#include "kaitai/kaitaistruct.h" -#include - -#if KAITAI_STRUCT_VERSION < 9000L -#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required" -#endif - -class glonass_t : public kaitai::kstruct { - -public: - class string_4_t; - class string_non_immediate_t; - class string_5_t; - class string_1_t; - class string_2_t; - class string_3_t; - - glonass_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, glonass_t* p__root = 0); - -private: - void _read(); - void _clean_up(); - -public: - ~glonass_t(); - - class string_4_t : public kaitai::kstruct { - - public: - - string_4_t(kaitai::kstream* p__io, glonass_t* p__parent = 0, glonass_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~string_4_t(); - - private: - bool f_tau_n; - int32_t m_tau_n; - - public: - int32_t tau_n(); - - private: - bool f_delta_tau_n; - int32_t m_delta_tau_n; - - public: - int32_t delta_tau_n(); - - private: - bool m_tau_n_sign; - uint64_t m_tau_n_value; - bool m_delta_tau_n_sign; - uint64_t m_delta_tau_n_value; - uint64_t m_e_n; - uint64_t m_not_used_1; - bool m_p4; - uint64_t m_f_t; - uint64_t m_not_used_2; - uint64_t m_n_t; - uint64_t m_n; - uint64_t m_m; - glonass_t* m__root; - glonass_t* m__parent; - - public: - bool tau_n_sign() const { return m_tau_n_sign; } - uint64_t tau_n_value() const { return m_tau_n_value; } - bool delta_tau_n_sign() const { return m_delta_tau_n_sign; } - uint64_t delta_tau_n_value() const { return m_delta_tau_n_value; } - uint64_t e_n() const { return m_e_n; } - uint64_t not_used_1() const { return m_not_used_1; } - bool p4() const { return m_p4; } - uint64_t f_t() const { return m_f_t; } - uint64_t not_used_2() const { return m_not_used_2; } - uint64_t n_t() const { return m_n_t; } - uint64_t n() const { return m_n; } - uint64_t m() const { return m_m; } - glonass_t* _root() const { return m__root; } - glonass_t* _parent() const { return m__parent; } - }; - - class string_non_immediate_t : public kaitai::kstruct { - - public: - - string_non_immediate_t(kaitai::kstream* p__io, glonass_t* p__parent = 0, glonass_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~string_non_immediate_t(); - - private: - uint64_t m_data_1; - uint64_t m_data_2; - glonass_t* m__root; - glonass_t* m__parent; - - public: - uint64_t data_1() const { return m_data_1; } - uint64_t data_2() const { return m_data_2; } - glonass_t* _root() const { return m__root; } - glonass_t* _parent() const { return m__parent; } - }; - - class string_5_t : public kaitai::kstruct { - - public: - - string_5_t(kaitai::kstream* p__io, glonass_t* p__parent = 0, glonass_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~string_5_t(); - - private: - uint64_t m_n_a; - uint64_t m_tau_c; - bool m_not_used; - uint64_t m_n_4; - uint64_t m_tau_gps; - bool m_l_n; - glonass_t* m__root; - glonass_t* m__parent; - - public: - uint64_t n_a() const { return m_n_a; } - uint64_t tau_c() const { return m_tau_c; } - bool not_used() const { return m_not_used; } - uint64_t n_4() const { return m_n_4; } - uint64_t tau_gps() const { return m_tau_gps; } - bool l_n() const { return m_l_n; } - glonass_t* _root() const { return m__root; } - glonass_t* _parent() const { return m__parent; } - }; - - class string_1_t : public kaitai::kstruct { - - public: - - string_1_t(kaitai::kstream* p__io, glonass_t* p__parent = 0, glonass_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~string_1_t(); - - private: - bool f_x_vel; - int32_t m_x_vel; - - public: - int32_t x_vel(); - - private: - bool f_x_accel; - int32_t m_x_accel; - - public: - int32_t x_accel(); - - private: - bool f_x; - int32_t m_x; - - public: - int32_t x(); - - private: - uint64_t m_not_used; - uint64_t m_p1; - uint64_t m_t_k; - bool m_x_vel_sign; - uint64_t m_x_vel_value; - bool m_x_accel_sign; - uint64_t m_x_accel_value; - bool m_x_sign; - uint64_t m_x_value; - glonass_t* m__root; - glonass_t* m__parent; - - public: - uint64_t not_used() const { return m_not_used; } - uint64_t p1() const { return m_p1; } - uint64_t t_k() const { return m_t_k; } - bool x_vel_sign() const { return m_x_vel_sign; } - uint64_t x_vel_value() const { return m_x_vel_value; } - bool x_accel_sign() const { return m_x_accel_sign; } - uint64_t x_accel_value() const { return m_x_accel_value; } - bool x_sign() const { return m_x_sign; } - uint64_t x_value() const { return m_x_value; } - glonass_t* _root() const { return m__root; } - glonass_t* _parent() const { return m__parent; } - }; - - class string_2_t : public kaitai::kstruct { - - public: - - string_2_t(kaitai::kstream* p__io, glonass_t* p__parent = 0, glonass_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~string_2_t(); - - private: - bool f_y_vel; - int32_t m_y_vel; - - public: - int32_t y_vel(); - - private: - bool f_y_accel; - int32_t m_y_accel; - - public: - int32_t y_accel(); - - private: - bool f_y; - int32_t m_y; - - public: - int32_t y(); - - private: - uint64_t m_b_n; - bool m_p2; - uint64_t m_t_b; - uint64_t m_not_used; - bool m_y_vel_sign; - uint64_t m_y_vel_value; - bool m_y_accel_sign; - uint64_t m_y_accel_value; - bool m_y_sign; - uint64_t m_y_value; - glonass_t* m__root; - glonass_t* m__parent; - - public: - uint64_t b_n() const { return m_b_n; } - bool p2() const { return m_p2; } - uint64_t t_b() const { return m_t_b; } - uint64_t not_used() const { return m_not_used; } - bool y_vel_sign() const { return m_y_vel_sign; } - uint64_t y_vel_value() const { return m_y_vel_value; } - bool y_accel_sign() const { return m_y_accel_sign; } - uint64_t y_accel_value() const { return m_y_accel_value; } - bool y_sign() const { return m_y_sign; } - uint64_t y_value() const { return m_y_value; } - glonass_t* _root() const { return m__root; } - glonass_t* _parent() const { return m__parent; } - }; - - class string_3_t : public kaitai::kstruct { - - public: - - string_3_t(kaitai::kstream* p__io, glonass_t* p__parent = 0, glonass_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~string_3_t(); - - private: - bool f_gamma_n; - int32_t m_gamma_n; - - public: - int32_t gamma_n(); - - private: - bool f_z_vel; - int32_t m_z_vel; - - public: - int32_t z_vel(); - - private: - bool f_z_accel; - int32_t m_z_accel; - - public: - int32_t z_accel(); - - private: - bool f_z; - int32_t m_z; - - public: - int32_t z(); - - private: - bool m_p3; - bool m_gamma_n_sign; - uint64_t m_gamma_n_value; - bool m_not_used; - uint64_t m_p; - bool m_l_n; - bool m_z_vel_sign; - uint64_t m_z_vel_value; - bool m_z_accel_sign; - uint64_t m_z_accel_value; - bool m_z_sign; - uint64_t m_z_value; - glonass_t* m__root; - glonass_t* m__parent; - - public: - bool p3() const { return m_p3; } - bool gamma_n_sign() const { return m_gamma_n_sign; } - uint64_t gamma_n_value() const { return m_gamma_n_value; } - bool not_used() const { return m_not_used; } - uint64_t p() const { return m_p; } - bool l_n() const { return m_l_n; } - bool z_vel_sign() const { return m_z_vel_sign; } - uint64_t z_vel_value() const { return m_z_vel_value; } - bool z_accel_sign() const { return m_z_accel_sign; } - uint64_t z_accel_value() const { return m_z_accel_value; } - bool z_sign() const { return m_z_sign; } - uint64_t z_value() const { return m_z_value; } - glonass_t* _root() const { return m__root; } - glonass_t* _parent() const { return m__parent; } - }; - -private: - bool m_idle_chip; - uint64_t m_string_number; - kaitai::kstruct* m_data; - uint64_t m_hamming_code; - uint64_t m_pad_1; - uint64_t m_superframe_number; - uint64_t m_pad_2; - uint64_t m_frame_number; - glonass_t* m__root; - kaitai::kstruct* m__parent; - -public: - bool idle_chip() const { return m_idle_chip; } - uint64_t string_number() const { return m_string_number; } - kaitai::kstruct* data() const { return m_data; } - uint64_t hamming_code() const { return m_hamming_code; } - uint64_t pad_1() const { return m_pad_1; } - uint64_t superframe_number() const { return m_superframe_number; } - uint64_t pad_2() const { return m_pad_2; } - uint64_t frame_number() const { return m_frame_number; } - glonass_t* _root() const { return m__root; } - kaitai::kstruct* _parent() const { return m__parent; } -}; - -#endif // GLONASS_H_ diff --git a/system/ubloxd/generated/glonass.py b/system/ubloxd/generated/glonass.py new file mode 100644 index 0000000000..40aa16bb6f --- /dev/null +++ b/system/ubloxd/generated/glonass.py @@ -0,0 +1,247 @@ +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +import kaitaistruct +from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO + + +if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 9): + raise Exception("Incompatible Kaitai Struct Python API: 0.9 or later is required, but you have %s" % (kaitaistruct.__version__)) + +class Glonass(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.idle_chip = self._io.read_bits_int_be(1) != 0 + self.string_number = self._io.read_bits_int_be(4) + # workaround for kaitai bit alignment issue (see glonass_fix.patch for C++) + # self._io.align_to_byte() + _on = self.string_number + if _on == 4: + self.data = Glonass.String4(self._io, self, self._root) + elif _on == 1: + self.data = Glonass.String1(self._io, self, self._root) + elif _on == 3: + self.data = Glonass.String3(self._io, self, self._root) + elif _on == 5: + self.data = Glonass.String5(self._io, self, self._root) + elif _on == 2: + self.data = Glonass.String2(self._io, self, self._root) + else: + self.data = Glonass.StringNonImmediate(self._io, self, self._root) + self.hamming_code = self._io.read_bits_int_be(8) + self.pad_1 = self._io.read_bits_int_be(11) + self.superframe_number = self._io.read_bits_int_be(16) + self.pad_2 = self._io.read_bits_int_be(8) + self.frame_number = self._io.read_bits_int_be(8) + + class String4(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.tau_n_sign = self._io.read_bits_int_be(1) != 0 + self.tau_n_value = self._io.read_bits_int_be(21) + self.delta_tau_n_sign = self._io.read_bits_int_be(1) != 0 + self.delta_tau_n_value = self._io.read_bits_int_be(4) + self.e_n = self._io.read_bits_int_be(5) + self.not_used_1 = self._io.read_bits_int_be(14) + self.p4 = self._io.read_bits_int_be(1) != 0 + self.f_t = self._io.read_bits_int_be(4) + self.not_used_2 = self._io.read_bits_int_be(3) + self.n_t = self._io.read_bits_int_be(11) + self.n = self._io.read_bits_int_be(5) + self.m = self._io.read_bits_int_be(2) + + @property + def tau_n(self): + if hasattr(self, '_m_tau_n'): + return self._m_tau_n + + self._m_tau_n = ((self.tau_n_value * -1) if self.tau_n_sign else self.tau_n_value) + return getattr(self, '_m_tau_n', None) + + @property + def delta_tau_n(self): + if hasattr(self, '_m_delta_tau_n'): + return self._m_delta_tau_n + + self._m_delta_tau_n = ((self.delta_tau_n_value * -1) if self.delta_tau_n_sign else self.delta_tau_n_value) + return getattr(self, '_m_delta_tau_n', None) + + + class StringNonImmediate(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.data_1 = self._io.read_bits_int_be(64) + self.data_2 = self._io.read_bits_int_be(8) + + + class String5(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.n_a = self._io.read_bits_int_be(11) + self.tau_c = self._io.read_bits_int_be(32) + self.not_used = self._io.read_bits_int_be(1) != 0 + self.n_4 = self._io.read_bits_int_be(5) + self.tau_gps = self._io.read_bits_int_be(22) + self.l_n = self._io.read_bits_int_be(1) != 0 + + + class String1(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.not_used = self._io.read_bits_int_be(2) + self.p1 = self._io.read_bits_int_be(2) + self.t_k = self._io.read_bits_int_be(12) + self.x_vel_sign = self._io.read_bits_int_be(1) != 0 + self.x_vel_value = self._io.read_bits_int_be(23) + self.x_accel_sign = self._io.read_bits_int_be(1) != 0 + self.x_accel_value = self._io.read_bits_int_be(4) + self.x_sign = self._io.read_bits_int_be(1) != 0 + self.x_value = self._io.read_bits_int_be(26) + + @property + def x_vel(self): + if hasattr(self, '_m_x_vel'): + return self._m_x_vel + + self._m_x_vel = ((self.x_vel_value * -1) if self.x_vel_sign else self.x_vel_value) + return getattr(self, '_m_x_vel', None) + + @property + def x_accel(self): + if hasattr(self, '_m_x_accel'): + return self._m_x_accel + + self._m_x_accel = ((self.x_accel_value * -1) if self.x_accel_sign else self.x_accel_value) + return getattr(self, '_m_x_accel', None) + + @property + def x(self): + if hasattr(self, '_m_x'): + return self._m_x + + self._m_x = ((self.x_value * -1) if self.x_sign else self.x_value) + return getattr(self, '_m_x', None) + + + class String2(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.b_n = self._io.read_bits_int_be(3) + self.p2 = self._io.read_bits_int_be(1) != 0 + self.t_b = self._io.read_bits_int_be(7) + self.not_used = self._io.read_bits_int_be(5) + self.y_vel_sign = self._io.read_bits_int_be(1) != 0 + self.y_vel_value = self._io.read_bits_int_be(23) + self.y_accel_sign = self._io.read_bits_int_be(1) != 0 + self.y_accel_value = self._io.read_bits_int_be(4) + self.y_sign = self._io.read_bits_int_be(1) != 0 + self.y_value = self._io.read_bits_int_be(26) + + @property + def y_vel(self): + if hasattr(self, '_m_y_vel'): + return self._m_y_vel + + self._m_y_vel = ((self.y_vel_value * -1) if self.y_vel_sign else self.y_vel_value) + return getattr(self, '_m_y_vel', None) + + @property + def y_accel(self): + if hasattr(self, '_m_y_accel'): + return self._m_y_accel + + self._m_y_accel = ((self.y_accel_value * -1) if self.y_accel_sign else self.y_accel_value) + return getattr(self, '_m_y_accel', None) + + @property + def y(self): + if hasattr(self, '_m_y'): + return self._m_y + + self._m_y = ((self.y_value * -1) if self.y_sign else self.y_value) + return getattr(self, '_m_y', None) + + + class String3(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.p3 = self._io.read_bits_int_be(1) != 0 + self.gamma_n_sign = self._io.read_bits_int_be(1) != 0 + self.gamma_n_value = self._io.read_bits_int_be(10) + self.not_used = self._io.read_bits_int_be(1) != 0 + self.p = self._io.read_bits_int_be(2) + self.l_n = self._io.read_bits_int_be(1) != 0 + self.z_vel_sign = self._io.read_bits_int_be(1) != 0 + self.z_vel_value = self._io.read_bits_int_be(23) + self.z_accel_sign = self._io.read_bits_int_be(1) != 0 + self.z_accel_value = self._io.read_bits_int_be(4) + self.z_sign = self._io.read_bits_int_be(1) != 0 + self.z_value = self._io.read_bits_int_be(26) + + @property + def gamma_n(self): + if hasattr(self, '_m_gamma_n'): + return self._m_gamma_n + + self._m_gamma_n = ((self.gamma_n_value * -1) if self.gamma_n_sign else self.gamma_n_value) + return getattr(self, '_m_gamma_n', None) + + @property + def z_vel(self): + if hasattr(self, '_m_z_vel'): + return self._m_z_vel + + self._m_z_vel = ((self.z_vel_value * -1) if self.z_vel_sign else self.z_vel_value) + return getattr(self, '_m_z_vel', None) + + @property + def z_accel(self): + if hasattr(self, '_m_z_accel'): + return self._m_z_accel + + self._m_z_accel = ((self.z_accel_value * -1) if self.z_accel_sign else self.z_accel_value) + return getattr(self, '_m_z_accel', None) + + @property + def z(self): + if hasattr(self, '_m_z'): + return self._m_z + + self._m_z = ((self.z_value * -1) if self.z_sign else self.z_value) + return getattr(self, '_m_z', None) + + diff --git a/system/ubloxd/generated/gps.cpp b/system/ubloxd/generated/gps.cpp deleted file mode 100644 index 8e1cb85b95..0000000000 --- a/system/ubloxd/generated/gps.cpp +++ /dev/null @@ -1,325 +0,0 @@ -// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild - -#include "gps.h" -#include "kaitai/exceptions.h" - -gps_t::gps_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, gps_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = this; - m_tlm = 0; - m_how = 0; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void gps_t::_read() { - m_tlm = new tlm_t(m__io, this, m__root); - m_how = new how_t(m__io, this, m__root); - n_body = true; - switch (how()->subframe_id()) { - case 1: { - n_body = false; - m_body = new subframe_1_t(m__io, this, m__root); - break; - } - case 2: { - n_body = false; - m_body = new subframe_2_t(m__io, this, m__root); - break; - } - case 3: { - n_body = false; - m_body = new subframe_3_t(m__io, this, m__root); - break; - } - case 4: { - n_body = false; - m_body = new subframe_4_t(m__io, this, m__root); - break; - } - } -} - -gps_t::~gps_t() { - _clean_up(); -} - -void gps_t::_clean_up() { - if (m_tlm) { - delete m_tlm; m_tlm = 0; - } - if (m_how) { - delete m_how; m_how = 0; - } - if (!n_body) { - if (m_body) { - delete m_body; m_body = 0; - } - } -} - -gps_t::subframe_1_t::subframe_1_t(kaitai::kstream* p__io, gps_t* p__parent, gps_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - f_af_0 = false; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void gps_t::subframe_1_t::_read() { - m_week_no = m__io->read_bits_int_be(10); - m_code = m__io->read_bits_int_be(2); - m_sv_accuracy = m__io->read_bits_int_be(4); - m_sv_health = m__io->read_bits_int_be(6); - m_iodc_msb = m__io->read_bits_int_be(2); - m_l2_p_data_flag = m__io->read_bits_int_be(1); - m_reserved1 = m__io->read_bits_int_be(23); - m_reserved2 = m__io->read_bits_int_be(24); - m_reserved3 = m__io->read_bits_int_be(24); - m_reserved4 = m__io->read_bits_int_be(16); - m__io->align_to_byte(); - m_t_gd = m__io->read_s1(); - m_iodc_lsb = m__io->read_u1(); - m_t_oc = m__io->read_u2be(); - m_af_2 = m__io->read_s1(); - m_af_1 = m__io->read_s2be(); - m_af_0_sign = m__io->read_bits_int_be(1); - m_af_0_value = m__io->read_bits_int_be(21); - m_reserved5 = m__io->read_bits_int_be(2); -} - -gps_t::subframe_1_t::~subframe_1_t() { - _clean_up(); -} - -void gps_t::subframe_1_t::_clean_up() { -} - -int32_t gps_t::subframe_1_t::af_0() { - if (f_af_0) - return m_af_0; - m_af_0 = ((af_0_sign()) ? ((af_0_value() - (1 << 21))) : (af_0_value())); - f_af_0 = true; - return m_af_0; -} - -gps_t::subframe_3_t::subframe_3_t(kaitai::kstream* p__io, gps_t* p__parent, gps_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - f_omega_dot = false; - f_idot = false; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void gps_t::subframe_3_t::_read() { - m_c_ic = m__io->read_s2be(); - m_omega_0 = m__io->read_s4be(); - m_c_is = m__io->read_s2be(); - m_i_0 = m__io->read_s4be(); - m_c_rc = m__io->read_s2be(); - m_omega = m__io->read_s4be(); - m_omega_dot_sign = m__io->read_bits_int_be(1); - m_omega_dot_value = m__io->read_bits_int_be(23); - m__io->align_to_byte(); - m_iode = m__io->read_u1(); - m_idot_sign = m__io->read_bits_int_be(1); - m_idot_value = m__io->read_bits_int_be(13); - m_reserved = m__io->read_bits_int_be(2); -} - -gps_t::subframe_3_t::~subframe_3_t() { - _clean_up(); -} - -void gps_t::subframe_3_t::_clean_up() { -} - -int32_t gps_t::subframe_3_t::omega_dot() { - if (f_omega_dot) - return m_omega_dot; - m_omega_dot = ((omega_dot_sign()) ? ((omega_dot_value() - (1 << 23))) : (omega_dot_value())); - f_omega_dot = true; - return m_omega_dot; -} - -int32_t gps_t::subframe_3_t::idot() { - if (f_idot) - return m_idot; - m_idot = ((idot_sign()) ? ((idot_value() - (1 << 13))) : (idot_value())); - f_idot = true; - return m_idot; -} - -gps_t::subframe_4_t::subframe_4_t(kaitai::kstream* p__io, gps_t* p__parent, gps_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void gps_t::subframe_4_t::_read() { - m_data_id = m__io->read_bits_int_be(2); - m_page_id = m__io->read_bits_int_be(6); - m__io->align_to_byte(); - n_body = true; - switch (page_id()) { - case 56: { - n_body = false; - m_body = new ionosphere_data_t(m__io, this, m__root); - break; - } - } -} - -gps_t::subframe_4_t::~subframe_4_t() { - _clean_up(); -} - -void gps_t::subframe_4_t::_clean_up() { - if (!n_body) { - if (m_body) { - delete m_body; m_body = 0; - } - } -} - -gps_t::subframe_4_t::ionosphere_data_t::ionosphere_data_t(kaitai::kstream* p__io, gps_t::subframe_4_t* p__parent, gps_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void gps_t::subframe_4_t::ionosphere_data_t::_read() { - m_a0 = m__io->read_s1(); - m_a1 = m__io->read_s1(); - m_a2 = m__io->read_s1(); - m_a3 = m__io->read_s1(); - m_b0 = m__io->read_s1(); - m_b1 = m__io->read_s1(); - m_b2 = m__io->read_s1(); - m_b3 = m__io->read_s1(); -} - -gps_t::subframe_4_t::ionosphere_data_t::~ionosphere_data_t() { - _clean_up(); -} - -void gps_t::subframe_4_t::ionosphere_data_t::_clean_up() { -} - -gps_t::how_t::how_t(kaitai::kstream* p__io, gps_t* p__parent, gps_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void gps_t::how_t::_read() { - m_tow_count = m__io->read_bits_int_be(17); - m_alert = m__io->read_bits_int_be(1); - m_anti_spoof = m__io->read_bits_int_be(1); - m_subframe_id = m__io->read_bits_int_be(3); - m_reserved = m__io->read_bits_int_be(2); -} - -gps_t::how_t::~how_t() { - _clean_up(); -} - -void gps_t::how_t::_clean_up() { -} - -gps_t::tlm_t::tlm_t(kaitai::kstream* p__io, gps_t* p__parent, gps_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void gps_t::tlm_t::_read() { - m_preamble = m__io->read_bytes(1); - if (!(preamble() == std::string("\x8B", 1))) { - throw kaitai::validation_not_equal_error(std::string("\x8B", 1), preamble(), _io(), std::string("/types/tlm/seq/0")); - } - m_tlm = m__io->read_bits_int_be(14); - m_integrity_status = m__io->read_bits_int_be(1); - m_reserved = m__io->read_bits_int_be(1); -} - -gps_t::tlm_t::~tlm_t() { - _clean_up(); -} - -void gps_t::tlm_t::_clean_up() { -} - -gps_t::subframe_2_t::subframe_2_t(kaitai::kstream* p__io, gps_t* p__parent, gps_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void gps_t::subframe_2_t::_read() { - m_iode = m__io->read_u1(); - m_c_rs = m__io->read_s2be(); - m_delta_n = m__io->read_s2be(); - m_m_0 = m__io->read_s4be(); - m_c_uc = m__io->read_s2be(); - m_e = m__io->read_s4be(); - m_c_us = m__io->read_s2be(); - m_sqrt_a = m__io->read_u4be(); - m_t_oe = m__io->read_u2be(); - m_fit_interval_flag = m__io->read_bits_int_be(1); - m_aoda = m__io->read_bits_int_be(5); - m_reserved = m__io->read_bits_int_be(2); -} - -gps_t::subframe_2_t::~subframe_2_t() { - _clean_up(); -} - -void gps_t::subframe_2_t::_clean_up() { -} diff --git a/system/ubloxd/generated/gps.h b/system/ubloxd/generated/gps.h deleted file mode 100644 index 9dfc5031f5..0000000000 --- a/system/ubloxd/generated/gps.h +++ /dev/null @@ -1,359 +0,0 @@ -#ifndef GPS_H_ -#define GPS_H_ - -// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild - -#include "kaitai/kaitaistruct.h" -#include - -#if KAITAI_STRUCT_VERSION < 9000L -#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required" -#endif - -class gps_t : public kaitai::kstruct { - -public: - class subframe_1_t; - class subframe_3_t; - class subframe_4_t; - class how_t; - class tlm_t; - class subframe_2_t; - - gps_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, gps_t* p__root = 0); - -private: - void _read(); - void _clean_up(); - -public: - ~gps_t(); - - class subframe_1_t : public kaitai::kstruct { - - public: - - subframe_1_t(kaitai::kstream* p__io, gps_t* p__parent = 0, gps_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~subframe_1_t(); - - private: - bool f_af_0; - int32_t m_af_0; - - public: - int32_t af_0(); - - private: - uint64_t m_week_no; - uint64_t m_code; - uint64_t m_sv_accuracy; - uint64_t m_sv_health; - uint64_t m_iodc_msb; - bool m_l2_p_data_flag; - uint64_t m_reserved1; - uint64_t m_reserved2; - uint64_t m_reserved3; - uint64_t m_reserved4; - int8_t m_t_gd; - uint8_t m_iodc_lsb; - uint16_t m_t_oc; - int8_t m_af_2; - int16_t m_af_1; - bool m_af_0_sign; - uint64_t m_af_0_value; - uint64_t m_reserved5; - gps_t* m__root; - gps_t* m__parent; - - public: - uint64_t week_no() const { return m_week_no; } - uint64_t code() const { return m_code; } - uint64_t sv_accuracy() const { return m_sv_accuracy; } - uint64_t sv_health() const { return m_sv_health; } - uint64_t iodc_msb() const { return m_iodc_msb; } - bool l2_p_data_flag() const { return m_l2_p_data_flag; } - uint64_t reserved1() const { return m_reserved1; } - uint64_t reserved2() const { return m_reserved2; } - uint64_t reserved3() const { return m_reserved3; } - uint64_t reserved4() const { return m_reserved4; } - int8_t t_gd() const { return m_t_gd; } - uint8_t iodc_lsb() const { return m_iodc_lsb; } - uint16_t t_oc() const { return m_t_oc; } - int8_t af_2() const { return m_af_2; } - int16_t af_1() const { return m_af_1; } - bool af_0_sign() const { return m_af_0_sign; } - uint64_t af_0_value() const { return m_af_0_value; } - uint64_t reserved5() const { return m_reserved5; } - gps_t* _root() const { return m__root; } - gps_t* _parent() const { return m__parent; } - }; - - class subframe_3_t : public kaitai::kstruct { - - public: - - subframe_3_t(kaitai::kstream* p__io, gps_t* p__parent = 0, gps_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~subframe_3_t(); - - private: - bool f_omega_dot; - int32_t m_omega_dot; - - public: - int32_t omega_dot(); - - private: - bool f_idot; - int32_t m_idot; - - public: - int32_t idot(); - - private: - int16_t m_c_ic; - int32_t m_omega_0; - int16_t m_c_is; - int32_t m_i_0; - int16_t m_c_rc; - int32_t m_omega; - bool m_omega_dot_sign; - uint64_t m_omega_dot_value; - uint8_t m_iode; - bool m_idot_sign; - uint64_t m_idot_value; - uint64_t m_reserved; - gps_t* m__root; - gps_t* m__parent; - - public: - int16_t c_ic() const { return m_c_ic; } - int32_t omega_0() const { return m_omega_0; } - int16_t c_is() const { return m_c_is; } - int32_t i_0() const { return m_i_0; } - int16_t c_rc() const { return m_c_rc; } - int32_t omega() const { return m_omega; } - bool omega_dot_sign() const { return m_omega_dot_sign; } - uint64_t omega_dot_value() const { return m_omega_dot_value; } - uint8_t iode() const { return m_iode; } - bool idot_sign() const { return m_idot_sign; } - uint64_t idot_value() const { return m_idot_value; } - uint64_t reserved() const { return m_reserved; } - gps_t* _root() const { return m__root; } - gps_t* _parent() const { return m__parent; } - }; - - class subframe_4_t : public kaitai::kstruct { - - public: - class ionosphere_data_t; - - subframe_4_t(kaitai::kstream* p__io, gps_t* p__parent = 0, gps_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~subframe_4_t(); - - class ionosphere_data_t : public kaitai::kstruct { - - public: - - ionosphere_data_t(kaitai::kstream* p__io, gps_t::subframe_4_t* p__parent = 0, gps_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~ionosphere_data_t(); - - private: - int8_t m_a0; - int8_t m_a1; - int8_t m_a2; - int8_t m_a3; - int8_t m_b0; - int8_t m_b1; - int8_t m_b2; - int8_t m_b3; - gps_t* m__root; - gps_t::subframe_4_t* m__parent; - - public: - int8_t a0() const { return m_a0; } - int8_t a1() const { return m_a1; } - int8_t a2() const { return m_a2; } - int8_t a3() const { return m_a3; } - int8_t b0() const { return m_b0; } - int8_t b1() const { return m_b1; } - int8_t b2() const { return m_b2; } - int8_t b3() const { return m_b3; } - gps_t* _root() const { return m__root; } - gps_t::subframe_4_t* _parent() const { return m__parent; } - }; - - private: - uint64_t m_data_id; - uint64_t m_page_id; - ionosphere_data_t* m_body; - bool n_body; - - public: - bool _is_null_body() { body(); return n_body; }; - - private: - gps_t* m__root; - gps_t* m__parent; - - public: - uint64_t data_id() const { return m_data_id; } - uint64_t page_id() const { return m_page_id; } - ionosphere_data_t* body() const { return m_body; } - gps_t* _root() const { return m__root; } - gps_t* _parent() const { return m__parent; } - }; - - class how_t : public kaitai::kstruct { - - public: - - how_t(kaitai::kstream* p__io, gps_t* p__parent = 0, gps_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~how_t(); - - private: - uint64_t m_tow_count; - bool m_alert; - bool m_anti_spoof; - uint64_t m_subframe_id; - uint64_t m_reserved; - gps_t* m__root; - gps_t* m__parent; - - public: - uint64_t tow_count() const { return m_tow_count; } - bool alert() const { return m_alert; } - bool anti_spoof() const { return m_anti_spoof; } - uint64_t subframe_id() const { return m_subframe_id; } - uint64_t reserved() const { return m_reserved; } - gps_t* _root() const { return m__root; } - gps_t* _parent() const { return m__parent; } - }; - - class tlm_t : public kaitai::kstruct { - - public: - - tlm_t(kaitai::kstream* p__io, gps_t* p__parent = 0, gps_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~tlm_t(); - - private: - std::string m_preamble; - uint64_t m_tlm; - bool m_integrity_status; - bool m_reserved; - gps_t* m__root; - gps_t* m__parent; - - public: - std::string preamble() const { return m_preamble; } - uint64_t tlm() const { return m_tlm; } - bool integrity_status() const { return m_integrity_status; } - bool reserved() const { return m_reserved; } - gps_t* _root() const { return m__root; } - gps_t* _parent() const { return m__parent; } - }; - - class subframe_2_t : public kaitai::kstruct { - - public: - - subframe_2_t(kaitai::kstream* p__io, gps_t* p__parent = 0, gps_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~subframe_2_t(); - - private: - uint8_t m_iode; - int16_t m_c_rs; - int16_t m_delta_n; - int32_t m_m_0; - int16_t m_c_uc; - int32_t m_e; - int16_t m_c_us; - uint32_t m_sqrt_a; - uint16_t m_t_oe; - bool m_fit_interval_flag; - uint64_t m_aoda; - uint64_t m_reserved; - gps_t* m__root; - gps_t* m__parent; - - public: - uint8_t iode() const { return m_iode; } - int16_t c_rs() const { return m_c_rs; } - int16_t delta_n() const { return m_delta_n; } - int32_t m_0() const { return m_m_0; } - int16_t c_uc() const { return m_c_uc; } - int32_t e() const { return m_e; } - int16_t c_us() const { return m_c_us; } - uint32_t sqrt_a() const { return m_sqrt_a; } - uint16_t t_oe() const { return m_t_oe; } - bool fit_interval_flag() const { return m_fit_interval_flag; } - uint64_t aoda() const { return m_aoda; } - uint64_t reserved() const { return m_reserved; } - gps_t* _root() const { return m__root; } - gps_t* _parent() const { return m__parent; } - }; - -private: - tlm_t* m_tlm; - how_t* m_how; - kaitai::kstruct* m_body; - bool n_body; - -public: - bool _is_null_body() { body(); return n_body; }; - -private: - gps_t* m__root; - kaitai::kstruct* m__parent; - -public: - tlm_t* tlm() const { return m_tlm; } - how_t* how() const { return m_how; } - kaitai::kstruct* body() const { return m_body; } - gps_t* _root() const { return m__root; } - kaitai::kstruct* _parent() const { return m__parent; } -}; - -#endif // GPS_H_ diff --git a/system/ubloxd/generated/gps.py b/system/ubloxd/generated/gps.py new file mode 100644 index 0000000000..a999016f3e --- /dev/null +++ b/system/ubloxd/generated/gps.py @@ -0,0 +1,193 @@ +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +import kaitaistruct +from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO + + +if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 9): + raise Exception("Incompatible Kaitai Struct Python API: 0.9 or later is required, but you have %s" % (kaitaistruct.__version__)) + +class Gps(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.tlm = Gps.Tlm(self._io, self, self._root) + self.how = Gps.How(self._io, self, self._root) + _on = self.how.subframe_id + if _on == 1: + self.body = Gps.Subframe1(self._io, self, self._root) + elif _on == 2: + self.body = Gps.Subframe2(self._io, self, self._root) + elif _on == 3: + self.body = Gps.Subframe3(self._io, self, self._root) + elif _on == 4: + self.body = Gps.Subframe4(self._io, self, self._root) + + class Subframe1(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.week_no = self._io.read_bits_int_be(10) + self.code = self._io.read_bits_int_be(2) + self.sv_accuracy = self._io.read_bits_int_be(4) + self.sv_health = self._io.read_bits_int_be(6) + self.iodc_msb = self._io.read_bits_int_be(2) + self.l2_p_data_flag = self._io.read_bits_int_be(1) != 0 + self.reserved1 = self._io.read_bits_int_be(23) + self.reserved2 = self._io.read_bits_int_be(24) + self.reserved3 = self._io.read_bits_int_be(24) + self.reserved4 = self._io.read_bits_int_be(16) + self._io.align_to_byte() + self.t_gd = self._io.read_s1() + self.iodc_lsb = self._io.read_u1() + self.t_oc = self._io.read_u2be() + self.af_2 = self._io.read_s1() + self.af_1 = self._io.read_s2be() + self.af_0_sign = self._io.read_bits_int_be(1) != 0 + self.af_0_value = self._io.read_bits_int_be(21) + self.reserved5 = self._io.read_bits_int_be(2) + + @property + def af_0(self): + if hasattr(self, '_m_af_0'): + return self._m_af_0 + + self._m_af_0 = ((self.af_0_value - (1 << 21)) if self.af_0_sign else self.af_0_value) + return getattr(self, '_m_af_0', None) + + + class Subframe3(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.c_ic = self._io.read_s2be() + self.omega_0 = self._io.read_s4be() + self.c_is = self._io.read_s2be() + self.i_0 = self._io.read_s4be() + self.c_rc = self._io.read_s2be() + self.omega = self._io.read_s4be() + self.omega_dot_sign = self._io.read_bits_int_be(1) != 0 + self.omega_dot_value = self._io.read_bits_int_be(23) + self._io.align_to_byte() + self.iode = self._io.read_u1() + self.idot_sign = self._io.read_bits_int_be(1) != 0 + self.idot_value = self._io.read_bits_int_be(13) + self.reserved = self._io.read_bits_int_be(2) + + @property + def omega_dot(self): + if hasattr(self, '_m_omega_dot'): + return self._m_omega_dot + + self._m_omega_dot = ((self.omega_dot_value - (1 << 23)) if self.omega_dot_sign else self.omega_dot_value) + return getattr(self, '_m_omega_dot', None) + + @property + def idot(self): + if hasattr(self, '_m_idot'): + return self._m_idot + + self._m_idot = ((self.idot_value - (1 << 13)) if self.idot_sign else self.idot_value) + return getattr(self, '_m_idot', None) + + + class Subframe4(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.data_id = self._io.read_bits_int_be(2) + self.page_id = self._io.read_bits_int_be(6) + self._io.align_to_byte() + _on = self.page_id + if _on == 56: + self.body = Gps.Subframe4.IonosphereData(self._io, self, self._root) + + class IonosphereData(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.a0 = self._io.read_s1() + self.a1 = self._io.read_s1() + self.a2 = self._io.read_s1() + self.a3 = self._io.read_s1() + self.b0 = self._io.read_s1() + self.b1 = self._io.read_s1() + self.b2 = self._io.read_s1() + self.b3 = self._io.read_s1() + + + + class How(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.tow_count = self._io.read_bits_int_be(17) + self.alert = self._io.read_bits_int_be(1) != 0 + self.anti_spoof = self._io.read_bits_int_be(1) != 0 + self.subframe_id = self._io.read_bits_int_be(3) + self.reserved = self._io.read_bits_int_be(2) + + + class Tlm(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.preamble = self._io.read_bytes(1) + if not self.preamble == b"\x8B": + raise kaitaistruct.ValidationNotEqualError(b"\x8B", self.preamble, self._io, u"/types/tlm/seq/0") + self.tlm = self._io.read_bits_int_be(14) + self.integrity_status = self._io.read_bits_int_be(1) != 0 + self.reserved = self._io.read_bits_int_be(1) != 0 + + + class Subframe2(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.iode = self._io.read_u1() + self.c_rs = self._io.read_s2be() + self.delta_n = self._io.read_s2be() + self.m_0 = self._io.read_s4be() + self.c_uc = self._io.read_s2be() + self.e = self._io.read_s4be() + self.c_us = self._io.read_s2be() + self.sqrt_a = self._io.read_u4be() + self.t_oe = self._io.read_u2be() + self.fit_interval_flag = self._io.read_bits_int_be(1) != 0 + self.aoda = self._io.read_bits_int_be(5) + self.reserved = self._io.read_bits_int_be(2) + + + diff --git a/system/ubloxd/generated/ubx.cpp b/system/ubloxd/generated/ubx.cpp deleted file mode 100644 index 81b82ccafc..0000000000 --- a/system/ubloxd/generated/ubx.cpp +++ /dev/null @@ -1,424 +0,0 @@ -// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild - -#include "ubx.h" -#include "kaitai/exceptions.h" - -ubx_t::ubx_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, ubx_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = this; - f_checksum = false; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void ubx_t::_read() { - m_magic = m__io->read_bytes(2); - if (!(magic() == std::string("\xB5\x62", 2))) { - throw kaitai::validation_not_equal_error(std::string("\xB5\x62", 2), magic(), _io(), std::string("/seq/0")); - } - m_msg_type = m__io->read_u2be(); - m_length = m__io->read_u2le(); - n_body = true; - switch (msg_type()) { - case 2569: { - n_body = false; - m_body = new mon_hw_t(m__io, this, m__root); - break; - } - case 533: { - n_body = false; - m_body = new rxm_rawx_t(m__io, this, m__root); - break; - } - case 531: { - n_body = false; - m_body = new rxm_sfrbx_t(m__io, this, m__root); - break; - } - case 309: { - n_body = false; - m_body = new nav_sat_t(m__io, this, m__root); - break; - } - case 2571: { - n_body = false; - m_body = new mon_hw2_t(m__io, this, m__root); - break; - } - case 263: { - n_body = false; - m_body = new nav_pvt_t(m__io, this, m__root); - break; - } - } -} - -ubx_t::~ubx_t() { - _clean_up(); -} - -void ubx_t::_clean_up() { - if (!n_body) { - if (m_body) { - delete m_body; m_body = 0; - } - } - if (f_checksum) { - } -} - -ubx_t::rxm_rawx_t::rxm_rawx_t(kaitai::kstream* p__io, ubx_t* p__parent, ubx_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - m_meas = 0; - m__raw_meas = 0; - m__io__raw_meas = 0; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void ubx_t::rxm_rawx_t::_read() { - m_rcv_tow = m__io->read_f8le(); - m_week = m__io->read_u2le(); - m_leap_s = m__io->read_s1(); - m_num_meas = m__io->read_u1(); - m_rec_stat = m__io->read_u1(); - m_reserved1 = m__io->read_bytes(3); - m__raw_meas = new std::vector(); - m__io__raw_meas = new std::vector(); - m_meas = new std::vector(); - const int l_meas = num_meas(); - for (int i = 0; i < l_meas; i++) { - m__raw_meas->push_back(m__io->read_bytes(32)); - kaitai::kstream* io__raw_meas = new kaitai::kstream(m__raw_meas->at(m__raw_meas->size() - 1)); - m__io__raw_meas->push_back(io__raw_meas); - m_meas->push_back(new measurement_t(io__raw_meas, this, m__root)); - } -} - -ubx_t::rxm_rawx_t::~rxm_rawx_t() { - _clean_up(); -} - -void ubx_t::rxm_rawx_t::_clean_up() { - if (m__raw_meas) { - delete m__raw_meas; m__raw_meas = 0; - } - if (m__io__raw_meas) { - for (std::vector::iterator it = m__io__raw_meas->begin(); it != m__io__raw_meas->end(); ++it) { - delete *it; - } - delete m__io__raw_meas; m__io__raw_meas = 0; - } - if (m_meas) { - for (std::vector::iterator it = m_meas->begin(); it != m_meas->end(); ++it) { - delete *it; - } - delete m_meas; m_meas = 0; - } -} - -ubx_t::rxm_rawx_t::measurement_t::measurement_t(kaitai::kstream* p__io, ubx_t::rxm_rawx_t* p__parent, ubx_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void ubx_t::rxm_rawx_t::measurement_t::_read() { - m_pr_mes = m__io->read_f8le(); - m_cp_mes = m__io->read_f8le(); - m_do_mes = m__io->read_f4le(); - m_gnss_id = static_cast(m__io->read_u1()); - m_sv_id = m__io->read_u1(); - m_reserved2 = m__io->read_bytes(1); - m_freq_id = m__io->read_u1(); - m_lock_time = m__io->read_u2le(); - m_cno = m__io->read_u1(); - m_pr_stdev = m__io->read_u1(); - m_cp_stdev = m__io->read_u1(); - m_do_stdev = m__io->read_u1(); - m_trk_stat = m__io->read_u1(); - m_reserved3 = m__io->read_bytes(1); -} - -ubx_t::rxm_rawx_t::measurement_t::~measurement_t() { - _clean_up(); -} - -void ubx_t::rxm_rawx_t::measurement_t::_clean_up() { -} - -ubx_t::rxm_sfrbx_t::rxm_sfrbx_t(kaitai::kstream* p__io, ubx_t* p__parent, ubx_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - m_body = 0; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void ubx_t::rxm_sfrbx_t::_read() { - m_gnss_id = static_cast(m__io->read_u1()); - m_sv_id = m__io->read_u1(); - m_reserved1 = m__io->read_bytes(1); - m_freq_id = m__io->read_u1(); - m_num_words = m__io->read_u1(); - m_reserved2 = m__io->read_bytes(1); - m_version = m__io->read_u1(); - m_reserved3 = m__io->read_bytes(1); - m_body = new std::vector(); - const int l_body = num_words(); - for (int i = 0; i < l_body; i++) { - m_body->push_back(m__io->read_u4le()); - } -} - -ubx_t::rxm_sfrbx_t::~rxm_sfrbx_t() { - _clean_up(); -} - -void ubx_t::rxm_sfrbx_t::_clean_up() { - if (m_body) { - delete m_body; m_body = 0; - } -} - -ubx_t::nav_sat_t::nav_sat_t(kaitai::kstream* p__io, ubx_t* p__parent, ubx_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - m_svs = 0; - m__raw_svs = 0; - m__io__raw_svs = 0; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void ubx_t::nav_sat_t::_read() { - m_itow = m__io->read_u4le(); - m_version = m__io->read_u1(); - m_num_svs = m__io->read_u1(); - m_reserved = m__io->read_bytes(2); - m__raw_svs = new std::vector(); - m__io__raw_svs = new std::vector(); - m_svs = new std::vector(); - const int l_svs = num_svs(); - for (int i = 0; i < l_svs; i++) { - m__raw_svs->push_back(m__io->read_bytes(12)); - kaitai::kstream* io__raw_svs = new kaitai::kstream(m__raw_svs->at(m__raw_svs->size() - 1)); - m__io__raw_svs->push_back(io__raw_svs); - m_svs->push_back(new nav_t(io__raw_svs, this, m__root)); - } -} - -ubx_t::nav_sat_t::~nav_sat_t() { - _clean_up(); -} - -void ubx_t::nav_sat_t::_clean_up() { - if (m__raw_svs) { - delete m__raw_svs; m__raw_svs = 0; - } - if (m__io__raw_svs) { - for (std::vector::iterator it = m__io__raw_svs->begin(); it != m__io__raw_svs->end(); ++it) { - delete *it; - } - delete m__io__raw_svs; m__io__raw_svs = 0; - } - if (m_svs) { - for (std::vector::iterator it = m_svs->begin(); it != m_svs->end(); ++it) { - delete *it; - } - delete m_svs; m_svs = 0; - } -} - -ubx_t::nav_sat_t::nav_t::nav_t(kaitai::kstream* p__io, ubx_t::nav_sat_t* p__parent, ubx_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void ubx_t::nav_sat_t::nav_t::_read() { - m_gnss_id = static_cast(m__io->read_u1()); - m_sv_id = m__io->read_u1(); - m_cno = m__io->read_u1(); - m_elev = m__io->read_s1(); - m_azim = m__io->read_s2le(); - m_pr_res = m__io->read_s2le(); - m_flags = m__io->read_u4le(); -} - -ubx_t::nav_sat_t::nav_t::~nav_t() { - _clean_up(); -} - -void ubx_t::nav_sat_t::nav_t::_clean_up() { -} - -ubx_t::nav_pvt_t::nav_pvt_t(kaitai::kstream* p__io, ubx_t* p__parent, ubx_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void ubx_t::nav_pvt_t::_read() { - m_i_tow = m__io->read_u4le(); - m_year = m__io->read_u2le(); - m_month = m__io->read_u1(); - m_day = m__io->read_u1(); - m_hour = m__io->read_u1(); - m_min = m__io->read_u1(); - m_sec = m__io->read_u1(); - m_valid = m__io->read_u1(); - m_t_acc = m__io->read_u4le(); - m_nano = m__io->read_s4le(); - m_fix_type = m__io->read_u1(); - m_flags = m__io->read_u1(); - m_flags2 = m__io->read_u1(); - m_num_sv = m__io->read_u1(); - m_lon = m__io->read_s4le(); - m_lat = m__io->read_s4le(); - m_height = m__io->read_s4le(); - m_h_msl = m__io->read_s4le(); - m_h_acc = m__io->read_u4le(); - m_v_acc = m__io->read_u4le(); - m_vel_n = m__io->read_s4le(); - m_vel_e = m__io->read_s4le(); - m_vel_d = m__io->read_s4le(); - m_g_speed = m__io->read_s4le(); - m_head_mot = m__io->read_s4le(); - m_s_acc = m__io->read_s4le(); - m_head_acc = m__io->read_u4le(); - m_p_dop = m__io->read_u2le(); - m_flags3 = m__io->read_u1(); - m_reserved1 = m__io->read_bytes(5); - m_head_veh = m__io->read_s4le(); - m_mag_dec = m__io->read_s2le(); - m_mag_acc = m__io->read_u2le(); -} - -ubx_t::nav_pvt_t::~nav_pvt_t() { - _clean_up(); -} - -void ubx_t::nav_pvt_t::_clean_up() { -} - -ubx_t::mon_hw2_t::mon_hw2_t(kaitai::kstream* p__io, ubx_t* p__parent, ubx_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void ubx_t::mon_hw2_t::_read() { - m_ofs_i = m__io->read_s1(); - m_mag_i = m__io->read_u1(); - m_ofs_q = m__io->read_s1(); - m_mag_q = m__io->read_u1(); - m_cfg_source = static_cast(m__io->read_u1()); - m_reserved1 = m__io->read_bytes(3); - m_low_lev_cfg = m__io->read_u4le(); - m_reserved2 = m__io->read_bytes(8); - m_post_status = m__io->read_u4le(); - m_reserved3 = m__io->read_bytes(4); -} - -ubx_t::mon_hw2_t::~mon_hw2_t() { - _clean_up(); -} - -void ubx_t::mon_hw2_t::_clean_up() { -} - -ubx_t::mon_hw_t::mon_hw_t(kaitai::kstream* p__io, ubx_t* p__parent, ubx_t* p__root) : kaitai::kstruct(p__io) { - m__parent = p__parent; - m__root = p__root; - - try { - _read(); - } catch(...) { - _clean_up(); - throw; - } -} - -void ubx_t::mon_hw_t::_read() { - m_pin_sel = m__io->read_u4le(); - m_pin_bank = m__io->read_u4le(); - m_pin_dir = m__io->read_u4le(); - m_pin_val = m__io->read_u4le(); - m_noise_per_ms = m__io->read_u2le(); - m_agc_cnt = m__io->read_u2le(); - m_a_status = static_cast(m__io->read_u1()); - m_a_power = static_cast(m__io->read_u1()); - m_flags = m__io->read_u1(); - m_reserved1 = m__io->read_bytes(1); - m_used_mask = m__io->read_u4le(); - m_vp = m__io->read_bytes(17); - m_jam_ind = m__io->read_u1(); - m_reserved2 = m__io->read_bytes(2); - m_pin_irq = m__io->read_u4le(); - m_pull_h = m__io->read_u4le(); - m_pull_l = m__io->read_u4le(); -} - -ubx_t::mon_hw_t::~mon_hw_t() { - _clean_up(); -} - -void ubx_t::mon_hw_t::_clean_up() { -} - -uint16_t ubx_t::checksum() { - if (f_checksum) - return m_checksum; - std::streampos _pos = m__io->pos(); - m__io->seek((length() + 6)); - m_checksum = m__io->read_u2le(); - m__io->seek(_pos); - f_checksum = true; - return m_checksum; -} diff --git a/system/ubloxd/generated/ubx.h b/system/ubloxd/generated/ubx.h deleted file mode 100644 index 022108489f..0000000000 --- a/system/ubloxd/generated/ubx.h +++ /dev/null @@ -1,484 +0,0 @@ -#ifndef UBX_H_ -#define UBX_H_ - -// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild - -#include "kaitai/kaitaistruct.h" -#include -#include - -#if KAITAI_STRUCT_VERSION < 9000L -#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required" -#endif - -class ubx_t : public kaitai::kstruct { - -public: - class rxm_rawx_t; - class rxm_sfrbx_t; - class nav_sat_t; - class nav_pvt_t; - class mon_hw2_t; - class mon_hw_t; - - enum gnss_type_t { - GNSS_TYPE_GPS = 0, - GNSS_TYPE_SBAS = 1, - GNSS_TYPE_GALILEO = 2, - GNSS_TYPE_BEIDOU = 3, - GNSS_TYPE_IMES = 4, - GNSS_TYPE_QZSS = 5, - GNSS_TYPE_GLONASS = 6 - }; - - ubx_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, ubx_t* p__root = 0); - -private: - void _read(); - void _clean_up(); - -public: - ~ubx_t(); - - class rxm_rawx_t : public kaitai::kstruct { - - public: - class measurement_t; - - rxm_rawx_t(kaitai::kstream* p__io, ubx_t* p__parent = 0, ubx_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~rxm_rawx_t(); - - class measurement_t : public kaitai::kstruct { - - public: - - measurement_t(kaitai::kstream* p__io, ubx_t::rxm_rawx_t* p__parent = 0, ubx_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~measurement_t(); - - private: - double m_pr_mes; - double m_cp_mes; - float m_do_mes; - gnss_type_t m_gnss_id; - uint8_t m_sv_id; - std::string m_reserved2; - uint8_t m_freq_id; - uint16_t m_lock_time; - uint8_t m_cno; - uint8_t m_pr_stdev; - uint8_t m_cp_stdev; - uint8_t m_do_stdev; - uint8_t m_trk_stat; - std::string m_reserved3; - ubx_t* m__root; - ubx_t::rxm_rawx_t* m__parent; - - public: - double pr_mes() const { return m_pr_mes; } - double cp_mes() const { return m_cp_mes; } - float do_mes() const { return m_do_mes; } - gnss_type_t gnss_id() const { return m_gnss_id; } - uint8_t sv_id() const { return m_sv_id; } - std::string reserved2() const { return m_reserved2; } - uint8_t freq_id() const { return m_freq_id; } - uint16_t lock_time() const { return m_lock_time; } - uint8_t cno() const { return m_cno; } - uint8_t pr_stdev() const { return m_pr_stdev; } - uint8_t cp_stdev() const { return m_cp_stdev; } - uint8_t do_stdev() const { return m_do_stdev; } - uint8_t trk_stat() const { return m_trk_stat; } - std::string reserved3() const { return m_reserved3; } - ubx_t* _root() const { return m__root; } - ubx_t::rxm_rawx_t* _parent() const { return m__parent; } - }; - - private: - double m_rcv_tow; - uint16_t m_week; - int8_t m_leap_s; - uint8_t m_num_meas; - uint8_t m_rec_stat; - std::string m_reserved1; - std::vector* m_meas; - ubx_t* m__root; - ubx_t* m__parent; - std::vector* m__raw_meas; - std::vector* m__io__raw_meas; - - public: - double rcv_tow() const { return m_rcv_tow; } - uint16_t week() const { return m_week; } - int8_t leap_s() const { return m_leap_s; } - uint8_t num_meas() const { return m_num_meas; } - uint8_t rec_stat() const { return m_rec_stat; } - std::string reserved1() const { return m_reserved1; } - std::vector* meas() const { return m_meas; } - ubx_t* _root() const { return m__root; } - ubx_t* _parent() const { return m__parent; } - std::vector* _raw_meas() const { return m__raw_meas; } - std::vector* _io__raw_meas() const { return m__io__raw_meas; } - }; - - class rxm_sfrbx_t : public kaitai::kstruct { - - public: - - rxm_sfrbx_t(kaitai::kstream* p__io, ubx_t* p__parent = 0, ubx_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~rxm_sfrbx_t(); - - private: - gnss_type_t m_gnss_id; - uint8_t m_sv_id; - std::string m_reserved1; - uint8_t m_freq_id; - uint8_t m_num_words; - std::string m_reserved2; - uint8_t m_version; - std::string m_reserved3; - std::vector* m_body; - ubx_t* m__root; - ubx_t* m__parent; - - public: - gnss_type_t gnss_id() const { return m_gnss_id; } - uint8_t sv_id() const { return m_sv_id; } - std::string reserved1() const { return m_reserved1; } - uint8_t freq_id() const { return m_freq_id; } - uint8_t num_words() const { return m_num_words; } - std::string reserved2() const { return m_reserved2; } - uint8_t version() const { return m_version; } - std::string reserved3() const { return m_reserved3; } - std::vector* body() const { return m_body; } - ubx_t* _root() const { return m__root; } - ubx_t* _parent() const { return m__parent; } - }; - - class nav_sat_t : public kaitai::kstruct { - - public: - class nav_t; - - nav_sat_t(kaitai::kstream* p__io, ubx_t* p__parent = 0, ubx_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~nav_sat_t(); - - class nav_t : public kaitai::kstruct { - - public: - - nav_t(kaitai::kstream* p__io, ubx_t::nav_sat_t* p__parent = 0, ubx_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~nav_t(); - - private: - gnss_type_t m_gnss_id; - uint8_t m_sv_id; - uint8_t m_cno; - int8_t m_elev; - int16_t m_azim; - int16_t m_pr_res; - uint32_t m_flags; - ubx_t* m__root; - ubx_t::nav_sat_t* m__parent; - - public: - gnss_type_t gnss_id() const { return m_gnss_id; } - uint8_t sv_id() const { return m_sv_id; } - uint8_t cno() const { return m_cno; } - int8_t elev() const { return m_elev; } - int16_t azim() const { return m_azim; } - int16_t pr_res() const { return m_pr_res; } - uint32_t flags() const { return m_flags; } - ubx_t* _root() const { return m__root; } - ubx_t::nav_sat_t* _parent() const { return m__parent; } - }; - - private: - uint32_t m_itow; - uint8_t m_version; - uint8_t m_num_svs; - std::string m_reserved; - std::vector* m_svs; - ubx_t* m__root; - ubx_t* m__parent; - std::vector* m__raw_svs; - std::vector* m__io__raw_svs; - - public: - uint32_t itow() const { return m_itow; } - uint8_t version() const { return m_version; } - uint8_t num_svs() const { return m_num_svs; } - std::string reserved() const { return m_reserved; } - std::vector* svs() const { return m_svs; } - ubx_t* _root() const { return m__root; } - ubx_t* _parent() const { return m__parent; } - std::vector* _raw_svs() const { return m__raw_svs; } - std::vector* _io__raw_svs() const { return m__io__raw_svs; } - }; - - class nav_pvt_t : public kaitai::kstruct { - - public: - - nav_pvt_t(kaitai::kstream* p__io, ubx_t* p__parent = 0, ubx_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~nav_pvt_t(); - - private: - uint32_t m_i_tow; - uint16_t m_year; - uint8_t m_month; - uint8_t m_day; - uint8_t m_hour; - uint8_t m_min; - uint8_t m_sec; - uint8_t m_valid; - uint32_t m_t_acc; - int32_t m_nano; - uint8_t m_fix_type; - uint8_t m_flags; - uint8_t m_flags2; - uint8_t m_num_sv; - int32_t m_lon; - int32_t m_lat; - int32_t m_height; - int32_t m_h_msl; - uint32_t m_h_acc; - uint32_t m_v_acc; - int32_t m_vel_n; - int32_t m_vel_e; - int32_t m_vel_d; - int32_t m_g_speed; - int32_t m_head_mot; - int32_t m_s_acc; - uint32_t m_head_acc; - uint16_t m_p_dop; - uint8_t m_flags3; - std::string m_reserved1; - int32_t m_head_veh; - int16_t m_mag_dec; - uint16_t m_mag_acc; - ubx_t* m__root; - ubx_t* m__parent; - - public: - uint32_t i_tow() const { return m_i_tow; } - uint16_t year() const { return m_year; } - uint8_t month() const { return m_month; } - uint8_t day() const { return m_day; } - uint8_t hour() const { return m_hour; } - uint8_t min() const { return m_min; } - uint8_t sec() const { return m_sec; } - uint8_t valid() const { return m_valid; } - uint32_t t_acc() const { return m_t_acc; } - int32_t nano() const { return m_nano; } - uint8_t fix_type() const { return m_fix_type; } - uint8_t flags() const { return m_flags; } - uint8_t flags2() const { return m_flags2; } - uint8_t num_sv() const { return m_num_sv; } - int32_t lon() const { return m_lon; } - int32_t lat() const { return m_lat; } - int32_t height() const { return m_height; } - int32_t h_msl() const { return m_h_msl; } - uint32_t h_acc() const { return m_h_acc; } - uint32_t v_acc() const { return m_v_acc; } - int32_t vel_n() const { return m_vel_n; } - int32_t vel_e() const { return m_vel_e; } - int32_t vel_d() const { return m_vel_d; } - int32_t g_speed() const { return m_g_speed; } - int32_t head_mot() const { return m_head_mot; } - int32_t s_acc() const { return m_s_acc; } - uint32_t head_acc() const { return m_head_acc; } - uint16_t p_dop() const { return m_p_dop; } - uint8_t flags3() const { return m_flags3; } - std::string reserved1() const { return m_reserved1; } - int32_t head_veh() const { return m_head_veh; } - int16_t mag_dec() const { return m_mag_dec; } - uint16_t mag_acc() const { return m_mag_acc; } - ubx_t* _root() const { return m__root; } - ubx_t* _parent() const { return m__parent; } - }; - - class mon_hw2_t : public kaitai::kstruct { - - public: - - enum config_source_t { - CONFIG_SOURCE_FLASH = 102, - CONFIG_SOURCE_OTP = 111, - CONFIG_SOURCE_CONFIG_PINS = 112, - CONFIG_SOURCE_ROM = 113 - }; - - mon_hw2_t(kaitai::kstream* p__io, ubx_t* p__parent = 0, ubx_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~mon_hw2_t(); - - private: - int8_t m_ofs_i; - uint8_t m_mag_i; - int8_t m_ofs_q; - uint8_t m_mag_q; - config_source_t m_cfg_source; - std::string m_reserved1; - uint32_t m_low_lev_cfg; - std::string m_reserved2; - uint32_t m_post_status; - std::string m_reserved3; - ubx_t* m__root; - ubx_t* m__parent; - - public: - int8_t ofs_i() const { return m_ofs_i; } - uint8_t mag_i() const { return m_mag_i; } - int8_t ofs_q() const { return m_ofs_q; } - uint8_t mag_q() const { return m_mag_q; } - config_source_t cfg_source() const { return m_cfg_source; } - std::string reserved1() const { return m_reserved1; } - uint32_t low_lev_cfg() const { return m_low_lev_cfg; } - std::string reserved2() const { return m_reserved2; } - uint32_t post_status() const { return m_post_status; } - std::string reserved3() const { return m_reserved3; } - ubx_t* _root() const { return m__root; } - ubx_t* _parent() const { return m__parent; } - }; - - class mon_hw_t : public kaitai::kstruct { - - public: - - enum antenna_status_t { - ANTENNA_STATUS_INIT = 0, - ANTENNA_STATUS_DONTKNOW = 1, - ANTENNA_STATUS_OK = 2, - ANTENNA_STATUS_SHORT = 3, - ANTENNA_STATUS_OPEN = 4 - }; - - enum antenna_power_t { - ANTENNA_POWER_FALSE = 0, - ANTENNA_POWER_TRUE = 1, - ANTENNA_POWER_DONTKNOW = 2 - }; - - mon_hw_t(kaitai::kstream* p__io, ubx_t* p__parent = 0, ubx_t* p__root = 0); - - private: - void _read(); - void _clean_up(); - - public: - ~mon_hw_t(); - - private: - uint32_t m_pin_sel; - uint32_t m_pin_bank; - uint32_t m_pin_dir; - uint32_t m_pin_val; - uint16_t m_noise_per_ms; - uint16_t m_agc_cnt; - antenna_status_t m_a_status; - antenna_power_t m_a_power; - uint8_t m_flags; - std::string m_reserved1; - uint32_t m_used_mask; - std::string m_vp; - uint8_t m_jam_ind; - std::string m_reserved2; - uint32_t m_pin_irq; - uint32_t m_pull_h; - uint32_t m_pull_l; - ubx_t* m__root; - ubx_t* m__parent; - - public: - uint32_t pin_sel() const { return m_pin_sel; } - uint32_t pin_bank() const { return m_pin_bank; } - uint32_t pin_dir() const { return m_pin_dir; } - uint32_t pin_val() const { return m_pin_val; } - uint16_t noise_per_ms() const { return m_noise_per_ms; } - uint16_t agc_cnt() const { return m_agc_cnt; } - antenna_status_t a_status() const { return m_a_status; } - antenna_power_t a_power() const { return m_a_power; } - uint8_t flags() const { return m_flags; } - std::string reserved1() const { return m_reserved1; } - uint32_t used_mask() const { return m_used_mask; } - std::string vp() const { return m_vp; } - uint8_t jam_ind() const { return m_jam_ind; } - std::string reserved2() const { return m_reserved2; } - uint32_t pin_irq() const { return m_pin_irq; } - uint32_t pull_h() const { return m_pull_h; } - uint32_t pull_l() const { return m_pull_l; } - ubx_t* _root() const { return m__root; } - ubx_t* _parent() const { return m__parent; } - }; - -private: - bool f_checksum; - uint16_t m_checksum; - -public: - uint16_t checksum(); - -private: - std::string m_magic; - uint16_t m_msg_type; - uint16_t m_length; - kaitai::kstruct* m_body; - bool n_body; - -public: - bool _is_null_body() { body(); return n_body; }; - -private: - ubx_t* m__root; - kaitai::kstruct* m__parent; - -public: - std::string magic() const { return m_magic; } - uint16_t msg_type() const { return m_msg_type; } - uint16_t length() const { return m_length; } - kaitai::kstruct* body() const { return m_body; } - ubx_t* _root() const { return m__root; } - kaitai::kstruct* _parent() const { return m__parent; } -}; - -#endif // UBX_H_ diff --git a/system/ubloxd/generated/ubx.py b/system/ubloxd/generated/ubx.py new file mode 100644 index 0000000000..9946584388 --- /dev/null +++ b/system/ubloxd/generated/ubx.py @@ -0,0 +1,273 @@ +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +import kaitaistruct +from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO +from enum import Enum + + +if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 9): + raise Exception("Incompatible Kaitai Struct Python API: 0.9 or later is required, but you have %s" % (kaitaistruct.__version__)) + +class Ubx(KaitaiStruct): + + class GnssType(Enum): + gps = 0 + sbas = 1 + galileo = 2 + beidou = 3 + imes = 4 + qzss = 5 + glonass = 6 + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.magic = self._io.read_bytes(2) + if not self.magic == b"\xB5\x62": + raise kaitaistruct.ValidationNotEqualError(b"\xB5\x62", self.magic, self._io, u"/seq/0") + self.msg_type = self._io.read_u2be() + self.length = self._io.read_u2le() + _on = self.msg_type + if _on == 2569: + self.body = Ubx.MonHw(self._io, self, self._root) + elif _on == 533: + self.body = Ubx.RxmRawx(self._io, self, self._root) + elif _on == 531: + self.body = Ubx.RxmSfrbx(self._io, self, self._root) + elif _on == 309: + self.body = Ubx.NavSat(self._io, self, self._root) + elif _on == 2571: + self.body = Ubx.MonHw2(self._io, self, self._root) + elif _on == 263: + self.body = Ubx.NavPvt(self._io, self, self._root) + + class RxmRawx(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.rcv_tow = self._io.read_f8le() + self.week = self._io.read_u2le() + self.leap_s = self._io.read_s1() + self.num_meas = self._io.read_u1() + self.rec_stat = self._io.read_u1() + self.reserved1 = self._io.read_bytes(3) + self._raw_meas = [] + self.meas = [] + for i in range(self.num_meas): + self._raw_meas.append(self._io.read_bytes(32)) + _io__raw_meas = KaitaiStream(BytesIO(self._raw_meas[i])) + self.meas.append(Ubx.RxmRawx.Measurement(_io__raw_meas, self, self._root)) + + + class Measurement(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.pr_mes = self._io.read_f8le() + self.cp_mes = self._io.read_f8le() + self.do_mes = self._io.read_f4le() + self.gnss_id = KaitaiStream.resolve_enum(Ubx.GnssType, self._io.read_u1()) + self.sv_id = self._io.read_u1() + self.reserved2 = self._io.read_bytes(1) + self.freq_id = self._io.read_u1() + self.lock_time = self._io.read_u2le() + self.cno = self._io.read_u1() + self.pr_stdev = self._io.read_u1() + self.cp_stdev = self._io.read_u1() + self.do_stdev = self._io.read_u1() + self.trk_stat = self._io.read_u1() + self.reserved3 = self._io.read_bytes(1) + + + + class RxmSfrbx(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.gnss_id = KaitaiStream.resolve_enum(Ubx.GnssType, self._io.read_u1()) + self.sv_id = self._io.read_u1() + self.reserved1 = self._io.read_bytes(1) + self.freq_id = self._io.read_u1() + self.num_words = self._io.read_u1() + self.reserved2 = self._io.read_bytes(1) + self.version = self._io.read_u1() + self.reserved3 = self._io.read_bytes(1) + self.body = [] + for i in range(self.num_words): + self.body.append(self._io.read_u4le()) + + + + class NavSat(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.itow = self._io.read_u4le() + self.version = self._io.read_u1() + self.num_svs = self._io.read_u1() + self.reserved = self._io.read_bytes(2) + self._raw_svs = [] + self.svs = [] + for i in range(self.num_svs): + self._raw_svs.append(self._io.read_bytes(12)) + _io__raw_svs = KaitaiStream(BytesIO(self._raw_svs[i])) + self.svs.append(Ubx.NavSat.Nav(_io__raw_svs, self, self._root)) + + + class Nav(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.gnss_id = KaitaiStream.resolve_enum(Ubx.GnssType, self._io.read_u1()) + self.sv_id = self._io.read_u1() + self.cno = self._io.read_u1() + self.elev = self._io.read_s1() + self.azim = self._io.read_s2le() + self.pr_res = self._io.read_s2le() + self.flags = self._io.read_u4le() + + + + class NavPvt(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.i_tow = self._io.read_u4le() + self.year = self._io.read_u2le() + self.month = self._io.read_u1() + self.day = self._io.read_u1() + self.hour = self._io.read_u1() + self.min = self._io.read_u1() + self.sec = self._io.read_u1() + self.valid = self._io.read_u1() + self.t_acc = self._io.read_u4le() + self.nano = self._io.read_s4le() + self.fix_type = self._io.read_u1() + self.flags = self._io.read_u1() + self.flags2 = self._io.read_u1() + self.num_sv = self._io.read_u1() + self.lon = self._io.read_s4le() + self.lat = self._io.read_s4le() + self.height = self._io.read_s4le() + self.h_msl = self._io.read_s4le() + self.h_acc = self._io.read_u4le() + self.v_acc = self._io.read_u4le() + self.vel_n = self._io.read_s4le() + self.vel_e = self._io.read_s4le() + self.vel_d = self._io.read_s4le() + self.g_speed = self._io.read_s4le() + self.head_mot = self._io.read_s4le() + self.s_acc = self._io.read_s4le() + self.head_acc = self._io.read_u4le() + self.p_dop = self._io.read_u2le() + self.flags3 = self._io.read_u1() + self.reserved1 = self._io.read_bytes(5) + self.head_veh = self._io.read_s4le() + self.mag_dec = self._io.read_s2le() + self.mag_acc = self._io.read_u2le() + + + class MonHw2(KaitaiStruct): + + class ConfigSource(Enum): + flash = 102 + otp = 111 + config_pins = 112 + rom = 113 + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.ofs_i = self._io.read_s1() + self.mag_i = self._io.read_u1() + self.ofs_q = self._io.read_s1() + self.mag_q = self._io.read_u1() + self.cfg_source = KaitaiStream.resolve_enum(Ubx.MonHw2.ConfigSource, self._io.read_u1()) + self.reserved1 = self._io.read_bytes(3) + self.low_lev_cfg = self._io.read_u4le() + self.reserved2 = self._io.read_bytes(8) + self.post_status = self._io.read_u4le() + self.reserved3 = self._io.read_bytes(4) + + + class MonHw(KaitaiStruct): + + class AntennaStatus(Enum): + init = 0 + dontknow = 1 + ok = 2 + short = 3 + open = 4 + + class AntennaPower(Enum): + false = 0 + true = 1 + dontknow = 2 + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.pin_sel = self._io.read_u4le() + self.pin_bank = self._io.read_u4le() + self.pin_dir = self._io.read_u4le() + self.pin_val = self._io.read_u4le() + self.noise_per_ms = self._io.read_u2le() + self.agc_cnt = self._io.read_u2le() + self.a_status = KaitaiStream.resolve_enum(Ubx.MonHw.AntennaStatus, self._io.read_u1()) + self.a_power = KaitaiStream.resolve_enum(Ubx.MonHw.AntennaPower, self._io.read_u1()) + self.flags = self._io.read_u1() + self.reserved1 = self._io.read_bytes(1) + self.used_mask = self._io.read_u4le() + self.vp = self._io.read_bytes(17) + self.jam_ind = self._io.read_u1() + self.reserved2 = self._io.read_bytes(2) + self.pin_irq = self._io.read_u4le() + self.pull_h = self._io.read_u4le() + self.pull_l = self._io.read_u4le() + + + @property + def checksum(self): + if hasattr(self, '_m_checksum'): + return self._m_checksum + + _pos = self._io.pos() + self._io.seek((self.length + 6)) + self._m_checksum = self._io.read_u2le() + self._io.seek(_pos) + return getattr(self, '_m_checksum', None) + + diff --git a/system/ubloxd/tests/print_gps_stats.py b/system/ubloxd/tests/print_gps_stats.py deleted file mode 100755 index 8d190f9ec1..0000000000 --- a/system/ubloxd/tests/print_gps_stats.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python3 -import time -import cereal.messaging as messaging - -if __name__ == "__main__": - sm = messaging.SubMaster(['ubloxGnss', 'gpsLocationExternal']) - - while 1: - ug = sm['ubloxGnss'] - gle = sm['gpsLocationExternal'] - - try: - cnos = [] - for m in ug.measurementReport.measurements: - cnos.append(m.cno) - print(f"Sats: {ug.measurementReport.numMeas} Accuracy: {gle.horizontalAccuracy:.2f} m cnos", sorted(cnos)) - except Exception: - pass - sm.update() - time.sleep(0.1) diff --git a/system/ubloxd/tests/test_glonass_kaitai.cc b/system/ubloxd/tests/test_glonass_kaitai.cc deleted file mode 100644 index 96f43742b4..0000000000 --- a/system/ubloxd/tests/test_glonass_kaitai.cc +++ /dev/null @@ -1,360 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "catch2/catch.hpp" -#include "system/ubloxd/generated/glonass.h" - -typedef std::vector> string_data; - -#define IDLE_CHIP_IDX 0 -#define STRING_NUMBER_IDX 1 -// string data 1-5 -#define HC_IDX 0 -#define PAD1_IDX 1 -#define SUPERFRAME_IDX 2 -#define PAD2_IDX 3 -#define FRAME_IDX 4 - -// Indexes for string number 1 -#define ST1_NU_IDX 2 -#define ST1_P1_IDX 3 -#define ST1_T_K_IDX 4 -#define ST1_X_VEL_S_IDX 5 -#define ST1_X_VEL_V_IDX 6 -#define ST1_X_ACCEL_S_IDX 7 -#define ST1_X_ACCEL_V_IDX 8 -#define ST1_X_S_IDX 9 -#define ST1_X_V_IDX 10 -#define ST1_HC_OFF 11 - -// Indexes for string number 2 -#define ST2_BN_IDX 2 -#define ST2_P2_IDX 3 -#define ST2_TB_IDX 4 -#define ST2_NU_IDX 5 -#define ST2_Y_VEL_S_IDX 6 -#define ST2_Y_VEL_V_IDX 7 -#define ST2_Y_ACCEL_S_IDX 8 -#define ST2_Y_ACCEL_V_IDX 9 -#define ST2_Y_S_IDX 10 -#define ST2_Y_V_IDX 11 -#define ST2_HC_OFF 12 - -// Indexes for string number 3 -#define ST3_P3_IDX 2 -#define ST3_GAMMA_N_S_IDX 3 -#define ST3_GAMMA_N_V_IDX 4 -#define ST3_NU_1_IDX 5 -#define ST3_P_IDX 6 -#define ST3_L_N_IDX 7 -#define ST3_Z_VEL_S_IDX 8 -#define ST3_Z_VEL_V_IDX 9 -#define ST3_Z_ACCEL_S_IDX 10 -#define ST3_Z_ACCEL_V_IDX 11 -#define ST3_Z_S_IDX 12 -#define ST3_Z_V_IDX 13 -#define ST3_HC_OFF 14 - -// Indexes for string number 4 -#define ST4_TAU_N_S_IDX 2 -#define ST4_TAU_N_V_IDX 3 -#define ST4_DELTA_TAU_N_S_IDX 4 -#define ST4_DELTA_TAU_N_V_IDX 5 -#define ST4_E_N_IDX 6 -#define ST4_NU_1_IDX 7 -#define ST4_P4_IDX 8 -#define ST4_F_T_IDX 9 -#define ST4_NU_2_IDX 10 -#define ST4_N_T_IDX 11 -#define ST4_N_IDX 12 -#define ST4_M_IDX 13 -#define ST4_HC_OFF 14 - -// Indexes for string number 5 -#define ST5_N_A_IDX 2 -#define ST5_TAU_C_IDX 3 -#define ST5_NU_IDX 4 -#define ST5_N_4_IDX 5 -#define ST5_TAU_GPS_IDX 6 -#define ST5_L_N_IDX 7 -#define ST5_HC_OFF 8 - -// Indexes for non immediate -#define ST6_DATA_1_IDX 2 -#define ST6_DATA_2_IDX 3 -#define ST6_HC_OFF 4 - - -std::string generate_inp_data(string_data& data) { - std::string inp_data = ""; - for (auto& [b, v] : data) { - std::string tmp = std::bitset<64>(v).to_string(); - inp_data += tmp.substr(64-b, b); - } - assert(inp_data.size() == 128); - - std::string string_data; - string_data.reserve(16); - for (int i = 0; i < 128; i+=8) { - std::string substr = inp_data.substr(i, 8); - string_data.push_back((uint8_t)std::stoi(substr.c_str(), 0, 2)); - } - - return string_data; -} - -string_data generate_string_data(uint8_t string_number) { - - srand((unsigned)time(0)); - string_data data; // - data.push_back({1, 0}); // idle chip - data.push_back({4, string_number}); // string number - - if (string_number == 1) { - data.push_back({2, 3}); // not_used - data.push_back({2, 1}); // p1 - data.push_back({12, 113}); // t_k - data.push_back({1, rand() & 1}); // x_vel_sign - data.push_back({23, 7122}); // x_vel_value - data.push_back({1, rand() & 1}); // x_accel_sign - data.push_back({4, 3}); // x_accel_value - data.push_back({1, rand() & 1}); // x_sign - data.push_back({26, 33554431}); // x_value - } else if (string_number == 2) { - data.push_back({3, 3}); // b_n - data.push_back({1, 1}); // p2 - data.push_back({7, 123}); // t_b - data.push_back({5, 31}); // not_used - data.push_back({1, rand() & 1}); // y_vel_sign - data.push_back({23, 7422}); // y_vel_value - data.push_back({1, rand() & 1}); // y_accel_sign - data.push_back({4, 3}); // y_accel_value - data.push_back({1, rand() & 1}); // y_sign - data.push_back({26, 67108863}); // y_value - } else if (string_number == 3) { - data.push_back({1, 0}); // p3 - data.push_back({1, 1}); // gamma_n_sign - data.push_back({10, 123}); // gamma_n_value - data.push_back({1, 0}); // not_used - data.push_back({2, 2}); // p - data.push_back({1, 1}); // l_n - data.push_back({1, rand() & 1}); // z_vel_sign - data.push_back({23, 1337}); // z_vel_value - data.push_back({1, rand() & 1}); // z_accel_sign - data.push_back({4, 9}); // z_accel_value - data.push_back({1, rand() & 1}); // z_sign - data.push_back({26, 100023}); // z_value - } else if (string_number == 4) { - data.push_back({1, rand() & 1}); // tau_n_sign - data.push_back({21, 197152}); // tau_n_value - data.push_back({1, rand() & 1}); // delta_tau_n_sign - data.push_back({4, 4}); // delta_tau_n_value - data.push_back({5, 0}); // e_n - data.push_back({14, 2}); // not_used_1 - data.push_back({1, 1}); // p4 - data.push_back({4, 9}); // f_t - data.push_back({3, 3}); // not_used_2 - data.push_back({11, 2047}); // n_t - data.push_back({5, 2}); // n - data.push_back({2, 1}); // m - } else if (string_number == 5) { - data.push_back({11, 2047}); // n_a - data.push_back({32, 4294767295}); // tau_c - data.push_back({1, 0}); // not_used_1 - data.push_back({5, 2}); // n_4 - data.push_back({22, 4114304}); // tau_gps - data.push_back({1, 0}); // l_n - } else { // non-immediate data is not parsed - data.push_back({64, rand()}); // data_1 - data.push_back({8, 6}); // data_2 - } - - data.push_back({8, rand() & 0xFF}); // hamming code - data.push_back({11, rand() & 0x7FF}); // pad - data.push_back({16, rand() & 0xFFFF}); // superframe - data.push_back({8, rand() & 0xFF}); // pad - data.push_back({8, rand() & 0xFF}); // frame - return data; -} - -TEST_CASE("parse_string_number_1"){ - string_data data = generate_string_data(1); - std::string inp_data = generate_inp_data(data); - - kaitai::kstream stream(inp_data); - glonass_t gl_string(&stream); - - REQUIRE(gl_string.idle_chip() == data[IDLE_CHIP_IDX].second); - REQUIRE(gl_string.string_number() == data[STRING_NUMBER_IDX].second); - REQUIRE(gl_string.hamming_code() == data[ST1_HC_OFF + HC_IDX].second); - REQUIRE(gl_string.pad_1() == data[ST1_HC_OFF + PAD1_IDX].second); - REQUIRE(gl_string.superframe_number() == data[ST1_HC_OFF + SUPERFRAME_IDX].second); - REQUIRE(gl_string.pad_2() == data[ST1_HC_OFF + PAD2_IDX].second); - REQUIRE(gl_string.frame_number() == data[ST1_HC_OFF + FRAME_IDX].second); - - kaitai::kstream str1(inp_data); - glonass_t str1_data(&str1); - glonass_t::string_1_t* s1 = static_cast(str1_data.data()); - - REQUIRE(s1->not_used() == data[ST1_NU_IDX].second); - REQUIRE(s1->p1() == data[ST1_P1_IDX].second); - REQUIRE(s1->t_k() == data[ST1_T_K_IDX].second); - - int mul = s1->x_vel_sign() ? (-1) : 1; - REQUIRE(s1->x_vel() == (data[ST1_X_VEL_V_IDX].second * mul)); - mul = s1->x_accel_sign() ? (-1) : 1; - REQUIRE(s1->x_accel() == (data[ST1_X_ACCEL_V_IDX].second * mul)); - mul = s1->x_sign() ? (-1) : 1; - REQUIRE(s1->x() == (data[ST1_X_V_IDX].second * mul)); -} - -TEST_CASE("parse_string_number_2"){ - string_data data = generate_string_data(2); - std::string inp_data = generate_inp_data(data); - - kaitai::kstream stream(inp_data); - glonass_t gl_string(&stream); - - REQUIRE(gl_string.idle_chip() == data[IDLE_CHIP_IDX].second); - REQUIRE(gl_string.string_number() == data[STRING_NUMBER_IDX].second); - REQUIRE(gl_string.hamming_code() == data[ST2_HC_OFF + HC_IDX].second); - REQUIRE(gl_string.pad_1() == data[ST2_HC_OFF + PAD1_IDX].second); - REQUIRE(gl_string.superframe_number() == data[ST2_HC_OFF + SUPERFRAME_IDX].second); - REQUIRE(gl_string.pad_2() == data[ST2_HC_OFF + PAD2_IDX].second); - REQUIRE(gl_string.frame_number() == data[ST2_HC_OFF + FRAME_IDX].second); - - kaitai::kstream str2(inp_data); - glonass_t str2_data(&str2); - glonass_t::string_2_t* s2 = static_cast(str2_data.data()); - - REQUIRE(s2->b_n() == data[ST2_BN_IDX].second); - REQUIRE(s2->not_used() == data[ST2_NU_IDX].second); - REQUIRE(s2->p2() == data[ST2_P2_IDX].second); - REQUIRE(s2->t_b() == data[ST2_TB_IDX].second); - int mul = s2->y_vel_sign() ? (-1) : 1; - REQUIRE(s2->y_vel() == (data[ST2_Y_VEL_V_IDX].second * mul)); - mul = s2->y_accel_sign() ? (-1) : 1; - REQUIRE(s2->y_accel() == (data[ST2_Y_ACCEL_V_IDX].second * mul)); - mul = s2->y_sign() ? (-1) : 1; - REQUIRE(s2->y() == (data[ST2_Y_V_IDX].second * mul)); -} - -TEST_CASE("parse_string_number_3"){ - string_data data = generate_string_data(3); - std::string inp_data = generate_inp_data(data); - - kaitai::kstream stream(inp_data); - glonass_t gl_string(&stream); - - REQUIRE(gl_string.idle_chip() == data[IDLE_CHIP_IDX].second); - REQUIRE(gl_string.string_number() == data[STRING_NUMBER_IDX].second); - REQUIRE(gl_string.hamming_code() == data[ST3_HC_OFF + HC_IDX].second); - REQUIRE(gl_string.pad_1() == data[ST3_HC_OFF + PAD1_IDX].second); - REQUIRE(gl_string.superframe_number() == data[ST3_HC_OFF + SUPERFRAME_IDX].second); - REQUIRE(gl_string.pad_2() == data[ST3_HC_OFF + PAD2_IDX].second); - REQUIRE(gl_string.frame_number() == data[ST3_HC_OFF + FRAME_IDX].second); - - kaitai::kstream str3(inp_data); - glonass_t str3_data(&str3); - glonass_t::string_3_t* s3 = static_cast(str3_data.data()); - - REQUIRE(s3->p3() == data[ST3_P3_IDX].second); - int mul = s3->gamma_n_sign() ? (-1) : 1; - REQUIRE(s3->gamma_n() == (data[ST3_GAMMA_N_V_IDX].second * mul)); - REQUIRE(s3->not_used() == data[ST3_NU_1_IDX].second); - REQUIRE(s3->p() == data[ST3_P_IDX].second); - REQUIRE(s3->l_n() == data[ST3_L_N_IDX].second); - mul = s3->z_vel_sign() ? (-1) : 1; - REQUIRE(s3->z_vel() == (data[ST3_Z_VEL_V_IDX].second * mul)); - mul = s3->z_accel_sign() ? (-1) : 1; - REQUIRE(s3->z_accel() == (data[ST3_Z_ACCEL_V_IDX].second * mul)); - mul = s3->z_sign() ? (-1) : 1; - REQUIRE(s3->z() == (data[ST3_Z_V_IDX].second * mul)); -} - -TEST_CASE("parse_string_number_4"){ - string_data data = generate_string_data(4); - std::string inp_data = generate_inp_data(data); - - kaitai::kstream stream(inp_data); - glonass_t gl_string(&stream); - - REQUIRE(gl_string.idle_chip() == data[IDLE_CHIP_IDX].second); - REQUIRE(gl_string.string_number() == data[STRING_NUMBER_IDX].second); - REQUIRE(gl_string.hamming_code() == data[ST4_HC_OFF + HC_IDX].second); - REQUIRE(gl_string.pad_1() == data[ST4_HC_OFF + PAD1_IDX].second); - REQUIRE(gl_string.superframe_number() == data[ST4_HC_OFF + SUPERFRAME_IDX].second); - REQUIRE(gl_string.pad_2() == data[ST4_HC_OFF + PAD2_IDX].second); - REQUIRE(gl_string.frame_number() == data[ST4_HC_OFF + FRAME_IDX].second); - - kaitai::kstream str4(inp_data); - glonass_t str4_data(&str4); - glonass_t::string_4_t* s4 = static_cast(str4_data.data()); - - int mul = s4->tau_n_sign() ? (-1) : 1; - REQUIRE(s4->tau_n() == (data[ST4_TAU_N_V_IDX].second * mul)); - mul = s4->delta_tau_n_sign() ? (-1) : 1; - REQUIRE(s4->delta_tau_n() == (data[ST4_DELTA_TAU_N_V_IDX].second * mul)); - REQUIRE(s4->e_n() == data[ST4_E_N_IDX].second); - REQUIRE(s4->not_used_1() == data[ST4_NU_1_IDX].second); - REQUIRE(s4->p4() == data[ST4_P4_IDX].second); - REQUIRE(s4->f_t() == data[ST4_F_T_IDX].second); - REQUIRE(s4->not_used_2() == data[ST4_NU_2_IDX].second); - REQUIRE(s4->n_t() == data[ST4_N_T_IDX].second); - REQUIRE(s4->n() == data[ST4_N_IDX].second); - REQUIRE(s4->m() == data[ST4_M_IDX].second); -} - -TEST_CASE("parse_string_number_5"){ - string_data data = generate_string_data(5); - std::string inp_data = generate_inp_data(data); - - kaitai::kstream stream(inp_data); - glonass_t gl_string(&stream); - - REQUIRE(gl_string.idle_chip() == data[IDLE_CHIP_IDX].second); - REQUIRE(gl_string.string_number() == data[STRING_NUMBER_IDX].second); - REQUIRE(gl_string.hamming_code() == data[ST5_HC_OFF + HC_IDX].second); - REQUIRE(gl_string.pad_1() == data[ST5_HC_OFF + PAD1_IDX].second); - REQUIRE(gl_string.superframe_number() == data[ST5_HC_OFF + SUPERFRAME_IDX].second); - REQUIRE(gl_string.pad_2() == data[ST5_HC_OFF + PAD2_IDX].second); - REQUIRE(gl_string.frame_number() == data[ST5_HC_OFF + FRAME_IDX].second); - - kaitai::kstream str5(inp_data); - glonass_t str5_data(&str5); - glonass_t::string_5_t* s5 = static_cast(str5_data.data()); - - REQUIRE(s5->n_a() == data[ST5_N_A_IDX].second); - REQUIRE(s5->tau_c() == data[ST5_TAU_C_IDX].second); - REQUIRE(s5->not_used() == data[ST5_NU_IDX].second); - REQUIRE(s5->n_4() == data[ST5_N_4_IDX].second); - REQUIRE(s5->tau_gps() == data[ST5_TAU_GPS_IDX].second); - REQUIRE(s5->l_n() == data[ST5_L_N_IDX].second); -} - -TEST_CASE("parse_string_number_NI"){ - string_data data = generate_string_data((rand() % 10) + 6); - std::string inp_data = generate_inp_data(data); - - kaitai::kstream stream(inp_data); - glonass_t gl_string(&stream); - - REQUIRE(gl_string.idle_chip() == data[IDLE_CHIP_IDX].second); - REQUIRE(gl_string.string_number() == data[STRING_NUMBER_IDX].second); - REQUIRE(gl_string.hamming_code() == data[ST6_HC_OFF + HC_IDX].second); - REQUIRE(gl_string.pad_1() == data[ST6_HC_OFF + PAD1_IDX].second); - REQUIRE(gl_string.superframe_number() == data[ST6_HC_OFF + SUPERFRAME_IDX].second); - REQUIRE(gl_string.pad_2() == data[ST6_HC_OFF + PAD2_IDX].second); - REQUIRE(gl_string.frame_number() == data[ST6_HC_OFF + FRAME_IDX].second); - - kaitai::kstream strni(inp_data); - glonass_t strni_data(&strni); - glonass_t::string_non_immediate_t* sni = static_cast(strni_data.data()); - - REQUIRE(sni->data_1() == data[ST6_DATA_1_IDX].second); - REQUIRE(sni->data_2() == data[ST6_DATA_2_IDX].second); -} diff --git a/system/ubloxd/tests/test_glonass_runner.cc b/system/ubloxd/tests/test_glonass_runner.cc deleted file mode 100644 index 62bf7476a1..0000000000 --- a/system/ubloxd/tests/test_glonass_runner.cc +++ /dev/null @@ -1,2 +0,0 @@ -#define CATCH_CONFIG_MAIN -#include "catch2/catch.hpp" diff --git a/system/ubloxd/ublox_msg.cc b/system/ubloxd/ublox_msg.cc deleted file mode 100644 index 728f3b15fa..0000000000 --- a/system/ubloxd/ublox_msg.cc +++ /dev/null @@ -1,530 +0,0 @@ -#include "system/ubloxd/ublox_msg.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common/swaglog.h" - -const double gpsPi = 3.1415926535898; -#define UBLOX_MSG_SIZE(hdr) (*(uint16_t *)&hdr[4]) - -inline static bool bit_to_bool(uint8_t val, int shifts) { - return (bool)(val & (1 << shifts)); -} - -inline int UbloxMsgParser::needed_bytes() { - // Msg header incomplete? - if (bytes_in_parse_buf < ublox::UBLOX_HEADER_SIZE) - return ublox::UBLOX_HEADER_SIZE + ublox::UBLOX_CHECKSUM_SIZE - bytes_in_parse_buf; - uint16_t needed = UBLOX_MSG_SIZE(msg_parse_buf) + ublox::UBLOX_HEADER_SIZE + ublox::UBLOX_CHECKSUM_SIZE; - // too much data - if (needed < (uint16_t)bytes_in_parse_buf) - return -1; - return needed - (uint16_t)bytes_in_parse_buf; -} - -inline bool UbloxMsgParser::valid_cheksum() { - uint8_t ck_a = 0, ck_b = 0; - for (int i = 2; i < bytes_in_parse_buf - ublox::UBLOX_CHECKSUM_SIZE; i++) { - ck_a = (ck_a + msg_parse_buf[i]) & 0xFF; - ck_b = (ck_b + ck_a) & 0xFF; - } - if (ck_a != msg_parse_buf[bytes_in_parse_buf - 2]) { - LOGD("Checksum a mismatch: %02X, %02X", ck_a, msg_parse_buf[6]); - return false; - } - if (ck_b != msg_parse_buf[bytes_in_parse_buf - 1]) { - LOGD("Checksum b mismatch: %02X, %02X", ck_b, msg_parse_buf[7]); - return false; - } - return true; -} - -inline bool UbloxMsgParser::valid() { - return bytes_in_parse_buf >= ublox::UBLOX_HEADER_SIZE + ublox::UBLOX_CHECKSUM_SIZE && - needed_bytes() == 0 && valid_cheksum(); -} - -inline bool UbloxMsgParser::valid_so_far() { - if (bytes_in_parse_buf > 0 && msg_parse_buf[0] != ublox::PREAMBLE1) { - return false; - } - if (bytes_in_parse_buf > 1 && msg_parse_buf[1] != ublox::PREAMBLE2) { - return false; - } - if (needed_bytes() == 0 && !valid()) { - return false; - } - return true; -} - -bool UbloxMsgParser::add_data(float log_time, const uint8_t *incoming_data, uint32_t incoming_data_len, size_t &bytes_consumed) { - last_log_time = log_time; - int needed = needed_bytes(); - if (needed > 0) { - bytes_consumed = std::min((uint32_t)needed, incoming_data_len); - // Add data to buffer - memcpy(msg_parse_buf + bytes_in_parse_buf, incoming_data, bytes_consumed); - bytes_in_parse_buf += bytes_consumed; - } else { - bytes_consumed = incoming_data_len; - } - - // Validate msg format, detect invalid header and invalid checksum. - while (!valid_so_far() && bytes_in_parse_buf != 0) { - // Corrupted msg, drop a byte. - bytes_in_parse_buf -= 1; - if (bytes_in_parse_buf > 0) - memmove(&msg_parse_buf[0], &msg_parse_buf[1], bytes_in_parse_buf); - } - - // There is redundant data at the end of buffer, reset the buffer. - if (needed_bytes() == -1) { - bytes_in_parse_buf = 0; - } - return valid(); -} - - -std::pair> UbloxMsgParser::gen_msg() { - std::string dat = data(); - kaitai::kstream stream(dat); - - ubx_t ubx_message(&stream); - auto body = ubx_message.body(); - - switch (ubx_message.msg_type()) { - case 0x0107: - return {"gpsLocationExternal", gen_nav_pvt(static_cast(body))}; - case 0x0213: // UBX-RXM-SFRB (Broadcast Navigation Data Subframe) - return {"ubloxGnss", gen_rxm_sfrbx(static_cast(body))}; - case 0x0215: // UBX-RXM-RAW (Multi-GNSS Raw Measurement Data) - return {"ubloxGnss", gen_rxm_rawx(static_cast(body))}; - case 0x0a09: - return {"ubloxGnss", gen_mon_hw(static_cast(body))}; - case 0x0a0b: - return {"ubloxGnss", gen_mon_hw2(static_cast(body))}; - case 0x0135: - return {"ubloxGnss", gen_nav_sat(static_cast(body))}; - default: - LOGE("Unknown message type %x", ubx_message.msg_type()); - return {"ubloxGnss", kj::Array()}; - } -} - - -kj::Array UbloxMsgParser::gen_nav_pvt(ubx_t::nav_pvt_t *msg) { - MessageBuilder msg_builder; - auto gpsLoc = msg_builder.initEvent().initGpsLocationExternal(); - gpsLoc.setSource(cereal::GpsLocationData::SensorSource::UBLOX); - gpsLoc.setFlags(msg->flags()); - gpsLoc.setHasFix((msg->flags() % 2) == 1); - gpsLoc.setLatitude(msg->lat() * 1e-07); - gpsLoc.setLongitude(msg->lon() * 1e-07); - gpsLoc.setAltitude(msg->height() * 1e-03); - gpsLoc.setSpeed(msg->g_speed() * 1e-03); - gpsLoc.setBearingDeg(msg->head_mot() * 1e-5); - gpsLoc.setHorizontalAccuracy(msg->h_acc() * 1e-03); - gpsLoc.setSatelliteCount(msg->num_sv()); - std::tm timeinfo = std::tm(); - timeinfo.tm_year = msg->year() - 1900; - timeinfo.tm_mon = msg->month() - 1; - timeinfo.tm_mday = msg->day(); - timeinfo.tm_hour = msg->hour(); - timeinfo.tm_min = msg->min(); - timeinfo.tm_sec = msg->sec(); - - std::time_t utc_tt = timegm(&timeinfo); - gpsLoc.setUnixTimestampMillis(utc_tt * 1e+03 + msg->nano() * 1e-06); - float f[] = { msg->vel_n() * 1e-03f, msg->vel_e() * 1e-03f, msg->vel_d() * 1e-03f }; - gpsLoc.setVNED(f); - gpsLoc.setVerticalAccuracy(msg->v_acc() * 1e-03); - gpsLoc.setSpeedAccuracy(msg->s_acc() * 1e-03); - gpsLoc.setBearingAccuracyDeg(msg->head_acc() * 1e-05); - return capnp::messageToFlatArray(msg_builder); -} - -kj::Array UbloxMsgParser::parse_gps_ephemeris(ubx_t::rxm_sfrbx_t *msg) { - // GPS subframes are packed into 10x 4 bytes, each containing 3 actual bytes - // We will first need to separate the data from the padding and parity - auto body = *msg->body(); - assert(body.size() == 10); - - std::string subframe_data; - subframe_data.reserve(30); - for (uint32_t word : body) { - word = word >> 6; // TODO: Verify parity - subframe_data.push_back(word >> 16); - subframe_data.push_back(word >> 8); - subframe_data.push_back(word >> 0); - } - - // Collect subframes in map and parse when we have all the parts - { - kaitai::kstream stream(subframe_data); - gps_t subframe(&stream); - - int subframe_id = subframe.how()->subframe_id(); - if (subframe_id > 3 || subframe_id < 1) { - // don't parse almanac subframes - return kj::Array(); - } - gps_subframes[msg->sv_id()][subframe_id] = subframe_data; - } - - // publish if subframes 1-3 have been collected - if (gps_subframes[msg->sv_id()].size() == 3) { - MessageBuilder msg_builder; - auto eph = msg_builder.initEvent().initUbloxGnss().initEphemeris(); - eph.setSvId(msg->sv_id()); - - int iode_s2 = 0; - int iode_s3 = 0; - int iodc_lsb = 0; - int week; - - // Subframe 1 - { - kaitai::kstream stream(gps_subframes[msg->sv_id()][1]); - gps_t subframe(&stream); - gps_t::subframe_1_t* subframe_1 = static_cast(subframe.body()); - - // Each message is incremented to be greater or equal than week 1877 (2015-12-27). - // To skip this use the current_time argument - week = subframe_1->week_no(); - week += 1024; - if (week < 1877) { - week += 1024; - } - //eph.setGpsWeek(subframe_1->week_no()); - eph.setTgd(subframe_1->t_gd() * pow(2, -31)); - eph.setToc(subframe_1->t_oc() * pow(2, 4)); - eph.setAf2(subframe_1->af_2() * pow(2, -55)); - eph.setAf1(subframe_1->af_1() * pow(2, -43)); - eph.setAf0(subframe_1->af_0() * pow(2, -31)); - eph.setSvHealth(subframe_1->sv_health()); - eph.setTowCount(subframe.how()->tow_count()); - iodc_lsb = subframe_1->iodc_lsb(); - } - - // Subframe 2 - { - kaitai::kstream stream(gps_subframes[msg->sv_id()][2]); - gps_t subframe(&stream); - gps_t::subframe_2_t* subframe_2 = static_cast(subframe.body()); - - // GPS week refers to current week, the ephemeris can be valid for the next - // if toe equals 0, this can be verified by the TOW count if it is within the - // last 2 hours of the week (gps ephemeris valid for 4hours) - if (subframe_2->t_oe() == 0 and subframe.how()->tow_count()*6 >= (SECS_IN_WEEK - 2*SECS_IN_HR)){ - week += 1; - } - eph.setCrs(subframe_2->c_rs() * pow(2, -5)); - eph.setDeltaN(subframe_2->delta_n() * pow(2, -43) * gpsPi); - eph.setM0(subframe_2->m_0() * pow(2, -31) * gpsPi); - eph.setCuc(subframe_2->c_uc() * pow(2, -29)); - eph.setEcc(subframe_2->e() * pow(2, -33)); - eph.setCus(subframe_2->c_us() * pow(2, -29)); - eph.setA(pow(subframe_2->sqrt_a() * pow(2, -19), 2.0)); - eph.setToe(subframe_2->t_oe() * pow(2, 4)); - iode_s2 = subframe_2->iode(); - } - - // Subframe 3 - { - kaitai::kstream stream(gps_subframes[msg->sv_id()][3]); - gps_t subframe(&stream); - gps_t::subframe_3_t* subframe_3 = static_cast(subframe.body()); - - eph.setCic(subframe_3->c_ic() * pow(2, -29)); - eph.setOmega0(subframe_3->omega_0() * pow(2, -31) * gpsPi); - eph.setCis(subframe_3->c_is() * pow(2, -29)); - eph.setI0(subframe_3->i_0() * pow(2, -31) * gpsPi); - eph.setCrc(subframe_3->c_rc() * pow(2, -5)); - eph.setOmega(subframe_3->omega() * pow(2, -31) * gpsPi); - eph.setOmegaDot(subframe_3->omega_dot() * pow(2, -43) * gpsPi); - eph.setIode(subframe_3->iode()); - eph.setIDot(subframe_3->idot() * pow(2, -43) * gpsPi); - iode_s3 = subframe_3->iode(); - } - - eph.setToeWeek(week); - eph.setTocWeek(week); - - gps_subframes[msg->sv_id()].clear(); - if (iodc_lsb != iode_s2 || iodc_lsb != iode_s3) { - // data set cutover, reject ephemeris - return kj::Array(); - } - return capnp::messageToFlatArray(msg_builder); - } - return kj::Array(); -} - -kj::Array UbloxMsgParser::parse_glonass_ephemeris(ubx_t::rxm_sfrbx_t *msg) { - // This parser assumes that no 2 satellites of the same frequency - // can be in view at the same time - auto body = *msg->body(); - assert(body.size() == 4); - { - std::string string_data; - string_data.reserve(16); - for (uint32_t word : body) { - for (int i = 3; i >= 0; i--) - string_data.push_back(word >> 8*i); - } - - kaitai::kstream stream(string_data); - glonass_t gl_string(&stream); - int string_number = gl_string.string_number(); - if (string_number < 1 || string_number > 5 || gl_string.idle_chip()) { - // don't parse non immediate data, idle_chip == 0 - return kj::Array(); - } - - // Check if new string either has same superframe_id or log transmission times make sense - bool superframe_unknown = false; - bool needs_clear = false; - for (int i = 1; i <= 5; i++) { - if (glonass_strings[msg->freq_id()].find(i) == glonass_strings[msg->freq_id()].end()) - continue; - if (glonass_string_superframes[msg->freq_id()][i] == 0 || gl_string.superframe_number() == 0) { - superframe_unknown = true; - } else if (glonass_string_superframes[msg->freq_id()][i] != gl_string.superframe_number()) { - needs_clear = true; - } - // Check if string times add up to being from the same frame - // If superframe is known this is redundant - // Strings are sent 2s apart and frames are 30s apart - if (superframe_unknown && - std::abs((glonass_string_times[msg->freq_id()][i] - 2.0 * i) - (last_log_time - 2.0 * string_number)) > 10) - needs_clear = true; - } - if (needs_clear) { - glonass_strings[msg->freq_id()].clear(); - glonass_string_superframes[msg->freq_id()].clear(); - glonass_string_times[msg->freq_id()].clear(); - } - glonass_strings[msg->freq_id()][string_number] = string_data; - glonass_string_superframes[msg->freq_id()][string_number] = gl_string.superframe_number(); - glonass_string_times[msg->freq_id()][string_number] = last_log_time; - } - if (msg->sv_id() == 255) { - // data can be decoded before identifying the SV number, in this case 255 - // is returned, which means "unknown" (ublox p32) - return kj::Array(); - } - - // publish if strings 1-5 have been collected - if (glonass_strings[msg->freq_id()].size() != 5) { - return kj::Array(); - } - - MessageBuilder msg_builder; - auto eph = msg_builder.initEvent().initUbloxGnss().initGlonassEphemeris(); - eph.setSvId(msg->sv_id()); - eph.setFreqNum(msg->freq_id() - 7); - - uint16_t current_day = 0; - uint16_t tk = 0; - - // string number 1 - { - kaitai::kstream stream(glonass_strings[msg->freq_id()][1]); - glonass_t gl_stream(&stream); - glonass_t::string_1_t* data = static_cast(gl_stream.data()); - - eph.setP1(data->p1()); - tk = data->t_k(); - eph.setTkDEPRECATED(tk); - eph.setXVel(data->x_vel() * pow(2, -20)); - eph.setXAccel(data->x_accel() * pow(2, -30)); - eph.setX(data->x() * pow(2, -11)); - } - - // string number 2 - { - kaitai::kstream stream(glonass_strings[msg->freq_id()][2]); - glonass_t gl_stream(&stream); - glonass_t::string_2_t* data = static_cast(gl_stream.data()); - - eph.setSvHealth(data->b_n()>>2); // MSB indicates health - eph.setP2(data->p2()); - eph.setTb(data->t_b()); - eph.setYVel(data->y_vel() * pow(2, -20)); - eph.setYAccel(data->y_accel() * pow(2, -30)); - eph.setY(data->y() * pow(2, -11)); - } - - // string number 3 - { - kaitai::kstream stream(glonass_strings[msg->freq_id()][3]); - glonass_t gl_stream(&stream); - glonass_t::string_3_t* data = static_cast(gl_stream.data()); - - eph.setP3(data->p3()); - eph.setGammaN(data->gamma_n() * pow(2, -40)); - eph.setSvHealth(eph.getSvHealth() | data->l_n()); - eph.setZVel(data->z_vel() * pow(2, -20)); - eph.setZAccel(data->z_accel() * pow(2, -30)); - eph.setZ(data->z() * pow(2, -11)); - } - - // string number 4 - { - kaitai::kstream stream(glonass_strings[msg->freq_id()][4]); - glonass_t gl_stream(&stream); - glonass_t::string_4_t* data = static_cast(gl_stream.data()); - - current_day = data->n_t(); - eph.setNt(current_day); - eph.setTauN(data->tau_n() * pow(2, -30)); - eph.setDeltaTauN(data->delta_tau_n() * pow(2, -30)); - eph.setAge(data->e_n()); - eph.setP4(data->p4()); - eph.setSvURA(glonass_URA_lookup.at(data->f_t())); - if (msg->sv_id() != data->n()) { - LOGE("SV_ID != SLOT_NUMBER: %d %" PRIu64, msg->sv_id(), data->n()); - } - eph.setSvType(data->m()); - } - - // string number 5 - { - kaitai::kstream stream(glonass_strings[msg->freq_id()][5]); - glonass_t gl_stream(&stream); - glonass_t::string_5_t* data = static_cast(gl_stream.data()); - - // string5 parsing is only needed to get the year, this can be removed and - // the year can be fetched later in laika (note rollovers and leap year) - eph.setN4(data->n_4()); - int tk_seconds = SECS_IN_HR * ((tk>>7) & 0x1F) + SECS_IN_MIN * ((tk>>1) & 0x3F) + (tk & 0x1) * 30; - eph.setTkSeconds(tk_seconds); - } - - glonass_strings[msg->freq_id()].clear(); - return capnp::messageToFlatArray(msg_builder); -} - - -kj::Array UbloxMsgParser::gen_rxm_sfrbx(ubx_t::rxm_sfrbx_t *msg) { - switch (msg->gnss_id()) { - case ubx_t::gnss_type_t::GNSS_TYPE_GPS: - return parse_gps_ephemeris(msg); - case ubx_t::gnss_type_t::GNSS_TYPE_GLONASS: - return parse_glonass_ephemeris(msg); - default: - return kj::Array(); - } -} - -kj::Array UbloxMsgParser::gen_rxm_rawx(ubx_t::rxm_rawx_t *msg) { - MessageBuilder msg_builder; - auto mr = msg_builder.initEvent().initUbloxGnss().initMeasurementReport(); - mr.setRcvTow(msg->rcv_tow()); - mr.setGpsWeek(msg->week()); - mr.setLeapSeconds(msg->leap_s()); - mr.setGpsWeek(msg->week()); - - auto mb = mr.initMeasurements(msg->num_meas()); - auto measurements = *msg->meas(); - for (int8_t i = 0; i < msg->num_meas(); i++) { - mb[i].setSvId(measurements[i]->sv_id()); - mb[i].setPseudorange(measurements[i]->pr_mes()); - mb[i].setCarrierCycles(measurements[i]->cp_mes()); - mb[i].setDoppler(measurements[i]->do_mes()); - mb[i].setGnssId(measurements[i]->gnss_id()); - mb[i].setGlonassFrequencyIndex(measurements[i]->freq_id()); - mb[i].setLocktime(measurements[i]->lock_time()); - mb[i].setCno(measurements[i]->cno()); - mb[i].setPseudorangeStdev(0.01 * (pow(2, (measurements[i]->pr_stdev() & 15)))); // weird scaling, might be wrong - mb[i].setCarrierPhaseStdev(0.004 * (measurements[i]->cp_stdev() & 15)); - mb[i].setDopplerStdev(0.002 * (pow(2, (measurements[i]->do_stdev() & 15)))); // weird scaling, might be wrong - - auto ts = mb[i].initTrackingStatus(); - auto trk_stat = measurements[i]->trk_stat(); - ts.setPseudorangeValid(bit_to_bool(trk_stat, 0)); - ts.setCarrierPhaseValid(bit_to_bool(trk_stat, 1)); - ts.setHalfCycleValid(bit_to_bool(trk_stat, 2)); - ts.setHalfCycleSubtracted(bit_to_bool(trk_stat, 3)); - } - - mr.setNumMeas(msg->num_meas()); - auto rs = mr.initReceiverStatus(); - rs.setLeapSecValid(bit_to_bool(msg->rec_stat(), 0)); - rs.setClkReset(bit_to_bool(msg->rec_stat(), 2)); - return capnp::messageToFlatArray(msg_builder); -} - -kj::Array UbloxMsgParser::gen_nav_sat(ubx_t::nav_sat_t *msg) { - MessageBuilder msg_builder; - auto sr = msg_builder.initEvent().initUbloxGnss().initSatReport(); - sr.setITow(msg->itow()); - - auto svs = sr.initSvs(msg->num_svs()); - auto svs_data = *msg->svs(); - for (int8_t i = 0; i < msg->num_svs(); i++) { - svs[i].setSvId(svs_data[i]->sv_id()); - svs[i].setGnssId(svs_data[i]->gnss_id()); - svs[i].setFlagsBitfield(svs_data[i]->flags()); - svs[i].setCno(svs_data[i]->cno()); - svs[i].setElevationDeg(svs_data[i]->elev()); - svs[i].setAzimuthDeg(svs_data[i]->azim()); - svs[i].setPseudorangeResidual(svs_data[i]->pr_res() * 0.1); - } - - return capnp::messageToFlatArray(msg_builder); -} - -kj::Array UbloxMsgParser::gen_mon_hw(ubx_t::mon_hw_t *msg) { - MessageBuilder msg_builder; - auto hwStatus = msg_builder.initEvent().initUbloxGnss().initHwStatus(); - hwStatus.setNoisePerMS(msg->noise_per_ms()); - hwStatus.setFlags(msg->flags()); - hwStatus.setAgcCnt(msg->agc_cnt()); - hwStatus.setAStatus((cereal::UbloxGnss::HwStatus::AntennaSupervisorState) msg->a_status()); - hwStatus.setAPower((cereal::UbloxGnss::HwStatus::AntennaPowerStatus) msg->a_power()); - hwStatus.setJamInd(msg->jam_ind()); - return capnp::messageToFlatArray(msg_builder); -} - -kj::Array UbloxMsgParser::gen_mon_hw2(ubx_t::mon_hw2_t *msg) { - MessageBuilder msg_builder; - auto hwStatus = msg_builder.initEvent().initUbloxGnss().initHwStatus2(); - hwStatus.setOfsI(msg->ofs_i()); - hwStatus.setMagI(msg->mag_i()); - hwStatus.setOfsQ(msg->ofs_q()); - hwStatus.setMagQ(msg->mag_q()); - - switch (msg->cfg_source()) { - case ubx_t::mon_hw2_t::config_source_t::CONFIG_SOURCE_ROM: - hwStatus.setCfgSource(cereal::UbloxGnss::HwStatus2::ConfigSource::ROM); - break; - case ubx_t::mon_hw2_t::config_source_t::CONFIG_SOURCE_OTP: - hwStatus.setCfgSource(cereal::UbloxGnss::HwStatus2::ConfigSource::OTP); - break; - case ubx_t::mon_hw2_t::config_source_t::CONFIG_SOURCE_CONFIG_PINS: - hwStatus.setCfgSource(cereal::UbloxGnss::HwStatus2::ConfigSource::CONFIGPINS); - break; - case ubx_t::mon_hw2_t::config_source_t::CONFIG_SOURCE_FLASH: - hwStatus.setCfgSource(cereal::UbloxGnss::HwStatus2::ConfigSource::FLASH); - break; - default: - hwStatus.setCfgSource(cereal::UbloxGnss::HwStatus2::ConfigSource::UNDEFINED); - break; - } - - hwStatus.setLowLevCfg(msg->low_lev_cfg()); - hwStatus.setPostStatus(msg->post_status()); - - return capnp::messageToFlatArray(msg_builder); -} diff --git a/system/ubloxd/ublox_msg.h b/system/ubloxd/ublox_msg.h deleted file mode 100644 index d21760edc2..0000000000 --- a/system/ubloxd/ublox_msg.h +++ /dev/null @@ -1,131 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include "cereal/messaging/messaging.h" -#include "common/util.h" -#include "system/ubloxd/generated/gps.h" -#include "system/ubloxd/generated/glonass.h" -#include "system/ubloxd/generated/ubx.h" - -using namespace std::string_literals; - -const int SECS_IN_MIN = 60; -const int SECS_IN_HR = 60 * SECS_IN_MIN; -const int SECS_IN_DAY = 24 * SECS_IN_HR; -const int SECS_IN_WEEK = 7 * SECS_IN_DAY; - -// protocol constants -namespace ublox { - const uint8_t PREAMBLE1 = 0xb5; - const uint8_t PREAMBLE2 = 0x62; - - const int UBLOX_HEADER_SIZE = 6; - const int UBLOX_CHECKSUM_SIZE = 2; - const int UBLOX_MAX_MSG_SIZE = 65536; - - struct ubx_mga_ini_time_utc_t { - uint8_t type; - uint8_t version; - uint8_t ref; - int8_t leapSecs; - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; - uint8_t reserved1; - uint32_t ns; - uint16_t tAccS; - uint16_t reserved2; - uint32_t tAccNs; - } __attribute__((packed)); - - inline std::string ubx_add_checksum(const std::string &msg) { - assert(msg.size() > 2); - - uint8_t ck_a = 0, ck_b = 0; - for (int i = 2; i < msg.size(); i++) { - ck_a = (ck_a + msg[i]) & 0xFF; - ck_b = (ck_b + ck_a) & 0xFF; - } - - std::string r = msg; - r.push_back(ck_a); - r.push_back(ck_b); - return r; - } - - inline std::string build_ubx_mga_ini_time_utc(struct tm time) { - ublox::ubx_mga_ini_time_utc_t payload = { - .type = 0x10, - .version = 0x0, - .ref = 0x0, - .leapSecs = -128, // Unknown - .year = (uint16_t)(1900 + time.tm_year), - .month = (uint8_t)(1 + time.tm_mon), - .day = (uint8_t)time.tm_mday, - .hour = (uint8_t)time.tm_hour, - .minute = (uint8_t)time.tm_min, - .second = (uint8_t)time.tm_sec, - .reserved1 = 0x0, - .ns = 0, - .tAccS = 30, - .reserved2 = 0x0, - .tAccNs = 0, - }; - assert(sizeof(payload) == 24); - - std::string msg = "\xb5\x62\x13\x40\x18\x00"s; - msg += std::string((char*)&payload, sizeof(payload)); - - return ubx_add_checksum(msg); - } -} - -class UbloxMsgParser { - public: - bool add_data(float log_time, const uint8_t *incoming_data, uint32_t incoming_data_len, size_t &bytes_consumed); - inline void reset() {bytes_in_parse_buf = 0;} - inline int needed_bytes(); - inline std::string data() {return std::string((const char*)msg_parse_buf, bytes_in_parse_buf);} - - std::pair> gen_msg(); - kj::Array gen_nav_pvt(ubx_t::nav_pvt_t *msg); - kj::Array gen_rxm_sfrbx(ubx_t::rxm_sfrbx_t *msg); - kj::Array gen_rxm_rawx(ubx_t::rxm_rawx_t *msg); - kj::Array gen_mon_hw(ubx_t::mon_hw_t *msg); - kj::Array gen_mon_hw2(ubx_t::mon_hw2_t *msg); - kj::Array gen_nav_sat(ubx_t::nav_sat_t *msg); - - private: - inline bool valid_cheksum(); - inline bool valid(); - inline bool valid_so_far(); - - kj::Array parse_gps_ephemeris(ubx_t::rxm_sfrbx_t *msg); - kj::Array parse_glonass_ephemeris(ubx_t::rxm_sfrbx_t *msg); - - std::unordered_map> gps_subframes; - - float last_log_time = 0.0; - size_t bytes_in_parse_buf = 0; - uint8_t msg_parse_buf[ublox::UBLOX_HEADER_SIZE + ublox::UBLOX_MAX_MSG_SIZE]; - - // user range accuracy in meters - const std::unordered_map glonass_URA_lookup = - {{ 0, 1}, { 1, 2}, { 2, 2.5}, { 3, 4}, { 4, 5}, {5, 7}, - { 6, 10}, { 7, 12}, { 8, 14}, { 9, 16}, {10, 32}, - {11, 64}, {12, 128}, {13, 256}, {14, 512}, {15, 1024}}; - - std::unordered_map> glonass_strings; - std::unordered_map> glonass_string_times; - std::unordered_map> glonass_string_superframes; -}; diff --git a/system/ubloxd/ubloxd.cc b/system/ubloxd/ubloxd.cc deleted file mode 100644 index 4e7e91f830..0000000000 --- a/system/ubloxd/ubloxd.cc +++ /dev/null @@ -1,62 +0,0 @@ -#include - -#include - -#include "cereal/messaging/messaging.h" -#include "common/swaglog.h" -#include "common/util.h" -#include "system/ubloxd/ublox_msg.h" - -ExitHandler do_exit; -using namespace ublox; - -int main() { - LOGW("starting ubloxd"); - AlignedBuffer aligned_buf; - UbloxMsgParser parser; - - PubMaster pm({"ubloxGnss", "gpsLocationExternal"}); - - std::unique_ptr context(Context::create()); - std::unique_ptr subscriber(SubSocket::create(context.get(), "ubloxRaw")); - assert(subscriber != NULL); - subscriber->setTimeout(100); - - - while (!do_exit) { - std::unique_ptr msg(subscriber->receive()); - if (!msg) { - continue; - } - - capnp::FlatArrayMessageReader cmsg(aligned_buf.align(msg.get())); - cereal::Event::Reader event = cmsg.getRoot(); - auto ubloxRaw = event.getUbloxRaw(); - float log_time = 1e-9 * event.getLogMonoTime(); - - const uint8_t *data = ubloxRaw.begin(); - size_t len = ubloxRaw.size(); - size_t bytes_consumed = 0; - - while (bytes_consumed < len && !do_exit) { - size_t bytes_consumed_this_time = 0U; - if (parser.add_data(log_time, data + bytes_consumed, (uint32_t)(len - bytes_consumed), bytes_consumed_this_time)) { - - try { - auto ublox_msg = parser.gen_msg(); - if (ublox_msg.second.size() > 0) { - auto bytes = ublox_msg.second.asBytes(); - pm.send(ublox_msg.first.c_str(), bytes.begin(), bytes.size()); - } - } catch (const std::exception& e) { - LOGE("Error parsing ublox message %s", e.what()); - } - - parser.reset(); - } - bytes_consumed += bytes_consumed_this_time; - } - } - - return 0; -} diff --git a/system/ubloxd/ubloxd.py b/system/ubloxd/ubloxd.py new file mode 100755 index 0000000000..84a926dd78 --- /dev/null +++ b/system/ubloxd/ubloxd.py @@ -0,0 +1,519 @@ +#!/usr/bin/env python3 +import math +import capnp +import calendar +import numpy as np +from collections import defaultdict +from dataclasses import dataclass + +from cereal import log +from cereal import messaging +from openpilot.system.ubloxd.generated.ubx import Ubx +from openpilot.system.ubloxd.generated.gps import Gps +from openpilot.system.ubloxd.generated.glonass import Glonass + + +SECS_IN_MIN = 60 +SECS_IN_HR = 60 * SECS_IN_MIN +SECS_IN_DAY = 24 * SECS_IN_HR +SECS_IN_WEEK = 7 * SECS_IN_DAY + + +class UbxFramer: + PREAMBLE1 = 0xB5 + PREAMBLE2 = 0x62 + HEADER_SIZE = 6 + CHECKSUM_SIZE = 2 + + def __init__(self) -> None: + self.buf = bytearray() + self.last_log_time = 0.0 + + def reset(self) -> None: + self.buf.clear() + + @staticmethod + def _checksum_ok(frame: bytes) -> bool: + ck_a = 0 + ck_b = 0 + for b in frame[2:-2]: + ck_a = (ck_a + b) & 0xFF + ck_b = (ck_b + ck_a) & 0xFF + return ck_a == frame[-2] and ck_b == frame[-1] + + def add_data(self, log_time: float, incoming: bytes) -> list[bytes]: + self.last_log_time = log_time + out: list[bytes] = [] + if not incoming: + return out + self.buf += incoming + + while True: + # find preamble + if len(self.buf) < 2: + break + start = self.buf.find(b"\xB5\x62") + if start < 0: + # no preamble in buffer + self.buf.clear() + break + if start > 0: + # drop garbage before preamble + self.buf = self.buf[start:] + + if len(self.buf) < self.HEADER_SIZE: + break + + length_le = int.from_bytes(self.buf[4:6], 'little', signed=False) + total_len = self.HEADER_SIZE + length_le + self.CHECKSUM_SIZE + if len(self.buf) < total_len: + break + + candidate = bytes(self.buf[:total_len]) + if self._checksum_ok(candidate): + out.append(candidate) + # consume this frame + self.buf = self.buf[total_len:] + else: + # drop first byte and retry + self.buf = self.buf[1:] + + return out + + +def _bit(b: int, shift: int) -> bool: + return (b & (1 << shift)) != 0 + + +@dataclass +class EphemerisCaches: + gps_subframes: defaultdict[int, dict[int, bytes]] + glonass_strings: defaultdict[int, dict[int, bytes]] + glonass_string_times: defaultdict[int, dict[int, float]] + glonass_string_superframes: defaultdict[int, dict[int, int]] + + +class UbloxMsgParser: + gpsPi = 3.1415926535898 + + # user range accuracy in meters + glonass_URA_lookup: dict[int, float] = { + 0: 1, 1: 2, 2: 2.5, 3: 4, 4: 5, 5: 7, + 6: 10, 7: 12, 8: 14, 9: 16, 10: 32, + 11: 64, 12: 128, 13: 256, 14: 512, 15: 1024, + } + + def __init__(self) -> None: + self.framer = UbxFramer() + self.caches = EphemerisCaches( + gps_subframes=defaultdict(dict), + glonass_strings=defaultdict(dict), + glonass_string_times=defaultdict(dict), + glonass_string_superframes=defaultdict(dict), + ) + + # Message generation entry point + def parse_frame(self, frame: bytes) -> tuple[str, capnp.lib.capnp._DynamicStructBuilder] | None: + # Quick header parse + msg_type = int.from_bytes(frame[2:4], 'big') + payload = frame[6:-2] + if msg_type == 0x0107: + body = Ubx.NavPvt.from_bytes(payload) + return self._gen_nav_pvt(body) + if msg_type == 0x0213: + # Manually parse RXM-SFRBX to avoid Kaitai EOF on some frames + if len(payload) < 8: + return None + gnss_id = payload[0] + sv_id = payload[1] + freq_id = payload[3] + num_words = payload[4] + exp = 8 + 4 * num_words + if exp != len(payload): + return None + words: list[int] = [] + off = 8 + for _ in range(num_words): + words.append(int.from_bytes(payload[off:off+4], 'little')) + off += 4 + + class _SfrbxView: + def __init__(self, gid: int, sid: int, fid: int, body: list[int]): + self.gnss_id = Ubx.GnssType(gid) + self.sv_id = sid + self.freq_id = fid + self.body = body + view = _SfrbxView(gnss_id, sv_id, freq_id, words) + return self._gen_rxm_sfrbx(view) + if msg_type == 0x0215: + body = Ubx.RxmRawx.from_bytes(payload) + return self._gen_rxm_rawx(body) + if msg_type == 0x0A09: + body = Ubx.MonHw.from_bytes(payload) + return self._gen_mon_hw(body) + if msg_type == 0x0A0B: + body = Ubx.MonHw2.from_bytes(payload) + return self._gen_mon_hw2(body) + if msg_type == 0x0135: + body = Ubx.NavSat.from_bytes(payload) + return self._gen_nav_sat(body) + return None + + # NAV-PVT -> gpsLocationExternal + def _gen_nav_pvt(self, msg: Ubx.NavPvt) -> tuple[str, capnp.lib.capnp._DynamicStructBuilder]: + dat = messaging.new_message('gpsLocationExternal', valid=True) + gps = dat.gpsLocationExternal + gps.source = log.GpsLocationData.SensorSource.ublox + gps.flags = msg.flags + gps.hasFix = (msg.flags % 2) == 1 + gps.latitude = msg.lat * 1e-07 + gps.longitude = msg.lon * 1e-07 + gps.altitude = msg.height * 1e-03 + gps.speed = msg.g_speed * 1e-03 + gps.bearingDeg = msg.head_mot * 1e-5 + gps.horizontalAccuracy = msg.h_acc * 1e-03 + gps.satelliteCount = msg.num_sv + + # build UTC timestamp millis (NAV-PVT is in UTC) + # tolerate invalid or unset date values like C++ timegm + try: + utc_tt = calendar.timegm((msg.year, msg.month, msg.day, msg.hour, msg.min, msg.sec, 0, 0, 0)) + except Exception: + utc_tt = 0 + gps.unixTimestampMillis = int(utc_tt * 1e3 + (msg.nano * 1e-6)) + + # match C++ float32 rounding semantics exactly + gps.vNED = [ + float(np.float32(msg.vel_n) * np.float32(1e-03)), + float(np.float32(msg.vel_e) * np.float32(1e-03)), + float(np.float32(msg.vel_d) * np.float32(1e-03)), + ] + gps.verticalAccuracy = msg.v_acc * 1e-03 + gps.speedAccuracy = msg.s_acc * 1e-03 + gps.bearingAccuracyDeg = msg.head_acc * 1e-05 + return ('gpsLocationExternal', dat) + + # RXM-SFRBX dispatch to GPS or GLONASS ephemeris + def _gen_rxm_sfrbx(self, msg) -> tuple[str, capnp.lib.capnp._DynamicStructBuilder] | None: + if msg.gnss_id == Ubx.GnssType.gps: + return self._parse_gps_ephemeris(msg) + if msg.gnss_id == Ubx.GnssType.glonass: + return self._parse_glonass_ephemeris(msg) + return None + + def _parse_gps_ephemeris(self, msg: Ubx.RxmSfrbx) -> tuple[str, capnp.lib.capnp._DynamicStructBuilder] | None: + # body is list of 10 words; convert to 30-byte subframe (strip parity/padding) + body = msg.body + if len(body) != 10: + return None + subframe_data = bytearray() + for word in body: + word >>= 6 + subframe_data.append((word >> 16) & 0xFF) + subframe_data.append((word >> 8) & 0xFF) + subframe_data.append(word & 0xFF) + + sf = Gps.from_bytes(bytes(subframe_data)) + subframe_id = sf.how.subframe_id + if subframe_id < 1 or subframe_id > 3: + return None + self.caches.gps_subframes[msg.sv_id][subframe_id] = bytes(subframe_data) + + if len(self.caches.gps_subframes[msg.sv_id]) != 3: + return None + + dat = messaging.new_message('ubloxGnss', valid=True) + eph = dat.ubloxGnss.init('ephemeris') + eph.svId = msg.sv_id + + iode_s2 = 0 + iode_s3 = 0 + iodc_lsb = 0 + week = 0 + + # Subframe 1 + sf1 = Gps.from_bytes(self.caches.gps_subframes[msg.sv_id][1]) + s1 = sf1.body + assert isinstance(s1, Gps.Subframe1) + week = s1.week_no + week += 1024 + if week < 1877: + week += 1024 + eph.tgd = s1.t_gd * math.pow(2, -31) + eph.toc = s1.t_oc * math.pow(2, 4) + eph.af2 = s1.af_2 * math.pow(2, -55) + eph.af1 = s1.af_1 * math.pow(2, -43) + eph.af0 = s1.af_0 * math.pow(2, -31) + eph.svHealth = s1.sv_health + eph.towCount = sf1.how.tow_count + iodc_lsb = s1.iodc_lsb + + # Subframe 2 + sf2 = Gps.from_bytes(self.caches.gps_subframes[msg.sv_id][2]) + s2 = sf2.body + assert isinstance(s2, Gps.Subframe2) + if s2.t_oe == 0 and sf2.how.tow_count * 6 >= (SECS_IN_WEEK - 2 * SECS_IN_HR): + week += 1 + eph.crs = s2.c_rs * math.pow(2, -5) + eph.deltaN = s2.delta_n * math.pow(2, -43) * self.gpsPi + eph.m0 = s2.m_0 * math.pow(2, -31) * self.gpsPi + eph.cuc = s2.c_uc * math.pow(2, -29) + eph.ecc = s2.e * math.pow(2, -33) + eph.cus = s2.c_us * math.pow(2, -29) + eph.a = math.pow(s2.sqrt_a * math.pow(2, -19), 2.0) + eph.toe = s2.t_oe * math.pow(2, 4) + iode_s2 = s2.iode + + # Subframe 3 + sf3 = Gps.from_bytes(self.caches.gps_subframes[msg.sv_id][3]) + s3 = sf3.body + assert isinstance(s3, Gps.Subframe3) + eph.cic = s3.c_ic * math.pow(2, -29) + eph.omega0 = s3.omega_0 * math.pow(2, -31) * self.gpsPi + eph.cis = s3.c_is * math.pow(2, -29) + eph.i0 = s3.i_0 * math.pow(2, -31) * self.gpsPi + eph.crc = s3.c_rc * math.pow(2, -5) + eph.omega = s3.omega * math.pow(2, -31) * self.gpsPi + eph.omegaDot = s3.omega_dot * math.pow(2, -43) * self.gpsPi + eph.iode = s3.iode + eph.iDot = s3.idot * math.pow(2, -43) * self.gpsPi + iode_s3 = s3.iode + + eph.toeWeek = week + eph.tocWeek = week + + # clear cache for this SV + self.caches.gps_subframes[msg.sv_id].clear() + if not (iodc_lsb == iode_s2 == iode_s3): + return None + return ('ubloxGnss', dat) + + def _parse_glonass_ephemeris(self, msg: Ubx.RxmSfrbx) -> tuple[str, capnp.lib.capnp._DynamicStructBuilder] | None: + # words are 4 bytes each; Glonass parser expects 16 bytes (string) + body = msg.body + if len(body) != 4: + return None + string_bytes = bytearray() + for word in body: + for i in (3, 2, 1, 0): + string_bytes.append((word >> (8 * i)) & 0xFF) + + gl = Glonass.from_bytes(bytes(string_bytes)) + string_number = gl.string_number + if string_number < 1 or string_number > 5 or gl.idle_chip: + return None + + # correlate by superframe and timing, similar to C++ logic + freq_id = msg.freq_id + superframe_unknown = False + needs_clear = False + for i in range(1, 6): + if i not in self.caches.glonass_strings[freq_id]: + continue + sf_prev = self.caches.glonass_string_superframes[freq_id].get(i, 0) + if sf_prev == 0 or gl.superframe_number == 0: + superframe_unknown = True + elif sf_prev != gl.superframe_number: + needs_clear = True + if superframe_unknown: + prev_time = self.caches.glonass_string_times[freq_id].get(i, 0.0) + if abs((prev_time - 2.0 * i) - (self.framer.last_log_time - 2.0 * string_number)) > 10: + needs_clear = True + + if needs_clear: + self.caches.glonass_strings[freq_id].clear() + self.caches.glonass_string_superframes[freq_id].clear() + self.caches.glonass_string_times[freq_id].clear() + + self.caches.glonass_strings[freq_id][string_number] = bytes(string_bytes) + self.caches.glonass_string_superframes[freq_id][string_number] = gl.superframe_number + self.caches.glonass_string_times[freq_id][string_number] = self.framer.last_log_time + + if msg.sv_id == 255: + # unknown SV id + return None + if len(self.caches.glonass_strings[freq_id]) != 5: + return None + + dat = messaging.new_message('ubloxGnss', valid=True) + eph = dat.ubloxGnss.init('glonassEphemeris') + eph.svId = msg.sv_id + eph.freqNum = msg.freq_id - 7 + + current_day = 0 + tk = 0 + + # string 1 + try: + s1 = Glonass.from_bytes(self.caches.glonass_strings[freq_id][1]).data + except Exception: + return None + assert isinstance(s1, Glonass.String1) + eph.p1 = int(s1.p1) + tk = int(s1.t_k) + eph.tkDEPRECATED = tk + eph.xVel = float(s1.x_vel) * math.pow(2, -20) + eph.xAccel = float(s1.x_accel) * math.pow(2, -30) + eph.x = float(s1.x) * math.pow(2, -11) + + # string 2 + try: + s2 = Glonass.from_bytes(self.caches.glonass_strings[freq_id][2]).data + except Exception: + return None + assert isinstance(s2, Glonass.String2) + eph.svHealth = int(s2.b_n >> 2) + eph.p2 = int(s2.p2) + eph.tb = int(s2.t_b) + eph.yVel = float(s2.y_vel) * math.pow(2, -20) + eph.yAccel = float(s2.y_accel) * math.pow(2, -30) + eph.y = float(s2.y) * math.pow(2, -11) + + # string 3 + try: + s3 = Glonass.from_bytes(self.caches.glonass_strings[freq_id][3]).data + except Exception: + return None + assert isinstance(s3, Glonass.String3) + eph.p3 = int(s3.p3) + eph.gammaN = float(s3.gamma_n) * math.pow(2, -40) + eph.svHealth = int(eph.svHealth | (1 if s3.l_n else 0)) + eph.zVel = float(s3.z_vel) * math.pow(2, -20) + eph.zAccel = float(s3.z_accel) * math.pow(2, -30) + eph.z = float(s3.z) * math.pow(2, -11) + + # string 4 + try: + s4 = Glonass.from_bytes(self.caches.glonass_strings[freq_id][4]).data + except Exception: + return None + assert isinstance(s4, Glonass.String4) + current_day = int(s4.n_t) + eph.nt = current_day + eph.tauN = float(s4.tau_n) * math.pow(2, -30) + eph.deltaTauN = float(s4.delta_tau_n) * math.pow(2, -30) + eph.age = int(s4.e_n) + eph.p4 = int(s4.p4) + eph.svURA = float(self.glonass_URA_lookup.get(int(s4.f_t), 0.0)) + # consistency check: SV slot number + # if it doesn't match, keep going but note mismatch (no logging here) + eph.svType = int(s4.m) + + # string 5 + try: + s5 = Glonass.from_bytes(self.caches.glonass_strings[freq_id][5]).data + except Exception: + return None + assert isinstance(s5, Glonass.String5) + eph.n4 = int(s5.n_4) + tk_seconds = int(SECS_IN_HR * ((tk >> 7) & 0x1F) + SECS_IN_MIN * ((tk >> 1) & 0x3F) + (tk & 0x1) * 30) + eph.tkSeconds = tk_seconds + + self.caches.glonass_strings[freq_id].clear() + return ('ubloxGnss', dat) + + def _gen_rxm_rawx(self, msg: Ubx.RxmRawx) -> tuple[str, capnp.lib.capnp._DynamicStructBuilder]: + dat = messaging.new_message('ubloxGnss', valid=True) + mr = dat.ubloxGnss.init('measurementReport') + mr.rcvTow = msg.rcv_tow + mr.gpsWeek = msg.week + mr.leapSeconds = msg.leap_s + + mb = mr.init('measurements', msg.num_meas) + for i, m in enumerate(msg.meas): + mb[i].svId = m.sv_id + mb[i].pseudorange = m.pr_mes + mb[i].carrierCycles = m.cp_mes + mb[i].doppler = m.do_mes + mb[i].gnssId = int(m.gnss_id.value) + mb[i].glonassFrequencyIndex = m.freq_id + mb[i].locktime = m.lock_time + mb[i].cno = m.cno + mb[i].pseudorangeStdev = 0.01 * (math.pow(2, (m.pr_stdev & 15))) + mb[i].carrierPhaseStdev = 0.004 * (m.cp_stdev & 15) + mb[i].dopplerStdev = 0.002 * (math.pow(2, (m.do_stdev & 15))) + + ts = mb[i].init('trackingStatus') + trk = m.trk_stat + ts.pseudorangeValid = _bit(trk, 0) + ts.carrierPhaseValid = _bit(trk, 1) + ts.halfCycleValid = _bit(trk, 2) + ts.halfCycleSubtracted = _bit(trk, 3) + + mr.numMeas = msg.num_meas + rs = mr.init('receiverStatus') + rs.leapSecValid = _bit(msg.rec_stat, 0) + rs.clkReset = _bit(msg.rec_stat, 2) + return ('ubloxGnss', dat) + + def _gen_nav_sat(self, msg: Ubx.NavSat) -> tuple[str, capnp.lib.capnp._DynamicStructBuilder]: + dat = messaging.new_message('ubloxGnss', valid=True) + sr = dat.ubloxGnss.init('satReport') + sr.iTow = msg.itow + svs = sr.init('svs', msg.num_svs) + for i, s in enumerate(msg.svs): + svs[i].svId = s.sv_id + svs[i].gnssId = int(s.gnss_id.value) + svs[i].flagsBitfield = s.flags + svs[i].cno = s.cno + svs[i].elevationDeg = s.elev + svs[i].azimuthDeg = s.azim + svs[i].pseudorangeResidual = s.pr_res * 0.1 + return ('ubloxGnss', dat) + + def _gen_mon_hw(self, msg: Ubx.MonHw) -> tuple[str, capnp.lib.capnp._DynamicStructBuilder]: + dat = messaging.new_message('ubloxGnss', valid=True) + hw = dat.ubloxGnss.init('hwStatus') + hw.noisePerMS = msg.noise_per_ms + hw.flags = msg.flags + hw.agcCnt = msg.agc_cnt + hw.aStatus = int(msg.a_status.value) + hw.aPower = int(msg.a_power.value) + hw.jamInd = msg.jam_ind + return ('ubloxGnss', dat) + + def _gen_mon_hw2(self, msg: Ubx.MonHw2) -> tuple[str, capnp.lib.capnp._DynamicStructBuilder]: + dat = messaging.new_message('ubloxGnss', valid=True) + hw = dat.ubloxGnss.init('hwStatus2') + hw.ofsI = msg.ofs_i + hw.magI = msg.mag_i + hw.ofsQ = msg.ofs_q + hw.magQ = msg.mag_q + # Map Ubx enum to cereal enum {undefined=0, rom=1, otp=2, configpins=3, flash=4} + cfg_map = { + Ubx.MonHw2.ConfigSource.rom: 1, + Ubx.MonHw2.ConfigSource.otp: 2, + Ubx.MonHw2.ConfigSource.config_pins: 3, + Ubx.MonHw2.ConfigSource.flash: 4, + } + hw.cfgSource = cfg_map.get(msg.cfg_source, 0) + hw.lowLevCfg = msg.low_lev_cfg + hw.postStatus = msg.post_status + return ('ubloxGnss', dat) + + +def main(): + parser = UbloxMsgParser() + pm = messaging.PubMaster(['ubloxGnss', 'gpsLocationExternal']) + sock = messaging.sub_sock('ubloxRaw', timeout=100, conflate=False) + + while True: + msg = messaging.recv_one_or_none(sock) + if msg is None: + continue + + data = bytes(msg.ubloxRaw) + log_time = msg.logMonoTime * 1e-9 + frames = parser.framer.add_data(log_time, data) + for frame in frames: + try: + res = parser.parse_frame(frame) + except Exception: + continue + if not res: + continue + service, dat = res + pm.send(service, dat) + +if __name__ == '__main__': + main() diff --git a/third_party/SConscript b/third_party/SConscript index 507c17c4a5..3a7497d162 100644 --- a/third_party/SConscript +++ b/third_party/SConscript @@ -1,4 +1,3 @@ Import('env') env.Library('json11', ['json11/json11.cpp'], CCFLAGS=env['CCFLAGS'] + ['-Wno-unqualified-std-cast-call']) -env.Library('kaitai', ['kaitai/kaitaistream.cpp'], CPPDEFINES=['KS_STR_ENCODING_NONE']) diff --git a/third_party/kaitai/custom_decoder.h b/third_party/kaitai/custom_decoder.h deleted file mode 100644 index 6da7f5fd23..0000000000 --- a/third_party/kaitai/custom_decoder.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef KAITAI_CUSTOM_DECODER_H -#define KAITAI_CUSTOM_DECODER_H - -#include - -namespace kaitai { - -class custom_decoder { -public: - virtual ~custom_decoder() {}; - virtual std::string decode(std::string src) = 0; -}; - -} - -#endif diff --git a/third_party/kaitai/exceptions.h b/third_party/kaitai/exceptions.h deleted file mode 100644 index 5c09c4672b..0000000000 --- a/third_party/kaitai/exceptions.h +++ /dev/null @@ -1,189 +0,0 @@ -#ifndef KAITAI_EXCEPTIONS_H -#define KAITAI_EXCEPTIONS_H - -#include - -#include -#include - -// We need to use "noexcept" in virtual destructor of our exceptions -// subclasses. Different compilers have different ideas on how to -// achieve that: C++98 compilers prefer `throw()`, C++11 and later -// use `noexcept`. We define KS_NOEXCEPT macro for that. - -#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) -#define KS_NOEXCEPT noexcept -#else -#define KS_NOEXCEPT throw() -#endif - -namespace kaitai { - -/** - * Common ancestor for all error originating from Kaitai Struct usage. - * Stores KSY source path, pointing to an element supposedly guilty of - * an error. - */ -class kstruct_error: public std::runtime_error { -public: - kstruct_error(const std::string what, const std::string src_path): - std::runtime_error(src_path + ": " + what), - m_src_path(src_path) - { - } - - virtual ~kstruct_error() KS_NOEXCEPT {}; - -protected: - const std::string m_src_path; -}; - -/** - * Error that occurs when default endianness should be decided with - * a switch, but nothing matches (although using endianness expression - * implies that there should be some positive result). - */ -class undecided_endianness_error: public kstruct_error { -public: - undecided_endianness_error(const std::string src_path): - kstruct_error("unable to decide on endianness for a type", src_path) - { - } - - virtual ~undecided_endianness_error() KS_NOEXCEPT {}; -}; - -/** - * Common ancestor for all validation failures. Stores pointer to - * KaitaiStream IO object which was involved in an error. - */ -class validation_failed_error: public kstruct_error { -public: - validation_failed_error(const std::string what, kstream* io, const std::string src_path): - kstruct_error("at pos " + kstream::to_string(static_cast(io->pos())) + ": validation failed: " + what, src_path), - m_io(io) - { - } - -// "at pos #{io.pos}: validation failed: #{msg}" - - virtual ~validation_failed_error() KS_NOEXCEPT {}; - -protected: - kstream* m_io; -}; - -/** - * Signals validation failure: we required "actual" value to be equal to - * "expected", but it turned out that it's not. - */ -template -class validation_not_equal_error: public validation_failed_error { -public: - validation_not_equal_error(const T& expected, const T& actual, kstream* io, const std::string src_path): - validation_failed_error("not equal", io, src_path), - m_expected(expected), - m_actual(actual) - { - } - - // "not equal, expected #{expected.inspect}, but got #{actual.inspect}" - - virtual ~validation_not_equal_error() KS_NOEXCEPT {}; - -protected: - const T& m_expected; - const T& m_actual; -}; - -/** - * Signals validation failure: we required "actual" value to be greater - * than or equal to "min", but it turned out that it's not. - */ -template -class validation_less_than_error: public validation_failed_error { -public: - validation_less_than_error(const T& min, const T& actual, kstream* io, const std::string src_path): - validation_failed_error("not in range", io, src_path), - m_min(min), - m_actual(actual) - { - } - - // "not in range, min #{min.inspect}, but got #{actual.inspect}" - - virtual ~validation_less_than_error() KS_NOEXCEPT {}; - -protected: - const T& m_min; - const T& m_actual; -}; - -/** - * Signals validation failure: we required "actual" value to be less - * than or equal to "max", but it turned out that it's not. - */ -template -class validation_greater_than_error: public validation_failed_error { -public: - validation_greater_than_error(const T& max, const T& actual, kstream* io, const std::string src_path): - validation_failed_error("not in range", io, src_path), - m_max(max), - m_actual(actual) - { - } - - // "not in range, max #{max.inspect}, but got #{actual.inspect}" - - virtual ~validation_greater_than_error() KS_NOEXCEPT {}; - -protected: - const T& m_max; - const T& m_actual; -}; - -/** - * Signals validation failure: we required "actual" value to be from - * the list, but it turned out that it's not. - */ -template -class validation_not_any_of_error: public validation_failed_error { -public: - validation_not_any_of_error(const T& actual, kstream* io, const std::string src_path): - validation_failed_error("not any of the list", io, src_path), - m_actual(actual) - { - } - - // "not any of the list, got #{actual.inspect}" - - virtual ~validation_not_any_of_error() KS_NOEXCEPT {}; - -protected: - const T& m_actual; -}; - -/** - * Signals validation failure: we required "actual" value to match - * the expression, but it turned out that it doesn't. - */ -template -class validation_expr_error: public validation_failed_error { -public: - validation_expr_error(const T& actual, kstream* io, const std::string src_path): - validation_failed_error("not matching the expression", io, src_path), - m_actual(actual) - { - } - - // "not matching the expression, got #{actual.inspect}" - - virtual ~validation_expr_error() KS_NOEXCEPT {}; - -protected: - const T& m_actual; -}; - -} - -#endif diff --git a/third_party/kaitai/kaitaistream.cpp b/third_party/kaitai/kaitaistream.cpp deleted file mode 100644 index d82ddb7e82..0000000000 --- a/third_party/kaitai/kaitaistream.cpp +++ /dev/null @@ -1,689 +0,0 @@ -#include - -#if defined(__APPLE__) -#include -#include -#define bswap_16(x) OSSwapInt16(x) -#define bswap_32(x) OSSwapInt32(x) -#define bswap_64(x) OSSwapInt64(x) -#define __BYTE_ORDER BYTE_ORDER -#define __BIG_ENDIAN BIG_ENDIAN -#define __LITTLE_ENDIAN LITTLE_ENDIAN -#elif defined(_MSC_VER) // !__APPLE__ -#include -#define __LITTLE_ENDIAN 1234 -#define __BIG_ENDIAN 4321 -#define __BYTE_ORDER __LITTLE_ENDIAN -#define bswap_16(x) _byteswap_ushort(x) -#define bswap_32(x) _byteswap_ulong(x) -#define bswap_64(x) _byteswap_uint64(x) -#else // !__APPLE__ or !_MSC_VER -#include -#include -#endif - -#include -#include -#include - -kaitai::kstream::kstream(std::istream* io) { - m_io = io; - init(); -} - -kaitai::kstream::kstream(std::string& data): m_io_str(data) { - m_io = &m_io_str; - init(); -} - -void kaitai::kstream::init() { - exceptions_enable(); - align_to_byte(); -} - -void kaitai::kstream::close() { - // m_io->close(); -} - -void kaitai::kstream::exceptions_enable() const { - m_io->exceptions( - std::istream::eofbit | - std::istream::failbit | - std::istream::badbit - ); -} - -// ======================================================================== -// Stream positioning -// ======================================================================== - -bool kaitai::kstream::is_eof() const { - if (m_bits_left > 0) { - return false; - } - char t; - m_io->exceptions( - std::istream::badbit - ); - m_io->get(t); - if (m_io->eof()) { - m_io->clear(); - exceptions_enable(); - return true; - } else { - m_io->unget(); - exceptions_enable(); - return false; - } -} - -void kaitai::kstream::seek(uint64_t pos) { - m_io->seekg(pos); -} - -uint64_t kaitai::kstream::pos() { - return m_io->tellg(); -} - -uint64_t kaitai::kstream::size() { - std::iostream::pos_type cur_pos = m_io->tellg(); - m_io->seekg(0, std::ios::end); - std::iostream::pos_type len = m_io->tellg(); - m_io->seekg(cur_pos); - return len; -} - -// ======================================================================== -// Integer numbers -// ======================================================================== - -// ------------------------------------------------------------------------ -// Signed -// ------------------------------------------------------------------------ - -int8_t kaitai::kstream::read_s1() { - char t; - m_io->get(t); - return t; -} - -// ........................................................................ -// Big-endian -// ........................................................................ - -int16_t kaitai::kstream::read_s2be() { - int16_t t; - m_io->read(reinterpret_cast(&t), 2); -#if __BYTE_ORDER == __LITTLE_ENDIAN - t = bswap_16(t); -#endif - return t; -} - -int32_t kaitai::kstream::read_s4be() { - int32_t t; - m_io->read(reinterpret_cast(&t), 4); -#if __BYTE_ORDER == __LITTLE_ENDIAN - t = bswap_32(t); -#endif - return t; -} - -int64_t kaitai::kstream::read_s8be() { - int64_t t; - m_io->read(reinterpret_cast(&t), 8); -#if __BYTE_ORDER == __LITTLE_ENDIAN - t = bswap_64(t); -#endif - return t; -} - -// ........................................................................ -// Little-endian -// ........................................................................ - -int16_t kaitai::kstream::read_s2le() { - int16_t t; - m_io->read(reinterpret_cast(&t), 2); -#if __BYTE_ORDER == __BIG_ENDIAN - t = bswap_16(t); -#endif - return t; -} - -int32_t kaitai::kstream::read_s4le() { - int32_t t; - m_io->read(reinterpret_cast(&t), 4); -#if __BYTE_ORDER == __BIG_ENDIAN - t = bswap_32(t); -#endif - return t; -} - -int64_t kaitai::kstream::read_s8le() { - int64_t t; - m_io->read(reinterpret_cast(&t), 8); -#if __BYTE_ORDER == __BIG_ENDIAN - t = bswap_64(t); -#endif - return t; -} - -// ------------------------------------------------------------------------ -// Unsigned -// ------------------------------------------------------------------------ - -uint8_t kaitai::kstream::read_u1() { - char t; - m_io->get(t); - return t; -} - -// ........................................................................ -// Big-endian -// ........................................................................ - -uint16_t kaitai::kstream::read_u2be() { - uint16_t t; - m_io->read(reinterpret_cast(&t), 2); -#if __BYTE_ORDER == __LITTLE_ENDIAN - t = bswap_16(t); -#endif - return t; -} - -uint32_t kaitai::kstream::read_u4be() { - uint32_t t; - m_io->read(reinterpret_cast(&t), 4); -#if __BYTE_ORDER == __LITTLE_ENDIAN - t = bswap_32(t); -#endif - return t; -} - -uint64_t kaitai::kstream::read_u8be() { - uint64_t t; - m_io->read(reinterpret_cast(&t), 8); -#if __BYTE_ORDER == __LITTLE_ENDIAN - t = bswap_64(t); -#endif - return t; -} - -// ........................................................................ -// Little-endian -// ........................................................................ - -uint16_t kaitai::kstream::read_u2le() { - uint16_t t; - m_io->read(reinterpret_cast(&t), 2); -#if __BYTE_ORDER == __BIG_ENDIAN - t = bswap_16(t); -#endif - return t; -} - -uint32_t kaitai::kstream::read_u4le() { - uint32_t t; - m_io->read(reinterpret_cast(&t), 4); -#if __BYTE_ORDER == __BIG_ENDIAN - t = bswap_32(t); -#endif - return t; -} - -uint64_t kaitai::kstream::read_u8le() { - uint64_t t; - m_io->read(reinterpret_cast(&t), 8); -#if __BYTE_ORDER == __BIG_ENDIAN - t = bswap_64(t); -#endif - return t; -} - -// ======================================================================== -// Floating point numbers -// ======================================================================== - -// ........................................................................ -// Big-endian -// ........................................................................ - -float kaitai::kstream::read_f4be() { - uint32_t t; - m_io->read(reinterpret_cast(&t), 4); -#if __BYTE_ORDER == __LITTLE_ENDIAN - t = bswap_32(t); -#endif - return reinterpret_cast(t); -} - -double kaitai::kstream::read_f8be() { - uint64_t t; - m_io->read(reinterpret_cast(&t), 8); -#if __BYTE_ORDER == __LITTLE_ENDIAN - t = bswap_64(t); -#endif - return reinterpret_cast(t); -} - -// ........................................................................ -// Little-endian -// ........................................................................ - -float kaitai::kstream::read_f4le() { - uint32_t t; - m_io->read(reinterpret_cast(&t), 4); -#if __BYTE_ORDER == __BIG_ENDIAN - t = bswap_32(t); -#endif - return reinterpret_cast(t); -} - -double kaitai::kstream::read_f8le() { - uint64_t t; - m_io->read(reinterpret_cast(&t), 8); -#if __BYTE_ORDER == __BIG_ENDIAN - t = bswap_64(t); -#endif - return reinterpret_cast(t); -} - -// ======================================================================== -// Unaligned bit values -// ======================================================================== - -void kaitai::kstream::align_to_byte() { - m_bits_left = 0; - m_bits = 0; -} - -uint64_t kaitai::kstream::read_bits_int_be(int n) { - int bits_needed = n - m_bits_left; - if (bits_needed > 0) { - // 1 bit => 1 byte - // 8 bits => 1 byte - // 9 bits => 2 bytes - int bytes_needed = ((bits_needed - 1) / 8) + 1; - if (bytes_needed > 8) - throw std::runtime_error("read_bits_int: more than 8 bytes requested"); - char buf[8]; - m_io->read(buf, bytes_needed); - for (int i = 0; i < bytes_needed; i++) { - uint8_t b = buf[i]; - m_bits <<= 8; - m_bits |= b; - m_bits_left += 8; - } - } - - // raw mask with required number of 1s, starting from lowest bit - uint64_t mask = get_mask_ones(n); - // shift mask to align with highest bits available in @bits - int shift_bits = m_bits_left - n; - mask <<= shift_bits; - // derive reading result - uint64_t res = (m_bits & mask) >> shift_bits; - // clear top bits that we've just read => AND with 1s - m_bits_left -= n; - mask = get_mask_ones(m_bits_left); - m_bits &= mask; - - return res; -} - -// Deprecated, use read_bits_int_be() instead. -uint64_t kaitai::kstream::read_bits_int(int n) { - return read_bits_int_be(n); -} - -uint64_t kaitai::kstream::read_bits_int_le(int n) { - int bits_needed = n - m_bits_left; - if (bits_needed > 0) { - // 1 bit => 1 byte - // 8 bits => 1 byte - // 9 bits => 2 bytes - int bytes_needed = ((bits_needed - 1) / 8) + 1; - if (bytes_needed > 8) - throw std::runtime_error("read_bits_int_le: more than 8 bytes requested"); - char buf[8]; - m_io->read(buf, bytes_needed); - for (int i = 0; i < bytes_needed; i++) { - uint8_t b = buf[i]; - m_bits |= (static_cast(b) << m_bits_left); - m_bits_left += 8; - } - } - - // raw mask with required number of 1s, starting from lowest bit - uint64_t mask = get_mask_ones(n); - // derive reading result - uint64_t res = m_bits & mask; - // remove bottom bits that we've just read by shifting - m_bits >>= n; - m_bits_left -= n; - - return res; -} - -uint64_t kaitai::kstream::get_mask_ones(int n) { - if (n == 64) { - return 0xFFFFFFFFFFFFFFFF; - } else { - return ((uint64_t) 1 << n) - 1; - } -} - -// ======================================================================== -// Byte arrays -// ======================================================================== - -std::string kaitai::kstream::read_bytes(std::streamsize len) { - std::vector result(len); - - // NOTE: streamsize type is signed, negative values are only *supposed* to not be used. - // http://en.cppreference.com/w/cpp/io/streamsize - if (len < 0) { - throw std::runtime_error("read_bytes: requested a negative amount"); - } - - if (len > 0) { - m_io->read(&result[0], len); - } - - return std::string(result.begin(), result.end()); -} - -std::string kaitai::kstream::read_bytes_full() { - std::iostream::pos_type p1 = m_io->tellg(); - m_io->seekg(0, std::ios::end); - std::iostream::pos_type p2 = m_io->tellg(); - size_t len = p2 - p1; - - // Note: this requires a std::string to be backed with a - // contiguous buffer. Officially, it's a only requirement since - // C++11 (C++98 and C++03 didn't have this requirement), but all - // major implementations had contiguous buffers anyway. - std::string result(len, ' '); - m_io->seekg(p1); - m_io->read(&result[0], len); - - return result; -} - -std::string kaitai::kstream::read_bytes_term(char term, bool include, bool consume, bool eos_error) { - std::string result; - std::getline(*m_io, result, term); - if (m_io->eof()) { - // encountered EOF - if (eos_error) { - throw std::runtime_error("read_bytes_term: encountered EOF"); - } - } else { - // encountered terminator - if (include) - result.push_back(term); - if (!consume) - m_io->unget(); - } - return result; -} - -std::string kaitai::kstream::ensure_fixed_contents(std::string expected) { - std::string actual = read_bytes(expected.length()); - - if (actual != expected) { - // NOTE: I think printing it outright is not best idea, it could contain non-ascii charactes like backspace and beeps and whatnot. It would be better to print hexlified version, and also to redirect it to stderr. - throw std::runtime_error("ensure_fixed_contents: actual data does not match expected data"); - } - - return actual; -} - -std::string kaitai::kstream::bytes_strip_right(std::string src, char pad_byte) { - std::size_t new_len = src.length(); - - while (new_len > 0 && src[new_len - 1] == pad_byte) - new_len--; - - return src.substr(0, new_len); -} - -std::string kaitai::kstream::bytes_terminate(std::string src, char term, bool include) { - std::size_t new_len = 0; - std::size_t max_len = src.length(); - - while (new_len < max_len && src[new_len] != term) - new_len++; - - if (include && new_len < max_len) - new_len++; - - return src.substr(0, new_len); -} - -// ======================================================================== -// Byte array processing -// ======================================================================== - -std::string kaitai::kstream::process_xor_one(std::string data, uint8_t key) { - size_t len = data.length(); - std::string result(len, ' '); - - for (size_t i = 0; i < len; i++) - result[i] = data[i] ^ key; - - return result; -} - -std::string kaitai::kstream::process_xor_many(std::string data, std::string key) { - size_t len = data.length(); - size_t kl = key.length(); - std::string result(len, ' '); - - size_t ki = 0; - for (size_t i = 0; i < len; i++) { - result[i] = data[i] ^ key[ki]; - ki++; - if (ki >= kl) - ki = 0; - } - - return result; -} - -std::string kaitai::kstream::process_rotate_left(std::string data, int amount) { - size_t len = data.length(); - std::string result(len, ' '); - - for (size_t i = 0; i < len; i++) { - uint8_t bits = data[i]; - result[i] = (bits << amount) | (bits >> (8 - amount)); - } - - return result; -} - -#ifdef KS_ZLIB -#include - -std::string kaitai::kstream::process_zlib(std::string data) { - int ret; - - unsigned char *src_ptr = reinterpret_cast(&data[0]); - std::stringstream dst_strm; - - z_stream strm; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - - ret = inflateInit(&strm); - if (ret != Z_OK) - throw std::runtime_error("process_zlib: inflateInit error"); - - strm.next_in = src_ptr; - strm.avail_in = data.length(); - - unsigned char outbuffer[ZLIB_BUF_SIZE]; - std::string outstring; - - // get the decompressed bytes blockwise using repeated calls to inflate - do { - strm.next_out = reinterpret_cast(outbuffer); - strm.avail_out = sizeof(outbuffer); - - ret = inflate(&strm, 0); - - if (outstring.size() < strm.total_out) - outstring.append(reinterpret_cast(outbuffer), strm.total_out - outstring.size()); - } while (ret == Z_OK); - - if (ret != Z_STREAM_END) { // an error occurred that was not EOF - std::ostringstream exc_msg; - exc_msg << "process_zlib: error #" << ret << "): " << strm.msg; - throw std::runtime_error(exc_msg.str()); - } - - if (inflateEnd(&strm) != Z_OK) - throw std::runtime_error("process_zlib: inflateEnd error"); - - return outstring; -} -#endif - -// ======================================================================== -// Misc utility methods -// ======================================================================== - -int kaitai::kstream::mod(int a, int b) { - if (b <= 0) - throw std::invalid_argument("mod: divisor b <= 0"); - int r = a % b; - if (r < 0) - r += b; - return r; -} - -#include -std::string kaitai::kstream::to_string(int val) { - // if int is 32 bits, "-2147483648" is the longest string representation - // => 11 chars + zero => 12 chars - // if int is 64 bits, "-9223372036854775808" is the longest - // => 20 chars + zero => 21 chars - char buf[25]; - int got_len = snprintf(buf, sizeof(buf), "%d", val); - - // should never happen, but check nonetheless - if (got_len > sizeof(buf)) - throw std::invalid_argument("to_string: integer is longer than string buffer"); - - return std::string(buf); -} - -#include -std::string kaitai::kstream::reverse(std::string val) { - std::reverse(val.begin(), val.end()); - - return val; -} - -uint8_t kaitai::kstream::byte_array_min(const std::string val) { - uint8_t min = 0xff; // UINT8_MAX - std::string::const_iterator end = val.end(); - for (std::string::const_iterator it = val.begin(); it != end; ++it) { - uint8_t cur = static_cast(*it); - if (cur < min) { - min = cur; - } - } - return min; -} - -uint8_t kaitai::kstream::byte_array_max(const std::string val) { - uint8_t max = 0; // UINT8_MIN - std::string::const_iterator end = val.end(); - for (std::string::const_iterator it = val.begin(); it != end; ++it) { - uint8_t cur = static_cast(*it); - if (cur > max) { - max = cur; - } - } - return max; -} - -// ======================================================================== -// Other internal methods -// ======================================================================== - -#ifndef KS_STR_DEFAULT_ENCODING -#define KS_STR_DEFAULT_ENCODING "UTF-8" -#endif - -#ifdef KS_STR_ENCODING_ICONV - -#include -#include -#include - -std::string kaitai::kstream::bytes_to_str(std::string src, std::string src_enc) { - iconv_t cd = iconv_open(KS_STR_DEFAULT_ENCODING, src_enc.c_str()); - - if (cd == (iconv_t) -1) { - if (errno == EINVAL) { - throw std::runtime_error("bytes_to_str: invalid encoding pair conversion requested"); - } else { - throw std::runtime_error("bytes_to_str: error opening iconv"); - } - } - - size_t src_len = src.length(); - size_t src_left = src_len; - - // Start with a buffer length of double the source length. - size_t dst_len = src_len * 2; - std::string dst(dst_len, ' '); - size_t dst_left = dst_len; - - char *src_ptr = &src[0]; - char *dst_ptr = &dst[0]; - - while (true) { - size_t res = iconv(cd, &src_ptr, &src_left, &dst_ptr, &dst_left); - - if (res == (size_t) -1) { - if (errno == E2BIG) { - // dst buffer is not enough to accomodate whole string - // enlarge the buffer and try again - size_t dst_used = dst_len - dst_left; - dst_left += dst_len; - dst_len += dst_len; - dst.resize(dst_len); - - // dst.resize might have allocated destination buffer in another area - // of memory, thus our previous pointer "dst" will be invalid; re-point - // it using "dst_used". - dst_ptr = &dst[dst_used]; - } else { - throw std::runtime_error("bytes_to_str: iconv error"); - } - } else { - // conversion successful - dst.resize(dst_len - dst_left); - break; - } - } - - if (iconv_close(cd) != 0) { - throw std::runtime_error("bytes_to_str: iconv close error"); - } - - return dst; -} -#elif defined(KS_STR_ENCODING_NONE) -std::string kaitai::kstream::bytes_to_str(std::string src, std::string src_enc) { - return src; -} -#else -#error Need to decide how to handle strings: please define one of: KS_STR_ENCODING_ICONV, KS_STR_ENCODING_NONE -#endif diff --git a/third_party/kaitai/kaitaistream.h b/third_party/kaitai/kaitaistream.h deleted file mode 100644 index e7f4c6ce34..0000000000 --- a/third_party/kaitai/kaitaistream.h +++ /dev/null @@ -1,268 +0,0 @@ -#ifndef KAITAI_STREAM_H -#define KAITAI_STREAM_H - -// Kaitai Struct runtime API version: x.y.z = 'xxxyyyzzz' decimal -#define KAITAI_STRUCT_VERSION 9000L - -#include -#include -#include -#include - -namespace kaitai { - -/** - * Kaitai Stream class (kaitai::kstream) is an implementation of - * Kaitai Struct stream API - * for C++/STL. It's implemented as a wrapper over generic STL std::istream. - * - * It provides a wide variety of simple methods to read (parse) binary - * representations of primitive types, such as integer and floating - * point numbers, byte arrays and strings, and also provides stream - * positioning / navigation methods with unified cross-language and - * cross-toolkit semantics. - * - * Typically, end users won't access Kaitai Stream class manually, but would - * describe a binary structure format using .ksy language and then would use - * Kaitai Struct compiler to generate source code in desired target language. - * That code, in turn, would use this class and API to do the actual parsing - * job. - */ -class kstream { -public: - /** - * Constructs new Kaitai Stream object, wrapping a given std::istream. - * \param io istream object to use for this Kaitai Stream - */ - kstream(std::istream* io); - - /** - * Constructs new Kaitai Stream object, wrapping a given in-memory data - * buffer. - * \param data data buffer to use for this Kaitai Stream - */ - kstream(std::string& data); - - void close(); - - /** @name Stream positioning */ - //@{ - /** - * Check if stream pointer is at the end of stream. Note that the semantics - * are different from traditional STL semantics: one does *not* need to do a - * read (which will fail) after the actual end of the stream to trigger EOF - * flag, which can be accessed after that read. It is sufficient to just be - * at the end of the stream for this method to return true. - * \return "true" if we are located at the end of the stream. - */ - bool is_eof() const; - - /** - * Set stream pointer to designated position. - * \param pos new position (offset in bytes from the beginning of the stream) - */ - void seek(uint64_t pos); - - /** - * Get current position of a stream pointer. - * \return pointer position, number of bytes from the beginning of the stream - */ - uint64_t pos(); - - /** - * Get total size of the stream in bytes. - * \return size of the stream in bytes - */ - uint64_t size(); - //@} - - /** @name Integer numbers */ - //@{ - - // ------------------------------------------------------------------------ - // Signed - // ------------------------------------------------------------------------ - - int8_t read_s1(); - - // ........................................................................ - // Big-endian - // ........................................................................ - - int16_t read_s2be(); - int32_t read_s4be(); - int64_t read_s8be(); - - // ........................................................................ - // Little-endian - // ........................................................................ - - int16_t read_s2le(); - int32_t read_s4le(); - int64_t read_s8le(); - - // ------------------------------------------------------------------------ - // Unsigned - // ------------------------------------------------------------------------ - - uint8_t read_u1(); - - // ........................................................................ - // Big-endian - // ........................................................................ - - uint16_t read_u2be(); - uint32_t read_u4be(); - uint64_t read_u8be(); - - // ........................................................................ - // Little-endian - // ........................................................................ - - uint16_t read_u2le(); - uint32_t read_u4le(); - uint64_t read_u8le(); - - //@} - - /** @name Floating point numbers */ - //@{ - - // ........................................................................ - // Big-endian - // ........................................................................ - - float read_f4be(); - double read_f8be(); - - // ........................................................................ - // Little-endian - // ........................................................................ - - float read_f4le(); - double read_f8le(); - - //@} - - /** @name Unaligned bit values */ - //@{ - - void align_to_byte(); - uint64_t read_bits_int_be(int n); - uint64_t read_bits_int(int n); - uint64_t read_bits_int_le(int n); - - //@} - - /** @name Byte arrays */ - //@{ - - std::string read_bytes(std::streamsize len); - std::string read_bytes_full(); - std::string read_bytes_term(char term, bool include, bool consume, bool eos_error); - std::string ensure_fixed_contents(std::string expected); - - static std::string bytes_strip_right(std::string src, char pad_byte); - static std::string bytes_terminate(std::string src, char term, bool include); - static std::string bytes_to_str(std::string src, std::string src_enc); - - //@} - - /** @name Byte array processing */ - //@{ - - /** - * Performs a XOR processing with given data, XORing every byte of input with a single - * given value. - * @param data data to process - * @param key value to XOR with - * @return processed data - */ - static std::string process_xor_one(std::string data, uint8_t key); - - /** - * Performs a XOR processing with given data, XORing every byte of input with a key - * array, repeating key array many times, if necessary (i.e. if data array is longer - * than key array). - * @param data data to process - * @param key array of bytes to XOR with - * @return processed data - */ - static std::string process_xor_many(std::string data, std::string key); - - /** - * Performs a circular left rotation shift for a given buffer by a given amount of bits, - * using groups of 1 bytes each time. Right circular rotation should be performed - * using this procedure with corrected amount. - * @param data source data to process - * @param amount number of bits to shift by - * @return copy of source array with requested shift applied - */ - static std::string process_rotate_left(std::string data, int amount); - -#ifdef KS_ZLIB - /** - * Performs an unpacking ("inflation") of zlib-compressed data with usual zlib headers. - * @param data data to unpack - * @return unpacked data - * @throws IOException - */ - static std::string process_zlib(std::string data); -#endif - - //@} - - /** - * Performs modulo operation between two integers: dividend `a` - * and divisor `b`. Divisor `b` is expected to be positive. The - * result is always 0 <= x <= b - 1. - */ - static int mod(int a, int b); - - /** - * Converts given integer `val` to a decimal string representation. - * Should be used in place of std::to_string() (which is available only - * since C++11) in older C++ implementations. - */ - static std::string to_string(int val); - - /** - * Reverses given string `val`, so that the first character becomes the - * last and the last one becomes the first. This should be used to avoid - * the need of local variables at the caller. - */ - static std::string reverse(std::string val); - - /** - * Finds the minimal byte in a byte array, treating bytes as - * unsigned values. - * @param val byte array to scan - * @return minimal byte in byte array as integer - */ - static uint8_t byte_array_min(const std::string val); - - /** - * Finds the maximal byte in a byte array, treating bytes as - * unsigned values. - * @param val byte array to scan - * @return maximal byte in byte array as integer - */ - static uint8_t byte_array_max(const std::string val); - -private: - std::istream* m_io; - std::istringstream m_io_str; - int m_bits_left; - uint64_t m_bits; - - void init(); - void exceptions_enable() const; - - static uint64_t get_mask_ones(int n); - - static const int ZLIB_BUF_SIZE = 128 * 1024; -}; - -} - -#endif diff --git a/third_party/kaitai/kaitaistruct.h b/third_party/kaitai/kaitaistruct.h deleted file mode 100644 index 8172ede6c9..0000000000 --- a/third_party/kaitai/kaitaistruct.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef KAITAI_STRUCT_H -#define KAITAI_STRUCT_H - -#include - -namespace kaitai { - -class kstruct { -public: - kstruct(kstream *_io) { m__io = _io; } - virtual ~kstruct() {} -protected: - kstream *m__io; -public: - kstream *_io() { return m__io; } -}; - -} - -#endif From 698e0ca00f53f8ed211aee698d48ace29302d57c Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sun, 7 Sep 2025 23:23:03 -0400 Subject: [PATCH 056/159] migration: new branch names (#1225) * migration: new branch names * more migration * update channel type * no more var * update * more * more --- .github/workflows/auto_pr_review.yaml | 8 ++++---- .github/workflows/sunnypilot-build-prebuilt.yaml | 6 +++--- ...c3-prep.yaml => sunnypilot-master-dev-prep.yaml} | 12 ++++++------ release/ci/squash_and_merge_prs.py | 2 +- system/version.py | 13 ++++++++----- 5 files changed, 22 insertions(+), 19 deletions(-) rename .github/workflows/{sunnypilot-master-dev-c3-prep.yaml => sunnypilot-master-dev-prep.yaml} (95%) diff --git a/.github/workflows/auto_pr_review.yaml b/.github/workflows/auto_pr_review.yaml index b9664b9066..cedeee1741 100644 --- a/.github/workflows/auto_pr_review.yaml +++ b/.github/workflows/auto_pr_review.yaml @@ -40,10 +40,10 @@ jobs: runs-on: ubuntu-latest if: (github.event.pull_request.head.repo.fork && (contains(github.event_name, 'pull_request') && github.event.action == 'synchronize')) env: - PR_LABEL: 'dev-c3' + PR_LABEL: 'dev' TRUST_FORK_PR_LABEL: 'trust-fork-pr' steps: - - name: Check if PR has dev-c3 label + - name: Check if PR has dev label id: check-labels uses: actions/github-script@v7 with: @@ -62,11 +62,11 @@ jobs: console.log(`PR #${prNumber} has ${process.env.PR_LABEL} label: ${hasDevC3Label}`); console.log(`PR #${prNumber} has ${process.env.TRUST_FORK_PR_LABEL} label: ${hasTrustLabel}`); - core.setOutput('has-dev-c3', hasDevC3Label ? 'true' : 'false'); + core.setOutput('has-dev', hasDevC3Label ? 'true' : 'false'); core.setOutput('has-trust', hasTrustLabel ? 'true' : 'false'); - name: Remove trust-fork-pr label if present - if: steps.check-labels.outputs.has-dev-c3 == 'true' && steps.check-labels.outputs.has-trust == 'true' + if: steps.check-labels.outputs.has-dev == 'true' && steps.check-labels.outputs.has-trust == 'true' uses: actions/github-script@v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/sunnypilot-build-prebuilt.yaml b/.github/workflows/sunnypilot-build-prebuilt.yaml index d654f5ab46..00ae1e28bf 100644 --- a/.github/workflows/sunnypilot-build-prebuilt.yaml +++ b/.github/workflows/sunnypilot-build-prebuilt.yaml @@ -8,14 +8,14 @@ env: PUBLIC_REPO_URL: "https://github.com/sunnypilot/sunnypilot" # Branch configurations - STAGING_C3_SOURCE_BRANCH: ${{ vars.STAGING_C3_SOURCE_BRANCH || 'master' }} # vars are set on repo settings. + STAGING_SOURCE_BRANCH: 'master' # Runtime configuration SOURCE_BRANCH: "${{ github.head_ref || github.ref_name }}" on: push: - branches: [ master, master-dev-c3-new ] + branches: [ master, master-dev ] tags: [ 'release/*' ] pull_request_target: types: [ labeled ] @@ -138,7 +138,7 @@ jobs: # for security. Only caches from the default branch are shared across all builds. This is by design and cannot be overridden. restore-keys: | scons-${{ runner.os }}-${{ runner.arch }}-${{ env.SOURCE_BRANCH }} - scons-${{ runner.os }}-${{ runner.arch }}-${{ env.STAGING_C3_SOURCE_BRANCH }} + scons-${{ runner.os }}-${{ runner.arch }}-${{ env.STAGING_SOURCE_BRANCH }} scons-${{ runner.os }}-${{ runner.arch }} - name: Set environment variables diff --git a/.github/workflows/sunnypilot-master-dev-c3-prep.yaml b/.github/workflows/sunnypilot-master-dev-prep.yaml similarity index 95% rename from .github/workflows/sunnypilot-master-dev-c3-prep.yaml rename to .github/workflows/sunnypilot-master-dev-prep.yaml index d4c201824e..122755f2c4 100644 --- a/.github/workflows/sunnypilot-master-dev-c3-prep.yaml +++ b/.github/workflows/sunnypilot-master-dev-prep.yaml @@ -1,9 +1,9 @@ -name: Build dev-c3-new +name: Build dev env: DEFAULT_SOURCE_BRANCH: "master" - DEFAULT_TARGET_BRANCH: "master-dev-c3-new" - PR_LABEL: "dev-c3" + DEFAULT_TARGET_BRANCH: "master-dev" + PR_LABEL: "dev" LFS_URL: 'https://gitlab.com/sunnypilot/public/sunnypilot-new-lfs.git/info/lfs' LFS_PUSH_URL: 'ssh://git@gitlab.com/sunnypilot/public/sunnypilot-new-lfs.git' @@ -25,7 +25,7 @@ on: target_branch: description: 'Target branch to reset and squash into' required: true - default: 'master-dev-c3-new' + default: 'master-dev' type: string cancel_in_progress: description: 'Cancel any in-progress runs of this workflow' @@ -43,7 +43,7 @@ jobs: if: ( (github.event_name == 'workflow_dispatch') || (github.event_name == 'push' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)) - || (contains(github.event_name, 'pull_request') && ((github.event.action == 'labeled' && (github.event.label.name == 'dev-c3' || github.event.label.name == 'trust-fork-pr') && contains(github.event.pull_request.labels.*.name, 'dev-c3')))) + || (contains(github.event_name, 'pull_request') && ((github.event.action == 'labeled' && (github.event.label.name == 'dev' || github.event.label.name == 'trust-fork-pr') && contains(github.event.pull_request.labels.*.name, 'dev')))) ) steps: - uses: actions/checkout@v4 @@ -55,7 +55,7 @@ jobs: uses: ./.github/workflows/wait-for-action # Path to where you place the action if: ( (github.event_name == 'push' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)) - || (contains(github.event_name, 'pull_request') && ((github.event.action == 'labeled' && (github.event.label.name == 'dev-c3' || github.event.label.name == 'trust-fork-pr') && contains(github.event.pull_request.labels.*.name, 'dev-c3')))) + || (contains(github.event_name, 'pull_request') && ((github.event.action == 'labeled' && (github.event.label.name == 'dev' || github.event.label.name == 'trust-fork-pr') && contains(github.event.pull_request.labels.*.name, 'dev')))) ) with: workflow: selfdrive_tests.yaml # The workflow file to monitor diff --git a/release/ci/squash_and_merge_prs.py b/release/ci/squash_and_merge_prs.py index 0f20f4f900..24922288be 100755 --- a/release/ci/squash_and_merge_prs.py +++ b/release/ci/squash_and_merge_prs.py @@ -14,7 +14,7 @@ def setup_argument_parser(): parser.add_argument('--pr-data', type=str, help='PR data in JSON format') parser.add_argument('--source-branch', type=str, default='master', help='Source branch for merging') - parser.add_argument('--target-branch', type=str, default='master-dev-c3-new-test', + parser.add_argument('--target-branch', type=str, default='master-dev-test', help='Target branch for merging') parser.add_argument('--squash-script-path', type=str, required=True, help='Path to the squash_and_merge.py script') diff --git a/system/version.py b/system/version.py index 87044b84a8..9719311b7e 100755 --- a/system/version.py +++ b/system/version.py @@ -10,8 +10,8 @@ from openpilot.common.basedir import BASEDIR from openpilot.common.swaglog import cloudlog from openpilot.common.git import get_commit, get_origin, get_branch, get_short_branch, get_commit_date -RELEASE_SP_BRANCHES = ['release-c3'] -TESTED_SP_BRANCHES = ['staging-c3', 'staging-c3-new'] +RELEASE_SP_BRANCHES = ['release-c3', 'release'] +TESTED_SP_BRANCHES = ['staging-c3', 'staging-c3-new', 'staging'] MASTER_SP_BRANCHES = ['master'] RELEASE_BRANCHES = ['release3-staging', 'release3', 'release-tici', 'nightly'] + RELEASE_SP_BRANCHES TESTED_BRANCHES = RELEASE_BRANCHES + ['devel', 'devel-staging', 'nightly-dev'] + TESTED_SP_BRANCHES @@ -21,6 +21,9 @@ SP_BRANCH_MIGRATIONS = { ("tici", "dev-c3-new"): "staging-tici", ("tici", "master"): "master-tici", ("tici", "master-dev-c3-new"): "master-tici", + ("tizi", "staging-c3-new"): "staging", + ("tizi", "dev-c3-new"): "dev", + ("tizi", "master-dev-c3-new"): "master-dev", } BUILD_METADATA_FILENAME = "build.json" @@ -131,7 +134,7 @@ class BuildMetadata: @property def development_channel(self) -> bool: - return self.channel.startswith("dev-") or self.channel.endswith("-prebuilt") + return self.channel == "dev" or self.channel.startswith("dev-") or self.channel.endswith("-prebuilt") @property def channel_type(self) -> str: @@ -139,11 +142,11 @@ class BuildMetadata: return "tici" elif self.development_channel: return "development" - elif self.channel.startswith("staging-"): + elif self.tested_channel: return "staging" elif self.master_channel: return "master" - elif self.tested_channel: + elif self.release_channel: return "release" else: return "feature" From 0739d4ac2d9ef05dd1dad3143a957c1c663f627c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 09:01:53 -0700 Subject: [PATCH 057/159] [bot] Update translations (#36089) Update translations Co-authored-by: Vehicle Researcher --- selfdrive/ui/translations/main_ar.ts | 14 -------------- selfdrive/ui/translations/main_de.ts | 14 -------------- selfdrive/ui/translations/main_es.ts | 14 -------------- selfdrive/ui/translations/main_fr.ts | 14 -------------- selfdrive/ui/translations/main_ja.ts | 14 -------------- selfdrive/ui/translations/main_ko.ts | 14 -------------- selfdrive/ui/translations/main_pt-BR.ts | 16 ---------------- selfdrive/ui/translations/main_th.ts | 14 -------------- selfdrive/ui/translations/main_tr.ts | 14 -------------- selfdrive/ui/translations/main_zh-CHS.ts | 16 ---------------- selfdrive/ui/translations/main_zh-CHT.ts | 16 ---------------- 11 files changed, 160 deletions(-) diff --git a/selfdrive/ui/translations/main_ar.ts b/selfdrive/ui/translations/main_ar.ts index ff2e7ab05c..381712770e 100644 --- a/selfdrive/ui/translations/main_ar.ts +++ b/selfdrive/ui/translations/main_ar.ts @@ -482,10 +482,6 @@ Firehose Mode allows you to maximize your training data uploads to improve openp An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. يتم تنزيل تحديث لنظام تشغيل جهازك في الخلفية. سيطلَب منك التحديث عندما يصبح جاهزاً للتثبيت. - - NVMe drive not mounted. - محرك NVMe غير مثبَّت. - openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. لم يكن openpilot قادراً على تحديد سيارتك. إما أن تكون سيارتك غير مدعومة أو أنه لم يتم التعرف على وحدة التحكم الإلكتروني (ECUs) فيها. يرجى تقديم طلب سحب من أجل إضافة نسخ برمجيات ثابتة إلى السيارة المناسبة. هل تحتاج إلى أي مساعدة؟ لا تتردد في التواصل مع doscord.comma.ai. @@ -1052,16 +1048,6 @@ Firehose Mode allows you to maximize your training data uploads to improve openp Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. - - Record Audio Feedback with LKAS button - - - - Press the LKAS button to record and share driving feedback with the openpilot team. When this toggle is disabled, the button acts as a bookmark button. The event will be highlighted in comma connect and the segment will be preserved on your device's storage. - -Note that this feature is only compatible with select cars. - - WiFiPromptWidget diff --git a/selfdrive/ui/translations/main_de.ts b/selfdrive/ui/translations/main_de.ts index 52fe55720d..28b07029eb 100644 --- a/selfdrive/ui/translations/main_de.ts +++ b/selfdrive/ui/translations/main_de.ts @@ -470,10 +470,6 @@ Der Firehose-Modus ermöglicht es dir, deine Trainingsdaten-Uploads zu maximiere An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. Ein Update für das Betriebssystem deines Geräts wird im Hintergrund heruntergeladen. Du wirst aufgefordert, das Update zu installieren, sobald es bereit ist. - - NVMe drive not mounted. - NVMe-Laufwerk nicht gemounted. - openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. openpilot konnte dein Auto nicht identifizieren. Dein Auto wird entweder nicht unterstützt oder die Steuergeräte (ECUs) werden nicht erkannt. Bitte reiche einen Pull Request ein, um die Firmware-Versionen für das richtige Fahrzeug hinzuzufügen. Hilfe findest du auf discord.comma.ai. @@ -1034,16 +1030,6 @@ Der Firehose-Modus ermöglicht es dir, deine Trainingsdaten-Uploads zu maximiere Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. - - Record Audio Feedback with LKAS button - - - - Press the LKAS button to record and share driving feedback with the openpilot team. When this toggle is disabled, the button acts as a bookmark button. The event will be highlighted in comma connect and the segment will be preserved on your device's storage. - -Note that this feature is only compatible with select cars. - - WiFiPromptWidget diff --git a/selfdrive/ui/translations/main_es.ts b/selfdrive/ui/translations/main_es.ts index 145eb7ae67..e8d57dddbe 100644 --- a/selfdrive/ui/translations/main_es.ts +++ b/selfdrive/ui/translations/main_es.ts @@ -478,10 +478,6 @@ El Modo Firehose te permite maximizar las subidas de datos de entrenamiento para An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. Se está descargando una actualización del sistema operativo de su dispositivo en segundo plano. Se le pedirá que actualice cuando esté listo para instalarse. - - NVMe drive not mounted. - Unidad NVMe no montada. - openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. openpilot no pudo identificar su automóvil. Su automóvil no es compatible o no se reconocen sus ECU. Por favor haga un pull request para agregar las versiones de firmware del vehículo adecuado. ¿Necesita ayuda? Únase a discord.comma.ai. @@ -1036,16 +1032,6 @@ El Modo Firehose te permite maximizar las subidas de datos de entrenamiento para Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. Graba y almacena el audio del micrófono mientras conduces. El audio se incluirá en el video de la cámara del tablero en comma connect. - - Record Audio Feedback with LKAS button - - - - Press the LKAS button to record and share driving feedback with the openpilot team. When this toggle is disabled, the button acts as a bookmark button. The event will be highlighted in comma connect and the segment will be preserved on your device's storage. - -Note that this feature is only compatible with select cars. - - WiFiPromptWidget diff --git a/selfdrive/ui/translations/main_fr.ts b/selfdrive/ui/translations/main_fr.ts index 297d936139..4efb92d0c8 100644 --- a/selfdrive/ui/translations/main_fr.ts +++ b/selfdrive/ui/translations/main_fr.ts @@ -472,10 +472,6 @@ Firehose Mode allows you to maximize your training data uploads to improve openp An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. Une mise à jour du système d'exploitation de votre appareil est en cours de téléchargement en arrière-plan. Vous serez invité à effectuer la mise à jour lorsqu'elle sera prête à être installée. - - NVMe drive not mounted. - Le disque NVMe n'est pas monté. - openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. openpilot n'a pas pu identifier votre voiture. Votre voiture n'est pas supportée ou ses ECUs ne sont pas reconnues. Veuillez soumettre un pull request pour ajouter les versions de firmware au véhicule approprié. Besoin d'aide ? Rejoignez discord.comma.ai. @@ -1030,16 +1026,6 @@ Firehose Mode allows you to maximize your training data uploads to improve openp Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. - - Record Audio Feedback with LKAS button - - - - Press the LKAS button to record and share driving feedback with the openpilot team. When this toggle is disabled, the button acts as a bookmark button. The event will be highlighted in comma connect and the segment will be preserved on your device's storage. - -Note that this feature is only compatible with select cars. - - WiFiPromptWidget diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts index 7bb5c5364f..4307cee91f 100644 --- a/selfdrive/ui/translations/main_ja.ts +++ b/selfdrive/ui/translations/main_ja.ts @@ -472,10 +472,6 @@ Firehoseモードを有効にすると学習データを最大限アップロー An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. オペレーティングシステムがバックグラウンドでダウンロードされています。インストールの準備が整うと更新を促されます。 - - NVMe drive not mounted. - SSDドライブ(NVMe)がマウントされていません。 - openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. openpilotが車両を識別できませんでした。車が未対応またはECUが認識されていない可能性があります。該当車両のファームウェアバージョンを追加するためにプルリクエストしてください。サポートが必要な場合は discord.comma.ai に参加することができます。 @@ -1031,16 +1027,6 @@ Firehoseモードを有効にすると学習データを最大限アップロー Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. 運転中にマイク音声を録音・保存します。音声は comma connect のドライブレコーダー映像に含まれます。 - - Record Audio Feedback with LKAS button - - - - Press the LKAS button to record and share driving feedback with the openpilot team. When this toggle is disabled, the button acts as a bookmark button. The event will be highlighted in comma connect and the segment will be preserved on your device's storage. - -Note that this feature is only compatible with select cars. - - WiFiPromptWidget diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index 807996f182..9ab43dd9b8 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -472,10 +472,6 @@ Firehose Mode allows you to maximize your training data uploads to improve openp An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. 백그라운드에서 운영 체제에 대한 업데이트가 다운로드되고 있습니다. 설치가 준비되면 업데이트 메시지가 표시됩니다. - - NVMe drive not mounted. - NVMe 드라이브가 마운트되지 않았습니다. - openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. 오픈파일럿이 차량을 식별할 수 없습니다. 지원되지 않는 차량이거나 ECU가 인식되지 않습니다. 해당 차량에 맞는 펌웨어 버전을 추가하려면 PR을 제출하세요. 도움이 필요하시면 discord.comma.ai에 참여하세요. @@ -1031,16 +1027,6 @@ Firehose Mode allows you to maximize your training data uploads to improve openp Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. 운전 중에 마이크 오디오를 녹음하고 저장하십시오. 오디오는 comma connect의 대시캠 비디오에 포함됩니다. - - Record Audio Feedback with LKAS button - - - - Press the LKAS button to record and share driving feedback with the openpilot team. When this toggle is disabled, the button acts as a bookmark button. The event will be highlighted in comma connect and the segment will be preserved on your device's storage. - -Note that this feature is only compatible with select cars. - - WiFiPromptWidget diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index 7f41588e8f..77aa5e07c1 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -474,10 +474,6 @@ O Modo Firehose permite maximizar o envio de dados de treinamento para melhorar An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. Uma atualização para o sistema operacional do seu dispositivo está sendo baixada em segundo plano. Você será solicitado a atualizar quando estiver pronto para instalar. - - NVMe drive not mounted. - Unidade NVMe não montada. - openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. O openpilot não conseguiu identificar o seu carro. Seu carro não é suportado ou seus ECUs não são reconhecidos. Envie um pull request para adicionar as versões de firmware ao veículo adequado. Precisa de ajuda? Junte-se discord.comma.ai. @@ -1036,18 +1032,6 @@ O Modo Firehose permite maximizar o envio de dados de treinamento para melhorar Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. Grave e armazene o áudio do microfone enquanto estiver dirigindo. O áudio será incluído ao vídeo dashcam no comma connect. - - Record Audio Feedback with LKAS button - Gravar feedback de áudio com o botão LKAS - - - Press the LKAS button to record and share driving feedback with the openpilot team. When this toggle is disabled, the button acts as a bookmark button. The event will be highlighted in comma connect and the segment will be preserved on your device's storage. - -Note that this feature is only compatible with select cars. - Pressione o botão LKAS para gravar e compartilhar feedback de direção com a equipe do openpilot. Quando esta opção estiver desativada, o botão funcionará como um botão de marcador. O evento será destacado no comma connect e o segmento será preservado no armazenamento do seu dispositivo. - -Observe que este recurso é compatível apenas com alguns modelos de carros. - WiFiPromptWidget diff --git a/selfdrive/ui/translations/main_th.ts b/selfdrive/ui/translations/main_th.ts index 34824c2680..9bd6822086 100644 --- a/selfdrive/ui/translations/main_th.ts +++ b/selfdrive/ui/translations/main_th.ts @@ -472,10 +472,6 @@ Firehose Mode allows you to maximize your training data uploads to improve openp An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. กำลังดาวน์โหลดอัปเดทสำหรับระบบปฏิบัติการอยู่เบื้องหลัง คุณจะได้รับการแจ้งเตือนเมื่อระบบพร้อมสำหรับการติดตั้ง - - NVMe drive not mounted. - ไม่ได้ติดตั้งไดร์ฟ NVMe - openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. openpilot ไม่สามารถระบุรถยนต์ของคุณได้ ระบบอาจไม่รองรับรถยนต์ของคุณหรือไม่รู้จัก ECU กรุณาส่ง pull request เพื่อเพิ่มรุ่นของเฟิร์มแวร์ให้กับรถยนต์ที่เหมาะสม หากต้องการความช่วยเหลือให้เข้าร่วม discord.comma.ai @@ -1027,16 +1023,6 @@ Firehose Mode allows you to maximize your training data uploads to improve openp Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. - - Record Audio Feedback with LKAS button - - - - Press the LKAS button to record and share driving feedback with the openpilot team. When this toggle is disabled, the button acts as a bookmark button. The event will be highlighted in comma connect and the segment will be preserved on your device's storage. - -Note that this feature is only compatible with select cars. - - WiFiPromptWidget diff --git a/selfdrive/ui/translations/main_tr.ts b/selfdrive/ui/translations/main_tr.ts index db6c4283a8..7c6c692d54 100644 --- a/selfdrive/ui/translations/main_tr.ts +++ b/selfdrive/ui/translations/main_tr.ts @@ -469,10 +469,6 @@ Firehose Mode allows you to maximize your training data uploads to improve openp An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. - - NVMe drive not mounted. - - openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. @@ -1024,16 +1020,6 @@ Firehose Mode allows you to maximize your training data uploads to improve openp Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. - - Record Audio Feedback with LKAS button - - - - Press the LKAS button to record and share driving feedback with the openpilot team. When this toggle is disabled, the button acts as a bookmark button. The event will be highlighted in comma connect and the segment will be preserved on your device's storage. - -Note that this feature is only compatible with select cars. - - WiFiPromptWidget diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts index 667d81ddd4..9481e62f10 100644 --- a/selfdrive/ui/translations/main_zh-CHS.ts +++ b/selfdrive/ui/translations/main_zh-CHS.ts @@ -472,10 +472,6 @@ Firehose Mode allows you to maximize your training data uploads to improve openp An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. 一个针对您设备的操作系统更新正在后台下载中。当更新准备好安装时,您将收到提示进行更新。 - - NVMe drive not mounted. - NVMe固态硬盘未被挂载。 - openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. openpilot 无法识别您的车辆。您的车辆可能未被支持,或是其电控单元 (ECU) 未被识别。请提交一个 Pull Request 为您的车辆添加正确的固件版本。需要帮助吗?请加入 discord.comma.ai。 @@ -1031,18 +1027,6 @@ Firehose Mode allows you to maximize your training data uploads to improve openp Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. 在驾驶时录制并存储麦克风音频。该音频将会包含在 comma connect 的行车记录仪视频中。 - - Record Audio Feedback with LKAS button - 使用“车道保持”按钮录制音频反馈 - - - Press the LKAS button to record and share driving feedback with the openpilot team. When this toggle is disabled, the button acts as a bookmark button. The event will be highlighted in comma connect and the segment will be preserved on your device's storage. - -Note that this feature is only compatible with select cars. - 按下“车道保持”按钮,即可录制并分享驾驶反馈给 openpilot 团队。当此开关禁用时,该按钮将用作书签按钮。该事件将在 comma connect 中高亮显示,且对应的视频片段将被保留在您的设备存储空间中。 - -请注意,此功能仅兼容部分车型。 - WiFiPromptWidget diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts index a0f1997a00..c3ef55d3d9 100644 --- a/selfdrive/ui/translations/main_zh-CHT.ts +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -472,10 +472,6 @@ Firehose Mode allows you to maximize your training data uploads to improve openp An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. 一個有關操作系統的更新正在後台下載中。當更新準備好安裝時,您將收到提示進行更新。 - - NVMe drive not mounted. - NVMe 固態硬碟未被掛載。 - openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. openpilot 無法識別您的車輛。您的車輛可能未被支援,或是其電控單元 (ECU) 未被識別。請提交一個 Pull Request 為您的車輛添加正確的韌體版本。需要幫助嗎?請加入 discord.comma.ai 。 @@ -1031,18 +1027,6 @@ Firehose Mode allows you to maximize your training data uploads to improve openp Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. 在駕駛時錄製並儲存麥克風音訊。此音訊將會收錄在 comma connect 的行車記錄器影片中。 - - Record Audio Feedback with LKAS button - 使用「車道維持」按鈕錄製音訊回饋 - - - Press the LKAS button to record and share driving feedback with the openpilot team. When this toggle is disabled, the button acts as a bookmark button. The event will be highlighted in comma connect and the segment will be preserved on your device's storage. - -Note that this feature is only compatible with select cars. - 按下「車道維持」按鈕,即可錄製並分享駕駛回饋給 openpilot 團隊。當此開關停用時,該按鈕的功能將轉為書籤按鈕。該事件將會在 comma connect 中被標註,且對應的路段影像將保留在您的裝置儲存空間中。 - -請注意,此功能僅與特定車款相容。 - WiFiPromptWidget From ea53111afc011530cbda17574e0e6726a11b3bc2 Mon Sep 17 00:00:00 2001 From: Jimmy <9859727+Quantizr@users.noreply.github.com> Date: Tue, 9 Sep 2025 07:56:07 -1000 Subject: [PATCH 058/159] basic jotpluggler (#36045) * jotpluggler! * demo, executable, fontfile * calc max and min, numpy, cloudlog * mypy things * simplified data.py * multiprocessed data ingest * allow verrryyy long search results * stream in multiprocessed segments * bug fixes * simplify and speed up timeseries * small fixes * rewrite layout * resizable layouts * cleanup * downsampling * deque for consistency * use item_visible_handler * only build visible UI * don't delete item handlers, add locks, don't expand large lists * delete item handlers after a frame * small data tree improvements * seperate datatree into its own file * reset when loading new segments * fix plot window resizing and recursive split resizing logic --- pyproject.toml | 1 + tools/jotpluggler/data.py | 311 ++++++++++++++++++++++++++++++++++ tools/jotpluggler/datatree.py | 266 +++++++++++++++++++++++++++++ tools/jotpluggler/layout.py | 262 ++++++++++++++++++++++++++++ tools/jotpluggler/pluggle.py | 247 +++++++++++++++++++++++++++ tools/jotpluggler/views.py | 195 +++++++++++++++++++++ uv.lock | 17 ++ 7 files changed, 1299 insertions(+) create mode 100644 tools/jotpluggler/data.py create mode 100644 tools/jotpluggler/datatree.py create mode 100644 tools/jotpluggler/layout.py create mode 100755 tools/jotpluggler/pluggle.py create mode 100644 tools/jotpluggler/views.py diff --git a/pyproject.toml b/pyproject.toml index 9ed1d8a4cb..88c4d06739 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -124,6 +124,7 @@ dev = [ tools = [ "metadrive-simulator @ https://github.com/commaai/metadrive/releases/download/MetaDrive-minimal-0.4.2.4/metadrive_simulator-0.4.2.4-py3-none-any.whl ; (platform_machine != 'aarch64')", + "dearpygui>=2.1.0", ] [project.urls] diff --git a/tools/jotpluggler/data.py b/tools/jotpluggler/data.py new file mode 100644 index 0000000000..41c305718e --- /dev/null +++ b/tools/jotpluggler/data.py @@ -0,0 +1,311 @@ +import numpy as np +import threading +import multiprocessing +import bisect +from collections import defaultdict +import tqdm +from openpilot.common.swaglog import cloudlog +from openpilot.tools.lib.logreader import _LogFileReader, LogReader + + +def flatten_dict(d: dict, sep: str = "/", prefix: str = None) -> dict: + result = {} + stack: list[tuple] = [(d, prefix)] + + while stack: + obj, current_prefix = stack.pop() + + if isinstance(obj, dict): + for key, val in obj.items(): + new_prefix = key if current_prefix is None else f"{current_prefix}{sep}{key}" + if isinstance(val, (dict, list)): + stack.append((val, new_prefix)) + else: + result[new_prefix] = val + elif isinstance(obj, list): + for i, item in enumerate(obj): + new_prefix = f"{current_prefix}{sep}{i}" + if isinstance(item, (dict, list)): + stack.append((item, new_prefix)) + else: + result[new_prefix] = item + else: + if current_prefix is not None: + result[current_prefix] = obj + return result + + +def extract_field_types(schema, prefix, field_types_dict): + stack = [(schema, prefix)] + + while stack: + current_schema, current_prefix = stack.pop() + + for field in current_schema.fields_list: + field_name = field.proto.name + field_path = f"{current_prefix}/{field_name}" + field_proto = field.proto + field_which = field_proto.which() + + field_type = field_proto.slot.type.which() if field_which == 'slot' else field_which + field_types_dict[field_path] = field_type + + if field_which == 'slot': + slot_type = field_proto.slot.type + type_which = slot_type.which() + + if type_which == 'list': + element_type = slot_type.list.elementType.which() + list_path = f"{field_path}/*" + field_types_dict[list_path] = element_type + + if element_type == 'struct': + stack.append((field.schema.elementType, list_path)) + + elif type_which == 'struct': + stack.append((field.schema, field_path)) + + elif field_which == 'group': + stack.append((field.schema, field_path)) + + +def _convert_to_optimal_dtype(values_list, capnp_type): + if not values_list: + return np.array([]) + + dtype_mapping = { + 'bool': np.bool_, 'int8': np.int8, 'int16': np.int16, 'int32': np.int32, 'int64': np.int64, + 'uint8': np.uint8, 'uint16': np.uint16, 'uint32': np.uint32, 'uint64': np.uint64, + 'float32': np.float32, 'float64': np.float64, 'text': object, 'data': object, + 'enum': object, 'anyPointer': object, + } + + target_dtype = dtype_mapping.get(capnp_type) + return np.array(values_list, dtype=target_dtype) if target_dtype else np.array(values_list) + + +def _match_field_type(field_path, field_types): + if field_path in field_types: + return field_types[field_path] + + path_parts = field_path.split('/') + template_parts = [p if not p.isdigit() else '*' for p in path_parts] + template_path = '/'.join(template_parts) + return field_types.get(template_path) + + +def msgs_to_time_series(msgs): + """Extract scalar fields and return (time_series_data, start_time, end_time).""" + collected_data = defaultdict(lambda: {'timestamps': [], 'columns': defaultdict(list), 'sparse_fields': set()}) + field_types = {} + extracted_schemas = set() + min_time = max_time = None + + for msg in msgs: + typ = msg.which() + timestamp = msg.logMonoTime * 1e-9 + if typ != 'initData': + if min_time is None: + min_time = timestamp + max_time = timestamp + + sub_msg = getattr(msg, typ) + if not hasattr(sub_msg, 'to_dict') or typ in ('qcomGnss', 'ubloxGnss'): + continue + + if hasattr(sub_msg, 'schema') and typ not in extracted_schemas: + extract_field_types(sub_msg.schema, typ, field_types) + extracted_schemas.add(typ) + + msg_dict = sub_msg.to_dict(verbose=True) + flat_dict = flatten_dict(msg_dict) + flat_dict['_valid'] = msg.valid + + type_data = collected_data[typ] + columns, sparse_fields = type_data['columns'], type_data['sparse_fields'] + known_fields = set(columns.keys()) + missing_fields = known_fields - flat_dict.keys() + + for field, value in flat_dict.items(): + if field not in known_fields and type_data['timestamps']: + sparse_fields.add(field) + columns[field].append(value) + if value is None: + sparse_fields.add(field) + + for field in missing_fields: + columns[field].append(None) + sparse_fields.add(field) + + type_data['timestamps'].append(timestamp) + + final_result = {} + for typ, data in collected_data.items(): + if not data['timestamps']: + continue + + typ_result = {'t': np.array(data['timestamps'], dtype=np.float64)} + sparse_fields = data['sparse_fields'] + + for field_name, values in data['columns'].items(): + if len(values) < len(data['timestamps']): + values = [None] * (len(data['timestamps']) - len(values)) + values + sparse_fields.add(field_name) + + if field_name in sparse_fields: + typ_result[field_name] = np.array(values, dtype=object) + else: + capnp_type = _match_field_type(f"{typ}/{field_name}", field_types) + typ_result[field_name] = _convert_to_optimal_dtype(values, capnp_type) + + final_result[typ] = typ_result + + return final_result, min_time or 0.0, max_time or 0.0 + + +def _process_segment(segment_identifier: str): + try: + lr = _LogFileReader(segment_identifier, sort_by_time=True) + return msgs_to_time_series(lr) + except Exception as e: + cloudlog.warning(f"Warning: Failed to process segment {segment_identifier}: {e}") + return {}, 0.0, 0.0 + + +class DataManager: + def __init__(self): + self._segments = [] + self._segment_starts = [] + self._start_time = 0.0 + self._duration = 0.0 + self._paths = set() + self._observers = [] + self._loading = False + self._lock = threading.RLock() + + def load_route(self, route: str) -> None: + if self._loading: + return + self._reset() + threading.Thread(target=self._load_async, args=(route,), daemon=True).start() + + def get_timeseries(self, path: str): + with self._lock: + msg_type, field = path.split('/', 1) + times, values = [], [] + + for segment in self._segments: + if msg_type in segment and field in segment[msg_type]: + times.append(segment[msg_type]['t']) + values.append(segment[msg_type][field]) + + if not times: + return [], [] + + combined_times = np.concatenate(times) - self._start_time + if len(values) > 1 and any(arr.dtype != values[0].dtype for arr in values): + values = [arr.astype(object) for arr in values] + + return combined_times, np.concatenate(values) + + def get_value_at(self, path: str, time: float): + with self._lock: + MAX_LOOKBACK = 5.0 # seconds + absolute_time = self._start_time + time + message_type, field = path.split('/', 1) + current_index = bisect.bisect_right(self._segment_starts, absolute_time) - 1 + for index in (current_index, current_index - 1): + if not 0 <= index < len(self._segments): + continue + segment = self._segments[index].get(message_type) + if not segment or field not in segment: + continue + times = segment['t'] + if len(times) == 0 or (index != current_index and absolute_time - times[-1] > MAX_LOOKBACK): + continue + position = np.searchsorted(times, absolute_time, 'right') - 1 + if position >= 0 and absolute_time - times[position] <= MAX_LOOKBACK: + return segment[field][position] + return None + + def get_all_paths(self): + with self._lock: + return sorted(self._paths) + + def get_duration(self): + with self._lock: + return self._duration + + def is_plottable(self, path: str): + data = self.get_timeseries(path) + if data is None: + return False + _, values = data + return np.issubdtype(values.dtype, np.number) or np.issubdtype(values.dtype, np.bool_) + + def add_observer(self, callback): + with self._lock: + self._observers.append(callback) + + def remove_observer(self, callback): + with self._lock: + if callback in self._observers: + self._observers.remove(callback) + + def _reset(self): + with self._lock: + self._loading = True + self._segments.clear() + self._segment_starts.clear() + self._paths.clear() + self._start_time = self._duration = 0.0 + observers = self._observers.copy() + + for callback in observers: + callback({'reset': True}) + + def _load_async(self, route: str): + try: + lr = LogReader(route, sort_by_time=True) + if not lr.logreader_identifiers: + cloudlog.warning(f"Warning: No log segments found for route: {route}") + return + + num_processes = max(1, multiprocessing.cpu_count() // 2) + with multiprocessing.Pool(processes=num_processes) as pool, tqdm.tqdm(total=len(lr.logreader_identifiers), desc="Processing Segments") as pbar: + for segment_result, start_time, end_time in pool.imap(_process_segment, lr.logreader_identifiers): + pbar.update(1) + if segment_result: + self._add_segment(segment_result, start_time, end_time) + except Exception: + cloudlog.exception(f"Error loading route {route}:") + finally: + self._finalize_loading() + + def _add_segment(self, segment_data: dict, start_time: float, end_time: float): + with self._lock: + self._segments.append(segment_data) + self._segment_starts.append(start_time) + + if len(self._segments) == 1: + self._start_time = start_time + self._duration = end_time - self._start_time + + for msg_type, data in segment_data.items(): + for field in data.keys(): + if field != 't': + self._paths.add(f"{msg_type}/{field}") + + observers = self._observers.copy() + + for callback in observers: + callback({'segment_added': True, 'duration': self._duration, 'segment_count': len(self._segments)}) + + def _finalize_loading(self): + with self._lock: + self._loading = False + observers = self._observers.copy() + duration = self._duration + + for callback in observers: + callback({'loading_complete': True, 'duration': duration}) diff --git a/tools/jotpluggler/datatree.py b/tools/jotpluggler/datatree.py new file mode 100644 index 0000000000..7bd026cf98 --- /dev/null +++ b/tools/jotpluggler/datatree.py @@ -0,0 +1,266 @@ +import os +import re +import threading +import numpy as np +from collections import deque +import dearpygui.dearpygui as dpg + + +class DataTreeNode: + def __init__(self, name: str, full_path: str = "", parent=None): + self.name = name + self.full_path = full_path + self.parent = parent + self.children: dict[str, DataTreeNode] = {} + self.is_leaf = False + self.child_count = 0 + self.is_plottable: bool | None = None + self.ui_created = False + self.children_ui_created = False + self.ui_tag: str | None = None + + +class DataTree: + MAX_NODES_PER_FRAME = 50 + + def __init__(self, data_manager, playback_manager): + self.data_manager = data_manager + self.playback_manager = playback_manager + self.current_search = "" + self.data_tree = DataTreeNode(name="root") + self._build_queue: deque[tuple[DataTreeNode, str | None, str | int]] = deque() + self._all_paths_cache: set[str] = set() + self._item_handlers: set[str] = set() + self._avg_char_width = None + self._queued_search = None + self._new_data = False + self._ui_lock = threading.RLock() + self.data_manager.add_observer(self._on_data_loaded) + + def create_ui(self, parent_tag: str): + with dpg.child_window(parent=parent_tag, border=False, width=-1, height=-1): + dpg.add_text("Available Data") + dpg.add_separator() + dpg.add_input_text(tag="search_input", width=-1, hint="Search fields...", callback=self.search_data) + dpg.add_separator() + with dpg.group(tag="data_tree_container"): + pass + + def _on_data_loaded(self, data: dict): + with self._ui_lock: + if data.get('segment_added'): + self._new_data = True + elif data.get('reset'): + self._all_paths_cache = set() + self._new_data = True + + + def _populate_tree(self): + self._clear_ui() + self.data_tree = self._add_paths_to_tree(self._all_paths_cache, incremental=False) + if self.data_tree: + self._request_children_build(self.data_tree) + + def _add_paths_to_tree(self, paths, incremental=False): + search_term = self.current_search.strip().lower() + filtered_paths = [path for path in paths if self._should_show_path(path, search_term)] + target_tree = self.data_tree if incremental else DataTreeNode(name="root") + + if not filtered_paths: + return target_tree + + parent_nodes_to_recheck = set() + for path in sorted(filtered_paths): + parts = path.split('/') + current_node = target_tree + current_path_prefix = "" + + for i, part in enumerate(parts): + current_path_prefix = f"{current_path_prefix}/{part}" if current_path_prefix else part + if i < len(parts) - 1: + parent_nodes_to_recheck.add(current_node) # for incremental changes from new data + if part not in current_node.children: + current_node.children[part] = DataTreeNode(name=part, full_path=current_path_prefix, parent=current_node) + current_node = current_node.children[part] + + if not current_node.is_leaf: + current_node.is_leaf = True + + self._calculate_child_counts(target_tree) + if incremental: + for p_node in parent_nodes_to_recheck: + p_node.children_ui_created = False + self._request_children_build(p_node) + return target_tree + + def update_frame(self, font): + with self._ui_lock: + if self._avg_char_width is None and dpg.is_dearpygui_running(): + self._avg_char_width = self.calculate_avg_char_width(font) + + if self._new_data: + current_paths = set(self.data_manager.get_all_paths()) + new_paths = current_paths - self._all_paths_cache + all_paths_empty = not self._all_paths_cache + self._all_paths_cache = current_paths + if all_paths_empty: + self._populate_tree() + elif new_paths: + self._add_paths_to_tree(new_paths, incremental=True) + self._new_data = False + return + + if self._queued_search is not None: + self.current_search = self._queued_search + self._all_paths_cache = set(self.data_manager.get_all_paths()) + self._populate_tree() + self._queued_search = None + return + + nodes_processed = 0 + while self._build_queue and nodes_processed < self.MAX_NODES_PER_FRAME: + child_node, parent_tag, before_tag = self._build_queue.popleft() + if not child_node.ui_created: + if child_node.is_leaf: + self._create_leaf_ui(child_node, parent_tag, before_tag) + else: + self._create_tree_node_ui(child_node, parent_tag, before_tag) + nodes_processed += 1 + + def search_data(self): + self._queued_search = dpg.get_value("search_input") + + def _clear_ui(self): + for handler_tag in self._item_handlers: + dpg.configure_item(handler_tag, show=False) + dpg.set_frame_callback(dpg.get_frame_count() + 1, callback=self._delete_handlers, user_data=list(self._item_handlers)) + self._item_handlers.clear() + + if dpg.does_item_exist("data_tree_container"): + dpg.delete_item("data_tree_container", children_only=True) + + self._build_queue.clear() + + def _delete_handlers(self, sender, app_data, user_data): + for handler in user_data: + dpg.delete_item(handler) + + def _calculate_child_counts(self, node: DataTreeNode): + if node.is_leaf: + node.child_count = 0 + else: + node.child_count = len(node.children) + for child in node.children.values(): + self._calculate_child_counts(child) + + def _create_tree_node_ui(self, node: DataTreeNode, parent_tag: str, before: str | int): + tag = f"tree_{node.full_path}" + node.ui_tag = tag + label = f"{node.name} ({node.child_count} fields)" + search_term = self.current_search.strip().lower() + expand = bool(search_term) and len(search_term) > 1 and any(search_term in path for path in self._get_descendant_paths(node)) + if expand and node.parent and node.parent.child_count > 100 and node.child_count > 2: # don't fully autoexpand large lists (only affects procLog rn) + label += " (+)" + expand = False + + with dpg.tree_node( + label=label, parent=parent_tag, tag=tag, default_open=expand, open_on_arrow=True, open_on_double_click=True, before=before, delay_search=True + ): + with dpg.item_handler_registry() as handler_tag: + dpg.add_item_toggled_open_handler(callback=lambda s, a, u: self._request_children_build(node)) + dpg.add_item_visible_handler(callback=lambda s, a, u: self._request_children_build(node)) + dpg.bind_item_handler_registry(tag, handler_tag) + self._item_handlers.add(handler_tag) + + node.ui_created = True + + def _create_leaf_ui(self, node: DataTreeNode, parent_tag: str, before: str | int): + with dpg.group(parent=parent_tag, tag=f"leaf_{node.full_path}", before=before, delay_search=True) as draggable_group: + with dpg.table(header_row=False, policy=dpg.mvTable_SizingStretchProp, delay_search=True): + dpg.add_table_column(init_width_or_weight=0.5) + dpg.add_table_column(init_width_or_weight=0.5) + with dpg.table_row(): + dpg.add_text(node.name) + dpg.add_text("N/A", tag=f"value_{node.full_path}") + + if node.is_plottable is None: + node.is_plottable = self.data_manager.is_plottable(node.full_path) + if node.is_plottable: + with dpg.drag_payload(parent=draggable_group, drag_data=node.full_path, payload_type="TIMESERIES_PAYLOAD"): + dpg.add_text(f"Plot: {node.full_path}") + + with dpg.item_handler_registry() as handler_tag: + dpg.add_item_visible_handler(callback=self._on_item_visible, user_data=node.full_path) + dpg.bind_item_handler_registry(draggable_group, handler_tag) + self._item_handlers.add(handler_tag) + + node.ui_created = True + node.ui_tag = f"value_{node.full_path}" + + def _on_item_visible(self, sender, app_data, user_data): + with self._ui_lock: + path = user_data + value_tag = f"value_{path}" + value_column_width = dpg.get_item_rect_size("sidebar_window")[0] // 2 + value = self.data_manager.get_value_at(path, self.playback_manager.current_time_s) + if value is not None: + formatted_value = self.format_and_truncate(value, value_column_width, self._avg_char_width) + dpg.set_value(value_tag, formatted_value) + else: + dpg.set_value(value_tag, "N/A") + + def _request_children_build(self, node: DataTreeNode): + with self._ui_lock: + if not node.children_ui_created and (node.name == "root" or (node.ui_tag is not None and dpg.get_value(node.ui_tag))): # check root or node expanded + parent_tag = "data_tree_container" if node.name == "root" else node.ui_tag + sorted_children = sorted(node.children.values(), key=self._natural_sort_key) + next_existing: list[int | str] = [0] * len(sorted_children) + current_before_tag: int | str = 0 + + for i in range(len(sorted_children) - 1, -1, -1): # calculate "before_tag" for correct ordering when incrementally building tree + child = sorted_children[i] + next_existing[i] = current_before_tag + if child.ui_created: + candidate_tag = f"leaf_{child.full_path}" if child.is_leaf else f"tree_{child.full_path}" + if dpg.does_item_exist(candidate_tag): + current_before_tag = candidate_tag + + for i, child_node in enumerate(sorted_children): + if not child_node.ui_created: + before_tag = next_existing[i] + self._build_queue.append((child_node, parent_tag, before_tag)) + node.children_ui_created = True + + def _should_show_path(self, path: str, search_term: str) -> bool: + if 'DEPRECATED' in path and not os.environ.get('SHOW_DEPRECATED'): + return False + return not search_term or search_term in path.lower() + + def _natural_sort_key(self, node: DataTreeNode): + node_type_key = node.is_leaf + parts = [int(p) if p.isdigit() else p.lower() for p in re.split(r'(\d+)', node.name) if p] + return (node_type_key, parts) + + def _get_descendant_paths(self, node: DataTreeNode): + for child_name, child_node in node.children.items(): + child_name_lower = child_name.lower() + if child_node.is_leaf: + yield child_name_lower + else: + for path in self._get_descendant_paths(child_node): + yield f"{child_name_lower}/{path}" + + @staticmethod + def calculate_avg_char_width(font): + sample_text = "abcdefghijklmnopqrstuvwxyz0123456789" + if size := dpg.get_text_size(sample_text, font=font): + return size[0] / len(sample_text) + return None + + @staticmethod + def format_and_truncate(value, available_width: float, avg_char_width: float) -> str: + s = f"{value:.5f}" if np.issubdtype(type(value), np.floating) else str(value) + max_chars = int(available_width / avg_char_width) - 3 + if len(s) > max_chars: + return s[: max(0, max_chars)] + "..." + return s diff --git a/tools/jotpluggler/layout.py b/tools/jotpluggler/layout.py new file mode 100644 index 0000000000..0c40116e66 --- /dev/null +++ b/tools/jotpluggler/layout.py @@ -0,0 +1,262 @@ +import dearpygui.dearpygui as dpg +from openpilot.tools.jotpluggler.data import DataManager +from openpilot.tools.jotpluggler.views import TimeSeriesPanel + +GRIP_SIZE = 4 +MIN_PANE_SIZE = 60 + + +class PlotLayoutManager: + def __init__(self, data_manager: DataManager, playback_manager, worker_manager, scale: float = 1.0): + self.data_manager = data_manager + self.playback_manager = playback_manager + self.worker_manager = worker_manager + self.scale = scale + self.container_tag = "plot_layout_container" + self.active_panels: list = [] + + self.grip_size = int(GRIP_SIZE * self.scale) + self.min_pane_size = int(MIN_PANE_SIZE * self.scale) + + initial_panel = TimeSeriesPanel(data_manager, playback_manager, worker_manager) + self.layout: dict = {"type": "panel", "panel": initial_panel} + + def create_ui(self, parent_tag: str): + if dpg.does_item_exist(self.container_tag): + dpg.delete_item(self.container_tag) + + with dpg.child_window(tag=self.container_tag, parent=parent_tag, border=False, width=-1, height=-1, no_scrollbar=True): + container_width, container_height = dpg.get_item_rect_size(self.container_tag) + self._create_ui_recursive(self.layout, self.container_tag, [], container_width, container_height) + + def _create_ui_recursive(self, layout: dict, parent_tag: str, path: list[int], width: int, height: int): + if layout["type"] == "panel": + self._create_panel_ui(layout, parent_tag, path) + else: + self._create_split_ui(layout, parent_tag, path, width, height) + + def _create_panel_ui(self, layout: dict, parent_tag: str, path: list[int]): + panel_tag = self._path_to_tag(path, "panel") + panel = layout["panel"] + self.active_panels.append(panel) + + with dpg.child_window(tag=panel_tag, parent=parent_tag, border=True, width=-1, height=-1, no_scrollbar=True): + with dpg.group(horizontal=True): + dpg.add_input_text(default_value=panel.title, width=int(100 * self.scale), callback=lambda s, v: setattr(panel, "title", v)) + dpg.add_combo(items=["Time Series"], default_value="Time Series", width=int(100 * self.scale)) + dpg.add_button(label="Clear", callback=lambda: self.clear_panel(panel), width=int(40 * self.scale)) + dpg.add_button(label="Delete", callback=lambda: self.delete_panel(path), width=int(40 * self.scale)) + dpg.add_button(label="Split H", callback=lambda: self.split_panel(path, 0), width=int(40 * self.scale)) + dpg.add_button(label="Split V", callback=lambda: self.split_panel(path, 1), width=int(40 * self.scale)) + + dpg.add_separator() + + content_tag = self._path_to_tag(path, "content") + with dpg.child_window(tag=content_tag, border=False, height=-1, width=-1, no_scrollbar=True): + panel.create_ui(content_tag) + + def _create_split_ui(self, layout: dict, parent_tag: str, path: list[int], width: int, height: int): + split_tag = self._path_to_tag(path, "split") + orientation, _, pane_sizes = self._get_split_geometry(layout, (width, height)) + + with dpg.group(tag=split_tag, parent=parent_tag, horizontal=orientation == 0): + for i, child_layout in enumerate(layout["children"]): + child_path = path + [i] + container_tag = self._path_to_tag(child_path, "container") + pane_width, pane_height = [(pane_sizes[i], -1), (-1, pane_sizes[i])][orientation] # fill 2nd dim up to the border + with dpg.child_window(tag=container_tag, width=pane_width, height=pane_height, border=False, no_scrollbar=True): + child_width, child_height = [(pane_sizes[i], height), (width, pane_sizes[i])][orientation] + self._create_ui_recursive(child_layout, container_tag, child_path, child_width, child_height) + if i < len(layout["children"]) - 1: + self._create_grip(split_tag, path, i, orientation) + + def clear_panel(self, panel): + panel.clear() + + def delete_panel(self, panel_path: list[int]): + if not panel_path: # Root deletion + old_panel = self.layout["panel"] + old_panel.destroy_ui() + self.active_panels.remove(old_panel) + new_panel = TimeSeriesPanel(self.data_manager, self.playback_manager, self.worker_manager) + self.layout = {"type": "panel", "panel": new_panel} + self._rebuild_ui_at_path([]) + return + + parent, child_index = self._get_parent_and_index(panel_path) + layout_to_delete = parent["children"][child_index] + self._cleanup_ui_recursive(layout_to_delete, panel_path) + + parent["children"].pop(child_index) + parent["proportions"].pop(child_index) + + if len(parent["children"]) == 1: # remove parent and collapse + remaining_child = parent["children"][0] + if len(panel_path) == 1: # parent is at root level - promote remaining child to root + self.layout = remaining_child + self._rebuild_ui_at_path([]) + else: # replace parent with remaining child in grandparent + grandparent_path = panel_path[:-2] + parent_index = panel_path[-2] + self._replace_layout_at_path(grandparent_path + [parent_index], remaining_child) + self._rebuild_ui_at_path(grandparent_path + [parent_index]) + else: # redistribute proportions + equal_prop = 1.0 / len(parent["children"]) + parent["proportions"] = [equal_prop] * len(parent["children"]) + self._rebuild_ui_at_path(panel_path[:-1]) + + def split_panel(self, panel_path: list[int], orientation: int): + current_layout = self._get_layout_at_path(panel_path) + existing_panel = current_layout["panel"] + new_panel = TimeSeriesPanel(self.data_manager, self.playback_manager, self.worker_manager) + parent, child_index = self._get_parent_and_index(panel_path) + + if parent is None: # Root split + self.layout = { + "type": "split", + "orientation": orientation, + "children": [{"type": "panel", "panel": existing_panel}, {"type": "panel", "panel": new_panel}], + "proportions": [0.5, 0.5], + } + self._rebuild_ui_at_path([]) + elif parent["type"] == "split" and parent["orientation"] == orientation: # Same orientation - insert into existing split + parent["children"].insert(child_index + 1, {"type": "panel", "panel": new_panel}) + parent["proportions"] = [1.0 / len(parent["children"])] * len(parent["children"]) + self._rebuild_ui_at_path(panel_path[:-1]) + else: # Different orientation - create new split level + new_split = {"type": "split", "orientation": orientation, "children": [current_layout, {"type": "panel", "panel": new_panel}], "proportions": [0.5, 0.5]} + self._replace_layout_at_path(panel_path, new_split) + self._rebuild_ui_at_path(panel_path) + + def _rebuild_ui_at_path(self, path: list[int]): + layout = self._get_layout_at_path(path) + if path: + container_tag = self._path_to_tag(path, "container") + else: # Root update + container_tag = self.container_tag + + self._cleanup_ui_recursive(layout, path) + dpg.delete_item(container_tag, children_only=True) + width, height = dpg.get_item_rect_size(container_tag) + self._create_ui_recursive(layout, container_tag, path, width, height) + + def _cleanup_ui_recursive(self, layout: dict, path: list[int]): + if layout["type"] == "panel": + panel = layout["panel"] + panel.destroy_ui() + if panel in self.active_panels: + self.active_panels.remove(panel) + else: + for i in range(len(layout["children"]) - 1): + handler_tag = f"{self._path_to_tag(path, f'grip_{i}')}_handler" + if dpg.does_item_exist(handler_tag): + dpg.delete_item(handler_tag) + + for i, child in enumerate(layout["children"]): + self._cleanup_ui_recursive(child, path + [i]) + + def update_all_panels(self): + for panel in self.active_panels: + panel.update() + + def on_viewport_resize(self): + self._resize_splits_recursive(self.layout, []) + + def _resize_splits_recursive(self, layout: dict, path: list[int], width: int | None = None, height: int | None = None): + if layout["type"] == "split": + split_tag = self._path_to_tag(path, "split") + if dpg.does_item_exist(split_tag): + available_sizes = (width, height) if width and height else dpg.get_item_rect_size(dpg.get_item_parent(split_tag)) + orientation, _, pane_sizes = self._get_split_geometry(layout, available_sizes) + size_properties = ("width", "height") + + for i, child_layout in enumerate(layout["children"]): + child_path = path + [i] + container_tag = self._path_to_tag(child_path, "container") + if dpg.does_item_exist(container_tag): + dpg.configure_item(container_tag, **{size_properties[orientation]: pane_sizes[i]}) + child_width, child_height = [(pane_sizes[i], available_sizes[1]), (available_sizes[0], pane_sizes[i])][orientation] + self._resize_splits_recursive(child_layout, child_path, child_width, child_height) + + def _get_split_geometry(self, layout: dict, available_size: tuple[int, int]) -> tuple[int, int, list[int]]: + orientation = layout["orientation"] + num_grips = len(layout["children"]) - 1 + usable_size = max(self.min_pane_size, available_size[orientation] - (num_grips * self.grip_size)) + pane_sizes = [max(self.min_pane_size, int(usable_size * prop)) for prop in layout["proportions"]] + return orientation, usable_size, pane_sizes + + def _get_layout_at_path(self, path: list[int]) -> dict: + current = self.layout + for index in path: + current = current["children"][index] + return current + + def _get_parent_and_index(self, path: list[int]) -> tuple: + return (None, -1) if not path else (self._get_layout_at_path(path[:-1]), path[-1]) + + def _replace_layout_at_path(self, path: list[int], new_layout: dict): + if not path: + self.layout = new_layout + else: + parent, index = self._get_parent_and_index(path) + parent["children"][index] = new_layout + + def _path_to_tag(self, path: list[int], prefix: str = "") -> str: + path_str = "_".join(map(str, path)) if path else "root" + return f"{prefix}_{path_str}" if prefix else path_str + + def _create_grip(self, parent_tag: str, path: list[int], grip_index: int, orientation: int): + grip_tag = self._path_to_tag(path, f"grip_{grip_index}") + width, height = [(self.grip_size, -1), (-1, self.grip_size)][orientation] + + with dpg.child_window(tag=grip_tag, parent=parent_tag, width=width, height=height, no_scrollbar=True, border=False): + button_tag = dpg.add_button(label="", width=-1, height=-1) + + with dpg.item_handler_registry(tag=f"{grip_tag}_handler"): + user_data = (path, grip_index, orientation) + dpg.add_item_active_handler(callback=self._on_grip_drag, user_data=user_data) + dpg.add_item_deactivated_handler(callback=self._on_grip_end, user_data=user_data) + dpg.bind_item_handler_registry(button_tag, f"{grip_tag}_handler") + + def _on_grip_drag(self, sender, app_data, user_data): + path, grip_index, orientation = user_data + layout = self._get_layout_at_path(path) + + if "_drag_data" not in layout: + layout["_drag_data"] = {"initial_proportions": layout["proportions"][:], "start_mouse": dpg.get_mouse_pos(local=False)[orientation]} + return + + drag_data = layout["_drag_data"] + split_tag = self._path_to_tag(path, "split") + if not dpg.does_item_exist(split_tag): + return + + _, usable_size, _ = self._get_split_geometry(layout, dpg.get_item_rect_size(split_tag)) + current_coord = dpg.get_mouse_pos(local=False)[orientation] + delta = current_coord - drag_data["start_mouse"] + delta_prop = delta / usable_size + + left_idx = grip_index + right_idx = left_idx + 1 + initial = drag_data["initial_proportions"] + min_prop = self.min_pane_size / usable_size + + new_left = max(min_prop, initial[left_idx] + delta_prop) + new_right = max(min_prop, initial[right_idx] - delta_prop) + + total_available = initial[left_idx] + initial[right_idx] + if new_left + new_right > total_available: + if new_left > new_right: + new_left = total_available - new_right + else: + new_right = total_available - new_left + + layout["proportions"] = initial[:] + layout["proportions"][left_idx] = new_left + layout["proportions"][right_idx] = new_right + + self._resize_splits_recursive(layout, path) + + def _on_grip_end(self, sender, app_data, user_data): + path, _, _ = user_data + self._get_layout_at_path(path).pop("_drag_data", None) diff --git a/tools/jotpluggler/pluggle.py b/tools/jotpluggler/pluggle.py new file mode 100755 index 0000000000..9868b998ed --- /dev/null +++ b/tools/jotpluggler/pluggle.py @@ -0,0 +1,247 @@ +#!/usr/bin/env python3 +import argparse +import os +import pyautogui +import subprocess +import dearpygui.dearpygui as dpg +import multiprocessing +import uuid +import signal +from openpilot.common.basedir import BASEDIR +from openpilot.tools.jotpluggler.data import DataManager +from openpilot.tools.jotpluggler.datatree import DataTree +from openpilot.tools.jotpluggler.layout import PlotLayoutManager + +DEMO_ROUTE = "a2a0ccea32023010|2023-07-27--13-01-19" + + +class WorkerManager: + def __init__(self, max_workers=None): + self.pool = multiprocessing.Pool(max_workers or min(4, multiprocessing.cpu_count()), initializer=WorkerManager.worker_initializer) + self.active_tasks = {} + + def submit_task(self, func, args_list, callback=None, task_id=None): + task_id = task_id or str(uuid.uuid4()) + + if task_id in self.active_tasks: + try: + self.active_tasks[task_id].terminate() + except Exception: + pass + + def handle_success(result): + self.active_tasks.pop(task_id, None) + if callback: + try: + callback(result) + except Exception as e: + print(f"Callback for task {task_id} failed: {e}") + + def handle_error(error): + self.active_tasks.pop(task_id, None) + print(f"Task {task_id} failed: {error}") + + async_result = self.pool.starmap_async(func, args_list, callback=handle_success, error_callback=handle_error) + self.active_tasks[task_id] = async_result + return task_id + + @staticmethod + def worker_initializer(): + signal.signal(signal.SIGINT, signal.SIG_IGN) + + def shutdown(self): + for task in self.active_tasks.values(): + try: + task.terminate() + except Exception: + pass + self.pool.terminate() + self.pool.join() + + +class PlaybackManager: + def __init__(self): + self.is_playing = False + self.current_time_s = 0.0 + self.duration_s = 0.0 + + def set_route_duration(self, duration: float): + self.duration_s = duration + self.seek(min(self.current_time_s, duration)) + + def toggle_play_pause(self): + if not self.is_playing and self.current_time_s >= self.duration_s: + self.seek(0.0) + self.is_playing = not self.is_playing + + def seek(self, time_s: float): + self.is_playing = False + self.current_time_s = max(0.0, min(time_s, self.duration_s)) + + def update_time(self, delta_t: float): + if self.is_playing: + self.current_time_s = min(self.current_time_s + delta_t, self.duration_s) + if self.current_time_s >= self.duration_s: + self.is_playing = False + return self.current_time_s + + +class MainController: + def __init__(self, scale: float = 1.0): + self.scale = scale + self.data_manager = DataManager() + self.playback_manager = PlaybackManager() + self.worker_manager = WorkerManager() + self._create_global_themes() + self.data_tree = DataTree(self.data_manager, self.playback_manager) + self.plot_layout_manager = PlotLayoutManager(self.data_manager, self.playback_manager, self.worker_manager, scale=self.scale) + self.data_manager.add_observer(self.on_data_loaded) + + def _create_global_themes(self): + with dpg.theme(tag="global_line_theme"): + with dpg.theme_component(dpg.mvLineSeries): + scaled_thickness = max(1.0, self.scale) + dpg.add_theme_style(dpg.mvPlotStyleVar_LineWeight, scaled_thickness, category=dpg.mvThemeCat_Plots) + + with dpg.theme(tag="global_timeline_theme"): + with dpg.theme_component(dpg.mvInfLineSeries): + scaled_thickness = max(1.0, self.scale) + dpg.add_theme_style(dpg.mvPlotStyleVar_LineWeight, scaled_thickness, category=dpg.mvThemeCat_Plots) + dpg.add_theme_color(dpg.mvPlotCol_Line, (255, 0, 0, 128), category=dpg.mvThemeCat_Plots) + + + def on_data_loaded(self, data: dict): + duration = data.get('duration', 0.0) + self.playback_manager.set_route_duration(duration) + + if data.get('reset'): + self.playback_manager.current_time_s = 0.0 + self.playback_manager.duration_s = 0.0 + self.playback_manager.is_playing = False + dpg.set_value("load_status", "Loading...") + dpg.set_value("timeline_slider", 0.0) + dpg.configure_item("timeline_slider", max_value=0.0) + dpg.configure_item("play_pause_button", label="Play") + dpg.configure_item("load_button", enabled=True) + elif data.get('loading_complete'): + num_paths = len(self.data_manager.get_all_paths()) + dpg.set_value("load_status", f"Loaded {num_paths} data paths") + dpg.configure_item("load_button", enabled=True) + elif data.get('segment_added'): + segment_count = data.get('segment_count', 0) + dpg.set_value("load_status", f"Loading... {segment_count} segments processed") + + dpg.configure_item("timeline_slider", max_value=duration) + + def setup_ui(self): + with dpg.window(tag="Primary Window"): + with dpg.group(horizontal=True): + # Left panel - Data tree + with dpg.child_window(label="Sidebar", width=300 * self.scale, tag="sidebar_window", border=True, resizable_x=True): + with dpg.group(horizontal=True): + dpg.add_input_text(tag="route_input", width=-75 * self.scale, hint="Enter route name...") + dpg.add_button(label="Load", callback=self.load_route, tag="load_button", width=-1) + dpg.add_text("Ready to load route", tag="load_status") + dpg.add_separator() + self.data_tree.create_ui("sidebar_window") + + # Right panel - Plots and timeline + with dpg.group(tag="right_panel"): + with dpg.child_window(label="Plot Window", border=True, height=-(30 + 13 * self.scale), tag="main_plot_area"): + self.plot_layout_manager.create_ui("main_plot_area") + + with dpg.child_window(label="Timeline", border=True): + with dpg.table(header_row=False, borders_innerH=False, borders_innerV=False, borders_outerH=False, borders_outerV=False): + dpg.add_table_column(width_fixed=True, init_width_or_weight=int(50 * self.scale)) # Play button + dpg.add_table_column(width_stretch=True) # Timeline slider + dpg.add_table_column(width_fixed=True, init_width_or_weight=int(50 * self.scale)) # FPS counter + with dpg.table_row(): + dpg.add_button(label="Play", tag="play_pause_button", callback=self.toggle_play_pause, width=int(50 * self.scale)) + dpg.add_slider_float(tag="timeline_slider", default_value=0.0, label="", width=-1, callback=self.timeline_drag) + dpg.add_text("", tag="fps_counter") + with dpg.item_handler_registry(tag="plot_resize_handler"): + dpg.add_item_resize_handler(callback=self.on_plot_resize) + dpg.bind_item_handler_registry("right_panel", "plot_resize_handler") + + dpg.set_primary_window("Primary Window", True) + + def on_plot_resize(self, sender, app_data, user_data): + self.plot_layout_manager.on_viewport_resize() + + def load_route(self): + route_name = dpg.get_value("route_input").strip() + if route_name: + dpg.set_value("load_status", "Loading route...") + dpg.configure_item("load_button", enabled=False) + self.data_manager.load_route(route_name) + + def toggle_play_pause(self, sender): + self.playback_manager.toggle_play_pause() + label = "Pause" if self.playback_manager.is_playing else "Play" + dpg.configure_item(sender, label=label) + + def timeline_drag(self, sender, app_data): + self.playback_manager.seek(app_data) + dpg.configure_item("play_pause_button", label="Play") + + def update_frame(self, font): + self.data_tree.update_frame(font) + + new_time = self.playback_manager.update_time(dpg.get_delta_time()) + if not dpg.is_item_active("timeline_slider"): + dpg.set_value("timeline_slider", new_time) + + self.plot_layout_manager.update_all_panels() + + dpg.set_value("fps_counter", f"{dpg.get_frame_rate():.1f} FPS") + + def shutdown(self): + self.worker_manager.shutdown() + + +def main(route_to_load=None): + dpg.create_context() + + # TODO: find better way of calculating display scaling + try: + w, h = next(tuple(map(int, l.split()[0].split('x'))) for l in subprocess.check_output(['xrandr']).decode().split('\n') if '*' in l) # actual resolution + scale = pyautogui.size()[0] / w # scaled resolution + except Exception: + scale = 1 + + with dpg.font_registry(): + default_font = dpg.add_font(os.path.join(BASEDIR, "selfdrive/assets/fonts/Inter-Regular.ttf"), int(13 * scale)) + dpg.bind_font(default_font) + + viewport_width, viewport_height = int(1200 * scale), int(800 * scale) + mouse_x, mouse_y = pyautogui.position() # TODO: find better way of creating the window where the user is (default dpg behavior annoying on multiple displays) + dpg.create_viewport( + title='JotPluggler', width=viewport_width, height=viewport_height, x_pos=mouse_x - viewport_width // 2, y_pos=mouse_y - viewport_height // 2 + ) + dpg.setup_dearpygui() + + controller = MainController(scale=scale) + controller.setup_ui() + + if route_to_load: + dpg.set_value("route_input", route_to_load) + controller.load_route() + + dpg.show_viewport() + + # Main loop + try: + while dpg.is_dearpygui_running(): + controller.update_frame(default_font) + dpg.render_dearpygui_frame() + finally: + controller.shutdown() + dpg.destroy_context() + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="A tool for visualizing openpilot logs.") + parser.add_argument("--demo", action="store_true", help="Use the demo route instead of providing one") + parser.add_argument("route", nargs='?', default=None, help="Optional route name to load on startup.") + args = parser.parse_args() + route = DEMO_ROUTE if args.demo else args.route + main(route_to_load=route) diff --git a/tools/jotpluggler/views.py b/tools/jotpluggler/views.py new file mode 100644 index 0000000000..bcadd4f387 --- /dev/null +++ b/tools/jotpluggler/views.py @@ -0,0 +1,195 @@ +import uuid +import threading +import numpy as np +from collections import deque +import dearpygui.dearpygui as dpg +from abc import ABC, abstractmethod + + +class ViewPanel(ABC): + """Abstract base class for all view panels that can be displayed in a plot container""" + + def __init__(self, panel_id: str = None): + self.panel_id = panel_id or str(uuid.uuid4()) + self.title = "Untitled Panel" + + @abstractmethod + def clear(self): + pass + + @abstractmethod + def create_ui(self, parent_tag: str): + pass + + @abstractmethod + def destroy_ui(self): + pass + + @abstractmethod + def get_panel_type(self) -> str: + pass + + @abstractmethod + def update(self): + pass + + +class TimeSeriesPanel(ViewPanel): + def __init__(self, data_manager, playback_manager, worker_manager, panel_id: str | None = None): + super().__init__(panel_id) + self.data_manager = data_manager + self.playback_manager = playback_manager + self.worker_manager = worker_manager + self.title = "Time Series Plot" + self.plot_tag = f"plot_{self.panel_id}" + self.x_axis_tag = f"{self.plot_tag}_x_axis" + self.y_axis_tag = f"{self.plot_tag}_y_axis" + self.timeline_indicator_tag = f"{self.plot_tag}_timeline" + self._ui_created = False + self._series_data: dict[str, tuple[list, list]] = {} + self._last_plot_duration = 0 + self._update_lock = threading.RLock() + self.results_deque: deque[tuple[str, list, list]] = deque() + self._new_data = False + + def create_ui(self, parent_tag: str): + self.data_manager.add_observer(self.on_data_loaded) + with dpg.plot(height=-1, width=-1, tag=self.plot_tag, parent=parent_tag, drop_callback=self._on_series_drop, payload_type="TIMESERIES_PAYLOAD"): + dpg.add_plot_legend() + dpg.add_plot_axis(dpg.mvXAxis, no_label=True, tag=self.x_axis_tag) + dpg.add_plot_axis(dpg.mvYAxis, no_label=True, tag=self.y_axis_tag) + timeline_series_tag = dpg.add_inf_line_series(x=[0], label="Timeline", parent=self.y_axis_tag, tag=self.timeline_indicator_tag) + dpg.bind_item_theme(timeline_series_tag, "global_timeline_theme") + + for series_path in list(self._series_data.keys()): + self.add_series(series_path) + self._ui_created = True + + def update(self): + with self._update_lock: + if not self._ui_created: + return + + if self._new_data: # handle new data in main thread + self._new_data = False + for series_path in list(self._series_data.keys()): + self.add_series(series_path, update=True) + + while self.results_deque: # handle downsampled results in main thread + results = self.results_deque.popleft() + for series_path, downsampled_time, downsampled_values in results: + series_tag = f"series_{self.panel_id}_{series_path}" + if dpg.does_item_exist(series_tag): + dpg.set_value(series_tag, [downsampled_time, downsampled_values]) + + # update timeline + current_time_s = self.playback_manager.current_time_s + dpg.set_value(self.timeline_indicator_tag, [[current_time_s], [0]]) + + # update timeseries legend label + for series_path, (time_array, value_array) in self._series_data.items(): + position = np.searchsorted(time_array, current_time_s, side='right') - 1 + if position >= 0 and (current_time_s - time_array[position]) <= 1.0: + value = value_array[position] + formatted_value = f"{value:.5f}" if np.issubdtype(type(value), np.floating) else str(value) + series_tag = f"series_{self.panel_id}_{series_path}" + if dpg.does_item_exist(series_tag): + dpg.configure_item(series_tag, label=f"{series_path}: {formatted_value}") + + # downsample if plot zoom changed significantly + plot_duration = dpg.get_axis_limits(self.x_axis_tag)[1] - dpg.get_axis_limits(self.x_axis_tag)[0] + if plot_duration > self._last_plot_duration * 2 or plot_duration < self._last_plot_duration * 0.5: + self._downsample_all_series(plot_duration) + + def _downsample_all_series(self, plot_duration): + plot_width = dpg.get_item_rect_size(self.plot_tag)[0] + if plot_width <= 0 or plot_duration <= 0: + return + + self._last_plot_duration = plot_duration + target_points_per_second = plot_width / plot_duration + work_items = [] + for series_path, (time_array, value_array) in self._series_data.items(): + if len(time_array) == 0: + continue + series_duration = time_array[-1] - time_array[0] if len(time_array) > 1 else 1 + points_per_second = len(time_array) / series_duration + if points_per_second > target_points_per_second * 2: + target_points = max(int(target_points_per_second * series_duration), plot_width) + work_items.append((series_path, time_array, value_array, target_points)) + elif dpg.does_item_exist(f"series_{self.panel_id}_{series_path}"): + dpg.set_value(f"series_{self.panel_id}_{series_path}", [time_array, value_array]) + + if work_items: + self.worker_manager.submit_task( + TimeSeriesPanel._downsample_worker, work_items, callback=lambda results: self.results_deque.append(results), task_id=f"downsample_{self.panel_id}" + ) + + def add_series(self, series_path: str, update: bool = False): + with self._update_lock: + if update or series_path not in self._series_data: + self._series_data[series_path] = self.data_manager.get_timeseries(series_path) + + time_array, value_array = self._series_data[series_path] + series_tag = f"series_{self.panel_id}_{series_path}" + if dpg.does_item_exist(series_tag): + dpg.set_value(series_tag, [time_array, value_array]) + else: + line_series_tag = dpg.add_line_series(x=time_array, y=value_array, label=series_path, parent=self.y_axis_tag, tag=series_tag) + dpg.bind_item_theme(line_series_tag, "global_line_theme") + dpg.fit_axis_data(self.x_axis_tag) + dpg.fit_axis_data(self.y_axis_tag) + plot_duration = dpg.get_axis_limits(self.x_axis_tag)[1] - dpg.get_axis_limits(self.x_axis_tag)[0] + self._downsample_all_series(plot_duration) + + def destroy_ui(self): + with self._update_lock: + self.data_manager.remove_observer(self.on_data_loaded) + if dpg.does_item_exist(self.plot_tag): + dpg.delete_item(self.plot_tag) + self._ui_created = False + + def get_panel_type(self) -> str: + return "timeseries" + + def clear(self): + with self._update_lock: + for series_path in list(self._series_data.keys()): + self.remove_series(series_path) + + def remove_series(self, series_path: str): + with self._update_lock: + if series_path in self._series_data: + if dpg.does_item_exist(f"series_{self.panel_id}_{series_path}"): + dpg.delete_item(f"series_{self.panel_id}_{series_path}") + del self._series_data[series_path] + + def on_data_loaded(self, data: dict): + self._new_data = True + + def _on_series_drop(self, sender, app_data, user_data): + self.add_series(app_data) + + @staticmethod + def _downsample_worker(series_path, time_array, value_array, target_points): + if len(time_array) <= target_points: + return series_path, time_array, value_array + + step = len(time_array) / target_points + indices = [] + + for i in range(target_points): + start_idx = int(i * step) + end_idx = int((i + 1) * step) + if start_idx == end_idx: + indices.append(start_idx) + else: + bucket_values = value_array[start_idx:end_idx] + min_idx = start_idx + np.argmin(bucket_values) + max_idx = start_idx + np.argmax(bucket_values) + if min_idx != max_idx: + indices.extend([min(min_idx, max_idx), max(min_idx, max_idx)]) + else: + indices.append(min_idx) + indices = sorted(set(indices)) + return series_path, time_array[indices], value_array[indices] diff --git a/uv.lock b/uv.lock index 9977ff1bf7..25d2b626cf 100644 --- a/uv.lock +++ b/uv.lock @@ -451,6 +451,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d2/fc/c0a3f4c4eaa5a22fbef91713474666e13d0ea2a69c84532579490a9f2cc8/dbus_next-0.2.3-py3-none-any.whl", hash = "sha256:58948f9aff9db08316734c0be2a120f6dc502124d9642f55e90ac82ffb16a18b", size = 57885, upload-time = "2021-07-25T22:11:25.466Z" }, ] +[[package]] +name = "dearpygui" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/fe/66293fc40254a29f060efd3398f2b1001ed79263ae1837db9ec42caa8f1d/dearpygui-2.1.0-cp311-cp311-macosx_10_6_x86_64.whl", hash = "sha256:03e5dc0b3dd2f7965e50bbe41f3316a814408064b582586de994d93afedb125c", size = 2100924, upload-time = "2025-07-07T14:20:00.602Z" }, + { url = "https://files.pythonhosted.org/packages/c4/4d/9fa1c3156ba7bbf4dc89e2e322998752fccfdc3575923a98dd6a4da48911/dearpygui-2.1.0-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:b5b37710c3fa135c48e2347f39ecd1f415146e86db5d404707a0bf72d16bd304", size = 1874441, upload-time = "2025-07-07T14:20:09.165Z" }, + { url = "https://files.pythonhosted.org/packages/5a/3c/af5673b50699e1734296a0b5bcef39bb6989175b001ad1f9b0e7888ad90d/dearpygui-2.1.0-cp311-cp311-manylinux1_x86_64.whl", hash = "sha256:b0cfd7ac7eaa090fc22d6aa60fc4b527fc631cee10c348e4d8df92bb39af03d2", size = 2636574, upload-time = "2025-07-07T14:20:14.951Z" }, + { url = "https://files.pythonhosted.org/packages/7f/db/ed4db0bb3d88e7a8c405472641419086bef9632c4b8b0489dc0c43519c0d/dearpygui-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:a9af54f96d3ef30c5db9d12cdf3266f005507396fb0da2e12e6b22b662161070", size = 1810266, upload-time = "2025-07-07T14:19:51.565Z" }, + { url = "https://files.pythonhosted.org/packages/55/9d/20a55786cc9d9266395544463d5db3be3528f7d5244bc52ba760de5dcc2d/dearpygui-2.1.0-cp312-cp312-macosx_10_6_x86_64.whl", hash = "sha256:1270ceb9cdb8ecc047c42477ccaa075b7864b314a5d09191f9280a24c8aa90a0", size = 2101499, upload-time = "2025-07-07T14:20:01.701Z" }, + { url = "https://files.pythonhosted.org/packages/a7/b2/39d820796b7ac4d0ebf93306c1f031bf3516b159408286f1fb495c6babeb/dearpygui-2.1.0-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:ce9969eb62057b9d4c88a8baaed13b5fbe4058caa9faf5b19fec89da75aece3d", size = 1874385, upload-time = "2025-07-07T14:20:11.226Z" }, + { url = "https://files.pythonhosted.org/packages/fc/26/c29998ffeb5eb8d638f307851e51a81c8bd4aeaf89ad660fc67ea4d1ac1a/dearpygui-2.1.0-cp312-cp312-manylinux1_x86_64.whl", hash = "sha256:a3ca8cf788db63ef7e2e8d6f277631b607d548b37606f080ca1b42b1f0a9b183", size = 2635863, upload-time = "2025-07-07T14:20:17.186Z" }, + { url = "https://files.pythonhosted.org/packages/28/9c/3ab33927f1d8c839c5b7033a33d44fc9f0aeb00c264fc9772cb7555a03c4/dearpygui-2.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:43f0e4db9402f44fc3683a1f5c703564819de18cc15a042de7f1ed1c8cb5d148", size = 1810460, upload-time = "2025-07-07T14:19:53.13Z" }, +] + [[package]] name = "dictdiffer" version = "0.9.0" @@ -1246,6 +1261,7 @@ dependencies = [ { name = "cffi" }, { name = "crcmod" }, { name = "cython" }, + { name = "dearpygui" }, { name = "future-fstrings" }, { name = "inputs" }, { name = "json-rpc" }, @@ -1337,6 +1353,7 @@ requires-dist = [ { name = "crcmod" }, { name = "cython" }, { name = "dbus-next", marker = "extra == 'dev'" }, + { name = "dearpygui", specifier = ">=2.1.0" }, { name = "dictdiffer", marker = "extra == 'dev'" }, { name = "future-fstrings" }, { name = "hypothesis", marker = "extra == 'testing'", specifier = "==6.47.*" }, From 2bfdd0d61db30cc5e97c144ce299bec81adc8144 Mon Sep 17 00:00:00 2001 From: Jason Young <46612682+jyoung8607@users.noreply.github.com> Date: Tue, 9 Sep 2025 18:02:31 -0400 Subject: [PATCH 059/159] PlotJuggler: Updated layout for torque controller (#36123) * PlotJuggler: Updated layout for torque controller * yeah, no --- pyproject.toml | 2 +- .../plotjuggler/layouts/torque-controller.xml | 305 +++++++++--------- 2 files changed, 156 insertions(+), 151 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 88c4d06739..1655b565e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -176,7 +176,7 @@ quiet-level = 3 # if you've got a short variable name that's getting flagged, add it here ignore-words-list = "bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie,preints,whit,indexIn,ws,uint,grey,deque,stdio,amin,BA,LITE,atEnd,UIs,errorString,arange,FocusIn,od,tim,relA,hist,copyable,jupyter,thead,TGE,abl,lite" builtin = "clear,rare,informal,code,names,en-GB_to_en-US" -skip = "./third_party/*, ./tinygrad/*, ./tinygrad_repo/*, ./msgq/*, ./panda/*, ./opendbc/*, ./opendbc_repo/*, ./rednose/*, ./rednose_repo/*, ./teleoprtc/*, ./teleoprtc_repo/*, *.ts, uv.lock, *.onnx, ./cereal/gen/*, */c_generated_code/*, docs/assets/*" +skip = "./third_party/*, ./tinygrad/*, ./tinygrad_repo/*, ./msgq/*, ./panda/*, ./opendbc/*, ./opendbc_repo/*, ./rednose/*, ./rednose_repo/*, ./teleoprtc/*, ./teleoprtc_repo/*, *.ts, uv.lock, *.onnx, ./cereal/gen/*, */c_generated_code/*, docs/assets/*, tools/plotjuggler/layouts/*" [tool.mypy] python_version = "3.11" diff --git a/tools/plotjuggler/layouts/torque-controller.xml b/tools/plotjuggler/layouts/torque-controller.xml index 606df03611..8e9a1a8526 100644 --- a/tools/plotjuggler/layouts/torque-controller.xml +++ b/tools/plotjuggler/layouts/torque-controller.xml @@ -1,77 +1,45 @@ - + - + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + @@ -79,115 +47,134 @@ - + - - + + - - + + - - + + - - + + - - + + - - + + - + - - - - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - + + - - - - + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -199,25 +186,34 @@ + + + + + + + + + + + + + - + - return (0) - /carState/canValid + return value * 3.6 + /carState/vEgo - + - return (value * v1 ^ 2) - (v2 * 9.81) - /controlsState/curvature - - /carState/vEgo - /liveParameters/roll - + return value * 2.23694 + /carState/vEgo @@ -228,15 +224,24 @@ /liveParameters/roll - + - return value * 2.23694 - /carState/vEgo + return (value * v1 ^ 2) - (v2 * 9.81) + /controlsState/curvature + + /carState/vEgo + /liveParameters/roll + - + - return value * 3.6 - /carState/vEgo + return value + 0.2 + /carParams/steerActuatorDelay + + + + return (0) + /carState/canValid From d0171084b51c2ee9eb2d3211adc5201edfb498f1 Mon Sep 17 00:00:00 2001 From: YassineYousfi Date: Tue, 9 Sep 2025 15:40:39 -0700 Subject: [PATCH 060/159] Update RELEASES.md 0.10.1 --- RELEASES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASES.md b/RELEASES.md index d89ee24628..90d99c0015 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -4,6 +4,7 @@ Version 0.10.1 (2025-09-08) * World Model: removed global localization inputs * World Model: 2x the number of parameters * World Model: trained on 4x the number of segments + * Driving Vision Model: trained on 4x the number of segments * Record driving feedback using LKAS button * Honda City 2023 support thanks to drFritz! From 6b131753380e21b22701827194cc3d083ec3f073 Mon Sep 17 00:00:00 2001 From: Jimmy <9859727+Quantizr@users.noreply.github.com> Date: Tue, 9 Sep 2025 21:09:08 -1000 Subject: [PATCH 061/159] jotpluggler: better handle sparse message data and bools (#36124) * better handle sparse message data * fix plotting of of bools * add type for msg._valid * fix typing * add assert in case something changes in future --- tools/jotpluggler/data.py | 105 ++++++++++++++++++++++++++----------- tools/jotpluggler/views.py | 18 +++---- 2 files changed, 82 insertions(+), 41 deletions(-) diff --git a/tools/jotpluggler/data.py b/tools/jotpluggler/data.py index 41c305718e..100dfe544d 100644 --- a/tools/jotpluggler/data.py +++ b/tools/jotpluggler/data.py @@ -3,7 +3,7 @@ import threading import multiprocessing import bisect from collections import defaultdict -import tqdm +from tqdm import tqdm from openpilot.common.swaglog import cloudlog from openpilot.tools.lib.logreader import _LogFileReader, LogReader @@ -70,9 +70,6 @@ def extract_field_types(schema, prefix, field_types_dict): def _convert_to_optimal_dtype(values_list, capnp_type): - if not values_list: - return np.array([]) - dtype_mapping = { 'bool': np.bool_, 'int8': np.int8, 'int16': np.int16, 'int32': np.int32, 'int64': np.int64, 'uint8': np.uint8, 'uint16': np.uint16, 'uint32': np.uint32, 'uint64': np.uint64, @@ -80,8 +77,8 @@ def _convert_to_optimal_dtype(values_list, capnp_type): 'enum': object, 'anyPointer': object, } - target_dtype = dtype_mapping.get(capnp_type) - return np.array(values_list, dtype=target_dtype) if target_dtype else np.array(values_list) + target_dtype = dtype_mapping.get(capnp_type, object) + return np.array(values_list, dtype=target_dtype) def _match_field_type(field_path, field_types): @@ -94,6 +91,21 @@ def _match_field_type(field_path, field_types): return field_types.get(template_path) +def _get_field_times_values(segment, field_name): + if field_name not in segment: + return None, None + + field_data = segment[field_name] + segment_times = segment['t'] + + if field_data['sparse']: + if len(field_data['t_index']) == 0: + return None, None + return segment_times[field_data['t_index']], field_data['values'] + else: + return segment_times, field_data['values'] + + def msgs_to_time_series(msgs): """Extract scalar fields and return (time_series_data, start_time, end_time).""" collected_data = defaultdict(lambda: {'timestamps': [], 'columns': defaultdict(list), 'sparse_fields': set()}) @@ -110,16 +122,22 @@ def msgs_to_time_series(msgs): max_time = timestamp sub_msg = getattr(msg, typ) - if not hasattr(sub_msg, 'to_dict') or typ in ('qcomGnss', 'ubloxGnss'): + if not hasattr(sub_msg, 'to_dict'): continue if hasattr(sub_msg, 'schema') and typ not in extracted_schemas: extract_field_types(sub_msg.schema, typ, field_types) extracted_schemas.add(typ) - msg_dict = sub_msg.to_dict(verbose=True) + try: + msg_dict = sub_msg.to_dict(verbose=True) + except Exception as e: + cloudlog.warning(f"Failed to convert sub_msg.to_dict() for message of type: {typ}: {e}") + continue + flat_dict = flatten_dict(msg_dict) flat_dict['_valid'] = msg.valid + field_types[f"{typ}/_valid"] = 'bool' type_data = collected_data[typ] columns, sparse_fields = type_data['columns'], type_data['sparse_fields'] @@ -152,11 +170,26 @@ def msgs_to_time_series(msgs): values = [None] * (len(data['timestamps']) - len(values)) + values sparse_fields.add(field_name) - if field_name in sparse_fields: - typ_result[field_name] = np.array(values, dtype=object) - else: - capnp_type = _match_field_type(f"{typ}/{field_name}", field_types) - typ_result[field_name] = _convert_to_optimal_dtype(values, capnp_type) + capnp_type = _match_field_type(f"{typ}/{field_name}", field_types) + + if field_name in sparse_fields: # extract non-None values and their indices + non_none_indices = [] + non_none_values = [] + for i, value in enumerate(values): + if value is not None: + non_none_indices.append(i) + non_none_values.append(value) + + if non_none_values: # check if indices > uint16 max, currently would require a 1000+ Hz signal since indices are within segments + assert max(non_none_indices) <= 65535, f"Sparse field {typ}/{field_name} has timestamp indices exceeding uint16 max. Max: {max(non_none_indices)}" + + typ_result[field_name] = { + 'values': _convert_to_optimal_dtype(non_none_values, capnp_type), + 'sparse': True, + 't_index': np.array(non_none_indices, dtype=np.uint16), + } + else: # dense representation + typ_result[field_name] = {'values': _convert_to_optimal_dtype(values, capnp_type), 'sparse': False} final_result[typ] = typ_result @@ -195,22 +228,31 @@ class DataManager: times, values = [], [] for segment in self._segments: - if msg_type in segment and field in segment[msg_type]: - times.append(segment[msg_type]['t']) - values.append(segment[msg_type][field]) + if msg_type in segment: + field_times, field_values = _get_field_times_values(segment[msg_type], field) + if field_times is not None: + times.append(field_times) + values.append(field_values) if not times: - return [], [] + return np.array([]), np.array([]) combined_times = np.concatenate(times) - self._start_time - if len(values) > 1 and any(arr.dtype != values[0].dtype for arr in values): - values = [arr.astype(object) for arr in values] - return combined_times, np.concatenate(values) + if len(values) > 1: + first_dtype = values[0].dtype + if all(arr.dtype == first_dtype for arr in values): # check if all arrays have compatible dtypes + combined_values = np.concatenate(values) + else: + combined_values = np.concatenate([arr.astype(object) for arr in values]) + else: + combined_values = values[0] if values else np.array([]) + + return combined_times, combined_values def get_value_at(self, path: str, time: float): with self._lock: - MAX_LOOKBACK = 5.0 # seconds + MAX_LOOKBACK = 5.0 # seconds absolute_time = self._start_time + time message_type, field = path.split('/', 1) current_index = bisect.bisect_right(self._segment_starts, absolute_time) - 1 @@ -218,14 +260,14 @@ class DataManager: if not 0 <= index < len(self._segments): continue segment = self._segments[index].get(message_type) - if not segment or field not in segment: + if not segment: continue - times = segment['t'] - if len(times) == 0 or (index != current_index and absolute_time - times[-1] > MAX_LOOKBACK): + times, values = _get_field_times_values(segment, field) + if times is None or len(times) == 0 or (index != current_index and absolute_time - times[-1] > MAX_LOOKBACK): continue position = np.searchsorted(times, absolute_time, 'right') - 1 if position >= 0 and absolute_time - times[position] <= MAX_LOOKBACK: - return segment[field][position] + return values[position] return None def get_all_paths(self): @@ -237,10 +279,9 @@ class DataManager: return self._duration def is_plottable(self, path: str): - data = self.get_timeseries(path) - if data is None: + _, values = self.get_timeseries(path) + if len(values) == 0: return False - _, values = data return np.issubdtype(values.dtype, np.number) or np.issubdtype(values.dtype, np.bool_) def add_observer(self, callback): @@ -272,7 +313,7 @@ class DataManager: return num_processes = max(1, multiprocessing.cpu_count() // 2) - with multiprocessing.Pool(processes=num_processes) as pool, tqdm.tqdm(total=len(lr.logreader_identifiers), desc="Processing Segments") as pbar: + with multiprocessing.Pool(processes=num_processes) as pool, tqdm(total=len(lr.logreader_identifiers), desc="Processing Segments") as pbar: for segment_result, start_time, end_time in pool.imap(_process_segment, lr.logreader_identifiers): pbar.update(1) if segment_result: @@ -292,9 +333,9 @@ class DataManager: self._duration = end_time - self._start_time for msg_type, data in segment_data.items(): - for field in data.keys(): - if field != 't': - self._paths.add(f"{msg_type}/{field}") + for field_name in data.keys(): + if field_name != 't': + self._paths.add(f"{msg_type}/{field_name}") observers = self._observers.copy() diff --git a/tools/jotpluggler/views.py b/tools/jotpluggler/views.py index bcadd4f387..4af9a102ac 100644 --- a/tools/jotpluggler/views.py +++ b/tools/jotpluggler/views.py @@ -46,10 +46,10 @@ class TimeSeriesPanel(ViewPanel): self.y_axis_tag = f"{self.plot_tag}_y_axis" self.timeline_indicator_tag = f"{self.plot_tag}_timeline" self._ui_created = False - self._series_data: dict[str, tuple[list, list]] = {} + self._series_data: dict[str, tuple[np.ndarray, np.ndarray]] = {} self._last_plot_duration = 0 self._update_lock = threading.RLock() - self.results_deque: deque[tuple[str, list, list]] = deque() + self._results_deque: deque[tuple[str, list, list]] = deque() self._new_data = False def create_ui(self, parent_tag: str): @@ -75,12 +75,12 @@ class TimeSeriesPanel(ViewPanel): for series_path in list(self._series_data.keys()): self.add_series(series_path, update=True) - while self.results_deque: # handle downsampled results in main thread - results = self.results_deque.popleft() + while self._results_deque: # handle downsampled results in main thread + results = self._results_deque.popleft() for series_path, downsampled_time, downsampled_values in results: series_tag = f"series_{self.panel_id}_{series_path}" if dpg.does_item_exist(series_tag): - dpg.set_value(series_tag, [downsampled_time, downsampled_values]) + dpg.set_value(series_tag, (downsampled_time, downsampled_values.astype(float))) # update timeline current_time_s = self.playback_manager.current_time_s @@ -118,11 +118,11 @@ class TimeSeriesPanel(ViewPanel): target_points = max(int(target_points_per_second * series_duration), plot_width) work_items.append((series_path, time_array, value_array, target_points)) elif dpg.does_item_exist(f"series_{self.panel_id}_{series_path}"): - dpg.set_value(f"series_{self.panel_id}_{series_path}", [time_array, value_array]) + dpg.set_value(f"series_{self.panel_id}_{series_path}", (time_array, value_array.astype(float))) if work_items: self.worker_manager.submit_task( - TimeSeriesPanel._downsample_worker, work_items, callback=lambda results: self.results_deque.append(results), task_id=f"downsample_{self.panel_id}" + TimeSeriesPanel._downsample_worker, work_items, callback=lambda results: self._results_deque.append(results), task_id=f"downsample_{self.panel_id}" ) def add_series(self, series_path: str, update: bool = False): @@ -133,9 +133,9 @@ class TimeSeriesPanel(ViewPanel): time_array, value_array = self._series_data[series_path] series_tag = f"series_{self.panel_id}_{series_path}" if dpg.does_item_exist(series_tag): - dpg.set_value(series_tag, [time_array, value_array]) + dpg.set_value(series_tag, (time_array, value_array.astype(float))) else: - line_series_tag = dpg.add_line_series(x=time_array, y=value_array, label=series_path, parent=self.y_axis_tag, tag=series_tag) + line_series_tag = dpg.add_line_series(x=time_array, y=value_array.astype(float), label=series_path, parent=self.y_axis_tag, tag=series_tag) dpg.bind_item_theme(line_series_tag, "global_line_theme") dpg.fit_axis_data(self.x_axis_tag) dpg.fit_axis_data(self.y_axis_tag) From 10580aca922789c58fae1a6922193df9b2fdf311 Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Wed, 10 Sep 2025 15:06:25 -0700 Subject: [PATCH 062/159] ci: adjust power draw bounds (#36130) * consider min * bounds --- system/hardware/tici/tests/test_power_draw.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/hardware/tici/tests/test_power_draw.py b/system/hardware/tici/tests/test_power_draw.py index 46b45460b5..4fbde81673 100644 --- a/system/hardware/tici/tests/test_power_draw.py +++ b/system/hardware/tici/tests/test_power_draw.py @@ -31,9 +31,9 @@ class Proc: PROCS = [ - Proc(['camerad'], 1.75, msgs=['roadCameraState', 'wideRoadCameraState', 'driverCameraState']), + Proc(['camerad'], 1.65, atol=0.4, msgs=['roadCameraState', 'wideRoadCameraState', 'driverCameraState']), Proc(['modeld'], 1.24, atol=0.2, msgs=['modelV2']), - Proc(['dmonitoringmodeld'], 0.7, msgs=['driverStateV2']), + Proc(['dmonitoringmodeld'], 0.65, atol=0.35, msgs=['driverStateV2']), Proc(['encoderd'], 0.23, msgs=[]), ] From 0e1b573f89ab425e724ee0b7278f2d31bfd7029e Mon Sep 17 00:00:00 2001 From: Jason Young <46612682+jyoung8607@users.noreply.github.com> Date: Thu, 11 Sep 2025 05:32:44 -0400 Subject: [PATCH 063/159] Honda: Add Honda Odyssey 2021-25 to release (#36132) * bump opendbc * regen CARS.md * add to RELEASES.md * forgot this was originally VG's PR * correctly typo the typo * follow recent DBC cleanup --- RELEASES.md | 3 ++- docs/CARS.md | 7 ++++--- opendbc_repo | 2 +- tools/sim/lib/simulated_car.py | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 90d99c0015..529bcb6b09 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -6,7 +6,8 @@ Version 0.10.1 (2025-09-08) * World Model: trained on 4x the number of segments * Driving Vision Model: trained on 4x the number of segments * Record driving feedback using LKAS button -* Honda City 2023 support thanks to drFritz! +* Honda City 2023 support thanks to vanillagorillaa and drFritz! +* Honda Odyssey 2021-25 support thanks to vanillagorillaa and MVL! Version 0.10.0 (2025-08-05) ======================== diff --git a/docs/CARS.md b/docs/CARS.md index 7269f25737..4c0569a1b8 100644 --- a/docs/CARS.md +++ b/docs/CARS.md @@ -4,7 +4,7 @@ A supported vehicle is one that just works when you install a comma device. All supported cars provide a better experience than any stock system. Supported vehicles reference the US market unless otherwise specified. -# 321 Supported Cars +# 322 Supported Cars |Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|Hardware Needed
 |Video|Setup Video| |---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:| @@ -83,7 +83,7 @@ A supported vehicle is one that just works when you install a comma device. All |Honda|Civic Hatchback 2017-18|Honda Sensing|openpilot available[1](#footnotes)|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Civic Hatchback 2019-21|All|openpilot available[1](#footnotes)|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Civic Hatchback 2022-24|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch B connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| -|Honda|Civic Hatchback Hybrid 2025|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch B connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| +|Honda|Civic Hatchback Hybrid 2025-26|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch B connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Civic Hatchback Hybrid (Europe only) 2023|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch B connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Civic Hybrid 2025|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch B connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|CR-V 2015-16|Touring Trim|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Honda Nidec connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| @@ -99,6 +99,7 @@ A supported vehicle is one that just works when you install a comma device. All |Honda|Insight 2019-22|All|openpilot available[1](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Inspire 2018|All|openpilot available[1](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Odyssey 2018-20|Honda Sensing|openpilot|26 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Honda Nidec connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| +|Honda|Odyssey 2021-25|All|openpilot available[1](#footnotes)|0 mph|43 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Passport 2019-25|All|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Honda Nidec connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Pilot 2016-22|Honda Sensing|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Honda Nidec connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Pilot 2023-25|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch C connector
- 1 angled mount (8 degrees)
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| @@ -247,7 +248,7 @@ A supported vehicle is one that just works when you install a comma device. All |Tesla[11](#footnotes)|Model 3 (with HW3) 2019-23[10](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Tesla A connector
- 1 USB-C coupler
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 long OBD-C cable (9.5 ft)
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Tesla[11](#footnotes)|Model 3 (with HW4) 2024-25[10](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Tesla B connector
- 1 USB-C coupler
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 long OBD-C cable (9.5 ft)
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Tesla[11](#footnotes)|Model Y (with HW3) 2020-23[10](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Tesla A connector
- 1 USB-C coupler
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 long OBD-C cable (9.5 ft)
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| -|Tesla[11](#footnotes)|Model Y (with HW4) 2024[10](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Tesla B connector
- 1 USB-C coupler
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 long OBD-C cable (9.5 ft)
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| +|Tesla[11](#footnotes)|Model Y (with HW4) 2024-25[10](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Tesla B connector
- 1 USB-C coupler
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 long OBD-C cable (9.5 ft)
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Toyota|Alphard 2019-20|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Toyota A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Toyota|Alphard Hybrid 2021|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Toyota A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Toyota|Avalon 2016|Toyota Safety Sense P|openpilot available[2](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Toyota A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| diff --git a/opendbc_repo b/opendbc_repo index 7afc25d8d4..435ef8203b 160000 --- a/opendbc_repo +++ b/opendbc_repo @@ -1 +1 @@ -Subproject commit 7afc25d8d4096bb31e25c0b7ae0b961ea05f5394 +Subproject commit 435ef8203be39c225e95ba8b10b7db7272b99fcc diff --git a/tools/sim/lib/simulated_car.py b/tools/sim/lib/simulated_car.py index 2681b26904..68ff3050db 100644 --- a/tools/sim/lib/simulated_car.py +++ b/tools/sim/lib/simulated_car.py @@ -11,7 +11,7 @@ from openpilot.tools.sim.lib.common import SimulatorState class SimulatedCar: """Simulates a honda civic 2022 (panda state + can messages) to OpenPilot""" - packer = CANPacker("honda_civic_ex_2022_can_generated") + packer = CANPacker("honda_bosch_radarless_generated") def __init__(self): self.pm = messaging.PubMaster(['can', 'pandaStates']) @@ -23,7 +23,7 @@ class SimulatedCar: @staticmethod def get_car_can_parser(): - dbc_f = 'honda_civic_ex_2022_can_generated' + dbc_f = 'honda_bosch_radarless_generated' checks = [] return CANParser(dbc_f, checks, 0) From 4ccd17903b6528d73ebd7ab5d4e30eca3685d2d0 Mon Sep 17 00:00:00 2001 From: Jason Young <46612682+jyoung8607@users.noreply.github.com> Date: Thu, 11 Sep 2025 05:59:15 -0400 Subject: [PATCH 064/159] correction to Honda release notes (#36133) correction to release notes --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 529bcb6b09..b868bb7d5e 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -7,7 +7,7 @@ Version 0.10.1 (2025-09-08) * Driving Vision Model: trained on 4x the number of segments * Record driving feedback using LKAS button * Honda City 2023 support thanks to vanillagorillaa and drFritz! -* Honda Odyssey 2021-25 support thanks to vanillagorillaa and MVL! +* Honda Odyssey 2021-25 support thanks to MVL! Version 0.10.0 (2025-08-05) ======================== From 3c28188d7a6b433211d665f5482720275088d7d3 Mon Sep 17 00:00:00 2001 From: Jason Young <46612682+jyoung8607@users.noreply.github.com> Date: Thu, 11 Sep 2025 07:04:15 -0400 Subject: [PATCH 065/159] Honda: Add Honda N-Box 2018 to release (#36134) * bump opendbc * regen CARS.md * add to RELEASES.md --- RELEASES.md | 1 + docs/CARS.md | 3 ++- opendbc_repo | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index b868bb7d5e..746dea9fd7 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -7,6 +7,7 @@ Version 0.10.1 (2025-09-08) * Driving Vision Model: trained on 4x the number of segments * Record driving feedback using LKAS button * Honda City 2023 support thanks to vanillagorillaa and drFritz! +* Honda N-Box 2018 support thanks to miettal! * Honda Odyssey 2021-25 support thanks to MVL! Version 0.10.0 (2025-08-05) diff --git a/docs/CARS.md b/docs/CARS.md index 4c0569a1b8..bd6a9c920c 100644 --- a/docs/CARS.md +++ b/docs/CARS.md @@ -4,7 +4,7 @@ A supported vehicle is one that just works when you install a comma device. All supported cars provide a better experience than any stock system. Supported vehicles reference the US market unless otherwise specified. -# 322 Supported Cars +# 323 Supported Cars |Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|Hardware Needed
 |Video|Setup Video| |---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:| @@ -98,6 +98,7 @@ A supported vehicle is one that just works when you install a comma device. All |Honda|HR-V 2023-25|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch B connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Insight 2019-22|All|openpilot available[1](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Inspire 2018|All|openpilot available[1](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| +|Honda|N-Box 2018|All|openpilot available[1](#footnotes)|0 mph|11 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Odyssey 2018-20|Honda Sensing|openpilot|26 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Honda Nidec connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Odyssey 2021-25|All|openpilot available[1](#footnotes)|0 mph|43 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Passport 2019-25|All|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Honda Nidec connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| diff --git a/opendbc_repo b/opendbc_repo index 435ef8203b..4170d7d876 160000 --- a/opendbc_repo +++ b/opendbc_repo @@ -1 +1 @@ -Subproject commit 435ef8203be39c225e95ba8b10b7db7272b99fcc +Subproject commit 4170d7d876a87904dab4b351aa8139ec3d400430 From 994170ddb593dfcdc7ec613b4eab2ca2c7c10309 Mon Sep 17 00:00:00 2001 From: Jimmy <9859727+Quantizr@users.noreply.github.com> Date: Thu, 11 Sep 2025 07:45:36 -1000 Subject: [PATCH 066/159] fix qcom decoder compilation on mac with platform check (#36131) --- tools/replay/SConscript | 4 +++- tools/replay/framereader.cc | 7 ++++++- tools/replay/framereader.h | 5 +++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tools/replay/SConscript b/tools/replay/SConscript index 99c8263a8c..136c4119f6 100644 --- a/tools/replay/SConscript +++ b/tools/replay/SConscript @@ -12,7 +12,9 @@ else: base_libs.append('OpenCL') replay_lib_src = ["replay.cc", "consoleui.cc", "camera.cc", "filereader.cc", "logreader.cc", "framereader.cc", - "route.cc", "util.cc", "seg_mgr.cc", "timeline.cc", "api.cc", "qcom_decoder.cc"] + "route.cc", "util.cc", "seg_mgr.cc", "timeline.cc", "api.cc"] +if arch != "Darwin": + replay_lib_src.append("qcom_decoder.cc") replay_lib = replay_env.Library("replay", replay_lib_src, LIBS=base_libs, FRAMEWORKS=base_frameworks) Export('replay_lib') replay_libs = [replay_lib, 'avutil', 'avcodec', 'avformat', 'bz2', 'zstd', 'curl', 'yuv', 'ncurses'] + base_libs diff --git a/tools/replay/framereader.cc b/tools/replay/framereader.cc index f2b1faf2c4..e9cd090446 100644 --- a/tools/replay/framereader.cc +++ b/tools/replay/framereader.cc @@ -39,9 +39,12 @@ struct DecoderManager { } std::unique_ptr decoder; + #ifndef __APPLE__ if (Hardware::TICI() && hw_decoder) { decoder = std::make_unique(); - } else { + } else + #endif + { decoder = std::make_unique(); } @@ -264,6 +267,7 @@ bool FFmpegVideoDecoder::copyBuffer(AVFrame *f, VisionBuf *buf) { return true; } +#ifndef __APPLE__ bool QcomVideoDecoder::open(AVCodecParameters *codecpar, bool hw_decoder) { if (codecpar->codec_id != AV_CODEC_ID_HEVC) { rError("Hardware decoder only supports HEVC codec"); @@ -305,3 +309,4 @@ bool QcomVideoDecoder::decode(FrameReader *reader, int idx, VisionBuf *buf) { } return result; } +#endif diff --git a/tools/replay/framereader.h b/tools/replay/framereader.h index 1fb3cdfeb1..d8e86fce0f 100644 --- a/tools/replay/framereader.h +++ b/tools/replay/framereader.h @@ -6,7 +6,10 @@ #include "msgq/visionipc/visionbuf.h" #include "tools/replay/filereader.h" #include "tools/replay/util.h" + +#ifndef __APPLE__ #include "tools/replay/qcom_decoder.h" +#endif extern "C" { #include @@ -65,6 +68,7 @@ private: AVBufferRef *hw_device_ctx = nullptr; }; +#ifndef __APPLE__ class QcomVideoDecoder : public VideoDecoder { public: QcomVideoDecoder() {}; @@ -75,3 +79,4 @@ public: private: MsmVidc msm_vidc = MsmVidc(); }; +#endif From 67238d5045a3b0cb1bd675acd02f7ee638dc656a Mon Sep 17 00:00:00 2001 From: vanillagorillaa <31773928+vanillagorillaa@users.noreply.github.com> Date: Thu, 11 Sep 2025 12:47:23 -0500 Subject: [PATCH 067/159] Update release notes (#36137) Update RELEASES.md --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 746dea9fd7..f9656cfb07 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -8,7 +8,7 @@ Version 0.10.1 (2025-09-08) * Record driving feedback using LKAS button * Honda City 2023 support thanks to vanillagorillaa and drFritz! * Honda N-Box 2018 support thanks to miettal! -* Honda Odyssey 2021-25 support thanks to MVL! +* Honda Odyssey 2021-25 support thanks to csouers and MVL! Version 0.10.0 (2025-08-05) ======================== From fa498221da86eb76e6342cd9897efd509671f077 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Thu, 11 Sep 2025 10:48:32 -0700 Subject: [PATCH 068/159] still thinking about this one --- RELEASES.md | 1 - 1 file changed, 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index f9656cfb07..189aa7ad54 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -5,7 +5,6 @@ Version 0.10.1 (2025-09-08) * World Model: 2x the number of parameters * World Model: trained on 4x the number of segments * Driving Vision Model: trained on 4x the number of segments -* Record driving feedback using LKAS button * Honda City 2023 support thanks to vanillagorillaa and drFritz! * Honda N-Box 2018 support thanks to miettal! * Honda Odyssey 2021-25 support thanks to csouers and MVL! From 572c03dbace3d9e0454c3d4f1561e31333821aeb Mon Sep 17 00:00:00 2001 From: Jimmy <9859727+Quantizr@users.noreply.github.com> Date: Thu, 11 Sep 2025 07:48:45 -1000 Subject: [PATCH 069/159] jotpluggler: fix flashing while searching (#36128) * modify in place instead of recreating nodes * don't delete DataTreeNodes and simplify code * faster: more efficient state tracking, better handler deletion --- tools/jotpluggler/datatree.py | 266 ++++++++++++++++++++-------------- 1 file changed, 160 insertions(+), 106 deletions(-) diff --git a/tools/jotpluggler/datatree.py b/tools/jotpluggler/datatree.py index 7bd026cf98..c18ab61892 100644 --- a/tools/jotpluggler/datatree.py +++ b/tools/jotpluggler/datatree.py @@ -2,7 +2,6 @@ import os import re import threading import numpy as np -from collections import deque import dearpygui.dearpygui as dpg @@ -12,8 +11,9 @@ class DataTreeNode: self.full_path = full_path self.parent = parent self.children: dict[str, DataTreeNode] = {} + self.filtered_children: dict[str, DataTreeNode] = {} + self.created_children: dict[str, DataTreeNode] = {} self.is_leaf = False - self.child_count = 0 self.is_plottable: bool | None = None self.ui_created = False self.children_ui_created = False @@ -28,13 +28,17 @@ class DataTree: self.playback_manager = playback_manager self.current_search = "" self.data_tree = DataTreeNode(name="root") - self._build_queue: deque[tuple[DataTreeNode, str | None, str | int]] = deque() - self._all_paths_cache: set[str] = set() - self._item_handlers: set[str] = set() + self._build_queue: dict[str, tuple[DataTreeNode, DataTreeNode, str | int]] = {} # full_path -> (node, parent, before_tag) + self._current_created_paths: set[str] = set() + self._current_filtered_paths: set[str] = set() + self._path_to_node: dict[str, DataTreeNode] = {} # full_path -> node + self._expanded_tags: set[str] = set() + self._item_handlers: dict[str, str] = {} # ui_tag -> handler_tag self._avg_char_width = None self._queued_search = None self._new_data = False self._ui_lock = threading.RLock() + self._handlers_to_delete = [] self.data_manager.add_observer(self._on_data_loaded) def create_ui(self, parent_tag: str): @@ -48,31 +52,102 @@ class DataTree: def _on_data_loaded(self, data: dict): with self._ui_lock: - if data.get('segment_added'): - self._new_data = True - elif data.get('reset'): - self._all_paths_cache = set() + if data.get('segment_added') or data.get('reset'): self._new_data = True + def update_frame(self, font): + if self._handlers_to_delete: # we need to do everything in main thread, frame callbacks are flaky + dpg.render_dearpygui_frame() # wait a frame to ensure queued callbacks are done + with self._ui_lock: + for handler in self._handlers_to_delete: + dpg.delete_item(handler) + self._handlers_to_delete.clear() - def _populate_tree(self): - self._clear_ui() - self.data_tree = self._add_paths_to_tree(self._all_paths_cache, incremental=False) - if self.data_tree: - self._request_children_build(self.data_tree) + with self._ui_lock: + if self._avg_char_width is None and dpg.is_dearpygui_running(): + self._avg_char_width = self.calculate_avg_char_width(font) - def _add_paths_to_tree(self, paths, incremental=False): + if self._new_data: + self._process_path_change() + self._new_data = False + return + + if self._queued_search is not None: + self.current_search = self._queued_search + self._process_path_change() + self._queued_search = None + return + + nodes_processed = 0 + while self._build_queue and nodes_processed < self.MAX_NODES_PER_FRAME: + child_node, parent, before_tag = self._build_queue.pop(next(iter(self._build_queue))) + parent_tag = "data_tree_container" if parent.name == "root" else parent.ui_tag + if not child_node.ui_created: + if child_node.is_leaf: + self._create_leaf_ui(child_node, parent_tag, before_tag) + else: + self._create_tree_node_ui(child_node, parent_tag, before_tag) + parent.created_children[child_node.name] = parent.children[child_node.name] + self._current_created_paths.add(child_node.full_path) + nodes_processed += 1 + + def _process_path_change(self): + self._build_queue.clear() search_term = self.current_search.strip().lower() - filtered_paths = [path for path in paths if self._should_show_path(path, search_term)] - target_tree = self.data_tree if incremental else DataTreeNode(name="root") - - if not filtered_paths: - return target_tree - - parent_nodes_to_recheck = set() - for path in sorted(filtered_paths): + all_paths = set(self.data_manager.get_all_paths()) + new_filtered_leafs = {path for path in all_paths if self._should_show_path(path, search_term)} + new_filtered_paths = set(new_filtered_leafs) + for path in new_filtered_leafs: parts = path.split('/') - current_node = target_tree + for i in range(1, len(parts)): + prefix = '/'.join(parts[:i]) + new_filtered_paths.add(prefix) + created_paths_to_remove = self._current_created_paths - new_filtered_paths + filtered_paths_to_remove = self._current_filtered_paths - new_filtered_leafs + + if created_paths_to_remove or filtered_paths_to_remove: + self._remove_paths_from_tree(created_paths_to_remove, filtered_paths_to_remove) + self._apply_expansion_to_tree(self.data_tree, search_term) + + paths_to_add = new_filtered_leafs - self._current_created_paths + if paths_to_add: + self._add_paths_to_tree(paths_to_add) + self._apply_expansion_to_tree(self.data_tree, search_term) + self._current_filtered_paths = new_filtered_paths + + def _remove_paths_from_tree(self, created_paths_to_remove, filtered_paths_to_remove): + for path in sorted(created_paths_to_remove, reverse=True): + current_node = self._path_to_node[path] + + if len(current_node.created_children) == 0: + self._current_created_paths.remove(current_node.full_path) + if item_handler_tag := self._item_handlers.get(current_node.ui_tag): + dpg.configure_item(item_handler_tag, show=False) + self._handlers_to_delete.append(item_handler_tag) + del self._item_handlers[current_node.ui_tag] + dpg.delete_item(current_node.ui_tag) + current_node.ui_created = False + current_node.ui_tag = None + current_node.children_ui_created = False + del current_node.parent.created_children[current_node.name] + del current_node.parent.filtered_children[current_node.name] + + for path in filtered_paths_to_remove: + parts = path.split('/') + current_node = self._path_to_node[path] + + part_array_index = -1 + while len(current_node.filtered_children) == 0 and part_array_index >= -len(parts): + current_node = current_node.parent + if parts[part_array_index] in current_node.filtered_children: + del current_node.filtered_children[parts[part_array_index]] + part_array_index -= 1 + + def _add_paths_to_tree(self, paths): + parent_nodes_to_recheck = set() + for path in sorted(paths): + parts = path.split('/') + current_node = self.data_tree current_path_prefix = "" for i, part in enumerate(parts): @@ -81,101 +156,81 @@ class DataTree: parent_nodes_to_recheck.add(current_node) # for incremental changes from new data if part not in current_node.children: current_node.children[part] = DataTreeNode(name=part, full_path=current_path_prefix, parent=current_node) + self._path_to_node[current_path_prefix] = current_node.children[part] + current_node.filtered_children[part] = current_node.children[part] current_node = current_node.children[part] if not current_node.is_leaf: current_node.is_leaf = True - self._calculate_child_counts(target_tree) - if incremental: - for p_node in parent_nodes_to_recheck: - p_node.children_ui_created = False - self._request_children_build(p_node) - return target_tree + for p_node in parent_nodes_to_recheck: + p_node.children_ui_created = False + self._request_children_build(p_node) - def update_frame(self, font): - with self._ui_lock: - if self._avg_char_width is None and dpg.is_dearpygui_running(): - self._avg_char_width = self.calculate_avg_char_width(font) + def _get_node_label_and_expand(self, node: DataTreeNode, search_term: str): + label = f"{node.name} ({len(node.filtered_children)} fields)" + expand = len(search_term) > 0 and any(search_term in path for path in self._get_descendant_paths(node)) + if expand and node.parent and len(node.parent.filtered_children) > 100 and len(node.filtered_children) > 2: + label += " (+)" # symbol for large lists which aren't fully expanded for performance (only affects procLog rn) + expand = False + return label, expand - if self._new_data: - current_paths = set(self.data_manager.get_all_paths()) - new_paths = current_paths - self._all_paths_cache - all_paths_empty = not self._all_paths_cache - self._all_paths_cache = current_paths - if all_paths_empty: - self._populate_tree() - elif new_paths: - self._add_paths_to_tree(new_paths, incremental=True) - self._new_data = False - return + def _apply_expansion_to_tree(self, node: DataTreeNode, search_term: str): + if node.ui_created and not node.is_leaf and node.ui_tag and dpg.does_item_exist(node.ui_tag): + label, expand = self._get_node_label_and_expand(node, search_term) + if expand: + self._expanded_tags.add(node.ui_tag) + dpg.set_value(node.ui_tag, expand) + elif node.ui_tag in self._expanded_tags: # not expanded and was expanded + self._expanded_tags.remove(node.ui_tag) + dpg.set_value(node.ui_tag, expand) + dpg.delete_item(node.ui_tag, children_only=True) # delete children (not visible since collapsed) + self._reset_ui_state_recursive(node) + node.children_ui_created = False + dpg.set_item_label(node.ui_tag, label) + for child in node.created_children.values(): + self._apply_expansion_to_tree(child, search_term) - if self._queued_search is not None: - self.current_search = self._queued_search - self._all_paths_cache = set(self.data_manager.get_all_paths()) - self._populate_tree() - self._queued_search = None - return - - nodes_processed = 0 - while self._build_queue and nodes_processed < self.MAX_NODES_PER_FRAME: - child_node, parent_tag, before_tag = self._build_queue.popleft() - if not child_node.ui_created: - if child_node.is_leaf: - self._create_leaf_ui(child_node, parent_tag, before_tag) - else: - self._create_tree_node_ui(child_node, parent_tag, before_tag) - nodes_processed += 1 + def _reset_ui_state_recursive(self, node: DataTreeNode): + for child in node.created_children.values(): + if child.ui_tag is not None: + if item_handler_tag := self._item_handlers.get(child.ui_tag): + self._handlers_to_delete.append(item_handler_tag) + dpg.configure_item(item_handler_tag, show=False) + del self._item_handlers[child.ui_tag] + self._reset_ui_state_recursive(child) + child.ui_created = False + child.ui_tag = None + child.children_ui_created = False + self._current_created_paths.remove(child.full_path) + node.created_children.clear() def search_data(self): - self._queued_search = dpg.get_value("search_input") - - def _clear_ui(self): - for handler_tag in self._item_handlers: - dpg.configure_item(handler_tag, show=False) - dpg.set_frame_callback(dpg.get_frame_count() + 1, callback=self._delete_handlers, user_data=list(self._item_handlers)) - self._item_handlers.clear() - - if dpg.does_item_exist("data_tree_container"): - dpg.delete_item("data_tree_container", children_only=True) - - self._build_queue.clear() - - def _delete_handlers(self, sender, app_data, user_data): - for handler in user_data: - dpg.delete_item(handler) - - def _calculate_child_counts(self, node: DataTreeNode): - if node.is_leaf: - node.child_count = 0 - else: - node.child_count = len(node.children) - for child in node.children.values(): - self._calculate_child_counts(child) + with self._ui_lock: + self._queued_search = dpg.get_value("search_input") def _create_tree_node_ui(self, node: DataTreeNode, parent_tag: str, before: str | int): - tag = f"tree_{node.full_path}" - node.ui_tag = tag - label = f"{node.name} ({node.child_count} fields)" + node.ui_tag = f"tree_{node.full_path}" search_term = self.current_search.strip().lower() - expand = bool(search_term) and len(search_term) > 1 and any(search_term in path for path in self._get_descendant_paths(node)) - if expand and node.parent and node.parent.child_count > 100 and node.child_count > 2: # don't fully autoexpand large lists (only affects procLog rn) - label += " (+)" - expand = False + label, expand = self._get_node_label_and_expand(node, search_term) + if expand: + self._expanded_tags.add(node.ui_tag) + elif node.ui_tag in self._expanded_tags: + self._expanded_tags.remove(node.ui_tag) with dpg.tree_node( - label=label, parent=parent_tag, tag=tag, default_open=expand, open_on_arrow=True, open_on_double_click=True, before=before, delay_search=True + label=label, parent=parent_tag, tag=node.ui_tag, default_open=expand, open_on_arrow=True, open_on_double_click=True, before=before, delay_search=True ): with dpg.item_handler_registry() as handler_tag: dpg.add_item_toggled_open_handler(callback=lambda s, a, u: self._request_children_build(node)) dpg.add_item_visible_handler(callback=lambda s, a, u: self._request_children_build(node)) - dpg.bind_item_handler_registry(tag, handler_tag) - self._item_handlers.add(handler_tag) - + dpg.bind_item_handler_registry(node.ui_tag, handler_tag) + self._item_handlers[node.ui_tag] = handler_tag node.ui_created = True def _create_leaf_ui(self, node: DataTreeNode, parent_tag: str, before: str | int): - with dpg.group(parent=parent_tag, tag=f"leaf_{node.full_path}", before=before, delay_search=True) as draggable_group: + node.ui_tag = f"leaf_{node.full_path}" + with dpg.group(parent=parent_tag, tag=node.ui_tag, before=before, delay_search=True): with dpg.table(header_row=False, policy=dpg.mvTable_SizingStretchProp, delay_search=True): dpg.add_table_column(init_width_or_weight=0.5) dpg.add_table_column(init_width_or_weight=0.5) @@ -186,21 +241,21 @@ class DataTree: if node.is_plottable is None: node.is_plottable = self.data_manager.is_plottable(node.full_path) if node.is_plottable: - with dpg.drag_payload(parent=draggable_group, drag_data=node.full_path, payload_type="TIMESERIES_PAYLOAD"): + with dpg.drag_payload(parent=node.ui_tag, drag_data=node.full_path, payload_type="TIMESERIES_PAYLOAD"): dpg.add_text(f"Plot: {node.full_path}") with dpg.item_handler_registry() as handler_tag: dpg.add_item_visible_handler(callback=self._on_item_visible, user_data=node.full_path) - dpg.bind_item_handler_registry(draggable_group, handler_tag) - self._item_handlers.add(handler_tag) - + dpg.bind_item_handler_registry(node.ui_tag, handler_tag) + self._item_handlers[node.ui_tag] = handler_tag node.ui_created = True - node.ui_tag = f"value_{node.full_path}" def _on_item_visible(self, sender, app_data, user_data): with self._ui_lock: path = user_data value_tag = f"value_{path}" + if not dpg.does_item_exist(value_tag): + return value_column_width = dpg.get_item_rect_size("sidebar_window")[0] // 2 value = self.data_manager.get_value_at(path, self.playback_manager.current_time_s) if value is not None: @@ -212,8 +267,7 @@ class DataTree: def _request_children_build(self, node: DataTreeNode): with self._ui_lock: if not node.children_ui_created and (node.name == "root" or (node.ui_tag is not None and dpg.get_value(node.ui_tag))): # check root or node expanded - parent_tag = "data_tree_container" if node.name == "root" else node.ui_tag - sorted_children = sorted(node.children.values(), key=self._natural_sort_key) + sorted_children = sorted(node.filtered_children.values(), key=self._natural_sort_key) next_existing: list[int | str] = [0] * len(sorted_children) current_before_tag: int | str = 0 @@ -228,7 +282,7 @@ class DataTree: for i, child_node in enumerate(sorted_children): if not child_node.ui_created: before_tag = next_existing[i] - self._build_queue.append((child_node, parent_tag, before_tag)) + self._build_queue[child_node.full_path] = (child_node, node, before_tag) node.children_ui_created = True def _should_show_path(self, path: str, search_term: str) -> bool: @@ -242,7 +296,7 @@ class DataTree: return (node_type_key, parts) def _get_descendant_paths(self, node: DataTreeNode): - for child_name, child_node in node.children.items(): + for child_name, child_node in node.filtered_children.items(): child_name_lower = child_name.lower() if child_node.is_leaf: yield child_name_lower From 70c0592e84a2cc5a8795b0d09d60eec46329c490 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Thu, 11 Sep 2025 11:03:59 -0700 Subject: [PATCH 070/159] CI: re-enable macOS build (#36120) * CI: re-enable macOS build * Update selfdrive_tests.yaml with new env variable --- .github/workflows/selfdrive_tests.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/selfdrive_tests.yaml b/.github/workflows/selfdrive_tests.yaml index cdafbbfede..beb426c669 100644 --- a/.github/workflows/selfdrive_tests.yaml +++ b/.github/workflows/selfdrive_tests.yaml @@ -91,7 +91,6 @@ jobs: build_mac: name: build macOS - if: false # temp disable since homebrew install is getting stuck runs-on: ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-macos-8x14' || 'macos-latest' }} steps: - uses: actions/checkout@v4 @@ -109,8 +108,8 @@ jobs: - name: Install dependencies run: ./tools/mac_setup.sh env: - # package install has DeprecationWarnings - PYTHONWARNINGS: default + PYTHONWARNINGS: default # package install has DeprecationWarnings + HOMEBREW_DISPLAY_INSTALL_TIMES: 1 - run: git lfs pull - name: Getting scons cache uses: ./.github/workflows/auto-cache From b7f8dd11a559f9cf7a427990e6d158d96a10a707 Mon Sep 17 00:00:00 2001 From: DevTekVE Date: Thu, 11 Sep 2025 21:44:43 +0200 Subject: [PATCH 071/159] SL: bugfix parameter handling in sunnylink restore and remote setting (#1234) * refactor: improve parameter handling in sunnylink for robustness - Updated `get_param_as_byte` to return `None` for nonexistent parameters. - Enhanced param compression and encoding in `sunnylinkd`. * refactor: centralize parameter restoration with new helper function - Added `save_param_from_base64_encoded_string` to handle param decoding and saving. - Updated backup manager and sunnylinkd to use the new method. - Improved code readability and reduced duplication in parameter handling logic. * don't bother * clean --- sunnypilot/sunnylink/athena/sunnylinkd.py | 26 +++++++--------- sunnypilot/sunnylink/backups/manager.py | 29 +++-------------- sunnypilot/sunnylink/utils.py | 38 +++++++++++++++++++++-- 3 files changed, 53 insertions(+), 40 deletions(-) diff --git a/sunnypilot/sunnylink/athena/sunnylinkd.py b/sunnypilot/sunnylink/athena/sunnylinkd.py index 363fa1defc..25a77c367b 100755 --- a/sunnypilot/sunnylink/athena/sunnylinkd.py +++ b/sunnypilot/sunnylink/athena/sunnylinkd.py @@ -23,7 +23,7 @@ from websocket import (ABNF, WebSocket, WebSocketException, WebSocketTimeoutExce import cereal.messaging as messaging from sunnypilot.sunnylink.api import SunnylinkApi -from sunnypilot.sunnylink.utils import sunnylink_need_register, sunnylink_ready, get_param_as_byte +from sunnypilot.sunnylink.utils import sunnylink_need_register, sunnylink_ready, get_param_as_byte, save_param_from_base64_encoded_string SUNNYLINK_ATHENA_HOST = os.getenv('SUNNYLINK_ATHENA_HOST', 'wss://ws.stg.api.sunnypilot.ai') HANDLER_THREADS = int(os.getenv('HANDLER_THREADS', "4")) @@ -184,14 +184,18 @@ def getParams(params_keys: list[str], compression: bool = False) -> str | dict[s try: param_keys_validated = [key for key in params_keys if key in getParamsAllKeys()] - params_dict: dict[str, list[dict[str, str | bool | int ]]] = {"params": [ - { + params_dict: dict[str, list[dict[str, str | bool | int]]] = {"params": []} + for key in param_keys_validated: + value = get_param_as_byte(key) + if value is None: + continue + + params_dict["params"].append({ "key": key, - "value": base64.b64encode(gzip.compress(get_param_as_byte(key)) if compression else get_param_as_byte(key)).decode('utf-8'), + "value": base64.b64encode(gzip.compress(value) if compression else value).decode('utf-8'), "type": int(params.get_type(key).value), "is_compressed": compression - } for key in param_keys_validated - ]} + }) response = {str(param.get('key')): str(param.get('value')) for param in params_dict.get("params", [])} response |= {"params": json.dumps(params_dict.get("params", []))} # Upcoming for settings v1 @@ -204,15 +208,9 @@ def getParams(params_keys: list[str], compression: bool = False) -> str | dict[s @dispatcher.add_method def saveParams(params_to_update: dict[str, str], compression: bool = False) -> None: - params = Params() - params_dict = {key: base64.b64decode(value) for key, value in params_to_update.items()} - - if compression: - params_dict = {key: gzip.decompress(value) for key, value in params_dict.items()} - - for key, value in params_dict.items(): + for key, value in params_to_update.items(): try: - params.put(key, value) + save_param_from_base64_encoded_string(key, value, compression) except Exception as e: cloudlog.error(f"sunnylinkd.saveParams.exception {e}") diff --git a/sunnypilot/sunnylink/backups/manager.py b/sunnypilot/sunnylink/backups/manager.py index 315300c73c..e52b547afe 100644 --- a/sunnypilot/sunnylink/backups/manager.py +++ b/sunnypilot/sunnylink/backups/manager.py @@ -12,7 +12,7 @@ from enum import Enum from typing import Any from openpilot.common.git import get_branch -from openpilot.common.params import Params, ParamKeyType, ParamKeyFlag +from openpilot.common.params import Params, ParamKeyFlag from openpilot.common.realtime import Ratekeeper from openpilot.common.swaglog import cloudlog from openpilot.system.version import get_version @@ -20,7 +20,7 @@ from openpilot.system.version import get_version from cereal import messaging, custom from sunnypilot.sunnylink.api import SunnylinkApi from sunnypilot.sunnylink.backups.utils import decrypt_compressed_data, encrypt_compress_data, SnakeCaseEncoder -from sunnypilot.sunnylink.utils import get_param_as_byte +from sunnypilot.sunnylink.utils import get_param_as_byte, save_param_from_base64_encoded_string class OperationType(Enum): @@ -173,8 +173,7 @@ class BackupManagerSP: self._update_progress(75.0, OperationType.RESTORE) # Apply configuration - all_values_encoded = self._get_metadata_value(backup_metadata, "all_values_encoded", "false") - self._apply_config(config_data, str(all_values_encoded).lower() == "true") + self._apply_config(config_data) self.restore_status = custom.BackupManagerSP.Status.completed self._update_progress(100.0, OperationType.RESTORE) @@ -187,7 +186,7 @@ class BackupManagerSP: self._report_status() return False - def _apply_config(self, config_data: dict[str, str], all_values_encoded: bool = False) -> None: + def _apply_config(self, config_data: dict[str, str]) -> None: """Applies configuration data from a backup, but only for parameters marked as backupable.""" backupable_params = [k.decode('utf-8') for k in self.params.all_keys(ParamKeyFlag.BACKUP)] backupable_set_lower = {p.lower() for p in backupable_params} @@ -199,26 +198,8 @@ class BackupManagerSP: if param.lower() in backupable_set_lower: # Find real param name (with correct casing) real_param = next(p for p in backupable_params if p.lower() == param.lower()) - param_type = self.params.get_type(real_param) try: - value = base64.b64decode(encoded_value) if all_values_encoded else encoded_value - - if param_type != ParamKeyType.BYTES: - value = value.decode('utf-8') # type: ignore - - if param_type == ParamKeyType.STRING: - value = value - elif param_type == ParamKeyType.BOOL: - value = value.lower() in ('true', '1', 'yes') # type: ignore - elif param_type == ParamKeyType.INT: - value = int(value) # type: ignore - elif param_type == ParamKeyType.FLOAT: - value = float(value) # type: ignore - elif param_type == ParamKeyType.TIME: - value = str(value) - elif param_type == ParamKeyType.JSON: - value = json.loads(value) - self.params.put(real_param, value) + save_param_from_base64_encoded_string(real_param, encoded_value) restored_count += 1 except Exception as e: cloudlog.error(f"Failed to restore param {param}: {str(e)}") diff --git a/sunnypilot/sunnylink/utils.py b/sunnypilot/sunnylink/utils.py index 569afd26b6..1310b91f0e 100644 --- a/sunnypilot/sunnylink/utils.py +++ b/sunnypilot/sunnylink/utils.py @@ -1,3 +1,5 @@ +import base64 +import gzip import json from sunnypilot.sunnylink.api import SunnylinkApi, UNREGISTERED_SUNNYLINK_DONGLE_ID from openpilot.common.params import Params, ParamKeyType @@ -58,13 +60,45 @@ def get_api_token(): print(f"API Token: {token}") -def get_param_as_byte(param_name: str) -> bytes: +def get_param_as_byte(param_name: str) -> bytes | None: + """Get a parameter as bytes. Returns None if the parameter does not exist.""" params = Params() param = params.get(param_name) - param_type = params.get_type(param_name) + if param is None: + return None + param_type = params.get_type(param_name) if param_type == ParamKeyType.BYTES: return bytes(param) elif param_type == ParamKeyType.JSON: return json.dumps(param).encode('utf-8') return str(param).encode('utf-8') + + +def save_param_from_base64_encoded_string(param_name: str, base64_encoded_data: str, is_compressed=False) -> None: + """Save a parameter from bytes. Overwrites the parameter if it already exists.""" + params = Params() + # Find real param name (with correct casing) + param_type = params.get_type(param_name) + value = base64.b64decode(base64_encoded_data) + + if is_compressed: + value = gzip.decompress(value) + + # We convert to string anything that isn't bytes first. We later transform further. + if param_type != ParamKeyType.BYTES: + value = value.decode('utf-8') # type: ignore + + if param_type == ParamKeyType.STRING: + value = value + elif param_type == ParamKeyType.BOOL: + value = value.lower() in ('true', '1', 'yes') # type: ignore + elif param_type == ParamKeyType.INT: + value = int(value) # type: ignore + elif param_type == ParamKeyType.FLOAT: + value = float(value) # type: ignore + elif param_type == ParamKeyType.TIME: + value = str(value) # type: ignore + elif param_type == ParamKeyType.JSON: + value = json.loads(value) + params.put(param_name, value) From 2c04a27a2a0c3d3bdf9dfc6079d724651e369b49 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Thu, 11 Sep 2025 14:03:37 -0700 Subject: [PATCH 072/159] ubloxd: cleanup unused files --- system/ubloxd/glonass_fix.patch | 13 ----- system/ubloxd/tests/ubloxd.py | 89 --------------------------------- 2 files changed, 102 deletions(-) delete mode 100644 system/ubloxd/glonass_fix.patch delete mode 100755 system/ubloxd/tests/ubloxd.py diff --git a/system/ubloxd/glonass_fix.patch b/system/ubloxd/glonass_fix.patch deleted file mode 100644 index 7eb973a348..0000000000 --- a/system/ubloxd/glonass_fix.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/system/ubloxd/generated/glonass.cpp b/system/ubloxd/generated/glonass.cpp -index 5b17bc327..b5c6aa610 100644 ---- a/system/ubloxd/generated/glonass.cpp -+++ b/system/ubloxd/generated/glonass.cpp -@@ -17,7 +17,7 @@ glonass_t::glonass_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, glonass - void glonass_t::_read() { - m_idle_chip = m__io->read_bits_int_be(1); - m_string_number = m__io->read_bits_int_be(4); -- m__io->align_to_byte(); -+ //m__io->align_to_byte(); - switch (string_number()) { - case 4: { - m_data = new string_4_t(m__io, this, m__root); diff --git a/system/ubloxd/tests/ubloxd.py b/system/ubloxd/tests/ubloxd.py deleted file mode 100755 index c17387114f..0000000000 --- a/system/ubloxd/tests/ubloxd.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env python3 -# type: ignore - -from openpilot.selfdrive.locationd.test import ublox -import struct - -baudrate = 460800 -rate = 100 # send new data every 100ms - - -def configure_ublox(dev): - # configure ports and solution parameters and rate - dev.configure_port(port=ublox.PORT_USB, inMask=1, outMask=1) # enable only UBX on USB - dev.configure_port(port=0, inMask=0, outMask=0) # disable DDC - - payload = struct.pack(' Date: Fri, 12 Sep 2025 01:00:05 -0400 Subject: [PATCH 073/159] UI: Developer UI (#1233) --- common/params_keys.h | 1 + selfdrive/ui/qt/onroad/alerts.cc | 9 + selfdrive/ui/qt/onroad/annotated_camera.h | 1 + selfdrive/ui/qt/onroad/driver_monitoring.cc | 5 + selfdrive/ui/sunnypilot/SConscript | 1 + .../qt/offroad/settings/visuals_panel.cc | 12 + .../qt/offroad/settings/visuals_panel.h | 1 + .../sunnypilot/qt/onroad/annotated_camera.cc | 5 + .../sunnypilot/qt/onroad/annotated_camera.h | 3 + .../qt/onroad/developer_ui/developer_ui.cc | 227 ++++++++++++++++++ .../qt/onroad/developer_ui/developer_ui.h | 31 +++ .../qt/onroad/developer_ui/ui_elements.h | 19 ++ selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 190 +++++++++++++++ selfdrive/ui/sunnypilot/qt/onroad/hud.h | 39 ++- selfdrive/ui/sunnypilot/ui.cc | 16 +- selfdrive/ui/sunnypilot/ui.h | 4 + selfdrive/ui/sunnypilot/ui_scene.h | 12 + selfdrive/ui/ui.h | 5 + 18 files changed, 578 insertions(+), 3 deletions(-) create mode 100644 selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.cc create mode 100644 selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h create mode 100644 selfdrive/ui/sunnypilot/qt/onroad/developer_ui/ui_elements.h create mode 100644 selfdrive/ui/sunnypilot/ui_scene.h diff --git a/common/params_keys.h b/common/params_keys.h index afb6b348eb..fc7842720b 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -146,6 +146,7 @@ inline static std::unordered_map keys = { {"CustomAccLongPressIncrement", {PERSISTENT | BACKUP, INT, "5"}}, {"CustomAccShortPressIncrement", {PERSISTENT | BACKUP, INT, "1"}}, {"DeviceBootMode", {PERSISTENT | BACKUP, INT, "0"}}, + {"DevUIInfo", {PERSISTENT | BACKUP, INT, "0"}}, {"EnableCopyparty", {PERSISTENT | BACKUP, BOOL}}, {"EnableGithubRunner", {PERSISTENT | BACKUP, BOOL}}, {"GithubRunnerSufficientVoltage", {CLEAR_ON_MANAGER_START , BOOL}}, diff --git a/selfdrive/ui/qt/onroad/alerts.cc b/selfdrive/ui/qt/onroad/alerts.cc index d6829c6b08..2e8f3612eb 100644 --- a/selfdrive/ui/qt/onroad/alerts.cc +++ b/selfdrive/ui/qt/onroad/alerts.cc @@ -4,6 +4,9 @@ #include #include "selfdrive/ui/qt/util.h" +#ifdef SUNNYPILOT +#include "selfdrive/ui/sunnypilot/ui.h" +#endif void OnroadAlerts::updateState(const UIState &s) { Alert a = getAlert(*(s.sm), s.scene.started_frame); @@ -73,6 +76,12 @@ void OnroadAlerts::paintEvent(QPaintEvent *event) { } QRect r = QRect(0 + margin, height() - h + margin, width() - margin*2, h - margin*2); +#ifdef SUNNYPILOT + const int dev_ui_info = uiStateSP()->scene.dev_ui_info; + const int adjustment = dev_ui_info > 1 && alert.size != cereal::SelfdriveState::AlertSize::FULL ? 30 : 0; + r = QRect(0 + margin, height() - h + margin - adjustment, width() - margin*2, h - margin*2); +#endif + QPainter p(this); // draw background + gradient diff --git a/selfdrive/ui/qt/onroad/annotated_camera.h b/selfdrive/ui/qt/onroad/annotated_camera.h index e3ca837907..5d9d21ab6b 100644 --- a/selfdrive/ui/qt/onroad/annotated_camera.h +++ b/selfdrive/ui/qt/onroad/annotated_camera.h @@ -12,6 +12,7 @@ #include "selfdrive/ui/sunnypilot/qt/onroad/model.h" #define ExperimentalButton ExperimentalButtonSP #define ModelRenderer ModelRendererSP +#define HudRenderer HudRendererSP #else #include "selfdrive/ui/qt/onroad/buttons.h" #include "selfdrive/ui/qt/onroad/hud.h" diff --git a/selfdrive/ui/qt/onroad/driver_monitoring.cc b/selfdrive/ui/qt/onroad/driver_monitoring.cc index 49f2c950b4..e67c483047 100644 --- a/selfdrive/ui/qt/onroad/driver_monitoring.cc +++ b/selfdrive/ui/qt/onroad/driver_monitoring.cc @@ -73,6 +73,11 @@ void DriverMonitorRenderer::draw(QPainter &painter, const QRect &surface_rect) { float y = surface_rect.height() - offset; float opacity = is_active ? 0.65f : 0.2f; +#ifdef SUNNYPILOT + const int dev_ui_info = uiStateSP()->scene.dev_ui_info; + y -= dev_ui_info > 1 ? 50 : 0; +#endif + drawIcon(painter, QPoint(x, y), dm_img, QColor(0, 0, 0, 70), opacity); QPointF keypoints[std::size(DEFAULT_FACE_KPTS_3D)]; diff --git a/selfdrive/ui/sunnypilot/SConscript b/selfdrive/ui/sunnypilot/SConscript index 2f3c8ddd8d..807bf02478 100644 --- a/selfdrive/ui/sunnypilot/SConscript +++ b/selfdrive/ui/sunnypilot/SConscript @@ -39,6 +39,7 @@ qt_src = [ "sunnypilot/qt/offroad/settings/visuals_panel.cc", "sunnypilot/qt/onroad/annotated_camera.cc", "sunnypilot/qt/onroad/buttons.cc", + "sunnypilot/qt/onroad/developer_ui/developer_ui.cc", "sunnypilot/qt/onroad/hud.cc", "sunnypilot/qt/onroad/model.cc", "sunnypilot/qt/onroad/onroad_home.cc", diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc index dd2f05416d..c3aaf12d22 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc @@ -72,6 +72,15 @@ VisualsPanel::VisualsPanel(QWidget *parent) : QWidget(parent) { list->addItem(chevron_info_settings); param_watcher->addParam("ChevronInfo"); + // Visuals: Developer UI Info (Dev UI) + std::vector dev_ui_settings_texts{tr("Off"), tr("Right"), tr("Right &&\nBottom")}; + dev_ui_settings = new ButtonParamControlSP( + "DevUIInfo", tr("Developer UI"), tr("Display real-time parameters and metrics from various sources."), + "", + dev_ui_settings_texts, + 380); + list->addItem(dev_ui_settings); + sunnypilotScroller = new ScrollViewSP(list, this); vlayout->addWidget(sunnypilotScroller); @@ -90,4 +99,7 @@ void VisualsPanel::paramsRefresh() { if (chevron_info_settings) { chevron_info_settings->refresh(); } + if (dev_ui_settings) { + dev_ui_settings->refresh(); + } } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.h index f342662c22..30ff31c301 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.h @@ -28,4 +28,5 @@ protected: std::map toggles; ParamWatcher * param_watcher; ButtonParamControlSP *chevron_info_settings; + ButtonParamControlSP *dev_ui_settings; }; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.cc b/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.cc index 3721a3d198..1d5567161a 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.cc @@ -14,3 +14,8 @@ AnnotatedCameraWidgetSP::AnnotatedCameraWidgetSP(VisionStreamType type, QWidget void AnnotatedCameraWidgetSP::updateState(const UIState &s) { AnnotatedCameraWidget::updateState(s); } + +void AnnotatedCameraWidgetSP::showEvent(QShowEvent *event) { + AnnotatedCameraWidget::showEvent(event); + ui_update_params_sp(uiState()); +} diff --git a/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.h b/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.h index 46ce7d4be3..8c0a385657 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.h +++ b/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.h @@ -15,4 +15,7 @@ class AnnotatedCameraWidgetSP : public AnnotatedCameraWidget { public: explicit AnnotatedCameraWidgetSP(VisionStreamType type, QWidget *parent = nullptr); void updateState(const UIState &s) override; + +protected: + void showEvent(QShowEvent *event) override; }; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.cc b/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.cc new file mode 100644 index 0000000000..292ba6f7bb --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.cc @@ -0,0 +1,227 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ +#include + +#include "common/util.h" +#include "selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h" + + +// Add Relative Distance to Primary Lead Car +// Unit: Meters +UiElement DeveloperUi::getDRel(bool lead_status, float lead_d_rel) { + QString value = lead_status ? QString::number(lead_d_rel, 'f', 0) : "-"; + QColor color = QColor(255, 255, 255, 255); + + if (lead_status) { + // Orange if close, Red if very close + if (lead_d_rel < 5) { + color = QColor(255, 0, 0, 255); + } else if (lead_d_rel < 15) { + color = QColor(255, 188, 0, 255); + } + } + + return UiElement(value, "REL DIST", "m", color); +} + +// Add Relative Velocity vs Primary Lead Car +// Unit: kph if metric, else mph +UiElement DeveloperUi::getVRel(bool lead_status, float lead_v_rel, bool is_metric, const QString &speed_unit) { + QString value = lead_status ? QString::number(lead_v_rel * (is_metric ? MS_TO_KPH : MS_TO_MPH), 'f', 0) : "-"; + QColor color = QColor(255, 255, 255, 255); + + if (lead_status) { + // Red if approaching faster than 10mph + // Orange if approaching (negative) + if (lead_v_rel < -4.4704) { + color = QColor(255, 0, 0, 255); + } else if (lead_v_rel < 0) { + color = QColor(255, 188, 0, 255); + } + } + + return UiElement(value, "REL SPEED", speed_unit, color); +} + +// Add Real Steering Angle +// Unit: Degrees +UiElement DeveloperUi::getSteeringAngleDeg(float angle_steers, bool lat_active, bool steer_override) { + QString value = QString("%1%2%3").arg(QString::number(angle_steers, 'f', 1)).arg("°").arg(""); + QColor color = lat_active ? (steer_override ? QColor(0x91, 0x9b, 0x95, 0xff) : QColor(0, 255, 0, 255)) : QColor(255, 255, 255, 255); + + // Red if large steering angle + // Orange if moderate steering angle + if (std::fabs(angle_steers) > 180) { + color = QColor(255, 0, 0, 255); + } else if (std::fabs(angle_steers) > 90) { + color = QColor(255, 188, 0, 255); + } + + return UiElement(value, "REAL STEER", "", color); +} + +// Add Actual Lateral Acceleration (roll compensated) when using Torque +// Unit: m/s² +UiElement DeveloperUi::getActualLateralAccel(float curvature, float v_ego, float roll, bool lat_active, bool steer_override) { + double actualLateralAccel = (curvature * pow(v_ego, 2)) - (roll * 9.81); + + QString value = QString::number(actualLateralAccel, 'f', 2); + QColor color = lat_active ? (steer_override ? QColor(0x91, 0x9b, 0x95, 0xff) : QColor(0, 255, 0, 255)) : QColor(255, 255, 255, 255); + + return UiElement(value, "ACTUAL L.A.", "m/s²", color); +} + +// Add Desired Steering Angle when using PID +// Unit: Degrees +UiElement DeveloperUi::getSteeringAngleDesiredDeg(bool lat_active, float steer_angle_desired, float angle_steers) { + QString value = lat_active ? QString("%1%2%3").arg(QString::number(steer_angle_desired, 'f', 1)).arg("°").arg("") : "-"; + QColor color = QColor(255, 255, 255, 255); + + if (lat_active) { + // Red if large steering angle + // Orange if moderate steering angle + if (std::fabs(angle_steers) > 180) { + color = QColor(255, 0, 0, 255); + } else if (std::fabs(angle_steers) > 90) { + color = QColor(255, 188, 0, 255); + } else { + color = QColor(0, 255, 0, 255); + } + } + + return UiElement(value, "DESIRED STEER", "", color); +} + +// Add Device Memory (RAM) Usage +// Unit: Percent +UiElement DeveloperUi::getMemoryUsagePercent(int memory_usage_percent) { + QString value = QString("%1%2").arg(QString::number(memory_usage_percent, 'd', 0)).arg("%"); + QColor color = (memory_usage_percent > 85) ? QColor(255, 188, 0, 255) : QColor(255, 255, 255, 255); + + return UiElement(value, "RAM", "", color); +} + +// Add Vehicle Current Acceleration +// Unit: m/s² +UiElement DeveloperUi::getAEgo(float a_ego) { + QString value = QString::number(a_ego, 'f', 1); + QColor color = QColor(255, 255, 255, 255); + + return UiElement(value, "ACC.", "m/s²", color); +} + +// Add Relative Velocity to Primary Lead Car +// Unit: kph if metric, else mph +UiElement DeveloperUi::getVEgoLead(bool lead_status, float lead_v_rel, float v_ego, bool is_metric, const QString &speed_unit) { + QString value = lead_status ? QString::number((lead_v_rel + v_ego) * (is_metric ? MS_TO_KPH : MS_TO_MPH), 'f', 0) : "-"; + QColor color = QColor(255, 255, 255, 255); + + if (lead_status) { + // Red if approaching faster than 10mph + // Orange if approaching (negative) + if (lead_v_rel < -4.4704) { + color = QColor(255, 0, 0, 255); + } else if (lead_v_rel < 0) { + color = QColor(255, 188, 0, 255); + } + } + + return UiElement(value, "L.S.", speed_unit, color); +} + +// Add Friction Coefficient Raw from torqued +// Unit: None +UiElement DeveloperUi::getFrictionCoefficientFiltered(float friction_coefficient_filtered, bool live_valid) { + QString value = QString::number(friction_coefficient_filtered, 'f', 3); + QColor color = live_valid ? QColor(0, 255, 0, 255) : QColor(255, 255, 255, 255); + + return UiElement(value, "FRIC.", "", color); +} + +// Add Lateral Acceleration Factor Raw from torqued +// Unit: m/s² +UiElement DeveloperUi::getLatAccelFactorFiltered(float lat_accel_factor_filtered, bool live_valid) { + QString value = QString::number(lat_accel_factor_filtered, 'f', 3); + QColor color = live_valid ? QColor(0, 255, 0, 255) : QColor(255, 255, 255, 255); + + return UiElement(value, "L.A.", "m/s²", color); +} + +// Add Steering Torque from Car EPS +// Unit: Newton Meters +UiElement DeveloperUi::getSteeringTorqueEps(float steering_torque_eps) { + QString value = QString::number(std::fabs(steering_torque_eps), 'f', 1); + QColor color = QColor(255, 255, 255, 255); + + return UiElement(value, "E.T.", "N·dm", color); +} + +// Add Bearing Degree and Direction from Car (Compass) +// Unit: Meters +UiElement DeveloperUi::getBearingDeg(float bearing_accuracy_deg, float bearing_deg) { + QString value = (bearing_accuracy_deg != 180.00) ? QString("%1%2%3").arg(QString::number(bearing_deg, 'd', 0)).arg("°").arg("") : "-"; + QColor color = QColor(255, 255, 255, 255); + QString dir_value; + + if (bearing_accuracy_deg != 180.00) { + if (((bearing_deg >= 337.5) && (bearing_deg <= 360)) || ((bearing_deg >= 0) && (bearing_deg <= 22.5))) { + dir_value = "N"; + } else if ((bearing_deg > 22.5) && (bearing_deg < 67.5)) { + dir_value = "NE"; + } else if ((bearing_deg >= 67.5) && (bearing_deg <= 112.5)) { + dir_value = "E"; + } else if ((bearing_deg > 112.5) && (bearing_deg < 157.5)) { + dir_value = "SE"; + } else if ((bearing_deg >= 157.5) && (bearing_deg <= 202.5)) { + dir_value = "S"; + } else if ((bearing_deg > 202.5) && (bearing_deg < 247.5)) { + dir_value = "SW"; + } else if ((bearing_deg >= 247.5) && (bearing_deg <= 292.5)) { + dir_value = "W"; + } else if ((bearing_deg > 292.5) && (bearing_deg < 337.5)) { + dir_value = "NW"; + } + } else { + dir_value = "OFF"; + } + + return UiElement(QString("%1 | %2").arg(dir_value).arg(value), "B.D.", "", color); +} + +// Add Altitude of Current Location +// Unit: Meters +UiElement DeveloperUi::getAltitude(float gps_accuracy, float altitude) { + QString value = (gps_accuracy != 0.00) ? QString::number(altitude, 'f', 1) : "-"; + QColor color = QColor(255, 255, 255, 255); + + return UiElement(value, "ALT.", "m", color); +} + +// Add Actuators Output +// Unit: Degree (angle) or m/s² (torque) +UiElement DeveloperUi::getActuatorsOutputLateral(cereal::CarParams::SteerControlType steerControlType, + cereal::CarControl::Actuators::Reader &actuators, + float desiredCurvature, float v_ego, float roll, bool lat_active, bool steer_override) { + QString label; + QString value; + QString unit; + + if (steerControlType == cereal::CarParams::SteerControlType::ANGLE) { + label = "DESIRED STEER"; + value = QString("%1%2%3").arg(QString::number(actuators.getSteeringAngleDeg(), 'f', 1)).arg("°").arg(""); + } else { + label = "DESIRED L.A."; + double desiredLateralAccel = (desiredCurvature * pow(v_ego, 2)) - (roll * 9.81); + value = QString::number(desiredLateralAccel, 'f', 2); + unit = "m/s²"; + } + + value = lat_active ? value : "-"; + QColor color = lat_active ? (steer_override ? QColor(0x91, 0x9b, 0x95, 0xff) : QColor(0, 255, 0, 255)) : QColor(255, 255, 255, 255); + + return UiElement(value, label, unit, color); +} diff --git a/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h b/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h new file mode 100644 index 0000000000..0c5c472209 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ +#pragma once + +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/sunnypilot/qt/onroad/developer_ui/ui_elements.h" + +class DeveloperUi { + +public: + static UiElement getDRel(bool lead_status, float lead_d_rel); + static UiElement getVRel(bool lead_status, float lead_v_rel, bool is_metric, const QString &speed_unit); + static UiElement getSteeringAngleDeg(float angle_steers, bool lat_active, bool steer_override); + static UiElement getActualLateralAccel(float curvature, float v_ego, float roll, bool lat_active, bool steer_override); + static UiElement getSteeringAngleDesiredDeg(bool lat_active, float steer_angle_desired, float angle_steers); + static UiElement getMemoryUsagePercent(int memory_usage_percent); + static UiElement getAEgo(float a_ego); + static UiElement getVEgoLead(bool lead_status, float lead_v_rel, float v_ego, bool is_metric, const QString &speed_unit); + static UiElement getFrictionCoefficientFiltered(float friction_coefficient_filtered, bool live_valid); + static UiElement getLatAccelFactorFiltered(float lat_accel_factor_filtered, bool live_valid); + static UiElement getSteeringTorqueEps(float steering_torque_eps); + static UiElement getBearingDeg(float bearing_accuracy_deg, float bearing_deg); + static UiElement getAltitude(float gps_accuracy, float altitude); + static UiElement getActuatorsOutputLateral(cereal::CarParams::SteerControlType steerControlType, + cereal::CarControl::Actuators::Reader &actuators, + float desiredCurvature, float v_ego, float roll, bool lat_active, bool steer_override); +}; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/ui_elements.h b/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/ui_elements.h new file mode 100644 index 0000000000..3711e5ac05 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/ui_elements.h @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ +#pragma once + +#include + +struct UiElement { + QString value{}; + QString label{}; + QString units{}; + QColor color{}; + + explicit UiElement(const QString &value = "", const QString &label = "", const QString &units = "", const QColor &color = QColor(255, 255, 255, 255)) + : value(value), label(label), units(units), color(color) {} +}; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index 233ca59f98..15722cc9f8 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -7,12 +7,202 @@ #include "selfdrive/ui/sunnypilot/qt/onroad/hud.h" +#include "selfdrive/ui/qt/util.h" + + HudRendererSP::HudRendererSP() {} void HudRendererSP::updateState(const UIState &s) { HudRenderer::updateState(s); + + const SubMaster &sm = *(s.sm); + const bool cs_alive = sm.alive("controlsState"); + const auto cs = sm["controlsState"].getControlsState(); + const auto car_state = sm["carState"].getCarState(); + const auto car_control = sm["carControl"].getCarControl(); + const auto radar_state = sm["radarState"].getRadarState(); + const auto is_gps_location_external = sm.rcv_frame("gpsLocationExternal") > 1; + const auto gpsLocation = is_gps_location_external ? sm["gpsLocationExternal"].getGpsLocationExternal() : sm["gpsLocation"].getGpsLocation(); + const auto ltp = sm["liveTorqueParameters"].getLiveTorqueParameters(); + const auto car_params = sm["carParams"].getCarParams(); + + static int reverse_delay = 0; + bool reverse_allowed = false; + if (int(car_state.getGearShifter()) != 4) { + reverse_delay = 0; + reverse_allowed = false; + } else { + reverse_delay += 50; + if (reverse_delay >= 1000) { + reverse_allowed = true; + } + } + + reversing = reverse_allowed; + is_metric = s.scene.is_metric; + + // Handle older routes where vEgoCluster is not set + v_ego_cluster_seen = v_ego_cluster_seen || car_state.getVEgoCluster() != 0.0; + float v_ego = v_ego_cluster_seen ? car_state.getVEgoCluster() : car_state.getVEgo(); + speed = cs_alive ? std::max(0.0, v_ego) : 0.0; + speed *= is_metric ? MS_TO_KPH : MS_TO_MPH; + + latActive = car_control.getLatActive(); + steerOverride = car_state.getSteeringPressed(); + + devUiInfo = s.scene.dev_ui_info; + + speedUnit = is_metric ? tr("km/h") : tr("mph"); + lead_d_rel = radar_state.getLeadOne().getDRel(); + lead_v_rel = radar_state.getLeadOne().getVRel(); + lead_status = radar_state.getLeadOne().getStatus(); + steerControlType = car_params.getSteerControlType(); + actuators = car_control.getActuators(); + torqueLateral = steerControlType == cereal::CarParams::SteerControlType::TORQUE; + angleSteers = car_state.getSteeringAngleDeg(); + desiredCurvature = cs.getDesiredCurvature(); + curvature = cs.getCurvature(); + roll = sm["liveParameters"].getLiveParameters().getRoll(); + memoryUsagePercent = sm["deviceState"].getDeviceState().getMemoryUsagePercent(); + gpsAccuracy = is_gps_location_external ? gpsLocation.getHorizontalAccuracy() : 1.0; // External reports accuracy, internal does not. + altitude = gpsLocation.getAltitude(); + vEgo = car_state.getVEgo(); + aEgo = car_state.getAEgo(); + steeringTorqueEps = car_state.getSteeringTorqueEps(); + bearingAccuracyDeg = gpsLocation.getBearingAccuracyDeg(); + bearingDeg = gpsLocation.getBearingDeg(); + torquedUseParams = ltp.getUseParams(); + latAccelFactorFiltered = ltp.getLatAccelFactorFiltered(); + frictionCoefficientFiltered = ltp.getFrictionCoefficientFiltered(); + liveValid = ltp.getLiveValid(); } void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { HudRenderer::draw(p, surface_rect); + if (!reversing) { + // Bottom Dev UI + if (devUiInfo == 2) { + QRect rect_bottom(surface_rect.left(), surface_rect.bottom() - 60, surface_rect.width(), 61); + p.setPen(Qt::NoPen); + p.setBrush(QColor(0, 0, 0, 100)); + p.drawRect(rect_bottom); + drawBottomDevUI(p, rect_bottom.left(), rect_bottom.center().y()); + } + + // Right Dev UI + if (devUiInfo != 0) { + QRect rect_right(surface_rect.right() - (UI_BORDER_SIZE * 2), UI_BORDER_SIZE * 1.5, 184, 170); + drawRightDevUI(p, surface_rect.right() - 184 - UI_BORDER_SIZE * 2, UI_BORDER_SIZE * 2 + rect_right.height()); + } + } +} + +void HudRendererSP::drawText(QPainter &p, int x, int y, const QString &text, QColor color) { + QRect real_rect = p.fontMetrics().boundingRect(text); + real_rect.moveCenter({x, y - real_rect.height() / 2}); + p.setPen(color); + p.drawText(real_rect.x(), real_rect.bottom(), text); +} + +int HudRendererSP::drawRightDevUIElement(QPainter &p, int x, int y, const QString &value, const QString &label, const QString &units, QColor &color) { + + p.setFont(InterFont(28, QFont::Bold)); + x += 92; + y += 80; + drawText(p, x, y, label); + + p.setFont(InterFont(30 * 2, QFont::Bold)); + y += 65; + drawText(p, x, y, value, color); + + p.setFont(InterFont(28, QFont::Bold)); + + if (units.length() > 0) { + p.save(); + x += 120; + y -= 25; + p.translate(x, y); + p.rotate(-90); + drawText(p, 0, 0, units); + p.restore(); + } + + return 130; +} + +void HudRendererSP::drawRightDevUI(QPainter &p, int x, int y) { + int rh = 5; + int ry = y; + + UiElement dRelElement = DeveloperUi::getDRel(lead_status, lead_d_rel); + rh += drawRightDevUIElement(p, x, ry, dRelElement.value, dRelElement.label, dRelElement.units, dRelElement.color); + ry = y + rh; + + UiElement vRelElement = DeveloperUi::getVRel(lead_status, lead_v_rel, is_metric, speedUnit); + rh += drawRightDevUIElement(p, x, ry, vRelElement.value, vRelElement.label, vRelElement.units, vRelElement.color); + ry = y + rh; + + UiElement steeringAngleDegElement = DeveloperUi::getSteeringAngleDeg(angleSteers, latActive, steerOverride); + rh += drawRightDevUIElement(p, x, ry, steeringAngleDegElement.value, steeringAngleDegElement.label, steeringAngleDegElement.units, steeringAngleDegElement.color); + ry = y + rh; + + UiElement actuatorsOutputLateralElement = DeveloperUi::getActuatorsOutputLateral(steerControlType, actuators, desiredCurvature, vEgo, roll, latActive, steerOverride); + rh += drawRightDevUIElement(p, x, ry, actuatorsOutputLateralElement.value, actuatorsOutputLateralElement.label, actuatorsOutputLateralElement.units, actuatorsOutputLateralElement.color); + ry = y + rh; + + UiElement actualLateralAccelElement = DeveloperUi::getActualLateralAccel(curvature, vEgo, roll, latActive, steerOverride); + rh += drawRightDevUIElement(p, x, ry, actualLateralAccelElement.value, actualLateralAccelElement.label, actualLateralAccelElement.units, actualLateralAccelElement.color); +} + +int HudRendererSP::drawBottomDevUIElement(QPainter &p, int x, int y, const QString &value, const QString &label, const QString &units, QColor &color) { + p.setFont(InterFont(38, QFont::Bold)); + QFontMetrics fm(p.font()); + QRect init_rect = fm.boundingRect(label + " "); + QRect real_rect = fm.boundingRect(init_rect, 0, label + " "); + real_rect.moveCenter({x, y}); + + QRect init_rect2 = fm.boundingRect(value); + QRect real_rect2 = fm.boundingRect(init_rect2, 0, value); + real_rect2.moveTop(real_rect.top()); + real_rect2.moveLeft(real_rect.right() + 10); + + QRect init_rect3 = fm.boundingRect(units); + QRect real_rect3 = fm.boundingRect(init_rect3, 0, units); + real_rect3.moveTop(real_rect.top()); + real_rect3.moveLeft(real_rect2.right() + 10); + + p.setPen(QColorConstants::White); + p.drawText(real_rect, Qt::AlignLeft | Qt::AlignVCenter, label); + + p.setPen(color); + p.drawText(real_rect2, Qt::AlignRight | Qt::AlignVCenter, value); + p.drawText(real_rect3, Qt::AlignLeft | Qt::AlignVCenter, units); + return 430; +} + +void HudRendererSP::drawBottomDevUI(QPainter &p, int x, int y) { + int rw = 90; + + UiElement aEgoElement = DeveloperUi::getAEgo(aEgo); + rw += drawBottomDevUIElement(p, rw, y, aEgoElement.value, aEgoElement.label, aEgoElement.units, aEgoElement.color); + + UiElement vEgoLeadElement = DeveloperUi::getVEgoLead(lead_status, lead_v_rel, vEgo, is_metric, speedUnit); + rw += drawBottomDevUIElement(p, rw, y, vEgoLeadElement.value, vEgoLeadElement.label, vEgoLeadElement.units, vEgoLeadElement.color); + + if (torqueLateral && torquedUseParams) { + UiElement frictionCoefficientFilteredElement = DeveloperUi::getFrictionCoefficientFiltered(frictionCoefficientFiltered, liveValid); + rw += drawBottomDevUIElement(p, rw, y, frictionCoefficientFilteredElement.value, frictionCoefficientFilteredElement.label, frictionCoefficientFilteredElement.units, frictionCoefficientFilteredElement.color); + + UiElement latAccelFactorFilteredElement = DeveloperUi::getLatAccelFactorFiltered(latAccelFactorFiltered, liveValid); + rw += drawBottomDevUIElement(p, rw, y, latAccelFactorFilteredElement.value, latAccelFactorFilteredElement.label, latAccelFactorFilteredElement.units, latAccelFactorFilteredElement.color); + } else { + UiElement steeringTorqueEpsElement = DeveloperUi::getSteeringTorqueEps(steeringTorqueEps); + rw += drawBottomDevUIElement(p, rw, y, steeringTorqueEpsElement.value, steeringTorqueEpsElement.label, steeringTorqueEpsElement.units, steeringTorqueEpsElement.color); + + UiElement bearingDegElement = DeveloperUi::getBearingDeg(bearingAccuracyDeg, bearingDeg); + rw += drawBottomDevUIElement(p, rw, y, bearingDegElement.value, bearingDegElement.label, bearingDegElement.units, bearingDegElement.color); + } + + UiElement altitudeElement = DeveloperUi::getAltitude(gpsAccuracy, altitude); + rw += drawBottomDevUIElement(p, rw, y, altitudeElement.value, altitudeElement.label, altitudeElement.units, altitudeElement.color); } diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.h b/selfdrive/ui/sunnypilot/qt/onroad/hud.h index 1e98cd3a52..d869d989df 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.h +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.h @@ -7,9 +7,8 @@ #pragma once -#include - #include "selfdrive/ui/qt/onroad/hud.h" +#include "selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h" class HudRendererSP : public HudRenderer { Q_OBJECT @@ -18,4 +17,40 @@ public: HudRendererSP(); void updateState(const UIState &s) override; void draw(QPainter &p, const QRect &surface_rect) override; + +private: + Params params; + void drawText(QPainter &p, int x, int y, const QString &text, QColor color = QColorConstants::White); + void drawRightDevUI(QPainter &p, int x, int y); + int drawRightDevUIElement(QPainter &p, int x, int y, const QString &value, const QString &label, const QString &units, QColor &color); + int drawBottomDevUIElement(QPainter &p, int x, int y, const QString &value, const QString &label, const QString &units, QColor &color); + void drawBottomDevUI(QPainter &p, int x, int y); + + bool lead_status; + float lead_d_rel; + float lead_v_rel; + bool torqueLateral; + float angleSteers; + float desiredCurvature; + float curvature; + float roll; + int memoryUsagePercent; + int devUiInfo; + float gpsAccuracy; + float altitude; + float vEgo; + float aEgo; + float steeringTorqueEps; + float bearingAccuracyDeg; + float bearingDeg; + bool torquedUseParams; + float latAccelFactorFiltered; + float frictionCoefficientFiltered; + bool liveValid; + QString speedUnit; + bool latActive; + bool steerOverride; + bool reversing; + cereal::CarParams::SteerControlType steerControlType; + cereal::CarControl::Actuators::Reader actuators; }; diff --git a/selfdrive/ui/sunnypilot/ui.cc b/selfdrive/ui/sunnypilot/ui.cc index b2701356cc..1277195df1 100644 --- a/selfdrive/ui/sunnypilot/ui.cc +++ b/selfdrive/ui/sunnypilot/ui.cc @@ -18,13 +18,22 @@ UIStateSP::UIStateSP(QObject *parent) : UIState(parent) { "modelV2", "controlsState", "liveCalibration", "radarState", "deviceState", "pandaStates", "carParams", "driverMonitoringState", "carState", "driverStateV2", "wideRoadCameraState", "managerState", "selfdriveState", "longitudinalPlan", - "modelManagerSP", "selfdriveStateSP", "longitudinalPlanSP", "backupManagerSP" + "modelManagerSP", "selfdriveStateSP", "longitudinalPlanSP", "backupManagerSP", + "carControl", "gpsLocationExternal", "gpsLocation", "liveTorqueParameters", + "carStateSP", "liveParameters" }); // update timer timer = new QTimer(this); QObject::connect(timer, &QTimer::timeout, this, &UIStateSP::update); timer->start(1000 / UI_FREQ); + + // Param watcher for UIScene param updates + param_watcher = new ParamWatcher(this); + connect(param_watcher, &ParamWatcher::paramChanged, [=](const QString ¶m_name, const QString ¶m_value) { + ui_update_params_sp(this); + }); + param_watcher->addParam("DevUIInfo"); } // This method overrides completely the update method from the parent class intentionally. @@ -39,6 +48,11 @@ void UIStateSP::update() { emit uiUpdate(*this); } +void ui_update_params_sp(UIStateSP *s) { + auto params = Params(); + s->scene.dev_ui_info = std::atoi(params.get("DevUIInfo").c_str()); +} + DeviceSP::DeviceSP(QObject *parent) : Device(parent) { QObject::connect(uiStateSP(), &UIStateSP::uiUpdate, this, &DeviceSP::update); QObject::connect(this, &Device::displayPowerChanged, this, &DeviceSP::handleDisplayPowerChanged); diff --git a/selfdrive/ui/sunnypilot/ui.h b/selfdrive/ui/sunnypilot/ui.h index cf8de1c4bb..393f997cbd 100644 --- a/selfdrive/ui/sunnypilot/ui.h +++ b/selfdrive/ui/sunnypilot/ui.h @@ -13,6 +13,7 @@ #include "selfdrive/ui/sunnypilot/qt/network/sunnylink/models/role_model.h" #include "selfdrive/ui/sunnypilot/qt/network/sunnylink/models/sponsor_role_model.h" #include "selfdrive/ui/ui.h" +#include "selfdrive/ui/qt/util.h" class UIStateSP : public UIState { Q_OBJECT @@ -73,6 +74,7 @@ private slots: private: std::vector sunnylinkRoles = {}; std::vector sunnylinkUsers = {}; + ParamWatcher *param_watcher; }; UIStateSP *uiStateSP(); @@ -92,3 +94,5 @@ private: DeviceSP *deviceSP(); inline DeviceSP *device() { return deviceSP(); } + +void ui_update_params_sp(UIStateSP *s); diff --git a/selfdrive/ui/sunnypilot/ui_scene.h b/selfdrive/ui/sunnypilot/ui_scene.h new file mode 100644 index 0000000000..93e0cd6c91 --- /dev/null +++ b/selfdrive/ui/sunnypilot/ui_scene.h @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +typedef struct UISceneSP : UIScene { + int dev_ui_info = 0; +} UISceneSP; diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index e78b573b66..5b3872b3d4 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -66,6 +66,11 @@ typedef struct UIScene { uint64_t started_frame; } UIScene; +#ifdef SUNNYPILOT +#include "sunnypilot/ui_scene.h" +#define UIScene UISceneSP +#endif + class UIState : public QObject { Q_OBJECT From c9dbf97649a27117be6d5955a49e2d4253337288 Mon Sep 17 00:00:00 2001 From: Jimmy <9859727+Quantizr@users.noreply.github.com> Date: Thu, 11 Sep 2025 20:31:32 -1000 Subject: [PATCH 074/159] jotpluggler: add icons, use monospace font, and fix ui quirks (#36141) * use play/pause icons * use monospace font * x button for delete * add icons for splitting * many scaling + scrollbar fixes and niceties * simplify texture loading code --- tools/jotpluggler/assets/pause.png | 3 +++ tools/jotpluggler/assets/play.png | 3 +++ tools/jotpluggler/assets/split_h.png | 3 +++ tools/jotpluggler/assets/split_v.png | 3 +++ tools/jotpluggler/assets/x.png | 3 +++ tools/jotpluggler/datatree.py | 31 +++++++++++---------------- tools/jotpluggler/layout.py | 32 ++++++++++++++++++---------- tools/jotpluggler/pluggle.py | 25 +++++++++++++--------- 8 files changed, 64 insertions(+), 39 deletions(-) create mode 100644 tools/jotpluggler/assets/pause.png create mode 100644 tools/jotpluggler/assets/play.png create mode 100644 tools/jotpluggler/assets/split_h.png create mode 100644 tools/jotpluggler/assets/split_v.png create mode 100644 tools/jotpluggler/assets/x.png diff --git a/tools/jotpluggler/assets/pause.png b/tools/jotpluggler/assets/pause.png new file mode 100644 index 0000000000..8040099831 --- /dev/null +++ b/tools/jotpluggler/assets/pause.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ea96d8193eb9067a5efdc5d88a3099730ecafa40efcd09d7402bb3efd723603 +size 2305 diff --git a/tools/jotpluggler/assets/play.png b/tools/jotpluggler/assets/play.png new file mode 100644 index 0000000000..b1556cf0ab --- /dev/null +++ b/tools/jotpluggler/assets/play.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:53097ac5403b725ff1841dfa186ea770b4bb3714205824bde36ec3c2a0fb5dba +size 2758 diff --git a/tools/jotpluggler/assets/split_h.png b/tools/jotpluggler/assets/split_h.png new file mode 100644 index 0000000000..4fd88806e1 --- /dev/null +++ b/tools/jotpluggler/assets/split_h.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:54dd035ff898d881509fa686c402a61af8ef5fb408b92414722da01f773b0d33 +size 2900 diff --git a/tools/jotpluggler/assets/split_v.png b/tools/jotpluggler/assets/split_v.png new file mode 100644 index 0000000000..752e62a4ae --- /dev/null +++ b/tools/jotpluggler/assets/split_v.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:adbd4e5df1f58694dca9dde46d1d95b4e7471684e42e6bca9f41ea5d346e67c5 +size 3669 diff --git a/tools/jotpluggler/assets/x.png b/tools/jotpluggler/assets/x.png new file mode 100644 index 0000000000..3b2eabd447 --- /dev/null +++ b/tools/jotpluggler/assets/x.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a6d9c90cb0dd906e0b15e1f7f3fd9f0dfad3c3b0b34eeed7a7882768dc5f3961 +size 2053 diff --git a/tools/jotpluggler/datatree.py b/tools/jotpluggler/datatree.py index c18ab61892..3390fed2e1 100644 --- a/tools/jotpluggler/datatree.py +++ b/tools/jotpluggler/datatree.py @@ -34,7 +34,7 @@ class DataTree: self._path_to_node: dict[str, DataTreeNode] = {} # full_path -> node self._expanded_tags: set[str] = set() self._item_handlers: dict[str, str] = {} # ui_tag -> handler_tag - self._avg_char_width = None + self._char_width = None self._queued_search = None self._new_data = False self._ui_lock = threading.RLock() @@ -43,12 +43,13 @@ class DataTree: def create_ui(self, parent_tag: str): with dpg.child_window(parent=parent_tag, border=False, width=-1, height=-1): - dpg.add_text("Available Data") + dpg.add_text("Timeseries List") dpg.add_separator() dpg.add_input_text(tag="search_input", width=-1, hint="Search fields...", callback=self.search_data) dpg.add_separator() - with dpg.group(tag="data_tree_container"): - pass + with dpg.child_window(border=False, width=-1, height=-1): + with dpg.group(tag="data_tree_container"): + pass def _on_data_loaded(self, data: dict): with self._ui_lock: @@ -64,8 +65,9 @@ class DataTree: self._handlers_to_delete.clear() with self._ui_lock: - if self._avg_char_width is None and dpg.is_dearpygui_running(): - self._avg_char_width = self.calculate_avg_char_width(font) + if self._char_width is None: + if size := dpg.get_text_size(" ", font=font): + self._char_width = size[0] if self._new_data: self._process_path_change() @@ -256,10 +258,10 @@ class DataTree: value_tag = f"value_{path}" if not dpg.does_item_exist(value_tag): return - value_column_width = dpg.get_item_rect_size("sidebar_window")[0] // 2 + value_column_width = dpg.get_item_rect_size(f"leaf_{path}")[0] // 2 value = self.data_manager.get_value_at(path, self.playback_manager.current_time_s) if value is not None: - formatted_value = self.format_and_truncate(value, value_column_width, self._avg_char_width) + formatted_value = self.format_and_truncate(value, value_column_width, self._char_width) dpg.set_value(value_tag, formatted_value) else: dpg.set_value(value_tag, "N/A") @@ -305,16 +307,9 @@ class DataTree: yield f"{child_name_lower}/{path}" @staticmethod - def calculate_avg_char_width(font): - sample_text = "abcdefghijklmnopqrstuvwxyz0123456789" - if size := dpg.get_text_size(sample_text, font=font): - return size[0] / len(sample_text) - return None - - @staticmethod - def format_and_truncate(value, available_width: float, avg_char_width: float) -> str: + def format_and_truncate(value, available_width: float, char_width: float) -> str: s = f"{value:.5f}" if np.issubdtype(type(value), np.floating) else str(value) - max_chars = int(available_width / avg_char_width) - 3 + max_chars = int(available_width / char_width) if len(s) > max_chars: - return s[: max(0, max_chars)] + "..." + return s[: max(0, max_chars - 3)] + "..." return s diff --git a/tools/jotpluggler/layout.py b/tools/jotpluggler/layout.py index 0c40116e66..917c156f9f 100644 --- a/tools/jotpluggler/layout.py +++ b/tools/jotpluggler/layout.py @@ -25,29 +25,33 @@ class PlotLayoutManager: if dpg.does_item_exist(self.container_tag): dpg.delete_item(self.container_tag) - with dpg.child_window(tag=self.container_tag, parent=parent_tag, border=False, width=-1, height=-1, no_scrollbar=True): + with dpg.child_window(tag=self.container_tag, parent=parent_tag, border=False, width=-1, height=-1, no_scrollbar=True, no_scroll_with_mouse=True): container_width, container_height = dpg.get_item_rect_size(self.container_tag) self._create_ui_recursive(self.layout, self.container_tag, [], container_width, container_height) def _create_ui_recursive(self, layout: dict, parent_tag: str, path: list[int], width: int, height: int): if layout["type"] == "panel": - self._create_panel_ui(layout, parent_tag, path) + self._create_panel_ui(layout, parent_tag, path, width, height) else: self._create_split_ui(layout, parent_tag, path, width, height) - def _create_panel_ui(self, layout: dict, parent_tag: str, path: list[int]): + def _create_panel_ui(self, layout: dict, parent_tag: str, path: list[int], width: int, height:int): panel_tag = self._path_to_tag(path, "panel") panel = layout["panel"] self.active_panels.append(panel) + text_size = int(13 * self.scale) + bar_height = (text_size+24) if width < int(279 * self.scale + 80) else (text_size+8) # adjust height to allow for scrollbar - with dpg.child_window(tag=panel_tag, parent=parent_tag, border=True, width=-1, height=-1, no_scrollbar=True): + with dpg.child_window(parent=parent_tag, border=True, width=-1, height=-1, no_scrollbar=True): with dpg.group(horizontal=True): - dpg.add_input_text(default_value=panel.title, width=int(100 * self.scale), callback=lambda s, v: setattr(panel, "title", v)) - dpg.add_combo(items=["Time Series"], default_value="Time Series", width=int(100 * self.scale)) - dpg.add_button(label="Clear", callback=lambda: self.clear_panel(panel), width=int(40 * self.scale)) - dpg.add_button(label="Delete", callback=lambda: self.delete_panel(path), width=int(40 * self.scale)) - dpg.add_button(label="Split H", callback=lambda: self.split_panel(path, 0), width=int(40 * self.scale)) - dpg.add_button(label="Split V", callback=lambda: self.split_panel(path, 1), width=int(40 * self.scale)) + with dpg.child_window(tag=panel_tag, width=-(text_size + 16), height=bar_height, horizontal_scrollbar=True, no_scroll_with_mouse=True, border=False): + with dpg.group(horizontal=True): + dpg.add_input_text(default_value=panel.title, width=int(100 * self.scale), callback=lambda s, v: setattr(panel, "title", v)) + dpg.add_combo(items=["Time Series"], default_value="Time Series", width=int(100 * self.scale)) + dpg.add_button(label="Clear", callback=lambda: self.clear_panel(panel), width=int(40 * self.scale)) + dpg.add_image_button(texture_tag="split_h_texture", callback=lambda: self.split_panel(path, 0), width=text_size, height=text_size) + dpg.add_image_button(texture_tag="split_v_texture", callback=lambda: self.split_panel(path, 1), width=text_size, height=text_size) + dpg.add_image_button(texture_tag="x_texture", callback=lambda: self.delete_panel(path), width=text_size, height=text_size) dpg.add_separator() @@ -177,11 +181,17 @@ class PlotLayoutManager: dpg.configure_item(container_tag, **{size_properties[orientation]: pane_sizes[i]}) child_width, child_height = [(pane_sizes[i], available_sizes[1]), (available_sizes[0], pane_sizes[i])][orientation] self._resize_splits_recursive(child_layout, child_path, child_width, child_height) + else: # leaf node/panel - adjust bar height to allow for scrollbar + panel_tag = self._path_to_tag(path, "panel") + if width is not None and width < int(279 * self.scale + 80): # scaled widths of the elements in top bar + fixed 8 padding on left and right of each item + dpg.configure_item(panel_tag, height=(int(13*self.scale) + 24)) + else: + dpg.configure_item(panel_tag, height=(int(13*self.scale) + 8)) def _get_split_geometry(self, layout: dict, available_size: tuple[int, int]) -> tuple[int, int, list[int]]: orientation = layout["orientation"] num_grips = len(layout["children"]) - 1 - usable_size = max(self.min_pane_size, available_size[orientation] - (num_grips * self.grip_size)) + usable_size = max(self.min_pane_size, available_size[orientation] - (num_grips * (self.grip_size + 8 * (2-orientation)))) # approximate, scaling is weird pane_sizes = [max(self.min_pane_size, int(usable_size * prop)) for prop in layout["proportions"]] return orientation, usable_size, pane_sizes diff --git a/tools/jotpluggler/pluggle.py b/tools/jotpluggler/pluggle.py index 9868b998ed..582a44454e 100755 --- a/tools/jotpluggler/pluggle.py +++ b/tools/jotpluggler/pluggle.py @@ -73,9 +73,10 @@ class PlaybackManager: if not self.is_playing and self.current_time_s >= self.duration_s: self.seek(0.0) self.is_playing = not self.is_playing + texture_tag = "pause_texture" if self.is_playing else "play_texture" + dpg.configure_item("play_pause_button", texture_tag=texture_tag) def seek(self, time_s: float): - self.is_playing = False self.current_time_s = max(0.0, min(time_s, self.duration_s)) def update_time(self, delta_t: float): @@ -83,6 +84,7 @@ class PlaybackManager: self.current_time_s = min(self.current_time_s + delta_t, self.duration_s) if self.current_time_s >= self.duration_s: self.is_playing = False + dpg.configure_item("play_pause_button", texture_tag="play_texture") return self.current_time_s @@ -109,7 +111,6 @@ class MainController: dpg.add_theme_style(dpg.mvPlotStyleVar_LineWeight, scaled_thickness, category=dpg.mvThemeCat_Plots) dpg.add_theme_color(dpg.mvPlotCol_Line, (255, 0, 0, 128), category=dpg.mvThemeCat_Plots) - def on_data_loaded(self, data: dict): duration = data.get('duration', 0.0) self.playback_manager.set_route_duration(duration) @@ -121,7 +122,7 @@ class MainController: dpg.set_value("load_status", "Loading...") dpg.set_value("timeline_slider", 0.0) dpg.configure_item("timeline_slider", max_value=0.0) - dpg.configure_item("play_pause_button", label="Play") + dpg.configure_item("play_pause_button", texture_tag="play_texture") dpg.configure_item("load_button", enabled=True) elif data.get('loading_complete'): num_paths = len(self.data_manager.get_all_paths()) @@ -134,6 +135,12 @@ class MainController: dpg.configure_item("timeline_slider", max_value=duration) def setup_ui(self): + with dpg.texture_registry(): + script_dir = os.path.dirname(os.path.realpath(__file__)) + for image in ["play", "pause", "x", "split_h", "split_v"]: + texture = dpg.load_image(os.path.join(script_dir, "assets", f"{image}.png")) + dpg.add_static_texture(width=texture[0], height=texture[1], default_value=texture[3], tag=f"{image}_texture") + with dpg.window(tag="Primary Window"): with dpg.group(horizontal=True): # Left panel - Data tree @@ -147,16 +154,17 @@ class MainController: # Right panel - Plots and timeline with dpg.group(tag="right_panel"): - with dpg.child_window(label="Plot Window", border=True, height=-(30 + 13 * self.scale), tag="main_plot_area"): + with dpg.child_window(label="Plot Window", border=True, height=-(32 + 13 * self.scale), tag="main_plot_area"): self.plot_layout_manager.create_ui("main_plot_area") with dpg.child_window(label="Timeline", border=True): with dpg.table(header_row=False, borders_innerH=False, borders_innerV=False, borders_outerH=False, borders_outerV=False): - dpg.add_table_column(width_fixed=True, init_width_or_weight=int(50 * self.scale)) # Play button + btn_size = int(13 * self.scale) + dpg.add_table_column(width_fixed=True, init_width_or_weight=(btn_size + 8)) # Play button dpg.add_table_column(width_stretch=True) # Timeline slider dpg.add_table_column(width_fixed=True, init_width_or_weight=int(50 * self.scale)) # FPS counter with dpg.table_row(): - dpg.add_button(label="Play", tag="play_pause_button", callback=self.toggle_play_pause, width=int(50 * self.scale)) + dpg.add_image_button(texture_tag="play_texture", tag="play_pause_button", callback=self.toggle_play_pause, width=btn_size, height=btn_size) dpg.add_slider_float(tag="timeline_slider", default_value=0.0, label="", width=-1, callback=self.timeline_drag) dpg.add_text("", tag="fps_counter") with dpg.item_handler_registry(tag="plot_resize_handler"): @@ -177,12 +185,9 @@ class MainController: def toggle_play_pause(self, sender): self.playback_manager.toggle_play_pause() - label = "Pause" if self.playback_manager.is_playing else "Play" - dpg.configure_item(sender, label=label) def timeline_drag(self, sender, app_data): self.playback_manager.seek(app_data) - dpg.configure_item("play_pause_button", label="Play") def update_frame(self, font): self.data_tree.update_frame(font) @@ -210,7 +215,7 @@ def main(route_to_load=None): scale = 1 with dpg.font_registry(): - default_font = dpg.add_font(os.path.join(BASEDIR, "selfdrive/assets/fonts/Inter-Regular.ttf"), int(13 * scale)) + default_font = dpg.add_font(os.path.join(BASEDIR, "selfdrive/assets/fonts/JetBrainsMono-Medium.ttf"), int(13 * scale)) dpg.bind_font(default_font) viewport_width, viewport_height = int(1200 * scale), int(800 * scale) From 810a2d9448df89ef84ecc1c794b63fad55350d69 Mon Sep 17 00:00:00 2001 From: DevTekVE Date: Fri, 12 Sep 2025 09:03:17 +0200 Subject: [PATCH 075/159] Revert & Reapply "UI: Developer UI" temporarily due to QT version mismatch (#1237) * Revert "UI: Developer UI (#1233)" This reverts commit 1bb4ca2547448f2189f67cb54db150e78bc4d487. * Reapply "UI: Developer UI (#1233)" This reverts commit b0a77049dacbdd59bc21d154820ba8cadf4ad201. * QColorConstants is not on device's QT version. Thanks @kumar for the fix --- selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 2 +- selfdrive/ui/sunnypilot/qt/onroad/hud.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index 15722cc9f8..9ead933d04 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -171,7 +171,7 @@ int HudRendererSP::drawBottomDevUIElement(QPainter &p, int x, int y, const QStri real_rect3.moveTop(real_rect.top()); real_rect3.moveLeft(real_rect2.right() + 10); - p.setPen(QColorConstants::White); + p.setPen(Qt::white); p.drawText(real_rect, Qt::AlignLeft | Qt::AlignVCenter, label); p.setPen(color); diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.h b/selfdrive/ui/sunnypilot/qt/onroad/hud.h index d869d989df..968789bc15 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.h +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.h @@ -20,7 +20,7 @@ public: private: Params params; - void drawText(QPainter &p, int x, int y, const QString &text, QColor color = QColorConstants::White); + void drawText(QPainter &p, int x, int y, const QString &text, QColor color = Qt::white); void drawRightDevUI(QPainter &p, int x, int y); int drawRightDevUIElement(QPainter &p, int x, int y, const QString &value, const QString &label, const QString &units, QColor &color); int drawBottomDevUIElement(QPainter &p, int x, int y, const QString &value, const QString &label, const QString &units, QColor &color); From 1be13fdc55a24a72bc33703c7343c9421fdd0842 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Fri, 12 Sep 2025 08:37:24 -0400 Subject: [PATCH 076/159] Revert "UI: Developer UI" (#1238) * Revert "Revert & Reapply "UI: Developer UI" temporarily due to QT version mismatch (#1237)" This reverts commit 810a2d9448df89ef84ecc1c794b63fad55350d69. * Revert "UI: Developer UI (#1233)" This reverts commit 1bb4ca2547448f2189f67cb54db150e78bc4d487. --- common/params_keys.h | 1 - selfdrive/ui/qt/onroad/alerts.cc | 9 - selfdrive/ui/qt/onroad/annotated_camera.h | 1 - selfdrive/ui/qt/onroad/driver_monitoring.cc | 5 - selfdrive/ui/sunnypilot/SConscript | 1 - .../qt/offroad/settings/visuals_panel.cc | 12 - .../qt/offroad/settings/visuals_panel.h | 1 - .../sunnypilot/qt/onroad/annotated_camera.cc | 5 - .../sunnypilot/qt/onroad/annotated_camera.h | 3 - .../qt/onroad/developer_ui/developer_ui.cc | 227 ------------------ .../qt/onroad/developer_ui/developer_ui.h | 31 --- .../qt/onroad/developer_ui/ui_elements.h | 19 -- selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 190 --------------- selfdrive/ui/sunnypilot/qt/onroad/hud.h | 39 +-- selfdrive/ui/sunnypilot/ui.cc | 16 +- selfdrive/ui/sunnypilot/ui.h | 4 - selfdrive/ui/sunnypilot/ui_scene.h | 12 - selfdrive/ui/ui.h | 5 - 18 files changed, 3 insertions(+), 578 deletions(-) delete mode 100644 selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.cc delete mode 100644 selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h delete mode 100644 selfdrive/ui/sunnypilot/qt/onroad/developer_ui/ui_elements.h delete mode 100644 selfdrive/ui/sunnypilot/ui_scene.h diff --git a/common/params_keys.h b/common/params_keys.h index fc7842720b..afb6b348eb 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -146,7 +146,6 @@ inline static std::unordered_map keys = { {"CustomAccLongPressIncrement", {PERSISTENT | BACKUP, INT, "5"}}, {"CustomAccShortPressIncrement", {PERSISTENT | BACKUP, INT, "1"}}, {"DeviceBootMode", {PERSISTENT | BACKUP, INT, "0"}}, - {"DevUIInfo", {PERSISTENT | BACKUP, INT, "0"}}, {"EnableCopyparty", {PERSISTENT | BACKUP, BOOL}}, {"EnableGithubRunner", {PERSISTENT | BACKUP, BOOL}}, {"GithubRunnerSufficientVoltage", {CLEAR_ON_MANAGER_START , BOOL}}, diff --git a/selfdrive/ui/qt/onroad/alerts.cc b/selfdrive/ui/qt/onroad/alerts.cc index 2e8f3612eb..d6829c6b08 100644 --- a/selfdrive/ui/qt/onroad/alerts.cc +++ b/selfdrive/ui/qt/onroad/alerts.cc @@ -4,9 +4,6 @@ #include #include "selfdrive/ui/qt/util.h" -#ifdef SUNNYPILOT -#include "selfdrive/ui/sunnypilot/ui.h" -#endif void OnroadAlerts::updateState(const UIState &s) { Alert a = getAlert(*(s.sm), s.scene.started_frame); @@ -76,12 +73,6 @@ void OnroadAlerts::paintEvent(QPaintEvent *event) { } QRect r = QRect(0 + margin, height() - h + margin, width() - margin*2, h - margin*2); -#ifdef SUNNYPILOT - const int dev_ui_info = uiStateSP()->scene.dev_ui_info; - const int adjustment = dev_ui_info > 1 && alert.size != cereal::SelfdriveState::AlertSize::FULL ? 30 : 0; - r = QRect(0 + margin, height() - h + margin - adjustment, width() - margin*2, h - margin*2); -#endif - QPainter p(this); // draw background + gradient diff --git a/selfdrive/ui/qt/onroad/annotated_camera.h b/selfdrive/ui/qt/onroad/annotated_camera.h index 5d9d21ab6b..e3ca837907 100644 --- a/selfdrive/ui/qt/onroad/annotated_camera.h +++ b/selfdrive/ui/qt/onroad/annotated_camera.h @@ -12,7 +12,6 @@ #include "selfdrive/ui/sunnypilot/qt/onroad/model.h" #define ExperimentalButton ExperimentalButtonSP #define ModelRenderer ModelRendererSP -#define HudRenderer HudRendererSP #else #include "selfdrive/ui/qt/onroad/buttons.h" #include "selfdrive/ui/qt/onroad/hud.h" diff --git a/selfdrive/ui/qt/onroad/driver_monitoring.cc b/selfdrive/ui/qt/onroad/driver_monitoring.cc index e67c483047..49f2c950b4 100644 --- a/selfdrive/ui/qt/onroad/driver_monitoring.cc +++ b/selfdrive/ui/qt/onroad/driver_monitoring.cc @@ -73,11 +73,6 @@ void DriverMonitorRenderer::draw(QPainter &painter, const QRect &surface_rect) { float y = surface_rect.height() - offset; float opacity = is_active ? 0.65f : 0.2f; -#ifdef SUNNYPILOT - const int dev_ui_info = uiStateSP()->scene.dev_ui_info; - y -= dev_ui_info > 1 ? 50 : 0; -#endif - drawIcon(painter, QPoint(x, y), dm_img, QColor(0, 0, 0, 70), opacity); QPointF keypoints[std::size(DEFAULT_FACE_KPTS_3D)]; diff --git a/selfdrive/ui/sunnypilot/SConscript b/selfdrive/ui/sunnypilot/SConscript index 807bf02478..2f3c8ddd8d 100644 --- a/selfdrive/ui/sunnypilot/SConscript +++ b/selfdrive/ui/sunnypilot/SConscript @@ -39,7 +39,6 @@ qt_src = [ "sunnypilot/qt/offroad/settings/visuals_panel.cc", "sunnypilot/qt/onroad/annotated_camera.cc", "sunnypilot/qt/onroad/buttons.cc", - "sunnypilot/qt/onroad/developer_ui/developer_ui.cc", "sunnypilot/qt/onroad/hud.cc", "sunnypilot/qt/onroad/model.cc", "sunnypilot/qt/onroad/onroad_home.cc", diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc index c3aaf12d22..dd2f05416d 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc @@ -72,15 +72,6 @@ VisualsPanel::VisualsPanel(QWidget *parent) : QWidget(parent) { list->addItem(chevron_info_settings); param_watcher->addParam("ChevronInfo"); - // Visuals: Developer UI Info (Dev UI) - std::vector dev_ui_settings_texts{tr("Off"), tr("Right"), tr("Right &&\nBottom")}; - dev_ui_settings = new ButtonParamControlSP( - "DevUIInfo", tr("Developer UI"), tr("Display real-time parameters and metrics from various sources."), - "", - dev_ui_settings_texts, - 380); - list->addItem(dev_ui_settings); - sunnypilotScroller = new ScrollViewSP(list, this); vlayout->addWidget(sunnypilotScroller); @@ -99,7 +90,4 @@ void VisualsPanel::paramsRefresh() { if (chevron_info_settings) { chevron_info_settings->refresh(); } - if (dev_ui_settings) { - dev_ui_settings->refresh(); - } } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.h index 30ff31c301..f342662c22 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.h @@ -28,5 +28,4 @@ protected: std::map toggles; ParamWatcher * param_watcher; ButtonParamControlSP *chevron_info_settings; - ButtonParamControlSP *dev_ui_settings; }; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.cc b/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.cc index 1d5567161a..3721a3d198 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.cc @@ -14,8 +14,3 @@ AnnotatedCameraWidgetSP::AnnotatedCameraWidgetSP(VisionStreamType type, QWidget void AnnotatedCameraWidgetSP::updateState(const UIState &s) { AnnotatedCameraWidget::updateState(s); } - -void AnnotatedCameraWidgetSP::showEvent(QShowEvent *event) { - AnnotatedCameraWidget::showEvent(event); - ui_update_params_sp(uiState()); -} diff --git a/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.h b/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.h index 8c0a385657..46ce7d4be3 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.h +++ b/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.h @@ -15,7 +15,4 @@ class AnnotatedCameraWidgetSP : public AnnotatedCameraWidget { public: explicit AnnotatedCameraWidgetSP(VisionStreamType type, QWidget *parent = nullptr); void updateState(const UIState &s) override; - -protected: - void showEvent(QShowEvent *event) override; }; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.cc b/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.cc deleted file mode 100644 index 292ba6f7bb..0000000000 --- a/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.cc +++ /dev/null @@ -1,227 +0,0 @@ -/** - * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. - * - * This file is part of sunnypilot and is licensed under the MIT License. - * See the LICENSE.md file in the root directory for more details. - */ -#include - -#include "common/util.h" -#include "selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h" - - -// Add Relative Distance to Primary Lead Car -// Unit: Meters -UiElement DeveloperUi::getDRel(bool lead_status, float lead_d_rel) { - QString value = lead_status ? QString::number(lead_d_rel, 'f', 0) : "-"; - QColor color = QColor(255, 255, 255, 255); - - if (lead_status) { - // Orange if close, Red if very close - if (lead_d_rel < 5) { - color = QColor(255, 0, 0, 255); - } else if (lead_d_rel < 15) { - color = QColor(255, 188, 0, 255); - } - } - - return UiElement(value, "REL DIST", "m", color); -} - -// Add Relative Velocity vs Primary Lead Car -// Unit: kph if metric, else mph -UiElement DeveloperUi::getVRel(bool lead_status, float lead_v_rel, bool is_metric, const QString &speed_unit) { - QString value = lead_status ? QString::number(lead_v_rel * (is_metric ? MS_TO_KPH : MS_TO_MPH), 'f', 0) : "-"; - QColor color = QColor(255, 255, 255, 255); - - if (lead_status) { - // Red if approaching faster than 10mph - // Orange if approaching (negative) - if (lead_v_rel < -4.4704) { - color = QColor(255, 0, 0, 255); - } else if (lead_v_rel < 0) { - color = QColor(255, 188, 0, 255); - } - } - - return UiElement(value, "REL SPEED", speed_unit, color); -} - -// Add Real Steering Angle -// Unit: Degrees -UiElement DeveloperUi::getSteeringAngleDeg(float angle_steers, bool lat_active, bool steer_override) { - QString value = QString("%1%2%3").arg(QString::number(angle_steers, 'f', 1)).arg("°").arg(""); - QColor color = lat_active ? (steer_override ? QColor(0x91, 0x9b, 0x95, 0xff) : QColor(0, 255, 0, 255)) : QColor(255, 255, 255, 255); - - // Red if large steering angle - // Orange if moderate steering angle - if (std::fabs(angle_steers) > 180) { - color = QColor(255, 0, 0, 255); - } else if (std::fabs(angle_steers) > 90) { - color = QColor(255, 188, 0, 255); - } - - return UiElement(value, "REAL STEER", "", color); -} - -// Add Actual Lateral Acceleration (roll compensated) when using Torque -// Unit: m/s² -UiElement DeveloperUi::getActualLateralAccel(float curvature, float v_ego, float roll, bool lat_active, bool steer_override) { - double actualLateralAccel = (curvature * pow(v_ego, 2)) - (roll * 9.81); - - QString value = QString::number(actualLateralAccel, 'f', 2); - QColor color = lat_active ? (steer_override ? QColor(0x91, 0x9b, 0x95, 0xff) : QColor(0, 255, 0, 255)) : QColor(255, 255, 255, 255); - - return UiElement(value, "ACTUAL L.A.", "m/s²", color); -} - -// Add Desired Steering Angle when using PID -// Unit: Degrees -UiElement DeveloperUi::getSteeringAngleDesiredDeg(bool lat_active, float steer_angle_desired, float angle_steers) { - QString value = lat_active ? QString("%1%2%3").arg(QString::number(steer_angle_desired, 'f', 1)).arg("°").arg("") : "-"; - QColor color = QColor(255, 255, 255, 255); - - if (lat_active) { - // Red if large steering angle - // Orange if moderate steering angle - if (std::fabs(angle_steers) > 180) { - color = QColor(255, 0, 0, 255); - } else if (std::fabs(angle_steers) > 90) { - color = QColor(255, 188, 0, 255); - } else { - color = QColor(0, 255, 0, 255); - } - } - - return UiElement(value, "DESIRED STEER", "", color); -} - -// Add Device Memory (RAM) Usage -// Unit: Percent -UiElement DeveloperUi::getMemoryUsagePercent(int memory_usage_percent) { - QString value = QString("%1%2").arg(QString::number(memory_usage_percent, 'd', 0)).arg("%"); - QColor color = (memory_usage_percent > 85) ? QColor(255, 188, 0, 255) : QColor(255, 255, 255, 255); - - return UiElement(value, "RAM", "", color); -} - -// Add Vehicle Current Acceleration -// Unit: m/s² -UiElement DeveloperUi::getAEgo(float a_ego) { - QString value = QString::number(a_ego, 'f', 1); - QColor color = QColor(255, 255, 255, 255); - - return UiElement(value, "ACC.", "m/s²", color); -} - -// Add Relative Velocity to Primary Lead Car -// Unit: kph if metric, else mph -UiElement DeveloperUi::getVEgoLead(bool lead_status, float lead_v_rel, float v_ego, bool is_metric, const QString &speed_unit) { - QString value = lead_status ? QString::number((lead_v_rel + v_ego) * (is_metric ? MS_TO_KPH : MS_TO_MPH), 'f', 0) : "-"; - QColor color = QColor(255, 255, 255, 255); - - if (lead_status) { - // Red if approaching faster than 10mph - // Orange if approaching (negative) - if (lead_v_rel < -4.4704) { - color = QColor(255, 0, 0, 255); - } else if (lead_v_rel < 0) { - color = QColor(255, 188, 0, 255); - } - } - - return UiElement(value, "L.S.", speed_unit, color); -} - -// Add Friction Coefficient Raw from torqued -// Unit: None -UiElement DeveloperUi::getFrictionCoefficientFiltered(float friction_coefficient_filtered, bool live_valid) { - QString value = QString::number(friction_coefficient_filtered, 'f', 3); - QColor color = live_valid ? QColor(0, 255, 0, 255) : QColor(255, 255, 255, 255); - - return UiElement(value, "FRIC.", "", color); -} - -// Add Lateral Acceleration Factor Raw from torqued -// Unit: m/s² -UiElement DeveloperUi::getLatAccelFactorFiltered(float lat_accel_factor_filtered, bool live_valid) { - QString value = QString::number(lat_accel_factor_filtered, 'f', 3); - QColor color = live_valid ? QColor(0, 255, 0, 255) : QColor(255, 255, 255, 255); - - return UiElement(value, "L.A.", "m/s²", color); -} - -// Add Steering Torque from Car EPS -// Unit: Newton Meters -UiElement DeveloperUi::getSteeringTorqueEps(float steering_torque_eps) { - QString value = QString::number(std::fabs(steering_torque_eps), 'f', 1); - QColor color = QColor(255, 255, 255, 255); - - return UiElement(value, "E.T.", "N·dm", color); -} - -// Add Bearing Degree and Direction from Car (Compass) -// Unit: Meters -UiElement DeveloperUi::getBearingDeg(float bearing_accuracy_deg, float bearing_deg) { - QString value = (bearing_accuracy_deg != 180.00) ? QString("%1%2%3").arg(QString::number(bearing_deg, 'd', 0)).arg("°").arg("") : "-"; - QColor color = QColor(255, 255, 255, 255); - QString dir_value; - - if (bearing_accuracy_deg != 180.00) { - if (((bearing_deg >= 337.5) && (bearing_deg <= 360)) || ((bearing_deg >= 0) && (bearing_deg <= 22.5))) { - dir_value = "N"; - } else if ((bearing_deg > 22.5) && (bearing_deg < 67.5)) { - dir_value = "NE"; - } else if ((bearing_deg >= 67.5) && (bearing_deg <= 112.5)) { - dir_value = "E"; - } else if ((bearing_deg > 112.5) && (bearing_deg < 157.5)) { - dir_value = "SE"; - } else if ((bearing_deg >= 157.5) && (bearing_deg <= 202.5)) { - dir_value = "S"; - } else if ((bearing_deg > 202.5) && (bearing_deg < 247.5)) { - dir_value = "SW"; - } else if ((bearing_deg >= 247.5) && (bearing_deg <= 292.5)) { - dir_value = "W"; - } else if ((bearing_deg > 292.5) && (bearing_deg < 337.5)) { - dir_value = "NW"; - } - } else { - dir_value = "OFF"; - } - - return UiElement(QString("%1 | %2").arg(dir_value).arg(value), "B.D.", "", color); -} - -// Add Altitude of Current Location -// Unit: Meters -UiElement DeveloperUi::getAltitude(float gps_accuracy, float altitude) { - QString value = (gps_accuracy != 0.00) ? QString::number(altitude, 'f', 1) : "-"; - QColor color = QColor(255, 255, 255, 255); - - return UiElement(value, "ALT.", "m", color); -} - -// Add Actuators Output -// Unit: Degree (angle) or m/s² (torque) -UiElement DeveloperUi::getActuatorsOutputLateral(cereal::CarParams::SteerControlType steerControlType, - cereal::CarControl::Actuators::Reader &actuators, - float desiredCurvature, float v_ego, float roll, bool lat_active, bool steer_override) { - QString label; - QString value; - QString unit; - - if (steerControlType == cereal::CarParams::SteerControlType::ANGLE) { - label = "DESIRED STEER"; - value = QString("%1%2%3").arg(QString::number(actuators.getSteeringAngleDeg(), 'f', 1)).arg("°").arg(""); - } else { - label = "DESIRED L.A."; - double desiredLateralAccel = (desiredCurvature * pow(v_ego, 2)) - (roll * 9.81); - value = QString::number(desiredLateralAccel, 'f', 2); - unit = "m/s²"; - } - - value = lat_active ? value : "-"; - QColor color = lat_active ? (steer_override ? QColor(0x91, 0x9b, 0x95, 0xff) : QColor(0, 255, 0, 255)) : QColor(255, 255, 255, 255); - - return UiElement(value, label, unit, color); -} diff --git a/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h b/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h deleted file mode 100644 index 0c5c472209..0000000000 --- a/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. - * - * This file is part of sunnypilot and is licensed under the MIT License. - * See the LICENSE.md file in the root directory for more details. - */ -#pragma once - -#include "selfdrive/ui/qt/util.h" -#include "selfdrive/ui/sunnypilot/qt/onroad/developer_ui/ui_elements.h" - -class DeveloperUi { - -public: - static UiElement getDRel(bool lead_status, float lead_d_rel); - static UiElement getVRel(bool lead_status, float lead_v_rel, bool is_metric, const QString &speed_unit); - static UiElement getSteeringAngleDeg(float angle_steers, bool lat_active, bool steer_override); - static UiElement getActualLateralAccel(float curvature, float v_ego, float roll, bool lat_active, bool steer_override); - static UiElement getSteeringAngleDesiredDeg(bool lat_active, float steer_angle_desired, float angle_steers); - static UiElement getMemoryUsagePercent(int memory_usage_percent); - static UiElement getAEgo(float a_ego); - static UiElement getVEgoLead(bool lead_status, float lead_v_rel, float v_ego, bool is_metric, const QString &speed_unit); - static UiElement getFrictionCoefficientFiltered(float friction_coefficient_filtered, bool live_valid); - static UiElement getLatAccelFactorFiltered(float lat_accel_factor_filtered, bool live_valid); - static UiElement getSteeringTorqueEps(float steering_torque_eps); - static UiElement getBearingDeg(float bearing_accuracy_deg, float bearing_deg); - static UiElement getAltitude(float gps_accuracy, float altitude); - static UiElement getActuatorsOutputLateral(cereal::CarParams::SteerControlType steerControlType, - cereal::CarControl::Actuators::Reader &actuators, - float desiredCurvature, float v_ego, float roll, bool lat_active, bool steer_override); -}; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/ui_elements.h b/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/ui_elements.h deleted file mode 100644 index 3711e5ac05..0000000000 --- a/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/ui_elements.h +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. - * - * This file is part of sunnypilot and is licensed under the MIT License. - * See the LICENSE.md file in the root directory for more details. - */ -#pragma once - -#include - -struct UiElement { - QString value{}; - QString label{}; - QString units{}; - QColor color{}; - - explicit UiElement(const QString &value = "", const QString &label = "", const QString &units = "", const QColor &color = QColor(255, 255, 255, 255)) - : value(value), label(label), units(units), color(color) {} -}; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index 9ead933d04..233ca59f98 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -7,202 +7,12 @@ #include "selfdrive/ui/sunnypilot/qt/onroad/hud.h" -#include "selfdrive/ui/qt/util.h" - - HudRendererSP::HudRendererSP() {} void HudRendererSP::updateState(const UIState &s) { HudRenderer::updateState(s); - - const SubMaster &sm = *(s.sm); - const bool cs_alive = sm.alive("controlsState"); - const auto cs = sm["controlsState"].getControlsState(); - const auto car_state = sm["carState"].getCarState(); - const auto car_control = sm["carControl"].getCarControl(); - const auto radar_state = sm["radarState"].getRadarState(); - const auto is_gps_location_external = sm.rcv_frame("gpsLocationExternal") > 1; - const auto gpsLocation = is_gps_location_external ? sm["gpsLocationExternal"].getGpsLocationExternal() : sm["gpsLocation"].getGpsLocation(); - const auto ltp = sm["liveTorqueParameters"].getLiveTorqueParameters(); - const auto car_params = sm["carParams"].getCarParams(); - - static int reverse_delay = 0; - bool reverse_allowed = false; - if (int(car_state.getGearShifter()) != 4) { - reverse_delay = 0; - reverse_allowed = false; - } else { - reverse_delay += 50; - if (reverse_delay >= 1000) { - reverse_allowed = true; - } - } - - reversing = reverse_allowed; - is_metric = s.scene.is_metric; - - // Handle older routes where vEgoCluster is not set - v_ego_cluster_seen = v_ego_cluster_seen || car_state.getVEgoCluster() != 0.0; - float v_ego = v_ego_cluster_seen ? car_state.getVEgoCluster() : car_state.getVEgo(); - speed = cs_alive ? std::max(0.0, v_ego) : 0.0; - speed *= is_metric ? MS_TO_KPH : MS_TO_MPH; - - latActive = car_control.getLatActive(); - steerOverride = car_state.getSteeringPressed(); - - devUiInfo = s.scene.dev_ui_info; - - speedUnit = is_metric ? tr("km/h") : tr("mph"); - lead_d_rel = radar_state.getLeadOne().getDRel(); - lead_v_rel = radar_state.getLeadOne().getVRel(); - lead_status = radar_state.getLeadOne().getStatus(); - steerControlType = car_params.getSteerControlType(); - actuators = car_control.getActuators(); - torqueLateral = steerControlType == cereal::CarParams::SteerControlType::TORQUE; - angleSteers = car_state.getSteeringAngleDeg(); - desiredCurvature = cs.getDesiredCurvature(); - curvature = cs.getCurvature(); - roll = sm["liveParameters"].getLiveParameters().getRoll(); - memoryUsagePercent = sm["deviceState"].getDeviceState().getMemoryUsagePercent(); - gpsAccuracy = is_gps_location_external ? gpsLocation.getHorizontalAccuracy() : 1.0; // External reports accuracy, internal does not. - altitude = gpsLocation.getAltitude(); - vEgo = car_state.getVEgo(); - aEgo = car_state.getAEgo(); - steeringTorqueEps = car_state.getSteeringTorqueEps(); - bearingAccuracyDeg = gpsLocation.getBearingAccuracyDeg(); - bearingDeg = gpsLocation.getBearingDeg(); - torquedUseParams = ltp.getUseParams(); - latAccelFactorFiltered = ltp.getLatAccelFactorFiltered(); - frictionCoefficientFiltered = ltp.getFrictionCoefficientFiltered(); - liveValid = ltp.getLiveValid(); } void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { HudRenderer::draw(p, surface_rect); - if (!reversing) { - // Bottom Dev UI - if (devUiInfo == 2) { - QRect rect_bottom(surface_rect.left(), surface_rect.bottom() - 60, surface_rect.width(), 61); - p.setPen(Qt::NoPen); - p.setBrush(QColor(0, 0, 0, 100)); - p.drawRect(rect_bottom); - drawBottomDevUI(p, rect_bottom.left(), rect_bottom.center().y()); - } - - // Right Dev UI - if (devUiInfo != 0) { - QRect rect_right(surface_rect.right() - (UI_BORDER_SIZE * 2), UI_BORDER_SIZE * 1.5, 184, 170); - drawRightDevUI(p, surface_rect.right() - 184 - UI_BORDER_SIZE * 2, UI_BORDER_SIZE * 2 + rect_right.height()); - } - } -} - -void HudRendererSP::drawText(QPainter &p, int x, int y, const QString &text, QColor color) { - QRect real_rect = p.fontMetrics().boundingRect(text); - real_rect.moveCenter({x, y - real_rect.height() / 2}); - p.setPen(color); - p.drawText(real_rect.x(), real_rect.bottom(), text); -} - -int HudRendererSP::drawRightDevUIElement(QPainter &p, int x, int y, const QString &value, const QString &label, const QString &units, QColor &color) { - - p.setFont(InterFont(28, QFont::Bold)); - x += 92; - y += 80; - drawText(p, x, y, label); - - p.setFont(InterFont(30 * 2, QFont::Bold)); - y += 65; - drawText(p, x, y, value, color); - - p.setFont(InterFont(28, QFont::Bold)); - - if (units.length() > 0) { - p.save(); - x += 120; - y -= 25; - p.translate(x, y); - p.rotate(-90); - drawText(p, 0, 0, units); - p.restore(); - } - - return 130; -} - -void HudRendererSP::drawRightDevUI(QPainter &p, int x, int y) { - int rh = 5; - int ry = y; - - UiElement dRelElement = DeveloperUi::getDRel(lead_status, lead_d_rel); - rh += drawRightDevUIElement(p, x, ry, dRelElement.value, dRelElement.label, dRelElement.units, dRelElement.color); - ry = y + rh; - - UiElement vRelElement = DeveloperUi::getVRel(lead_status, lead_v_rel, is_metric, speedUnit); - rh += drawRightDevUIElement(p, x, ry, vRelElement.value, vRelElement.label, vRelElement.units, vRelElement.color); - ry = y + rh; - - UiElement steeringAngleDegElement = DeveloperUi::getSteeringAngleDeg(angleSteers, latActive, steerOverride); - rh += drawRightDevUIElement(p, x, ry, steeringAngleDegElement.value, steeringAngleDegElement.label, steeringAngleDegElement.units, steeringAngleDegElement.color); - ry = y + rh; - - UiElement actuatorsOutputLateralElement = DeveloperUi::getActuatorsOutputLateral(steerControlType, actuators, desiredCurvature, vEgo, roll, latActive, steerOverride); - rh += drawRightDevUIElement(p, x, ry, actuatorsOutputLateralElement.value, actuatorsOutputLateralElement.label, actuatorsOutputLateralElement.units, actuatorsOutputLateralElement.color); - ry = y + rh; - - UiElement actualLateralAccelElement = DeveloperUi::getActualLateralAccel(curvature, vEgo, roll, latActive, steerOverride); - rh += drawRightDevUIElement(p, x, ry, actualLateralAccelElement.value, actualLateralAccelElement.label, actualLateralAccelElement.units, actualLateralAccelElement.color); -} - -int HudRendererSP::drawBottomDevUIElement(QPainter &p, int x, int y, const QString &value, const QString &label, const QString &units, QColor &color) { - p.setFont(InterFont(38, QFont::Bold)); - QFontMetrics fm(p.font()); - QRect init_rect = fm.boundingRect(label + " "); - QRect real_rect = fm.boundingRect(init_rect, 0, label + " "); - real_rect.moveCenter({x, y}); - - QRect init_rect2 = fm.boundingRect(value); - QRect real_rect2 = fm.boundingRect(init_rect2, 0, value); - real_rect2.moveTop(real_rect.top()); - real_rect2.moveLeft(real_rect.right() + 10); - - QRect init_rect3 = fm.boundingRect(units); - QRect real_rect3 = fm.boundingRect(init_rect3, 0, units); - real_rect3.moveTop(real_rect.top()); - real_rect3.moveLeft(real_rect2.right() + 10); - - p.setPen(Qt::white); - p.drawText(real_rect, Qt::AlignLeft | Qt::AlignVCenter, label); - - p.setPen(color); - p.drawText(real_rect2, Qt::AlignRight | Qt::AlignVCenter, value); - p.drawText(real_rect3, Qt::AlignLeft | Qt::AlignVCenter, units); - return 430; -} - -void HudRendererSP::drawBottomDevUI(QPainter &p, int x, int y) { - int rw = 90; - - UiElement aEgoElement = DeveloperUi::getAEgo(aEgo); - rw += drawBottomDevUIElement(p, rw, y, aEgoElement.value, aEgoElement.label, aEgoElement.units, aEgoElement.color); - - UiElement vEgoLeadElement = DeveloperUi::getVEgoLead(lead_status, lead_v_rel, vEgo, is_metric, speedUnit); - rw += drawBottomDevUIElement(p, rw, y, vEgoLeadElement.value, vEgoLeadElement.label, vEgoLeadElement.units, vEgoLeadElement.color); - - if (torqueLateral && torquedUseParams) { - UiElement frictionCoefficientFilteredElement = DeveloperUi::getFrictionCoefficientFiltered(frictionCoefficientFiltered, liveValid); - rw += drawBottomDevUIElement(p, rw, y, frictionCoefficientFilteredElement.value, frictionCoefficientFilteredElement.label, frictionCoefficientFilteredElement.units, frictionCoefficientFilteredElement.color); - - UiElement latAccelFactorFilteredElement = DeveloperUi::getLatAccelFactorFiltered(latAccelFactorFiltered, liveValid); - rw += drawBottomDevUIElement(p, rw, y, latAccelFactorFilteredElement.value, latAccelFactorFilteredElement.label, latAccelFactorFilteredElement.units, latAccelFactorFilteredElement.color); - } else { - UiElement steeringTorqueEpsElement = DeveloperUi::getSteeringTorqueEps(steeringTorqueEps); - rw += drawBottomDevUIElement(p, rw, y, steeringTorqueEpsElement.value, steeringTorqueEpsElement.label, steeringTorqueEpsElement.units, steeringTorqueEpsElement.color); - - UiElement bearingDegElement = DeveloperUi::getBearingDeg(bearingAccuracyDeg, bearingDeg); - rw += drawBottomDevUIElement(p, rw, y, bearingDegElement.value, bearingDegElement.label, bearingDegElement.units, bearingDegElement.color); - } - - UiElement altitudeElement = DeveloperUi::getAltitude(gpsAccuracy, altitude); - rw += drawBottomDevUIElement(p, rw, y, altitudeElement.value, altitudeElement.label, altitudeElement.units, altitudeElement.color); } diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.h b/selfdrive/ui/sunnypilot/qt/onroad/hud.h index 968789bc15..1e98cd3a52 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.h +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.h @@ -7,8 +7,9 @@ #pragma once +#include + #include "selfdrive/ui/qt/onroad/hud.h" -#include "selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h" class HudRendererSP : public HudRenderer { Q_OBJECT @@ -17,40 +18,4 @@ public: HudRendererSP(); void updateState(const UIState &s) override; void draw(QPainter &p, const QRect &surface_rect) override; - -private: - Params params; - void drawText(QPainter &p, int x, int y, const QString &text, QColor color = Qt::white); - void drawRightDevUI(QPainter &p, int x, int y); - int drawRightDevUIElement(QPainter &p, int x, int y, const QString &value, const QString &label, const QString &units, QColor &color); - int drawBottomDevUIElement(QPainter &p, int x, int y, const QString &value, const QString &label, const QString &units, QColor &color); - void drawBottomDevUI(QPainter &p, int x, int y); - - bool lead_status; - float lead_d_rel; - float lead_v_rel; - bool torqueLateral; - float angleSteers; - float desiredCurvature; - float curvature; - float roll; - int memoryUsagePercent; - int devUiInfo; - float gpsAccuracy; - float altitude; - float vEgo; - float aEgo; - float steeringTorqueEps; - float bearingAccuracyDeg; - float bearingDeg; - bool torquedUseParams; - float latAccelFactorFiltered; - float frictionCoefficientFiltered; - bool liveValid; - QString speedUnit; - bool latActive; - bool steerOverride; - bool reversing; - cereal::CarParams::SteerControlType steerControlType; - cereal::CarControl::Actuators::Reader actuators; }; diff --git a/selfdrive/ui/sunnypilot/ui.cc b/selfdrive/ui/sunnypilot/ui.cc index 1277195df1..b2701356cc 100644 --- a/selfdrive/ui/sunnypilot/ui.cc +++ b/selfdrive/ui/sunnypilot/ui.cc @@ -18,22 +18,13 @@ UIStateSP::UIStateSP(QObject *parent) : UIState(parent) { "modelV2", "controlsState", "liveCalibration", "radarState", "deviceState", "pandaStates", "carParams", "driverMonitoringState", "carState", "driverStateV2", "wideRoadCameraState", "managerState", "selfdriveState", "longitudinalPlan", - "modelManagerSP", "selfdriveStateSP", "longitudinalPlanSP", "backupManagerSP", - "carControl", "gpsLocationExternal", "gpsLocation", "liveTorqueParameters", - "carStateSP", "liveParameters" + "modelManagerSP", "selfdriveStateSP", "longitudinalPlanSP", "backupManagerSP" }); // update timer timer = new QTimer(this); QObject::connect(timer, &QTimer::timeout, this, &UIStateSP::update); timer->start(1000 / UI_FREQ); - - // Param watcher for UIScene param updates - param_watcher = new ParamWatcher(this); - connect(param_watcher, &ParamWatcher::paramChanged, [=](const QString ¶m_name, const QString ¶m_value) { - ui_update_params_sp(this); - }); - param_watcher->addParam("DevUIInfo"); } // This method overrides completely the update method from the parent class intentionally. @@ -48,11 +39,6 @@ void UIStateSP::update() { emit uiUpdate(*this); } -void ui_update_params_sp(UIStateSP *s) { - auto params = Params(); - s->scene.dev_ui_info = std::atoi(params.get("DevUIInfo").c_str()); -} - DeviceSP::DeviceSP(QObject *parent) : Device(parent) { QObject::connect(uiStateSP(), &UIStateSP::uiUpdate, this, &DeviceSP::update); QObject::connect(this, &Device::displayPowerChanged, this, &DeviceSP::handleDisplayPowerChanged); diff --git a/selfdrive/ui/sunnypilot/ui.h b/selfdrive/ui/sunnypilot/ui.h index 393f997cbd..cf8de1c4bb 100644 --- a/selfdrive/ui/sunnypilot/ui.h +++ b/selfdrive/ui/sunnypilot/ui.h @@ -13,7 +13,6 @@ #include "selfdrive/ui/sunnypilot/qt/network/sunnylink/models/role_model.h" #include "selfdrive/ui/sunnypilot/qt/network/sunnylink/models/sponsor_role_model.h" #include "selfdrive/ui/ui.h" -#include "selfdrive/ui/qt/util.h" class UIStateSP : public UIState { Q_OBJECT @@ -74,7 +73,6 @@ private slots: private: std::vector sunnylinkRoles = {}; std::vector sunnylinkUsers = {}; - ParamWatcher *param_watcher; }; UIStateSP *uiStateSP(); @@ -94,5 +92,3 @@ private: DeviceSP *deviceSP(); inline DeviceSP *device() { return deviceSP(); } - -void ui_update_params_sp(UIStateSP *s); diff --git a/selfdrive/ui/sunnypilot/ui_scene.h b/selfdrive/ui/sunnypilot/ui_scene.h deleted file mode 100644 index 93e0cd6c91..0000000000 --- a/selfdrive/ui/sunnypilot/ui_scene.h +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. - * - * This file is part of sunnypilot and is licensed under the MIT License. - * See the LICENSE.md file in the root directory for more details. - */ - -#pragma once - -typedef struct UISceneSP : UIScene { - int dev_ui_info = 0; -} UISceneSP; diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index 5b3872b3d4..e78b573b66 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -66,11 +66,6 @@ typedef struct UIScene { uint64_t started_frame; } UIScene; -#ifdef SUNNYPILOT -#include "sunnypilot/ui_scene.h" -#define UIScene UISceneSP -#endif - class UIState : public QObject { Q_OBJECT From 4f44d6e6436041a4f09a4d5c530405fc019c2492 Mon Sep 17 00:00:00 2001 From: Nayan Date: Fri, 12 Sep 2025 10:58:59 -0400 Subject: [PATCH 077/159] Reapply "UI: Developer UI" (#1238) (#1239) This reverts commit 1be13fdc55a24a72bc33703c7343c9421fdd0842. Co-authored-by: Jason Wen --- common/params_keys.h | 1 + selfdrive/ui/qt/onroad/alerts.cc | 9 + selfdrive/ui/qt/onroad/annotated_camera.h | 1 + selfdrive/ui/qt/onroad/driver_monitoring.cc | 5 + selfdrive/ui/sunnypilot/SConscript | 1 + .../qt/offroad/settings/visuals_panel.cc | 12 + .../qt/offroad/settings/visuals_panel.h | 1 + .../sunnypilot/qt/onroad/annotated_camera.cc | 5 + .../sunnypilot/qt/onroad/annotated_camera.h | 3 + .../qt/onroad/developer_ui/developer_ui.cc | 227 ++++++++++++++++++ .../qt/onroad/developer_ui/developer_ui.h | 31 +++ .../qt/onroad/developer_ui/ui_elements.h | 19 ++ selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 190 +++++++++++++++ selfdrive/ui/sunnypilot/qt/onroad/hud.h | 39 ++- selfdrive/ui/sunnypilot/ui.cc | 16 +- selfdrive/ui/sunnypilot/ui.h | 4 + selfdrive/ui/sunnypilot/ui_scene.h | 12 + selfdrive/ui/ui.h | 5 + 18 files changed, 578 insertions(+), 3 deletions(-) create mode 100644 selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.cc create mode 100644 selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h create mode 100644 selfdrive/ui/sunnypilot/qt/onroad/developer_ui/ui_elements.h create mode 100644 selfdrive/ui/sunnypilot/ui_scene.h diff --git a/common/params_keys.h b/common/params_keys.h index afb6b348eb..fc7842720b 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -146,6 +146,7 @@ inline static std::unordered_map keys = { {"CustomAccLongPressIncrement", {PERSISTENT | BACKUP, INT, "5"}}, {"CustomAccShortPressIncrement", {PERSISTENT | BACKUP, INT, "1"}}, {"DeviceBootMode", {PERSISTENT | BACKUP, INT, "0"}}, + {"DevUIInfo", {PERSISTENT | BACKUP, INT, "0"}}, {"EnableCopyparty", {PERSISTENT | BACKUP, BOOL}}, {"EnableGithubRunner", {PERSISTENT | BACKUP, BOOL}}, {"GithubRunnerSufficientVoltage", {CLEAR_ON_MANAGER_START , BOOL}}, diff --git a/selfdrive/ui/qt/onroad/alerts.cc b/selfdrive/ui/qt/onroad/alerts.cc index d6829c6b08..2e8f3612eb 100644 --- a/selfdrive/ui/qt/onroad/alerts.cc +++ b/selfdrive/ui/qt/onroad/alerts.cc @@ -4,6 +4,9 @@ #include #include "selfdrive/ui/qt/util.h" +#ifdef SUNNYPILOT +#include "selfdrive/ui/sunnypilot/ui.h" +#endif void OnroadAlerts::updateState(const UIState &s) { Alert a = getAlert(*(s.sm), s.scene.started_frame); @@ -73,6 +76,12 @@ void OnroadAlerts::paintEvent(QPaintEvent *event) { } QRect r = QRect(0 + margin, height() - h + margin, width() - margin*2, h - margin*2); +#ifdef SUNNYPILOT + const int dev_ui_info = uiStateSP()->scene.dev_ui_info; + const int adjustment = dev_ui_info > 1 && alert.size != cereal::SelfdriveState::AlertSize::FULL ? 30 : 0; + r = QRect(0 + margin, height() - h + margin - adjustment, width() - margin*2, h - margin*2); +#endif + QPainter p(this); // draw background + gradient diff --git a/selfdrive/ui/qt/onroad/annotated_camera.h b/selfdrive/ui/qt/onroad/annotated_camera.h index e3ca837907..5d9d21ab6b 100644 --- a/selfdrive/ui/qt/onroad/annotated_camera.h +++ b/selfdrive/ui/qt/onroad/annotated_camera.h @@ -12,6 +12,7 @@ #include "selfdrive/ui/sunnypilot/qt/onroad/model.h" #define ExperimentalButton ExperimentalButtonSP #define ModelRenderer ModelRendererSP +#define HudRenderer HudRendererSP #else #include "selfdrive/ui/qt/onroad/buttons.h" #include "selfdrive/ui/qt/onroad/hud.h" diff --git a/selfdrive/ui/qt/onroad/driver_monitoring.cc b/selfdrive/ui/qt/onroad/driver_monitoring.cc index 49f2c950b4..e67c483047 100644 --- a/selfdrive/ui/qt/onroad/driver_monitoring.cc +++ b/selfdrive/ui/qt/onroad/driver_monitoring.cc @@ -73,6 +73,11 @@ void DriverMonitorRenderer::draw(QPainter &painter, const QRect &surface_rect) { float y = surface_rect.height() - offset; float opacity = is_active ? 0.65f : 0.2f; +#ifdef SUNNYPILOT + const int dev_ui_info = uiStateSP()->scene.dev_ui_info; + y -= dev_ui_info > 1 ? 50 : 0; +#endif + drawIcon(painter, QPoint(x, y), dm_img, QColor(0, 0, 0, 70), opacity); QPointF keypoints[std::size(DEFAULT_FACE_KPTS_3D)]; diff --git a/selfdrive/ui/sunnypilot/SConscript b/selfdrive/ui/sunnypilot/SConscript index 2f3c8ddd8d..807bf02478 100644 --- a/selfdrive/ui/sunnypilot/SConscript +++ b/selfdrive/ui/sunnypilot/SConscript @@ -39,6 +39,7 @@ qt_src = [ "sunnypilot/qt/offroad/settings/visuals_panel.cc", "sunnypilot/qt/onroad/annotated_camera.cc", "sunnypilot/qt/onroad/buttons.cc", + "sunnypilot/qt/onroad/developer_ui/developer_ui.cc", "sunnypilot/qt/onroad/hud.cc", "sunnypilot/qt/onroad/model.cc", "sunnypilot/qt/onroad/onroad_home.cc", diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc index dd2f05416d..c3aaf12d22 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc @@ -72,6 +72,15 @@ VisualsPanel::VisualsPanel(QWidget *parent) : QWidget(parent) { list->addItem(chevron_info_settings); param_watcher->addParam("ChevronInfo"); + // Visuals: Developer UI Info (Dev UI) + std::vector dev_ui_settings_texts{tr("Off"), tr("Right"), tr("Right &&\nBottom")}; + dev_ui_settings = new ButtonParamControlSP( + "DevUIInfo", tr("Developer UI"), tr("Display real-time parameters and metrics from various sources."), + "", + dev_ui_settings_texts, + 380); + list->addItem(dev_ui_settings); + sunnypilotScroller = new ScrollViewSP(list, this); vlayout->addWidget(sunnypilotScroller); @@ -90,4 +99,7 @@ void VisualsPanel::paramsRefresh() { if (chevron_info_settings) { chevron_info_settings->refresh(); } + if (dev_ui_settings) { + dev_ui_settings->refresh(); + } } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.h index f342662c22..30ff31c301 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.h @@ -28,4 +28,5 @@ protected: std::map toggles; ParamWatcher * param_watcher; ButtonParamControlSP *chevron_info_settings; + ButtonParamControlSP *dev_ui_settings; }; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.cc b/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.cc index 3721a3d198..1d5567161a 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.cc @@ -14,3 +14,8 @@ AnnotatedCameraWidgetSP::AnnotatedCameraWidgetSP(VisionStreamType type, QWidget void AnnotatedCameraWidgetSP::updateState(const UIState &s) { AnnotatedCameraWidget::updateState(s); } + +void AnnotatedCameraWidgetSP::showEvent(QShowEvent *event) { + AnnotatedCameraWidget::showEvent(event); + ui_update_params_sp(uiState()); +} diff --git a/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.h b/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.h index 46ce7d4be3..8c0a385657 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.h +++ b/selfdrive/ui/sunnypilot/qt/onroad/annotated_camera.h @@ -15,4 +15,7 @@ class AnnotatedCameraWidgetSP : public AnnotatedCameraWidget { public: explicit AnnotatedCameraWidgetSP(VisionStreamType type, QWidget *parent = nullptr); void updateState(const UIState &s) override; + +protected: + void showEvent(QShowEvent *event) override; }; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.cc b/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.cc new file mode 100644 index 0000000000..292ba6f7bb --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.cc @@ -0,0 +1,227 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ +#include + +#include "common/util.h" +#include "selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h" + + +// Add Relative Distance to Primary Lead Car +// Unit: Meters +UiElement DeveloperUi::getDRel(bool lead_status, float lead_d_rel) { + QString value = lead_status ? QString::number(lead_d_rel, 'f', 0) : "-"; + QColor color = QColor(255, 255, 255, 255); + + if (lead_status) { + // Orange if close, Red if very close + if (lead_d_rel < 5) { + color = QColor(255, 0, 0, 255); + } else if (lead_d_rel < 15) { + color = QColor(255, 188, 0, 255); + } + } + + return UiElement(value, "REL DIST", "m", color); +} + +// Add Relative Velocity vs Primary Lead Car +// Unit: kph if metric, else mph +UiElement DeveloperUi::getVRel(bool lead_status, float lead_v_rel, bool is_metric, const QString &speed_unit) { + QString value = lead_status ? QString::number(lead_v_rel * (is_metric ? MS_TO_KPH : MS_TO_MPH), 'f', 0) : "-"; + QColor color = QColor(255, 255, 255, 255); + + if (lead_status) { + // Red if approaching faster than 10mph + // Orange if approaching (negative) + if (lead_v_rel < -4.4704) { + color = QColor(255, 0, 0, 255); + } else if (lead_v_rel < 0) { + color = QColor(255, 188, 0, 255); + } + } + + return UiElement(value, "REL SPEED", speed_unit, color); +} + +// Add Real Steering Angle +// Unit: Degrees +UiElement DeveloperUi::getSteeringAngleDeg(float angle_steers, bool lat_active, bool steer_override) { + QString value = QString("%1%2%3").arg(QString::number(angle_steers, 'f', 1)).arg("°").arg(""); + QColor color = lat_active ? (steer_override ? QColor(0x91, 0x9b, 0x95, 0xff) : QColor(0, 255, 0, 255)) : QColor(255, 255, 255, 255); + + // Red if large steering angle + // Orange if moderate steering angle + if (std::fabs(angle_steers) > 180) { + color = QColor(255, 0, 0, 255); + } else if (std::fabs(angle_steers) > 90) { + color = QColor(255, 188, 0, 255); + } + + return UiElement(value, "REAL STEER", "", color); +} + +// Add Actual Lateral Acceleration (roll compensated) when using Torque +// Unit: m/s² +UiElement DeveloperUi::getActualLateralAccel(float curvature, float v_ego, float roll, bool lat_active, bool steer_override) { + double actualLateralAccel = (curvature * pow(v_ego, 2)) - (roll * 9.81); + + QString value = QString::number(actualLateralAccel, 'f', 2); + QColor color = lat_active ? (steer_override ? QColor(0x91, 0x9b, 0x95, 0xff) : QColor(0, 255, 0, 255)) : QColor(255, 255, 255, 255); + + return UiElement(value, "ACTUAL L.A.", "m/s²", color); +} + +// Add Desired Steering Angle when using PID +// Unit: Degrees +UiElement DeveloperUi::getSteeringAngleDesiredDeg(bool lat_active, float steer_angle_desired, float angle_steers) { + QString value = lat_active ? QString("%1%2%3").arg(QString::number(steer_angle_desired, 'f', 1)).arg("°").arg("") : "-"; + QColor color = QColor(255, 255, 255, 255); + + if (lat_active) { + // Red if large steering angle + // Orange if moderate steering angle + if (std::fabs(angle_steers) > 180) { + color = QColor(255, 0, 0, 255); + } else if (std::fabs(angle_steers) > 90) { + color = QColor(255, 188, 0, 255); + } else { + color = QColor(0, 255, 0, 255); + } + } + + return UiElement(value, "DESIRED STEER", "", color); +} + +// Add Device Memory (RAM) Usage +// Unit: Percent +UiElement DeveloperUi::getMemoryUsagePercent(int memory_usage_percent) { + QString value = QString("%1%2").arg(QString::number(memory_usage_percent, 'd', 0)).arg("%"); + QColor color = (memory_usage_percent > 85) ? QColor(255, 188, 0, 255) : QColor(255, 255, 255, 255); + + return UiElement(value, "RAM", "", color); +} + +// Add Vehicle Current Acceleration +// Unit: m/s² +UiElement DeveloperUi::getAEgo(float a_ego) { + QString value = QString::number(a_ego, 'f', 1); + QColor color = QColor(255, 255, 255, 255); + + return UiElement(value, "ACC.", "m/s²", color); +} + +// Add Relative Velocity to Primary Lead Car +// Unit: kph if metric, else mph +UiElement DeveloperUi::getVEgoLead(bool lead_status, float lead_v_rel, float v_ego, bool is_metric, const QString &speed_unit) { + QString value = lead_status ? QString::number((lead_v_rel + v_ego) * (is_metric ? MS_TO_KPH : MS_TO_MPH), 'f', 0) : "-"; + QColor color = QColor(255, 255, 255, 255); + + if (lead_status) { + // Red if approaching faster than 10mph + // Orange if approaching (negative) + if (lead_v_rel < -4.4704) { + color = QColor(255, 0, 0, 255); + } else if (lead_v_rel < 0) { + color = QColor(255, 188, 0, 255); + } + } + + return UiElement(value, "L.S.", speed_unit, color); +} + +// Add Friction Coefficient Raw from torqued +// Unit: None +UiElement DeveloperUi::getFrictionCoefficientFiltered(float friction_coefficient_filtered, bool live_valid) { + QString value = QString::number(friction_coefficient_filtered, 'f', 3); + QColor color = live_valid ? QColor(0, 255, 0, 255) : QColor(255, 255, 255, 255); + + return UiElement(value, "FRIC.", "", color); +} + +// Add Lateral Acceleration Factor Raw from torqued +// Unit: m/s² +UiElement DeveloperUi::getLatAccelFactorFiltered(float lat_accel_factor_filtered, bool live_valid) { + QString value = QString::number(lat_accel_factor_filtered, 'f', 3); + QColor color = live_valid ? QColor(0, 255, 0, 255) : QColor(255, 255, 255, 255); + + return UiElement(value, "L.A.", "m/s²", color); +} + +// Add Steering Torque from Car EPS +// Unit: Newton Meters +UiElement DeveloperUi::getSteeringTorqueEps(float steering_torque_eps) { + QString value = QString::number(std::fabs(steering_torque_eps), 'f', 1); + QColor color = QColor(255, 255, 255, 255); + + return UiElement(value, "E.T.", "N·dm", color); +} + +// Add Bearing Degree and Direction from Car (Compass) +// Unit: Meters +UiElement DeveloperUi::getBearingDeg(float bearing_accuracy_deg, float bearing_deg) { + QString value = (bearing_accuracy_deg != 180.00) ? QString("%1%2%3").arg(QString::number(bearing_deg, 'd', 0)).arg("°").arg("") : "-"; + QColor color = QColor(255, 255, 255, 255); + QString dir_value; + + if (bearing_accuracy_deg != 180.00) { + if (((bearing_deg >= 337.5) && (bearing_deg <= 360)) || ((bearing_deg >= 0) && (bearing_deg <= 22.5))) { + dir_value = "N"; + } else if ((bearing_deg > 22.5) && (bearing_deg < 67.5)) { + dir_value = "NE"; + } else if ((bearing_deg >= 67.5) && (bearing_deg <= 112.5)) { + dir_value = "E"; + } else if ((bearing_deg > 112.5) && (bearing_deg < 157.5)) { + dir_value = "SE"; + } else if ((bearing_deg >= 157.5) && (bearing_deg <= 202.5)) { + dir_value = "S"; + } else if ((bearing_deg > 202.5) && (bearing_deg < 247.5)) { + dir_value = "SW"; + } else if ((bearing_deg >= 247.5) && (bearing_deg <= 292.5)) { + dir_value = "W"; + } else if ((bearing_deg > 292.5) && (bearing_deg < 337.5)) { + dir_value = "NW"; + } + } else { + dir_value = "OFF"; + } + + return UiElement(QString("%1 | %2").arg(dir_value).arg(value), "B.D.", "", color); +} + +// Add Altitude of Current Location +// Unit: Meters +UiElement DeveloperUi::getAltitude(float gps_accuracy, float altitude) { + QString value = (gps_accuracy != 0.00) ? QString::number(altitude, 'f', 1) : "-"; + QColor color = QColor(255, 255, 255, 255); + + return UiElement(value, "ALT.", "m", color); +} + +// Add Actuators Output +// Unit: Degree (angle) or m/s² (torque) +UiElement DeveloperUi::getActuatorsOutputLateral(cereal::CarParams::SteerControlType steerControlType, + cereal::CarControl::Actuators::Reader &actuators, + float desiredCurvature, float v_ego, float roll, bool lat_active, bool steer_override) { + QString label; + QString value; + QString unit; + + if (steerControlType == cereal::CarParams::SteerControlType::ANGLE) { + label = "DESIRED STEER"; + value = QString("%1%2%3").arg(QString::number(actuators.getSteeringAngleDeg(), 'f', 1)).arg("°").arg(""); + } else { + label = "DESIRED L.A."; + double desiredLateralAccel = (desiredCurvature * pow(v_ego, 2)) - (roll * 9.81); + value = QString::number(desiredLateralAccel, 'f', 2); + unit = "m/s²"; + } + + value = lat_active ? value : "-"; + QColor color = lat_active ? (steer_override ? QColor(0x91, 0x9b, 0x95, 0xff) : QColor(0, 255, 0, 255)) : QColor(255, 255, 255, 255); + + return UiElement(value, label, unit, color); +} diff --git a/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h b/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h new file mode 100644 index 0000000000..0c5c472209 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ +#pragma once + +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/sunnypilot/qt/onroad/developer_ui/ui_elements.h" + +class DeveloperUi { + +public: + static UiElement getDRel(bool lead_status, float lead_d_rel); + static UiElement getVRel(bool lead_status, float lead_v_rel, bool is_metric, const QString &speed_unit); + static UiElement getSteeringAngleDeg(float angle_steers, bool lat_active, bool steer_override); + static UiElement getActualLateralAccel(float curvature, float v_ego, float roll, bool lat_active, bool steer_override); + static UiElement getSteeringAngleDesiredDeg(bool lat_active, float steer_angle_desired, float angle_steers); + static UiElement getMemoryUsagePercent(int memory_usage_percent); + static UiElement getAEgo(float a_ego); + static UiElement getVEgoLead(bool lead_status, float lead_v_rel, float v_ego, bool is_metric, const QString &speed_unit); + static UiElement getFrictionCoefficientFiltered(float friction_coefficient_filtered, bool live_valid); + static UiElement getLatAccelFactorFiltered(float lat_accel_factor_filtered, bool live_valid); + static UiElement getSteeringTorqueEps(float steering_torque_eps); + static UiElement getBearingDeg(float bearing_accuracy_deg, float bearing_deg); + static UiElement getAltitude(float gps_accuracy, float altitude); + static UiElement getActuatorsOutputLateral(cereal::CarParams::SteerControlType steerControlType, + cereal::CarControl::Actuators::Reader &actuators, + float desiredCurvature, float v_ego, float roll, bool lat_active, bool steer_override); +}; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/ui_elements.h b/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/ui_elements.h new file mode 100644 index 0000000000..3711e5ac05 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/onroad/developer_ui/ui_elements.h @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ +#pragma once + +#include + +struct UiElement { + QString value{}; + QString label{}; + QString units{}; + QColor color{}; + + explicit UiElement(const QString &value = "", const QString &label = "", const QString &units = "", const QColor &color = QColor(255, 255, 255, 255)) + : value(value), label(label), units(units), color(color) {} +}; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index 233ca59f98..9ead933d04 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -7,12 +7,202 @@ #include "selfdrive/ui/sunnypilot/qt/onroad/hud.h" +#include "selfdrive/ui/qt/util.h" + + HudRendererSP::HudRendererSP() {} void HudRendererSP::updateState(const UIState &s) { HudRenderer::updateState(s); + + const SubMaster &sm = *(s.sm); + const bool cs_alive = sm.alive("controlsState"); + const auto cs = sm["controlsState"].getControlsState(); + const auto car_state = sm["carState"].getCarState(); + const auto car_control = sm["carControl"].getCarControl(); + const auto radar_state = sm["radarState"].getRadarState(); + const auto is_gps_location_external = sm.rcv_frame("gpsLocationExternal") > 1; + const auto gpsLocation = is_gps_location_external ? sm["gpsLocationExternal"].getGpsLocationExternal() : sm["gpsLocation"].getGpsLocation(); + const auto ltp = sm["liveTorqueParameters"].getLiveTorqueParameters(); + const auto car_params = sm["carParams"].getCarParams(); + + static int reverse_delay = 0; + bool reverse_allowed = false; + if (int(car_state.getGearShifter()) != 4) { + reverse_delay = 0; + reverse_allowed = false; + } else { + reverse_delay += 50; + if (reverse_delay >= 1000) { + reverse_allowed = true; + } + } + + reversing = reverse_allowed; + is_metric = s.scene.is_metric; + + // Handle older routes where vEgoCluster is not set + v_ego_cluster_seen = v_ego_cluster_seen || car_state.getVEgoCluster() != 0.0; + float v_ego = v_ego_cluster_seen ? car_state.getVEgoCluster() : car_state.getVEgo(); + speed = cs_alive ? std::max(0.0, v_ego) : 0.0; + speed *= is_metric ? MS_TO_KPH : MS_TO_MPH; + + latActive = car_control.getLatActive(); + steerOverride = car_state.getSteeringPressed(); + + devUiInfo = s.scene.dev_ui_info; + + speedUnit = is_metric ? tr("km/h") : tr("mph"); + lead_d_rel = radar_state.getLeadOne().getDRel(); + lead_v_rel = radar_state.getLeadOne().getVRel(); + lead_status = radar_state.getLeadOne().getStatus(); + steerControlType = car_params.getSteerControlType(); + actuators = car_control.getActuators(); + torqueLateral = steerControlType == cereal::CarParams::SteerControlType::TORQUE; + angleSteers = car_state.getSteeringAngleDeg(); + desiredCurvature = cs.getDesiredCurvature(); + curvature = cs.getCurvature(); + roll = sm["liveParameters"].getLiveParameters().getRoll(); + memoryUsagePercent = sm["deviceState"].getDeviceState().getMemoryUsagePercent(); + gpsAccuracy = is_gps_location_external ? gpsLocation.getHorizontalAccuracy() : 1.0; // External reports accuracy, internal does not. + altitude = gpsLocation.getAltitude(); + vEgo = car_state.getVEgo(); + aEgo = car_state.getAEgo(); + steeringTorqueEps = car_state.getSteeringTorqueEps(); + bearingAccuracyDeg = gpsLocation.getBearingAccuracyDeg(); + bearingDeg = gpsLocation.getBearingDeg(); + torquedUseParams = ltp.getUseParams(); + latAccelFactorFiltered = ltp.getLatAccelFactorFiltered(); + frictionCoefficientFiltered = ltp.getFrictionCoefficientFiltered(); + liveValid = ltp.getLiveValid(); } void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { HudRenderer::draw(p, surface_rect); + if (!reversing) { + // Bottom Dev UI + if (devUiInfo == 2) { + QRect rect_bottom(surface_rect.left(), surface_rect.bottom() - 60, surface_rect.width(), 61); + p.setPen(Qt::NoPen); + p.setBrush(QColor(0, 0, 0, 100)); + p.drawRect(rect_bottom); + drawBottomDevUI(p, rect_bottom.left(), rect_bottom.center().y()); + } + + // Right Dev UI + if (devUiInfo != 0) { + QRect rect_right(surface_rect.right() - (UI_BORDER_SIZE * 2), UI_BORDER_SIZE * 1.5, 184, 170); + drawRightDevUI(p, surface_rect.right() - 184 - UI_BORDER_SIZE * 2, UI_BORDER_SIZE * 2 + rect_right.height()); + } + } +} + +void HudRendererSP::drawText(QPainter &p, int x, int y, const QString &text, QColor color) { + QRect real_rect = p.fontMetrics().boundingRect(text); + real_rect.moveCenter({x, y - real_rect.height() / 2}); + p.setPen(color); + p.drawText(real_rect.x(), real_rect.bottom(), text); +} + +int HudRendererSP::drawRightDevUIElement(QPainter &p, int x, int y, const QString &value, const QString &label, const QString &units, QColor &color) { + + p.setFont(InterFont(28, QFont::Bold)); + x += 92; + y += 80; + drawText(p, x, y, label); + + p.setFont(InterFont(30 * 2, QFont::Bold)); + y += 65; + drawText(p, x, y, value, color); + + p.setFont(InterFont(28, QFont::Bold)); + + if (units.length() > 0) { + p.save(); + x += 120; + y -= 25; + p.translate(x, y); + p.rotate(-90); + drawText(p, 0, 0, units); + p.restore(); + } + + return 130; +} + +void HudRendererSP::drawRightDevUI(QPainter &p, int x, int y) { + int rh = 5; + int ry = y; + + UiElement dRelElement = DeveloperUi::getDRel(lead_status, lead_d_rel); + rh += drawRightDevUIElement(p, x, ry, dRelElement.value, dRelElement.label, dRelElement.units, dRelElement.color); + ry = y + rh; + + UiElement vRelElement = DeveloperUi::getVRel(lead_status, lead_v_rel, is_metric, speedUnit); + rh += drawRightDevUIElement(p, x, ry, vRelElement.value, vRelElement.label, vRelElement.units, vRelElement.color); + ry = y + rh; + + UiElement steeringAngleDegElement = DeveloperUi::getSteeringAngleDeg(angleSteers, latActive, steerOverride); + rh += drawRightDevUIElement(p, x, ry, steeringAngleDegElement.value, steeringAngleDegElement.label, steeringAngleDegElement.units, steeringAngleDegElement.color); + ry = y + rh; + + UiElement actuatorsOutputLateralElement = DeveloperUi::getActuatorsOutputLateral(steerControlType, actuators, desiredCurvature, vEgo, roll, latActive, steerOverride); + rh += drawRightDevUIElement(p, x, ry, actuatorsOutputLateralElement.value, actuatorsOutputLateralElement.label, actuatorsOutputLateralElement.units, actuatorsOutputLateralElement.color); + ry = y + rh; + + UiElement actualLateralAccelElement = DeveloperUi::getActualLateralAccel(curvature, vEgo, roll, latActive, steerOverride); + rh += drawRightDevUIElement(p, x, ry, actualLateralAccelElement.value, actualLateralAccelElement.label, actualLateralAccelElement.units, actualLateralAccelElement.color); +} + +int HudRendererSP::drawBottomDevUIElement(QPainter &p, int x, int y, const QString &value, const QString &label, const QString &units, QColor &color) { + p.setFont(InterFont(38, QFont::Bold)); + QFontMetrics fm(p.font()); + QRect init_rect = fm.boundingRect(label + " "); + QRect real_rect = fm.boundingRect(init_rect, 0, label + " "); + real_rect.moveCenter({x, y}); + + QRect init_rect2 = fm.boundingRect(value); + QRect real_rect2 = fm.boundingRect(init_rect2, 0, value); + real_rect2.moveTop(real_rect.top()); + real_rect2.moveLeft(real_rect.right() + 10); + + QRect init_rect3 = fm.boundingRect(units); + QRect real_rect3 = fm.boundingRect(init_rect3, 0, units); + real_rect3.moveTop(real_rect.top()); + real_rect3.moveLeft(real_rect2.right() + 10); + + p.setPen(Qt::white); + p.drawText(real_rect, Qt::AlignLeft | Qt::AlignVCenter, label); + + p.setPen(color); + p.drawText(real_rect2, Qt::AlignRight | Qt::AlignVCenter, value); + p.drawText(real_rect3, Qt::AlignLeft | Qt::AlignVCenter, units); + return 430; +} + +void HudRendererSP::drawBottomDevUI(QPainter &p, int x, int y) { + int rw = 90; + + UiElement aEgoElement = DeveloperUi::getAEgo(aEgo); + rw += drawBottomDevUIElement(p, rw, y, aEgoElement.value, aEgoElement.label, aEgoElement.units, aEgoElement.color); + + UiElement vEgoLeadElement = DeveloperUi::getVEgoLead(lead_status, lead_v_rel, vEgo, is_metric, speedUnit); + rw += drawBottomDevUIElement(p, rw, y, vEgoLeadElement.value, vEgoLeadElement.label, vEgoLeadElement.units, vEgoLeadElement.color); + + if (torqueLateral && torquedUseParams) { + UiElement frictionCoefficientFilteredElement = DeveloperUi::getFrictionCoefficientFiltered(frictionCoefficientFiltered, liveValid); + rw += drawBottomDevUIElement(p, rw, y, frictionCoefficientFilteredElement.value, frictionCoefficientFilteredElement.label, frictionCoefficientFilteredElement.units, frictionCoefficientFilteredElement.color); + + UiElement latAccelFactorFilteredElement = DeveloperUi::getLatAccelFactorFiltered(latAccelFactorFiltered, liveValid); + rw += drawBottomDevUIElement(p, rw, y, latAccelFactorFilteredElement.value, latAccelFactorFilteredElement.label, latAccelFactorFilteredElement.units, latAccelFactorFilteredElement.color); + } else { + UiElement steeringTorqueEpsElement = DeveloperUi::getSteeringTorqueEps(steeringTorqueEps); + rw += drawBottomDevUIElement(p, rw, y, steeringTorqueEpsElement.value, steeringTorqueEpsElement.label, steeringTorqueEpsElement.units, steeringTorqueEpsElement.color); + + UiElement bearingDegElement = DeveloperUi::getBearingDeg(bearingAccuracyDeg, bearingDeg); + rw += drawBottomDevUIElement(p, rw, y, bearingDegElement.value, bearingDegElement.label, bearingDegElement.units, bearingDegElement.color); + } + + UiElement altitudeElement = DeveloperUi::getAltitude(gpsAccuracy, altitude); + rw += drawBottomDevUIElement(p, rw, y, altitudeElement.value, altitudeElement.label, altitudeElement.units, altitudeElement.color); } diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.h b/selfdrive/ui/sunnypilot/qt/onroad/hud.h index 1e98cd3a52..968789bc15 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.h +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.h @@ -7,9 +7,8 @@ #pragma once -#include - #include "selfdrive/ui/qt/onroad/hud.h" +#include "selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h" class HudRendererSP : public HudRenderer { Q_OBJECT @@ -18,4 +17,40 @@ public: HudRendererSP(); void updateState(const UIState &s) override; void draw(QPainter &p, const QRect &surface_rect) override; + +private: + Params params; + void drawText(QPainter &p, int x, int y, const QString &text, QColor color = Qt::white); + void drawRightDevUI(QPainter &p, int x, int y); + int drawRightDevUIElement(QPainter &p, int x, int y, const QString &value, const QString &label, const QString &units, QColor &color); + int drawBottomDevUIElement(QPainter &p, int x, int y, const QString &value, const QString &label, const QString &units, QColor &color); + void drawBottomDevUI(QPainter &p, int x, int y); + + bool lead_status; + float lead_d_rel; + float lead_v_rel; + bool torqueLateral; + float angleSteers; + float desiredCurvature; + float curvature; + float roll; + int memoryUsagePercent; + int devUiInfo; + float gpsAccuracy; + float altitude; + float vEgo; + float aEgo; + float steeringTorqueEps; + float bearingAccuracyDeg; + float bearingDeg; + bool torquedUseParams; + float latAccelFactorFiltered; + float frictionCoefficientFiltered; + bool liveValid; + QString speedUnit; + bool latActive; + bool steerOverride; + bool reversing; + cereal::CarParams::SteerControlType steerControlType; + cereal::CarControl::Actuators::Reader actuators; }; diff --git a/selfdrive/ui/sunnypilot/ui.cc b/selfdrive/ui/sunnypilot/ui.cc index b2701356cc..1277195df1 100644 --- a/selfdrive/ui/sunnypilot/ui.cc +++ b/selfdrive/ui/sunnypilot/ui.cc @@ -18,13 +18,22 @@ UIStateSP::UIStateSP(QObject *parent) : UIState(parent) { "modelV2", "controlsState", "liveCalibration", "radarState", "deviceState", "pandaStates", "carParams", "driverMonitoringState", "carState", "driverStateV2", "wideRoadCameraState", "managerState", "selfdriveState", "longitudinalPlan", - "modelManagerSP", "selfdriveStateSP", "longitudinalPlanSP", "backupManagerSP" + "modelManagerSP", "selfdriveStateSP", "longitudinalPlanSP", "backupManagerSP", + "carControl", "gpsLocationExternal", "gpsLocation", "liveTorqueParameters", + "carStateSP", "liveParameters" }); // update timer timer = new QTimer(this); QObject::connect(timer, &QTimer::timeout, this, &UIStateSP::update); timer->start(1000 / UI_FREQ); + + // Param watcher for UIScene param updates + param_watcher = new ParamWatcher(this); + connect(param_watcher, &ParamWatcher::paramChanged, [=](const QString ¶m_name, const QString ¶m_value) { + ui_update_params_sp(this); + }); + param_watcher->addParam("DevUIInfo"); } // This method overrides completely the update method from the parent class intentionally. @@ -39,6 +48,11 @@ void UIStateSP::update() { emit uiUpdate(*this); } +void ui_update_params_sp(UIStateSP *s) { + auto params = Params(); + s->scene.dev_ui_info = std::atoi(params.get("DevUIInfo").c_str()); +} + DeviceSP::DeviceSP(QObject *parent) : Device(parent) { QObject::connect(uiStateSP(), &UIStateSP::uiUpdate, this, &DeviceSP::update); QObject::connect(this, &Device::displayPowerChanged, this, &DeviceSP::handleDisplayPowerChanged); diff --git a/selfdrive/ui/sunnypilot/ui.h b/selfdrive/ui/sunnypilot/ui.h index cf8de1c4bb..393f997cbd 100644 --- a/selfdrive/ui/sunnypilot/ui.h +++ b/selfdrive/ui/sunnypilot/ui.h @@ -13,6 +13,7 @@ #include "selfdrive/ui/sunnypilot/qt/network/sunnylink/models/role_model.h" #include "selfdrive/ui/sunnypilot/qt/network/sunnylink/models/sponsor_role_model.h" #include "selfdrive/ui/ui.h" +#include "selfdrive/ui/qt/util.h" class UIStateSP : public UIState { Q_OBJECT @@ -73,6 +74,7 @@ private slots: private: std::vector sunnylinkRoles = {}; std::vector sunnylinkUsers = {}; + ParamWatcher *param_watcher; }; UIStateSP *uiStateSP(); @@ -92,3 +94,5 @@ private: DeviceSP *deviceSP(); inline DeviceSP *device() { return deviceSP(); } + +void ui_update_params_sp(UIStateSP *s); diff --git a/selfdrive/ui/sunnypilot/ui_scene.h b/selfdrive/ui/sunnypilot/ui_scene.h new file mode 100644 index 0000000000..93e0cd6c91 --- /dev/null +++ b/selfdrive/ui/sunnypilot/ui_scene.h @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +typedef struct UISceneSP : UIScene { + int dev_ui_info = 0; +} UISceneSP; diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index e78b573b66..5b3872b3d4 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -66,6 +66,11 @@ typedef struct UIScene { uint64_t started_frame; } UIScene; +#ifdef SUNNYPILOT +#include "sunnypilot/ui_scene.h" +#define UIScene UISceneSP +#endif + class UIState : public QObject { Q_OBJECT From bffb2fb6fabd384a39517e46d841b45b97a58210 Mon Sep 17 00:00:00 2001 From: DevTekVE Date: Sun, 14 Sep 2025 20:22:51 +0200 Subject: [PATCH 078/159] bugfix: param store to support the latest param changes (#1244) * bugfix: update parameter handling to use custom CarControlSP.Param and improve param retrieval * bump opendbc --- cereal/custom.capnp | 15 +++++++- opendbc_repo | 2 +- .../selfdrive/controls/controlsd_ext.py | 2 +- .../selfdrive/controls/lib/param_store.py | 36 ++++++++++--------- sunnypilot/sunnylink/utils.py | 18 ++++++++-- 5 files changed, 50 insertions(+), 23 deletions(-) diff --git a/cereal/custom.capnp b/cereal/custom.capnp index 5468e0f39d..8d4bc3cb82 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -202,7 +202,20 @@ struct CarControlSP @0xa5cd762cd951a455 { struct Param { key @0 :Text; - value @1 :Text; + type @2 :ParamType; + value @3 :Data; + + valueDEPRECATED @1 :Text; # The data type change may cause issues with backwards compatibility. + } + + enum ParamType { + string @0; + bool @1; + int @2; + float @3; + time @4; + json @5; + bytes @6; } } diff --git a/opendbc_repo b/opendbc_repo index c705ebf987..189dc3f78c 160000 --- a/opendbc_repo +++ b/opendbc_repo @@ -1 +1 @@ -Subproject commit c705ebf9872193e97f9498868cead9e9affdee15 +Subproject commit 189dc3f78c3b2eeb0402e69760602aa7149d05c9 diff --git a/sunnypilot/selfdrive/controls/controlsd_ext.py b/sunnypilot/selfdrive/controls/controlsd_ext.py index 7e06ac77c1..a096b7dc8c 100644 --- a/sunnypilot/selfdrive/controls/controlsd_ext.py +++ b/sunnypilot/selfdrive/controls/controlsd_ext.py @@ -73,7 +73,7 @@ class ControlsExt: # MADS state CC_SP.mads = sm['selfdriveStateSP'].mads - CC_SP.params = self.param_store.publish() + CC_SP.params = self.param_store.param_list return CC_SP diff --git a/sunnypilot/selfdrive/controls/lib/param_store.py b/sunnypilot/selfdrive/controls/lib/param_store.py index 2ef3473187..65a0175340 100644 --- a/sunnypilot/selfdrive/controls/lib/param_store.py +++ b/sunnypilot/selfdrive/controls/lib/param_store.py @@ -4,39 +4,41 @@ Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. This file is part of sunnypilot and is licensed under the MIT License. See the LICENSE.md file in the root directory for more details. """ -import capnp - from cereal import custom - from opendbc.car import structs from openpilot.common.params import Params +from sunnypilot.sunnylink.utils import get_param_as_byte + class ParamStore: keys: list[str] - values: dict[str, str] + _params: dict[str, custom.CarControlSP.Param] def __init__(self, CP: structs.CarParams): universal_params: list[str] = [] brand_params: list[str] = [] self.keys = universal_params + brand_params - self.values = {} - self.cached_params_list: list[capnp.lib.capnp._DynamicStructBuilder] | None = None + self._params = {} self.frame = 0 def update(self, params: Params) -> None: - if self.frame % 300 == 0: - old_values = dict(self.values) - self.values = {k: params.get(k) or "0" for k in self.keys} - if old_values != self.values: - self.cached_params_list = None - self.frame += 1 + if self.frame % 300 != 0: + return - def publish(self) -> list[capnp.lib.capnp._DynamicStructBuilder]: - if self.cached_params_list is None: - # TODO-SP: Why are we doing a list instead of a dictionary here? - self.cached_params_list = [custom.CarControlSP.Param(key=k, value=self.values[k]) for k in self.keys] - return self.cached_params_list + for key in self.keys: + param_type = params.get_type(key).name.lower() # Using string instead of number because its "loose" dependency, and could change by OP at anytime. + + # Over engineering opportunity: It's possible this conversion is slow, we may check the value as params returns it for cache purposes. Not today. + param_value = get_param_as_byte(key, params) + if (existing_param := self._params.get(key)) is not None and existing_param.value == param_value: + continue + + self._params[key] = custom.CarControlSP.Param(key=key, value=param_value, type=param_type) + + @property + def param_list(self) -> list[custom.CarControlSP.Param]: + return [v for k,v in self._params.items()] diff --git a/sunnypilot/sunnylink/utils.py b/sunnypilot/sunnylink/utils.py index 1310b91f0e..91c0788795 100644 --- a/sunnypilot/sunnylink/utils.py +++ b/sunnypilot/sunnylink/utils.py @@ -60,9 +60,9 @@ def get_api_token(): print(f"API Token: {token}") -def get_param_as_byte(param_name: str) -> bytes | None: +def get_param_as_byte(param_name: str, params=None) -> bytes | None: """Get a parameter as bytes. Returns None if the parameter does not exist.""" - params = Params() + params = params or Params() # Use existing Params instance if provided param = params.get(param_name) if param is None: return None @@ -85,6 +85,17 @@ def save_param_from_base64_encoded_string(param_name: str, base64_encoded_data: if is_compressed: value = gzip.decompress(value) + # We convert to string anything that isn't bytes first. We later transform further. + param_value = _convert_param_to_type(value, param_type) + params.put(param_name, param_value) + + +def _convert_param_to_type(value: bytes, param_type: ParamKeyType) -> bytes | str | int | float | bool | dict | None: + """ + Convert a byte value to the specified param type. Used internally when getting a Param to convert it to the right type. + If this method looks familiar, it's because on SP we have a similar one in openpilot/sunnypilot/car/__init__.py. + """ + # We convert to string anything that isn't bytes first. We later transform further. if param_type != ParamKeyType.BYTES: value = value.decode('utf-8') # type: ignore @@ -101,4 +112,5 @@ def save_param_from_base64_encoded_string(param_name: str, base64_encoded_data: value = str(value) # type: ignore elif param_type == ParamKeyType.JSON: value = json.loads(value) - params.put(param_name, value) + + return value From b32c6dafee755b2a961c37fa6967cc1fe5292398 Mon Sep 17 00:00:00 2001 From: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Sun, 14 Sep 2025 18:45:22 -0700 Subject: [PATCH 079/159] modeld: add laneline helper for plan indices calculation (#1240) * modeld: add laneline_helper for plan X indices calculation * spacing * keep type hints * openpilot * sunnypilot/models/helpers add modeld helpers to helpers * Send it from each fill message --------- Co-authored-by: Jason Wen --- selfdrive/modeld/fill_model_msg.py | 5 +++-- sunnypilot/modeld/fill_model_msg.py | 19 ++----------------- sunnypilot/modeld_v2/fill_model_msg.py | 5 +++-- sunnypilot/models/helpers.py | 24 ++++++++++++++++++++++++ 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/selfdrive/modeld/fill_model_msg.py b/selfdrive/modeld/fill_model_msg.py index 82c4c92b1d..7273745c7b 100644 --- a/selfdrive/modeld/fill_model_msg.py +++ b/selfdrive/modeld/fill_model_msg.py @@ -3,6 +3,7 @@ import capnp import numpy as np from cereal import log from openpilot.selfdrive.modeld.constants import ModelConstants, Plan, Meta +from openpilot.sunnypilot.models.helpers import plan_x_idxs_helper SEND_RAW_PRED = os.getenv('SEND_RAW_PRED') @@ -95,8 +96,8 @@ def fill_model_msg(base_msg: capnp._DynamicStructBuilder, extended_msg: capnp._D # action modelV2.action = action - # times at X_IDXS of edges and lines aren't used - LINE_T_IDXS: list[float] = [] + # times at X_IDXS of edges and lines + LINE_T_IDXS: list[float] = plan_x_idxs_helper(ModelConstants, Plan, net_output_data) # lane lines modelV2.init('laneLines', 4) diff --git a/sunnypilot/modeld/fill_model_msg.py b/sunnypilot/modeld/fill_model_msg.py index dadffc8433..a62c451efd 100644 --- a/sunnypilot/modeld/fill_model_msg.py +++ b/sunnypilot/modeld/fill_model_msg.py @@ -3,6 +3,7 @@ import capnp import numpy as np from cereal import log from openpilot.sunnypilot.modeld.constants import ModelConstants, Plan +from openpilot.sunnypilot.models.helpers import plan_x_idxs_helper from openpilot.sunnypilot.selfdrive.controls.lib.drive_helpers import CONTROL_N, get_lag_adjusted_curvature, MIN_SPEED SEND_RAW_PRED = os.getenv('SEND_RAW_PRED') @@ -120,23 +121,7 @@ def fill_model_msg(base_msg: capnp._DynamicStructBuilder, extended_msg: capnp._D modelV2_action.desiredCurvature = desired_curvature # times at X_IDXS according to model plan - PLAN_T_IDXS = [np.nan] * ModelConstants.IDX_N - PLAN_T_IDXS[0] = 0.0 - plan_x = net_output_data['plan'][0,:,Plan.POSITION][:,0].tolist() - for xidx in range(1, ModelConstants.IDX_N): - tidx = 0 - # increment tidx until we find an element that's further away than the current xidx - while tidx < ModelConstants.IDX_N - 1 and plan_x[tidx+1] < ModelConstants.X_IDXS[xidx]: - tidx += 1 - if tidx == ModelConstants.IDX_N - 1: - # if the Plan doesn't extend far enough, set plan_t to the max value (10s), then break - PLAN_T_IDXS[xidx] = ModelConstants.T_IDXS[ModelConstants.IDX_N - 1] - break - # interpolate to find `t` for the current xidx - current_x_val = plan_x[tidx] - next_x_val = plan_x[tidx+1] - p = (ModelConstants.X_IDXS[xidx] - current_x_val) / (next_x_val - current_x_val) if abs(next_x_val - current_x_val) > 1e-9 else float('nan') - PLAN_T_IDXS[xidx] = p * ModelConstants.T_IDXS[tidx+1] + (1 - p) * ModelConstants.T_IDXS[tidx] + PLAN_T_IDXS: list[float] = plan_x_idxs_helper(ModelConstants, Plan, net_output_data) # lane lines modelV2.init('laneLines', 4) diff --git a/sunnypilot/modeld_v2/fill_model_msg.py b/sunnypilot/modeld_v2/fill_model_msg.py index c7de698f61..ee0eb48684 100644 --- a/sunnypilot/modeld_v2/fill_model_msg.py +++ b/sunnypilot/modeld_v2/fill_model_msg.py @@ -3,6 +3,7 @@ import capnp import numpy as np from cereal import log from openpilot.sunnypilot.modeld_v2.constants import ModelConstants, Plan +from openpilot.sunnypilot.models.helpers import plan_x_idxs_helper from openpilot.selfdrive.controls.lib.drive_helpers import get_curvature_from_plan SEND_RAW_PRED = os.getenv('SEND_RAW_PRED') @@ -118,8 +119,8 @@ def fill_model_msg(base_msg: capnp._DynamicStructBuilder, extended_msg: capnp._D # action (includes lateral planning now) modelV2.action = action - # times at X_IDXS of edges and lines aren't used - LINE_T_IDXS: list[float] = [] + # times at X_IDXS of edges and lines + LINE_T_IDXS: list[float] = plan_x_idxs_helper(ModelConstants, Plan, net_output_data) # lane lines modelV2.init('laneLines', 4) diff --git a/sunnypilot/models/helpers.py b/sunnypilot/models/helpers.py index ecf0a39b72..20b94fb611 100644 --- a/sunnypilot/models/helpers.py +++ b/sunnypilot/models/helpers.py @@ -185,3 +185,27 @@ def load_meta_constants(model_metadata): meta = MetaTombRaider return meta + + +# The following method(s) are modeld helper methods +def plan_x_idxs_helper(constants, plan, model_output) -> list[float]: + # times at X_IDXS according to plan. + LINE_T_IDXS = [np.nan] * constants.IDX_N + LINE_T_IDXS[0] = 0.0 + plan_x = model_output['plan'][0, :, plan.POSITION][:, 0].tolist() + for xidx in range(1, constants.IDX_N): + tidx = 0 + # increment tidx until we find an element that's further away than the current xidx + while tidx < constants.IDX_N - 1 and plan_x[tidx + 1] < constants.X_IDXS[xidx]: + tidx += 1 + if tidx == constants.IDX_N - 1: + # if the plan doesn't extend far enough, set plan_t to the max value (10s), then break + LINE_T_IDXS[xidx] = constants.T_IDXS[constants.IDX_N - 1] + break + # interpolate to find `t` for the current xidx + current_x_val = plan_x[tidx] + next_x_val = plan_x[tidx + 1] + p = (constants.X_IDXS[xidx] - current_x_val) / (next_x_val - current_x_val) if abs( + next_x_val - current_x_val) > 1e-9 else float('nan') + LINE_T_IDXS[xidx] = p * constants.T_IDXS[tidx + 1] + (1 - p) * constants.T_IDXS[tidx] + return LINE_T_IDXS From 747460363fca35025cf7cf306269c95b4e7bc0aa Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sun, 14 Sep 2025 23:51:29 -0400 Subject: [PATCH 080/159] panda: consolidate supported panda checks (#1248) * panda: fix upstream merge conflicts * move it higher * consolidate checks * update * bump * actual bump --- panda | 2 +- selfdrive/pandad/pandad.py | 26 ++++++++++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/panda b/panda index 7c393d1cd5..69ab12ee2a 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit 7c393d1cd5cc88d3c28af2086bf25ff6f3035574 +Subproject commit 69ab12ee2a2958bb9825bd772ff03be6714b6c0e diff --git a/selfdrive/pandad/pandad.py b/selfdrive/pandad/pandad.py index 361c1f2148..f4064ddcd4 100755 --- a/selfdrive/pandad/pandad.py +++ b/selfdrive/pandad/pandad.py @@ -29,6 +29,12 @@ def flash_panda(panda_serial: str) -> Panda: HARDWARE.recover_internal_panda() raise + # skip flashing if the detected panda is not supported + supported_panda = check_panda_support(panda) + if not supported_panda: + cloudlog.warning(f"Panda {panda_serial} is not supported (hw_type: {panda.get_type()}), skipping flash...") + return panda + fw_signature = get_expected_signature(panda) internal_panda = panda.is_internal() @@ -36,12 +42,6 @@ def flash_panda(panda_serial: str) -> Panda: panda_signature = b"" if panda.bootstub else panda.get_signature() cloudlog.warning(f"Panda {panda_serial} connected, version: {panda_version}, signature {panda_signature.hex()[:16]}, expected {fw_signature.hex()[:16]}") - # skip flashing if the detected device is not supported from upstream - hw_type = panda.get_type() - if hw_type not in Panda.SUPPORTED_DEVICES: - cloudlog.warning(f"Panda {panda_serial} is not supported (hw_type: {hw_type}), skipping flash...") - return panda - if panda.bootstub or panda_signature != fw_signature: cloudlog.info("Panda firmware out of date, update required") panda.flash() @@ -67,6 +67,14 @@ def flash_panda(panda_serial: str) -> Panda: return panda +def check_panda_support(panda) -> bool: + hw_type = panda.get_type() + if hw_type in Panda.SUPPORTED_DEVICES: + return True + + return False + + def main() -> None: # signal pandad to close the relay and exit def signal_handler(signum, frame): @@ -140,6 +148,12 @@ def main() -> None: params.put("PandaSignatures", b','.join(p.get_signature() for p in pandas)) for panda in pandas: + # skip health check if the detected panda is not supported + supported_panda = check_panda_support(panda) + if not supported_panda: + cloudlog.warning(f"Panda {panda.get_usb_serial()} is not supported (hw_type: {panda.get_type()}), skipping health check...") + continue + # check health for lost heartbeat health = panda.health() if health["heartbeat_lost"]: From 94f93a9f266e6a51d6a79ac092cefd2f7b0b6551 Mon Sep 17 00:00:00 2001 From: DevTekVE Date: Tue, 16 Sep 2025 10:05:34 +0200 Subject: [PATCH 081/159] ui: Add standstill timer to HUD (#1251) * Add standstill timer to HUD - Introduced a timer displaying elapsed time when the car is at a standstill. - Added settings toggle to enable/disable this feature. - Updated UI elements and related logic to support the standstill timer. * ruff be happy * stop screaming * c stands for not cereal * slight cleanup * a bit more cleanup * unused --------- Co-authored-by: nayan Co-authored-by: Jason Wen --- common/params_keys.h | 1 + .../qt/offroad/settings/visuals_panel.cc | 7 ++++ selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 42 +++++++++++++++++++ selfdrive/ui/sunnypilot/qt/onroad/hud.h | 4 ++ selfdrive/ui/sunnypilot/ui.cc | 2 + selfdrive/ui/sunnypilot/ui_scene.h | 1 + 6 files changed, 57 insertions(+) diff --git a/common/params_keys.h b/common/params_keys.h index 011a3161f9..44d25ec413 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -159,6 +159,7 @@ inline static std::unordered_map keys = { {"QuietMode", {PERSISTENT | BACKUP, BOOL, "0"}}, {"RainbowMode", {PERSISTENT | BACKUP, BOOL, "0"}}, {"ShowAdvancedControls", {PERSISTENT | BACKUP, BOOL, "0"}}, + {"StandstillTimer", {PERSISTENT | BACKUP, BOOL, "0"}}, // MADS params {"Mads", {PERSISTENT | BACKUP, BOOL, "1"}}, diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc index c3aaf12d22..e19760f2e1 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc @@ -35,6 +35,13 @@ VisualsPanel::VisualsPanel(QWidget *parent) : QWidget(parent) { "../assets/offroad/icon_monitoring.png", false, }, + { + "StandstillTimer", + tr("Enable Standstill Timer"), + tr("Show a timer on the HUD when the car is at a standstill."), + "../assets/offroad/icon_monitoring.png", + false, + }, }; // Add regular toggles first diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index 9ead933d04..291a669ac5 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -75,6 +75,9 @@ void HudRendererSP::updateState(const UIState &s) { latAccelFactorFiltered = ltp.getLatAccelFactorFiltered(); frictionCoefficientFiltered = ltp.getFrictionCoefficientFiltered(); liveValid = ltp.getLiveValid(); + + standstillTimer = s.scene.standstill_timer; + isStandstill = car_state.getStandstill(); } void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { @@ -94,6 +97,11 @@ void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { QRect rect_right(surface_rect.right() - (UI_BORDER_SIZE * 2), UI_BORDER_SIZE * 1.5, 184, 170); drawRightDevUI(p, surface_rect.right() - 184 - UI_BORDER_SIZE * 2, UI_BORDER_SIZE * 2 + rect_right.height()); } + + // Standstill Timer + if (standstillTimer) { + drawStandstillTimer(p, surface_rect.right() / 12 * 10, surface_rect.bottom() / 12 * 1.53); + } } } @@ -206,3 +214,37 @@ void HudRendererSP::drawBottomDevUI(QPainter &p, int x, int y) { UiElement altitudeElement = DeveloperUi::getAltitude(gpsAccuracy, altitude); rw += drawBottomDevUIElement(p, rw, y, altitudeElement.value, altitudeElement.label, altitudeElement.units, altitudeElement.color); } + +void HudRendererSP::drawStandstillTimer(QPainter &p, int x, int y) { + if (isStandstill) { + standstillElapsedTime += 1.0 / UI_FREQ; + + int minute = static_cast(standstillElapsedTime / 60); + int second = static_cast(standstillElapsedTime - (minute * 60)); + + // stop sign for standstill timer + const int size = 190; // size + const float angle = M_PI / 8.0; + + QPolygon octagon; + for (int i = 0; i < 8; i++) { + float curr_angle = angle + i * M_PI / 4.0; + int point_x = x + size / 2 * cos(curr_angle); + int point_y = y + size / 2 * sin(curr_angle); + octagon << QPoint(point_x, point_y); + } + + p.setPen(QPen(Qt::white, 6)); + p.setBrush(QColor(255, 90, 81, 200)); // red pastel + p.drawPolygon(octagon); + + QString time_str = QString("%1:%2").arg(minute, 1, 10, QChar('0')).arg(second, 2, 10, QChar('0')); + p.setFont(InterFont(55, QFont::Bold)); + p.setPen(Qt::white); + QRect timerTextRect = p.fontMetrics().boundingRect(QString(time_str)); + timerTextRect.moveCenter({x, y}); + p.drawText(timerTextRect, Qt::AlignCenter, QString(time_str)); + } else { + standstillElapsedTime = 0.0; + } +} diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.h b/selfdrive/ui/sunnypilot/qt/onroad/hud.h index 968789bc15..75fc520fcf 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.h +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.h @@ -25,6 +25,7 @@ private: int drawRightDevUIElement(QPainter &p, int x, int y, const QString &value, const QString &label, const QString &units, QColor &color); int drawBottomDevUIElement(QPainter &p, int x, int y, const QString &value, const QString &label, const QString &units, QColor &color); void drawBottomDevUI(QPainter &p, int x, int y); + void drawStandstillTimer(QPainter &p, int x, int y); bool lead_status; float lead_d_rel; @@ -53,4 +54,7 @@ private: bool reversing; cereal::CarParams::SteerControlType steerControlType; cereal::CarControl::Actuators::Reader actuators; + bool standstillTimer; + bool isStandstill; + float standstillElapsedTime; }; diff --git a/selfdrive/ui/sunnypilot/ui.cc b/selfdrive/ui/sunnypilot/ui.cc index 1277195df1..7b10929bc6 100644 --- a/selfdrive/ui/sunnypilot/ui.cc +++ b/selfdrive/ui/sunnypilot/ui.cc @@ -34,6 +34,7 @@ UIStateSP::UIStateSP(QObject *parent) : UIState(parent) { ui_update_params_sp(this); }); param_watcher->addParam("DevUIInfo"); + param_watcher->addParam("StandstillTimer"); } // This method overrides completely the update method from the parent class intentionally. @@ -51,6 +52,7 @@ void UIStateSP::update() { void ui_update_params_sp(UIStateSP *s) { auto params = Params(); s->scene.dev_ui_info = std::atoi(params.get("DevUIInfo").c_str()); + s->scene.standstill_timer = params.getBool("StandstillTimer"); } DeviceSP::DeviceSP(QObject *parent) : Device(parent) { diff --git a/selfdrive/ui/sunnypilot/ui_scene.h b/selfdrive/ui/sunnypilot/ui_scene.h index 93e0cd6c91..c941be675c 100644 --- a/selfdrive/ui/sunnypilot/ui_scene.h +++ b/selfdrive/ui/sunnypilot/ui_scene.h @@ -9,4 +9,5 @@ typedef struct UISceneSP : UIScene { int dev_ui_info = 0; + bool standstill_timer = false; } UISceneSP; From cb94d3b0550e3ee329f17f143fe9a3cbba1e9430 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Tue, 16 Sep 2025 22:51:32 -0400 Subject: [PATCH 082/159] Longitudinal: Smart Cruise Control prerequisites (#1249) * Controls: Vision Turn Speed Control * fix * Data type temp fix * format * more * even more * self contain targets * state cleanup * fix * param updates * no need * use similar state machine * raise exception if not found * new state * entirely internal * use long active * more * rename and expose aTarget * rename to SCC-V * init tests * slight tests * expose toggle * lint * todo * remove lat planner sub and mock sm data * introduce aTarget * rename * rename * update fill_model_msg.py to calculate PLAN_T_IDXS for lanelines and road edges * sync upstream * no SCC-V yet * Revert "no SCC-V yet" This reverts commit b67281bcac0dce0c6c3237afc2584cf29144c83c. * wrap it with SCC main * no SCC-V yet * noqa now * fix * OP long for now, enable for ICBM once merged * type hints * let's get it straight from carcontrol instead * not needed * unused * add source to track * we can do this --------- Co-authored-by: discountchubbs --- cereal/custom.capnp | 9 +++++++++ .../controls/lib/longitudinal_planner.py | 3 +++ sunnypilot/__init__.py | 7 +++++++ .../controls/lib/longitudinal_planner.py | 20 +++++++++++++++++++ .../lib/smart_cruise_control/__init__.py | 0 .../smart_cruise_control.py | 13 ++++++++++++ 6 files changed, 52 insertions(+) create mode 100644 sunnypilot/selfdrive/controls/lib/smart_cruise_control/__init__.py create mode 100644 sunnypilot/selfdrive/controls/lib/smart_cruise_control/smart_cruise_control.py diff --git a/cereal/custom.capnp b/cereal/custom.capnp index 8d4bc3cb82..e09b32a0a6 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -122,6 +122,8 @@ struct ModelManagerSP @0xaedffd8f31e7b55d { struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { dec @0 :DynamicExperimentalControl; + longitudinalPlanSource @1 :LongitudinalPlanSource; + smartCruiseControl @2 :SmartCruiseControl; struct DynamicExperimentalControl { state @0 :DynamicExperimentalControlState; @@ -133,6 +135,13 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { blended @1; } } + + struct SmartCruiseControl { + } + + enum LongitudinalPlanSource { + cruise @0; + } } struct OnroadEventSP @0xda96579883444c35 { diff --git a/selfdrive/controls/lib/longitudinal_planner.py b/selfdrive/controls/lib/longitudinal_planner.py index 96248b7132..139cdc06e7 100755 --- a/selfdrive/controls/lib/longitudinal_planner.py +++ b/selfdrive/controls/lib/longitudinal_planner.py @@ -146,6 +146,9 @@ class LongitudinalPlanner(LongitudinalPlannerSP): clipped_accel_coast_interp = np.interp(v_ego, [MIN_ALLOW_THROTTLE_SPEED, MIN_ALLOW_THROTTLE_SPEED*2], [accel_clip[1], clipped_accel_coast]) accel_clip[1] = min(accel_clip[1], clipped_accel_coast_interp) + # Get new v_cruise and a_desired from Smart Cruise Control + v_cruise, self.a_desired = LongitudinalPlannerSP.update_targets(self, sm, self.v_desired_filter.x, self.a_desired, v_cruise) + if force_slow_decel: v_cruise = 0.0 diff --git a/sunnypilot/__init__.py b/sunnypilot/__init__.py index e69de29bb2..ab5441aa71 100644 --- a/sunnypilot/__init__.py +++ b/sunnypilot/__init__.py @@ -0,0 +1,7 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" +PARAMS_UPDATE_PERIOD = 3 # seconds diff --git a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py index 6952a97f1f..ec020000a3 100644 --- a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py +++ b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py @@ -8,15 +8,19 @@ See the LICENSE.md file in the root directory for more details. from cereal import messaging, custom from opendbc.car import structs from openpilot.sunnypilot.selfdrive.controls.lib.dec.dec import DynamicExperimentalController +from openpilot.sunnypilot.selfdrive.controls.lib.smart_cruise_control.smart_cruise_control import SmartCruiseControl from openpilot.sunnypilot.models.helpers import get_active_bundle DecState = custom.LongitudinalPlanSP.DynamicExperimentalControl.DynamicExperimentalControlState +Source = custom.LongitudinalPlanSP.LongitudinalPlanSource class LongitudinalPlannerSP: def __init__(self, CP: structs.CarParams, mpc): self.dec = DynamicExperimentalController(CP, mpc) + self.scc = SmartCruiseControl() self.generation = int(model_bundle.generation) if (model_bundle := get_active_bundle()) else None + self.source = Source.cruise @property def mlsim(self) -> bool: @@ -29,6 +33,18 @@ class LongitudinalPlannerSP: return self.dec.mode() + def update_targets(self, sm: messaging.SubMaster, v_ego: float, a_ego: float, v_cruise: float) -> tuple[float, float]: + self.scc.update(sm, v_ego, a_ego, v_cruise) + + targets = { + Source.cruise : (v_cruise, a_ego), + } + + self.source = min(targets, key=lambda k: targets[k][0]) + v_target, a_target = targets[self.source] + + return v_target, a_target + def update(self, sm: messaging.SubMaster) -> None: self.dec.update(sm) @@ -38,6 +54,7 @@ class LongitudinalPlannerSP: plan_sp_send.valid = sm.all_checks(service_list=['carState', 'controlsState']) longitudinalPlanSP = plan_sp_send.longitudinalPlanSP + longitudinalPlanSP.longitudinalPlanSource = self.source # Dynamic Experimental Control dec = longitudinalPlanSP.dec @@ -45,4 +62,7 @@ class LongitudinalPlannerSP: dec.enabled = self.dec.enabled() dec.active = self.dec.active() + # Smart Cruise Control + smartCruiseControl = longitudinalPlanSP.smartCruiseControl # noqa: F841 + pm.send('longitudinalPlanSP', plan_sp_send) diff --git a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/__init__.py b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/smart_cruise_control.py b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/smart_cruise_control.py new file mode 100644 index 0000000000..0a04c243c1 --- /dev/null +++ b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/smart_cruise_control.py @@ -0,0 +1,13 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" +from cereal import messaging + + +class SmartCruiseControl: + + def update(self, sm: messaging.SubMaster, v_ego: float, a_ego: float, v_cruise: float): + pass From 784e1d665880f65b46cfe3c0c242fe71e22f4a2e Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Wed, 17 Sep 2025 22:55:36 -0400 Subject: [PATCH 083/159] Smart Cruise Control: Vision (SCC-V) (#997) * Controls: Vision Turn Speed Control * fix * Data type temp fix * format * more * even more * self contain targets * state cleanup * fix * param updates * no need * use similar state machine * raise exception if not found * new state * entirely internal * use long active * more * rename and expose aTarget * rename to SCC-V * init tests * slight tests * expose toggle * lint * todo * remove lat planner sub and mock sm data * introduce aTarget * rename * rename * update fill_model_msg.py to calculate PLAN_T_IDXS for lanelines and road edges * sync upstream * no SCC-V yet * Revert "no SCC-V yet" This reverts commit b67281bcac0dce0c6c3237afc2584cf29144c83c. * wrap it with SCC main * leave enabled out of here * wat * enabled and active on cereal * OP long for now, enable for ICBM once merged * need this * unused * let's go hybrid * fix * add override state * update tests * huh * don't math here if not enabled * ui: Smart Cruise Control - Vision (SCC-V) (#1253) * vtsc-ui * slight cleanup * more cleanup * unused * a bit more * pulse like it's hot * draw only enabled and active * let's try this for now * settle * finalize UI * brighter color so we blind devtekve * add long override --------- Co-authored-by: Jason Wen * slight cleanup * more * type hints --------- Co-authored-by: discountchubbs Co-authored-by: Kumar <36933347+rav4kumar@users.noreply.github.com> --- cereal/custom.capnp | 21 ++ common/params_keys.h | 1 + .../qt/offroad/settings/longitudinal_panel.cc | 9 + .../qt/offroad/settings/longitudinal_panel.h | 1 + selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 63 ++++++ selfdrive/ui/sunnypilot/qt/onroad/hud.h | 6 + .../controls/lib/longitudinal_planner.py | 14 +- .../smart_cruise_control.py | 12 +- .../tests/test_vision_controller.py | 104 +++++++++ .../smart_cruise_control/vision_controller.py | 205 ++++++++++++++++++ 10 files changed, 431 insertions(+), 5 deletions(-) create mode 100644 sunnypilot/selfdrive/controls/lib/smart_cruise_control/tests/test_vision_controller.py create mode 100644 sunnypilot/selfdrive/controls/lib/smart_cruise_control/vision_controller.py diff --git a/cereal/custom.capnp b/cereal/custom.capnp index e09b32a0a6..66aa1b71f8 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -137,10 +137,31 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { } struct SmartCruiseControl { + vision @0 :Vision; + + struct Vision { + state @0 :VisionState; + vTarget @1 :Float32; + aTarget @2 :Float32; + currentLateralAccel @3 :Float32; + maxPredictedLateralAccel @4 :Float32; + enabled @5 :Bool; + active @6 :Bool; + } + + enum VisionState { + disabled @0; # System disabled or inactive. + enabled @1; # No predicted substantial turn on vision range. + entering @2; # A substantial turn is predicted ahead, adapting speed to turn comfort levels. + turning @3; # Actively turning. Managing acceleration to provide a roll on turn feeling. + leaving @4; # Road ahead straightens. Start to allow positive acceleration. + overriding @5; # System overriding with manual control. + } } enum LongitudinalPlanSource { cruise @0; + sccVision @1; } } diff --git a/common/params_keys.h b/common/params_keys.h index 44d25ec413..f0511bf9c2 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -159,6 +159,7 @@ inline static std::unordered_map keys = { {"QuietMode", {PERSISTENT | BACKUP, BOOL, "0"}}, {"RainbowMode", {PERSISTENT | BACKUP, BOOL, "0"}}, {"ShowAdvancedControls", {PERSISTENT | BACKUP, BOOL, "0"}}, + {"SmartCruiseControlVision", {PERSISTENT | BACKUP, BOOL, "0"}}, {"StandstillTimer", {PERSISTENT | BACKUP, BOOL, "0"}}, // MADS params diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc index 15ed10bf9a..ac7b57e297 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc @@ -18,6 +18,13 @@ LongitudinalPanel::LongitudinalPanel(QWidget *parent) : QWidget(parent) { cruisePanelScroller = new ScrollViewSP(list, this); vlayout->addWidget(cruisePanelScroller); + SmartCruiseControlVision = new ParamControl( + "SmartCruiseControlVision", + tr("Smart Cruise Control - Vision"), + tr("Use vision path predictions to estimate the appropriate speed to drive through turns ahead."), + ""); + list->addItem(SmartCruiseControlVision); + customAccIncrement = new CustomAccIncrement("CustomAccIncrementsEnabled", tr("Custom ACC Speed Increments"), "", "", this); list->addItem(customAccIncrement); @@ -75,5 +82,7 @@ void LongitudinalPanel::refresh(bool _offroad) { customAccIncrement->setEnabled(has_longitudinal_control && !is_pcm_cruise && !offroad); customAccIncrement->refresh(); + SmartCruiseControlVision->setEnabled(has_longitudinal_control); + offroad = _offroad; } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h index 58e94f333b..36c35720e7 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h @@ -29,4 +29,5 @@ private: ScrollViewSP *cruisePanelScroller = nullptr; QWidget *cruisePanelScreen = nullptr; CustomAccIncrement *customAccIncrement = nullptr; + ParamControl *SmartCruiseControlVision; }; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index 291a669ac5..fb2a69c24b 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -4,6 +4,7 @@ * This file is part of sunnypilot and is licensed under the MIT License. * See the LICENSE.md file in the root directory for more details. */ +#include #include "selfdrive/ui/sunnypilot/qt/onroad/hud.h" @@ -25,6 +26,7 @@ void HudRendererSP::updateState(const UIState &s) { const auto gpsLocation = is_gps_location_external ? sm["gpsLocationExternal"].getGpsLocationExternal() : sm["gpsLocation"].getGpsLocation(); const auto ltp = sm["liveTorqueParameters"].getLiveTorqueParameters(); const auto car_params = sm["carParams"].getCarParams(); + const auto lp_sp = sm["longitudinalPlanSP"].getLongitudinalPlanSP(); static int reverse_delay = 0; bool reverse_allowed = false; @@ -78,11 +80,30 @@ void HudRendererSP::updateState(const UIState &s) { standstillTimer = s.scene.standstill_timer; isStandstill = car_state.getStandstill(); + longOverride = car_control.getCruiseControl().getOverride(); + smartCruiseControlVisionEnabled = lp_sp.getSmartCruiseControl().getVision().getEnabled(); + smartCruiseControlVisionActive = lp_sp.getSmartCruiseControl().getVision().getActive(); } void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { HudRenderer::draw(p, surface_rect); if (!reversing) { + // Smart Cruise Control + int x_offset = -260; + int y1_offset = -80; + // int y2_offset = -140; // reserved for 2 icons + + bool scc_vision_active_pulse = pulseElement(smartCruiseControlVisionFrame); + if ((smartCruiseControlVisionEnabled && !smartCruiseControlVisionActive) || (smartCruiseControlVisionActive && scc_vision_active_pulse)) { + drawSmartCruiseControlOnroadIcon(p, surface_rect, x_offset, y1_offset, "SCC-V"); + } + + if (smartCruiseControlVisionActive) { + smartCruiseControlVisionFrame++; + } else { + smartCruiseControlVisionFrame = 0; + } + // Bottom Dev UI if (devUiInfo == 2) { QRect rect_bottom(surface_rect.left(), surface_rect.bottom() - 60, surface_rect.width(), 61); @@ -112,6 +133,48 @@ void HudRendererSP::drawText(QPainter &p, int x, int y, const QString &text, QCo p.drawText(real_rect.x(), real_rect.bottom(), text); } +bool HudRendererSP::pulseElement(int frame) { + if (frame % UI_FREQ < (UI_FREQ / 2.5)) { + return false; + } + + return true; +} + +void HudRendererSP::drawSmartCruiseControlOnroadIcon(QPainter &p, const QRect &surface_rect, int x_offset, int y_offset, std::string name) { + int x = surface_rect.center().x(); + int y = surface_rect.height() / 4; + + QString text = QString::fromStdString(name); + QFont font = InterFont(36, QFont::Bold); + p.setFont(font); + + QFontMetrics fm(font); + + int padding_v = 5; + int box_width = 160; + int box_height = fm.height() + padding_v * 2; + + QRectF bg_rect(x - (box_width / 2) + x_offset, + y - (box_height / 2) + y_offset, + box_width, box_height); + + QPainterPath boxPath; + boxPath.addRoundedRect(bg_rect, 10, 10); + + int text_w = fm.horizontalAdvance(text); + qreal baseline_y = bg_rect.top() + padding_v + fm.ascent(); + qreal text_x = bg_rect.center().x() - (text_w / 2.0); + + QPainterPath textPath; + textPath.addText(QPointF(text_x, baseline_y), font, text); + boxPath = boxPath.subtracted(textPath); + + p.setPen(Qt::NoPen); + p.setBrush(longOverride ? QColor(0x91, 0x9b, 0x95, 0xf1) : QColor(0, 0xff, 0, 0xff)); + p.drawPath(boxPath); +} + int HudRendererSP::drawRightDevUIElement(QPainter &p, int x, int y, const QString &value, const QString &label, const QString &units, QColor &color) { p.setFont(InterFont(28, QFont::Bold)); diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.h b/selfdrive/ui/sunnypilot/qt/onroad/hud.h index 75fc520fcf..4c92835957 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.h +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.h @@ -26,6 +26,8 @@ private: int drawBottomDevUIElement(QPainter &p, int x, int y, const QString &value, const QString &label, const QString &units, QColor &color); void drawBottomDevUI(QPainter &p, int x, int y); void drawStandstillTimer(QPainter &p, int x, int y); + bool pulseElement(int frame); + void drawSmartCruiseControlOnroadIcon(QPainter &p, const QRect &surface_rect, int x_offset, int y_offset, std::string name); bool lead_status; float lead_d_rel; @@ -57,4 +59,8 @@ private: bool standstillTimer; bool isStandstill; float standstillElapsedTime; + bool longOverride; + bool smartCruiseControlVisionEnabled; + bool smartCruiseControlVisionActive; + int smartCruiseControlVisionFrame; }; diff --git a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py index ec020000a3..f2358a2648 100644 --- a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py +++ b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py @@ -37,7 +37,8 @@ class LongitudinalPlannerSP: self.scc.update(sm, v_ego, a_ego, v_cruise) targets = { - Source.cruise : (v_cruise, a_ego), + Source.cruise: (v_cruise, a_ego), + Source.sccVision: (self.scc.vision.output_v_target, self.scc.vision.output_a_target) } self.source = min(targets, key=lambda k: targets[k][0]) @@ -63,6 +64,15 @@ class LongitudinalPlannerSP: dec.active = self.dec.active() # Smart Cruise Control - smartCruiseControl = longitudinalPlanSP.smartCruiseControl # noqa: F841 + smartCruiseControl = longitudinalPlanSP.smartCruiseControl + # Vision Turn Speed Control + sccVision = smartCruiseControl.vision + sccVision.state = self.scc.vision.state + sccVision.vTarget = float(self.scc.vision.output_v_target) + sccVision.aTarget = float(self.scc.vision.output_a_target) + sccVision.currentLateralAccel = float(self.scc.vision.current_lat_acc) + sccVision.maxPredictedLateralAccel = float(self.scc.vision.max_pred_lat_acc) + sccVision.enabled = self.scc.vision.is_enabled + sccVision.active = self.scc.vision.is_active pm.send('longitudinalPlanSP', plan_sp_send) diff --git a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/smart_cruise_control.py b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/smart_cruise_control.py index 0a04c243c1..c66c2c392a 100644 --- a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/smart_cruise_control.py +++ b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/smart_cruise_control.py @@ -4,10 +4,16 @@ Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. This file is part of sunnypilot and is licensed under the MIT License. See the LICENSE.md file in the root directory for more details. """ -from cereal import messaging +import cereal.messaging as messaging +from openpilot.sunnypilot.selfdrive.controls.lib.smart_cruise_control.vision_controller import SmartCruiseControlVision class SmartCruiseControl: + def __init__(self): + self.vision = SmartCruiseControlVision() - def update(self, sm: messaging.SubMaster, v_ego: float, a_ego: float, v_cruise: float): - pass + def update(self, sm: messaging.SubMaster, v_ego: float, a_ego: float, v_cruise: float) -> None: + long_enabled = sm['carControl'].enabled + long_override = sm['carControl'].cruiseControl.override + + self.vision.update(sm, long_enabled, long_override, v_ego, a_ego, v_cruise) diff --git a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/tests/test_vision_controller.py b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/tests/test_vision_controller.py new file mode 100644 index 0000000000..9f6efffb55 --- /dev/null +++ b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/tests/test_vision_controller.py @@ -0,0 +1,104 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" +import numpy as np + +import cereal.messaging as messaging +from cereal import custom, log +from openpilot.common.params import Params +from openpilot.common.realtime import DT_MDL +from openpilot.selfdrive.car.cruise import V_CRUISE_UNSET +from openpilot.selfdrive.modeld.constants import ModelConstants +from openpilot.sunnypilot.selfdrive.controls.lib.smart_cruise_control.vision_controller import SmartCruiseControlVision + +VisionState = custom.LongitudinalPlanSP.SmartCruiseControl.VisionState + + +def generate_modelV2(): + model = messaging.new_message('modelV2') + position = log.XYZTData.new_message() + speed = 30 + position.x = [float(x) for x in (speed + 0.5) * np.array(ModelConstants.T_IDXS)] + model.modelV2.position = position + orientation = log.XYZTData.new_message() + curvature = 0.05 + orientation.x = [float(curvature) for _ in ModelConstants.T_IDXS] + orientation.y = [0.0 for _ in ModelConstants.T_IDXS] + model.modelV2.orientation = orientation + orientationRate = log.XYZTData.new_message() + orientationRate.z = [float(z) for z in ModelConstants.T_IDXS] + model.modelV2.orientationRate = orientationRate + velocity = log.XYZTData.new_message() + velocity.x = [float(x) for x in (speed + 0.5) * np.ones_like(ModelConstants.T_IDXS)] + velocity.x[0] = float(speed) # always start at current speed + model.modelV2.velocity = velocity + acceleration = log.XYZTData.new_message() + acceleration.x = [float(x) for x in np.zeros_like(ModelConstants.T_IDXS)] + acceleration.y = [float(y) for y in np.zeros_like(ModelConstants.T_IDXS)] + model.modelV2.acceleration = acceleration + + return model + + +def generate_carState(): + car_state = messaging.new_message('carState') + speed = 30 + v_cruise = 50 + car_state.carState.vEgo = float(speed) + car_state.carState.standstill = False + car_state.carState.vCruise = float(v_cruise * 3.6) + + return car_state + + +def generate_controlsState(): + controls_state = messaging.new_message('controlsState') + controls_state.controlsState.curvature = 0.05 + + return controls_state + + +class TestSmartCruiseControlVision: + + def setup_method(self): + self.params = Params() + self.reset_params() + self.scc_v = SmartCruiseControlVision() + + mdl = generate_modelV2() + cs = generate_carState() + controls_state = generate_controlsState() + self.sm = {'modelV2': mdl.modelV2, 'carState': cs.carState, 'controlsState': controls_state.controlsState} + + def reset_params(self): + self.params.put_bool("SmartCruiseControlVision", True) + + def test_initial_state(self): + assert self.scc_v.state == VisionState.disabled + assert not self.scc_v.is_active + assert self.scc_v.output_v_target == V_CRUISE_UNSET + assert self.scc_v.output_a_target == 0. + + def test_system_disabled(self): + self.params.put_bool("SmartCruiseControlVision", False) + self.scc_v.enabled = self.params.get_bool("SmartCruiseControlVision") + + for _ in range(int(10. / DT_MDL)): + self.scc_v.update(self.sm, True, False, 0., 0., 0.) + assert self.scc_v.state == VisionState.disabled + assert not self.scc_v.is_active + + def test_disabled(self): + for _ in range(int(10. / DT_MDL)): + self.scc_v.update(self.sm, False, False, 0., 0., 0.) + assert self.scc_v.state == VisionState.disabled + + def test_transition_disabled_to_enabled(self): + for _ in range(int(10. / DT_MDL)): + self.scc_v.update(self.sm, True, False, 0., 0., 0.) + assert self.scc_v.state == VisionState.enabled + + # TODO-SP: mock modelV2 data to test other states diff --git a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/vision_controller.py b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/vision_controller.py new file mode 100644 index 0000000000..f12a00f23e --- /dev/null +++ b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/vision_controller.py @@ -0,0 +1,205 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" +import numpy as np + +import cereal.messaging as messaging +from cereal import custom +from openpilot.common.constants import CV +from openpilot.common.params import Params +from openpilot.common.realtime import DT_MDL +from openpilot.selfdrive.car.cruise import V_CRUISE_UNSET +from openpilot.sunnypilot import PARAMS_UPDATE_PERIOD + +VisionState = custom.LongitudinalPlanSP.SmartCruiseControl.VisionState + +ACTIVE_STATES = (VisionState.entering, VisionState.turning, VisionState.leaving) +ENABLED_STATES = (VisionState.enabled, VisionState.overriding, *ACTIVE_STATES) + +_MIN_V = 20 * CV.KPH_TO_MS # Do not operate under 20 km/h + +_ENTERING_PRED_LAT_ACC_TH = 1.3 # Predicted Lat Acc threshold to trigger entering turn state. +_ABORT_ENTERING_PRED_LAT_ACC_TH = 1.1 # Predicted Lat Acc threshold to abort entering state if speed drops. + +_TURNING_LAT_ACC_TH = 1.6 # Lat Acc threshold to trigger turning state. + +_LEAVING_LAT_ACC_TH = 1.3 # Lat Acc threshold to trigger leaving turn state. +_FINISH_LAT_ACC_TH = 1.1 # Lat Acc threshold to trigger the end of the turn cycle. + +_A_LAT_REG_MAX = 2. # Maximum lateral acceleration + +_NO_OVERSHOOT_TIME_HORIZON = 4. # s. Time to use for velocity desired based on a_target when not overshooting. + +# Lookup table for the minimum smooth deceleration during the ENTERING state +# depending on the actual maximum absolute lateral acceleration predicted on the turn ahead. +_ENTERING_SMOOTH_DECEL_V = [-0.2, -1.] # min decel value allowed on ENTERING state +_ENTERING_SMOOTH_DECEL_BP = [1.3, 3.] # absolute value of lat acc ahead + +# Lookup table for the acceleration for the TURNING state +# depending on the current lateral acceleration of the vehicle. +_TURNING_ACC_V = [0.5, 0., -0.4] # acc value +_TURNING_ACC_BP = [1.5, 2.3, 3.] # absolute value of current lat acc + +_LEAVING_ACC = 0.5 # Conformable acceleration to regain speed while leaving a turn. + + +class SmartCruiseControlVision: + v_target: float = 0 + a_target: float = 0. + v_ego: float = 0. + a_ego: float = 0. + output_v_target: float = V_CRUISE_UNSET + output_a_target: float = 0. + + def __init__(self): + self.params = Params() + self.frame = -1 + self.long_enabled = False + self.long_override = False + self.is_enabled = False + self.is_active = False + self.enabled = self.params.get_bool("SmartCruiseControlVision") + self.v_cruise_setpoint = 0. + + self.state = VisionState.disabled + self.current_lat_acc = 0. + self.max_pred_lat_acc = 0. + + def get_a_target_from_control(self) -> float: + return self.a_target + + def get_v_target_from_control(self) -> float: + if self.is_active: + return max(self.v_target, _MIN_V) + self.a_target * _NO_OVERSHOOT_TIME_HORIZON + + return V_CRUISE_UNSET + + def _update_params(self) -> None: + if self.frame % int(PARAMS_UPDATE_PERIOD / DT_MDL) == 0: + self.enabled = self.params.get_bool("SmartCruiseControlVision") + + def _update_calculations(self, sm: messaging.SubMaster) -> None: + if not self.long_enabled: + return + else: + rate_plan = np.array(np.abs(sm['modelV2'].orientationRate.z)) + vel_plan = np.array(sm['modelV2'].velocity.x) + + self.current_lat_acc = self.v_ego ** 2 * abs(sm['controlsState'].curvature) + + # get the maximum lat accel from the model + predicted_lat_accels = rate_plan * vel_plan + self.max_pred_lat_acc = np.amax(predicted_lat_accels) + + # get the maximum curve based on the current velocity + v_ego = max(self.v_ego, 0.1) # ensure a value greater than 0 for calculations + max_curve = self.max_pred_lat_acc / (v_ego**2) + + # Get the target velocity for the maximum curve + self.v_target = (_A_LAT_REG_MAX / max_curve) ** 0.5 + + def _update_state_machine(self) -> tuple[bool, bool]: + # ENABLED, ENTERING, TURNING, LEAVING + if self.state != VisionState.disabled: + # longitudinal and feature disable always have priority in a non-disabled state + if not self.long_enabled or not self.enabled: + self.state = VisionState.disabled + elif self.long_override: + self.state = VisionState.overriding + + else: + # ENABLED + if self.state == VisionState.enabled: + # Do not enter a turn control cycle if the speed is low. + if self.v_ego <= _MIN_V: + pass + # If significant lateral acceleration is predicted ahead, then move to Entering turn state. + elif self.max_pred_lat_acc >= _ENTERING_PRED_LAT_ACC_TH: + self.state = VisionState.entering + + # OVERRIDING + elif self.state == VisionState.overriding: + if not self.long_override: + self.state = VisionState.enabled + + # ENTERING + elif self.state == VisionState.entering: + # Transition to Turning if current lateral acceleration is over the threshold. + if self.current_lat_acc >= _TURNING_LAT_ACC_TH: + self.state = VisionState.turning + # Abort if the predicted lateral acceleration drops + elif self.max_pred_lat_acc < _ABORT_ENTERING_PRED_LAT_ACC_TH: + self.state = VisionState.enabled + + # TURNING + elif self.state == VisionState.turning: + # Transition to Leaving if current lateral acceleration drops below a threshold. + if self.current_lat_acc <= _LEAVING_LAT_ACC_TH: + self.state = VisionState.leaving + + # LEAVING + elif self.state == VisionState.leaving: + # Transition back to Turning if current lateral acceleration goes back over the threshold. + if self.current_lat_acc >= _TURNING_LAT_ACC_TH: + self.state = VisionState.turning + # Finish if current lateral acceleration goes below a threshold. + elif self.current_lat_acc < _FINISH_LAT_ACC_TH: + self.state = VisionState.enabled + + # DISABLED + elif self.state == VisionState.disabled: + if self.long_enabled and self.enabled: + if self.long_override: + self.state = VisionState.overriding + else: + self.state = VisionState.enabled + + enabled = self.state in ENABLED_STATES + active = self.state in ACTIVE_STATES + + return enabled, active + + def _update_solution(self) -> float: + # DISABLED, ENABLED + if self.state not in ACTIVE_STATES: + # when not overshooting, calculate v_turn as the speed at the prediction horizon when following + # the smooth deceleration. + a_target = self.a_ego + # ENTERING + elif self.state == VisionState.entering: + # when not overshooting, target a smooth deceleration in preparation for a sharp turn to come. + a_target = np.interp(self.max_pred_lat_acc, _ENTERING_SMOOTH_DECEL_BP, _ENTERING_SMOOTH_DECEL_V) + # TURNING + elif self.state == VisionState.turning: + # When turning, we provide a target acceleration that is comfortable for the lateral acceleration felt. + a_target = np.interp(self.current_lat_acc, _TURNING_ACC_BP, _TURNING_ACC_V) + # LEAVING + elif self.state == VisionState.leaving: + # When leaving, we provide a comfortable acceleration to regain speed. + a_target = _LEAVING_ACC + else: + raise NotImplementedError(f"SCC-V state not supported: {self.state}") + + return a_target + + def update(self, sm: messaging.SubMaster, long_enabled: bool, long_override: bool, v_ego: float, a_ego: float, + v_cruise_setpoint: float) -> None: + self.long_enabled = long_enabled + self.long_override = long_override + self.v_ego = v_ego + self.a_ego = a_ego + self.v_cruise_setpoint = v_cruise_setpoint + + self._update_params() + self._update_calculations(sm) + + self.is_enabled, self.is_active = self._update_state_machine() + self.a_target = self._update_solution() + + self.output_v_target = self.get_v_target_from_control() + self.output_a_target = self.get_a_target_from_control() + + self.frame += 1 From 1f8941367d52a34c313049f1da6d84d57e2bf940 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Thu, 18 Sep 2025 00:06:16 -0400 Subject: [PATCH 084/159] Intelligent Cruise Button Management (ICBM) (#1242) * init * slightly more * check across all * publish on CC_SP * more infra setup * try it out for HKG for now * slight cleanup * oops * legacy * send * actually take over * expose toggle * icbm * need to allow * fix * name * small fixes * actually send it now * set default * use cs is_metric * offroad only lol * allow them all * fix * send desire as-is * use stock method * clean up hysteresis * speed cluster may be more accurate * rename * allow init and resume from pcmCruise * just send it * fix * only allow custom v cruise after no button press at initial enabled * no hysteresis for now * fix tests * fix min check * only apply to non pcm changes * add ICBM * some more ui * bump * slight cleanup * fixup * cleanup * type hints * type hints * bump * bump * bring back hysteresis * fix ui * do not spam if overriding or below allowed speed --- cereal/custom.capnp | 24 +++ common/params_keys.h | 1 + opendbc_repo | 2 +- selfdrive/car/card.py | 2 +- selfdrive/car/cruise.py | 13 +- selfdrive/car/helpers.py | 3 + selfdrive/car/tests/test_cruise_speed.py | 5 +- selfdrive/controls/controlsd.py | 5 +- selfdrive/selfdrived/selfdrived.py | 9 ++ .../qt/offroad/settings/longitudinal_panel.cc | 30 +++- .../qt/offroad/settings/longitudinal_panel.h | 2 + sunnypilot/selfdrive/car/cruise_ext.py | 52 ++++++- .../__init__.py | 0 .../controller.py | 137 ++++++++++++++++++ .../helpers.py | 8 + sunnypilot/selfdrive/car/interfaces.py | 10 ++ .../selfdrive/controls/controlsd_ext.py | 2 + 17 files changed, 289 insertions(+), 16 deletions(-) create mode 100644 sunnypilot/selfdrive/car/intelligent_cruise_button_management/__init__.py create mode 100644 sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py create mode 100644 sunnypilot/selfdrive/car/intelligent_cruise_button_management/helpers.py diff --git a/cereal/custom.capnp b/cereal/custom.capnp index 66aa1b71f8..0791841a55 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -25,6 +25,26 @@ struct ModularAssistiveDrivingSystem { } } +struct IntelligentCruiseButtonManagement { + state @0 :IntelligentCruiseButtonManagementState; + sendButton @1 :SendButtonState; + vTarget @2 :Float32; + + enum IntelligentCruiseButtonManagementState { + inactive @0; # No button press or default state + preActive @1; # Pre-active state before transitioning to increasing or decreasing + increasing @2; # Increasing speed + decreasing @3; # Decreasing speed + holding @4; # Holding steady speed + } + + enum SendButtonState { + none @0; + increase @1; + decrease @2; + } +} + # Same struct as Log.RadarState.LeadData struct LeadData { dRel @0 :Float32; @@ -48,6 +68,7 @@ struct LeadData { struct SelfdriveStateSP @0x81c2f05a394cf4af { mads @0 :ModularAssistiveDrivingSystem; + intelligentCruiseButtonManagement @1 :IntelligentCruiseButtonManagement; } struct ModelManagerSP @0xaedffd8f31e7b55d { @@ -210,6 +231,8 @@ struct OnroadEventSP @0xda96579883444c35 { struct CarParamsSP @0x80ae746ee2596b11 { flags @0 :UInt32; # flags for car specific quirks in sunnypilot safetyParam @1 : Int16; # flags for sunnypilot's custom safety flags + pcmCruiseSpeed @3 :Bool = true; + intelligentCruiseButtonManagementAvailable @4 :Bool; neuralNetworkLateralControl @2 :NeuralNetworkLateralControl; @@ -229,6 +252,7 @@ struct CarControlSP @0xa5cd762cd951a455 { params @1 :List(Param); leadOne @2 :LeadData; leadTwo @3 :LeadData; + intelligentCruiseButtonManagement @4 :IntelligentCruiseButtonManagement; struct Param { key @0 :Text; diff --git a/common/params_keys.h b/common/params_keys.h index f0511bf9c2..80d12c6b95 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -149,6 +149,7 @@ inline static std::unordered_map keys = { {"EnableCopyparty", {PERSISTENT | BACKUP, BOOL}}, {"EnableGithubRunner", {PERSISTENT | BACKUP, BOOL}}, {"GithubRunnerSufficientVoltage", {CLEAR_ON_MANAGER_START , BOOL}}, + {"IntelligentCruiseButtonManagement", {PERSISTENT | BACKUP , BOOL}}, {"InteractivityTimeout", {PERSISTENT | BACKUP, INT, "0"}}, {"IsDevelopmentBranch", {CLEAR_ON_MANAGER_START, BOOL}}, {"MaxTimeOffroad", {PERSISTENT | BACKUP, INT, "1800"}}, diff --git a/opendbc_repo b/opendbc_repo index 189dc3f78c..f54d85c7d9 160000 --- a/opendbc_repo +++ b/opendbc_repo @@ -1 +1 @@ -Subproject commit 189dc3f78c3b2eeb0402e69760602aa7149d05c9 +Subproject commit f54d85c7d99d45ada6f6978621b10c8b421b1923 diff --git a/selfdrive/car/card.py b/selfdrive/car/card.py index 820c68e895..2e52c00827 100755 --- a/selfdrive/car/card.py +++ b/selfdrive/car/card.py @@ -179,7 +179,7 @@ class Car: self.params.put_nonblocking("CarParamsSPPersistent", cp_sp_bytes) self.mock_carstate = MockCarState() - self.v_cruise_helper = VCruiseHelper(self.CP) + self.v_cruise_helper = VCruiseHelper(self.CP, self.CP_SP) self.is_metric = self.params.get_bool("IsMetric") self.experimental_mode = self.params.get_bool("ExperimentalMode") diff --git a/selfdrive/car/cruise.py b/selfdrive/car/cruise.py index 5ffb43f9e5..c82287d2b1 100644 --- a/selfdrive/car/cruise.py +++ b/selfdrive/car/cruise.py @@ -30,8 +30,8 @@ CRUISE_INTERVAL_SIGN = { class VCruiseHelper(VCruiseHelperSP): - def __init__(self, CP): - VCruiseHelperSP.__init__(self) + def __init__(self, CP, CP_SP): + VCruiseHelperSP.__init__(self, CP, CP_SP) self.CP = CP self.v_cruise_kph = V_CRUISE_UNSET self.v_cruise_cluster_kph = V_CRUISE_UNSET @@ -46,10 +46,13 @@ class VCruiseHelper(VCruiseHelperSP): def update_v_cruise(self, CS, enabled, is_metric): self.v_cruise_kph_last = self.v_cruise_kph + self.get_minimum_set_speed(is_metric) + if CS.cruiseState.available: - if not self.CP.pcmCruise: + _enabled = self.update_enabled_state(CS, enabled) + if not self.CP.pcmCruise or (not self.CP_SP.pcmCruiseSpeed and _enabled): # if stock cruise is completely disabled, then we can use our own set speed logic - self._update_v_cruise_non_pcm(CS, enabled, is_metric) + self._update_v_cruise_non_pcm(CS, _enabled, is_metric) self.v_cruise_cluster_kph = self.v_cruise_kph self.update_button_timers(CS, enabled) else: @@ -111,7 +114,7 @@ class VCruiseHelper(VCruiseHelperSP): if CS.gasPressed and button_type in (ButtonType.decelCruise, ButtonType.setCruise): self.v_cruise_kph = max(self.v_cruise_kph, CS.vEgo * CV.MS_TO_KPH) - self.v_cruise_kph = np.clip(round(self.v_cruise_kph, 1), V_CRUISE_MIN, V_CRUISE_MAX) + self.v_cruise_kph = np.clip(round(self.v_cruise_kph, 1), self.v_cruise_min, V_CRUISE_MAX) def update_button_timers(self, CS, enabled): # increment timer for buttons still pressed diff --git a/selfdrive/car/helpers.py b/selfdrive/car/helpers.py index 275c84479f..a7abc1976c 100644 --- a/selfdrive/car/helpers.py +++ b/selfdrive/car/helpers.py @@ -60,5 +60,8 @@ def convert_carControlSP(struct: capnp.lib.capnp._DynamicStructReader) -> struct struct_dataclass.params = [structs.CarControlSP.Param(**remove_deprecated(p)) for p in struct_dict.get('params', [])] struct_dataclass.leadOne = structs.LeadData(**remove_deprecated(struct_dict.get('leadOne', {}))) struct_dataclass.leadTwo = structs.LeadData(**remove_deprecated(struct_dict.get('leadTwo', {}))) + struct_dataclass.intelligentCruiseButtonManagement = structs.IntelligentCruiseButtonManagement( + **remove_deprecated(struct_dict.get('intelligentCruiseButtonManagement', {})) + ) return struct_dataclass diff --git a/selfdrive/car/tests/test_cruise_speed.py b/selfdrive/car/tests/test_cruise_speed.py index 4f9444d4bb..8512651de3 100644 --- a/selfdrive/car/tests/test_cruise_speed.py +++ b/selfdrive/car/tests/test_cruise_speed.py @@ -5,7 +5,7 @@ import numpy as np from parameterized import parameterized_class from cereal import log from openpilot.selfdrive.car.cruise import VCruiseHelper, V_CRUISE_MIN, V_CRUISE_MAX, V_CRUISE_INITIAL, IMPERIAL_INCREMENT -from cereal import car +from cereal import car, custom from openpilot.common.constants import CV from openpilot.selfdrive.test.longitudinal_maneuvers.maneuver import Maneuver @@ -49,7 +49,8 @@ class TestCruiseSpeed: class TestVCruiseHelper: def setup_method(self): self.CP = car.CarParams(pcmCruise=self.pcm_cruise) - self.v_cruise_helper = VCruiseHelper(self.CP) + self.CP_SP = custom.CarParamsSP() + self.v_cruise_helper = VCruiseHelper(self.CP, self.CP_SP) self.reset_cruise_speed_state() def reset_cruise_speed_state(self): diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 9e88a37690..3751efc87a 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -116,7 +116,8 @@ class Controls(ControlsExt, ModelStateBase): CC.latActive = _lat_active and not CS.steerFaultTemporary and not CS.steerFaultPermanent and \ (not standstill or self.CP.steerAtStandstill) - CC.longActive = CC.enabled and not any(e.overrideLongitudinal for e in self.sm['onroadEvents']) and self.CP.openpilotLongitudinalControl + CC.longActive = CC.enabled and not any(e.overrideLongitudinal for e in self.sm['onroadEvents']) and \ + (self.CP.openpilotLongitudinalControl or not self.CP_SP.pcmCruiseSpeed) actuators = CC.actuators actuators.longControlState = self.LoC.long_control_state @@ -168,7 +169,7 @@ class Controls(ControlsExt, ModelStateBase): CC.orientationNED = self.calibrated_pose.orientation.xyz.tolist() CC.angularVelocity = self.calibrated_pose.angular_velocity.xyz.tolist() - CC.cruiseControl.override = CC.enabled and not CC.longActive and self.CP.openpilotLongitudinalControl + CC.cruiseControl.override = CC.enabled and not CC.longActive and (self.CP.openpilotLongitudinalControl or not self.CP_SP.pcmCruiseSpeed) CC.cruiseControl.cancel = CS.cruiseState.enabled and (not CC.enabled or not self.CP.pcmCruise) CC.cruiseControl.resume = CC.enabled and CS.cruiseState.standstill and not self.sm['longitudinalPlan'].shouldStop diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index 749378f3a6..69dc51360b 100755 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -26,6 +26,7 @@ from openpilot.system.version import get_build_metadata from openpilot.sunnypilot.mads.mads import ModularAssistiveDrivingSystem from openpilot.sunnypilot.selfdrive.car.car_specific import CarSpecificEventsSP from openpilot.sunnypilot.selfdrive.car.cruise_helpers import CruiseHelper +from openpilot.sunnypilot.selfdrive.car.intelligent_cruise_button_management.controller import IntelligentCruiseButtonManagement from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP REPLAY = "REPLAY" in os.environ @@ -156,6 +157,7 @@ class SelfdriveD(CruiseHelper): self.events_sp_prev = [] self.mads = ModularAssistiveDrivingSystem(self) + self.icbm = IntelligentCruiseButtonManagement(self.CP, self.CP_SP) self.car_events_sp = CarSpecificEventsSP(self.CP, self.params) @@ -442,6 +444,8 @@ class SelfdriveD(CruiseHelper): self.events.add(EventName.personalityChanged) self.experimental_mode_switched = False + self.icbm.run(CS, self.sm['carControl'], self.is_metric) + def data_sample(self): _car_state = messaging.recv_one(self.car_state_sock) CS = _car_state.carState if _car_state else self.CS_prev @@ -546,6 +550,11 @@ class SelfdriveD(CruiseHelper): mads.active = self.mads.active mads.available = self.mads.enabled_toggle + icbm = ss_sp.intelligentCruiseButtonManagement + icbm.state = self.icbm.state + icbm.sendButton = self.icbm.cruise_button + icbm.vTarget = self.icbm.v_target + self.pm.send('selfdriveStateSP', ss_sp_msg) # onroadEventsSP - logged every second or on change diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc index ac7b57e297..df4a6077b5 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc @@ -18,6 +18,16 @@ LongitudinalPanel::LongitudinalPanel(QWidget *parent) : QWidget(parent) { cruisePanelScroller = new ScrollViewSP(list, this); vlayout->addWidget(cruisePanelScroller); + intelligentCruiseButtonManagement = new ParamControlSP( + "IntelligentCruiseButtonManagement", + tr("Intelligent Cruise Button Management (ICBM) (Alpha)"), + tr("When enabled, sunnypilot will attempt to manage the built-in cruise control buttons by emulating button presses for limited longitudinal control."), + "", + this + ); + intelligentCruiseButtonManagement->setConfirmation(true, false); + list->addItem(intelligentCruiseButtonManagement); + SmartCruiseControlVision = new ParamControl( "SmartCruiseControlVision", tr("Smart Cruise Control - Vision"), @@ -42,16 +52,22 @@ void LongitudinalPanel::showEvent(QShowEvent *event) { void LongitudinalPanel::refresh(bool _offroad) { auto cp_bytes = params.get("CarParamsPersistent"); - if (!cp_bytes.empty()) { + auto cp_sp_bytes = params.get("CarParamsSPPersistent"); + if (!cp_bytes.empty() && !cp_sp_bytes.empty()) { AlignedBuffer aligned_buf; + AlignedBuffer aligned_buf_sp; capnp::FlatArrayMessageReader cmsg(aligned_buf.align(cp_bytes.data(), cp_bytes.size())); + capnp::FlatArrayMessageReader cmsg_sp(aligned_buf_sp.align(cp_sp_bytes.data(), cp_sp_bytes.size())); cereal::CarParams::Reader CP = cmsg.getRoot(); + cereal::CarParamsSP::Reader CP_SP = cmsg_sp.getRoot(); has_longitudinal_control = hasLongitudinalControl(CP); is_pcm_cruise = CP.getPcmCruise(); + intelligent_cruise_button_management_available = CP_SP.getIntelligentCruiseButtonManagementAvailable(); } else { has_longitudinal_control = false; is_pcm_cruise = false; + intelligent_cruise_button_management_available = false; } QString accEnabledDescription = tr("Enable custom Short & Long press increments for cruise speed increase/decrease."); @@ -63,7 +79,7 @@ void LongitudinalPanel::refresh(bool _offroad) { customAccIncrement->setDescription(onroadOnlyDescription); customAccIncrement->showDescription(); } else { - if (has_longitudinal_control) { + if (has_longitudinal_control || intelligent_cruise_button_management_available) { if (is_pcm_cruise) { customAccIncrement->setDescription(accPcmCruiseDisabledDescription); customAccIncrement->showDescription(); @@ -75,14 +91,20 @@ void LongitudinalPanel::refresh(bool _offroad) { customAccIncrement->toggleFlipped(false); customAccIncrement->setDescription(accNoLongDescription); customAccIncrement->showDescription(); + params.remove("IntelligentCruiseButtonManagement"); + intelligentCruiseButtonManagement->toggleFlipped(false); } } + bool icbm_allowed = intelligent_cruise_button_management_available && !has_longitudinal_control; + intelligentCruiseButtonManagement->setEnabled(icbm_allowed && offroad); + // enable toggle when long is available and is not PCM cruise - customAccIncrement->setEnabled(has_longitudinal_control && !is_pcm_cruise && !offroad); + bool cai_allowed = (has_longitudinal_control && !is_pcm_cruise) || icbm_allowed; + customAccIncrement->setEnabled(cai_allowed && !offroad); customAccIncrement->refresh(); - SmartCruiseControlVision->setEnabled(has_longitudinal_control); + SmartCruiseControlVision->setEnabled(has_longitudinal_control || icbm_allowed); offroad = _offroad; } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h index 36c35720e7..af89822595 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h @@ -23,6 +23,7 @@ private: Params params; bool has_longitudinal_control = false; bool is_pcm_cruise = false; + bool intelligent_cruise_button_management_available = false;; bool offroad = false; QStackedLayout *main_layout = nullptr; @@ -30,4 +31,5 @@ private: QWidget *cruisePanelScreen = nullptr; CustomAccIncrement *customAccIncrement = nullptr; ParamControl *SmartCruiseControlVision; + ParamControl *intelligentCruiseButtonManagement = nullptr; }; diff --git a/sunnypilot/selfdrive/car/cruise_ext.py b/sunnypilot/selfdrive/car/cruise_ext.py index f443aeee0e..716e3e1c93 100644 --- a/sunnypilot/selfdrive/car/cruise_ext.py +++ b/sunnypilot/selfdrive/car/cruise_ext.py @@ -7,19 +7,46 @@ See the LICENSE.md file in the root directory for more details. import numpy as np from cereal import car +from opendbc.car import structs from openpilot.common.params import Params +from openpilot.sunnypilot.selfdrive.car.intelligent_cruise_button_management.helpers import get_minimum_set_speed ButtonType = car.CarState.ButtonEvent.Type +CRUISE_BUTTON_TIMER = {ButtonType.decelCruise: 0, ButtonType.accelCruise: 0, + ButtonType.setCruise: 0, ButtonType.resumeCruise: 0, + ButtonType.cancel: 0, ButtonType.mainCruise: 0} + +V_CRUISE_MIN = 8 + + +def update_manual_button_timers(CS: car.CarState, button_timers: dict[car.CarState.ButtonEvent.Type, int]) -> None: + # increment timer for buttons still pressed + for k in button_timers: + if button_timers[k] > 0: + button_timers[k] += 1 + + for b in CS.buttonEvents: + if b.type.raw in button_timers: + # Start/end timer and store current state on change of button pressed + button_timers[b.type.raw] = 1 if b.pressed else 0 + + class VCruiseHelperSP: - def __init__(self) -> None: + def __init__(self, CP: structs.CarParams, CP_SP: structs.CarParamsSP) -> None: + self.CP = CP + self.CP_SP = CP_SP self.params = Params() + self.v_cruise_min = 0 + self.enabled_prev = False self.custom_acc_enabled = self.params.get_bool("CustomAccIncrementsEnabled") self.short_increment = self.params.get("CustomAccShortPressIncrement", return_default=True) self.long_increment = self.params.get("CustomAccLongPressIncrement", return_default=True) + self.enable_button_timers = CRUISE_BUTTON_TIMER + def read_custom_set_speed_params(self) -> None: self.custom_acc_enabled = self.params.get_bool("CustomAccIncrementsEnabled") self.short_increment = self.params.get("CustomAccShortPressIncrement", return_default=True) @@ -39,3 +66,26 @@ class VCruiseHelperSP: v_cruise_delta = v_cruise_delta * actual_increment return round_to_nearest, v_cruise_delta + + def get_minimum_set_speed(self, is_metric: bool) -> None: + if self.CP_SP.pcmCruiseSpeed: + self.v_cruise_min = V_CRUISE_MIN + return + + self.v_cruise_min = get_minimum_set_speed(is_metric) + + def update_enabled_state(self, CS: car.CarState, enabled: bool) -> bool: + # special enabled state for non pcmCruiseSpeed, unchanged for non pcmCruise + if not self.CP_SP.pcmCruiseSpeed: + update_manual_button_timers(CS, self.enable_button_timers) + button_pressed = any(self.enable_button_timers[k] > 0 for k in self.enable_button_timers) + + if enabled and not self.enabled_prev: + self.enabled_prev = not button_pressed + enabled = False + elif not enabled: + self.enabled_prev = enabled + + return enabled and self.enabled_prev + + return enabled diff --git a/sunnypilot/selfdrive/car/intelligent_cruise_button_management/__init__.py b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py new file mode 100644 index 0000000000..0b0957b828 --- /dev/null +++ b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py @@ -0,0 +1,137 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" +from cereal import car, custom +from opendbc.car import structs, apply_hysteresis +from openpilot.common.constants import CV +from openpilot.common.realtime import DT_CTRL +from openpilot.sunnypilot.selfdrive.car.intelligent_cruise_button_management.helpers import get_minimum_set_speed +from openpilot.sunnypilot.selfdrive.car.cruise_ext import CRUISE_BUTTON_TIMER, update_manual_button_timers + +LongitudinalPlanSource = custom.LongitudinalPlanSP.LongitudinalPlanSource +State = custom.IntelligentCruiseButtonManagement.IntelligentCruiseButtonManagementState +SendButtonState = custom.IntelligentCruiseButtonManagement.SendButtonState + +ALLOWED_SPEED_THRESHOLD = 1.8 # m/s, ~4 MPH +HYST_GAP = 0.75 +INACTIVE_TIMER = 0.4 + + +SEND_BUTTONS = { + State.increasing: SendButtonState.increase, + State.decreasing: SendButtonState.decrease, +} + + +class IntelligentCruiseButtonManagement: + def __init__(self, CP: structs.CarParams, CP_SP: structs.CarParamsSP): + self.CP = CP + self.CP_SP = CP_SP + + self.v_target = 0 + self.v_cruise_cluster = 0 + self.v_cruise_min = 0 + self.cruise_button = SendButtonState.none + self.state = State.inactive + self.pre_active_timer = 0 + + self.is_ready = False + self.is_ready_prev = False + self.v_target_ms_last = 0.0 + self.is_metric = False + + self.cruise_button_timers = CRUISE_BUTTON_TIMER + + @property + def v_cruise_equal(self) -> bool: + return self.v_target == self.v_cruise_cluster + + def update_calculations(self, CS: car.CarState) -> None: + speed_conv = CV.MS_TO_KPH if self.is_metric else CV.MS_TO_MPH + ms_conv = CV.KPH_TO_MS if self.is_metric else CV.MPH_TO_MS + v_cruise_ms = CS.vCruise * CV.KPH_TO_MS + + # all targets in m/s + v_targets = { + LongitudinalPlanSource.cruise: v_cruise_ms + } + source = min(v_targets, key=lambda k: v_targets[k]) + v_target_ms = v_targets[source] + + self.v_target_ms_last = apply_hysteresis(v_target_ms, self.v_target_ms_last, HYST_GAP * ms_conv) + + self.v_target = round(self.v_target_ms_last * speed_conv) + self.v_cruise_min = get_minimum_set_speed(self.is_metric) + self.v_cruise_cluster = round(CS.cruiseState.speedCluster * speed_conv) + + def update_state_machine(self) -> custom.IntelligentCruiseButtonManagement.SendButtonState: + self.pre_active_timer = max(0, self.pre_active_timer - 1) + + # HOLDING, ACCELERATING, DECELERATING, PRE_ACTIVE + if self.state != State.inactive: + if not self.is_ready: + self.state = State.inactive + + else: + # PRE_ACTIVE + if self.state == State.preActive: + if self.pre_active_timer <= 0: + if self.v_cruise_equal: + self.state = State.holding + + elif self.v_target > self.v_cruise_cluster: + self.state = State.increasing + + elif self.v_target < self.v_cruise_cluster and self.v_cruise_cluster > self.v_cruise_min: + self.state = State.decreasing + + # HOLDING + elif self.state == State.holding: + if not self.v_cruise_equal: + self.state = State.preActive + + # ACCELERATING + elif self.state == State.increasing: + if self.v_target <= self.v_cruise_cluster: + self.state = State.holding + + # DECELERATING + elif self.state == State.decreasing: + if self.v_target >= self.v_cruise_cluster or self.v_cruise_cluster <= self.v_cruise_min: + self.state = State.holding + + # INACTIVE + elif self.state == State.inactive: + if self.is_ready and not self.is_ready_prev: + self.pre_active_timer = int(INACTIVE_TIMER / DT_CTRL) + self.state = State.preActive + + send_button = SEND_BUTTONS.get(self.state, SendButtonState.none) + + return send_button + + def update_readiness(self, CS: car.CarState, CC: car.CarControl) -> None: + update_manual_button_timers(CS, self.cruise_button_timers) + + allowed_speed = CS.vEgo > ALLOWED_SPEED_THRESHOLD + ready = CS.cruiseState.enabled and allowed_speed and not CC.cruiseControl.override and not CC.cruiseControl.cancel and \ + not CC.cruiseControl.resume + button_pressed = any(self.cruise_button_timers[k] > 0 for k in self.cruise_button_timers) + + self.is_ready = ready and not button_pressed + + def run(self, CS: car.CarState, CC: car.CarControl, is_metric: bool) -> None: + if self.CP_SP.pcmCruiseSpeed: + return + + self.is_metric = is_metric + + self.update_calculations(CS) + self.update_readiness(CS, CC) + + self.cruise_button = self.update_state_machine() + + self.is_ready_prev = self.is_ready diff --git a/sunnypilot/selfdrive/car/intelligent_cruise_button_management/helpers.py b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/helpers.py new file mode 100644 index 0000000000..eb4bbdecb5 --- /dev/null +++ b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/helpers.py @@ -0,0 +1,8 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" +def get_minimum_set_speed(is_metric: bool) -> int: + return 30 if is_metric else 20 diff --git a/sunnypilot/selfdrive/car/interfaces.py b/sunnypilot/selfdrive/car/interfaces.py index cd7a24b63b..55244caa57 100644 --- a/sunnypilot/selfdrive/car/interfaces.py +++ b/sunnypilot/selfdrive/car/interfaces.py @@ -43,11 +43,21 @@ def _initialize_neural_network_lateral_control(CI: CarInterfaceBase, CP: structs CP_SP.neuralNetworkLateralControl.fuzzyFingerprint = not exact_match +def _initialize_intelligent_cruise_button_management(CP: structs.CarParams, CP_SP: structs.CarParamsSP, params: Params = None) -> None: + if params is None: + params = Params() + + icbm_enabled = params.get_bool("IntelligentCruiseButtonManagement") + if icbm_enabled and CP_SP.intelligentCruiseButtonManagementAvailable and not CP.openpilotLongitudinalControl: + CP_SP.pcmCruiseSpeed = False + + def setup_interfaces(CI: CarInterfaceBase, params: Params = None) -> None: CP = CI.CP CP_SP = CI.CP_SP _initialize_neural_network_lateral_control(CI, CP, CP_SP, params) + _initialize_intelligent_cruise_button_management(CP, CP_SP, params) def initialize_params(params) -> list[dict[str, Any]]: diff --git a/sunnypilot/selfdrive/controls/controlsd_ext.py b/sunnypilot/selfdrive/controls/controlsd_ext.py index a096b7dc8c..e0f9326bf8 100644 --- a/sunnypilot/selfdrive/controls/controlsd_ext.py +++ b/sunnypilot/selfdrive/controls/controlsd_ext.py @@ -75,6 +75,8 @@ class ControlsExt: CC_SP.params = self.param_store.param_list + CC_SP.intelligentCruiseButtonManagement = sm['selfdriveStateSP'].intelligentCruiseButtonManagement + return CC_SP @staticmethod From 4441671227ab6936c60a5f8898a4c03ef7bee2b6 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Thu, 18 Sep 2025 16:02:51 -0400 Subject: [PATCH 085/159] Revert "Intelligent Cruise Button Management (ICBM)" (#1257) Revert "Intelligent Cruise Button Management (ICBM) (#1242)" This reverts commit 1f8941367d52a34c313049f1da6d84d57e2bf940. --- cereal/custom.capnp | 24 --- common/params_keys.h | 1 - opendbc_repo | 2 +- selfdrive/car/card.py | 2 +- selfdrive/car/cruise.py | 13 +- selfdrive/car/helpers.py | 3 - selfdrive/car/tests/test_cruise_speed.py | 5 +- selfdrive/controls/controlsd.py | 5 +- selfdrive/selfdrived/selfdrived.py | 9 -- .../qt/offroad/settings/longitudinal_panel.cc | 30 +--- .../qt/offroad/settings/longitudinal_panel.h | 2 - sunnypilot/selfdrive/car/cruise_ext.py | 52 +------ .../__init__.py | 0 .../controller.py | 137 ------------------ .../helpers.py | 8 - sunnypilot/selfdrive/car/interfaces.py | 10 -- .../selfdrive/controls/controlsd_ext.py | 2 - 17 files changed, 16 insertions(+), 289 deletions(-) delete mode 100644 sunnypilot/selfdrive/car/intelligent_cruise_button_management/__init__.py delete mode 100644 sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py delete mode 100644 sunnypilot/selfdrive/car/intelligent_cruise_button_management/helpers.py diff --git a/cereal/custom.capnp b/cereal/custom.capnp index 0791841a55..66aa1b71f8 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -25,26 +25,6 @@ struct ModularAssistiveDrivingSystem { } } -struct IntelligentCruiseButtonManagement { - state @0 :IntelligentCruiseButtonManagementState; - sendButton @1 :SendButtonState; - vTarget @2 :Float32; - - enum IntelligentCruiseButtonManagementState { - inactive @0; # No button press or default state - preActive @1; # Pre-active state before transitioning to increasing or decreasing - increasing @2; # Increasing speed - decreasing @3; # Decreasing speed - holding @4; # Holding steady speed - } - - enum SendButtonState { - none @0; - increase @1; - decrease @2; - } -} - # Same struct as Log.RadarState.LeadData struct LeadData { dRel @0 :Float32; @@ -68,7 +48,6 @@ struct LeadData { struct SelfdriveStateSP @0x81c2f05a394cf4af { mads @0 :ModularAssistiveDrivingSystem; - intelligentCruiseButtonManagement @1 :IntelligentCruiseButtonManagement; } struct ModelManagerSP @0xaedffd8f31e7b55d { @@ -231,8 +210,6 @@ struct OnroadEventSP @0xda96579883444c35 { struct CarParamsSP @0x80ae746ee2596b11 { flags @0 :UInt32; # flags for car specific quirks in sunnypilot safetyParam @1 : Int16; # flags for sunnypilot's custom safety flags - pcmCruiseSpeed @3 :Bool = true; - intelligentCruiseButtonManagementAvailable @4 :Bool; neuralNetworkLateralControl @2 :NeuralNetworkLateralControl; @@ -252,7 +229,6 @@ struct CarControlSP @0xa5cd762cd951a455 { params @1 :List(Param); leadOne @2 :LeadData; leadTwo @3 :LeadData; - intelligentCruiseButtonManagement @4 :IntelligentCruiseButtonManagement; struct Param { key @0 :Text; diff --git a/common/params_keys.h b/common/params_keys.h index 80d12c6b95..f0511bf9c2 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -149,7 +149,6 @@ inline static std::unordered_map keys = { {"EnableCopyparty", {PERSISTENT | BACKUP, BOOL}}, {"EnableGithubRunner", {PERSISTENT | BACKUP, BOOL}}, {"GithubRunnerSufficientVoltage", {CLEAR_ON_MANAGER_START , BOOL}}, - {"IntelligentCruiseButtonManagement", {PERSISTENT | BACKUP , BOOL}}, {"InteractivityTimeout", {PERSISTENT | BACKUP, INT, "0"}}, {"IsDevelopmentBranch", {CLEAR_ON_MANAGER_START, BOOL}}, {"MaxTimeOffroad", {PERSISTENT | BACKUP, INT, "1800"}}, diff --git a/opendbc_repo b/opendbc_repo index f54d85c7d9..189dc3f78c 160000 --- a/opendbc_repo +++ b/opendbc_repo @@ -1 +1 @@ -Subproject commit f54d85c7d99d45ada6f6978621b10c8b421b1923 +Subproject commit 189dc3f78c3b2eeb0402e69760602aa7149d05c9 diff --git a/selfdrive/car/card.py b/selfdrive/car/card.py index 2e52c00827..820c68e895 100755 --- a/selfdrive/car/card.py +++ b/selfdrive/car/card.py @@ -179,7 +179,7 @@ class Car: self.params.put_nonblocking("CarParamsSPPersistent", cp_sp_bytes) self.mock_carstate = MockCarState() - self.v_cruise_helper = VCruiseHelper(self.CP, self.CP_SP) + self.v_cruise_helper = VCruiseHelper(self.CP) self.is_metric = self.params.get_bool("IsMetric") self.experimental_mode = self.params.get_bool("ExperimentalMode") diff --git a/selfdrive/car/cruise.py b/selfdrive/car/cruise.py index c82287d2b1..5ffb43f9e5 100644 --- a/selfdrive/car/cruise.py +++ b/selfdrive/car/cruise.py @@ -30,8 +30,8 @@ CRUISE_INTERVAL_SIGN = { class VCruiseHelper(VCruiseHelperSP): - def __init__(self, CP, CP_SP): - VCruiseHelperSP.__init__(self, CP, CP_SP) + def __init__(self, CP): + VCruiseHelperSP.__init__(self) self.CP = CP self.v_cruise_kph = V_CRUISE_UNSET self.v_cruise_cluster_kph = V_CRUISE_UNSET @@ -46,13 +46,10 @@ class VCruiseHelper(VCruiseHelperSP): def update_v_cruise(self, CS, enabled, is_metric): self.v_cruise_kph_last = self.v_cruise_kph - self.get_minimum_set_speed(is_metric) - if CS.cruiseState.available: - _enabled = self.update_enabled_state(CS, enabled) - if not self.CP.pcmCruise or (not self.CP_SP.pcmCruiseSpeed and _enabled): + if not self.CP.pcmCruise: # if stock cruise is completely disabled, then we can use our own set speed logic - self._update_v_cruise_non_pcm(CS, _enabled, is_metric) + self._update_v_cruise_non_pcm(CS, enabled, is_metric) self.v_cruise_cluster_kph = self.v_cruise_kph self.update_button_timers(CS, enabled) else: @@ -114,7 +111,7 @@ class VCruiseHelper(VCruiseHelperSP): if CS.gasPressed and button_type in (ButtonType.decelCruise, ButtonType.setCruise): self.v_cruise_kph = max(self.v_cruise_kph, CS.vEgo * CV.MS_TO_KPH) - self.v_cruise_kph = np.clip(round(self.v_cruise_kph, 1), self.v_cruise_min, V_CRUISE_MAX) + self.v_cruise_kph = np.clip(round(self.v_cruise_kph, 1), V_CRUISE_MIN, V_CRUISE_MAX) def update_button_timers(self, CS, enabled): # increment timer for buttons still pressed diff --git a/selfdrive/car/helpers.py b/selfdrive/car/helpers.py index a7abc1976c..275c84479f 100644 --- a/selfdrive/car/helpers.py +++ b/selfdrive/car/helpers.py @@ -60,8 +60,5 @@ def convert_carControlSP(struct: capnp.lib.capnp._DynamicStructReader) -> struct struct_dataclass.params = [structs.CarControlSP.Param(**remove_deprecated(p)) for p in struct_dict.get('params', [])] struct_dataclass.leadOne = structs.LeadData(**remove_deprecated(struct_dict.get('leadOne', {}))) struct_dataclass.leadTwo = structs.LeadData(**remove_deprecated(struct_dict.get('leadTwo', {}))) - struct_dataclass.intelligentCruiseButtonManagement = structs.IntelligentCruiseButtonManagement( - **remove_deprecated(struct_dict.get('intelligentCruiseButtonManagement', {})) - ) return struct_dataclass diff --git a/selfdrive/car/tests/test_cruise_speed.py b/selfdrive/car/tests/test_cruise_speed.py index 8512651de3..4f9444d4bb 100644 --- a/selfdrive/car/tests/test_cruise_speed.py +++ b/selfdrive/car/tests/test_cruise_speed.py @@ -5,7 +5,7 @@ import numpy as np from parameterized import parameterized_class from cereal import log from openpilot.selfdrive.car.cruise import VCruiseHelper, V_CRUISE_MIN, V_CRUISE_MAX, V_CRUISE_INITIAL, IMPERIAL_INCREMENT -from cereal import car, custom +from cereal import car from openpilot.common.constants import CV from openpilot.selfdrive.test.longitudinal_maneuvers.maneuver import Maneuver @@ -49,8 +49,7 @@ class TestCruiseSpeed: class TestVCruiseHelper: def setup_method(self): self.CP = car.CarParams(pcmCruise=self.pcm_cruise) - self.CP_SP = custom.CarParamsSP() - self.v_cruise_helper = VCruiseHelper(self.CP, self.CP_SP) + self.v_cruise_helper = VCruiseHelper(self.CP) self.reset_cruise_speed_state() def reset_cruise_speed_state(self): diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 3751efc87a..9e88a37690 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -116,8 +116,7 @@ class Controls(ControlsExt, ModelStateBase): CC.latActive = _lat_active and not CS.steerFaultTemporary and not CS.steerFaultPermanent and \ (not standstill or self.CP.steerAtStandstill) - CC.longActive = CC.enabled and not any(e.overrideLongitudinal for e in self.sm['onroadEvents']) and \ - (self.CP.openpilotLongitudinalControl or not self.CP_SP.pcmCruiseSpeed) + CC.longActive = CC.enabled and not any(e.overrideLongitudinal for e in self.sm['onroadEvents']) and self.CP.openpilotLongitudinalControl actuators = CC.actuators actuators.longControlState = self.LoC.long_control_state @@ -169,7 +168,7 @@ class Controls(ControlsExt, ModelStateBase): CC.orientationNED = self.calibrated_pose.orientation.xyz.tolist() CC.angularVelocity = self.calibrated_pose.angular_velocity.xyz.tolist() - CC.cruiseControl.override = CC.enabled and not CC.longActive and (self.CP.openpilotLongitudinalControl or not self.CP_SP.pcmCruiseSpeed) + CC.cruiseControl.override = CC.enabled and not CC.longActive and self.CP.openpilotLongitudinalControl CC.cruiseControl.cancel = CS.cruiseState.enabled and (not CC.enabled or not self.CP.pcmCruise) CC.cruiseControl.resume = CC.enabled and CS.cruiseState.standstill and not self.sm['longitudinalPlan'].shouldStop diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index 69dc51360b..749378f3a6 100755 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -26,7 +26,6 @@ from openpilot.system.version import get_build_metadata from openpilot.sunnypilot.mads.mads import ModularAssistiveDrivingSystem from openpilot.sunnypilot.selfdrive.car.car_specific import CarSpecificEventsSP from openpilot.sunnypilot.selfdrive.car.cruise_helpers import CruiseHelper -from openpilot.sunnypilot.selfdrive.car.intelligent_cruise_button_management.controller import IntelligentCruiseButtonManagement from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP REPLAY = "REPLAY" in os.environ @@ -157,7 +156,6 @@ class SelfdriveD(CruiseHelper): self.events_sp_prev = [] self.mads = ModularAssistiveDrivingSystem(self) - self.icbm = IntelligentCruiseButtonManagement(self.CP, self.CP_SP) self.car_events_sp = CarSpecificEventsSP(self.CP, self.params) @@ -444,8 +442,6 @@ class SelfdriveD(CruiseHelper): self.events.add(EventName.personalityChanged) self.experimental_mode_switched = False - self.icbm.run(CS, self.sm['carControl'], self.is_metric) - def data_sample(self): _car_state = messaging.recv_one(self.car_state_sock) CS = _car_state.carState if _car_state else self.CS_prev @@ -550,11 +546,6 @@ class SelfdriveD(CruiseHelper): mads.active = self.mads.active mads.available = self.mads.enabled_toggle - icbm = ss_sp.intelligentCruiseButtonManagement - icbm.state = self.icbm.state - icbm.sendButton = self.icbm.cruise_button - icbm.vTarget = self.icbm.v_target - self.pm.send('selfdriveStateSP', ss_sp_msg) # onroadEventsSP - logged every second or on change diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc index df4a6077b5..ac7b57e297 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc @@ -18,16 +18,6 @@ LongitudinalPanel::LongitudinalPanel(QWidget *parent) : QWidget(parent) { cruisePanelScroller = new ScrollViewSP(list, this); vlayout->addWidget(cruisePanelScroller); - intelligentCruiseButtonManagement = new ParamControlSP( - "IntelligentCruiseButtonManagement", - tr("Intelligent Cruise Button Management (ICBM) (Alpha)"), - tr("When enabled, sunnypilot will attempt to manage the built-in cruise control buttons by emulating button presses for limited longitudinal control."), - "", - this - ); - intelligentCruiseButtonManagement->setConfirmation(true, false); - list->addItem(intelligentCruiseButtonManagement); - SmartCruiseControlVision = new ParamControl( "SmartCruiseControlVision", tr("Smart Cruise Control - Vision"), @@ -52,22 +42,16 @@ void LongitudinalPanel::showEvent(QShowEvent *event) { void LongitudinalPanel::refresh(bool _offroad) { auto cp_bytes = params.get("CarParamsPersistent"); - auto cp_sp_bytes = params.get("CarParamsSPPersistent"); - if (!cp_bytes.empty() && !cp_sp_bytes.empty()) { + if (!cp_bytes.empty()) { AlignedBuffer aligned_buf; - AlignedBuffer aligned_buf_sp; capnp::FlatArrayMessageReader cmsg(aligned_buf.align(cp_bytes.data(), cp_bytes.size())); - capnp::FlatArrayMessageReader cmsg_sp(aligned_buf_sp.align(cp_sp_bytes.data(), cp_sp_bytes.size())); cereal::CarParams::Reader CP = cmsg.getRoot(); - cereal::CarParamsSP::Reader CP_SP = cmsg_sp.getRoot(); has_longitudinal_control = hasLongitudinalControl(CP); is_pcm_cruise = CP.getPcmCruise(); - intelligent_cruise_button_management_available = CP_SP.getIntelligentCruiseButtonManagementAvailable(); } else { has_longitudinal_control = false; is_pcm_cruise = false; - intelligent_cruise_button_management_available = false; } QString accEnabledDescription = tr("Enable custom Short & Long press increments for cruise speed increase/decrease."); @@ -79,7 +63,7 @@ void LongitudinalPanel::refresh(bool _offroad) { customAccIncrement->setDescription(onroadOnlyDescription); customAccIncrement->showDescription(); } else { - if (has_longitudinal_control || intelligent_cruise_button_management_available) { + if (has_longitudinal_control) { if (is_pcm_cruise) { customAccIncrement->setDescription(accPcmCruiseDisabledDescription); customAccIncrement->showDescription(); @@ -91,20 +75,14 @@ void LongitudinalPanel::refresh(bool _offroad) { customAccIncrement->toggleFlipped(false); customAccIncrement->setDescription(accNoLongDescription); customAccIncrement->showDescription(); - params.remove("IntelligentCruiseButtonManagement"); - intelligentCruiseButtonManagement->toggleFlipped(false); } } - bool icbm_allowed = intelligent_cruise_button_management_available && !has_longitudinal_control; - intelligentCruiseButtonManagement->setEnabled(icbm_allowed && offroad); - // enable toggle when long is available and is not PCM cruise - bool cai_allowed = (has_longitudinal_control && !is_pcm_cruise) || icbm_allowed; - customAccIncrement->setEnabled(cai_allowed && !offroad); + customAccIncrement->setEnabled(has_longitudinal_control && !is_pcm_cruise && !offroad); customAccIncrement->refresh(); - SmartCruiseControlVision->setEnabled(has_longitudinal_control || icbm_allowed); + SmartCruiseControlVision->setEnabled(has_longitudinal_control); offroad = _offroad; } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h index af89822595..36c35720e7 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h @@ -23,7 +23,6 @@ private: Params params; bool has_longitudinal_control = false; bool is_pcm_cruise = false; - bool intelligent_cruise_button_management_available = false;; bool offroad = false; QStackedLayout *main_layout = nullptr; @@ -31,5 +30,4 @@ private: QWidget *cruisePanelScreen = nullptr; CustomAccIncrement *customAccIncrement = nullptr; ParamControl *SmartCruiseControlVision; - ParamControl *intelligentCruiseButtonManagement = nullptr; }; diff --git a/sunnypilot/selfdrive/car/cruise_ext.py b/sunnypilot/selfdrive/car/cruise_ext.py index 716e3e1c93..f443aeee0e 100644 --- a/sunnypilot/selfdrive/car/cruise_ext.py +++ b/sunnypilot/selfdrive/car/cruise_ext.py @@ -7,46 +7,19 @@ See the LICENSE.md file in the root directory for more details. import numpy as np from cereal import car -from opendbc.car import structs from openpilot.common.params import Params -from openpilot.sunnypilot.selfdrive.car.intelligent_cruise_button_management.helpers import get_minimum_set_speed ButtonType = car.CarState.ButtonEvent.Type -CRUISE_BUTTON_TIMER = {ButtonType.decelCruise: 0, ButtonType.accelCruise: 0, - ButtonType.setCruise: 0, ButtonType.resumeCruise: 0, - ButtonType.cancel: 0, ButtonType.mainCruise: 0} - -V_CRUISE_MIN = 8 - - -def update_manual_button_timers(CS: car.CarState, button_timers: dict[car.CarState.ButtonEvent.Type, int]) -> None: - # increment timer for buttons still pressed - for k in button_timers: - if button_timers[k] > 0: - button_timers[k] += 1 - - for b in CS.buttonEvents: - if b.type.raw in button_timers: - # Start/end timer and store current state on change of button pressed - button_timers[b.type.raw] = 1 if b.pressed else 0 - - class VCruiseHelperSP: - def __init__(self, CP: structs.CarParams, CP_SP: structs.CarParamsSP) -> None: - self.CP = CP - self.CP_SP = CP_SP + def __init__(self) -> None: self.params = Params() - self.v_cruise_min = 0 - self.enabled_prev = False self.custom_acc_enabled = self.params.get_bool("CustomAccIncrementsEnabled") self.short_increment = self.params.get("CustomAccShortPressIncrement", return_default=True) self.long_increment = self.params.get("CustomAccLongPressIncrement", return_default=True) - self.enable_button_timers = CRUISE_BUTTON_TIMER - def read_custom_set_speed_params(self) -> None: self.custom_acc_enabled = self.params.get_bool("CustomAccIncrementsEnabled") self.short_increment = self.params.get("CustomAccShortPressIncrement", return_default=True) @@ -66,26 +39,3 @@ class VCruiseHelperSP: v_cruise_delta = v_cruise_delta * actual_increment return round_to_nearest, v_cruise_delta - - def get_minimum_set_speed(self, is_metric: bool) -> None: - if self.CP_SP.pcmCruiseSpeed: - self.v_cruise_min = V_CRUISE_MIN - return - - self.v_cruise_min = get_minimum_set_speed(is_metric) - - def update_enabled_state(self, CS: car.CarState, enabled: bool) -> bool: - # special enabled state for non pcmCruiseSpeed, unchanged for non pcmCruise - if not self.CP_SP.pcmCruiseSpeed: - update_manual_button_timers(CS, self.enable_button_timers) - button_pressed = any(self.enable_button_timers[k] > 0 for k in self.enable_button_timers) - - if enabled and not self.enabled_prev: - self.enabled_prev = not button_pressed - enabled = False - elif not enabled: - self.enabled_prev = enabled - - return enabled and self.enabled_prev - - return enabled diff --git a/sunnypilot/selfdrive/car/intelligent_cruise_button_management/__init__.py b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py deleted file mode 100644 index 0b0957b828..0000000000 --- a/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py +++ /dev/null @@ -1,137 +0,0 @@ -""" -Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. - -This file is part of sunnypilot and is licensed under the MIT License. -See the LICENSE.md file in the root directory for more details. -""" -from cereal import car, custom -from opendbc.car import structs, apply_hysteresis -from openpilot.common.constants import CV -from openpilot.common.realtime import DT_CTRL -from openpilot.sunnypilot.selfdrive.car.intelligent_cruise_button_management.helpers import get_minimum_set_speed -from openpilot.sunnypilot.selfdrive.car.cruise_ext import CRUISE_BUTTON_TIMER, update_manual_button_timers - -LongitudinalPlanSource = custom.LongitudinalPlanSP.LongitudinalPlanSource -State = custom.IntelligentCruiseButtonManagement.IntelligentCruiseButtonManagementState -SendButtonState = custom.IntelligentCruiseButtonManagement.SendButtonState - -ALLOWED_SPEED_THRESHOLD = 1.8 # m/s, ~4 MPH -HYST_GAP = 0.75 -INACTIVE_TIMER = 0.4 - - -SEND_BUTTONS = { - State.increasing: SendButtonState.increase, - State.decreasing: SendButtonState.decrease, -} - - -class IntelligentCruiseButtonManagement: - def __init__(self, CP: structs.CarParams, CP_SP: structs.CarParamsSP): - self.CP = CP - self.CP_SP = CP_SP - - self.v_target = 0 - self.v_cruise_cluster = 0 - self.v_cruise_min = 0 - self.cruise_button = SendButtonState.none - self.state = State.inactive - self.pre_active_timer = 0 - - self.is_ready = False - self.is_ready_prev = False - self.v_target_ms_last = 0.0 - self.is_metric = False - - self.cruise_button_timers = CRUISE_BUTTON_TIMER - - @property - def v_cruise_equal(self) -> bool: - return self.v_target == self.v_cruise_cluster - - def update_calculations(self, CS: car.CarState) -> None: - speed_conv = CV.MS_TO_KPH if self.is_metric else CV.MS_TO_MPH - ms_conv = CV.KPH_TO_MS if self.is_metric else CV.MPH_TO_MS - v_cruise_ms = CS.vCruise * CV.KPH_TO_MS - - # all targets in m/s - v_targets = { - LongitudinalPlanSource.cruise: v_cruise_ms - } - source = min(v_targets, key=lambda k: v_targets[k]) - v_target_ms = v_targets[source] - - self.v_target_ms_last = apply_hysteresis(v_target_ms, self.v_target_ms_last, HYST_GAP * ms_conv) - - self.v_target = round(self.v_target_ms_last * speed_conv) - self.v_cruise_min = get_minimum_set_speed(self.is_metric) - self.v_cruise_cluster = round(CS.cruiseState.speedCluster * speed_conv) - - def update_state_machine(self) -> custom.IntelligentCruiseButtonManagement.SendButtonState: - self.pre_active_timer = max(0, self.pre_active_timer - 1) - - # HOLDING, ACCELERATING, DECELERATING, PRE_ACTIVE - if self.state != State.inactive: - if not self.is_ready: - self.state = State.inactive - - else: - # PRE_ACTIVE - if self.state == State.preActive: - if self.pre_active_timer <= 0: - if self.v_cruise_equal: - self.state = State.holding - - elif self.v_target > self.v_cruise_cluster: - self.state = State.increasing - - elif self.v_target < self.v_cruise_cluster and self.v_cruise_cluster > self.v_cruise_min: - self.state = State.decreasing - - # HOLDING - elif self.state == State.holding: - if not self.v_cruise_equal: - self.state = State.preActive - - # ACCELERATING - elif self.state == State.increasing: - if self.v_target <= self.v_cruise_cluster: - self.state = State.holding - - # DECELERATING - elif self.state == State.decreasing: - if self.v_target >= self.v_cruise_cluster or self.v_cruise_cluster <= self.v_cruise_min: - self.state = State.holding - - # INACTIVE - elif self.state == State.inactive: - if self.is_ready and not self.is_ready_prev: - self.pre_active_timer = int(INACTIVE_TIMER / DT_CTRL) - self.state = State.preActive - - send_button = SEND_BUTTONS.get(self.state, SendButtonState.none) - - return send_button - - def update_readiness(self, CS: car.CarState, CC: car.CarControl) -> None: - update_manual_button_timers(CS, self.cruise_button_timers) - - allowed_speed = CS.vEgo > ALLOWED_SPEED_THRESHOLD - ready = CS.cruiseState.enabled and allowed_speed and not CC.cruiseControl.override and not CC.cruiseControl.cancel and \ - not CC.cruiseControl.resume - button_pressed = any(self.cruise_button_timers[k] > 0 for k in self.cruise_button_timers) - - self.is_ready = ready and not button_pressed - - def run(self, CS: car.CarState, CC: car.CarControl, is_metric: bool) -> None: - if self.CP_SP.pcmCruiseSpeed: - return - - self.is_metric = is_metric - - self.update_calculations(CS) - self.update_readiness(CS, CC) - - self.cruise_button = self.update_state_machine() - - self.is_ready_prev = self.is_ready diff --git a/sunnypilot/selfdrive/car/intelligent_cruise_button_management/helpers.py b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/helpers.py deleted file mode 100644 index eb4bbdecb5..0000000000 --- a/sunnypilot/selfdrive/car/intelligent_cruise_button_management/helpers.py +++ /dev/null @@ -1,8 +0,0 @@ -""" -Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. - -This file is part of sunnypilot and is licensed under the MIT License. -See the LICENSE.md file in the root directory for more details. -""" -def get_minimum_set_speed(is_metric: bool) -> int: - return 30 if is_metric else 20 diff --git a/sunnypilot/selfdrive/car/interfaces.py b/sunnypilot/selfdrive/car/interfaces.py index 55244caa57..cd7a24b63b 100644 --- a/sunnypilot/selfdrive/car/interfaces.py +++ b/sunnypilot/selfdrive/car/interfaces.py @@ -43,21 +43,11 @@ def _initialize_neural_network_lateral_control(CI: CarInterfaceBase, CP: structs CP_SP.neuralNetworkLateralControl.fuzzyFingerprint = not exact_match -def _initialize_intelligent_cruise_button_management(CP: structs.CarParams, CP_SP: structs.CarParamsSP, params: Params = None) -> None: - if params is None: - params = Params() - - icbm_enabled = params.get_bool("IntelligentCruiseButtonManagement") - if icbm_enabled and CP_SP.intelligentCruiseButtonManagementAvailable and not CP.openpilotLongitudinalControl: - CP_SP.pcmCruiseSpeed = False - - def setup_interfaces(CI: CarInterfaceBase, params: Params = None) -> None: CP = CI.CP CP_SP = CI.CP_SP _initialize_neural_network_lateral_control(CI, CP, CP_SP, params) - _initialize_intelligent_cruise_button_management(CP, CP_SP, params) def initialize_params(params) -> list[dict[str, Any]]: diff --git a/sunnypilot/selfdrive/controls/controlsd_ext.py b/sunnypilot/selfdrive/controls/controlsd_ext.py index e0f9326bf8..a096b7dc8c 100644 --- a/sunnypilot/selfdrive/controls/controlsd_ext.py +++ b/sunnypilot/selfdrive/controls/controlsd_ext.py @@ -75,8 +75,6 @@ class ControlsExt: CC_SP.params = self.param_store.param_list - CC_SP.intelligentCruiseButtonManagement = sm['selfdriveStateSP'].intelligentCruiseButtonManagement - return CC_SP @staticmethod From fb743d313e441e09c07b23d8497ebe98f3fa5c14 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Thu, 18 Sep 2025 16:47:40 -0400 Subject: [PATCH 086/159] Reapply "Intelligent Cruise Button Management (ICBM)" (#1257) (#1258) * Reapply "Intelligent Cruise Button Management (ICBM)" (#1257) This reverts commit 4441671227ab6936c60a5f8898a4c03ef7bee2b6. * ICBM: `pcmCruiseSpeed` is true during initialization * bump * fix tests --- cereal/custom.capnp | 26 +++- common/params_keys.h | 1 + opendbc_repo | 2 +- selfdrive/car/card.py | 2 +- selfdrive/car/cruise.py | 13 +- selfdrive/car/helpers.py | 3 + selfdrive/car/tests/test_cruise_speed.py | 9 +- selfdrive/controls/controlsd.py | 5 +- selfdrive/selfdrived/selfdrived.py | 9 ++ .../qt/offroad/settings/longitudinal_panel.cc | 30 +++- .../qt/offroad/settings/longitudinal_panel.h | 2 + sunnypilot/selfdrive/car/cruise_ext.py | 52 ++++++- .../__init__.py | 0 .../controller.py | 137 ++++++++++++++++++ .../helpers.py | 8 + sunnypilot/selfdrive/car/interfaces.py | 10 ++ .../selfdrive/car/tests/test_custom_cruise.py | 3 +- .../selfdrive/controls/controlsd_ext.py | 2 + 18 files changed, 294 insertions(+), 20 deletions(-) create mode 100644 sunnypilot/selfdrive/car/intelligent_cruise_button_management/__init__.py create mode 100644 sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py create mode 100644 sunnypilot/selfdrive/car/intelligent_cruise_button_management/helpers.py diff --git a/cereal/custom.capnp b/cereal/custom.capnp index 66aa1b71f8..c4b5464029 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -25,6 +25,26 @@ struct ModularAssistiveDrivingSystem { } } +struct IntelligentCruiseButtonManagement { + state @0 :IntelligentCruiseButtonManagementState; + sendButton @1 :SendButtonState; + vTarget @2 :Float32; + + enum IntelligentCruiseButtonManagementState { + inactive @0; # No button press or default state + preActive @1; # Pre-active state before transitioning to increasing or decreasing + increasing @2; # Increasing speed + decreasing @3; # Decreasing speed + holding @4; # Holding steady speed + } + + enum SendButtonState { + none @0; + increase @1; + decrease @2; + } +} + # Same struct as Log.RadarState.LeadData struct LeadData { dRel @0 :Float32; @@ -48,6 +68,7 @@ struct LeadData { struct SelfdriveStateSP @0x81c2f05a394cf4af { mads @0 :ModularAssistiveDrivingSystem; + intelligentCruiseButtonManagement @1 :IntelligentCruiseButtonManagement; } struct ModelManagerSP @0xaedffd8f31e7b55d { @@ -210,6 +231,8 @@ struct OnroadEventSP @0xda96579883444c35 { struct CarParamsSP @0x80ae746ee2596b11 { flags @0 :UInt32; # flags for car specific quirks in sunnypilot safetyParam @1 : Int16; # flags for sunnypilot's custom safety flags + pcmCruiseSpeed @3 :Bool; + intelligentCruiseButtonManagementAvailable @4 :Bool; neuralNetworkLateralControl @2 :NeuralNetworkLateralControl; @@ -229,6 +252,7 @@ struct CarControlSP @0xa5cd762cd951a455 { params @1 :List(Param); leadOne @2 :LeadData; leadTwo @3 :LeadData; + intelligentCruiseButtonManagement @4 :IntelligentCruiseButtonManagement; struct Param { key @0 :Text; @@ -237,7 +261,7 @@ struct CarControlSP @0xa5cd762cd951a455 { valueDEPRECATED @1 :Text; # The data type change may cause issues with backwards compatibility. } - + enum ParamType { string @0; bool @1; diff --git a/common/params_keys.h b/common/params_keys.h index f0511bf9c2..80d12c6b95 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -149,6 +149,7 @@ inline static std::unordered_map keys = { {"EnableCopyparty", {PERSISTENT | BACKUP, BOOL}}, {"EnableGithubRunner", {PERSISTENT | BACKUP, BOOL}}, {"GithubRunnerSufficientVoltage", {CLEAR_ON_MANAGER_START , BOOL}}, + {"IntelligentCruiseButtonManagement", {PERSISTENT | BACKUP , BOOL}}, {"InteractivityTimeout", {PERSISTENT | BACKUP, INT, "0"}}, {"IsDevelopmentBranch", {CLEAR_ON_MANAGER_START, BOOL}}, {"MaxTimeOffroad", {PERSISTENT | BACKUP, INT, "1800"}}, diff --git a/opendbc_repo b/opendbc_repo index 189dc3f78c..52d50f9841 160000 --- a/opendbc_repo +++ b/opendbc_repo @@ -1 +1 @@ -Subproject commit 189dc3f78c3b2eeb0402e69760602aa7149d05c9 +Subproject commit 52d50f984191d63cf6a79398b21df2d2e3b9236e diff --git a/selfdrive/car/card.py b/selfdrive/car/card.py index 820c68e895..2e52c00827 100755 --- a/selfdrive/car/card.py +++ b/selfdrive/car/card.py @@ -179,7 +179,7 @@ class Car: self.params.put_nonblocking("CarParamsSPPersistent", cp_sp_bytes) self.mock_carstate = MockCarState() - self.v_cruise_helper = VCruiseHelper(self.CP) + self.v_cruise_helper = VCruiseHelper(self.CP, self.CP_SP) self.is_metric = self.params.get_bool("IsMetric") self.experimental_mode = self.params.get_bool("ExperimentalMode") diff --git a/selfdrive/car/cruise.py b/selfdrive/car/cruise.py index 5ffb43f9e5..c82287d2b1 100644 --- a/selfdrive/car/cruise.py +++ b/selfdrive/car/cruise.py @@ -30,8 +30,8 @@ CRUISE_INTERVAL_SIGN = { class VCruiseHelper(VCruiseHelperSP): - def __init__(self, CP): - VCruiseHelperSP.__init__(self) + def __init__(self, CP, CP_SP): + VCruiseHelperSP.__init__(self, CP, CP_SP) self.CP = CP self.v_cruise_kph = V_CRUISE_UNSET self.v_cruise_cluster_kph = V_CRUISE_UNSET @@ -46,10 +46,13 @@ class VCruiseHelper(VCruiseHelperSP): def update_v_cruise(self, CS, enabled, is_metric): self.v_cruise_kph_last = self.v_cruise_kph + self.get_minimum_set_speed(is_metric) + if CS.cruiseState.available: - if not self.CP.pcmCruise: + _enabled = self.update_enabled_state(CS, enabled) + if not self.CP.pcmCruise or (not self.CP_SP.pcmCruiseSpeed and _enabled): # if stock cruise is completely disabled, then we can use our own set speed logic - self._update_v_cruise_non_pcm(CS, enabled, is_metric) + self._update_v_cruise_non_pcm(CS, _enabled, is_metric) self.v_cruise_cluster_kph = self.v_cruise_kph self.update_button_timers(CS, enabled) else: @@ -111,7 +114,7 @@ class VCruiseHelper(VCruiseHelperSP): if CS.gasPressed and button_type in (ButtonType.decelCruise, ButtonType.setCruise): self.v_cruise_kph = max(self.v_cruise_kph, CS.vEgo * CV.MS_TO_KPH) - self.v_cruise_kph = np.clip(round(self.v_cruise_kph, 1), V_CRUISE_MIN, V_CRUISE_MAX) + self.v_cruise_kph = np.clip(round(self.v_cruise_kph, 1), self.v_cruise_min, V_CRUISE_MAX) def update_button_timers(self, CS, enabled): # increment timer for buttons still pressed diff --git a/selfdrive/car/helpers.py b/selfdrive/car/helpers.py index 275c84479f..a7abc1976c 100644 --- a/selfdrive/car/helpers.py +++ b/selfdrive/car/helpers.py @@ -60,5 +60,8 @@ def convert_carControlSP(struct: capnp.lib.capnp._DynamicStructReader) -> struct struct_dataclass.params = [structs.CarControlSP.Param(**remove_deprecated(p)) for p in struct_dict.get('params', [])] struct_dataclass.leadOne = structs.LeadData(**remove_deprecated(struct_dict.get('leadOne', {}))) struct_dataclass.leadTwo = structs.LeadData(**remove_deprecated(struct_dict.get('leadTwo', {}))) + struct_dataclass.intelligentCruiseButtonManagement = structs.IntelligentCruiseButtonManagement( + **remove_deprecated(struct_dict.get('intelligentCruiseButtonManagement', {})) + ) return struct_dataclass diff --git a/selfdrive/car/tests/test_cruise_speed.py b/selfdrive/car/tests/test_cruise_speed.py index 4f9444d4bb..61bae68931 100644 --- a/selfdrive/car/tests/test_cruise_speed.py +++ b/selfdrive/car/tests/test_cruise_speed.py @@ -5,7 +5,7 @@ import numpy as np from parameterized import parameterized_class from cereal import log from openpilot.selfdrive.car.cruise import VCruiseHelper, V_CRUISE_MIN, V_CRUISE_MAX, V_CRUISE_INITIAL, IMPERIAL_INCREMENT -from cereal import car +from cereal import car, custom from openpilot.common.constants import CV from openpilot.selfdrive.test.longitudinal_maneuvers.maneuver import Maneuver @@ -44,12 +44,13 @@ class TestCruiseSpeed: assert simulation_steady_state == pytest.approx(cruise_speed, abs=.01), f'Did not reach {self.speed} m/s' -# TODO: test pcmCruise -@parameterized_class(('pcm_cruise',), [(False,)]) +# TODO: test pcmCruise and pcmCruiseSpeed +@parameterized_class(('pcm_cruise', 'pcm_cruise_speed'), [(False, True)]) class TestVCruiseHelper: def setup_method(self): self.CP = car.CarParams(pcmCruise=self.pcm_cruise) - self.v_cruise_helper = VCruiseHelper(self.CP) + self.CP_SP = custom.CarParamsSP(pcmCruiseSpeed=self.pcm_cruise_speed) + self.v_cruise_helper = VCruiseHelper(self.CP, self.CP_SP) self.reset_cruise_speed_state() def reset_cruise_speed_state(self): diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 9e88a37690..3751efc87a 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -116,7 +116,8 @@ class Controls(ControlsExt, ModelStateBase): CC.latActive = _lat_active and not CS.steerFaultTemporary and not CS.steerFaultPermanent and \ (not standstill or self.CP.steerAtStandstill) - CC.longActive = CC.enabled and not any(e.overrideLongitudinal for e in self.sm['onroadEvents']) and self.CP.openpilotLongitudinalControl + CC.longActive = CC.enabled and not any(e.overrideLongitudinal for e in self.sm['onroadEvents']) and \ + (self.CP.openpilotLongitudinalControl or not self.CP_SP.pcmCruiseSpeed) actuators = CC.actuators actuators.longControlState = self.LoC.long_control_state @@ -168,7 +169,7 @@ class Controls(ControlsExt, ModelStateBase): CC.orientationNED = self.calibrated_pose.orientation.xyz.tolist() CC.angularVelocity = self.calibrated_pose.angular_velocity.xyz.tolist() - CC.cruiseControl.override = CC.enabled and not CC.longActive and self.CP.openpilotLongitudinalControl + CC.cruiseControl.override = CC.enabled and not CC.longActive and (self.CP.openpilotLongitudinalControl or not self.CP_SP.pcmCruiseSpeed) CC.cruiseControl.cancel = CS.cruiseState.enabled and (not CC.enabled or not self.CP.pcmCruise) CC.cruiseControl.resume = CC.enabled and CS.cruiseState.standstill and not self.sm['longitudinalPlan'].shouldStop diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index 749378f3a6..69dc51360b 100755 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -26,6 +26,7 @@ from openpilot.system.version import get_build_metadata from openpilot.sunnypilot.mads.mads import ModularAssistiveDrivingSystem from openpilot.sunnypilot.selfdrive.car.car_specific import CarSpecificEventsSP from openpilot.sunnypilot.selfdrive.car.cruise_helpers import CruiseHelper +from openpilot.sunnypilot.selfdrive.car.intelligent_cruise_button_management.controller import IntelligentCruiseButtonManagement from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP REPLAY = "REPLAY" in os.environ @@ -156,6 +157,7 @@ class SelfdriveD(CruiseHelper): self.events_sp_prev = [] self.mads = ModularAssistiveDrivingSystem(self) + self.icbm = IntelligentCruiseButtonManagement(self.CP, self.CP_SP) self.car_events_sp = CarSpecificEventsSP(self.CP, self.params) @@ -442,6 +444,8 @@ class SelfdriveD(CruiseHelper): self.events.add(EventName.personalityChanged) self.experimental_mode_switched = False + self.icbm.run(CS, self.sm['carControl'], self.is_metric) + def data_sample(self): _car_state = messaging.recv_one(self.car_state_sock) CS = _car_state.carState if _car_state else self.CS_prev @@ -546,6 +550,11 @@ class SelfdriveD(CruiseHelper): mads.active = self.mads.active mads.available = self.mads.enabled_toggle + icbm = ss_sp.intelligentCruiseButtonManagement + icbm.state = self.icbm.state + icbm.sendButton = self.icbm.cruise_button + icbm.vTarget = self.icbm.v_target + self.pm.send('selfdriveStateSP', ss_sp_msg) # onroadEventsSP - logged every second or on change diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc index ac7b57e297..df4a6077b5 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc @@ -18,6 +18,16 @@ LongitudinalPanel::LongitudinalPanel(QWidget *parent) : QWidget(parent) { cruisePanelScroller = new ScrollViewSP(list, this); vlayout->addWidget(cruisePanelScroller); + intelligentCruiseButtonManagement = new ParamControlSP( + "IntelligentCruiseButtonManagement", + tr("Intelligent Cruise Button Management (ICBM) (Alpha)"), + tr("When enabled, sunnypilot will attempt to manage the built-in cruise control buttons by emulating button presses for limited longitudinal control."), + "", + this + ); + intelligentCruiseButtonManagement->setConfirmation(true, false); + list->addItem(intelligentCruiseButtonManagement); + SmartCruiseControlVision = new ParamControl( "SmartCruiseControlVision", tr("Smart Cruise Control - Vision"), @@ -42,16 +52,22 @@ void LongitudinalPanel::showEvent(QShowEvent *event) { void LongitudinalPanel::refresh(bool _offroad) { auto cp_bytes = params.get("CarParamsPersistent"); - if (!cp_bytes.empty()) { + auto cp_sp_bytes = params.get("CarParamsSPPersistent"); + if (!cp_bytes.empty() && !cp_sp_bytes.empty()) { AlignedBuffer aligned_buf; + AlignedBuffer aligned_buf_sp; capnp::FlatArrayMessageReader cmsg(aligned_buf.align(cp_bytes.data(), cp_bytes.size())); + capnp::FlatArrayMessageReader cmsg_sp(aligned_buf_sp.align(cp_sp_bytes.data(), cp_sp_bytes.size())); cereal::CarParams::Reader CP = cmsg.getRoot(); + cereal::CarParamsSP::Reader CP_SP = cmsg_sp.getRoot(); has_longitudinal_control = hasLongitudinalControl(CP); is_pcm_cruise = CP.getPcmCruise(); + intelligent_cruise_button_management_available = CP_SP.getIntelligentCruiseButtonManagementAvailable(); } else { has_longitudinal_control = false; is_pcm_cruise = false; + intelligent_cruise_button_management_available = false; } QString accEnabledDescription = tr("Enable custom Short & Long press increments for cruise speed increase/decrease."); @@ -63,7 +79,7 @@ void LongitudinalPanel::refresh(bool _offroad) { customAccIncrement->setDescription(onroadOnlyDescription); customAccIncrement->showDescription(); } else { - if (has_longitudinal_control) { + if (has_longitudinal_control || intelligent_cruise_button_management_available) { if (is_pcm_cruise) { customAccIncrement->setDescription(accPcmCruiseDisabledDescription); customAccIncrement->showDescription(); @@ -75,14 +91,20 @@ void LongitudinalPanel::refresh(bool _offroad) { customAccIncrement->toggleFlipped(false); customAccIncrement->setDescription(accNoLongDescription); customAccIncrement->showDescription(); + params.remove("IntelligentCruiseButtonManagement"); + intelligentCruiseButtonManagement->toggleFlipped(false); } } + bool icbm_allowed = intelligent_cruise_button_management_available && !has_longitudinal_control; + intelligentCruiseButtonManagement->setEnabled(icbm_allowed && offroad); + // enable toggle when long is available and is not PCM cruise - customAccIncrement->setEnabled(has_longitudinal_control && !is_pcm_cruise && !offroad); + bool cai_allowed = (has_longitudinal_control && !is_pcm_cruise) || icbm_allowed; + customAccIncrement->setEnabled(cai_allowed && !offroad); customAccIncrement->refresh(); - SmartCruiseControlVision->setEnabled(has_longitudinal_control); + SmartCruiseControlVision->setEnabled(has_longitudinal_control || icbm_allowed); offroad = _offroad; } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h index 36c35720e7..af89822595 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h @@ -23,6 +23,7 @@ private: Params params; bool has_longitudinal_control = false; bool is_pcm_cruise = false; + bool intelligent_cruise_button_management_available = false;; bool offroad = false; QStackedLayout *main_layout = nullptr; @@ -30,4 +31,5 @@ private: QWidget *cruisePanelScreen = nullptr; CustomAccIncrement *customAccIncrement = nullptr; ParamControl *SmartCruiseControlVision; + ParamControl *intelligentCruiseButtonManagement = nullptr; }; diff --git a/sunnypilot/selfdrive/car/cruise_ext.py b/sunnypilot/selfdrive/car/cruise_ext.py index f443aeee0e..716e3e1c93 100644 --- a/sunnypilot/selfdrive/car/cruise_ext.py +++ b/sunnypilot/selfdrive/car/cruise_ext.py @@ -7,19 +7,46 @@ See the LICENSE.md file in the root directory for more details. import numpy as np from cereal import car +from opendbc.car import structs from openpilot.common.params import Params +from openpilot.sunnypilot.selfdrive.car.intelligent_cruise_button_management.helpers import get_minimum_set_speed ButtonType = car.CarState.ButtonEvent.Type +CRUISE_BUTTON_TIMER = {ButtonType.decelCruise: 0, ButtonType.accelCruise: 0, + ButtonType.setCruise: 0, ButtonType.resumeCruise: 0, + ButtonType.cancel: 0, ButtonType.mainCruise: 0} + +V_CRUISE_MIN = 8 + + +def update_manual_button_timers(CS: car.CarState, button_timers: dict[car.CarState.ButtonEvent.Type, int]) -> None: + # increment timer for buttons still pressed + for k in button_timers: + if button_timers[k] > 0: + button_timers[k] += 1 + + for b in CS.buttonEvents: + if b.type.raw in button_timers: + # Start/end timer and store current state on change of button pressed + button_timers[b.type.raw] = 1 if b.pressed else 0 + + class VCruiseHelperSP: - def __init__(self) -> None: + def __init__(self, CP: structs.CarParams, CP_SP: structs.CarParamsSP) -> None: + self.CP = CP + self.CP_SP = CP_SP self.params = Params() + self.v_cruise_min = 0 + self.enabled_prev = False self.custom_acc_enabled = self.params.get_bool("CustomAccIncrementsEnabled") self.short_increment = self.params.get("CustomAccShortPressIncrement", return_default=True) self.long_increment = self.params.get("CustomAccLongPressIncrement", return_default=True) + self.enable_button_timers = CRUISE_BUTTON_TIMER + def read_custom_set_speed_params(self) -> None: self.custom_acc_enabled = self.params.get_bool("CustomAccIncrementsEnabled") self.short_increment = self.params.get("CustomAccShortPressIncrement", return_default=True) @@ -39,3 +66,26 @@ class VCruiseHelperSP: v_cruise_delta = v_cruise_delta * actual_increment return round_to_nearest, v_cruise_delta + + def get_minimum_set_speed(self, is_metric: bool) -> None: + if self.CP_SP.pcmCruiseSpeed: + self.v_cruise_min = V_CRUISE_MIN + return + + self.v_cruise_min = get_minimum_set_speed(is_metric) + + def update_enabled_state(self, CS: car.CarState, enabled: bool) -> bool: + # special enabled state for non pcmCruiseSpeed, unchanged for non pcmCruise + if not self.CP_SP.pcmCruiseSpeed: + update_manual_button_timers(CS, self.enable_button_timers) + button_pressed = any(self.enable_button_timers[k] > 0 for k in self.enable_button_timers) + + if enabled and not self.enabled_prev: + self.enabled_prev = not button_pressed + enabled = False + elif not enabled: + self.enabled_prev = enabled + + return enabled and self.enabled_prev + + return enabled diff --git a/sunnypilot/selfdrive/car/intelligent_cruise_button_management/__init__.py b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py new file mode 100644 index 0000000000..0b0957b828 --- /dev/null +++ b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py @@ -0,0 +1,137 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" +from cereal import car, custom +from opendbc.car import structs, apply_hysteresis +from openpilot.common.constants import CV +from openpilot.common.realtime import DT_CTRL +from openpilot.sunnypilot.selfdrive.car.intelligent_cruise_button_management.helpers import get_minimum_set_speed +from openpilot.sunnypilot.selfdrive.car.cruise_ext import CRUISE_BUTTON_TIMER, update_manual_button_timers + +LongitudinalPlanSource = custom.LongitudinalPlanSP.LongitudinalPlanSource +State = custom.IntelligentCruiseButtonManagement.IntelligentCruiseButtonManagementState +SendButtonState = custom.IntelligentCruiseButtonManagement.SendButtonState + +ALLOWED_SPEED_THRESHOLD = 1.8 # m/s, ~4 MPH +HYST_GAP = 0.75 +INACTIVE_TIMER = 0.4 + + +SEND_BUTTONS = { + State.increasing: SendButtonState.increase, + State.decreasing: SendButtonState.decrease, +} + + +class IntelligentCruiseButtonManagement: + def __init__(self, CP: structs.CarParams, CP_SP: structs.CarParamsSP): + self.CP = CP + self.CP_SP = CP_SP + + self.v_target = 0 + self.v_cruise_cluster = 0 + self.v_cruise_min = 0 + self.cruise_button = SendButtonState.none + self.state = State.inactive + self.pre_active_timer = 0 + + self.is_ready = False + self.is_ready_prev = False + self.v_target_ms_last = 0.0 + self.is_metric = False + + self.cruise_button_timers = CRUISE_BUTTON_TIMER + + @property + def v_cruise_equal(self) -> bool: + return self.v_target == self.v_cruise_cluster + + def update_calculations(self, CS: car.CarState) -> None: + speed_conv = CV.MS_TO_KPH if self.is_metric else CV.MS_TO_MPH + ms_conv = CV.KPH_TO_MS if self.is_metric else CV.MPH_TO_MS + v_cruise_ms = CS.vCruise * CV.KPH_TO_MS + + # all targets in m/s + v_targets = { + LongitudinalPlanSource.cruise: v_cruise_ms + } + source = min(v_targets, key=lambda k: v_targets[k]) + v_target_ms = v_targets[source] + + self.v_target_ms_last = apply_hysteresis(v_target_ms, self.v_target_ms_last, HYST_GAP * ms_conv) + + self.v_target = round(self.v_target_ms_last * speed_conv) + self.v_cruise_min = get_minimum_set_speed(self.is_metric) + self.v_cruise_cluster = round(CS.cruiseState.speedCluster * speed_conv) + + def update_state_machine(self) -> custom.IntelligentCruiseButtonManagement.SendButtonState: + self.pre_active_timer = max(0, self.pre_active_timer - 1) + + # HOLDING, ACCELERATING, DECELERATING, PRE_ACTIVE + if self.state != State.inactive: + if not self.is_ready: + self.state = State.inactive + + else: + # PRE_ACTIVE + if self.state == State.preActive: + if self.pre_active_timer <= 0: + if self.v_cruise_equal: + self.state = State.holding + + elif self.v_target > self.v_cruise_cluster: + self.state = State.increasing + + elif self.v_target < self.v_cruise_cluster and self.v_cruise_cluster > self.v_cruise_min: + self.state = State.decreasing + + # HOLDING + elif self.state == State.holding: + if not self.v_cruise_equal: + self.state = State.preActive + + # ACCELERATING + elif self.state == State.increasing: + if self.v_target <= self.v_cruise_cluster: + self.state = State.holding + + # DECELERATING + elif self.state == State.decreasing: + if self.v_target >= self.v_cruise_cluster or self.v_cruise_cluster <= self.v_cruise_min: + self.state = State.holding + + # INACTIVE + elif self.state == State.inactive: + if self.is_ready and not self.is_ready_prev: + self.pre_active_timer = int(INACTIVE_TIMER / DT_CTRL) + self.state = State.preActive + + send_button = SEND_BUTTONS.get(self.state, SendButtonState.none) + + return send_button + + def update_readiness(self, CS: car.CarState, CC: car.CarControl) -> None: + update_manual_button_timers(CS, self.cruise_button_timers) + + allowed_speed = CS.vEgo > ALLOWED_SPEED_THRESHOLD + ready = CS.cruiseState.enabled and allowed_speed and not CC.cruiseControl.override and not CC.cruiseControl.cancel and \ + not CC.cruiseControl.resume + button_pressed = any(self.cruise_button_timers[k] > 0 for k in self.cruise_button_timers) + + self.is_ready = ready and not button_pressed + + def run(self, CS: car.CarState, CC: car.CarControl, is_metric: bool) -> None: + if self.CP_SP.pcmCruiseSpeed: + return + + self.is_metric = is_metric + + self.update_calculations(CS) + self.update_readiness(CS, CC) + + self.cruise_button = self.update_state_machine() + + self.is_ready_prev = self.is_ready diff --git a/sunnypilot/selfdrive/car/intelligent_cruise_button_management/helpers.py b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/helpers.py new file mode 100644 index 0000000000..eb4bbdecb5 --- /dev/null +++ b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/helpers.py @@ -0,0 +1,8 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" +def get_minimum_set_speed(is_metric: bool) -> int: + return 30 if is_metric else 20 diff --git a/sunnypilot/selfdrive/car/interfaces.py b/sunnypilot/selfdrive/car/interfaces.py index cd7a24b63b..55244caa57 100644 --- a/sunnypilot/selfdrive/car/interfaces.py +++ b/sunnypilot/selfdrive/car/interfaces.py @@ -43,11 +43,21 @@ def _initialize_neural_network_lateral_control(CI: CarInterfaceBase, CP: structs CP_SP.neuralNetworkLateralControl.fuzzyFingerprint = not exact_match +def _initialize_intelligent_cruise_button_management(CP: structs.CarParams, CP_SP: structs.CarParamsSP, params: Params = None) -> None: + if params is None: + params = Params() + + icbm_enabled = params.get_bool("IntelligentCruiseButtonManagement") + if icbm_enabled and CP_SP.intelligentCruiseButtonManagementAvailable and not CP.openpilotLongitudinalControl: + CP_SP.pcmCruiseSpeed = False + + def setup_interfaces(CI: CarInterfaceBase, params: Params = None) -> None: CP = CI.CP CP_SP = CI.CP_SP _initialize_neural_network_lateral_control(CI, CP, CP_SP, params) + _initialize_intelligent_cruise_button_management(CP, CP_SP, params) def initialize_params(params) -> list[dict[str, Any]]: diff --git a/sunnypilot/selfdrive/car/tests/test_custom_cruise.py b/sunnypilot/selfdrive/car/tests/test_custom_cruise.py index 3bed8534ef..a1f7f8f027 100644 --- a/sunnypilot/selfdrive/car/tests/test_custom_cruise.py +++ b/sunnypilot/selfdrive/car/tests/test_custom_cruise.py @@ -11,7 +11,8 @@ ButtonEvent = car.CarState.ButtonEvent ButtonType = car.CarState.ButtonEvent.Type -@parameterized_class(('pcm_cruise',), [(False,)]) +# TODO: test pcmCruise and pcmCruiseSpeed +@parameterized_class(('pcm_cruise', 'pcm_cruise_speed'), [(False, True)]) class TestCustomAccIncrements(TestVCruiseHelper): def setup_method(self): TestVCruiseHelper.setup_method(self) diff --git a/sunnypilot/selfdrive/controls/controlsd_ext.py b/sunnypilot/selfdrive/controls/controlsd_ext.py index a096b7dc8c..e0f9326bf8 100644 --- a/sunnypilot/selfdrive/controls/controlsd_ext.py +++ b/sunnypilot/selfdrive/controls/controlsd_ext.py @@ -75,6 +75,8 @@ class ControlsExt: CC_SP.params = self.param_store.param_list + CC_SP.intelligentCruiseButtonManagement = sm['selfdriveStateSP'].intelligentCruiseButtonManagement + return CC_SP @staticmethod From 60e056cc0aaa58f5180668d7bd006b7c41ff1036 Mon Sep 17 00:00:00 2001 From: Kumar <36933347+rav4kumar@users.noreply.github.com> Date: Thu, 18 Sep 2025 21:34:03 -0700 Subject: [PATCH 087/159] mapd: Bump version `v1.10.0` -> `v1.11.0` (#1111) * bump mapd v1.10.1 * v1.11.0 * v1.11.0 * permission --------- Co-authored-by: DevTekVE Co-authored-by: Jason Wen --- sunnypilot/mapd/mapd_installer.py | 2 +- third_party/mapd_pfeiferj/mapd | Bin 9371832 -> 9371832 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/sunnypilot/mapd/mapd_installer.py b/sunnypilot/mapd/mapd_installer.py index 9f7a8c2a5c..e49ff8c64e 100755 --- a/sunnypilot/mapd/mapd_installer.py +++ b/sunnypilot/mapd/mapd_installer.py @@ -22,7 +22,7 @@ from openpilot.system.version import is_prebuilt from openpilot.sunnypilot.mapd import MAPD_PATH, MAPD_BIN_DIR import openpilot.system.sentry as sentry -VERSION = 'v1.10.0' +VERSION = 'v1.11.0' URL = f"https://github.com/pfeiferj/openpilot-mapd/releases/download/{VERSION}/mapd" diff --git a/third_party/mapd_pfeiferj/mapd b/third_party/mapd_pfeiferj/mapd index e5e45e2b989abfcec00474466f9e096a53274252..eb2372ceedb336ebe967067042d4c37c2204b71d 100755 GIT binary patch delta 3134822 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 z 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

guOeX!fh(Z@o;NepNQ&nE#Dm6~$4ZfWv1z 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

e1sC{kzX;>2%o< zRc*ISmlMn%liv)y<3SlS@XjBT^mmrg(iw8S=fYk_r}y?!58B<}q3=9DFkk`a6Z=>u z)lts*#4h-&pz2IlX385-5n=SLaCBc z4rl5Oyj%Y9Ecvd7-yx`JZ2RtTsXqNyT7HL2?Ca}`&SAdgNI7qHje}}%?df*kf@^p4 z?w@V>8_&|qZRwXgWU6ZRHZ(iz&-!#|^mAmE{}1XF*4r(m|G~AQGg!pu$QpnFR>``4KthN>%5e4SsE**>kabjiA@&%HI4+GCC-tb93co{>884@GHp_ zc{hC8Q}34D2kDu&-$On!M)jS#*6)AqcK<7Nt&g@sUF+cP!?gnU0or@F9A$uJCC5GT zJ_Cv)RC153?>EY=y%FkK@8>$V`$N>V-p@dFt@o3SYt_%sR5wpP%Psq2MAOSx|3gkS zvs68VYdv@qQji2i-zPh94B>t9PJZ+V9v$-1A64Q}{5%$4T=RIBx@P6yQaZ=&{_WK5 zekski@)7sTugvC`${q9N-R7RFye`p`_@|fa^(bAbt{F&=(kB|OEv1jCYkhzZ2vp^o?F?H}{DM+UA{Onxc+3OLRiF5%PA0kT zO~7A;TJLgg5sWn`jyQKQM!uVtFP2%TFtT?s+_xJ+)UZKmbmJ0O=;qPKOJp32%dh`h zpMK_EWRENNBA6&_F4Z2vrE?Zy6F2S^;2!Fs&B8spbBTs#FJPoQ~A!7KXeAoZa4mja|Ds#^+>qz;lNEqxd>bDZiPmT}zx(h3F%md1weT_9C2 zXbI8}3uxpcvRBgA;B^KpU#V*ymI}A~`*5uv^EAKw<43@=PqX6UW%p$d0ig zs%xDjuW`HfcY)!Dzlzr0p}i~Q4jc=tX&C+cv|%N>evN8Z%4i<_!`wBt`)HL{0;Y zfRe@DFkXcPp7;BL3l}Nz@g5`So_W4W@m0+le$05=O=B9T8g}eh+qB^s#;dM|d(gqB zDN)sUOV##nC64NlVUxZbyJ`38mg#Vk^cRR3lowK2R0z5c9Bb3Ys|nNB|| zrRB{RNWANp5IDTqcXrBNE$639Y8baZ#qq{#ZZq-Q?}&(T6_BP^7y6EKtZ(>ApKTB0 zD;KuDqG`{`=ZzY+FOtt1*){O9DNRv|latrTZvu;&-Oi{EA_aQeh@%b+(vG2(t16!}gA~vM*PytY0fL`eZHUlL2+JJb!!`;+$yIzoY`{f2fqg8!JmA*pfUXTSoQ*n!Jj_=U@>ttVR#dUg- z%!q~u#i)ve_)YZyRWbWo@iK}Y7R!$DuRYWhqL%^DeR)mMgWQE;nClZMqy(EH6!#KY zfaBjhU&OEdH19=O(C&@j+$N@YTGy#u)NH-HKB0muz4AdF`jXVuqYb%DJAfNb2)H}0HkvKLb=m_0`Eg<`9FboRIl2OXE>g6 zJ1_`l@D9+wh6cS03@)Je-vtII(4hB#et`2HK98i#_wl)zUV9%O0Gbc*3PMyqzz67P z2Yw+bZ-<=KugneQ%5L2Zq>`OLcv&-qU$xmT zS82BFd<%qwa$N{Vn$a#G9Q3nGr=Jhy8f)87xFkn~gh#6av)Dp+>w(O>A+KOr?uP36 z4xRf5;=l-7c#!#eej$tsKazLCQ;hqu%oaX|CVB@s_Q+uUEpNRUxZC%j8C1mIBPUoN z57K)|@^}}=JkJjaw^8LDd5?7h-$$rY2+jUPdYMSj-n)=%dEh+gY^hc&dTCqxv$fv z&t*UB^|02{gVpA1!=vB^)VtFUwPjhPm+>@g<6SME#^C7$;h#o7{!31=Ts}el_sPf2 zA+&EF6#Vv%IyMCO{DdQinO}UX$K@t}0ogl~CVc_Hy(=yK0yFbAefNc&;2ZndMVbQp zaQ{LN>bGBp_)51MllRLGVV_zw2dtFUH72b_9VX#Xdhi@78m4^i6Wp$V`|)zt9bk(@ zVTJ5$DNLcm$NeUGEW*<4cfv1%?JyN`oyTbXcO-Q_Acq@;oUOFz01T|J^n$?(K52F> zK)2K;(v|}<-0RLHt=l{x>dvj^U|y^Tpzyo)xNoW3m-z6(W*??d-j^~sEIdtn86dL_ z71l;r1v_go4Gn!%Uh*Z3BZ0?0feQw2z(9=AN5Rfib$y4B5J;LB<@Ze=(&TStM&Rd7 zZ{iDeMCd=imBE4UyFY`S*7fY{w@}7!ERXmOv536CnrYI1WHDc%kkTRf1Yd0>?T~zm zuU7Cq)SLfajw-O0U!)-X!_HphVtYl7=$_gaIA@{xy}hm6`>2(BJ8+K$j0I;fYcR|3 z^#i!(zxSzo9;GYvzy0yBP3bcH&?lx%!wXe#UoCC8?^Al0`k+neO!e2Rbh`TMQ96}I z{~&|RLFLnaz>*DgHb^M?kqSFW`w>dtY})suEVWj6S7p)s!*Xr65AQN|ZaqTq^`CWE zUv>R0#otZpn$;Z-WVH{igdT^2Zk003ZzZ1a-D-~qaH#B-N&t{WA6LrHA}Sgpn?Ypm zrCe{Gdy!T-zlXZ9(CTIR;|P6SC3kjC)xLx%UIh`w4A&5-sKW7^UY&<&Mz0r%WAWfo zSppZ_?rOOjr)5s6k-dG|r6I-whpzOb7i;8@?7|M(0<>fV7*vI$r6ZBLnHfG$E+vTF zw}>t2i(sSVD9R%p^#HOfB7Mz47(}II(!B(@EIgT8)a=ar|v!P*!r#|LIJm%hJ1u6DiSWKg6^4;DcR8}hm z-u2{nvC0@f5NnGZrz|bredeh2WNY#7`PBBP?2P)ih|9}5DpT41vk_MQ88q*xjIyn9 zT+vU8L0gOs6*Gm$OWm?%P31^R?SD}6aXA=$ zrvq7F3A5<_<1p*FzCa0v<8mUqx29p%ICPLh8Q-F5C*(mO=LE#`T`okHFmjx-1#;-l zpJbcZRP8@_w+W$*N_Br1Gc`9WBA8zLNy_;4Ac;!U=(Xc7s|;=NmjPFq5EeGzZEJFz$}E#T0*9I+F@hv`8KnR3N4gcM7kCSAyMv?8z&k z<)`ISad`U-vvE8uG5%+zs9(E%pX+YKK8o+I#AQi zPCxvNt->{rk;wU$5Bd~eqh|F=D7}70J`ta)-HIN$$f1jV&pO^qQfTM(J%!_lnBLFI zxb|iJoj3#&6i|r*!Egzlh3)1}8huU<>+;yHi_{;*1+jZ-)nnn5m;l=bP-^NOriv?a z{Geh6U`Yu-($BxhNIHH_4)hs>O`LbTG|Kn|CO#7qwdJtvc-;N4&Z|d#ecMese@20m z|3eo)(CJ?gYW6v0{3`ne{))ZX9Y@e8ewC{r5!-%4jDDF3OL5q5GTRL0={N96u1jw_*v;^7LpU@eme;+S<;MB`$-GQjDqL#grK_0Sh~^HyUW@Vri= z1;4}M21D2Ha-A7xhy8(HkdXh7<)~df`+~fax4T@bx`4s|Kz?;{D&NSWd3Ewpz6vMv zMLc?%c3qN^uDvKX@ZIm}+(r46E(3U>bn)^_5NlA%?~?xc3QE2#i;TxJk;#e2H55@V zqbT@_T*OVJ(&{U6OoVF{=cG2Q`!ZwQ|CvH<|CD1r@p63yP5)Eg-?nTCejq@u^hY}J zC)ym(Z7yu1ZkJI>y?l_HE_&Kw?`ZaWdW2maO)>rHz4ixnVA_-pq7i0$8r(jM%=Q5V z<;b?*gMZi)A>4at*{lI!Z(p>h<-G@6xp!|X_wH)t-t1QH&D?Xbphd^|t-N?kEBD5? za&Js4_i|dfcU{B1u8kue)Nr%$o)h;J-MWl5C`oUz4}fZ$;bHI8AG~7SMDPk2R(R!t z9vjps<~GbLqH3|YaBW1fl(6B2v)97Gh%ZFadJlUx5>jhD>^-e0G5Zus$k_+@-2gpa zS&{sma4rTO#wlc0J5CzXhH-abL(RM6BZIlS&yPU8!Zn8rad0s1vDp|N=H42!M@}l@ zgu>MwurXoNvI1hk4gQ-9&G5b-( z91XtcYQQM@`Y4_AwD;s_D(0G1kSw^le;lF61bYmXp@LTH)kC2tK&8)uN{$Io-w*nu?K$KDlQ&qY4=F>$88IP(kL6`1NC z;-Q&(YSl39=VG5TnF6({-5xlxsLsbe%9~*&R0yWgZSDD<^EY3l$7y?8U}hG5*Vc~n zJ3Y0x=xJZOi^;StT~3|bVZOYPO=?#xY&z|2XD>8(5a95$M^0(7$XD-fxyYYt<=)Cx z?mdos?n~n$Y#^+Dou%w2y(OLUvv-Opu7Lm@YdVmNu%>E61C&DX@&LXnag74H?d=16 zUUz-=E$@~g^h|sEXow3gp4f@bwYMjleON% z9bkV{AFfYnCM^iG_b|Uj+XC$`@nfhv*VyN0-?ix?Ey6$WJEhBj-zi^+A=V6~vKNoB05?l-LKHI~9mtW_24!nMD6-)3)ArOL#Q z(z@Qv?>g1H=kd(l@e)doP~Y4gXwt&$s*>^)d>cu7!|Y=^x!S#S_@W9{^aw^=3b-bp{XPJ#Gt|ssUP9Zy z(9m%E48+lI3C9#YKqtbnS;0zUvrj<{O2|sgnx@hsn?1==nM#{&_LOVR=0ncr`+PLQ zQS5)H=5Djca(s`l4>KR6Ny0wXyrX=Zun#u3J?nss#ZvksB=`WLEh6n{z5MepQp~w}6!SK1 zI}ds0T}&(+Wq>B7al`_#m9UOhd4ynsVTw>L+$inDSc;6Y3#680M%lCcRvy%$15 zzh7<>POGErAnQ40&mJru!nK7O@e)9db2);$2Rp^RQ7WL?B*eWl|I3qANZm1$R+Op4T<(~&4GS} z4kX%pggj%s?AFdSib%3gZT>+pX-W2=kU6bKmOTM9rXrrtUJW@ln*+i3) z?cv>dTZFu22r~EnKhC}bKB{W@|L$%Ygf!BVdp21T2r&c*B_XtILhn@p0ZE}F0t!!Q zCZQL>Tmi?1fHa9B0fB&sln9Eb1kfkQLsKXUB0)u2TK?a;_ilC*;_vzXd_H_~_ufjjSIL$rX*5xyfBBRY`^ zP3CAX)_G>_YOnWbzsTbfS<>X8Y*Vluq8HQTUaZetrmxcE-u!f$L?`VDs3IwNSq91xp%s zV7x(227E}+&%2JGe zH0|sGfpZUzF1x^)&Ksd{q*}kxLk@4qI^k`&q5i0$%*#L<@2uEG6-%)_<@P+G4-V4A zo^m6@Y*Kp4F{XoPc1NL~nJ)Ik$_dF3?T%=E*al}~yE(h4figPSx=npHMJZz=^yf}d z%J>-ld43ed^^(`OaIl@Vv0~h} zqwZl;&cXd>7a(z&bB?eLI1-!#6G=7Bfyr|vZcDdw4jd^%<>q$IDRZB_D;lQ-?3-QJ z{6tzh44i}A-!KPh29np4a*Q$NG|d9@(8wp{5I-h;RZ-Pg=dbb!M>AH(UeV z4X0C#zSn=Iky&z_*lT-0e@xN#*SDh#iu1nt0By*EZXHYev*h+X^{DV&XfvKJ^HJ=WUP~OW+47b zs#j87-3oa1$VC}-Qn3wW$#biSei$R0X+)OnOZCRe_2O0G0BCCphX5F_SU4D(TX8TS z+b)!eqtvl-cNP*AduioZxsmaiuPJP_+{m{8h8(-_Il{j4im`G-fL|CqPR=t%IN%0M zi{Gyf(_cpmk57=_GZ~lnrspQhlZ_Qe3d<(T%Z#Q8cka-RFI$*t#Z)=LpY$cHf7V~_nm7$<6L`OEwyo% zki9leSUfAg&&Cpa->oVBIXNUSNAKxy>#DNi*|Wfc{lWSFi%wyIM;f zrdJ2F$hmfkhLY;TY+F@(G+Aa;uf5E<_TpM<=d`b?4b#)Vst# zl^ojng8Y8A6ZW?_*WOx7ZIHP!nGf5wQo5z$D62p6Uw{(EY*neLVm1y6XZc&VfwC%Q zcWR}K3D=+Jw^GJM>CZ*2lnHUxZCr2md{>43GgFQ?Y^1ug{}@ARl`g&Fw^|gVG_+&J3BL5PI4yO zdvJbK%~5u0Ept?_s(ajnJVy>hR;7P{R+>FW?QicKImvlek2?4FSuOqH(ggdgW;qY{ zv;S$hPP6K*(9?6(S$$(}^;unt!ys}hC~ran_JD`*h|>b|EJD^B{|vX>P$%0&2=u8yho39VH-brKG#7+)>P2 zlj);BgKJomWI$(wYgm)iM&^(5_L2FcynST;D6c;k`J=ox$aH;>>GQQgrYGStQyy(b zJMC{~OWb1tc1*wLqW;aObWumi_m3XN;t_%oHo$_Qmieo*EfPY7pELh*QQJw!eHdzc zxDSK>W_Hrs^K{kP^Kq@#o{OhbgLFSz?!c#*xTlI^l$IlRV}m&VMAqUQxx4+>=Tz$S zYd0n2I=-!^T&G_z(P^h&FOX%PqvU9s=JX4>loDbD^8eN<( z4~VM^UonRuMda^&8_WD4s1h&3j)l!?8I&#@K8C6niZVu|v>moUZrIKPKU~xb?{EdU z+19It5|zH~ai6PBQ}7V9E+2$w9=OOZ!>H^5OENO5E|7;b`TwH95#`=%zfgsHaGZ-s_J)x1q`kaWMEt< z2eAD!i@l2I_yUxbm+9C-xmn=mYMpwhoqj-d7Rm9!`0=}>oUe!5nP8PRNm4RHu%G%Y zk{i2V>?>*JA{g?DXw4$IhX>=!CI3f{!Yhm97x`e(m?d&|7pbX&`>mH~{t!O$cZx1A zk(coMHr3v*qs>d93FCdeYVV(;$Ct_J9(d2jIb2V>OpfMK7wGabxk(*7jRUsJo6*YU zat!}0g7Sx-pDdS~`Qm38%x|gzA94>_nU>2zg%ur?fW>Z4F@lm%k9J#R_l^wa$%jO%EsP?qzHMvziP!XttbM&CWh z@)qROQ*J^xy$oVumo2&|uy^q|ZC@!{n`0aX-Xa{fD2W?YZ5xtLf0tuX67bF$MH@)G zEKfm#{S`0E3)oRTg#zVM!mwO zp^^Zr5(pomp8@Koi(%v34)Yk3+2Eo1niKg$YOTl#jKC=dy;`t_t4YvlQ%oA6o}HN}#|k_(~^d!6^m?^U?kKBm-HHH3aB zDKFB@SFz7NNZVhP`x(yDgID3I{R4YwJKkxkjf=6U~yq)k1><7Z_gm0#q zBsWaa2*0H}SFk3}uO}sygTyo7?S$}BA!5dO-or`sfcr~9%4HzsRJurVXP(aG`PG=C zYC3Nnsy>|>cWBcI?m!ULYjSHR=Gf?}GDmzZ%rS(!sD(KW9%A28N-H}jU~b=D|0s97 zj(2wMupe~sD9n9b?ro?t!T|aCbp8!_H}8=PNO@EKg`cKV?pv6Q_O$aYM9!4s4tIG~ z9k;zeyt~!*rE2V=_t(np4O{5vwVKVujgsF6?{%bYZ_9(~T&k}f9y&{|>*SV!S3Yq9 zMK>6(p+4*6DODvm(lM08NeLVO8A^_QHv*OPYLhHX2BKu|Fr5q=(b53wun`WH zRGPa{?$l7Oe4wpuFqf2-yDE(z;x~rkI6*Oc*EqVoQU2P|`s;LX6CmDAw>H7n3m$j} zqGk`pZ^laixEY>T41=Sgqv^% z18sj7M&qv6?%;gExdyVKL1E}NxtG!N!U6P!#?IsKj>S0JzVJPu3P!Q_E34TbI4&jzhNbGsq!l2%ey&0q4LKC*jA9J<36#IeP%@9J2`jd2Hha67PJLKj#i=h1#ZeB6-Sd&3ut08UJad44-64lj=bds02uE%1g`IM$y%^BG6OFCI2`70HeEAu>o`)JyS@*wQuj(sS%;-1&ggAYL<2I{a|Zq6@WplQ2dk^J)` zdSkczJiqBjfqOukC#lOGd3kn0&Rsf$|Dc;sv#J;((#B|3J$5|-9WsnDKC!D+PzR(vDmNjFJ@GlJMJe`I!ryZXJ1yjcZa^0}s+F?cyK?U0(;dpsO)#Z7=w4)#P%R%(Q0XY)EtFIrB zBjO*fgmD@ap+@?m*An!CNZ$f!K?8-Yyw1J6NtX|(<9W8`crMjG91E z1(x-RkKpj;K{?czrjIi66S*nsmBizaf&=#zmd^U+TId^-mdD}HTn|jW;uDCe133LA z59-o()kDH=EHP4@dw=BvG*hxlvek#?Q4+ukObcZj-q{1r)v%W~ZB>w<8s=%%UG&hFJgseO8 zwb+hhhhpz})IaNa$zgdkLK1Eq#-5}j)j0xvDw*Q($Mdxni0!PehF;R}BXZl$xIVTi zz-s7WSiZSp?%B=jrPHpG>vB7IU6FPIvG~|rfux|>U!E`74y)RIGmyF~X3nG}()lBD z`=Cv}$`LmZ4sw^WM$J2oy7~91+3Rh>8taHFZ2}hp%2YYlqK%ItE))*1Gbm`$3#x8| zoMyEbEJDFt-6?^B1(tJ~Yq{D~1d#2h?1`)wu0>c&deO)tIoPiYvTC3ozHk2u@NVxm_eFf1sMPk$)j>{+1`X*8>^6 zWQm|3Kb0-KtZNNLprH&0Jr-M<$Nz0ZR<$9E-jGr)wW(8_%w^nJE@uR`P|n4H)^#9D zSwIaI)ax@jw4Di{@X-h72#wPDlF}^?RE}Hf?Q~Uy25=%<^@pGV1ah@j8wmZo2If(n z&*XS?y@hK!*fY;^KT)meVXvvhq%5J_&*ZCyzBJ);xMOCeG((5*fPg<=PILY{%P z{CF6;v&g`cIXHpVosct{xnmettA?RxTGwgn2BMG+It8Fog=K{N-z%L!r3^<;d6qem zY9$YQPh`yx2mvvqo|I=}4L^8NUe|JR=^cu6LfSAiQVran90#iG66WPEbHnt+o;{N(N7sl&lO`{*bJmScC8`75bee2O+&hu1YVu{Uw_YVtKRl zm8K>j(5%&F8u^thlEXF9Fu7^jf_04e0Y_rPY!;{-k>yI-&9^zT=^~N?-4O!vDno#{bOX#55QeIwc>{K$mlnfV zgUVczZv;>?$P2S%a5~D^Y_#69b)?sent)p0Op*w4tWcp!5XQ@8SG5vQ0^JI zd6S$l<+H}%a*pCzubu6(Pf0FM$yQ7WjC&kJ--9lmkyCMC?R`{ml4yCB5xUv{YQq{$ zDQD&2>=w$~Tr5}cPV%!*Gu3%wUXW_XVdOV*!!ZyknW(@H@Kk0%$Pg7&$d9Q@A5waN zl(=5CMffR0x!gKEYc=W(=HG8Re)s3!WY22dMCpy+8hR=J8$=0zN5{T_?|e5|zLmi# z$x0G+(Vv>qgl}b;-!-D8-^!;!Ul(JrAUjLe-8w>@=so-2a+pUB8zezmbowlOJ}s2v zs925VM`%la4MMIW{Jk~H|ME8?qWO2Shv5xM{!Z@I?&M1kDF@n}77HAa9|V%IbLvan zpkslqunbLdCIve5oxH*D7G<1+&8ip8I0p;RNjiobD|uUZ4x#L-%$AfCYIt6bjcK7o za)XXVHP3R+p}Fd;tcTIX+hOqi->XRfw2Bs7=T*K1n*^LJEW>90E%jojA^ENmfOpJefyJYhPL3d6Fb79_(D!lzZj3(hy_|{(+=&`ToNM@Mrb-qf_8QGD zz)_~q$P2KN)S<5~V8{RGatiy8+$6Szl3BBXckK=E0cAseIl6^1LsR}Ehoks_|DiZe ziCR%SRgb9xr(;0%9Q@^I9j8QbI#s5xVnaMB@}lfwiU7i1jt>c>_7~+g*tO5ND8~l3 zQ0k#Qi-TW_Eu%wmJY?tZa)<}uJPvK;s&<_Ir;Bob`8Q@t4=It?rtt_#__?3eb`3rc z{4S=!Kgbn z7_F4Te%0c)JMiIHlNWeMN$ha^7&gHRFFO^?&mD(xD);6|GZpLHD!~7!9u9C zktLk!U6NlgT%d)QAT0c7`z7peLH(Ct^_HT^=dzs0!#V}u#WCu08OM+GU$A;zmJfop zzC!T56KmyJkj0kgr1Co{Su^KE(4i}c^lPCUMA1?Q7eXJ<_|~~-NQzrZ`%|s(>I~>@)A9UCSQ{~#YdviBdV$kTaMnSYJkYAukZ@W z=1zN~7iqvRa<@?Q2`fk|g~w-COL&`kO#Ms?uFKO6uafOLEDq&J_*4tX6;gk9B?Ic1 zbL%-=eSDkfXk}Vc=sYlx^YREmsB)UM0T2pKWmOc*V%3p?U*FXHSBL4=FEY|m@s981 z3OSg1-jL0Pwlv`etSrlF2cuTZ#n7G`V0T!JwPWr^`uT>O)pVHFgl4F5ARhwQtgvF~ zJd!`(rXQ}!UFq~G7P0y+HFc3r`}lel<^zm$y8FxOcH(4+yl{;vm zSo*1hvY`eoWa^On-j+jMq);}O-$q~+$bfx@zwW^0u751- zD}(LRbx%07TI{llE#KHJz^ZOj0BuOy4$QBoZpH2OZlGSN=Um5jV2-X+YC2JYiPfl- zhw{+IdCWs!q4);J+FM|mqh-#}Rj52JedwVat(E?W8+Vj0w*05Hvx-(#I$LdfD@xlB zVPIzhduUY6(lv*m)_WcGQuPh2frH_{`DgW(b3OIYN4A=8ro!^pBZH~6!@2*T9ZvbX zdUZ8qGd|WNi5M)BBWf0%6I~M*Yvzk?BU>n`D4F5Fah_$heY>nqJhxfvAX=hcsl$L- zU_lBcgQ`VU)uR}Lh!5R54?7ZAgeuQsIj;;unhZpb%y(08_n$$uWbQGDEF|4_HHt)Y zfx4>Z=@k7Rm7Ai6S=vF6#J-fYmti>Cr;%;o0i}yhn<;K3LGqhdg-RB zpP$od7ZGeYirc!y3vy1J($3!Wr-(pvvbt}exvrwsK;Uc1?aEfAgADq`C2^2Vo=RIY z?}}4xrGrv!n_z(lN2}~`Km5NlT{jOQDAG;52>J61{4ARMsowiQ+V3WM^SJUcTey1M zT@1o$)eLtL19g3=y9m$r$0#G+)Ge9X^!8H~OXq4r=x=Fp=Ko*4Xl2rWuSgi{ zfWUv}z^v&8m4BnvR=Uors`Rhp(r`P;K50k7lIln}OolqbIs!o@hk@4C5u?1jG=@%&C7825m>W~wx*}F%CO3xcIn5>G zOdL-mV}fXI4-_lMO3ieJWI1((xoLqU!_fz$+tH)&A*k0-^t*G|H0s}1r(l)GqUOup zL60njdFE%jSXVrz^>!NG7d3zhzG~;*lDM}>>f$NXJ5bf|D5#v=CGG?B6p&-BOaaP+VI$clnmZdgIZ|-Q^qa7it#!FOX0)VI8OSFt% zI7?OL3e=rKKOh6Kf~wZu7)KIVLBSr;uGBZ66J8?5bE=~X-SZMnTYfGS_GM_PhO$*Z zk}KV>hG#TcAr&Lj1@;NwAHgxo;&fb*`yS2k7Cqha_zuJ(I_53n;C;E}EgIBSV{bMB z9k|}pM?@Inse=!&(v^n!IDd_xh4`A_pN$Rd6H?-ph*aCr!$zfKJ~9TvRmw*Ba?hMs zKCQ3CiX9WUz9PM$@-ltvBcd!hy1i|BC?p4H&EjmALlekTw-iez3(eL#G%8uq5~udl2OwiAa<>0tf#4Tk4D=v9@WqJs zQmCJZXqH%fha`9^*6T*-2I$IZ?Ju@;*Va3GSIvS&5K>)00yUx2exe=XExhUjPYT7? z7gZS>u)x$8Nr+8Q>O;T|q;2)J`DXgI^Jne9o@>bIBMWo-{0_kpUprUJazxiKSzOlM4^GAnO}W$rTSPf7aM$XUh$@3 zfq?EDE(FJ)d^!;*!aH4G0G>Exz-bqb1k+3-FU|#wO&r+#Ef|`O?##f%6<8K%E&FT-|~M}>>CubTM3Wwa#^gYh&5U}#>I3yzgldyyQ)ywi(v}G>CYe$f}RVwtnNcV z*#gU^N2a?aioMCj9GYE$rFn9-CiQW=gkrh6T{M^Jbf~uM*n8HC&HXRM0AMHugoyg+ zc_PXlaWq+B`Np?e&+1?@L)5`M&QQ8*D)a`%&o@Ce%T~3U_TSs(fyXnbj)gSOGTNtF zllq9v+?q3f&S|GGYYf~6#q7>k09avZUu!Xmi#f(zYmQwuOa@DTcKq zWDyzz6Je2;vb6k;76}Q>Cr4GfwD)D#wQ$peG*T9=WZc3t1szHy6CId z;IUZ3C5vW}fL6-_9j&TUKDw$^1ZqWS3&9+-h{j%ggIV;9##mY?`%o*xK~HdDYw-kt zMXlu%Avz%6T%QQhad2K%iCM|QtwBXtIV2ddB>c``_Y{t4jQvduv%>0d=|KT6u zHQEKg7aWdJ7E0y&HcO`E?Co@VPd`S8kmx+AAO?a`%OE;wA%Z>;^(r0qP&jdz+EY#p zg-41oV?QhXILzFTvx-JyHGl^tQnWYr>Pu6+>cmpsJr9q-t$*6pDM#+$x@3zKy~A>1 zluz&#$cFLLM=AA}YzDw*LF=O|!ptV}PFRMv;w%8GkO$hpRRH@kp9pK7D18l@_*fXe> zLCY(L0>-O-FZ#9t7PglXl?_P#QI|ra#B+xIv?5AGhfGRUhcaeLDs)i3)`%n9UGuxr zi73(E<6H=|r5AU7PL^m9R=+C!B}ZbpN;$8br#{h$BL15;DkssEXz?Lu7uB*SIc1y$ zh6YC>Hwx`(D55-mTXmOWp|{i2`ytUt`{vq6>^FJCG=8L!P%Xh@L4o#+XGosYNVKc- zHtMiP>U}jyU5^+sso{ld_sQ+~`-E7B-3%hrUIgbe#cF2H>$Ql^$6(_S zGtuh6zw7;%=&Eu@QLZ~>pf-|P&T*scSP?RwpVaWb1<&23ckIUaD5%&m_}>y*dxX_C z*ZCW?`jTdd-N%wG4Ml7`Tr)7bLH*Wr>W**Pb!u%?IanT~&*P~wRtRK-7mtaPq29jI z>U1OmDSaNUnqF4W6&vl0`R$SPMs%0Y1u93ejF#i;C49Y%7B;_-s9eFjt28D~Lo>^m?;RLb#cP%yQ!s;2F%%OZ>O)~M5NI-o^Hm8AeY_&BBlqWDHnoHi0pUNxlr#`salmpmcszIxd(fN3hGGgqrPIylNZlU61JQY%8 zppt8*~6hxx90jA;YD!|Gft;T;v+_X)w}X)BtFp2>Mx z=^EB90|0wsXIS2fE&D8r3AHs^>!MPxN{e{UG)hx1xCX#M*|3=ySQl#q2YE;2=M?5P z6Q3G5E;x;PB#3OoaXOJ8PU1>}H7!IZCKv^kbn#;|xaNy1v z5FA1kDWZFwr!ujl#XKP6iB{?<_QXzTDvP@NZ{j=$^RYV5qfPMS0I$+_cBGLZsXpL{=Iqiv^ zh3?saa4N8jXrrpaylKYFvoVr(bQPH%-J2=VP?=$w=mtBM{_A~8?Iyx|1Y(?<;m_I( zCH(SYjB`2uZ^gXB*x~K`?Pa`QCE0Qq2R~`+U>Qiwj)POQqPsrN7)HYy!?@5*nC%_U zAp=UYkSM!O9}zA#P6Qu=pvp$!_*itBtyAMPn>8{GCk9OUpHgZc5uEY~ij=`` zn}#E_rEgkoouGDQwRsF{`P^NXhamV7^RpH6b`|sX(KA zs?5K4#{umouNaYtX+ejOA$`zcCQ5UHW|lQN_ytmQL#(T_ca=GT{|OE2CsN{@0)S3X z%~bcSUZn)6lYU87N>#RXj2H)c`oYxSnr`$H!J+=B$#YVUImu|BX3Mmu+0xsj*)XsD zF*0|2F2{UiI?u;{WTi8YEDIxp9PEaqC0Ah>t{PdXIG)3e-S>Ue1fCf^yz7~j2F=LoHW}-ym#&|3VfIKw1;vD8I&#$LVqb%TMTaVy9)d8 zPf*2FOdfGyGJJsO(tI@KsiZ~& zMWaMxnl$*zMhq8g$zfEn;Dm!z&#*iUCo8Qct4)$p{$0M&YRkeg_Dk>ptdmUFjaHgB zP&7-_o2<+Z-X>v}pzZ4l^m8}fgR(S|}2+r#+`6zQea7}iy z77U$%jT{5v0)Q&vlH}(olay^U!63rB#7hV87nMs2F$wrxve8uuL}7bl6KgbfMQ`jE zG{(=3OxPRiE>lh_%NscL;1DpznIu;lrPW0SC~NPbeJBO#kTsGN)u<}8pyO;n^&X~f zHnaqwTCEHeCeW?HBEUG`oqQ(yMHsX{oir+{%nsXzjelO|q%_`5=VifYP<9sR{tl~; zYT(CC3hvocHWuz$Tw)QHyDSJ{Y;r#i^3T3<-D)dJmy|0IoW~KF!U+TUv?U9XOMsK% zy$oJYk)&Ibabt^CM~eVVO}V2mWngj zlI;Z#xNltGvY2h9-z$>qXJgpFT|f!`vWy)K+$_L>{9vG@k&9vZaUAtIo-Unsm)w^B zwAgC<2|+tQy^OzbOz{MdgT_7%6MPj)7`HP6bHdLtm=h0Z@r~UjoBQ}ici02PHjgX# zdkhR%maU;XgF8Ne51T;FSAtV*SN%284?$yPnB1}=$(9D`RrZ-=I|}KN2B}(h67QI; zPGM)o=iYfCg=hDf>bOSqi)6>O1%0MSZr2|}LdBo3`Cn35xkod6M5xoPt-0FN9tW*N zsu?vCm0j-8UVs+^=&Quvpwee)F#d+a^bgQ^9G5^gJiaT?Xn3lb`xqBjuj3u&_v$L7 zHo1fe=0fW*nemv+GE8PEq0y_D>{Xc9DU$69CigH;?haTAS(MDjm^pdIa(o9~E&)H6 z!&7bB!S3oLLed{$WP*T3Nrvkf@8FWF`h?=IV?s@h6kK}vgb2urfHQzTGWQ^X8M+FcH~VH-L0Ge4j3Z zvo3?Py0Bh=!SkWc(i+^f_-_%=nJJuwq%+rWf((YMJ|uwM{Nsb?2w3CT1j4)aLyPdO z6C}U`82*ZfiG{JSwQq5AtQ7{BX4y`qder6{loIGwY>)regI;`6yp04IVz^k$`7efx zx4iHnuBtNi9U+2U@ajpLFal+K>DCA_(-ff~jC3T-7oRSqT_eR){^LL#EDM7C3@C_Y&3gH+lpAtEj zIG2URRRzB)+>@=a%>7$wVY=v$)IveJA3B1pdrYmWbta^Px&hjt+20kOaVQT=$!a4T zFk{QemM%JT3|aSVGep18*X~r(6;wQ|S7bTN=9VXEe}-sMTg8D~ z5qb7AMVs0_C-CPa+MOw4n`4P8?`O45F@dU*Kus-KY#FX+`b&cuNWNEU48UTAl1J)F zURk2M8LP%3Sg0>U8gfz;E@_WA`UQK*6s1leEy)t`oYjcOc>X2&Bum72=)J|$jVuwu z_jrs&+gJ3qi(aCj(OQ%O53hhSMvLwq=!$bbH>aJWVX;HB1yyURx1mt2PGH$!NAn22$6FVj$f0uTMm! z&fHih;~^hPoFwAwRzW=jDLwPW!Cd-!vUmf@EG9f7UN-&~OLw0UErW940`Fu}{D0T> zvFp`6Ye(ud1&$@0%$g#)8N3TmOc7y*5UkZ&;mru}XD+uFzBd&ng!Ys=O@tfI=g?Er zL{Go4Okg7%(f|Zl7HqZst8o7`Y=sOjQ0cRXAs9yupA*eI-80n9RB@K%ifh_Lqu4)u zv};jRyO?JCcw@t^r0@p*oPp*|7afh440Lq5NHPX@qkGd~G{8X(zVN{X2@yrNu)JzD5i5*O9HsIa zYR?cYj9U$~cLt&mQ2W9R@mL+Twp;#*z2yBb(X17OiY7o^^S^*CS-ahVP0Yspcc4XF zNX8xuY=YIkb$Kt1%A3%%e_@C7?Gk;?+%BGOcrBC@Hc~@hi_}kKC%fs}Pv@_XO;;*G7$)r}a=TO6fiw?2rUDpY>x`!yaNZlxs z20YJoQVeRJ8BQ?sqPw7;;{=F(YD!a5Z7aXJgDWO-lAYjc&CRle`j8%fK_rCNSHdu` zY6Vb{_a$%9h8M&r!zMD!1pQr}MCO?yF*M1kE2|pi4-fNvTyRE{XNu;HYXD~Xo6>P~ zY^HeAxO)#}&JqJdPl61cK`1ZRrV#g-&JrnsF_^+?RF@U5G$+e!ctZ0jdA4XRCn-6& zxRLc67PH)xUCdrtM9XH2W-MSgLRg+#L`P?fw#Lhg>EUcJUn2^gBjgYr>@3V})u1-| zD}AWX95Cu2S~Ev9?+zNQ3u9!-Mw6;A8L-Sqs-_*TxZpj0!yKg@P-O@>!xT28t;;rc zvX!5LN(@bvU2#jvYpxht-x{V|F&S-_-HkRi7AmJ5JwI1;2%QVM;lTn9jSNt&3tBk8B;|IDJTca{y6HABVt0Q)pd{Rw%N2WN3;&a4~P+F$9|a0G!#h7iKbII;xQe!1v+lEiXa%7{BlK1&|6S{^x>+X zc&M8nQr}!LF#COA_0p71w$4Ur_dE=v?51R!k3B&7%h*-hVL(&Ap3n|Pjeh8!RP{ay zXuHW}k+1E`JM;^baj6CJLT{V&=7pfECIiT(_hn?rTjDe ztTw!Jo|qE%X`NaS4x0S>i#w{7+=Q-pK$v6dHD8mrZ1n0&tyzAa)aQ-bF^o^ z7#yIJgg$PNR+2J|!~(3tkTr;%T_8e++9fDzu>^Pr@m#uP!dBvAP(_)x3G`L`*_c|W z?KeuXx#djzp!#CFSnAz#H zVX!ue$~1CQIp`Usn0Ue zN;nbU0x)v!3+YwzX#Z#Q_A*Ff#B?tcauX2aqPyrYOGC^h>>T)dJSHu>j$L|IJLUtw z<8l#d@>OP#SS~_1-CZt|6+V}JrX?7-JCAxU7fpMEX9C>8-3$ zp4;Q{=jPGT<)S5P;RT;RN|L2|liO(SOQMgdwGvNX zy(B{2F`vI5@*|qoRhZQ0%Ftb`Yv{fFeOrq8+ zMN;-Hw`wC)n_(J?0x^FBL8k&)iN($VB+6*uyusk0sqyHtJf)LuBZOlK>U_xxJ_Osox&A5U35y`eDY+aUGeT4%)$scl@bfACsfb1mZUeRwSeSwrA=X=6 z2;K54)OQ?sWz4^kOC4VkvP)~_#HaMsD+s*@{oI2V^C`Xf3IY$#s%72sPv_DHuZZrZ zWaS;2wnjvAb~0Swxk>~ue~t!-m;ANS{gp#qSBVzGK5(r`y->4bQf>P%^Qs7DQM{u{ z6ju%PQe3L-5Qh3awnh9Ljj3|QtT)6;wIA=7(CJme-;hL?SBXL9{{TK_Gqy>WZGrAW~gz}cBppGQcaBpxff9k1!x}8-G!M-2QU)yQH63Y#B>Gik7!@%N9J#|frWV~JqGw;15qyu<=t;h;4&iqTu zYQvv$VczCXnZMHyZ;9BU#hLD1wabL?af3bOA+uG3LDf=OV9|C<{`gwxNW4Pqt^U37Ry%*U-q zN8UkDbONXv~=%H_F zTGT)~z7e5sLn(HX80Rw;jqxTY2R2W5S7_ZP*o|+i_Y;Mr}YiV3D}baInu z4cHBv#Rfw-ZQLxL2r+mol~SGSxpk$%*i}xY+!}Rs?{3NP+K)W}(kN{jf%y zL0!n}I{6c5tqVPr=O#O2U)~$>q8Q zqJz0S6I{Lpn@FsvNj1we$NgRV0`14vte|z^r*@EG?*NRxl0x4Xa&Lg}e>G|PJCG&+ z>Meq~k@y!acGg?u5Oz~7Ncj0{CnT^pHZlM$nXZ@GVFSaDpwjoT%Wt9ld5cYy&XgKO zDFry3()$D9LEmf_i3pAKDG=c(`wf@HQ6#3yBTUuB0cu&pZ92U}v~?-iZc)nyQsf7s ziSg8I>idC+XLD!^(zaHx z(J1E?19VC@=c?Sx<)ko$^##2S&E6$m4f04(EUFZBB#2x!S&N#W)DLm^tQW2MP~2?L zO$TBHJNFku1go8ymC~CW?qkTW%%m;5MSCQFF`;|=HBKs`(p`0-p?T)#3&br!@ObVK zR~oX;ic_Yg>~%e0v|TDRI$CB+Zjq;Q^A-i|6^X{8nbdc$Xi)#7nHoAuen(7wwq(2i z9L?J+w$-m#o#tQ7AHSG76sqUtMiz>#p%?mTg2=UinnbnOR-zOUL z5tVXmvr9j;gMuR}0HYtR*(cgW;`*!7au?;j5~f#2BDRts;2z(`(2ad?9xS0Q`$dHD z!3#8YKQ792qow;1;D%)Mr5k;)o!_}%1i0W=Q#!F#{6Ro5ptLe5b}w~!D@{#Y~!;1-loEUo~83nG~o zNNs4!$B5Q;`>|3Fc&^0cW$rDbzza%YT8U6=9L-NfVBU2pWG_Jnb_3 zqe`Ne*2#imJpz5axOX*F1C_9{9zms5YNa6K`A1cif**+Q!zYhN);^H%m&veb`_DA-DWmRqNk3D zo`zYp;hZZ4F${tE-jIS4cGju5 zpfD04XJwFp-&FKM{PcZej)lcDu7C>7@&7*hYwO!UOZT%EKa9? zA%?_4N6Leaq();q7hhYW_+;`rDQ3G)+9lOJG98nQ@ceF@WV!DcCpwtguh`6--E>QA9`^Ggw!4NW&s zvU)1^6F}<0k0MD4Ep}hcLUlb>2uYIl1i2at)Ic)GqYOTXje}(DaPD-^%mZS%Hp3{yhY?|7q%PnFZ8%eSf8OknAuh3zMhQ8>>M5L&ZvU@#x9;|q4C!-=Pc2V;*o z4bSRT#NLHVzY+dMDEVvujnyNDZvPuTxj^dh9nRVtY36s>Bi@@vTfP$$jV05l{yCA@ zWgeVbCD@uU7P6h5=ir&QEZo_&s%KOFGkC6!#WqklR-6;VlhUfHd*lzPSqw=HX7#U8 z)!Igxfp;p>%f=SAJuf!8d26#%V3CrQqkZ*(H6zy&aS=K4OqcIe9jVS>HFU6lHBBrF zN+BnrzQk9F`%`48aD)E#+a<@Q54DOd>F%}FD(qJ(EJj3TOe@E7gczN2k>s-soZZvl zsVv9eNx7bd-<1n57q6r&2M-pj*)8k*B&HaTPcEGG6DS9(^O2uLy97RX5P<(`Tqb6! z4xY70r#ZX$;6Y8+-c0e=#G9dKuq4?(F^kU1)OtHdxkJ4}$aYQKG+uj}u3Z;Dj{+;H z?90>M1% zIabggMm213#`2*2u{Cs39w85LM|X>A_o{;L3z+YBaXb3P2y|Xy*%V$i8=0twB+W2? zu!|HSVrteCS{df+soo2}h9>_i7BtX?oM$=QSb5M>9dfZgWGqIFl{NF-*AvEfC7IPg~mG* z=r2 z#SVj&w*M*K&`v6toWxyuv7QVn`@T``>-o63s+}svBE{g!&1&V)w<8LMRgctil z8Gy56=?xEaQ;NPXLXh#d!+iv->7TaKiu7NtnGr<)e$$aO3b(>$qwAX#b8f zdjAPr2G2EcQ*6gg!dQCS%^Xt`q!81t7D)u)y9nf9!?Wo&1wcIBf!CZY_8@U zChiYdQ3YY>jOUmtD6dSoO-Ey@@a)8Rjxu0aF4K_ax|yqpyCJQ0Gdqa8nMT~<^sSqD zoFRicxSOp!a0cUM7A zENc1y>k=e@XI+)_Sq9|O>mKGTF}DkRBQq4%I3K~X{adYV$#99HEH#W2c%GEaaMOKa*}q0E7Q?BYuk`uj)7vLSW*}u+2DonGzT;} z+f~hlVGKoWskLH+&5nD>IO}H9mUBlgixD)y(;Vm8a7iT{CBG}7!7kU9J)l*G`-OOQ zdQy|ooIm_0ns(nUrjE982vMwb%hMe08jlhc&p-cS*B>QO`$ z52JZr=8U>|_T%>3>4uj%%sr3oKIeOrx3@XIk^1Ay-iSo%2W>14+p>0=+f$NpssN5r zUb=fzhPU}Kt>V7k^oqB+fm;$ds(cEq%&`R1TyL|to7&Pwy6kO^ifMq4l}QLEyI)z6 zg?q-!;Y%%t3zXv*%JJUHPM*V_)Xc{$jD|bZ*T?*r%fMmCmX^N6EreG4n8!K5jv-fH zb0i=AA4svj=4gKEP6K?+t@x=eE%h}=7(dFQd|z`MziCA0ea%sZ%}6_DZo)78DBjN; z;iG`BD!WwyMZ^8f!qAjv`k5Pe6>HZk8kHS?y050le&H56;b-2!~~N15bR8o z{mt>Fc;#_g>u<)jU#_@<>O3ljU4g33YTzF}hH92uXwvlq%$>L-(!m9QeLu~lc>!j) zab00F-5-EaZl{X@=8eYUAv7=0JjH%jAs=7bMh^nb?ft-6;B<@+H(8u?RsP&cJ%h~Q zexM`mHIfXRbyco!rGEvPQ;dTOD^QpHA?BWexFqRk*jP%ZKsJKf zLFEM*ztdBp<_5rGZm9VLHnZDMz@9e9z&qan?b?J?Hg;fhe@bo`NI79@2B6Q$<}S#Cj&6~l zz8)%R!_{K9u5{AG{7O16n+uI!K2EO)^FY5ybqmIMF_2#zdi;BITbK_d6hrMSQ#UrO z+8gt~WHl5lS%$yr)?zADod=qB? zlt^=LUkwKZyc)3Ywh!HiG`9wle}~D!3CVf(J+O*N&Ds(~!z^YWM#pRx;59MxVzKG)J(kUqk2@N6xfsgY^K{R9gT)Kd1L{v#m}rTpS3}%Xc1t%6NVX#UmT56PX+Uxba%rj0{RSlG*q?h1NXFV5z}x6I zpX4#U>CH=bLFWA4$@BC=nTva?g_zs|mWeeAd>-ljrN@vvxeLmgfKv zE}ym0n+`QJhh=Z=%WdbSzvrD?*;<==!(HHEls@$b98~TGO#Sd0^MM<1w>Xu_ zK|3WwYLt0TQr0?^p`ne;-gY9`C?U9MS|bM$yeTQmoeEpi=bb^?)apdAN>b)Il~D&% zg9z%^n3;^>PBcHWVSrD*U zU=($UF*lAz2KMx`OfayA__6)OvzkqXOTthUV}8sVY~`k9Cc)giK__C&asDue;mEL; zk|`OMZ)DRLGON2cHb=tFj=~KwURHl}RVB}^s+2>)y#(v<9_rKBEVt3Q{e8s4*~vcx zm(y2qd$;N%XOQZ^HgVXYnjr(~|6}dV~? z%w%y*%WQe4nSooIsl3uWm6ls(Vhd$Pr6y`xW+k>+*}`U4W@1@-MdSB8^SUqY1+n^k zAHP3%+!wFc%$b=pXU?2$&KzkkBHAMu3qB-c**mbY;X-xyG(bYaxmNA$7HSczFByJ= ziK+CcwGobu(t-7AEjMW=J<60auK?xMG8Bdb3jEZgOkQii@uWO11IjyMl%cJ$!ha&z z2!8;%6&oKonw&}9pbmUz7BLF=DaCUwj>dT4XpDg)x9kfkzJo}^Nv_cyL_#hQs`nPz zrE_p|5W@evT8OJr+`;_BI+bGUKYoK5FkWM5@LLIhH8Cvj`o5 zT#ftrps~lG4~;PVS$an>00nacU~*a3tJ2xH`G|2Zl^Z5?7O@vFKp*46^c6SFuhJMArIasIsOFiO6#~X3%w6V7A$`2njYU#kiO3pWrsT7waMn|Q=@$Ri0@9+mA zA6}Yf=d_xjbN!gHwE$-gl0-Mq=ZPfIlVhD)cNK{Nw$AziYL9*mPz_LiXTQcAqSaL_ z3t;HhGwFe*vBfNTnh@4=j6%DKP5?Kso0!!YqeWBiWY9a^#7G9-G+A`^45Z4$1amlK z84JOsG1`)sz$Vh5pN)YE#il@fn*yPDX{jFPWQR))8f<Wb!KR ztZiyqm%RGY)LtUXoJQ~W5>ZiMiX81Y>x}Y+rj{MFbR6FHB*zeH-djX7sU-Cl?U+=s zkRO?faI^ZD-dzAv!4hOEa|LXZQ(#V5itbi(j>MLaoxw03b=?4sFcO*;?+k2DvvFbrXi@$skCl{fN75Yp zsyfE8vP!@?1 zs8U#r3^29Tx0to~w=UCS2s&HPryN}EGbTfHiTmu$8r&=ka|;k%stg_`Z7qUI870Q? zjSB2qY+((i*D{1m{pxEc)pSCnuB)rHZD7351NPFqIPFxtL-k|+n|0f4+E+}DN!1?R z3*>{~EUwds%kaM%u}54MWbM8p#S)KHnsMzz=-Gb4hjVN7g`Vt7z59tE>fx*6XWFW+al{8_nxX-$0h|7Oh zHCWt&8{&o!5mvL`i%=R$5pc~R4qNf8Tzw;rqR$T%zxv(eQDmG^q-L-STIDd&BX{q8 zHDqDhX^o))Ej)uQb0Jhg63SxJxZ-8zGwEP6rI3ndM*6H-WJP%_Eq%znwaO#dq*Phl zv<#~(=nfVx-Q;7SF$a+&wP=KkkmV$4ve3HWB4}tp9ZcFVLu~IEk_7sMrQV)r(;`9E z8F>~hWH(r-`fe@Az;~O=z-0$Vv^%`D-ZXb4sA>nb86n2Rm|USV8__|-g>L5^&*ef# zEoEI>H9`dYV2uZA+7WtXga{m-gjrW?8qx}^+f^BG&a;5D-!=4dCOVEEMbu>;LkDW= z552-gK_>DaDWV)f3=;CAi-1tIwQJbAPNEOnT5u}y+F_OA9c`Ro3BWxSkB$^$5VG>! zNGzhZ6gLV#{wr5kNhw{}s#i z>~A?H)2@Tq7jhhtWF05sER_Q(ah&MOEO%9kcPwojCjx@r?+yrHREn)TlAwOVNn>h6 zes9FL>7NHx&Sdh^4&aa(yOr3V90ls(J%Ndo57KADGM9m<8kJE2>pKz-2ma>L?z^T^ z+Z%Pa9hXd?(Km_!z8VMJ>l%xCiZ2AC9u7`=){8X0;k{Pd8BjZ~qd`qbNt!5+zju%m*T?4#;&}Tkc=G7HN`vD0KAfcbB4ie6w zj6#9~Wd`Bq5-7>G!gqwuACxoGHqGxXsT@Baj6ZG{>y5E$)Ekmv)-EYdU zAD}K1+~4NVRFD6%>1mJu#?i+U#8B&R;aeQ z=$`nF^yAH9fEhsm6Csw&qtO$EgUNEkaAcg_Gf}kk+l9)dBNbUjJ#7odA z3sO`wQFKA*N0(dRC+k^-m^}u33%h{AaLDuOE#f9$_*!5! z&YyOUZk+^|W#>uNWCmA)5>%LVw}ahzh4lC&5suj0?UTfiu1ICwMcbqz{N0%y{~msY zy0nAJigj&rML>0n*Uf2X#yaWPaPKyJ^66I5y$yF;7g^khxPuM~i}=9NE%Q8O7%qh3@tSx2+X6oaw7&CC>GNP=+{KeRDZcry~W zWs2S*b6&WNlZ|;#l-B5pm}*ud$yZIQ?Z82%XkW_$MrDbB&L_J9*C?l00B#m5+o@Q9 zR(2X&S`q$`-IX&DmgZQs!W-y`ERkvfPdSz);=o6*W{K|R)AZUjbYWDs@MYK&vqkR- z7IZ;@MATH-4uClg-u)_m`vP1Jz-_T09ukKcO{VjkaKAk#W@~HIap3xeEv`D-@M}dK z*j-91%-T(KK3jC+9>^SUwNtOqh#XFnvrv~HU}=E=jd&`ZH)P6 z%^7E)a>O7$p>Plc4?hcbEqtkf;o+b+&K~rh0vp*lH5zOcYEW-X5dpB{;5odp3yUdw zfkeGP^i+XU-;o+8!@G>|MH9StmB%0re+E73r~~0ho2ClKV6;;KlRW~hj^-d?XAW`| z=9HR_TX6>kXf}Te`t%;t>=_JqIW~CEZp9DK6pTJXROCMXa)>%i6Jw0^97D^diH?>J zZlJ$2MJRnVO$1GX9@tdRMY_eE$@9R_EA(enU5a%=f>kCuQ1P3?+|N7lY>1*vh&g@n z4I85`?vBLWZIlm+>;Y?iL8AY$t_5!UUy+AfT^#Fjo|QA5N5zwy>WfGPte zM!4c5wCOhJQ?Lx2M2oCqSKkJX0y%)?dR7#@z#5k3`Djm2>@09Pe;PhZv~PltK^w~g zu#V@>5*ZBO;4IPKw=;&!j<^>oYknBA`_C4!jZvBD)}JQL7Nacw{`Bf>k!AU5Cbha< ze9Yu?f%H&@JVv)*N6>+1_yQ$Npos5jku7i6AA@wDYGu_G=~n^6ptugiL~h>a1CCum?( z&>GX7mk;_vj4~CV3(6Y1;BGNvREepXub%bZ1MaQ8p{H|Z=Oud7BP8WQw(<4=^fH${ z7Lsz6{fY~^2h^l{ppvK2oO?t(PM8L8f7~@-D%Y>c;hn|k$H99*JYjVD9?_1e%n_<>ts!@G|IR+PP|4%r9quckv?tm1kE-QDw z{gxno&OC55`94vD>5b;1uKb0V-a`AYw(Cys@_Ax~xfO-XhXP&Jhx*JH&zr-FD&~vP zEZTQlAd-BO;rwRKH&0)Zk1r5~X6zCVh`vql5!m0b43H?4mOmh3$7He+UE<=r*r*KK zUTmsi)6s4B2CZ1%tw$?QLH%P&^ca=TLebk&eGd&-h}e;jd(+B=qH~C^4XmxZ!;t};gFcd_K3D_T?jgCZLxe^}md$urQp zy|`qU|7!zWoX-cW0Gk1H?_6K81l&4{9?u$S0R1VW9haB}2z8~=Cn5V17w!rF9Zo9j_0-yTir7G%^o{5B$phULo{&o@nD$9IUOTt$D)H0aYqt zE@la-ABr!<7ti~kJl>PvA`#gb-}%7807_XThI$?A1#Qw+?G-@l7eR2n`T~8wNObmh z_OFX598Oy-h6UaU8*V+1L|MNp5a>Dw(vyotzi1b0-pZT*cufC9oDF4@88Stxb3H)F zOuD*Qe4yu!Y>fXtULtyN2;mD5V&3aVt(J=Rh%t%V1A=lL>rH3oli$omP&!JZ*gXpa z_2i9#ZD`(7F}wN2RGqxb{T!U0>Iwp=e3vQbMcOj4HWv&(7sm{+FIArUe{XKV`i{nrETVnYoA2TS_t$y(sF`yml2JYe1mm_|qYqN89$RQ-^M@cIOm zD6eBA-S>W7XDX~|`KITaX!{W!)54!TqtIxomiE zt010wHv1H1Jtk&b3VYJA$3&aa9l0Uk@E_&{c^#s(Lx=0m%f|ql(Jb%N-3E9U1I(dr z%f&$RXj-@&wxizk@p9OXVtTq(l5RUf{3zY@xaic}@7nio;l1Tz3jO%Fm}dDdg+{D^ zzq^DUUjYHHYzGoO31NPXuC4&^XKDCKF{DYMku%Xon^uY&n-m(CxgnXwDu`d`(JJWE zCG@~5F$&Vq$E(EhSV*vtv8{D7Y+8Y6!t2dSuEKKG34lKaql%RN3Id$;_5VA?5(Y`qbZ#4n933= z@?4bRIUCRXdlMaBBjU|1i_A}oCFc6@idL@`%gllGn%3_`K1eGEH4m&`gT_21w7L}> zEv{doxEaZ(#nie`@N)IjB6eJa17;umu{D*0SwryrZC@wV86QyF7aKAM+HkpGlreOw zt7#tSbY-PQ9L6)^`NmKwD$Y2Z^J(uhVk1WiE~Tt>@Q2hmXze<&(masbt{0#C<3pLX zB^viDsMw7J?Qaw{c^2dmSn1D-g|~JJyoLiY%CS3r+@AV8ClYa3X6|z$-q$GddeQdh z#7|~DzSCEMG1IdfVIIeIxSQ~^tZ3mT(a4+&g+x(Hp}iRAv?1MaDkv64zUYl-Y`>rJ zFESY)SHDdQPOD!&sP0=(iD&)%UXy~a@w`4A_ksc?EKaNX=x{B3pv(mL#`ljEoXL7) z@9;lpjB#0{KCnz+DtN==`87O$fIs~xrBA_L_013ES{58o?-^zOs=m?48jgb7eK?XYO>Dsb!Nl9lmT_8 zFTyGK-IS99k#r2<5ZDmmL?~e`V!I1YmP?QYoD%!D`aQ~Z;BaK40mpK3AT4=8^f$ji zuWb{dp(W~I+rV^Z_In8QhK0cp6MgCG3&P$$Qo9Gul*x29{HOwkE3X_`H!Dz)_vq?W z>inXxdqFddAo;3@phvce_U75Djj-#saV(YoenHsKNYDS!$o^{@x${NQ!+cxO_7^c5 z12{Ub9Q2a`Ww$&YSyhwpx5P1jqv!kXc$aE+Dj|HVNsr3NVMS0+CUmtYwI~qTNrN!c zc`9-RiZyP>Z~#Uru18R4g;QHi58RuzXk9&mwiJjb;|{k1iKtFA)5>GeSV!D`g84OF zfiA+=J4Cs)&TTYxhsa6#9dcrATe$Jz7ld?O+g8guZB_4p)H*7OkgnP8|@PBBfg-0uPulKM8uPyd#Z&|3f6L#Ivl%_D%Ms!re8Tua@`ZR@Fydt8F z@jO}-S12w)OO4WAr?S^YKt}rjC4uXEFwUFXAm7(GQWj$?%|L8rIt+p4Xk4HRgF_Y# zVCuvBKw~xvrz8!h+}Fje3~}lIJ490*h(+CZiY8_@AhOZ_O&a`$?w^SQTiZ$Zz9ISq zL-{~HE_O-cU{WSBDO$m)a!lbxN8dm!ndRs`^w%!Yu?s+0ElBh-3+Bo>P~ULnNNNu~ zY;*B!q&I}X1U{LsZajh7_xWo@H@peEwHJe;4Mk#vVZ}U3=C>6~N`Cb^Gz1%!K|_1H zQ=hlMl1i8*&3Rj7G@Hz-qn@I$6TSA9h>h{rvXxuitc~AziSm$gry=TnL^T^1sr~WF zb()2l%xLz0c*@FmI;iFq@FdmnaLdmd>D{+QyfKWS3SLa4_U85Az3PV7n|i+^BHg2C z1KrOU#Y^aP8OoNAr&o517z2I_1OEK$!QbYFZ=x={J>k>SyJ0iKWfZ%Gy48~XKga3# z9z@ecYQ3%paETk>L0GTLmv|x|gI4ST%tU&6j~nJ117^+3*Fh?@e*>uxG0farm}z^( zaLbAQpmVPpRF*-Lih<-lG_zQ=)d?F6%>^+%<$ovLB-Q)_o zS`0z~P<=VINp)lF3K}Ux+49snL%P*~f8?b)bL^guEpGUu==^?9_%z{wXlmK_98Ejm zUOILINsnI-;s!Uw){LYLb&)juAds|}CLDxnb|-B*C?bNodTv>@xcQ7;JEV9`pX;@R zyzT~l9_mWsJ@6WZ93}o_z9;;RW2*&S>A3^K20XX99xQVAdOhubuMQq!524FVsoNn$ z>^PsL2M>wx>-6~+qtEZ-Or#;QVUKm=+oR7T>h$@r=wPsVxH=9iLfmjYDC^w4Z3nL) zu4*y}ao=Gu?zQCmzUX0${;wo8dT@`d>%rUMhW8VELFGGY;qlTW=lh~*lkv}DNGMo7 zhIw6}_i{A6m|{N=^NfB!M=OqsAS(VqGy$r8uhUo=^rLc@)S6G{KVVenfTV+tK)tro zxFZOdJ-41-I3h+^POhiFj=-XNWIgry5LmAx+|*JE?y2}tQ3~O(WrJAvkZeQ}ivk{$ z(&`J2zkv#L6u+Ev;5bSg756dvc;h{lNGp#j5qZ>gz?bcFkLW}qeR-6@^N^~KVn{x9cfrR6(4#23Bac7V^A6p#`=?uC^ z29mF4ui`NOeF%Y!r6k+NPTG&%B#80nP?YaoRm6SiLb zl#}Mbj;J4AWA(du2~PuXf+(QMc)(}nHw*_#VEyItS$$y>X9)8Ep{070s=vtwq_x}p zgZ=BjET#05;b9z8cTC)kAo;8k5gu(y*1~yM9hFa<RT4hg?nrB$p5%#-TZWWd~!t_ zy`kR`e_TZ03`wsPajvCsx@Ezr2w~E>h%I5?rWlfBKF3BXNpeYgN;U*DPf1cuEhI@b zwWcul)IySc|G2m@6Y$^o{|i36vaBa5(n%Vw)YwMkKP4!L9{3DV2HT&ZcR$s68qk*A z64Ie7XozKxW_12jwYu&@cX(P^4K;ABwscH0jCS#UF?LYe!y9-eZpt#3MA_*}GXyYHZEL63yy^V$)h-h9k_)EmzAs!~{ggDyPgKU)j?&X$l`(0UI{pd_Mjs8l^ZURFP z8-O~7;>7WjezE2k>HJqB+(;l@0X%Y4F48}LEoNChX-AKJjq|=>L(4D?OP+$0ki5Tv zPjVxreRYTBHnT&f$sQLgw^(BmEM!h^z^r4E*yJKoP%8CGL|Th1yZ9i8Pp^}PXa^Y zaQgV~M3<)bEWxG#rwB-$W_hHuRfA~tO_?WtG=#d3P{l6FQw>Sw#a64i_ z_;>cXqR<}@I?Js0d5rnpIOc-P%=bYrRLA6&%?3k#|+16t1}Ty0W`F2LeR zJ4?lqY=137rHM3a4)`ikJA(q0eXLnQdwy0Xt7Zjl)%#qSubLM`s%JK3H7}5OW|P(d zSYZ}Z+Gktng;QdL*TqB(D`9<$HWas{MdPM`$tLGrO!lKH5xv75hmhEH2kzU*MFH+`4_9$mR8O(K1;2j^jy#PF2AIMqwQfU+r;7V zhypi^LcNL>{RFbGCnC5b7JsZKRsv~@bt^|c-)pfI=)aY=|19i~J&xdzyPxS_5k5P_V`6iu;L%gRpD9`g1wHo7j(pwC*>1e$Vt*-8nGcG0GtL!H|1rXcklx#M$PV+hbrdlrD< zj}hFm7C@->gZn#Hdw}}RGzlDl5?X2}>UPIs&vV4r*G(}AyWBvA$LYY8u(v?_4}tvClQ=`MQuoaorX6Z+?| z^vQ3Au`ca;;IUW@@P}h5w2JLUF3^*Z5&hXJB>otJc2#t^<&urctFT9cEsZ=6pO-0) z)}0qIzLA;*eMWE;9X&5X`7=0ede9>-CYW$PFf>P9#Dh?#4wUx0sN&G2aEh(WlnzwvDp>QY@tvn|dZ*ix^18FskW@fwSTQSPH~|2>RoKc-r!(Ml1gmM-2rj z!2q_7Ef5U>1BMM?k+l6U1K6>@gvL_uMfe(F(!YpkQe0|x5h*T`=+BE{5RY{7)R;t? zdkI^@Irwbc63a`Mgg<}ZcS+=${V2^T?&p8~Dq5%06{l$ImpTtvF}5B@Dz&~WlA>xc zsTBsB)>PngCIY-Y=e0A^xQe7Ru#Lvij;lx?f~R=;;i~8rlyABdPInGL z&T$_VD+#5UPU|26M=Heb0z*YbR5A69TH%XU~YloL?`{b{3FO#d1>3=oL#(ru4gM@~{=tn+! zTx7M#4oYI&2v$}dP03ct{;X;18*Zx%jI7+%*4b!!&?=#<^Mc)Cm6Oajk=aYC3&=JD z+S}38$4j!^DEd0k%E2m)p6{S#ULIW^ha4?tZz*w{&yJsFrD3{g@DK;*&i0jEcvu^L zYlrA$Z`r!>27Goe+F!k8hR)4On45KPBqO=_51+@R)A~lTaqHIi0ve+&O)0whOHBzy zMU7-zv*m1C`rb$W?wc8n5-?}nN?$jYo>KKL(TWn*%oqo$i;-Kuzg{R#a7E^EhIcKw>) zZNPyLCSOw`rM8r9hhJ%@$JZ}PHjT|=A5Bz~kfomuW&jGfk zZvh3sq*%ED+vhg@2*Fl*xur}(98_6L8DK1(AgGYtZG|Rn_FY&#sG*uK?nop3Wr*dS zc66J+jOW5?Tlm&rHtx{Zv!o+dD?e#+a(qhJ4?qs?7cXO>eTi8^GOiY_r1GsWZn{(d zR&pF}sDAP(EI{x=?z5ev&IVx*183c@>x)`BdXcX0DTU18HlcC=9d9M4ux7imDKy(6 zU9;s88=CC}8{N=aCJjJ^wyfFiR2ilrx}+T+il;hk9JXn;)~3v#+?Q^OqF z)$^8a+Vm*bb452g+FC9SN8Lf!Y3>!886dl|9u4DF-PS6+agV~T0NE|fUo&H@tO_t@ zBcW|^k2&7aN?m$)bWr~`G6>F_U;aS=?p;T#8(o+*@PyqtP|A!B z_W>99Y;OsD%iN>LVz90s)0gE?2bm-3DdO-)&SZb zq%#@6T|vlo8I0v_h2ZO6?!DUkLIVww(TbeekTXRub~4bj*p*=UK;Z9-oK$SWDbE;O zj>a-Yv5$u9K39gwo*}>7ZQN_1hXZp=?b8790ck6c+V<}dDg68Y?-JGITDF(^0d-4E z+I)%&l`4@ZQ#0)Np)v~jZSM`0eS?w_d~`L+bevNqnz0hqI>y`|3zftD{+z??T!nbR z_LxE)!(=xzLXE<}0vFQ4Fo1cSHidzVGU)9v7Xo-}k5HFzprEFW=h%8Z*|rJ&FI={> z?3MIfxC}HG73~U_o#D~7XLg{|5wc@UBdrL5lRAUZuPs4`@_8XBzjO;lvKz0(vCy;A03V1 zU2N?+ykEnx7@m%nof5F;u|&wx*L*1iD~T1DArmIu^T5dSu+s5i6-j?a%P7lpf=0{| zk$zJkd@n^h>tgUzJ`Xdrt+ac8fu=stFQ2GU=7QdAC&Np+i`YJ;L>v2lWjA zIPO6Q=IuQ7s$>4QkSF+mZj67kP=CsQz=m{xgez!l-2jISkRMlRC)0I3cOZ zbLb--Oa%X}PGJk(jXYXlv|UFNC=7mA8*|Q)Lq+ni-wx9)P&N5u`-m3LQ={d7z7I{3 z4>s6b^W%gD+A-y)tVX92m4}+n%80B-zfqf+i)&-ni6YTs}CB&%)PP zfP!nO#J)xkQZi0nfJYXB?cq{`*PiOsn!ZYs?c>(4XpFVMXq&H|b(`h?@XUBlqP7AG_$MhWk@;tVFsLocXhBo?d=LS90#QEQjT(fCpy&1Da=AzNy|KwhUE<| z(h@ma&E4dTmS6<>8!UKaZtFnvyGdJ1q$$}?LO_4)U>`N5;C%7mU3ooMV z!gmjyFw-kNq@b=n<&CKO^uIK*qo*8*V!8j)1d6q#9;q^pn^>%x2&JW|azqDMNIaSV zkyP0+3fHz#s4OJl@ue{)Cl&UP!Bo;ydQosMDbQ+Xk5<)&1B7|hr18CEA8s(&)!-Yw zq}^g_N+`2bm8T#>8U$g?9J&uYqCcCzq&8x^y%GRu(`uU6){sHN!xa4*e31yTM6M1}o74Cfh0e4fL(`uP8SI1i}d@FdsN z&@&0P4(10M9L>0fM$@a_XdWm34EZ<*%(MS2m$qg|bwvT6eQHX7X2>_#t%p+yQbTiZ4U)O|C`132qg8 zrKj9kr+5g350vBdaQp?YGgBN)3kS+x{o$z@4lt!Bn(?jk^Q{S{`K8LYiHr5{UUmM& zFz1pU$V1&rr@`8b*Q7} zHGr|jpd7%`Z^6mv%(?_kbZC(5QR}lksDoZX%?Han*^0s*vFWsIFbp|6M$oH+W#>*D zn5_aeWWg&}owzi6m@^GoHOf~FLuQS-&DVBKCl8Sl z#n*Fj*EKG{aEbkS{raW`CM1N4hsZ}G(5Xk!nN#S@W>+T+E%sb1nl@C<;#>g`#0qDe zqi=@F&;hIL)l@bbYMak+r#Cd)sa~dCI(K2>(=}iYX8_hR4 zeHQBAjh_FH1`n5gx)$=xV~V?a$2y#o5t`l>LX(Wu&*+`%fef6kQ-z0c;2Q!|NzQ2p z#gCMoI1@V}->=Yb!(~Wl$&}NaS>5X>7s;x?aXl~V^2L{OKf8tOBV=f+LL*0O*|}kg z|8%4MBV|zFBoGvMVBypqBT~=;N8c3Y5Op3Y<2aeSkMd?k&jqqp_pOEB ziOL#;@2%iBW=9%Vp-v-Zybcjc>qr?ouyD#Y4~Sdb5NjYiS8N#Oti-%50qs?6!LL5; z*NoyTe;P3YR)?=f$^hSDmE=g^a_c`w${qs~J~Sj*==3#co7%BMrqXqohcgU_+Xb)}~#>%8%Mn^L`ZMj8$81 zy&nhDECnGi`!on2*T0XJP~DjTWr1Z)-lxUYSYQytSnIOl|I&44jb5TRN6TohIPK6Q z^!;eroq6w<)f9Sz6y_T#+isANEz*H2o4S=KNn85}J#&MUe6D4Q!7_kC zHkpUe$2Z6eaW0JH)MCV1u;t-~vGH+B`fZGCk4*K+6f%~DKsIKL8!Kh=_d%pao8h!* zthCiOxeZ*()#L`+HC9f-a=-X6@Z&nmTE@%0rI9b46?s{(1p}+p`iCPK3;|ah#0mSz>Q*(*9Zvw9aYfEZyCV#YqM45O-qEFl8R)$v3PR zr*;ohQDFV)>NpwdRofBjdZUy&xKA0}-2k`G4Q>;IySo8!`*d)2T5)3?aPQqHyKp)Q z@0QD+;r0zC(1?7;%XDCACLr#2?^5~pUXgWpXq^E+K3)c*&Y1dj)_e_Xc+YN79ZbNunBr#H5fPUD z6Qw$J?E{Ugx&_@hQSOU??czqKYm+Hath#oV_OzhHTV!|MNT*?C{kTKt7zH%{7AV~} z(Dqy8cuSQxStiMmq5AUcYHjau-rhn_B(;UvwkeoqO_GBU@01ryMU!M^t6E!H#VlPW z>_f4)%9u%)o^TSojI#QvZm5JZ?1k?Pa5l`$6zEscP^mMaW97MGri@K(*(KMehWb+j zu&E&-7iPK^Mg+ZltL)g0aXSO-fPbfh9b{vV)bH`~LCAnNj6l|ckHhKjTV?zREUEPx z)&L^8_~<{D6zCyQo3#wc=Lj0?`rLxCq{@fthQTwAf)k=!39DHPCd+r* z0ZH32qPI|{1HNy+)8UN8hzjmR8)#lxT1~BJa;E$Pc^%HYFGGrEXURSY@X@rTmuN9o z3j1TB##Lpk*Zr{u{G-`&oLP`PN50q`$G--nxZXYbGDix_iDvXyj(n*D=N8b#^J04y-8WS(4r$y| zn+7N9X)yDj24e4J8yH-|&%Z{krpa0CKG*|U_!P|Nn~@ceyJIkbNP2pj>=gohDEGlC z;FtFmc2?y0Xm2m0-=@hM%@0%m>9Fg}qeatYkk`sq2*s+JEZa2mINX~~d#B4>Z!>HR zmAc{S#u@Tf+!VfRhU^WObYlc)8GqJ9-s3>A4j7yw+Y1VDB3rxt*-X@pwzfrSb zSRPR{VV3-#1w+J}&u*9PTjWpej%3p?5ODIpWb(a34)MvyV$fb#L^t0dLqkr&iorCn z2roGrpmKrku8pM?cgO+L3$uLsInzw0GlQF(#)h$!VeRM4nUUFpM11wUa_39tIBVG8HeuH_uJI1(-q zT;ejM{Z+~^v*Hm=);r~*Hj|qm!c28nsc!jplee~(p1xD&;zsI_x$*-Ru3rR}N6^o6 zdD)8KpHGZ;xz?~(mRprb5& z_V3|vQe$2CoD8)j9sB^6Tug8)O)V_=CM)1dd}W?#jV%JPb$;p2ML>-zlj(1ip^Nv( zWtOYH^x(a+gXMSMqJn$nYI6%yur@o_a3#di(EDVl`45_QAC}`qpQ4BElaXfMMm3mn zI0g35`6>}s^wB&y&m151gVTixt5!Z4Sjcf%S{S@A^pfE+BmAlPv_&3#a|ZgVmjR_&bw zoG-SmCgVAdA|90OI$r~_798#XsSggP%4@+D4RAhcfWvbOdip`xvwc4E_lFiNBf6r7jWtH=KiK#R`ff^WTp+d(AYz@@_i0x zDLx%YGwt%ir==zYmJba5mq6r+fbUACzB9e9E`qX zV7_Yuh`e-5oM&Hl=E%mzCa$>$N^ zf!4+>meY}VclTmBC7fTVuD3wfGoo`wVfVlQZ5X2n(d^M&UMd7sd>~oHxI$AI-P`QY!`7T^{<__?|x=Ac~6)z0cF^T zSU^$b;G*+;46Y7c?kSvkj*=gfX^du;MQ{<~V=@vmf^g1qTpDW3$g7XZX96Bi)5cCl&p+ytRBM{CO7^f^vC`&M;Kb*x^vNoCcZbu}RWcS~bBPQC`ju-z6=r}yGgj#t6%chQfelx~v^!sR1Z)e68%ys1w%LqFS~mb2Nx{1?>e+a5 zH;vPzI?BrbflX?1pyfn7eW}R>MwvvK@Pt&UP`L~a89w2z(VD*S_|Kb~ua*gHO5~Ck zO*CM&Oyz&s-1Vc09$PJYpqoSI)kEWqxCXj;X|-&D!aY$q8(K~+&YS7XurAJft&uGt zp~j-{fjYdWi6>+_*400ZTKv+k6+N{^j)Hvq^BOtWk*J;HPz;yS3p^Lvmv(Ci&x(ui zzH|X`Vx=xx`url@^`x9(?oKD4l)WwGW(r*^H^y|=$~S;Yuz8hl0b9Uq)UMhsUbRv# z(%Y|<>EN1oqX&!KWRah7lU?V;4$WNXB_pnPINY z`!YCyej*ucP9XDBa!e4`UOqF^{h#Rxwk`1VW|-1w)>E<_&+cYS3(k=|B`3%vy5s0`CtV+`H_xz9f%hg$=**_6HxBEu@0x=ucyjIM72l=uF2 zDy@uDf3(GHWHR4hrRU4S&`a#Vl#9b7k~@^r)+4a*0~39JpCI6_3OI7UN6IZ&qY*ImdW(S?R0fLwyP`}{;ZUiFaD%Eo|XM0u~P?Q9xMfK|Agv& zk<3DA58zhg(_xV^7wn`jo|QLPakUzCcn*P#C3aI7jeJhd4pb`0L)Zv@ywBl0jXR*( z+urW{%*5AEYe{*X0rTp4`31TMiOGjaz<>)of zeF-#J!ZcX3K@MSEW#~p3(rxky3>}F?Ch;$lir7@5f@CcM4PaK4V#-QMc@j}YxGZ#ukDu4UiBCj5K(Z+dK#99avw`b!Q zl;>ftz&#<)%e-FAU=ZRh$OFaVe6^mt(sg6Eu>th}>Nsv|)4a?}rAHmkr^volrcG)A zN@f3SS+xTfew&=%-d00VNF7@FD)yr#n4OV`x5Kh}_h=2-)MlEboj{CJIcSL)AKx>| z2<4et%m@W>uvF9teV#yjx5^G)*r3Ab%vKp`uZ=H6?C&GNS*=YF` zTHfqx(J*LyO1HlxgX#PZnT1jVuT$z}E;Zd!eV)F2Np8NmG4R5Zm<55aY>cvjK=bj_ zzM2a!8l1?xUABcXbc6Sz@`H#d;A2N9_$6YnqJy=QRI@746_%QCr{QT8ps zqmta_0hEyG-Z@uK$)^0tVjmwC=~+SBmt zsj$aVM4{YdP0*Ur{z9p)2A;|bBT8pskI~PClJC&GaHo4`hs&$V?nqWUJH!X}!Bg66 za!gvHcH*ClX+MJ#a~JzwFgg2P($Qi#ugB8y*AUeEDtW&yb3?WTAx;^F5eIa6MxId$ za?|T_CU*M!(Uc(oZe}6vO0wq`TF6|s<4zgkqf|ZExrXkPc5%B4Y~N81&d;Pk8>IH* zC3#0|h&*+Db%pXs@Z zIWy?=mGtH=*%f8Z>_Q05(ggB*Q?_XZ?w@aRH0J#d*R(pE)z4D$n{uDQYLE@pbFZcCQ{60*hUu+N0dUiWMZ>)k%ne_cTatN};$L@yyc`FUx4ZrsYa_&~b zTihLWXkx>{}7>XWn2~cYGgF~(v*tR_g=}FX@py+0oY)^-32tq_Y3lS#(!;s6-yONAcZX<;v7m)F>cV!#;XfI@`k{q0VsZKVP zP}N=;KR`j)2?!bP@hPL5M~Cz4_riwL#8^=!#)^uksqe}R-DIKxmIqqvm`pr+la3Qw z{`=&EjbL8uu8pTB_sNymIYB=$#d0K&C;+EC$niR3M&Z0iGfyOPpJ-jN9Pia#tC>xI z70aVWP{o^cWItRI)5y7BcE?$jE(c^RmeEA~gsL9!YRj?KS#5F4k^Mt<9hRj1a-Yfh z%Ly1fyWy|7!}$x$2<)4v1SjbaCb4ymNt*^2se7t9$*CX!O7lY#8eg%5l6{Kfr?d@B&>vC~wzsGV47#6gX)C zNRgiN)I&d>B38>z_$9YaKGiL z9lEWar`p)s;GQ`w`*F(pN1&XSZ9{~fI{K>2pRf)mYoFduj~$lbA<5c|7{~VA;8zQl zBx|?DyPgjw)4s#94>K&b4nwGZU)p%k{NL3-sPp@>ukr6Mf6)E!Bja(E9nAOO`-pc_ zevn9xBVuu&6!XN=%l=<{(mzQTkSdht{zODvZXBMJsB!l1#s3FILo4!KbD=Fm6&k1*Lz$Zxv=C| z89`p3$kzG|_g{QV;u9%ajAKuPGW92ENY^~%6B!YxLI>FOa4HvxJXh;5<7nY0azU=L z*@7`W0I=oodh-$n)sus-uXgaL>->|=i3>dQj!-KgMW>g0M zBaCK9L3H0S#1zk^XOF>dgabaupnSxWcZnQhPNoSZax^gS53q~fn9t7$Xj~sG9V?L% zX)sMFn&B#%&7;7K6_;&di+zhXRSr8 z18#&M81$OCqTQd$|MAjfJO1S=q%e{3#=pN-(On+@eqTie9{-k9QMt#z2dXIabJ+vK ziebFC8CqdRxaFE*-S;_yCUFzo=W-!x{4u@G-kP8BmV0k?jgAI>A%~lZp8Nu8Y^p{- zej%ecUgYasaai_qFXL$7}cp(}n3 zefg#Ahi31s-z+j&TU=YZ(QMiY*&Ri1MNuP7Q3gwuH(f)qwC;qGD~A7vqCcE4wkry&A(gATXe6rkCjq{y%2gZj3H@9O;{I4Q5nH7U5fhTi!~9%F{?#2tU9z!};3 z$~?hf=#y#d*K!m)UkjL_gQbC?gDb%K+SjU`pFu6YkvkZ`%hv$_!{aydCI)b}0RUSR zfKbXjDJNLg#MADRu=ci0pfe|BL}-WAK5MuywQlnbIzKP|jUvC5o6RwF=v%DeK=S=g z%2pZY>IR0EpQ4`M!OvYt`QOPH#1xo%)9&x&ExG7@qPAd!i;%!7Fh{PQd>&p zZ9K`r*Je72QxSlUc4{ z{^U>JmCHD^F&`BdyY!a>yc|nAUQ;o?LdJvBPeIXacN--cV*~0Jby;J))PBWWK6Q`c z@`_BxqJD-;m`78E8Ed-yWBrO$P)A3|5q=9_kEQP_KElWqL%L8wzgNm9EY)Y}p;Pd9RGp>QPsu4batv2v2qpX|eQV=j;gn;^ zDVYZUC?}XxY0Hl?gK@{s$mVqRN8RMX{~=@jY1to1#W(_m@=i;Cj{97FTIR%b)7YZU zQbjog!8!zf&}~`AZNNV%^>sL-n!_bO$y8h?s^CJZ_$Rngbm}KL z0aN^Ic0Jmd?N${GGRpZG2r2GGtA3UTZulro`|J*vH5N9%+GP$nhBX#!$!(2YqMI@z z&%hds=SVB;fNtimFQ8v!cf_bK`}eN6L>~R*D0ZAeQz>rMK7(0UNVlJXPWv>iID@0; zlj+nMP{as|{Z&RaiztT-=Hqa7TZ{0y#TA8c|)4mUa1!TNF=h>OG8Lul`BI1H9gKcQ}b ztL{(ky0@&N#B*{IoYAETwE7(46bkLVy3oOMvP&StVN=T#mSti5U~tvdTSY&j_oUJNJZfw0!O8TN^>~# zim??;PEXnQh*i0Lv%nzjdAi#dmTF8(J58dKwQgV3VQ-}>2e{NP_Q3$CNK7iC+ouG-mAG~yyWvh!)-MH%Hr$wfIA z0fix#pzqlz{gRvsx064;d`UMhPGhBGq~7K#`r?vI(`)AW6@@uLS-g#XcpSJIs&AXz zS3}rAYMIM2fn}8njJJ$OryM1m@Xexqm`MefB({*gLV!zi_Y?yW|igc-EI8dkStsL;G*gQ={Yy$vONh^vjcJD{f+Up3Ns;C^%D~j$2No+;EuF4jG|MMjGo(lNzJcnKb zf6i4oHX;9Z1f%UUH#;*k*fh2@7uyh6;Tdd6h^xt;g}}5~GiUdx>1%SnR9%z*_@X5G zm2CfjX@CJ5N!c8aXXG8Y_t9p1CEM!11*cSYk}z3E0xf=G7>G zzO9i#p~?cKrV<8oo68VUe$b-LeX_YN9bV1$zy=7Q#E>vKH5L_q7}Jqmvx2 zGg#>yIbibEau3%vZ=d^?8kudW7KcCeHQN%IO>9JmXVOBmE#7kITYAN8yQfE@w(}PE zVJkc4)i`2?<)^hbQA~CEa1QCFkzg$xY1o*b%k_h4ZRb>!;+RJte%wlw2&I8AJWF|Y^!4}F;VANw#@@56gdZ6Ov@68(T*xEGvF)u224OM@F)*f8kk z3hQnDrNLv(ZP??zwQz250!DLcLcDycR$@9Xp8Z}k-eR?HPCj8H=fpgNPUDY zkivs(BLF+=U;42;$d-m;ga4%qXM*%~Hj26g+Z^GL!z=Ftx);<#`Ie?y3atpX4dR}( zbM>SuSoP%B8~+(2lS5QbK1Z>CLdL!jTLvTJj; z0KJG!*)A2s)e$<=-Zp|Mw>kBWwT-nDr_$I@_~5(S^B*>WFKkzJJ}xn|2Vr6@S2V<{@zO@f<%JIp4_>KghYf`Vwc2L z)K*(nk=WHvZM7xVDkZPzDXO-jq6jTfN~3h4mY|!q+AQ=>7o{kVs{ilIefQWLh>Pl#sBKwA{sGylBh|XGN@4&&nV9UNqt5!^Juf*z#@6bNG22^sZ;3GS#}B} z!lh8hnMApUv8s{CP+NBgd~lZf)Ki+VGOBl&_U?y6;72-94-0NAr2E4=lV^7bETpS7 zaTS;oD&vZwawwPT)lyQ>m2W#eIU?O0i0naaU44SrkA+A=5h8mJ$!k|E2_<9VEinmo z!sO;h&P>4rq_w5Yb}}GhVfR?k9FIM3ybuGL_Jf;-B}$L#J4vZ^lyE9tM^PcTwG7B$ z;&WV~gt`BL5V9CTSJtaF=%YGH9rj~zfX)KCQAdf4bn5!pVqO3Aq;z1|rb?ek&$>!C z@FTb5lk=nF_foKc!cNqFQhwB;-t{y;(}%RS9>l5^9j{m9XVS&0%=a|CgHpwr8&~%@ za|1&pL20Ze*0ElQLd-62fjL|qX6vMn?vfmVIn`)of)e5~5*cyRU46~LbSeRpQhIfY zs;^WrHnQ$xcz!ilhXcYOB`>Fsa8WJ z(wQ#d#pr@NFdHf=)OKi=ZyD7%n$uYEW=XC`%Nr{(u^)Vo=xg}!_|b@2PJgg%CGu3;Ew6dT65`Y?v`zp0X})qex^^$~zU>~PFs5I?ZK57!TWvzZd- zmc^6LVyfFri7%Tw*gly5_=f(eqeMkuZV>ED#@ujbw=;6#$F;FMjXaZ;DuHFJ7yKaq zK`j5c!H8Xb>rK`^jBieNOC@tT@<~(%V!(zP(8WCBa4usW(VWXgGl9doyo$CaDoGF( zlL1#~-z>v4a$jYg*)zUjW;bz{h+1;!wRnv9?^v({D##X$Q_1smFbQnU;#pD0yjd~K z7aybU7nSOPl?*7`y_-P!=x!b5NtBwbbh6;`%ny=rZ`cMpm#j<%5`&(71jBnc^tOZH z7rv%N&6Q5rmTiIB4`p`=wGVx5qquv%zEr)1lEea!MQRI0p1xy;^h(;*0;<~y>6yEn z*?syejor9^D8tpC0$NJTr=VRCDkUR`XG$Fx1vbvHgreuHz5T(cX~jZyq4mcu=)Xahyke=*;3z zj%spU%YbvyP`>@4j`Mr8wvF;ShH_ThBJMw~=8B{IwlF|mZ7U5BDei2i3Y-v1+)x{b3Ni`c$O6ibnDa4vcYc-?PfI zmb4}`>RBv>>y!0aOxAfv=+kGF+U~dqXs!3$6*M|di6EuDQUT)dSDPZzlsGU94Atkf zk*DeB?n)vEdkVF6vS4In=xR=CBxhS&2AuJN0z2OAm8O~t^~}fG<$j&0a|gw6S(t9w z;B0gUrE0LI<8oQMdl#cr3LWgA)C@AYmq?ivALz3142h1)ye1~QtG$x}ZAgT}->hox zf1^p7rO#zBNjtGg+DS7>4X8sR9Ge0Ug8-AXlfxwKR3s4#PSJ#Rj#*6NId-SBM11;X z$r9mHBHp)m>Ud)ebk@eeGewMkT#VzKFt!4M&g{p<*jr-E3UJXr+S^H~&B3d35aiy6 z^64GUD60=ZIjBUGUvQv|LC{sA?EMrdFQ(LPMNGch`pHoq%@DdW%9r;#q1^6%l;ew` zJo5{k%X0GS*Kh4rd;Al#JLC(B0(eo!| zquGJ?fTzH_@PvVngY0-0=01RrACu@~=c5tt_1m5KccKq9_mn=>B^4{MgAmjUr2n<7+4+;Z$N zRY;Zm{-wo}quu8?)o3W{QC_Oz27}>KfY9fV$3;GgLi+J$9&Vq^rppb5>Vi2USi9@6m2@4N?4EOwSCYX}j112m)>JN@t9ai9>xKS`V!^8o zjruE%pl$j*1jsKyg;j*y_yclZVJ{ zpwiUx%OPqtP&wh_jwP|~VrKX0CaN+>X-PM9fb8H(HVEZt?zu6XZ%tk_n-Xa8- z9ny&UNkJeQKMHxcCA~37QO#l5yHHy`bj5;x^eehOSc$jTwo{EEN@(0wNKy{oS4JGA z?UR2?ZD!`N-*_&{Zp3AUo3UWyYnTQhAMZ}mlp)IB!PuBGVKvKj*431b4OwR+>I|a! zLzPD6CG^=)CESdo&O?>v=Cu_2lJZ5})@UoQzNubb1%&wG2CMu+Tpu*fY!wx5k&7v@ z!K?&RLh)~dsM;{4Cg1ft2WuC!0_j7 zw1R(6ZKD(Xdw3gJMkvYr^uY)v3fF><7@;ij>;-R-{tPJIy&kFbGQUJaM=G`P4(Y0q z;OujBWF#_%G@7}$l`4-`qN-v*@C_V(SRJtk z^*m@b%Vf6Aay8qG)wa{X(aJ>g*6eeml~NX*jb9HFTB7-?Nfy+d_&CQrR%zt9?Fa@0 z-**63Z=sgsl$G#_ zmzDP=V|5sNoMC{melyR7R$c>;as-@ot>bxVB>Q3 zjeB+OeL;~Em4=8W9tCDIu5ZjjdawHenGbec1xF$GW{J(^{-sPnp(8)SZ@3Qr3d3o;vKQ&aiRG&}5L+-%!VwR!s(vm(sz> ziXV>JoSm%HLnIiCjqhL(O8nk)27*J8uPBL3-nq7Wbz*4zE6S1Jvet!q@vhFr|Hhu^ z6s4gju{~+$IJbju{936FXcw(QUAWo-Cyf3;+BFw9s8HAp#Xr#A zG#>+XuJtN)o`G7fTgfCP-jb;66i0n z^D0)Ol(h<-;~HzZ#>;grUe@dA!woxTS8tkZSH3V}=Hmcxo=IdXYyE3G?M_!}ScZK; zO^zw%mx9~1FH zAHJLLJs&Te6+{(5?#qx7A-qUwsDZz?NQnr%4?GAg*T}C^lf^))93%A}<5M=HL<-2l zZK+L$5^gzih(=~8F|M$rFdt+n@)nm=j^$sFB;(~_;bb7v1UmmyypyG@q z+l47f@B&^>4P}6S-A_S(t@RMxbf;8zo6;MROhxCn=QOX-dNnja7DpYV zki`1d^O%3~?%=HC;)5l^{NhO5Or9^9bEgd0KmZ!1+TiLq366{6xQQk7LQI5@wq6L}ngkdW$J z4upj8OY(56+HsWCSJBBFP+<>+)XQQ7)TNxYnvdk$_bBikrAk=t>_lNb|39$k_hM`c zcej4Fn)B-vv!AKjJeTFDuY+Y#mzOr+IHq$~OnNK;k=_ldM@wUVqsYWavZ@2r;5 z*)<>0V8=C3*k}t9zecHU$tgqo)}W;*`eu!!@{Kx=q_Q2ge3X1_8vnM5j;@t7&T+Ax zKMDF`K6M%j{oSl*-yyGcawu$i>|QK+++Hx!2>V6pq~T;|bmo(^hYFnzO0 z>5ORBctZ>Mcuqs#1TZ_IS+6ctqP4*k`Xnu2Y`mw;!(z1eX6>v|d=dSV4E{-bL-f^V zr4>8lzS}^RGnHl*+yK!dQ>kLv|29p}M7SykQ|7T*h2<>jNT=JimAnoum3gFuZ-4N& zV&(r=LS8`$dFSrWn_>O_{!Htc67o)zkawhnyu&5reNsZ+UYR$;8S`Bw6wE3iZ%YYz z8%xMrTSDI3#yo#J$qAWZe5MXwJNEJ6HkbF6X>h?_tM$;4VdXazU{11Az~N*aOJX~M zKwsXf#5BbECEj`lKn&W^5s-%&NDIib18HRNEIg+Hxeg#&B4vUT-G&=N>l z+m#qRItsxbK>6F1s_ZLbcjV!Zs6v+V3)Gp0CdW0T0&j}!M^3rxRoW}59MZM=u_afY7ZUQDK`L2Pl3^lVi;N0Yms0N!RYxCFltr| zqs3Hex5Q{&+>>)lI53)x+E2)Q^?wG;NR409!g{1uU{n1_wy^;Odo<1 zABCO)l0F3g;jqKXexWpUpQ5l)hGpzNC87+p5y$)dfX|C7`-N01u6I5qXLeSA&y4SG zSW3=8PmK-i)fbi~YumT%?6ut5O8q`o27t9?9z_R(0?{?_{M|Zh|A>8Z)(+dPv9{A8 zP5oS6Lq8ma`q|^)Y;N%_=@#U3K#OV057Hu5V~P=C3Uxc6ywEs8Rx1&TYdRze!*jGiMTRZ17nFa}6EYyakGLuPHjXNtl`-}p7u^fM(~=k2%n zuJbmF=M){K18+L>)(bn58gJ8|_wuJ|IWn*%^ijwa@ymf6LTq!CCYW{1kHW`LS;r@h z#6jg5mQgc}IH<@AXn4j%sOLe&-;!2A?jhH@^rk*zYJ13#Tqo?3ieYD^y9eb=xUTvm zxMk>*E`Yci`BNDfFdLN(s`Y*b87k`tx$JV5zqzaJsx?~*pdUv3eFFFsHVl7h7A8b- zv<@wEW?DtMaY*Wys7Ik?5FH(@jcDb5AuRhS91W0k9AD$`PhAL^cQ_~aS&@DjiO(g< zVE1C^Y}}&Dpp$;dQA^Y>KQGg#4|rKW=MxZBXz=G)=X|t`wrv-2wEuH?C}3>Nle7Hl z2e|oG8VFrc`$>6z<^yM*cYj9<2HEvsor8FgFZHNeeTXhu>dfuJOl>x;Q6f1)9ppGh zV~)UbtN(%$7+BL#wrJ*cbCms%%hqRy_?9Cwp5oK!C#P1DgIe#R_LEX8yco4MuF^(G z_(RC`FQp&XrP!>yq|&s zi+4K9O9eXx7Jv9)ff>RSkb$?rKbKbt9gE?=nm#+OG^{P7V`bFHSGYFo3q**(57Zo6 z;l-my@Eja;Xf5kcF%*9Sdr@t&yPZ&)n#*SC3L}39y>n8jVfM*Beo}EaTTU*cZ*!G; zmP^aX>y+|&y~U8Kyf{<6HT>+XjO}p6ZR}?2&|5dP*p3>egyP>|QIt8Y3^EU)F{hOt z9BFYHff>)x)zjFmX-2+hl(4{0>S81O6TEtvD3@juA)XU%WMy|aqa<6*YsmTyru1dB z{~M)?IgNb2RjTX37lbuYA$G#f1Hi0FCfh7*{zK==$CWn#2yW^A7Qq*>+2_8+R%f@# zh#}PX<0r_pwu?T_kU!dxKf;jzk|BSvA%6g+ey>DX3YO4o-z&9)v6)pJow|Syt$SAM zjJ~#hgU)`h1rfABkOStzvr0mnNCT*FLs~I37h=c{H01jk@+;BWvr0wFp^dcrEGRyJ zLVl30zx9z$W7ZKOF2@!8+OvMpJhnKt{R1yr8_@4Rz_YfJO8uyetFjx>dYGnQz)0Id zO5)kY&Lgo6t@=@^6O`7_Fa(S2#C{q25cDSVPs(^$4x#9hZd1XH;0XRMfITJ;GIi8E zAk0WTECOc7Pny|bzz4o}N8I0QH z%+^bb>BKpur51I#yNXk{9WG6@%sT|u!lG_F;Me7DH`MAcM}1v;s)k*Iht>Dzo;Rno zLZuYXyvxb+7i0HrTj_we@b`>8!Mg5Q<5MR*CU>syyF}_cq-ZZI-Z;;mba^fysQ%PwixpQ>;N|+)99J{XFa`iUKtLS zxIKz)MK-mAZn(k!f;7l4h8OX(M3NaQ>m(cezBbwBT(Czdzp0rUgApTWcSy;Gj1H+p z62D@tf5ookB#okqp)`>O{;H$`qu0O~rf*s3%%eN&@R~Nl=VMFM+Vx(yYi;lI>ohy-H@rb(!awp(R@6YF zky>PUhU&E}$JSAWOG*M;p6xD4%ku~I$?4W}3wd3TcKXMttq<+T6@^B{2zOu^t>^(m z;vs~?#eyK5vn1SE;7qu7AoR@qhmvjib`kCULuqR{ zw20jPgq^jQs{N^i1vHFb{IT zqq07{Iy?S`@|@ZC$M^1+gx6^KKM3!xL+AdH*5tUbhZ51j?WvT0ldZ|>8n=hd*SI|w zO%&($=2xBj6F|LhDUF&Rn1`3FaK=8#HSr_95MVFAM2Kv1?VTq zVf0j;FUw^l=hUYkZz&~nye5|o8ss3={uUfJGSItus`** zDLujElcA3gJiF323SNgzv@J)eN6Kw^@?s}IJXHJ)AawD={S&vflNUR!H1eRLdT|4~ z>Zq{Ee)1wgJ9)9UrJ_Qx_Z=@RkN)@g=1p!uX)aJgtf3?|MwQ95Z>i4wCPp7wWHlIXEcXiJ_6ob?# zeT$*Ko#xzC`ZUU55AUZTPP}z^cx7ES?TQ$at1FeHjXW_m(Ez*)00z!F{Dvg~&^a5f zAy(!vJe#v&-fhgVdqp(F{D7Ej%!t^(8|;2VFgA-v`9Zt?x^S*DV{6m+drG{T%Yq`G zF6aWO?+6>Q9ova`#hahZG5K02WFNVwY%-hQqcLU?Wqya2n?;!UP5Q_zvU$mF5r55i z7mey6_-kcaTQR>Q)7liW(vbg_A%7XC?bp!0A@j9sYZn{JFEo^&Zzw-kD<3cKxt(RG zkY=bb4e8=@S9S7n6^$(4Z=epYg5%!&f*;Br`oLAlkR^q#x{9i_`KA(NDL+^0tH@|H zP@LNB=QvY)|4KShO7Ql__Mj)1q#EyP=d;$h2|l0o20%QiEa9lBn~>+T-dLoa&tmD( zwZz}+?OLLmrX^mPbDx%Q5~kC$ozYV{xB{#b@+-tE#@nNpk?VI--M2r7raHa*13NUU(v%V z5kOmB_l>@irrR_lCtiGD6zVCyZ~fMS>Zi^vTNJ4@g0lv9nt&%xx@ zC&Ljm!bg((6e{au2a7a^tFffY`b3Ds-aeZ0I<S5e4PJ7Oz4)x)jH&c^Jf@6LvJc?08 zR*QpCSRqsrd^^&0zeh02P+4cxxHXz7mfl~(-Y{+P_JWE%7MYvj= zZncZiXclQZUlAqJ=0Lhm8yr`uEciZ|m(l-+Dh2ePL+Ff3;Tm-g6yY?1Kx zzh5(y0O4zf(3OYQb5zY=IPR0#zMAioQL7b4^UXA8QTP?R)+`EB$$9_N=u0W`n}_OX zTaLX+6#~RU;Qe*wC&#;s6W+T3K_8-zi#Ohk2Hvczch0A1f8n@8r2GRA{|8rw8pl8@ z2jZ!dgM6t~kce@-s1vpzD;=h3E1v2rX~sDmT&T@A`!}|3!Q%1)VJjv=N`u3( z3!5oaG}ZP2cr)hSD*CUk@S`SS;sbRyj;zndakoBtWxRL{QF2s1yoxF)qN(Q)UM1Px zC$_U-+SGV?Wu~| zW`6i0Ty&g~wTgS9S=Y;CT7&wAOxqnjoOajBEJS*ZDeW|`2Ik8$)1{$3SC-N0&XW0B z`81i<@~6qP2J;o9(bEc!DA#ECp;*RKXw1KE{@D#8M6kI!pYM_{cbYSEu~aGagL?~c z2D9J_n}wJ8m`b{P3;Ui`L=Fd1ZpIvdm%1WFLbvO0<7FNI_yNEC{O3jd>ezlG(^}6? z%e2=_kR@6~>G7(KsTTgS za z-MQC8zCeaI1{>3lF+!LJ)7=;mWH~W~0;`Lr9=ENU=tghg@<~7+B}*%$BX8^eW&3*ic+{EqR@U)E!<*# zfi}mB>b!TpaTXLd-kamcAMYd-#if^{tMMX{{jY2s-hPW3))t?$&%KV=Wcgt#W!4eN zmLpT?avd>&r-izr4uiV^TTX(j;|#7B?W!x}d4AUZZRl=Y(Wu&Gw$?|+z1o9l@l&?M#r%s~SwHbK0|{alBBo+n(~Cu);t4^h_K z7&p1XGjZ`P@~SUA6H(=zhO)yWEfolK&ba!T&Viq|K6FkFUJzy1dDvvlInfZ^!uY~` zDeYeA=;}Smd3+sTM2i}TAy7I8yo!`gy1{pDZ_MH5VxsFx2e%$H)D}{xY*0GId+JnK zS2}RKH*_qd8WycY@JcOT81qaT4lUv&@CCjJ7fvF1$UWR_oj*yp>@_cDaSZb(I%8Oi zrZp0LJ8be(Ab9Xi3T-SG!Vyn_;rcfcvZkW7?`L|nqhW{UWxCo_MEhoG+eX?BO&{2sg=J^#B=0Lq z1nyzz)=aeZwwJJEHs!A_Q)zoW(Yf?_M7;6~Sd=oheq{Nig6K$ z2n0XTCl~8lyYtd#f-^tUX@9ch=U6nQ&yo;WhhNs-lu_n#b%DLQl=?K6{OtPhjyl!W zCH4$z%UhmWX#DIxLksMC)4@*Jkdd7T>}w(H*TCu+EgA2OQQ-pG-9pU7wFwPciUiBo z3utUhu~=6h8_A=UAampFwXH-iv*p4v`meRC%~<<*#P=)#J3?Ra;x;YldG zN)v4SV4BuOEMyD|aIwd`Cw(0msBDRs>2HO%c2?MN{nMmq<H8 z@sfEc{n<^#cw}N@i`QFUY8!P8x{FD=?Gc#4wnuXs5$#v0wEcFUmnfizsOyq|*NQs# zfZ^69dwdVrF8rAC^P;xp%G_*APZ4Q0Z=`B3h{fg=^wA5V&^(4#^%5O%UDltyPzM_< zFN#>OrMeql8^^<~{NO5GBWN{ zWn96XNwoV#QM>BzNw$4>gmcheNwz#}>sm^ita&c3a{YD)?Equ*E z6xCa(GwhWHqtd5c6K#1|B<5p*C?i4v{{jHaNxMsh?xtP&yyXj9Lz8;N`eUhE9L{RX z$7Rnd8Y_S;k|tMh8lgXdC6ynA8%eNI<)DpJ%^;NzB=Zc}V-a5E{Ia*0%CQ)IM2GlX z9{q0uYPyF;6Rgg11;(fuo~V3qm~~+xe&5BCayDplfz}SJnqxsJ!yPj(H~Fxob4-OTq);2qQuNf{^qJAQm~9ULQPUcL^)77 z9sJ>TJ!u3!SiW3Duce4S=CO1sMTA$me#m0wcYSZb?lLa9!VuxfORhZRSEtxip;Q7a zcTgm60dOe*Q~l8b@z zi8d=ji0DeH=!D}rN&Uo+<`4?$FJANp>0yw5X0|rJR(1j2dqa5mk2&6+O-M@pktq zFNotri0~FE!V<_D3*JkgsJ(d1IIwa~OsQawLHD3h*hc2mGG z(Yr0KSOgSZLFV(q056GaA}fcn?7UpkH`kW*+VmKf`JMsT>qyg@p18ih5q&dE42+An z#xhtVO*)l-$Vf;J^bT5*mEwvkxaJQRL!)b3|41;|%9TsB{eh6&-(1SFM#(ZImd2fA zE}1Ps;|+BhS_hfaPSceU!aufAP4}h7=UMYmBj2T5W-L0UjcRFeW(gCYA5I-1DtexQ z7g}GYeo6T&N(Ir|BSciytYPW3t-qu7vS^*(1}@{8XhZ86dh1oNFS4PknSLK3Li)L( z;XIDNgw85xX0qKwh2L-Aa{&3hW1?-Crv^v|lE2<;Ex^0weA4@TFYFC4I+N;Je}xB6 zzb)+&RM~It(|2BuqnAdCc=LSRRVX@`v*?eJBB*}WaJ*H#VCb;={BqA9Xbx``TbWXl zV#u>o%-HAL4Y#ULvr!_X{Ej&HrCib8PZ~B#Eb~u;1qVt&uq352m{Qp<>1@U7V6=E? z5CZ@4ZkLNkCc1oO!`u2x(H30r#<#(hfqpBSX{+JBRFVVQH4lAC;g^0*O|0(bTXYHb zng_J$r8xXTqyC81=1_?3P`?+Yc+T}=tou@0^I`1}YOJtgNIU z)lQuJK0jEKePkR0D9p1deLR$LEUg-k)!adNv8P|#4{1*s@6QvB!4gzD|C4Md-v=dLUnuIFuE~8w6Gvxv=v*{h;ya(-ED_VU2SKpw4~B>I+Q$#vCF zyhF2<_P-)+mHbyku*Cco5!vBjW9uczeH)-#Ew!rk62@&_q1ozTM;X5v)sh-oFJbV@ zGD#={0mjq7C<8`dtQPc5v^B?g?VlA-n`y4lqA((QX0)u1CTVN70xssj11n9>5R`TfmS-#GG`F5+DN zEn}sODZ;lL5K8COIS`6qgu=`jls;XIcXPKkb?)agj0NXccFtG0|C4k^`BPGwh+wuP z)6g^#X8Cj;EqX;%)1H*U>riQ6)mGfDDC#h)DyECb_=AB)Tpz$HeQY7RoVuK7Y@Ljrk>hA^%w{3U0`YWqf6b?4o`js+$h;SR2&6dp5>;A=aaG1x2;qRbC+X?)A zJ>1zW97cENh_v!)m8@^0g}nYI8!HM@QiAJ~_dJ0UDwVAB>G)js`h{30P{2IV*d3`s zC{4;dQIi(V6W$eFKrP*&e~`7Q$(Odz6Tz-XRi=~k#Aww>N$chT_iGY=N_|!I(>ELIUlXdiA#Hw51nV!w6=F5O=3hnn<~1nd z;pDSGEYxI~>8h zntz#6*Hj3hMFd@mmba5=>HkSCM$N3gxBhcamW<`qv=_=#aBS5Gs`-|vX*rWd{oay0 z3l(nOblCI-kN`cnZll^a;1Q^vt0P1 z>`9c>7YroIX!z1Xx@I*J|5% zgYMj`)0?)gg(WebPOTNa%J-hGO*7g?XgoDqCju;|rc?KIBDCx$eeCZon!;(uIuTN9 z7c$O=CE4brBsLg`+wx0cfNwD2shezU#O`BN=?a@&Kk8JO$z-jeI@Im!IshSccqW@*0mx*FF{b8D(fEPiBmNn zYuX0Q$9j8^=3|{WUE6KZ8#4M>5iGa?n`chgCKSVL9#z>WI#~`@p?TZk%IvMh&Gn|^ z8^xH$@z&w!s(?Sy;k10qBxhG9j$N)x?Cx(<=#@<(N=b}%yx$q&YOSoUnW|hMLw8-GZ_< z?Ot$}RqPz?&~}clJUK?OIz}0& z{G=F_FNV<@{p~wP8b*F4VRR9Gb$K5UW)RH&atSHXItg>#sIBVdj zff+14TU6)AIY#$`T@B-y?P~6)zES$^L^_%+nkB<-or_?Z!!SClxtMHjLk8T6bT`>f z!mFRc&LY??wH~M0ls%#kx>)YfWrI-c?&Zh8q~=GWfw>*M^pQviM)c^lR68d1oiXW2 z`#;i-XS|2$t3Cbskw^?qYi7;W%U5?UkNCsATKS83)g+oG?-lYb)b*$xK>PQK>bxbu ze<3_+uZW6kit&i&ixPBtjD4KWzqn5**nyk2Pt*xPXGWnjOn%<{9tgMSgC zcJE`+Aa*x2OkM?3z5FxqkA0VD<1K~;cWzN3gei4^)uO;{6{D z-Crx&^${gM`9y?NnFAK&*#mQD%Cr_sF+--ceZHw=&Jnc(Z}z-PCJ#_?7N|H6y8{an zZBy!*GE&-6ha63=8>TqPwIh^a4Xw>7lIx{(Do3}P2Sqio`1~Ia=faGGBBZykp}!Rjc$7Efmoub23}xI5`7TIHmBz757w>ZOU-w?7%7;X_{^#|V zDcSJnrI%^sAuV8?3;*ykWgfyhyXkPvmdVi8*_RK&UExb34kK_6D<$6WyWWRR9~RAd z^ASAA8vGZ9ekMZeHkoys(mhSP*6@}_T9Eb9@9-xymlB@KlUhC+;pjp366 zDXgRopNYs9vP26{>-C%1xP$M7H@cxJPU&;UH$O`8rdIcJE`5ygE< z41}6}Ap+bFpru{-|BI`40IqDB{DnBgZ$*45@~Q&m>%VEPKfR9*lo7_Mqa02xkH8;+ z_9q?@$4iZS>pv=>)Iu<_&ru9CJB{bTa%bZ4W3%~C6$RrU^w?KEKPAx?L2Hj9uzxg} zzY?FY@8>Hq%W`ubwK^t}aYA+eF)`7zA23f|<1IZ_L&@{Fs1oOIwX{gISuEJ@hY#PR z-Xq=_GPiIhDUUFA^5O1<<02?F$CrKKk=7qCfdg<1vC9f3AW( z<>Mkc8v9xGte>Mi%I1nhRT7iy=v?EiJ$ICEpMCeZsAw*eV~=gwHi-gHiW=rV)aIn< zW%+L`Z9Iw9iiefFJ7EtbB-+CrvB&|48>rr~l})i*-gm?cMwR<#jG3@fdM7Sq-*x>RO^hWNLQLFu9SC5@EOm20Ha$_@J=|~ zP!9vsPy_SqX%WkA+Woy~`e_j!30`c#;0i@F4L?>_sx-DuF{Qb|R^b-x5b2B4qBfRY z)1IRL|Bj~kGon6fr#?lu^G4IUGopDCy4lzpLSLaD8LwZM0TZu1=5~I3rThs=#gD(Y1P*vP~+sj zuO%m447kXVZ};Jp1V%T@aa83S*qK1Zje33~6xPFQL3|v}_(p`aNwK@J0V0>J?@pbi zqXSyZ#j5AED&g3+U z^^@;!Qlk9sl6eu|o#>N@ja}qv!4aKl+IM1$OY%E6Y4vB7V_l{nyt!m`PKZZ^!Dt;3 z^I!9w6WPnZN3fOUztQyDSy7{s7rK386uu)ehI{Zg(vO&iB{&!6z8bQ}X7wcvqi#UJy5%Tx8P$XNs7*7i3!NLV+Rw7eoF}GOeLySdGq=j#{6DPaJlh(ew3eSNH~P`#i{iH^H^V0v z0|b*ydq`+^u}dOZk1*BW#CGqa_*+9=e_%%LL_U9tW;FV;@TVbvis!L@JoqQNyNAYHMxcSrGHF>$IjgnLw&ORQhW&Ip zav7UpZxqY!N1Oi=9qHA-gtyOxV&7Wvx4u3v6wAg$c?H=`i)DLp10Cu6E5f^iTI}23 zDRlda=u^S1SpK&u^wL$)Mc-|4ZM4@$OLF}y;b=?9-=Zt$-|OvCi~jhrbZL73Z;`|~ z<=>8qcd-|A=?7bTO8L^UG~}9S6%}e-hmE)?f826<3wPKtXHpOAqse!FE$rkAPDl5uIhFYLb&iS*MQi z78asOZ;8ajv@mNFO3FDP3Z@`T!WgulX!nRH3FsN#EZUHaf~q6~1HR#lvwblw7nn?43$em& zVZX_yA6>d96uzK*1BB-AKpT~BRMU4^Rn^~f_#jq6=FD_#H4k0ZUj3Ib_MrA=HO@ST zrkT}XCXlhMKC-QtV3hl{W64P1jJa98#gK4cgGG%ohe}Ar=>hq1RjY@f*o+4Nx-fvL zafcz{>I7Fc%A8GW-BcMGVC++d1Csv(AWfH$!l+FtwK;;PUoWNRu_>F=fjXGg8aM}5 z5?Egc*i{`$#?(cEmFy}E<%6!AUfvo5-}*RzocvCMze%KQusf4Cz|^>7DT+)N-yTb?{W%*OKQ1W?>}Y z`D@z?@UXJ^8OH1P@@zeqg~~N$=3pIXf?qE>8?!B+>9p+WNd=y2ZA*>|`FW{z&8w)r zm)c!BH?os9d#N!laR`f9`BwQ*I;VQNn>*88FSS1hU6fb*`^9_?3)5s8%X&Q7d-jUM zz6d!l*NlEFuLiVDlN*(#txe8C;VwW=3bi$FPDNe^$6FJS&s&|WY}uH$jmWFQ%4vizRpZR(mo z&tz)`uw|fo+olInjE_2&b?+7s2=~7DsEt`r3fn=R-~nStG&ig}qH#>qN3FwJxON4# zeZ}CNkOO$OenU}A0vWSS{kU=@vQY?(Zt}_B* z3c_()B!lcr{e0CLKF4|hW&6?E^H?AKBrmD^$QR104(0o*e1iF|uUfmz^}ctAD-P^S z4J)gGE`^DAsBb-w5L}fozOtGa0Cxu;43@`>(MCSnC$xBWv++ z2voa`3bZcy_9pQ=z81|ekUkqYChDHY;*Jf2im1Wq2<8PAm&mi3`1&*M5R8EWEC>sE z-S_TIIuDt51sqqq*s)_{0Jn}sC;NU}$tOsyjZ>K|gVg6sGXQ*;NE?FG9(b+#ZjjnZ z&umBCg4Nb$9QY4bpVc#QJ4LV>Wcjljd4;IYA*3=jL~Vp45UWDe9$pdlC=foq^3yY9 z30330dq9Tr?j<%b-F8pls9aLQRh0&Xs;`-G{4-RYWgbT3!_?iCub778D0O-J-63qg zVa4+-B`NALR;n-{g&GFcP)n#ad0rgENcGZ?f=MCN7kSiOYz*3j3!QMT&W_8VEPv1NEzf9(7 zE3lb#DO_DrWjwNm%WQ2;)e~v<0OT1Q#4v;-K+a6M6rnDu5TciW{mB;O@h-He3TV;$n`YW!2Q-9A(9a0S9AYoKQgRU5to=(7H>XbbIub187jn0^Ydnz6ZH44lh(;SODk=fF@?W+HqNCY+O} z(LHNdH>Xfij9NQn*p55IhHD};jKv>@XeIXKxO|mvGJS~M%^0-{7<(ZG11pSLR##72 z_WeSYW7SZ%4}Q5t6-;zszB!PN&BtrUDY0s4k8j~tVV$stYQ68`PxE8d4=i_o#*VaF z!*ca!8d*b~&}IN^=GjWHb@so%yy|K;)lI?QCj6Zb9E2&x+G87FK$_VB4Ly)GU|1`J zoSWpU<9R;3D~V8HkZl>R8c<_O?f&@|9J*^$%2cF`S1WtaJTMu$J}A$l zw-+IHxDB-?v|m|TR#P2Y79GVkvak)#H>V1<)bId|(x&KF-W13Rrim1e;>Iw)v7I{9 zQhQg*#VtP8e}B3~t!vpRN&2%Q=#yG%cZ(83e(`E8%jtF0HeT)0;61#u2`hKpJK!Bm zSY|G7bNzA-o_r|kyuMPeWJ$d;1$t!^^a`}rmR0m^ygIBmq;Uua%f-IhsJo82htpL- zpZVxhHPGf&O*J`zH~>$PQ7thA^nJlXj8#@k`OnikwbhpVHlB+W)^}~Seq%H@7|s39 z-rUD%j?+3qTiC4o3MXofY@#`J)cT>p(bj^p z({~mQ!@-qiiMG0+Tv|;h%K6fjI;uzUf{`dVrg*{Jx~dz^t)*6=7IoF0#jD)?@fJN( zLX{NXE5ODvUhR8GtEpu@b+m_FtN*!*4%AbtDUu{>lcCqJ=Hn@b>8I;8cYv7^UbR+b zU1;S@(@w+pMi1(c0K);Ze1htS)5`M`)HHtvkI5njTrsYAyOOA{Ry5;kAMRBic@Yj?P#bD_IXqPWY?-VXxK;{ z;QDVBJR59nq=uWD)2>Epi_&?B6~zF`z=?Hr9)hRmH&zqOUsFgkHHdy{tTxeN{@pVx zk!XU+axrylqAFDp`d)Ab=Eh$@=Q{+R^Ue*_V!@AyKgOstnS8AIv)m9=x2lQSuq;rA zx84fJ)kU|R5j#xT0k z0t?f(5yq>^RsJ3FX@j})t(K~lZLCvGsYWX`($cXz9Y|IKxz8=R1KYG>$6BcsXE=d3 z2_pKcDWz1zwy0z zoj*&+yI4YAA@U4FnUR^@<$hp4lu+@T67q6O$or~J1FytvH9cLWO-I?Xoe_1 zt8T$LgiFuD$?y@ywpY8Cg-OlZ*Y2567K_@e@s!sA(*Id|wU4{}gwqSr9iY|5Q2P!T zGLGUf>^fk`RHyt7YQ!^|93wcQzV#OD7|=1pF55DXZJXkGmyuUovGk_)9o2SWu3fYs zJf36x7ExmXh^QY1{QBzcUGfNv;aj@;TGVfYrZdv){nlg=z`8_OUuOoI^9_v zjwq;fSa3%oLW>u*`!}_#Yq*17vvnpVl@B+Y zGIRA!F#BCXlPLc=wQ2m7956ICA?+EuMGBhvc)vYX@zlBc_v5;{kt4^X?(rh=Ox z{}Zs{3=9-Z?jzs4NkOKx2AG)~J7(v<(RcFgic({!ZlY)2I_nJG!fVXIzQ0k%}Rb zjA2voKM?14wgwYzM;-a)tOb7|?;1|saiqcfVe*hpLAW~@H$$Ga+0qe=CNQ>($!K!;n^K}H}KM#M?YFRyyYW7r9wOAPU%zqltik@mbw8rtCYWreTs=!o&pOGaPD!<6m0$ zQbTZ`!@yo@$B<3%?&>4=U8I@dyej22C$949rN+lyNlvREN8fqCxBy?<_Gx#hSvk|y zwQks}4u|Uu3^Rjq?5?~ui{f8Yf42P5k}C98H(D-NroFw@H!W8>&~ts%&RDzHr`LlB z?(L(#=HY7h2`r?fzUpenpD^+Js-JZD)YnF*@ZV%Vc3|f1Z>a2rHSW)whdd@xOSpi! zE6wq1MCV!y`X@#07w%RW%UqE6Jji>#og{CrMqU>tZ!XA7Q&QDG!?|(h1BW*J o~ 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

w>=Jfky>?Oy^{g;g%%wTSTj;y9!mq|- zha=8j-@hiIaE?%m+_FMo!*288`*jk9p1 z?lo9Rp$vTw!!^Q7z862Sg0%Pt7^Y7a)6pM9JpX+Me~0{ZNGk-zbF}FxF zpmwI-KZ-2lCffF+cs?i7Za2;1z*(!SvbujI)qh6ypXItJZ`FT>*w{DfKSR5P^`D{L z96V!uN_p`Pt^Em+D%Zx+(Vq}R%G%x!ZCX>>&#=S3H`dV(t6pdH`p+V~RmteZDorZM zUXoU2%rq%3z$^HKs@QwZ>6a@ZGl0O9WZB!%Pd~E*zsB#==R8d34QcFo@tisDDUA8! zc>wUhA@aWfM^N5)JW0I(eg2F8(5n|jvd@MuYt8Gx=R6KTQdP1XaxN7kIkl`*3<(FC zs)~Oe-vBTT61;k3z(rWezcPl-mWs8e#{^BYiPoyzRBl3A_70oygC1}U4|(~2+psl_ z_dZ@G<{J6$@^Sptx7eRQ24jE=`xP}m7#zsgbbiX2}?D{ zFN-)=aFjetrJ1TPi)8(S`)3~h!J}8S1*xWq&#%DKw(}r$`b7lOtt*;)#q}42#Z94( zzi5V{Ir!7`vc1ijU&L!X_fc2TCWMw<)v*8cRfsxKo0fhucD>N(1A|=3RPAm9e_ezVq;aE!L_@1u{X5Kde1IAIyi!DJA>Q&3R4*$`<g{L#qWkH-~x2p}j| zsf|m4k^0^gsqXtTHR}I1O}Xb1NLy}-7B$-%_=oTfXu2N_K#Xmv5MIJnnEpu7s z#7sx1m|Mt}e5VM!3Ybv_z6?nuFWcIZdfyVGyigF$2VN33jzQJgdkZHv7s~Q29I}ZN z_m{}_y!R|3KYcLi04Ph7cNu+6g`;TaUt*D8cf=&9#%$fH1;g|J8hBf0%Mi-EXxeQA zWL>2-x5Zd6>vRm1j)5B75#iqYpI%B35S9+2R7qQ$*g_^y_J#__{yeNUNxgQo_>M?V zMoI#g2m7<+Hmye)&UF0E#aDGqVUuw>>x6bpvG7)|2q33QpxdodYF#OMA>wpqC3J*u zpP+XuwVc!bm%|WcSp`)6=m|$Ct07*)tHcBbHKGa9$^EWq5D>Kwn~cpZi-MxSvb-v| zrBL&`;$@X$!ia9c3{}Mu?O1VCIWI`;k-H+5wcyo`*L!^LYql~vp4r5@AdCW%E-WPFEjxUGcC5LZk6dRPZ z2$M1z4b@uJ_rdp;P@4xLxeu6@7NwTBAI=gm`gLlcfv2(n8gXg1ft~NZrI6cfP%xPe zz4qumvIXF}mq}U<%^1W2gId%^epEgHKf1h!JgS8hWKw+Jht^~lyO}(5TV^NfJ;5(k zgMh82dDS9LGAVP=l=Jb`CZM|6kPXXls#!KHW`U(GU5}3rW>Tkjk-RKUcJ223UKGj# z1v40oN+8dB6t-E7{n6HTpa{=E)eM}Rg~E#s(MGjQ7i$US++o(A%U+g)jkIi;oM?Px z*%$Ii)1SvkHpho{jrDxW@uCuIG z9#MH~s0+Fbvvax7+?78BCA<6Om(TT8zvo6 zchX$xrpQ%RQzNusY;N=?l#SYR*T+q6#wT;_@z}0(&`pkj!1J@49B=x40C~I1k$zne z=*uXlqa9?+f5ulw&@6X3%Jk6)+Uzd(HyPT{9d|j*XH+*}JjXca!1!xWqK$CJHJa%g zYFtcRJ>=fzTcdT|Y~bE)9&)rXZj|facJ84C_+E;_VX|N5+u{cxV2Gj02GYftlSf8R z*_YKK#_@~5BUj+~*3l$;%4+=P1}G+L=y6YZ96XSpdCK8l<-;|iRJJ5-3zFEmO02t= z92=Q8x?C$ZoqYv4ePAWCVfg`8=}7~eBjkmx+Bclu@{&7hmWeX9^x1=r&upeLFFD!k z6I@N7{&|410g<1sB)sM395wDOw==;JwAfp=_+&s`%r>-v#mHE27_BX10_c!8&~MXt zy6%mQ9Zp^i<<#^}z}H-pVVAn%a6?rwM|9*R!X^MW2CRGKkb&80HDSnIx&(+IXh)r~ zt~-8{MT;8Bkby%l2lH=X~Kqv?k=}(t7zR;AuZY0Mb z#$hhjjWA#(Ta9rr7eK55X$)0n<2lDTWFp4l2&&z2j6+moxv!~s7(Lfm?(+ZmX?bH= zRVY;Xdsq`-o(D~DBA;Mv?Cv9{AZlZlkKErFL#KS?jE0A2XCCXRs z(5S*PXd1wHF0hnb3o(wlzrW^ue3E}!*5#w^4yTSKFIW87>*kG30l@XR2EMc8B-?k~qQ zVPk8#n-Yt`(?J>2b5m)lzdXPnC2N8dMo60~n&B>1Y?e1w`O7~VN1+r3K3I zsINRFQ0{JAPDO!oh_L~E8>nK9F-Q(K=8`2y4ht@si_R_~OZW#+t5W>5AuX6Ygp(-< zc)527Ef13W1uZbw8jC=uD-5`)%?9G{PWOZ4=%_9n;|?A0I z#6<{{46*YN3HW!8(&G#1@XVgEgIVJEsxk>gzz;UoHC}RGx{Z;^KUkTo?@4rK3#SK@ z<#3wVvq3{+EPW9oCz?O2en3mP#E?G)h02cxU2=K|NYF`hninc3nywF~{h@Mt=;429 z_ROZ+YImlR!PL5`{D{|q!FCeT5aHiimiXqTa?9W>z>dXD-tIC;=*3L6VDEYA96czH zZcagAa?Ak0eoha3p9-CO8d43x8T58s!m+e1-a&l0h3{7x42|yJ=(Od2w&7Ged*6Cn z8@}Z+tfYhiWd_r>Fu6w>I*&|&O$CeN0-f)>z|{i(Wz9#x1J$j7jW6B+2!q4u=3ziM zZ|tA+>~GQjCfnoGFI-NEQfJS|vk{HiQpSyV8|H$nvg&vAaViLxV}lm6+=*2$!%yZC z96G?<)k43A%e|e>m%)ZIr%?(;^bT;NOc!^v>E0lk9U*sWuy7~xQ@lV`ay{vIgxt*w z^+_~_;Z*QdcM7w}0c>^Jhylk^M~j>q{1V2ffii??eQ~*G=`9O*>e92c$084MlN8%l zc$xC4Nu>NtQ*`@&ci4H|jEl1?W}ePoXE^0#a9XS_h~9~mL$r}Oqtm1mo~2JB<=*Wv zGS@D-0U;q080&7dRyD)YOh(l?TIgnMpzw0bv2-@-TmnJA0@LM{QWxqTCAalSRVIH1 z$T39h%5*zYqCnA5`7uhK?&k}_VODmbP5A+sirKViFwrDQ{=to}gTU#AQC`Szn;Ukm z8i9HdvNbp+QMtSThi)kj&=OP)US+5{%D&rmiIgGB1GHKW>uIGdCvn;~PrrKP-m|jo zYE=8|k2)oEDO&E02+me9a%ZD~ro?~}8TbAiBhN6l`jrI;tb+}Q=kPlltiDoznhTEO zr@ojn`(?y0?|m&6@?Js(QrY zf1DgItwTx@zUsO_E6vGCIb8lClJ&%OP1JXt=&3k}K1BoR%{Y0KJHFs?4j_&-PVUvB z6!X)8#%E&TK#h8Q13GTNzg3Ay3;;>wpERMRJS{aZ`((O$eh(v%oF8Y8>{ito=Q$IZ zF+5dv*Qw7TU1>|zcuNs38;F-9jfmEXmu0T18L4E!0>R~3o{yJ1#%4m=FrXAk`%|~+ z7Kp?uQ*O!(Hc>G1@4Km^9Q2Q`u}@w>IR?pTnClV;IZ333D%MuF`oK@Kt98A0ByzcqIPX|PIM=CeC5N>69pGhhz&F>=Yh%e2uLXUjBJze8MMsu?$)Z+?}Ea2uBGq{ z33dS5@aykTxFe>GTyt%e&HfZu^Eo`dXn)$3K5iqotR0bfL>yvu#Mdz* ze02I!dBk|~OO{(j2P;2dw}90U>4FivV7kT!k~`(b>@ix8#z8bOS&j=xRkjpEL!X1h z0jR4i6O{rEC^w(1qs8OtcC;AxPqf(I>fvb7q#kT-_?F=tOwHN?E#j$bTe(|?3d(z! zYdN%l8pfYm4=qLkEi$ZC@2mk@q}E3Z`ns*`?{WY!-er%{brIvgyq#>((cx8m@-TE* zM``Wk=ILXhLNNEA#Hs|m?OFD}pTW-v)qGG(FJ`yFKSkbvn8N(_veoT$ z7aU`!f?&GZUT&N7T}yC$OhCQrqCa-zQTzuDuq9fnPC33Cisv9xP_POOEdrH%u&}c1 z+N)mQf`Y}TjFa5Uu>+Y1bA;kn$OY8OT%nBJd4T*I!>%iMcLndRbO%LoGSb>q+2yIs zL@0VWJ2|kKi-a+i;gd1%2NYxCNJVTDvj=r-^k+kV9`_!oxJG`*;$7RuRLruP?pTQI56DNQ5r^V|rB%PG_-`VbCYg4>7qC z{d9JupV3Up+%!HxW)BkTbt%h5Q^Ubzi+*a}Oo z7LMZ3*q?rPGP}{dPI8jlLX&E6_oc&~WFOO?W;)wR79J&*z(&ewIJKvdb7y&~KVX4K zf6%;7fIaEM{2)He+==wG&a&LB1a|`~F83~cJ{RF^#~?7p1E##Z(WleF<--fqkrCcT z9jtO#oA&nmX1Y~!oT@(SD9qYoccR-ELqFH5N9wa4^}L%O^{~oKeCmGB$961Dv_dTO zry{G|+^ZZhDjd9t4M`cV)l+j%lRKNf>_ffMK4&@QmSm0VP zOZ9<-Dx>jSHx_I_&MzAaI;YDKi7+9cQVl`^Y}@f4VX(H3_$LyQ#^F3b{LUPKOFayR zn`w}DSbsh^l3Mnb1Ko{W$pao>6Md8}H)H>EI<#h@iCuxd9WrFkpv~Q&>Mh18U1Csk zmsq9ZSdN8i8zi2oP4hD3_Q)e?a{|D!=b{)HAI3zgwgEe^6dO8X89Q71%Cn0cYP$Xc z#dZN=9_&a%yU0yZR^!Dk@>l5W9747Z+mljevEAOc(?dIR=FYM}xleYLW4pjVrdPgN z+6e$B5Fu4~5y}R1SdPk99D&3UNsQHO;RH)s)P9rR)%I8vcXYaP&V=yCl7Xmy*GkIFvi%Q|%UsCun$g zRJsdRdSGEFD50i)@S^l6s7nhpI`a9Ww7$C>n*)lNX9)CA*1_0x5$obA0_#}#gOH*Q z0&c;BTw8%-jcOWc!243B;42bTt4le)u~TZ)F48#5!CMayWMbHrngkaUlqyZrVT$Zj z@Yz(&%=s(ur5`XbyNB$D$m6UY*mn5(a(c+=CZDc!q=)>7`?^Gc21GrJ!g|Ubu$v=$ z0vTG<^q#T>f34~%4>VmGPS<BS*xHs@Kw3qCGSJAy>VY2`4^n(d(JPqt8|9_ml2Y6IP)IWT8)2RW{`=-ngN+2Qhl1)PIy_Yn)0*Z=C zNkS13kz5N$K)Q&4LO>7|OAt`75wMFu3cYAh1QrFp-jOis9Y-dBTC9+5okQ>T z5lQaDzsFhOz9Nch^cAtTocL=E)gwan7wT{G&?=MoVXR~QVf6)^Wi&G8(@v4YzvF)-Ev1DUS zQU$WD+a&5y*Z@(Z`49CKs0-A_n~e3G3d0v@j`mf&y27w5oij=s_T1^6SW|@xPOAR2 z0V1f$S7vgmU67y=>Z09K@i|TFgJ9bjn3!L;ejF%hU32niu9PK z`cI!b-9K6@Me2YR=nQujuu=tuY9wV25@9~LJ&Uts-91dt3=(#n==yw+=utCB-(Xg^ zCsE{J5$%Vn`5`leIDqlzAj<71!g^Rh$w7EtEC85;F|(yRCsy4ZRxuyB@3#*T z@dKU%q_eQgO0yx$ZGb=p-W0`GCt^AfG4*c{RtH7_7jlr!$p=dzKdN$Lu&^q`4o4}$ z%MO_3ih`)&P|+M`?=y$O0u)3$h63Nc$YYpTXnnsky)aCSNrqng)@NA0P-CB!#^5h3 zv~2R^+~+2QGnoef@mcIb7}s#&7vR;|F}E4$1(JrQLx^Y#9L%ZLlbU?nJeUgpj;Z4V zIg`&fYRU&n(7?N%%;Z5S zP?N}WnZ!HYoRj!A!VlL>{X9a1_YyjC0II`3m4kP)=!f@IElK6z^H4SvWg}e%58uhh zW?2kAeI!V7Stpt_Qlxlb)VB}Pwvi&x)Hutq2n^_%^!-Q?RXIk;FqMF=93ul7Ju#sF z+Cv>iiQv9a9x(*Kt_1MLaElcNWn1)V#tImSD^V6e)07|pEQ+z{W6iP{?xs-X#6C>f!X;C{d>x(iKJO>%k4-@eL9pL8Z8<(hhge8NX%D9 zk%BZ?D;_U9Ls`_WPJp4#+fqyS_I-8*rz&95Q;rF6%7V>*(Kn-oEw|WqzJX4tSPFz; zRfq{H7&Mq|q`nT_w)@kmFaXUm*!2ySWen_^=fE+XDoa77%93IL^i(ewg`tb46owK7 zAm}jZ*mA7HKrngxrTYI;Vw4#=2it&^9adtB(O790+7=%cMBB!I?KY%?V?=jRXmg6@ zAH#c;g6Wpyz-p$JzoHz*t!zJc__Fd=tfb}{BFg)x7J4*9ejAO-5PiL!qI-4Pogoqt zA^F>ZD%l#^Uxg`KgWMOh`mnu2h(Cp8iZHLvki0%C38j=w(IFPAe+V^|!~<^!wnBj^ z@o-Q9V^&vMmnm$4G2j5&7R_(%F~(Now5Hn@K|g1Twh?~<_>4hpS@>08aRKPkW&jdM z#kC2PlqEQoq>i5Qt5{NjEvU63&G(G4APWv*dY9hK5^b!{zDs{(!Dcvw{If-o=}Ik! zfXPtZ+mp^_i^0Kz(4*_f&F^byP>$#k-0nXo&<3(5yCO#j!&uPrgEX^yNM8n341TSS|KGT9;7%Q6B1u2FQi+mI8 z17$p!Ogqp7Z(BBPu~+^OY^=#-87I=~ej5jv^#RO)e7vJCji6*_#%re-I+aX(DpE8cZakEAEj-SNpKOC8&!-`r}0-AHHS{D7;sv z7UM-@!+t%5CXN>^Qtll)_Q*9rko|FIhu9qlAz^V$#6eJg?$(UjH)r%w4>~y>j@%IP znIKjshI-zmeF%$S`dkiSET^a4aR6#?bIkajHN!VvQ{2EjK{N??1qz-r+ws*G(2mPu ztorH$6f#kCZI`4U`4qI&sVk>)H1@AG6e2NrqJZ!kb`rRU04Ne4xNZ(KSp6TAby(E{mkv3 z^{8%nnifqFFLInoh)Z|wTk@&#R0yxHP_L;N{6NyD8vdrKVipT>>mdlOq_Oas2B*i| zq!BPBndIm+Aj8mKLaU~U#) zra*e}3IaxyDR4ezJ}O!{>r|Lg7wc7>rbq&C{87=^XSm&9dp{YG9r4peh+l;b5gKe( zyn5jdp}*oZ9I+oVT||33Q`McO{OJhKIMkH(P8WkLK~(24K+cN>JtmrZ4@K}8j5O1s6FI}etQCbVu?DJs)V7NQeeka?g*ApTt z%2{$e5^ktcARVry;IV%~gylL*6{9`2VX|u_rG|EOU63~L+#DEh(Y_tTCRGC!al85M z-P{^Du3mF9wCM`%Wn{dEk>pI|O|rt4suUQ=#3kdo9lOd5c+&OTWW1jWWtD}4Aj6hg z6P`>=$Ve_RlMCwJECB6%yIp;AKyNA ze)G0FM!A0b65o#CKf??Q@c5T#D<_oxmd)|{Pu zE$8h{baEC9H@@VUCBof9^|FsBWHz+A0_ro|yI{6x**MCnE$;c~UkFuP zNpi~#>d=BN%od_&!F))Irw3plLqH-h!39uRpNYc%dfKji@GE6BWBtKX_kxP|8SKR8 zAuIiatpYu*I1MUq**wjWX4qY6#2m5B%GjAJnz|Qc2X>;AT=9Cf;RUCD(r z&uPkvqwqYjXcV7DheLx^fO%H^++GNsr!XA&z_{BRuu8Er!wee1-Y7Puld@CBRGxt5 z!Ot8pVTC|+H#cB2h6l?>BXY|ZX?5Y0W@GPD+mLL9hh5TuhUAOp*3xbCLcZu=J-Us) z$rlm+9-XV~Hl}O&HL}bVO%t7jyT#c%1XXx92aJRR3VBZJAbU6!p?8Mn?OH@xb46Pp zXa3J~%}LaP{4{}%&V}V^C|Tx#lD4eXdIYTP8K=@5-)B4i6~GRk`aIF9Bh(spb>;Co zXh<5n975E*F*omc8T>#~QNM1w1ry_&xju#r#;OwAp3FJm;5bAiZi3}(Z5IcsC$rHnFtU=G51Xn4;u1D_Lj$8b0< zwh2xt;Jb%t=kzBMSL+U}=+7 zb93l*Ub#+DURp~mScTz~vF{v7;1b^CoOiMV^`Pl|!VUY5K@9*hkSDLZ}A)P;Tr3NpER4-6h5B;r1^ymxN{64hm z1+mOiy?dHkFBQ?o^EAp_Dng9s36#H7M0P*V@f=gZ875<`FWDUd*m34KTVtGT|EQEM zrbYkf%*PqyA@2g=?~9=rCw5rh@IV6S#sy+2;yfOC5o`2of$+1mqpJmCs0XfG`~E%Z zt&1^@P>0V0Gj)Cg9vJ1E2~Bm(gJp1@As!Z*G4LH|-;1z4U)F^$XS32p&?tM5{>=eE z8gznrq&b6CFyoc=c>tt8Hy|CJ3P|Jme}eRZF7)wY5kUnn3Xd9UlylT5AEI?HiXc`y z*m#Z0L|zm&VC__NS?aV>KqjcL^$q<`puI+^F9RY?UlPG1FSpn8c?L}Fn43Fsr7t%( zz_6Gyu9(c#ym_M-NJMOP01?Lq_E_Ocj^?7SYYKo!WNR2-oQ4#nmu z$0BDsyE1JM{be-OhR;XtrYX+MjI|{Jc;EZy89g9pX=^>>o($_o$GJ}C%8>>7Z9n?_MTzx zdJr}Er<0-vRJdHcY5f9n93$+LD@0T4iZ^M?3L$FkN@1`VbJ>wXCs%+>%q5?dh)vs` zLSiM%8W`JD8oLr-`zbNmry zEEkNX!iJk$+di40^6uoZ+IZQx2HcoqM`a@_VU=(sa_J!xkn4N+!3wm8TI)7&5ZCub z>;NwGRoNw7->-!hr>$+OXd&L`Li#c~z=sO0#JJ7-z6u3eP6Is?JKOa=Iw;g$hK>qa zbO=CXA{b^wbpSD!`qL=-tWAdurvrTEsn)bK*TDv zT+Us)0K=`kn-DrO-%Z#DeX{#W;VsIQptuqLN_-)L8KwDgjxL=u&vXwYOfu52P-jCb1+sq#fJi0s|Jb_ zmay*!gWHQTtj)L#?z4?JA=HJ=Y!rioiswVVbC1Fm>ajp4kS-_=u+TV%JmC$|{{MBz z;cCc<81f32A)f|mIK#ZpIh^r49FPK+;RI{~tp03EEjF33YHW$8uQ!R8yd(tBbM{ag z|E8GK2x82iJ2ByO7JtzK9M^W1vvI2E3ct@rFTmeY;O`@J`%T31Ii-ed>a^Ji{~QPT z?<~r&ZD=q(wOLHAxdB0s?8`5!ji6O3UEvW*HMWS(IQa7t8nrotdldC+6r&)^j7kHP zV8EssTSO#u__;f2#TFr%xDy@RVlb^mbQ|wr1&rG&TJa|chFgW5pT^L}tq1}7wH+PX zDjuEuN&Zbr1L>-w2$5Sby+WIJeZAesps`F}+g7c6b&QOUEjopV0#meQD;(3<#R#e9 zXH$W89r5nKZWhgtnB zFOzMX7#aP1O_dgv{Q_&5B>!X3aQ>~x!F&F+W*byPPI!?sgGS*EdnO zVKY11D$tOILKX^9w|=6YT2&qqGKn;%5Pg4GHCv3SSeuqeOACc9MGd$=}hkDQ$em}IToje|4R3lot6YZnC3)mq7B+{Op@B^JUIJmR@ zLVkaj+c|V!zdzNXChrK*rd_b&_*}k(QKO^^B9Y&DDac|xgsO zJ!r%(@d2mAFWXKbyP-8B4lRARh-)Hzplt^{(jb4%@Aj=v}zBobPY9q;K9uxDI|ISTWfR7doD8Ne%Xh8I`YK z);!pfw(Sw0m{$$BCEFb@(o^qM9WQu}HoqrS(%p?{Wd>dSK=_f*`$mD+@oF5keqV&~ zXt=;A8s+k9AmzU=Hd#MdOAS5{-L0F}(i0yDX_l?dO~=zWABfOi&gwT?7?vjwL{{Ik3FCBU;b{0`5jwSJ!AB>I@EZS`IMD#57p6hz2k@()FEZsl{HAgR6E^VccYb z#dJ0wd&CxGrR{q~2!jX$N^(&PI<{9l4Sm1Yhlsh2pyeN8buTyG^XZ4;2aC@WjX{0A z?2hM+E2G~1SVW8~sR@)q5HkBFf}R5<-eh--z$t&MkBSRr4f{HD0d`EM!ZB^bBX(A(9w=wy+op9_Y-0td`N9K%+&7$N}-7G;o~GLTeVUEPpv)$?&c1?pA- zt}xb1$DlmK2Rkc;xK_2&fW5)0f3nqxnkaG_u#dcjbpgxbbz$euJ#zwUEAs{F>zEU@ob zZsgT4<;F8TjLkce`W+Tc8zUXyS`Fd18=#+IBsrj~r*S53E<8n?HXUTdSP6_^b2x1~ z3{OjTvJncB;q;$y{L4dBdRR=wS?_*dz(bQ9}yY2k^z3lWbPQI0w=An>ez{2yAtV- zBO(@_iojxVwQ~m_C4ztiLj-Y>;1U44mFxTQ7~^DkG2j!>=0h?^L=hvG84K`N9Q8gb zwwvMfTT{sMnE1`Ikp4O*y2|g`tGw(ZQXGh$(;Q{#Xbfw`z~O!HH8AVhmN2>WJqG=J z)R#@F*KCU@Yf~M}p`%^BfZ*SX5!Ha39BN+J^d=oyTQ`ta4{qp5d28I=t-niZ@tqhP z^U4BT%>fRZhKxuB$goEeiDPc#??WLA_TWFKM5RAYE1io5?d+>sx#T@mFYC+ zXEDwz8)aF@yY#czUHN0vFJeMUA&W)qCX55FZ)A^T7vS_{yJHbBRa5y7LiG`E+_x8| z8kl?{fqEYofx&S7_eK$egSzP^{=pD4=Q!flzfGWJ$3^ScZQJwF9t4797Vh}m(&^SE=T`J?3W?ZuFx?9VfBV10Seib1>IOz?yue0Z} z@pgv^kfpzhi2B$%|7`s4wo09CA$<5(5yhE;FPf$E43oq?Jr6NpGm*kiz|a~(ZBK}} z_|qWF^KrNM7|s2XrKUEp41|)??`FaDgWAf3z$W4TwCDsB6o_vj`d;qEDS~FQsvl%k zpk?{73@enH3^@@;ZMir zt>>ob8NIvqY^B4fU%j&D>y7EwNiil0zGEy>fvw0#KT_-8zVr_C)G5&&UJyeRs4#C9 z{qs@!;gpE~_lLJ0qq-$xaPBsbn=}vmU0pfa1US_UC$Cs(D>9U@vg|4as!QWrun?jQ zlq?96*q2fIo!4Qnh1Jl_V8#XPcgyDJLQp`a(sLle^RufFrv$DiyX+>RBcl`vcq@IsoabFwIFUHa|iy zl!-qZI@1wH9J^B~-K;f(y0H}wO^30sJgs#J68lrsY0;E^Ef+SMv)0|C53aR&`ksi> z@JvlSHyn`?x4l|U0*oUOSi%1x8Wd{I1~&ai1O3qLgUYY`kMiO4_8HM261&b#KNP80NFSZG&8F5L{JudF#XPndX{t=drtKAQ!8QRl_)Uf;Nf)moS2Bq zM>z%6Txxw@42Vlv)|gl0@RSk>9=$9=qZpWwF0!W?=iPa+ojOl4r@L7|Z(kOX z*26aX=CbJF%&M45Bd>^{&>l0fOIY3nX)eQz%YiT;1O@Z$9<=ldwozfmm#L1n5YVXT zikRm9T~kOd)2_z`QPhpt8c2gW>^G6(6$(p27H3I(O(un+MMES=yU98fv;K4&$O_~h zs+e6rirR5{x8UDJn}EU`%q<1n0qW|&GSDhMCeW51nT^B9>t@oN--XQ`!9Ovy;ddTN zCI+d7^4;&ES2Rf1Jb+>z^zn`HMlSR<(0JK?bS4Pw71h!!5D^(MAmxGFkZ zf6S#Pu8P6dgG1<>t2l~v7j=1yv1^ORO630sl>T+p>ks&Qmk*&ie~A7Th-H7k=gMNp zpCUe~I^fUpN;aY~vlT8Q{CCdg+?z zhJ2$Zu3WNZ(bKQYXAKt3iMHt>;>nb zeeAz3W?+%p-Vj4zi8kC3Q=r~>Z26}Jt-k@`Z}C&~!woSKW~bj@kM_5;p>8)tHbmLC zZ(@uWBIui&IN=TSGZI`okScH!q9m&jZk9vjSYMBzGKV;cxcGgygx}DvNy@l=;m!@_ zVDLVHgGqx~nj5vu^_!E~Vxv~Z2bU>prLj?SLrqeruZF!ZJS(W44^Xurqdd)#N~8Y9 zK=*Z`Ie!Z|v>nnXK~>-F+WLJxZ*%?jzx3RrvgdVU{rp~9vZp#QH4pw1KKjN>!Nv+I(Bg@UvHNkdJ+5wNM8|L5GiNrWI529WgR> zEdmBhncoAsOAr^zZeoL07^y9zoVKt#FBojkJo`E+94G^S*|SvV?N}TgyCWLA7vO*z zMcx%r2?c!AkF_5=#?OadVx}!UR=#)rA7eDPhBmw_gD94k*Tm3}=xWWtdX#q;QP9v1 zn$k)%frGmr-W88oTD_7eBQ4&q^pm43OuOw!0W5rozC*DjFMan@mSm5|9mOem{Ftj+9&)-6#U_(=xo8K12tWg!`Fx+K~r5DAy zOA%4Xwp73SS~ELDY9Dvmt7Qkh!`&M+7tTYDePqnA@$Eh6G9NK7O|ZF?F$=$WNT!+b zDZ1h=-flexTG%5M>cMZh!*UvG&UwfiYl0ZSgYz<%aZYS2eQh&Y}dS7 zuC3CcxfC=aVftu=AV-2EvJg`#+k}5g!@R&NUTmj8#wEcgHE-^i<*v zY-l)%t?6gb{_BOB!YES@Z9wtWtsLXnoC z*4x2!r@EYLy_rgLYsjXx?}bko?W-ZX`1}$Kl=eb=jd2jVrcAf)3#KVGWqWsZ=kfNM zG85_l>eP~=TA_KE2l>TnNthT}^ou-Ruetj#({HMrlQpMubIt&VLVDygYdD>(C3OgM zz>Mj&WqsHskq>=MZ5fBVb`RE;Es-Gnc5Rs=K94r`iJ}5vu-IG08j$=5VBx0rhebcX zg0g&N_r{Mq6!Qjc2lEEs;=Pl>lC(WWdCkkptFq0upr3u^;>KMbP$dtjs1+FUfNK?R z((8cO?F=$N^Qz(1`mBy@8&wpbmmf!mr;y~t?xAP@bL!ds5T7(Wm+tq}XOXS0v?WIC z?yxVJ8EMt70VlONv(j4e%}g|t?#xO%y{_ZaB{+A<8Bb=zySYpthl6 zO`-e%*^FMRC+&?lKe%48_Ld=WxYp}z)NAJ_Bi#$nW#HC5KN;cy*mDK8 z@7&d%W6R_|j&9=soIq)#P72t@t^CJ`R$RHslAWKwzdt zh4cFuiUNo}kDAvP;rw@kWPoKl`3Fl0(Yk#wZ|rQlH;oCF-J0Ke>N*t#;oO0eT72{m z(3Xi8``BPJ8SG~SsMu0)s;#)Z6zkY&&xv4JY+)G!44^qLJrnnX5qmxkmBIp%|4f*C z)V(-OOQ8|rGKxL&DU=%yULQgm!sSNm&V|%HLUy-opjRSfLY;!oaL>nq2|2A;6nUem zRzTlH$XM(8Sh^Jv^MAGAtvJbKmAB>bsV`!l3z6PouvB~yE8T_ahEu-VHMOM6wEdqfW;8F(5%55Z}BQfPcnZwIybhHd< z{uamP#--@ z2|tbWO$(fow3ngX!u%2=XGT6d1%vVjSB!*I5uv@T`D-m$3ON8<-+Zjc-5BX#Ior@! zgETx!tz+c~ue0dsGXP;_tO106^iiyA$BAbCj+LLWehJ==^HF|!Il^#oYi^tjbH2s- z*E)I(cFRP%9Vg>FQXrhU(cR{r{?ty$FzdyKX}FLtS{E&#--K*Yb3i>O8-d*IYv_|b zrA$=1o|L1kJ07Bw5-hGLiT;){iN%g4^<_g#G>xb)<8wdHz~1!4EI}7CAo;QE&6o+v z5Ih6txj?lz=S3>+y))mjw3zR%4Ft;WZuXZUDRTCRJY_+R*2@L}(}&m{eKR3w0po#- zYH6A0=kU^i4l$ZP7J8H1;$@5%szA`hL5X-7-@UDVYaSqvain4=+0G~G(Xeclqs`N3 z69KFR8xPdg#{oiqYi>}=pGN;{RSbn25_jOF5KI*g8;me~JGAxfy7Y0pRLbwvyRk{3 z4*`GFxvnbP%jCMQs&Knk;;PXT4P*@KEh`(y@W8=S0pnaGU_`_GpYe=uXgJb9b`s^2 zjgRFRF`sj^;B+DvUIt~#xl&!d#rPpw=^{_^=w&jIA6C25Fi`U=DIJ(V)S`*lKS%P%8 z-knUI39>=ZwGa#ttUnJy+@VleGegrH{Fk~W$VQf2dOSfUC1H;>)Mx9?K$5(giu`et zP6vWAf3x(=nWZ^8z)C+S$R?^+zNM#j6FJQK%_N%CL`Hh`C}>Y!@ZI zmY5K_6y4lN4Ju<@?1-B9(-95Lt7{(t3&iK7$A zGRO-FVggW$e4B%(!?O`;{iZgxX)ebE{?k%t`PX)XAS(w2<={x_ev5UbW9oz_%j+Dwu9|o(~1Klx@9QAvWG^%N!ckQV#OMrLO62 z`a;^>Qtk=vcJ)5QLRH3;muNvNY4gU0LD`L?k#tlZkJUo;vuj|f+29ln2Wl!jvJ82- zP0`SU-fk_E>!aim3o_QAwKLyBMoQPzTmf98`{186y#>4$}uWWoB-BneyAoRL{10WbSpMf({ZXS=-5} zwTdTVz;FO3UjQu`PQ%*EDSZmHJY$W5DsEsCXny4YVs6HD4fjGAbx)BI zmNc4}BGcT9vzT7+T}00!xIotPzFWhUx`)|iCq_Te?$k&a&m5c!asiSI&KjrC6u%WZ zLQ)X4-!9wN33~;AS_t34e9#v+w=aFEPO5C~l?>kKhCKMaQswmEYriSPEH>AI%QLJy z(9fyT#z;IB{E#eZvUfu9e8g3}1M5rK2*}=$nK>-ZiEGNNz&!FaM!^mE)9f@E*VJg> z(JEqD1;xouD7sZa@vRr=SeiUmXYy=}ya{M_Gaz<0j+D^ublJRR4ZSfmY71N#wmjp4 zR;<0U@noUrGH_=`qqiX3@w2k90m-4Tb(Bwe8=LdJ!L+`kY{q&!qw{P!(NV_oFUICM z2s5&Ew zS#-_x2B}n>*3dhUgZJOdLHl4%97<#bJoqI0w_Rka_lOXfsAk$*Q^7t2zxz^RSBP)G znp2$`CK>%4spi_xuU(}bha5d_Er<+V>K)^$tMymXSeo6IQI zXM}OY>kZH?PpsHk7_>YMvQ*48>>Or#7lE$h0DYb@Ym&dzrAa+x9NP?WRjD(EZy)$K z1I@H8C(_$JA&==9eJ!Lo4xwVLO zT0>h@hbO`s8M+ma(yVj5r;N8A_aV<-vYTNmY0@^Xd)*S)HnNQsQrN1w({_~bE(>z5 zPSIeiUkyT765D0?-c-seEN|vph-b`oQAdi1zi7ZHzjKx;$nye#zUl@rU{v)J3^+uJx6% zmMjYH2Mw&qpHlkC{v08@5a{65(eCI*tNO`iHNP7R2Y(+}Nc%!`p%eXNpC|~k1K@s>@IvpG&Re11x{K^6INTl0?WRtiPEUKuC zbZ%RI!L!0Trylm4m$9y|8ySBl4wg^yZd#8PZq=rXgN@z9KYy=H0YhX%jzKrt&$@Y{ zHuWAN8w5Y+?BLn^8pmxNL*#Ns>4iXPIOSQ*2YMFU>Kj4SrPw^{Va!k{JrwA9$CI8O zD)W4xtRyR|6uAwPbAzvzwOO4%r@M*I-!l4?c^`N-DuXkh)R03~73co~60N<#YxB1N5(2 zbZ5AXjCTIK1Zz9fX}4C!eQH)j|A3wqrrA9yWrW;_kb*NKcEd*>*qLFh;hnW>*?hJN?Ijbasr44#_&F7_u@aWHPrw z1?H!3)uiYQ8S90E7eH?x>Xji=f>Zya@M7ASA>+Kkd{OqbfpjcGc2A6jt&TbPT^Os% zVEf~BEbURr!3#_+_w;n5M_gx+X>f2f^6{WbIjDfu9VG{`2msV6+hEbxDyxP~zxfQU z&y?eWPu4TfT=u%DqOF~m&EPmzmcfw}E&7%8u^@B<++AtW$W!%d($874N3=QQ*%U^ibP-GB%uu}!vd}bwRkpnOo zy!#<*@oyWDk>5pQFZ0f_f(<@Wf>NbBLO~1254Tw=Sm*1=c}=D zm&KM>*95L{Qrl#AEl`$6hyin0)Q97t+A@_bXO(+`tX_L5ZVh5%s=~m$)--*Bl#PH< zZf^RU{aIVLJ2oJ#PdQ9lZ0pEGptgaZz$BDe)1N+@0ODZONI!Ff_{d2%xOQcYre+PJ z%ohWw`$W0PJW&&45YUM-lW`L*{&||lO_EW5#;>OaxFQ*?m?UF7AX^vCr%xxz!BOiW zA>}#ECE)lf%=g44V++1i2YO!d(U2%A7%ko5vKlqHip8)%J(&e+=t`Baq<=&;UuyJ_ zY}Y#agWJTCqcYhcTWz(uKpHR%kd@t~d%#vZ8fa$<$))cYNb@|cdq_6r$;}06vjSRA z(TRs-EXQA-%LiS>-UUl$4Ml~&p;U8DzE(cdsE_0F56cF)1Vn40A4B=n+jl`%qLq|! z+*LtZYREjpX!gT0x*Aw4r|i$&IgU0z47YTV@~r#m@1O}K0p!*BcM}T@;W&w(#Fa}yK-nA@^lKgDC;U@c{f) zB{1+tRA(wIeHLmzRf?9ytY7uUSV~rcXra&T7jKg}mVE$xo(i9}>7^?%rWj412{YVZ zE2+U$8A7|J%KFGQa$>3sjNm%Vw7_|rm!WL=CTJLFkCFI2AF4Y|Ht;QDVGzO1S@q#E zY@|7;@Js>?LnOuEDlv=LCmhmO>sY0sk#cx9B&a z^SH)80CO=DH$9&n4LEPo_o9KhOas3OpvYZUW$Fga&FPfYHO9SDyxU)vo-yf z%4UtIY_7ft)h`?7k2)hK?q z&@9KOW#1Xf@8;cGE`Zh^-LJ5lqa>D_ae?hU z54Cqo5h!m##G8%Z6}H#8)za-4LDYRCK-dqHt`m?sOYy8m5Ua5SScp^iFc@iD?pC+p zoQ(yEi!F|MwP1GU&>whgDCjBaO9e9^`2+Mn&XCb8rM-b2wabgFPs*pQ`*zZtCuJxP z)bf8B=+*}e6q&Agpfh-&cs2+6I{Vl$&@;|~p2k4WV4&gm4YXTN4C2U~{{yuChe33r zx1W;1zR5a+rUX5fqQ^@$sn$~<85K{-LZo+J_cRoCz-7_@X`TfS^)qm&O9u*^3yUgnavyNANCmyO z);XUf)8wz`Q17`i!1|FVjhibYneg(lWn^fbEA6R>#o|RD10{#S6s2;%$LUism2xm~ z^AZ>a6Ke$Xm>vR5Wit(5@KtxJHBW{`;m(;L$kAb-UzhKXZj zuGZ2I&NRC+-0J1y)6}%PV7UAo!mCa~+SJjxLZ<9vDygY`VTccD5X) zeY{iEfDRbXVGCp<>#~RGgJ-1d1t0ZPbX<}SGUz;<8Xl#gw98{lw53xG(lx?Ao9*f`Dp~%wg>9SKvJS!ut z+uf-1vzT=zEqNBJ;YHs+D|<3#Ghc(iy-0TS#(^hxq#&ALk!*}$;ZL5%)V{1F?Unnu zG}}PC6zEm_tk4dq`Ji2U)<^By7J15-jGMjCW~MWCB$ea4eCsK2KB(?7A10=0)_u;u zh3anuy8N8k*uOVzF8a(T^jFg%uJ$ZiL!}rt|1@ZDS2b zSm7tbv$_gyyoL9b!_N4`x6{R7>=57B0Tj<;2XeTKUB$%lNgAKh@dj<{N$ZxtidUO; zbI2{h^z{;0TG!E)C31vi5_Nk)j&bXcXtaifwHne7FTkfz(A`px^19Er*&)PE}CC6Nu94F|TFo4J;XJNbu*IOEwRt$Fk4|EEzN?ruJ^^+QhS3GJxQoC2NT}HG~cqi3@Z(|9iwyJEa`)NHNfuJQT2^JCmAuIq`huOu>QuX_f_ZahM>*}yJNNMH&`n< zhf@@2wf3u#V#x4k&)Lb>PmHdf zqSO_JiG6R6xOjSgh4i)l+?Q6bKn&MIv~Pv9vq7rTb&=twe}~(TDqR;^TN<+xu8YTL z$4YFd`gC-qVPwnoh)kl?*I>grhq#?88_ulPVBkiJRU?={mQ}_GM(_xFu9Ch?CRafd z{TNkCpk5alL944*$vF1{jy!>ZES0=hOTR#yb2Oz;=sC1U8On-0so827TTK~0H(<*m zxO%m$S9c~X(3#+T{5K00=PzqeLcO>M_dV{gMXep;6~t3s4d0700Z;v@UJ}{XVG0fJ znL?w5)oapIYv9%~$C5^8*2voRw)Qq4!vSGHeb{bmk=I%&;h+32g_73FEcdqP=_TK# ze%7nkkk8ME6&jO;s7KY$_G_-78o5q(jCmGj+>$Q1V8Y{_Eia!n?NXWov7BZ+c?AOsMx`Zyb2^f!PLF402VRhS0t}_z=Km zDbSfZuCPUCE4`@q8#2U#+YsK6$TuCXmu7qDF&K?=Zt(A-%jw9P!(K+r z^^-S13R39C8!|$*vPllB{Z&t1tkg<)*z4YpwRcE=@_tjE2v&h= zxjSF!gTbd@3n~F8RKM^j-FZ_6_5_X22EI-F`-VzE&AAnrFJ-W?9r<&P;|QY?nez-? zPfZhbAXqn7hX$Co&oF3v4rOkZ$-#(R`qZqYRhkJ45F@&6vy4ET<=30B|Kcff3k)$) z2{6*m+S!acZIOd8~LUNpHHa6-=@rb$UzYF@!#U3vuWv03Y>yOJ>llw`9{nB~sn131PX8el`WS z*J2{)0o@Cj%tfH@Vlc_c>*DpxGPU((PpyTf1V?Xu*CW?yuhVdv&p<%=a+K$|FXZii zTSn$8{%UWaXGH;yv6>?bQBh@I8n;I&Qi@4)ji?obaXH5uOUBg(lOu zUUp@@0`s)**ay|iwmWL0o>j}E#oGYN`Bb`1jsbZ{-7Z(Md2%}}L^y4+UA~Bj?N-&1 zb4@;8-3`t+47ZT?7f>cXq^<@=%qeWreT)<~PHuCkg8J_Om#Rze?|@(Q+g|j;4%r6H z*VzdwI*k%{%2xF<;`FzB0nO@xl|Ury-wy#YQ7>BksA)x%yY~>pz+7ZMbeN~LzP}eX z)BP^l&h+z6IgKquuLC7ZZc_huWOwWG?zH+HImzc1Yl&WV$A`*_Nv(FtWRFt3yKG$c z_53c`(|V^j{jv+(b5`*Uib0;0Y^@!&-OWcdaKiw&S&k2mXkZtd1|ynZm_Unn%ZM7z zBO2wPE9ta*w`>MZc44<{fDQ>xW@2UuG6D? zWgGt`=uinDoYjA+WityQ@ci$E1G4a(y*dSch%+7$^wfv4fqUWPe0SRPp={>g#F_Bh zYfH;@cj+0>x6kr4`u#&$KbD_#X3RY4A`Om^rFKUY+_W7B+~SgjT(a#)(kAW7^#{_Q z?WR9E#*o6D1+bG88z^8lFb{| zJrm}K#KDa}mIJE))5pPdj#Dns;*T*A2&x~;Ts#(#Rs&C^QY2pNFvGwg^Gb*wE4OgxR&dE^R1+KkYW6 zU5ex!I45TBgG})*YBS!yW!&7kJj^equ>+1V*AZkm^BZL{|A6H`{)Z~d|I_62sodcH zJw#ZFy6g>^>Qe;Wfh@vfoJ#Ze!v^_jCt9%|vMAHa{jxQ(a9a+@(2!BzARbcLC7dz% zP-0ln-E@sw9FTpyC-}jCVCP$c4#+s1ykC!#_si)01F}bO%zahMoK+vD@Po2`Pt+_$ z&9|3BWIv?=0pJp1>m{_T;>n;O$FX!s%E+3Q6;wX0RduC>gGv@CDmetpdkTaXh!act zLFvaf6Y#O-<;M+K9FbE8Wr4Rd#-Kg*`b<*D*01lKk2$EnaD3r21blNoER`!D`2ph^ z;v5%GvT|I90`DCc#1(T~TU!GSA-}7#u&6K~%_v@Tl;0qjh@W{MBhS(spUc`tSOgBa zbpaS=n!<)B01e%^o&^lSTQBPZjNWh2y^*3`;;K=@pK_!Nc^;CYZhNSgzz3+ExK|xy zcwZOla7d;>)XhI6n;;L`jzc)$Kx8>Ahgi=JqTz>S=g!H!9B|uW6_kmqmj2-+C*Oy! z68l1p-qd%^D7dy5y=xTQ@f&pZFl4k-iU(*d8N7A`JEr>D9mlNH;0qaH{l-C4zJvul z=L;F{hhtET1+G!2YiZpVvZZy4v)HvSAl+~1MV?>Ean=RuWe3aS^!AsSK_=b)QqDwZ zBmRWZD__Ym));3s->;=dF6iKyHJamKnEl(citJR^57zKl%rUP;>Xa8UI0fF@d&nOS z>h*;YH4hL1*WC1e-`=3Hc;5JbY%iBJBu_Nh`o0F+|Nm@|+xz3HgW~RMFCOigbeU=L z@(W6dqI%!R)=f{8{fkhjS%FX#GNGvHtjrZhqar=z?$?Owds@SSyt@6Hl6B@Hv&sz+IdPuu6dUTu_FJ|jdgLh7o|Wfa)sc4T zalZ87QG_glIB=k0Gx9hlms*df(XwMQdQdfNl=FS;jN9s7<~$V97TF#DKv0Roj*MKS zIm5_}q~0b*DA*NM(=Xz3N)zzxM`aiyIsCV>t>p#k_ALb2c9f4_agWrwP1$htk6>-C zNhg)Wh%?j8a|gdu#=H=HAmW*2vz!r8kO3e+?Q>>CM_&b%8PVGUqyWhom`f`&qJsi* zM)U=bxnx8~IX-fo4iVN2ZRgMy&WJt)eyJz5bE^3p$X6X z9-(Ws>EQQJi}1C{53*l%?^K*eQ9(rwY4H!TjVZra=<6S3Qws>_50Ee}{Z0Wt$`!0! z|A=#7xWw~E*^%2&kvPbz_Y)SW{H*IDJ^vFFBrbsnk`SY?3$iq2M%D+s#C26 zMg9z?97Xv*%Z_Y(%3{$QpV_C+f765Pj@ESIXGw1R|GG|}#6$+r?Q;R%)zKL<&)Lko zD}I!X&C!Gvp#xVI%B$D%o}sB|$Zp4FyI}a{Iz!{+b68jqC?U{VAe3!hN~@2{Kr=Sz zG~mnUgTDNYK07W)a8J2Xruv-6l=3j8CG_yG@LJ>bo?n5;>GapHKoxIFJb_Th{ov@P z=>y@DeAZ&o3E8m5c7BfuT;&P))~^-iWruf5YZprAPRM}~5PRzDuR@aq5*JkZGNcjA z5lzEzzA5;?=Zfv!^O@OrEn0q3wlQoDZtypF(20{WAs6()U(Z34He@HUA+DC4#IDV= zaK$2RIYb_QR)HS4iG|Bla=1XF%r7Xz)&(W0f}7_6?YSJ=Y7b(+@pm@9MM2LPi*IoV zUp^)MtE&QhMCjNR+Hy*E=nO+WIGPb*UEbt6?Xzkv`Rq(4_E6FR*IRHsNc!K`Uh$-KpP2Y zO@NeQ5-fshN;C=58`04c*)aF$^*aP!isfkK!>Z%MfCIRZ zvi~zIKq`u}aEv9ox~B92{+-d#!%2^fiywHj`%mAX&wv{6^=dGN6!01Nb;+7L7OocM zmcrr>bTiB?Wzr8P+k(psb4yB@Y#m(I0h5v86!*%YhN?DDe!Y{wGbjj3cT@n0!XIi{`usC=-=r zI0JY!U7Z1Gkh!-;iuhnJjEL>;b?{eV3D$<;zKU+2kz@Q*?i+9!bd0X_$XNhy7_B-B z$B7zh7Ec}0RXMcu`=|cNL3|s5j1Q>lYH1I=ujx|M<>n)?GfOb7(lN#+=V_OA!PN0B znG(;*&Yr4IXbB>17WplPQ4{fjq<$j=TyhI7-WrQsXQJ@^$RS(7mbDLy>UYDjAG~pF`_&kgTsk8)t zlC}cWj6((^3u79T>aVeq73a)h>J7zC0STOusRbq zCJ8Ca#SV1(CqHCz0|ZqkwfQ#w>#>E#8;2UMe)~^?G5wqfDF&i&Maqi%cZ2IDo41w44%q7`5 zT{Za~P}tmw&)&Zi0WcOucqcyE6bk`Fb6tqB#=dlW39)K@B1JH*y)11}jA^Ji7!@9b zX-`t=WhrAjI3eE^e_bK}U8w>2&df7k3m2^#&vwqng-`)Sk#?4Y&w)C8ogn|U!wR91 zeg)ppm$R96$-ZC}tG+{f_fjrZn<>|={rHB(yaqDmx=8)2;HS!(q-;3F{|51OYBp1{ zF79Z(9qGTx0BMwRpW-YX;8CZ z8u`2Q4&DSvGrsP?UstHLr`f;bKz-q7$oPL`LtJx}3lXL}=>wxsn+h2czvsnURBqLF z^HppNNru?yDMl-4P$*27)hL=>0d4F|37xC}2l}pLPxMvU!s50*@cK(@ioz{(_B{26 z9B;)fV5Qe&WQ|`>0fg}S@IIu=En22p+gzt6En6n2&(__iX!T#Rx5b05`~_dy^LtXS z%M6tlfE}i1VhrAX=p605fy4eF%r|5czsI2ojKqH<|CDvhFg%m}l*JE-JLsky;x-8C z`O+3G6RfS(n5-vG(w&>KKW`NWMAv9~$|3u>)iS@y%`-BLi7zh%9!#pb7?s!wbun2qgTUHiG~D zZb<=mWN)8&CyenNrH3bkrnr6I5-fZ|Xk)j-EsZ4@wdeL7S>g_^c+#zYU^HSmO5JK8 z`l{NNjM2CwQl)&yyQ$c`>F)Xnyxa3~y~Or|SsFzlCcOjHa}D*}*X4aLJS)QO%!1y{ z`K=2r`2QGt6ZjgB?|=N>C!1^{A_)>%C1#$Gki-%}V&96|_gZ3KOBb~!_N~Z6IaRe) zQK=G&RPB_aMNm{xNeIfP)>=X}|Mz*Gdv9)1{eAylFR%M#mNRG0oH=vm%$YNeBCQ@o ztmof_@f;}UE|#r(IQ94+PCsl-I=BN3j||^8piu^ovy0|l&N@IxyKB%?vxTk*%o^QN-76xwpL{tI@?!c!HH^Sqy>NG)7|m$4Q9pF zJ}s!Sn@Fey5D#7z{wD^9df8!b!C)`ap0D<)pOx(n2NDhKYg&+itnm;%Q>y`m z91xj@QPscQ_3tWn>6Pu$L+#Ro?9v15(#zYW`|97$I?S^Aw=r5?_=d=#j_$6$%HGR3 zxE6C0Ge@8Un=uGCXPXN0=Yu5-YG#`32Jx4kIvI>K%OIZVNzF=&%e6B{|C@%E%ElwN;VJ}E0^Dgwy2dR`cBEtZF3zHg`o z=JyqGX7{WQd_@_vidyqZ)cU^rzZ=_$w00YPYE;S0DVn+8=-);+Gwjkg;`_Q|nF{7k zS)u;ojMkDq$zb~Lrl+NQLRgV_l)WKH$!pHNYlR!qD0PkEHdo2I5G?vCO!;9C^zqUG=7Aeecd-Lz z;m#9CE8OlA5%42KF#|ek`8{I!J%nEtUGVhZ9VYq&)SXsz9B8t}4u-0}Hw^ZST49l) zu<3GO-gmL@$%jVu1&qpA>1{WaE?%Vx;i7g~;HPWb&|i6%{{tMe+SLvVb!?XmzSEaL z#L5a6)V1waKnm8=5yd+~7~$vu;dLmat)U7P+t>wD(?}6s=@y8>I?zM> zew~D(uukTA#b+Jz{e zz^BH*iw#n2X&H>3+k2OBP1|lK*x-qIFxBS<(?9Rxg$G|CrL%={;~d=*VphO<;KIb= zx3q1Hh!*YzKcjJV!y^2yHLy_3uFIRx(P1ej`0jo~-W+PLiuZiUKFe}|h;YcN*yugP znq?USTtSTzUz9cc+7*qlP!5};btsUt$1!ki&fXj>9Me^f^# zEB8+upwHG3+bULsvjaQJvmWl4aR&w(1@qDYwlG@L*`u8D_a*YHBf{vH1QDX_aiV7l zqOEy8HLWYQ(tvuRJb`|WS!EJMxY<2Bv>RUChFk8=adf(oh*TW(mVkFX(azJByJ*}$ zL^Qx(hrwN4g=?k>IsfY+G z)<}${5xxRyJ?2|I%5Y0-*P4lOc%8Fzb8$fNx1?2TA;u|BPSS=JVi0yGlUs?_ z)UBn6FPmShxV+tYl2)}8!@Q4`NMA-3T8R|zO(l}Y(}GrFNUtkR3Uc)Lm3~^@b(8jO zMg5*jE$cKWi=m5v99@qq2Km9zE3YIcY=G(hSeoS&5VAIhZ=ARA)1Sq&57YB0wQntg zy+@R27>7Bn#W>$qcFDPoO$oeYR3Oi{#Okt@?6Nrd&l9x&Eitd`vzo7K2V~G zMOii5LUM9g%ywe6^7MGts<*{CGfwu$bPy}}4dagDBku>+wlNp4n6yRZX@48xUwwG; z`0{nFIKW%82#0i2DdVAGdmKKXYaKzamhr`V38Hioqf_&-(avShEfcO!S|Qa=-d%`v zTQ94ihpYqO#KDwiyrFEgV1&o6mu+>pX!e4ydY3EF)J>>FY-+m*3xc)YC_ zJg#_GKPB%jVz&1eC6dQxZR#Sfo0XTx=$$^okJfY(A1h~%QFM1P&F?Cko>}d%bEo8*OAuaDA2+K~5o`U1kHti|i^X_4-XIU!MtP?#&AG71RqtLMTI+sgc z)=oImyS+s{W!urLExpASGv8J2BUYO$Wxehrwwle`D0F}*M~C`hzdSdqO@DFT%#w6~ zSfTuRBy0Zw@!DMGp+(N%Ai+g@w)r`&ZdAb+aqM#ki4Tnf6bK~Z|CF*qFLostKMkgQ2VMGHlVI&7m#DY`ja%z?wp$Pr>h#2l%GB9yK@ z!9Amk6a3mC`e%gbU-n_O;^_wu(b$n9F676m4BI`$N)Cj5TF0`_sLg@3+=M zb|Wy2hK>@Wy%$@vEJW`Aruy$$3)$62prz4Rm)g_Xu^6%tdNdkDg*))Vcf}Ot@v^K#|f5m5ufLM(X*`?T+^>KpZO=+W+7(VL(`nv`tzms^SQxs>ufVZ2>6u%dFufE_P!W4 z>^$u1Hkd4~+!0Uw`h?@cuStx2vr^BaC}) zRPjOGc7V2gAo>Rf0;U3(#a!L_>d+?&9*vz$i^hpc-aAWFo=Lqw6e&RuSHH3DL(|8O zT0=Z${t;y8+!9s0>s8zQ@P?}BO1kN-GI}I_d(zGPu{h~^mjGGK0Qu>gK|VC~s%<=c zV;6b2dkK&=N`N$Hjr>R)F*7qwfMg$Sf%<-$>0$LK%pj@fPdog!mnx*tsUX{&67t%yro#Ky#;w*{OXYBEWH(p=nq(t=x!prU%l&r4Uu%e5^70TPjfQm`l%mu5&5sfJ@_$ z2Sa`u-%(goMQiAemDT~SjjZaOq=) zNC~NCO|}yjfA2AT(Loa8DVSW#){JZb__t1oyVyyQm zyFAPBEL`&hK#RNK7#=rAmuIr45yf&jKvFi^USi@M=o{0|CC4Ku9;V7P1>Z$ktE9 z3P0aBWZlf7yidd|Wm$O|wp6tB`z_qA`xeICltrhPidnwjz9A3m&@wS8{tZDSw;ZtY zp&^}TS!-LyxC>PvtOLVJB-f?61SLI?%%6()l)_!~;iqDua%C4eF9({tchSP-VuHhG zn3p^h4ypJUcgnXmEu0e@RR$&x`xPFm;b-FQ$a)C5hL@Y|*Xa*RlxzwxXa4aS=-stM zMisiSLiF)TERpPv@>zvGwQ0)dqM5@z>^v~4t;l<&2v^SRq*^O6_M3L` z+~_;w6@{CSqxm@Fx`me;5I=K+h*Kznb^(NWVAiz_BF0>Eqfy?h%|&^A zn~_#ZD_Mu#hS)mCb=+xvh6rcW>ZGQX4VDXuv@0FlJzB& zEEtJ&6A)Z*SE5qsHK>$hsr0ld{k}!0u06IHtNk6riA`=5KEX3lZVk$fZfXT=+~u?Y zrUSd(D&X?Z2U|r~$EJ*N_Er&C?t%$-U!hNiRWR*ng1&IhvP|*0vJW>xGDThG*^l&F zrf8(R4x^xLB3ilpBemToVq6azT=&zDG;5n^Pgj|!W~@?!zRW$*k&5@ zw=-M|cZz%NQD|wM2Vas&pwwN$ue@UeL)$?MR(_h7RX}%f@c_;PrFVB_@^1uB_*UP>t`z7Eh47 ztp4}oqqv!sbK56OZ$fz;LP5K+Nw-{~zjBnC?FQfGhtQPW7`0zQ=2DrJdY3ZkZ%0MV*>XN598f_yN`51LUw}+ar=oaedfS1#R0S zx>gv36AJq!&u@!Czh9SlU$5e-djgwG8qWXriU9AYn~({kU5I{#p*lj5Pu?p+_)0=Q z78ksjVA>-T%3cv%y1oT6t6I0dq2Kn3s8TtxIw3lf=RT3_nrx8piix`H6U{1DKm|UG z^0%U7(bKkmgLLTTColxdQkC-b>poE#d+68uz_hT<9uUDE^DSkrp$ui-a!+=+>hg@9 z+;XpP9ztjLi*~rW#Rbi8QNsiHYXE5nU>J|3O$V?GZd9T8x?h&$K`|S=&V`h_o9X01 zG1^MFAE?q{(bZ4E3a%55^(2d)w{0_RIV1*KOD@n$djDj#D_Rs6oVy%`R@#fqN3es2 zG&mxLSgQo+ReZZ!tJncAMeTnOxYuP2U;ZizIxM=B4Y!uG06+gVMIIH6yxqVqi5Bhk z5KP8hX#7zTrF{D}Z8$1EbALD=+eG$cNpqsn-8_P6OJ@%^O1t9Z=sM+VgWNwG4>~MA z27}*r6n8-J6j&K=vO`Q9ogVEGNYOv3?sUzqf;&s_AH|-sWB*?T_l0}9N4(B3!0T^> zQKL;9v31777rJAo$?`9q)*cu2>Zd3L+yxFueGpw3|Lt=M#qy5mlbL-H!h_vM`Mcj> z#o{h%7_FG$E@n{06QZ#b@O`+F`kxTB6$EfuaRSQ`l73xDtGQ&QI)f|ucRI)k%ECbDduoRub;#)N8}8p$v=ULw|3B~Q?PR#{7JZS_D?^FSk7)i z=AT7*P6_x~L~}|_Tgu>{jWVIOl&qgcT`uEpOYu4-s)yimvXk~48@3xMaDyKVH@x9+ zX@{Z_1^4~ofZgYmsN+L=!OY* zhBr*GLX0~t+9)}2Q#dVVI_tG&lIIzS422TTh*%?O1dTZZg!Q(zo)PiJ*X=W+3wNRp zHOvNOc798vvPD>MukFx4@jnNligO*DGrH;D>{#HKQ6Jy>A@<#`=wvn&UQ+{lkS(S$ z>F=$e56_B@{CQyoojxmK82E8|^o!^lf=%m9NIn+3H$C_gx0Cku3eX9MsO;)_n;tp1 zm!qZUL?^Dafc`uu;(0K_&xlo=-7 zUqmOyBBltT3PlKcFhcK^LH>i!fB+i52_$aQ+W)!vD0?>2tP5fTD;yWaBu3!ti((K% zpH9A)0Nq3lFNr|T=yOTLRzyY$L$MAwhFZl?x8jPIL^S8O|Bw79mii6;BR}a^QJ3q> z|HxnRtI@vSf8<|BeMa0&l`b2MUHdZh4=~u^%f?j7Urq}z!!?AFy)0VdDT$|-MH*8s zV>wOu4Z3udZB+M+s9{iCqiesxV2jcLR{#jVt*?j<+(chmdj(^0Et5`P5n&-Su#QjX zwH(aD@1UjW-|TGRm@yFFw5B_Pa^p_>RWVU{_>{i5Di$k0J*8UL#8_p^Q_8p|KEq4% zO@9}0Za+YCpMfU6`jn>qE}EIYhwHj1&p0mnlxKP*9sJa*l(}n`?{$%EW@KWidk#1p zU$}LbBa+N@^eUX-Nq^>uWd8b_8r~4q`Rf5q%?D$p<%;eM^(@ivxuS09tv?aB3{U6w zLA=JimxY~}ajm%Qq33jtav!_;(7O*j9T8TueV*vcz*f-CJkinIgj#)P^< zo_B!o=lPcT3cD_$u?6;U9zW(zgJ5DDAr?Vw9X1uu&DpHVxys5YLzU{vxS;hA8O$fcdg^G{5Hb8AU`BD!*8w?Cm-f1-J4Cl7D{ zk?_=5SWbV!9jfM%Jp*M9eL_L^px@1;HuptcBW?XBwD3O8C&vQRGto5!#b#sc`Cqhp zo7O%w@EdIpxxWEfiF{c@dT9`Z!MK5ln%KxK{WLq0v_H8JZHvCGoaSPkq zqBfLo*U*MXq9@bj$0g+a7&N&~Yo9Sq9vd{-vc!%iYnSLWQFcD0(~k|}VkLTlv4N+_ z6Ju;3w4Y#XQVlS>pBP};+Jk9mfI$d`Hh&o-96<~I!Vo=Ptq&0onhQBS1(;w9HkJ{( zzt|3&+{FeqPan|fry`L%ada`2eugQ4gR5tv8}stU#s57%2OrQE4-H;kWDj_n1@N*5 z#Rq5*U=OPI4U&2O%^tH6|B?t~@t(OMD zv1+|CX4P=}D(~o3A}RZoXvlN1u?A@!ll=OwF&AMo{9C+j-b2&=7HWkxeBe0*p-cH# z7dsSv4aXKMk&gZ?y1Ak{YYBzv6!}`jnkP{A*H{botfX15#Q?0v_g+KfBD$$R#rz{8 zAlEzpBicD8Hu;+<=K`2%?>{2MJdm#a1Hp-1S0N;JGL0z|!`xu7VAyzYl=2J39PVJ% zrDJ3=uVKNHD^^;XEuA>A?9$6J5Q$5l%LYuHmy4*bS*qZVfo2)y{T;L@-h)`RR(`oq ztwj6H(km5KkR5@zjAf^7*IRGgth^EnBi!|-1))$?`Md9Rr-FmniJDMnV~IL3_H}O9 z)wyB44OJAS_G6%P1&TB4%k-8aLsKoioYo-i+=q*Rs}ByDaTs7q6WS~^G#%+|3S%U# zSJ(LVD(}~v(J+6r>5NTgY%YV7+Cx*CmuA>Jiy9t`hS`0c8%}q}QxYlF@11Zkb)sI1 z^tK`4k#??w1&JK}I$K?>KO=$k|3V_~%QqsCZ8F9D3yH@6zmPzWqb*2;u$Lk34>tHe zD6#(yNF>9&XM!_DNlFC20SQ+GWhM_tS(#r8ag?>iu6yVeG{YnQxG{)0SM0Br5AxoE zErTx=>{qam8aT;z-uTSd9iSZGJ_YS(A+2(f(YV}o z%1Op^!5UHU zY$yF;CybwkYcs7=hn+r|E(l)dDPxqcmeV;;nE;3FI23{$&)JN9gG_aD7 zjOTG@!f#tcrOTnw(v(on7{d@+TMmPIlQchBjuGB~Vt7@$oQ!h42(_5m>1TTM$gdJL z@RhnIcxN6>^9A2;E>@=@o$>`B+=TI!eYt~~^QgZcioIW~m@9qbhhkVB{0yX_Q2QeR zcLacdl|Rp}riK2fixXpiqgXP9mPawiV#SuPW;Rw`pFxGSL-d_;GKu?M%BTa&ksauM zmOA^3*RggkdoJZwK+8AjY(Nn{ay6aiF5_IkqJht+bf_Zm*<7sHqgAwpyWEEA2N=b$ zkqSUDJSb@gZTBjpcX;wX&?pAoJWwZseX*&ljNbhYz1q^df-03LsFJMZ_N8SP^=J;g zQ%N>7ZZ5MtX|;;lc9G$9s*-e9HY}yzD#;$U(!1wSgCJSIsI-rz^rj%`?m3#_Lgm3IbyB=*W;@8RMQl6ikChs^foNNnaqJgWCm5 zT~Wdv*brG&S%i0KLSz^-7mJa_^e9YLS@w~$qw?Sr+7%*GnOk1Yrn;fBwUqy`_Jia zxU9v#MwR6x&Iiv|mfft?-`A@v*-I!kLh2ia{8_XxLPl``CTSBo6e0C(%a60jIntQE z-_D{gk(f!kiooTOm_UP|fAh$FN>ej%cmD54S-)=WrUl3R5sxS&P)jvA z-|LHK#@Tr8j!Dn!1#hWY0Dkr7Q_A%>LXTR?(|c89Y{kT;IALak3exJ)bs>Y3s%v-3;$dQ$MmMdYl?ca&|P(;!v0GOwa-s%*}OS*mPoUQhL-UB5m`q{XcM~ywAhwysFdkhAgD+DfoPo|lSvEHhq1-50g(GZMm2X!7 zVa7bL9yJwdX*n8=tt#7i>5y6Z#dVyF+!=Jbs`RV45+*ag4bitWw_IJzMc74-D!1N; z{;4X%l<#~ftePAdoH+=J>vfZh{?r5pH?!Xr<^v}HbIHIV+m>pw5(;6&ixtAiTMO+! zPIpl#JabTRv*LvUn%N3%J&yBVh3;3A6#y;9C}>tpo%AN7iVChdPW_{0W4=kciZ(^d z;L@+)R%%^U3zyTyXc>ep`_pJyMR|RRf@0*z(wY6kb;*&LQl(je8!eBK4Y2b58iU%I z{gB1>$vo^lYLioSnat0R%mz1Z95U#|=hVJBq#m~FIP!(sR++TwGO|iG4;Igs8>uk* zK@HgQK92lw^u_5qsj+5Wn@+!1mlG26etb#?6;rLe+8{A*+}=oOo&b$Iea1mmyEzz^ z%*GB0d=30YA_C?j|0eRCkiR}n(2^RmmC`VhuGf$iyN8Bqx691=?B+yM!R>K4`_YYJ z4jF-Cp3}>TxP9q>b0DnKRy>mN9E9z-4B^slT__+7H*mBJH~5*aMSpjVI>gGF{Gzl2 z&5xCpyYZLi3&GGIn}~e4z$MG^4j(vcoyPwi;aWY6bc9CAj$yWZg`(a{1t-I0AxQ=5*tY^IJ zVeCJHGxDd={&*RbIv4kCIwgq} ziaP69$1?6YC>h?=yQb{mt}|aQE^+-fjlQobV_0_b`hpAjHDy%A+)oWz!N+;O>)*!B zy(^#MfmIo+tU5-+YGD~d1ixCcQO!)#5ZuItmzTXG-xk7SHKTEQ3-+1jh&Pt6Cns3Z zysel%(VubU@V>QWi@1;C!Q!dK>O&!?eU|#zL~ggQf5cYblj}EoGX{eIVflYxu-Xbi z`C}oqts}=Gip-%p(hrxnO)hk$j%=gcKT2wX3|9`-r*;XlqSChp4Ns8m{ZAZyO37wZ zt^5_q1qV!~M}y$*b}TuR&L_yG0o#$e2AMYrlNb{(|3;$(=)md6k`pMduB_`D5~_V! zX4YpMO3^xTHeaD>b!9ViSvpZy1}J;Z)2+IYCZj1LQ6`$3P`^Z3%a} z3mgi_0#RFwpmEqSr<+Xv8YEpg`@dg~G)T}07GDbqFmoL=6G-rSI_+v8%bHu!i3YMB zgIS9t4qPjQu;(9BLtCv z?RrB!Il~_reVvMD5HffwBuoF)VHUF5ah6WjcTJ{G`eO*dRr=rHs_alxgl3(kLy+I| zKk7my`=n#Zx(6%U>UKx|TSnbfjD?M*^@chivq{Oycx2Yva4Y23|Br?nBd=!3y2(X# z6OqpxUDTOy^4Cua zXz+;wO7bv0O5r!RAU}Dx%sP%v(PU5*1Sk!-hKb0yxuGu!DEl*ZIKj}{c>Bx;)17E- zBU#V&JKPb0kIPRfbgPjJFK2Do&N8~5Dm9h?$=gRfr?nWt&@_0-SZQ)}mkH&nak z4%K`GBEaa!^o{i2{wdU`sf_hsqeqQGY(hM3HsbYDIt>17bg(qdZz?Mw-tPLQGO8}` zLs?garl*@Nr{mUGA`UA!Y8_yvr$F0ePd{G0xaZb(fA=J}X0oE+2}^x0+xI-|s2uUv zflA+%fmFH&OdbQ9NiSvNYx=MmHda_Co5`wmu*j~#BCFTg)2yHXJ1TCkFT29`4b_Zv z=YP2z^dzU|vJ-Fi#!&C(GQ@jteFU>i-TnYL=yj^l!shZi7pO{OTF7?F{}SkM3mL^J zI8bgO!yUPA`pKqpb{<8ylntu&zVn>IV1jG}lML%(4RMP&37eXvza2L*RV==c@ev`2 zL{7_FO2J#(OOxqXOBu|2M2LWz{0bvK9)f2yTgvX?iQ3**Pih(r<6ccU(`;MO)bS|Ic{VwR;;GXLh9pZDgX7F_%uZ!9u@)>bI3!J$OM% z!FGXv=|x-F+_0F9qo(a-2jjaRt!yXNBJ0^fjjd;X2ze;|9n)tddy&K2GP((NFFg>` zr7+cPQ!-XG6PC@Kj$oaxxO5DMyMEZ^u7PT5!Y=s>cu_R^(oai)(6~8Wu{nwP(+6+M z<{k++reSW6`Scl{1=t&2Ub#7k^4^vml&y29R(m>CV_OfZdo^4^M`+V&lPhl zMD{|wVV%gbgJJpnY9dYRAZuGK0FHF1gVfI=aa!5Y_!>szJIZ>@E>M;R4;iO-&} zDwi}>f-!8SN~;MsGo8wIlCiF#Se@Cv_W`x(B%}OV;nc<|pRB=-3ue>8PI3t|QsD%O z>@4;3yW10JR%dB@*{CIb(^>kvz)+BWEX|vK>MSGN>*YVEFEI5RrFqe-&a#!YGl;<4 zMbAy?cy2y{XUoeDrHB5)=Fav*EM8moowq$g;tHEh& zd1@}ATU{|>%aeCEna&l1X?-`t0)%tD?%1P)^VzI8l&W=?b+{+@$J4OxvI-9kgJ`>m zwv3mRX@7Sp$oHsUFX?YyPM$sFV4N&|&_kwr_L)^QR5^w>VTGRZeQpibo}NZ)ID79Y zt6InV>xB%ouK8^pp7PI3n$SxU*MN1lx9mx2eWep4bN3^f&|6k>OSisU(t@`2mWd93 z!fUI~Z7)A^dPm|qg~j5wn%2J~yV@$x{)pPH2Y(0lkv{I})(!Bj1$x_#^8vyjYXU9k zBR}ERlPIFEVfBloxqW4IrViW1aM__R4gw@sVSftc(hTzJCs#0vSH{tm>^SRWlrltCsJfzHqb{6kdd4MOZEU6 z&tEu`9blYF@PN$zn5KB6S8uP7&R)j-C@ZJnl>xM*{63vt4lvmA=7+R+puv_ue@Kr9 z$|y$p;D;18NJc_sZaGK>TF)@71~UJT`GRveE^E4YyBSU;dq1{x98Rw%1{u8=O#=rT zv;yvfWpy4~?)8rOG%p0zCvOV(b~Busy4$KF*3u9;%@Mb59q7ssxfB6Kx{t!?MEX#< zm;LvL$)4_|5p)ET1Crc}z8!{x8NGDUaM_GKbOwEZsf?2bc4W%O`aTO|&(Ky6mujSi znGZrj^GdV4%Xr+%w7e4 ztnA4!iH?qyRrzZ^JsoREU@U#_8DDsM<2{36I?(0!iVi-o7T6e?V&9hm3?QD`zi*sh zh0@CRjguQMs`h~lSoVRGjNi2<@ZE|SHh)g$333gCgLIoTnJz9cs5OBSQe~GUyx#Ng8VEk;WY(F&9knMxez_R_$%m0YHN!yc*(kj3XR!G7QEx`902lO%Mzw)~irek9eMS2TL%4aD|Mw<3o7e)9~(#!~nB z24cK>w;#KFhlV!h$MN6%A~NlsrXyD29l(1N^TT)WV}qZ(DF0*mj&XGTYy`Dh06w?9 zuhxmCE`XL&Fzq?TM7jIH!(hV{xxgsAWdsddC_5*m^9-R8B`}+wY-9Ay6aV5Y+rjtK zsRjW*Lkl{i;|};DxysPChc0|#RN;faG32>aCQ3j1_8_Ek!cF^FNc}Lbh@Eo6llK|yG=8xm zq<$Pm&dUsT+A@rKEGc3q4+E2JX;w`7(9>lGCWCNa(!iu0<&&YyGA3J6@m!m%>(CK( z&OCMV<)8(h8tNoe?B#~cxj&SKEiY;Y?hwntACFQIi7Uk)5$~7Fbe5hQhSI#xKnZ*< zqZ6OWAyzH?))d2IaZ4;Q&wx2DeTTqq`LA)O}#Jf%T-$U)!$x3v(w=7Q!y}X^xeJON}^zrn9 zPRIrqb~^jgI34f4#@Hx0Oj=a0BHIBTQG?=Pud8%Sn)2HhDbaAbm z#-4Rw;P}vyrhZ|lAxr7h7ls4J4DwzF7dXI)Stl!6)!v**to8=dD5N>g0yI6!UF`dy zI7hjogX?4`vp@NMDSzSNg?IFqQun}pI*4~E`iVAg#DLFwkh5SC?O!jWl@s}Ne?6?{ z@R8qOFcn1f2BT)GUek~2ZIr&&oz?FX4Z$#d5*pSwjks#HQBG$^tFHj}&+9bmD>;r) zC{2HSWsv6SKx(^5rZ5cV=w=hyPa%*lZj#a7w{gyDozcu}M7|mFW3CT?p^{^WC-DRg-=s)VD8PPQ}9Rt&Pe z^^Kfvxcr_UKo`G(W|2JufW99a}Tsyt8#&*fZN@NmBeTlOTiX7)-ij1T6Id? zDr37qPq!ZO)*1koNkNp}b;W~hKSpgfq=i^d0T19B8_K+Vj14)q9Jwj@8z)_?$4BDG z?wF}89oZ`D>M=Xc*;4WCbh|w@!ZMj2NH- z9XKGAGJ9*we#Y$ld56T2jr#Cx{7%M3!#RXU&)R{%9IY58YCX-2 zp|c%^ctdlyj0{3Vjkl0DYx0tF8-`@)95>ZQz65G_z#!i*{j5Yv;I=AInd8zU>CS#z zYO$90+gh%#)dFocEcyK0to=pMXX;VCJSgdVS&J9ZjD9rXd#T1$8E^QM=3?6BOh>d4 zJ2?NQaeX@fy^M4-)z=J~Cz8V+X0Zwsvq$z&((2f-?_tBfP7(ICgKXH>DTaL$v}!P~ zTd|R~q*3r*S;5~8m227+jDj=pa5UX+FHpeE!-;$09nuJeDxr|U14&w%g+W7c#%W2T zJ$q#=GpL6RM?8hOSH^P;MC|JOKBuGZc*;F3iIVooCPwNlyHtHNHt&?rCOp+U#nDEZP$(!XOJ%&c6a27WW++rLK9r)4U-k~;n zH8941%>h{^&Qhw_*mtyp{I_CAxLhY)!hwE1bmM?AT8#kFf&q_K1*&&YR^nl-VV8jc zi=dAWN>2qfR~%$JOUvtY`eq|TPrn-wek#d*nsY$t;F}>5bfN?(wiR_f;NY2D~kv9Im*kOi}o?f z6dyMiT5%NP_Hxg2x=;j+emu%D$(x?w*Uwa1%LHkd;A`DYog!E;U~a`7lhI6*t?%fo zu%0&hn8EC;?b5a$gUW<*AKRt9Iwl)&+DCS2t$&nVg3uNZa{k6y=bCQKC^5*jZG+qf z^^75^Z8ymM&k+5p!mhIKaR zU<|IO_JM^pSzWNC(SsARg4ZonK2%hY{7*{J1oO$!=oE^xmarZ#F|%pSswt$Q*4LQj_&S&nh{P+xRBtpv4B6`OGX@h9VALrXmWC+Cy`2eH2*&Q5;D zK5iZD{8@$t>L;%4f5ZubL&JibE)DgUTZREJtJzO}hV5Ga3O^-l_}sqwl=wXOCLb~& zVms?=gHOTWo=xe` zH#mZ{=Da%1Gu(k{pOHh{^b(BjJGAMHtRke?zF%kXf8Z>3kw}KwP}v`tTBN0 z{wr|2$~KiL1z*HT#e50fsNZE7K$}IKawINGkLZr5+#i)2ff@5G&M$gp$I4o$v(?$f z2wV3sgg<+us?yZpi@-Fh)8zmIX5=kZ8#yDn=K9S`3aNzJay(4vH2N7C5qQp)VX z@ZD*yn08S#&Xui|odal9u1vz+;NNp`ui^%k z&XdhNXR|Q_ULv`T(-MB6M`>;`l%6N+@e9s*IHzw%HE+mvj_!{!QU~vpFX!Da+v3$? zF(AT3bVCmJZd4)}z9=_kABRXJKWI|kSNSW2zPJgG6DRV`ha>6Vu*By>2Y7JC&PT># z^WC396Y}LUGveUhk`wuc-7VOlU^%-j12~S}ZP_gqek9;11RD#~;D5SfBEI|0Z(Q(0 z4USk5qRqsU)tojcpgGQ!lM6lt75d@tP?U#qxHD%fte@Y)sY`#L7TlELq+R^wDNWTc z2$aUnS#VS1;@orz=5}Vwo2k4Vydx{{eOxvP@pVu)l6PcBW!DIratFqXsxVfN3de7L2;=t6r}P2--l^2n{=(n()9Bm?QtrwI5j#Mj8|w_Lt;Fw% zlX0_CazS_evW0It4ZJJgQbZgDFRJM4c=$fp=I!1d$*N`qjJzkmv^tAF=|r>sCxg7{TRUfQ;MbaV{tq60mJztviC&^q zp9%J*9L!qu1H>y2FFuU3KrSA}{(PNeIPSTy8&Y7DmNyueSTHVm@8OpXb)!uMjUd|d za2+5I2A@WV-!tw{85aMMqn0<@RKRy+au(qieu=s8zH7+r^{}#*OGpP-+&EwGnPzP~z-auJp>R9~GNBH> zD2&7~7vr%>OV4Qa16d6LJx@K5UD$x-PE{Vter7+K`%u<w0)l|@r={o^X_3qaOW<60V(T)sBXr-|o8GywoCPQ2i z8IGZ4et%0R16uwU8Mx&*qvhsI2K*h08R?_Pn=3(v^N*z3!_wW>B^p}C4gDVtMA|j* zCiq<+%bF}RALIIcd@!APEd7)+wdnR^*%?<|>py|{5VHnnXisE7{E9!V&yN^kXia6o z3~xnhYr*)2o@1B(9fB>pOxaHS;4k0ce1aBwSy~Xa$p0_dS$Vyc8a#nVAex9YnrQc? zCccY*a}#&$nox54(EYz;4~JXJo>HIK+SMGwzJJQGD@*OdhL(?PD1AZQAo{(zm+G(| zWw!E@WG{E?Wn33p%3Rg`|GGbuF+Lj*xrTQt)~8uMM3GkyL)+3H&!m_4yb`%R$o07- zc*v}MF6&jc4A^-rXIB1X-eexN&Qt`7eId*HVruB~62oZa#!Z7M`h|>YVPVG|0HU)Y zvtytCn;pMGd3$y=(ONXbZ%FEMkQ=fvA1*4tkQFOtheD8;@y@P-cXW+mG~S#pMdkwN zwHM!^iUo3+_tlfd39^~`y_B`-MS<+*y`x0l49-jSPA`$%mma;8ldSSSbje*SKN$|% zDJ6;{*v2cF;?t}|vLANFJ)IHBwB_HjkNZMww-xNG`1awqf6G>$x|DZ-3%ohw+}q^# zS_a8zXxe-uCyXO_!%C;v=@GmRoy2aES!AyfH*)A}8K=A+OsigFp{SWVC-98drF7!2mo$KcE~QA1<#8 zL)|%;Prm*bNYRC|g{Pa=>e^F+yvE{Mj;0q%;jWh%h%!e8(yl@&-EB@M-w&j_g)-1H zP>ZxyI#_zCj~X3@;bo{_3^d%)X5!iV2#At245VD7N6axO~`H|K^9L z95Rye4GkAdfrHkNFM}ofX%m}0r)NWrD~?R0pL#7lrZ%pxlUK>eZU>V3fSEw%sr8w> z2*Mc+n2R*S)BjS)C@jp!^NgO)2FtpTpcv_i&gG1~k+Qz~Rf5o;qEB z4GUx!P(`g>z6uiTH&cw#AZ#%?d~Ib)Q&cAQL{GaevW%>SF)kpbjZ-inW}{ z6@O3x0T&!pA2W^)9n>8xig1?Zs5ap*YzrM#YzwpYIjX(PZ1F$TmV%tsK1L7-15-9> ztZz#Toz+?hO>)#(ZSA%fS~3%4`v9uwqK3I`)BkqM*f@Zixu|^@G`8O^>fnZxSf9qN zg9&3sd>0#}G(YVVYF|qAH!E2~OR4K{N|oj5uEv;s z$KaGK$ALk(WQ@W${|=z`9$b`$dZW>&x0VLftOB z48_u6(stgza8uTORvtLY5vzG=G|As#XqMMtU31jyIu_$hZgO<@qSz@19r|1}A$H4; zrB&&8^(%1J!+LJzTzjAh?!xbWNM{d5RibDwwQR%V$j$R&ZOxQ{_`(@Sy`gm9jMZ*I zyVJEfXn>)A1!ZO zfJCO3>J-=wFReiPH0GBDR|^tD=nw!WqWN2Bo|`^|-iH1atJVDvz*oB&6tf1Up)zIE z5JdT`;awa-{XTV>AT8)W;2fm2KB_;>@m53HM}rg`Ryh}n7CX2yd8AIB$=h!vVt*8u zT!2w{xc-HK=WUSb4oKG$TQvEovUayrj)2-1epAHHh1GWjx< z_EX#Oy?YiF6KSBIn(3HUPeWWAe>IT(J1RdbjQ^t#HSkw!D{0X*&RccFRv)QXf@UaikcO9US0e2I<6jc`)|3n;{C zsGtTqLfn+6&rAAy(xWD0hrIFQx(*Der2j_dEnUcxCQ0}v7j6E-glwk zimD%1f;JQ%hGjB@8dg-pvEv+AQElDo26nqC@4Fx>kdo09>h1cgk=iZXp}mbI>5gUU zv5e;T>2!!Mg0<^;&*)YyL*iR0eK(0-R#a=VeUar@GfD_hgA?xRqiTtne8jA+x`9{r zz)x1rC^pKC%^F&G7`mpO26wsu;0RC10JYk0!X$Y$NPG#!M7 zvs;iF?PCo*QInSxmentMQ*# zA!>UkuY>#oa*ar}oPuI!ki=eDp+I3W4GdNL_}_qH$Q{kw1HELrzR89eK8db`s@D*Z zWOo>77(~~?)PM%dEJbrsGms11PCBIkgSw&Wt! z3RlB}u$=i~2)LhYVQB(Ry>Z)A@brPH;5rnO;C)dQyhHT;GOL8X8F|wcT*z39s{Z{f z&6@)8G))e!fV2J6REe%26WuKgSNoQJXi>&sr}aeS)RC3dIOVU7^hITLH1}U8Q>O@3 zV4pTQLhXlY*CW(6%C`L!9jW?rk>-&g5gv|<1c`#_S|ms`6Pm70qD3Ilks=axtfG!V zwDF@=)N7@aw8qU$pYWce5tLWTtfH2~#62q1T2+eSG^n0cinzcZt`zPpxa#*Qf9XJB zQXN(G<8Q&IWbmm26xmbE9(D7704l4~_9`CaU6k5bxz>|zMX9wEJkJ|cRei@? zlO|V%Ogq{>>-Vavo7wdXct0^4AEeOJiGk!9tv+Gva*UefG7*-FfgsxTU#c{sxiM;h zav*~?#HjDeByCU=(Bn#SL2`L;3#Rj}ZH9u$81R3t+aGn4s)OJ&5S0Q1UrQINt9=4o zfT&LJ)gU-J&JJ79ura7f)UJlQ%Gyn$r!|VY8Qh(_=}#kLRd?T$&_F`qV8r|o%E~$T z!HE{cs)1JVGK99ps_(K|nMx6HkfQ6aQQJ5*&?^XnjKvLyDs#*jMdRbts(#o2K4%Z3@8_Qa``DvpZ9+ldx~Q9s_|6dHz#@4C_BI5i?Xla<3zY%#5cAbV@x#1U8i zC8OYmZd5m3ty(1rCbDEbvcrf~PbmOLe_X@*kVW1rqqIf~;?+>F?$&sA1=j@n%*>_%M@)QQ!Zq~PQ(2Q4Jk-!MCip;bOdH7Id>NtzF;xUIV@ zpdh)YZodIA{4R>#pPb^VmfjTl8Tz-2_WQ3`HW3~|LAVH;ehjp}1T3q5tdVD9wYs0h z67y=GF)+!zT$((nV`JvJtPdKik!Hut+b}P#ZlZ2BzS=caTPnL+XMNUGonwxO)%w8H z!&K*UDt*ZhsjrzW`wGBIH-!XK^XBSI#PmPa9J)?GYeLm%if^HgXGLQUIPo|*a~kb# zp++EX$MqIqzZ&G#QuV8f{A0L4osVtRO_*H=cQmZ?jZvO2Q77x68leb49Whb+mTGJa zroW>W35B(o+NaNQ=L}P);*%t^6>V>+c4WWMuYg94EYDVIDRU(g^fc_j^Sc@^Ib+V) zObmBAP;6_p9n0HNP~gsWpn0v;20jac*mC@b@Wd8G$ry`o{kiU7dfHk|Nu9PFc`%OV zvXu(DNivQacxZPZUDubAFtp$lCoFX9H`mn$fqkv4dII|ixzbN-h4L2NI5V_-h_?J9 z0!BgSXM-!8WU*evYA;S;O~EwacZnHoOYkVSn)!_ljp8H9eM|LsX^eqM!N3&0rM6d& zx1zPd?)Vh<7I7kB#Tj~I z=K3G}v}P6xf=#nSM}%o@f%B3wi^?evThR8m)f=hUY`R13%5hNi4Q34B@B~_iJ{H?x zhMTpUzhIKt(FK$8;rdLe-9o$eba{z#xu8i-yCS-5f&u0>Xy9Uul73lbFz6D@k$zb3 zlURrOJKRB+s|EV9hT*#2LG@2HaC7`G++cFwT>>|~|Gnb1L6-ho$LtK_)*85VEW&LH zaLdEVL&-6_(a}KdA3wI-;g2`qwvAVdj%wBNQ2mZ?eEKhY6rO4CsNObLE&vGYT7}~o zeb4_@bA9&UxF&h`Wt@LePFd`V%agf_THbk1ymsomWhc0Z3&P-F>;&P+)2~bMeRD2G zJ9Gq`tWcwv5U}k15Hq2R+C*3^GQM9zqaAK4*eIV<;b_p}J$wewTDv*iSg^0Rqb^<5n9ATwgx-kfh*>|w638ct<~7(_=&|0M zwY(c18re;48W5?yI;QIunOu++5T5MJ zF_Y<3H#IyAm_rWedQfI4EaXF~TPSUbK9Fs07(Kvb zs%=959=hEn3u5 zt>799vns2g|1-QkPV`g*D<;>|Zv20oy?1=n#q&RYcd4WRsicr{2_f*>g^+~MAqA;Y zMJXaB1Sx_PQ4tUlx>EB3WfYW-NE8Xp6I7~#f^ffR~@N|6>2`90@VlFNzjkH7C9 zugB|dU%Rujv%9l1v$L~7V4l!#OR*BLw4}`lODx^*4+es>g-U{X!?pl0)dNCzRQ3K$|r60C;Q`?$wHG1JS|Xvf}{8OV(>O)zVu4k1d(fyBG!c zQJtH$JWuN|-cIwvF3-pTO4E=r=uehd?{Be`$ALsy*d8dQ>>St*htRPBN@Ug#Mvl@g zSo$a8(6go(wN&3m2&du?wT{l`!BYxkP31|?lcs*lgW*F`hA1(n0tMn#Do{17UZ=mAg5C0=gfpW8{A04J81C_YQ4F(RT230%-N*o$)$%v*C1C>l*&AscZ z4q>EfS<7R!*d{i0ApT?dMr6MjZ5ij5*vWcO3_#<=}kV{UcT8q<30zci*bH|F5~Zp>&pnWNPCUt{P4 z7>+B(ke^d)dQ$75(6d|U4JnS|0aM?-X)g${`9l?iE+4AYaXZ`g7S$*ec5;7GDYDIN zOVc7nDE;=N($6O^nx{0+HR?W0>6lVv$+M`_58fa@jH?CK`YPU9M~udhco*Y};~ntM zI19KuB0Le=05bJw3sK|hMlzOaUa9Fp;lq^}w{B*&PYhSuMel231i0}evu zmL*5h7bBHNZAZFL+*3+NjERK@{yD&NpTe$6QO&p*S}{s#M}DJ}6y)rSoUWs%O3v{J zt?fS={Z*5aM=O1*-GT8^XP^NToJb#xR+^?_rfX{gW_6@GQrsea_E)A2MVhuE8|%bZ znH2Z5(yd0Uwg#j!&n(Q^7e%>GEA4DY-=#xOBZ6Ha%ZnRXO-9Tho~lry3hiICsu2HC zx)9>Ox@=;NFj(L-$0#X&2qqDw>R?kScZ^cM+A{{izvuz#kB?EJVla5>siOh9zq7Ip z8uMEBMg3U~(ri_2JLtbu;Afqpcd8mp-89eS`PHcqKc z`=(ZRr;MZ3+->CFU$`T&#EiL8Q6g6IH%*nmRE3FYSPaUt+tB6sA z;mWKqi#{K(wDc}phwyy}ok=~OQNrr#R#1Ka!vl2K5F1{x|FMSU&t|b|=@-=b8Kpt1 zDj)Z=K<#c!N`aa-cc{EzJgFESxlD@ND1x~C-d@wr`PEeW|mmg)mpiJ<;+(yrV4X$zwS&d1&pa|QRRpdEIX=ppqhMG)LQX?{&sb%QC zvV#`2jJpte1ln52TxjMbC5~xVqbw+sewn2BSq0sgq{Q1#uR)AIxTuz3XS^k(9QJu& zoLP2S2Q2GS^T}vqJUuoUwi$T)Ojeq^rK{bkWHKlK3n#uNrmLALmRB&t!FP=rl2Kbd zn^<**KT7r~N~`JsycU3egw%z7NLt)Wgu~y#sc2qp^`KeQm|Q`$VTzJrG$4zPH5WCk z%c=Q`N}YN8;2XiI4`km1+@8Z$$wr5*ZCqIolv zR5s=ya`_AxX$lum=?vYxgIir@Dv6P9P(Ml_?H5nPnx&Z)^bN-ipWmdthx|f#s?1a# zvK#8f+1Joks29&iL%o1J!g5$7Tmy$V=*UbZ#vOV^1NwcYQac$D0ZVe+)Xz5Gpe&4& zEK3cQ4Om04R$>Tfgu?GM)-*UU+ItUCi&;v`M(Dt^kgAG@TguNtiCFp&oX4SUoKX^{K%exC#uX$L1)xFqeNl2Q#V`mCwOu z!(vG4EYy`ixngw`vT#0cHVgnN#lVo8UqvyB#|5xjo-}pA$8`E55l!RfDjue=!}%+A z9M)mSVU?x)JID>%j)OM9OkoE*IpgW$xj^M{Dwzx8`o0*tHCIW)f!YQyDTi%mTF}jx zl)1t1L^SuV!Mm^6KdY(MB=u#bR<&&{bZ&5##viibK>W+fd=D_4tqo}4JSDLee)0w7 z+IAQmlv`pH@U_6_ldv6&1@l}C-Y{-3#vB$8UM*?GnET8<5l(F$3}NsIny2&$S;qLY zyOoof6gO$lS5~==#HUq#F!FGweSy-2 zOe&PxGLVNC`kynY+hQf5QGV9wHfm{8=vy#gu)m>ZN^5KSJm}tz=Lw_Yll)sUo`}D}N}?Fg&Pm9!B$^!XRRES1`Iu=kF=%!ymZN z=qsH@%!@26P=e~T6#JRrvzZk2iqetCEJMe7@ru%;HZTl>KzeR?#j0Il`a^sIBft0c z`;DKX`mZXH19IoGovw19cmvz}eyg)dUYc>26h*U7Hv&Gaz_A>{pIuPX8-o<0k zu$ZQm8V1vjwB}VMG>nlp++(`j=KYG9-~%~*8_|hZl?cs@-qxn}*o20okq~e5*^GYw zRV9Vjl@AqavJAW3#>_-a#$`$?wh{3>^#nzkWApAz95{9Y#^!2YUV;793H0?cMY{!O z2y$Lcr@xmep*7}OaE~93KRBbH`GNz5yKh%PL8Wn5BcVUV#(4@$!ON(MoyS&bZ|{OP z@h*Yq#ZtV@NzBqS91BUAkh^4#VVp*jc&`Iwy|STEjCvlfJ%))hpAFGN4?0Pz#;gls zvL^nMtbEFXr}k3FS^V3yA{w(%Ek#`n8{#Pam>C-F2ZMSG4PEzw9<={8?A)GjLO;Bw z><)Ev!rJuG*w%y!URQE#ePgM{awWo>XLGz&&7kDvN}^XH`sD)pWzcdZ#=jvHp^Qx} zvD8i}Ye@5#E4`p?jf3w%6=v~K4Z3_;sb9kj0ZMauox4tjqC)ULzK@7h3mQxC9T9t0ZYhAB_hJewj0?>jBIw;?Cp8t zLD|+I8$9kp?7_FIN?J|VG)tuF8%>?hK{S58F-?0LPA)svDy8u$YSs=k z#W)F7!p7a&@g~n@0}!llJ>5hw9b2a)<({00y+6>q%z4a?;Jq@NHm)>Q5Zg)}1!sv0 z?aClo1nO}bvzm<#^DfOCv&*p^;WB3R`klt?l=Vui?wWuR4WdV>(A8d zO??}B=Z*EsF^ret@!ELFpAru?vO$?uwOmaumx%B;T9FNJDR-lOnSsUBsc{wi3_nHV zLdcIdDzPRfI<;PB0~))1puiBIeKOZ!4{B_fj0_hZa`b zdnw!@k&dr7Dc!BMUdF%7cd#*RyPT|lJNYiKwXM|t#XF+j!!EG(E?wQG&gjP2mfjU0QnDk)ajc{OnBo8O`pcq+gd`C8D++p#rQ z7dCG;fLx)Hz`E-|HrAZgd2d_uUa`XK;OU)E8h(ewv{UJ8 zPf_37Qiamkovj$Tg>1TvX%-ohsFLcCclgo7xh} zAqG_u3pm~1S0Vv_;r|Ukl-9hjWFzlzBFr~3dAB<@#hgVIxOmM1i=S28n9?1l zDCDMIU;U4I+XGg%Gpuoe|A6(M+jYtb{$&Tu`G}GGfzr?&1}86S`+SnUN;qYF2xp@FHnjLdC88QHGsslDitg-2?Pe~!wKiElQoc%g0k$4gz&4>$RKUtw ziAx2G*d_u-f*A|JS)Z|97#f8+FT_&P$4W?KhPK(Q*YrYV?n2Hz=wqe6ZFd9q4Lonn zqw#y-tMN2_yhnKo_dB4qmlNPLHhQlT9P=3#_2TZJ$GVJNUE%x3lZYSCMa#KruhI!8 zW`Es_+58Fx>{EgVj;>ttr!)J-l0R&h!9H1<;`4S`m_nern(ULInUWM+b$Q8uH4W?& zznzx+e4Yd>GSln(6kq>8r9N{@um|`OmDIJvZn{tD?1%GJnx^emaQ#_|+po09&3v({ zXrk?#*Ouyeta!{7O+14b&v@X7rPsvsz`MW`lb$8MDtJOCVmz}LPyBYlv#MyaA83IK zw1ZRI*|wJQMwEO2f?8f1@B;UOJ@3)u2b3n^`>Nwcdr-pMtScL&vlSoObU!|;xjLA!>p6-#sKjz?;GwMlr|U3E8dJA}N_>4(`7k#K z8F7+oms#C(Ubj%4nf-WUT7FPzhB-g{Io;ogb835XoDOLF23zSNLs^%;NSK5i6DxJcw`#+dWZO96G(3MY>>M<$mPtWRjbE}5J&zZuYVQhWC z=Y^g-tar&^P_Nja-qBQg>#*J>Y44y*lK!PjOk$_fwZlp?G_9vmsdJZ<7)#Jv>hzh? z!xmhNR(xh?8g4fA%{Ok)eQ1F;%~Iq?M?X`V!WZWPD}p#>&O9E{+!cFM5(WZDAjED(VF<)~-1-2WvKnSlU6K zefLu6_z@)m96ZmLZXE$L>Oz@El_$8mRY&1dhEuV3jw*HPr>LB>_G5pYWMPzzMkCa@ zK9V&0tosu5IRu%WLkpC`uKOVRcszhUNvHJvgI=ew_woj*r<5f73+R)5*QcFYgg2z$ zZO`JZ3CK{=Sf{T;C8w0We9B&5OJfS$sNGkvf8R@_X38R6&X&2RKACtOM2&b=h>7A-9b3+5OK-ztr`18ZFKPIg~D-AHdl zTfbGBd&P14;75M-Td2fv4EavUOw`kCFW_JlOb%Fkc-`0RoH^h;B?hNORLJk(L;ibR z+Vh>#$^g`btlz_Y`gL7L^!LgmZdQw9{7b9TXgHy5 zD$yLAe=kuSwh6|keWl7Q_sDJ7dfZo{NL#v=9PN0eOewT_B*7$GmpYxp$&vl>H0GT0 zmW|>ykd8*@l{c&&3n3ZJqLUYJk}1k@?}Adp#(N+am3*u1c1>D!$&^8@>Q75)@^6qq z*_J?;FDb(kZr4=H(lH3&+ENBlg`Lq#AJ%*)3-vSeRuwneS1A-u`+igWY`@wa$A42E zvxOmJiaHSbM`k6X%(uUm%(f9k>VaW|Vy-|ao^@I2rDsk?=KYl`QIY*C*niE;4rC@P z%q_bi`ez!}2P<12xSJ&g6_Ri$D7`~0oLEq(esw_Iyd}x z_>Zrtq+yX=BBa`Fvs;qNVd~ONQ+F`|+0@X#T&wUyE?3#gBKx!PRm&k5HmHLOKW z4t!%s75VlekAKPevTIJbZB*dm*n0U{$EN|fF0YIC2l?iO^tU0YH$zc#G_G;_V<*htx{8BCIgP$ zpk@iz_*aukp2rr1P+g`NWD}7hMIDLk=A1yaS4^c^U(qVEt7j>Df_ISD5OC2fzcfm} zuY}lREA%;wdVP_(3TkBvb6^P6%Q#-TuMDxGs^1~w3qaTEsQH<(YMb~D9 zaGZ;=l(%J@ks-^$SjWCzSIlr3!~V5q+J|Z(X1#-o&F;q}y<*Szd{D*2BtiD&$e!u# zB!fQN;9s+&SuZ1d6@vGDAi+%vf*llQ6}F{b< z*VlX?PTk!^a_&pm$Si>e^h)Dhii5&S@f%L3@a^_2$m8F*;gWy9s^#I!{k#k2Rpjv~ zn5gC9J6Ajk7HE0+5?arK=}vjZXnFK&U1l12CMDbotXQ_ql`zZ^;4W6%a*GR;dfBw2UVBh-*y3d*cW$D-Q4|T4(A>@ZDvoCOiX=0V z_Mte(ZeQVP?b$4zdrv>s-xa^LqyC(R-c8oN=~2ttYv0@pT2-XE71YP?eZHV9+zj@E z0DRJDs3X8%NH^OT^(eijh{)B%S`T%{yb5%AE2v6Ga8(`SaBUKv-gxwZg@^ z>Wkm}?pE;~yT{shM%|;JhxXm0puO?EG2Rd3X`N*xaN#8U=FIJkH=kHKZ7*Jk|%RyVuiGfg(mfC*q;jtJ*4B6(~06ZnkqR-UaLME(U+y z#BVflvG$+miBG|LEssyZa^oAP&2{?zhVgv~-k>m8u}0xSJ9Y&=w(9VvX!-S?%h&R| z70ki=Xpm^Yr*(ovzO7X)njb85gB*5O*1W9muEgF#_yfp8-v)~bSb)AJbdJ|lZ9&7b zl5c;dIt>aD^*pa&K~^syjJ^^^8$v`4+m>36_d~=FI0ofVYl&iOO0zVz6r%qSo`bB) zL383W7~rTy8b?K?!(Xb>^>pHP^*H)8TnOuG$JKB#pXrNtnB&z*5oz^p6?2Pv;pvR$ zew2vvWa0N*h~so^5oGlP9oAsowih>5>(jj`(bBqz8pMd&^jNg`*4op7->a;)UxOXT zW5q?QZA>sVj1kd}@8U#})pjjN|MyuP;ckt(QTrD8McpDdJgbe}7!CI7rnrMBJ5j`V zaMh42>xy`5${WbO9Zvxs*X&>ag=@f_K>)p?zv%CVBF6iaem7qW0+>izpD4~ow+Dy; zcpiNKs9ddBv{v;+I@tha&ejvZMBj)6w#e`HfHDo8%Dk?Zsi%muQ5#U^BRt#jR6!3d zJWcn2omNdJy~qfGB99^KXgoO&D6*)sNI8vfBrqnVIF;;!tadzMdJ*)y)<^I-ZK}4t zs}ZI$4TNdKU}8O{!j3L^z6) zMQy7!gnmyEsn$0f_Ea&-YJHBZX(FiFbe>qRd8i6Sr3rmw3Y!?OP1h&KKCn+VT%Tzy z>^Rs4C^hy(((tZtt4{P`>x`j8d!}pB$pLpNFa}|#hMPc2FQfpIk6QDVh zes3mXsrlQ@eI5BtFfpu6IVI9j*i^K#+DfX^AI-!HO}{J)GQ8W8>F4I+AKq<^D4>N% zv!+vr7J^-;o`W314B>8y9@MK8mPua!N)KAqJU$Wy*QxdSbghLLA8q#a6}u%`{o7RS zi=NhwG`+Qm3#>H1V;7!nyB%m}YmpjsaU77$wKOjd$|%=nzXfs0TZ?`im$8j#uWuKu zY9o3!`E3}gg%#)=0IbC!4wf7(aQi4}YgP9jx=(0kMJ4P{#FbnMp}OfJD`+0qvI@1t zRMs*jT_o1?QPUw_*x(4BW${<>W@=S}fo~LBz4nCAk#y14wmODtWQaJoJRDDHG!22W ze5g}~Xcm!IUFBd0*mN$R0yoLQzz*xN=Ek-nLxkH-_|f|rXw0P1HxQ=e5o-vXH$yW; zf3^_MK(E+>Gs=6?)Jzd?+u=uRGeuMG@3H>XaQ9M{s2P5jn_dfd#{oCv@PigX0cT^g z1V>Qlnk6&`$i-QrYtYpvksCx}`;V26PFTX}a+YZ4zBCf*exsK>!q6!_+lp3P$^Aw? zDYU<>2=eywb2gH8X)hX7K_X)KzaXK4$7hLX+YMjpmL)VhtcJz_S2Qx>bTsZqm}u;v zs~vPS*mh$5i?TZckqN&48Z)?Ea*Ck9X@LQgHfs zdKb~F+J$QRr|;nj8kcJOt{Me)6=Q54RihbQMK=tIlU+qG+pQd`+f59#PNCV|LVh#a?{hUnxOM_V5ejcj>gRQ8ByXT{}a zy+oHlz{+M*m#;oePu09dqgJ=5k23>XdvWgCIMRpQh%@?t+)K^eMYQ!XQHwr%1XBzi zqh*hZcD66QNa-aWcCDe8Stg&$poThB_L%6zx99X0J$!%`^O*% zq}m3jO&vAo1~a`1H^mY#H|AEqSEuUzMI7J%*k3&6*+$)V=e};MMA(J?;(1Rn`B-%q z1;m90EzNK3ZmmISPl&!e+qF8Lsi?zUy*&HDb&NOa_=*Asi$}e14q$D$QOO51eXw}J z9f4XmQKp-<7Mv6k28u4+?g<0YLt{L+hdKr4o7<4)D7XyONgD-{G6#tk?)lj!M(+>A z@~Q1mc&e#7MwO+FR`2xJTMbL-V6-}2edM-|knJybTH9Z|;AU6*(bfI6YT3SZ#~rQW zace6YpDlvZoPscAvXFovOx4w@XEje_{cyHkzvoW7v&En;l?QYSc;}@$&U3RlJ07ZS zl>@p^E)V9LAoZwG+g(5+xattmztb-`sSQ{DZRS>I0&m__#Sqb)qSf6M;Pm)UyuvwS zhzN%{qK|za!0AUR^xd%0F4?fO=ZHbp)l`xrf*V(@=ZYQCo}O{3C(8u@rsz;Hu>Tbc zVp3Jd;KNZ6jTC(1oNsk^YDduqr>InRHi{uC)k7}ugI(aCb)(XuVoc!mu~pmmi5m@h z66s&Lq_1~#ls*Zb+jO`7Bcz_f5+c^obdTeB#9 z1eVw8j^-moqSfun7@+WiVz+&0(}Es3R*!_Z7O;ww4OeJZSjN)Mrv!yOXD0I=LcD%M z=0lV{O3V!C?(~UE;86Z3F+Z@LOY&_iEg3EDgr0l4vgszI9adWVw3r;Q-{~8J0zVrg zHo7lGG7Vm93&vrQ-^Yj#tpjQLI1xl2jTPQF-0|sHB-P`jTDF@OT0Tyk=Agop#|y=_ z-9m4T7e~V1g{)!@D6Z8EhB295en#xIJwKWX#)=4QTgQ_VpcppqjKwV*51-ZVgEvU6 z$&?_qrisk>^=8#HXd+XQR-3jyD{8r2ynoYi^jYC=?Rw4o7F9C<-N$cNK*|FEB_QpS zQBL^!+UhekmO2ui7jD+(D*_)_58}pzI)&{d;63E@s(d_Z)4e3dNds z+!N+3JU`(<#f7X~qDu>T_IRQ2TMsDwoa4=Dm@jD)QDzaI*$*gNc>X4Je?VE-O>)IM zfiX^>m_C>PqWAN}d!d&{7`QqeJJ|CVO`a|exb5O^n4Z>Ij_eswDMN-oAafIXeWutO zkmB@-;Umi8EU_Zc%S^_c<>YVgQs`_kEwF5OC5bqF`(4Ldvmqe_tZ?}-%JJzO7$8G> zndwe=#?h~H1qIeKKN)r0zC%l15|aZxT++Y3U%k*pW6*cv(Xxndwe- zfN{+i8|{G_nrL@W+?%_VsRom?WO1U%=Gj6*6*VX10KX|G_6cslyMg8mBp zBd4;3jKiK=H2GEWcR+!eZV(R4Z<*-Rskl9Y4LUi#dSJbGS){d)58Gy%#L*Y&87|-; z4U_28`U3_B@xfdx*%qy>kBBqzbOi`qY#87I0->5o3=c?mNrp)Gn%ExN&~l6XT|WJc zDgPSg%XdT2W}YwWX!@HXa@lh6TEJRPb6U%up-sz0PQYw4*&xGX6tx1h9paLlLYr2I zRRK+0l0B*48)8skgiG?p8+7CivBd3awvLC}M>q6wL2tY%Rzw%gf;D{?xTkqo@<$v~ zGp*?{^w>(#&?o;X2+e$4GJqDY6#WAhF(@bWaYgq^F(~XAGuc2t3l*^egZ2e@ccc$i ziJAeu%`BKqJOB`=ewCOQ(AZ2iO1e|_YB4dq_I>ngyyaxGZTAi7s`G6=gyBb5SBoIq zkJrg_jTjR6$6x~;qx7EZGsCeLg?}^J+9G=}GEHQ>H^PgLT}qaB*!c9DzFdRwb?UMYt6hW2%p%J#&>fdCS1U47Y+U(0u#g zC}Z2tLyK^Cwx3QBjn&vT|4w^8M)!PVq?)#0gh|*Vo@r9J!RgE?CX{yO^uVO5lX8hm z*&+1n9znL%9q7xh;t|{Y4!UIvYtue4!L4_P8*D(cUHpxX>=V!1zW9x@_KT&qv(@R_ z{i3}Gb}3hnrnm#5Z9VL3E`mC;25|(~>4Pta06mIK0|EzbXTyg-Ej$3h6AIV?fjg@G z)NxdDK=fi4t%H~Vb!h)V>~KZV&;0VFa=dK!BPsL~SmEwoa?JSzTUORQ$M{2{v77DP z7~1%`SX2KSW^vfO{0eV#Z87KhOhm-j<^^mvUo8zd6Gkr|5ySb6>=98GIOQn5!X#Y6 zwpiFJzrBtdr$jupe#yhvzm`+cpD24$WF)ovLR_y^1XZSZZq_EglHy~ytQPb6)E;%I z!!hxNd%gw4sdZdD|7Y^(+wB*x>rpfas!Su-&~tbG{PS0s=orIVU=ep_jjg<@4m8#BEv)R7L`y;A7)Zy~aDGQS$@D|q8~Vn7|-et|)xTSPLoHM_o<(Ew9^o)&!v z!$LKe^zYA8_3x4X>myYe$u8voUQ7%4)J!)je3hbp5Mu*2n8^lsxDj&lY?ow6R6m04 zQ1r8brPnTISsfTG@w|V2)x&$ zYQG&jOKnQT%7Bw*x{)0x^Gk#yY?Vv$Sj5WKq_h`X)syr~sc03D>yiZ%yG(2h=xHV! z?X}bIW#VXPgqe(XVSL@=M*Lbv$IoIpxYfOCFCH$VCS_s*eSS`)27GRQG~nS%gY)7= zW=OMhXwiAmwmulr1c=ox45`8<$>$fCAziyfcg~BrfaxYcqs1^KUl602LuJyN7ex1f zt}Yp(=-ve}F;KW9-z}v%zlbA&*Si_mC+c1ENhuBaRTKn#YNi`Ki7|Ll%nvw(1F^;M zw_*b^hwzA_T^B`Cz#=oZffeS}MX@m=?-C;0xqM1O%n)gV(hV;uNAp_gGWC$vy zn>WPqP+v3MNh$rIgnWJ%0}_kCz5X$Fe(hSdBX*V0qTj{yL5E$^spKY2obTHdw=0Q7 z;akBy3-K&=$u)>>{2`w4FEY7fWJBD#_UvUbE}*-a(;y9OZkNSVzJ<&z**oseDSGOP zSQ3zY04?nUT6G7l(lg2zlK)lF*|*SSlvhsCkgGyFJI$Q33$3{-;sd|!QneKui|L!I zm~kJvq|bM>yM`4i2fDT_mx16`=xx5Ux#fmk*M;A!RZ8F6fGi#H?fYAnK7Bfv`0;JeoH6~>i-X~7|wVjc{%~mDDaBzOR8_vt4@DQ&o?btg1&i1mE4~D7Nk{6=-TrDRJxNp_6 zeR1`Tu;<3BD@@=)RWo#Q242evcr9Cb9yWO`2$a&%EE`$1YzybIF-~P;%(4k;0GG|> zX2(}8ESw7`Iu%YdTNS8wHd`gCmaXkvHp!`Ml38(G^&mnOYZOVfmFGIs+uy11;HFvS zvFJyQoK0=z?{iRhUaQ%UpeAX#D!6zq3rvFtL_O2BfoykUCY z&pA&JLUdK;$yJR^g;^bKY8lQ8>_evg><(O+sWQ(C0jPA^HU|Uxw>&TDdEP^wOd}6B zaxhdB?T{3Z@&b$g5{Ag)$SxV>vHAci%wE^N+^)B{aPT_Mas`JH(fY!{@3hwj9SfcN zF)BYn!HO~)oyu&aAMT2nj)y&Uq8;_rigCUBP>cbmfDZ?tJyweK9Z?9>>1wloy8G9_$wL&67B*wZUS2HAxN(epXSl zeL3E>d3xHdAokTYGQHN02IUmvZrPgYhHG!eW|Z%T;B4>P^3_|ibMD}l+AjIDAj>PS zpwIK5zgWge{Q^`cK!1FH+c4*J)kH%rUlGVx3Ju!;uO7ZW-eHp+pcvohOwFmOn@q8dXi1~o03eh7Qewkt zshez)ezu9a2FIqI+t$+sgTVpV$0-a@_hSw@=j(uc^u?ySVSK2?U7oVt4Wygya<}b^ zK-%UZSJwXx;u~ugr7Xtb%`TZ2@H@t^&zU;ZG@9foQ{B#CZHoEJJrp-G$#iRf^6-+) zYeZn0bL0t*iSJ%8iMo2p=-fj4Ss!%<(CHs|gZ9-xbTTZ}XQ9~4u7|MZxIlOM$2SS1 zxk5c;rHA+5kCy2(mjA~gFGn|tt!F8J&Luy?;{1D!{2J^!`b>e}z(p@vBepmNsAX(> zB@zx7O~DS6Eae9<;IfSLB^2&0``U0}=LBzQkI4ejvsUBW3yOF*L`*fyZAUSFqcaNa z#Ywc?TP8HuSfrmfGFb~oMU_(?g4h;AkmP8TdKBoG0;2#%Gj>*yeiq+rQb0A?z#H5F zG`gEe?W;+}3u^?HqRv;V*p)0;P{kcQcvc=MTA0N_E*A)`scTWdfosvLayr7-zVF9v9?H*_D|ORhLiu<>&Zj>7{FA zQF;y8wdU4u;PQ}T*}*rFu5W~>b8pm;b!=a)paXc@b*Lvla)Igu#H*&PZ+!{3Ovw}M z&ln&#`YHhFfp~Ts^1Nw#fPC8vCU#%7@F)!llnH@F7W^r}If7EC@O(*H3wk|J&bLub zsv9JGv}vYx?u+FX1I`LBIn1v@)BM8M9C9O%6e9#Ve)ICiM>SbSfcTZqL5``|PX^Ox zL9(WGC4C6yWecU5B~x4*UvlWt30B_bG0n>d?rHP1^6ap;}lJ?f1-3Y8i&1 zkVfBz$qgRW(A=6dJzRFMz4s0s372C$-|q+tEvAMcGW@|fC)3jr^7Up3>ctK~fIV6) zjntgp5K)X%MRs z)Ti8y4_xYJU}VjaiNS4gy#+J)cL6T8w*l_m82JSv7f*_n!$J!?XaBSLi|IzJ%yn=1 z9xkwhox@JA+hv@dwWbTD`qD|eY-|t8Dj#I^y=2Ap@LDsVlkhPIc00a}wPmm$b&Hk} zlo2N*bvXLs!3Q6(8iV4EXnY(7?U8KS9Vfd+L$&o)XCDR|{tzsZ@4a-|XuCu&CrZh_ ze`OF}OLDa7RLHENbe+38r#Br>l#OX+yo{^0{v-|z+z-SBEJ1jJH@R20FlhQVUS@`8 z{R{lJ|0n#m8vGP^$!BaENt^4)Bm@`!xenOIopz)o$jv(PCl5Us`KB6hj*jynF?iPpLu-x<<)kyr>@+L)e4Os{Vz3r`6JCsl;Yp2 zdb+Zzpc?9ihrlJU^u!@JK3{LzjvCaH-K|!dT2DUO2n^v**!8qIrcbf_iYbP5(rJo; zvHGhc$XZ{fdfsA~z38+e;ayD0LN?S%^WCQpCQTcfDrBR7>(}od)%*31kYOzn)S3Ve zo&he}NPQW&IWepJ2QVuQulpaelW$9(1UjZjU)!RG=m$miw!J%u7S)#xbZU7!(-ucX}RvEW@80(mb>7g(O7#zYRzFD2ak%st{U{*3^T}-#Q@uVLU9eqpFXbzja4?FFX)g z+0wDo`5UZ_9J*mOYg!%MRI3jNQO4aljl0uU@Cbe1R7N&f=Uiqi%1pqac`oy;uR5Kz zGeqlUM#)1UgY3;@aBx^t)$T&pCe*2!Y|u19ZCIPnJ+LZ}QC_S?ScV26GRhZ3L-Nnf zD4!0E$4uufqcSvUHf?SuJGi&Rg-(=l#u{w<{y0@{E_Y+EXFv-XPro&nW(OjWO zUKp+my096xmT@tK8z9)8*Q9zI2Z+4=x7Wj(-2lsS{_sn*wzX7jCHZu`wQO%C3TY$L zZ3kCT?>2Hx`+Vl5BTVb&bDz`u%^Z&Rrd?(`Aem_bCp@kkRgi zhrlgzGi3W{1T2jLX)i2U@#V&28?N2Ac#7!|7tZ^@QiK+lWysFek;e^r%(Rx7@)c|c zqElFu?@ixlVo9n_^|Rz-SWt4aWCRGiJWDEY7y2{{=7svWu}d!S&QH_k3&N7Nm7~0% z-{H84w0B?PLQScL-@O-&b&~abuGoPhBH{!;OWB=dYGfo1N&OGlnTXhNwUZQ9 zY|wU=L%Vc|Rx7(-JGxM5$ztd+ zJQDFgoQ`#twS(Q0)HMuorh5ffc$w~XmiG~Y`QF2_H5$;ei|pl@puW@+?y1^Ry{n7# z^$co-(Lai!TLgttaTgiqm8Pz?q<@n^nOT_PvMX331i%EfH;U~uG>H>X+f1pz%1VKY z3WHHx$kIx??KdmR96%YT(O;=Zw5>AwwQ@~SjmQCr0{ z1$PaWErjOpCYwf##;F>%oK81Bo6)}RoTQ80WELL~=`J6xsHx-sLrsV2SPvOS$GXeN zh^$8CREFxZjq2Eti_zG4$4RpFkXin|ylu`-IW@4>kQVrVWDl_R6xH_sQ1f)IIWc?? z+Q=lxFe)`8{f{UAp0cIw$Y<2KC%Bm;wWn;_sNp7UrOk(!q6LL6j>odZmZz{p?GlI5 zGF&!bEJ;T{g~6~#s9!Ag2nqA20ik|D;Xj)x`de=f8Zjl_#HH@!hUGejc2-CHJjHNuqW zg#os&w=KBZ5Y7aowd0UsRBcUQAGe}6afEkGV1nEGt8dZ#HGyfM*#17?s5qU{SMG&z z=wx4+JP;Am+GDaA(OB%@llI$s6in9pV|kKeNa{XVPlSrYWXO*oBjAHPY$ z%~I}%4H5}+sc#oNpwF+cckY9J$JZz1P)L6%Ik160q{55GsdIn%A^+vUx)lP#6Ec!z zMt6KIq^(bYi9Gs*Og3|;ILCEoKgDSt-X|J%Ew7x^r#N;!~PDKyJvz=xD6QSllmV!WMra9>R^g0hmO}Ged$j%hr*C{Y$M){Ey%x_=cC4ziSkKK1a)qawWnAGM zy`NACFogj&S@>n$Icpi9nC@YD)F?;?2g=8)xucP@AQ0t|eUMB{{QJaBssIecoe_P# z5>XmENQSv{b7=k`+0Q>7nwH5caJX?&WC(cK%H|q;8$K5`M=~E0*sALot9Y}^XY5!muiAxlI9xPMD13}I-Kt{r_lM|m+&hH_K z)FNAU#!VQrvt?X-p}EEnMqYD`=X}|f`Hy7F#~xfkx^o4>s33_t50P26tNUru5SfCF ziv2^JD++L}sIr`A4n()l_ESoZY+mbuE&6RE&B&1nk%heOv!ejpwMxJ~v}G9of7(a~ za^&N%b4Cr7k>O)Dfv8D{spf7`i}6{@iqX}VdJdIA?q09M{u7%S97cIVWh2D#+B#G= ziKqb1w@^6)UqIF;WpHDdg3>K+m#i4Y8f7(8P-RD^LX7h6{>=Js2#rJ;)~Rh@AE4-wa$_Lo{`)9f(hHZyf)`|A1Mb_AP_qA|F;B@_ zarnFk29z>rJ)==_xl(xO0aNma4Y!CjjRQ_ovKsw73dGH# za=hGoy@CNWcoc+(Mx$knd?1wV1{7_qL>iMMCX1$wmOU{}kBx??T`>(8A#;^!=u{x+ zX*sCgKN-iUO87-N`eZ5^l0?g&mYw|~_d*Z*9G3(%vJ}#lr)3?M?Z;GXkhH2=TTymp z@yEwV#qUp?$gu1)isz4!&%hq*%D23X>JL!QFKa|nv$1kk$ilZ!?O{x}Z!rZP2BY7S zQT_s*9E&ZVL^?NCw!{Hj`#6~!J{K$D1yCM$!ByGbSxLLb0ohbKJx@9j^yi7`2fFLXoDL;kevmq=@J&(wC)gYVJht2vTq@O3c!Vt5D^;m69FS6t{ zrtRZpnhkBbI9|3F-uQ724iwm!!7Ac$X*#yBOXg>4S1z%v(=0`sqY$&assA(Rt5<3B zGqPbE;;DM7S$fSy8wR^W8GUivCTv62pB06D3$i!gO=6?)NmA6vWx2lt zwz|O}`E##HGCnF*Z3zhHAW0-Zk^ls;rUF7LEuAELbF|T8Tj`HUQc3L0Ah1^HARsaE z0d?1n=NRr>Iq8;pv z5!wfILqk|HDmIFJzLNf!CWlzZQO{i2xi!|iMD-Kw&0wj?XTwkH)|E?*ri8kv%dv*h zXFH@^ip`Y?bT3!>g4I{clLKlcs!ITi_k4yPx=H=<6k}H>+c7myK5C1~YoShn29F6< zVYfPWM!zGq{1e9?GvrDuU&1s?ZnRyxMonhR&bIHa(Tv%0dCd}7tM&QoU2qz|dD%_y zZ)w$L9^2_Q;~J?svJqBt?*^5vnGQpMxsv~{*4$cefTZ8&pfz)F+m=iolc<)!W67k< z5n!2Ry8g#92f2RUjl^y4o9D_oov-jx%jT|+SL(|vH-0~s*jPxszpZnTco$s4TJ=?cRAt^sZ$@65rW_d}f z+5#a4aomsj-WnK4?H$|bJE()e3;i@+SkZN7C+Y*zk5rUqHEJj(nFV)o$?#~Y7F#Sk zi>IK193F&V<+%_%U%N%$pixvfA6w{Ozed&P%eo%#bht^K$+|#>*3ztLXHiO9K=I~M zf4)f#7s$F;S{BZiwLH?7-=a-4eu0d%HC@gSLg}aZGS*`fz~B<>e+9E&2V+Cy7om{t z=jAkJ0nB7yFQ-KSpYkxuU%YdhisyqeFk&;}YhlpJfv(F6fGb){HFy!r7E14sg6rsW zqrr?am)$^73t=Q!MgG8=x-68@wJ?jZMC)sj?smj_{%D%MP}XTyyM}tP9hM?C{m;as z-8!72?rM%jV0gt+q*;EnrD{^s=aLK*%jba8Fnao5%z&Cdk0g2UKdZx2qOb%MbO z46@z<9a(r^WwBgs51)xcmg?$3%gp5)YOY#73r~BkdqN@bXD>oK;0(1$Ucdp8?8VZ- zCXalXizq0s=gSMW?=I5}RlXg-tCHKLePHiH;LO3&X3HfqqB#~3UWx4Y?mx;Qb$KOP z)J)?8T5GJ(zIm5HTZzEp2lK^-DD!a(TC_w?@Ws!)&>z_=iHdUlgW-56JBF`hS7JAR zSW9XY%-4SNMzb%xW~MKN3*{V(?Y(4JUS~6X;Xw+5*AvR)`yQL|Z1lsAZe%qAVzbfM)$UXHc>=6*;N+L7M zqiEr)vY9O}kq*BqMeCO8sd~6H6-HJIc1283+A@XAvwRS+GA~i(;8GS?sVxWwxB>zH z<{OxGR5ag7Q1%AvGp}dCV7_qnubBvF#}b- zvzO|=Cbg598!^FETKF1lUjCHux{Qx-2j%%pS;<|@Rg7HyAU;CeHK8G|%XE)CKlRKe zdh2ye-vM;&b=eCyW!RU?HeOdOc{X)%6B@Q$#xU;~0?;@lwOmG|SK#wOKkzbaO_iiV z%HjnZS3t5vb;Rce&4NqAd2pru@Cv|!QaBti7`?lD==^e-90Xq)-Kp&?G)oU`%Y5@Y zDJ$g2%GOS$H&@7b-@;`#36>1lUEJvC3R%CwIwZh;gW6!GgOg727Tj;bJAt*UtNVFB z^B~ODpq8xd z-;{NIDvl3l(y=#X8=ri$JxLU@Qa+lC#+>C+e}F%22Su>icRx2^)BW7QO&pWG1pR*R zRcwv=u$QHqdJa6Scrl*s_?Dhge$)9IIDaug)@7TNyPv*6*OpE3`X24lZMUoJT`^yw zajT^_U0Er8;Z0_=_Ro*Wa}}%z;0UW^_sC0o^pP+aCa`SWL|cd|OMwpW6CYhA8;G@) z32NyC;4l$97SlZg1u{`!dF6MCUoGnfXT+&?M8}2Gm%0uoqnO_Ccv~%n?=+{ZOF3)p zNY#o^#HCKn2%%%EWxW4GKuhO_mV)|@d#mLkn-2mD>jQo~Zoqgng9a98X`@M}h?Vj!KmJP3Z<3GOKGEKBbbXU- z&hzS{4U|%V^z9$fq5_%ByWKXGHee9c$Shy0FV+>q>fUZTT_98W4peqHDb`r54a-qT zL1|l0br}p4Hx6eY0GDT#09RV*PG*07TZjh>wd6h}3d8rR3)nppKMJ6UJ+0En4ui!PjN&C%F zYP||xboxDsKHegi!qVQePzE*ZZj>kis$I0-9JsYwK_~pK7*WQ(UAGHqNug|ETfdu* z7s`gY*{U{Bi!@%92qJ^fr637k1)Yh=ef^xjqm$V6Tl*e{@3j%x&-r^(d~a!dkHvTF zvUhU+Za5fZ@I?41Le2Kds|jxaOU2~$*>#&@JmN!aI|^y-Ryh!%{H)t#pYRc2-QMso zb2W;<*=w7;+yL@bz9wI_)Vq?e<+!}GQo_yF3`_0>Ecs$l+%6*ndM`o%C9pO2u;A=Z z(XQ?Ci4>?Wag8c>?jXQkso1wps@%D=Xp)t`O0UCOmK7di#i76*vZ>oU_t9lLWOQh~ zRG2GrwTm0~^FG{*P1RwoZc@@T_Ym9JEmXQgKHfl=@YyZZR&Zb~`W%!i11CP)9~_re z>PUzinoi}b&Y_VzEtdH!0{`G9NNf$%xeq>zAD4WC}|6iatvz=zHz`~uGy@$ z4yhkN99Ty?KLDCvzDLR~_yhcpT1(gHXg;CWinDyXT_AS_&@PgD>5^qya#N42B=$Q>LLEZmQj z&?!rNaVkgGN??y|Nn1XWwLDX?Xjuv<@0+k-D*i~$_rgq#P#4^#XFitoeTqf_qj!MO z!?fXJ+0YBZmZENJKtEJ`Jc?zy6Z!9v&)3yTp1*sY&SEKL*K+WH3Lo^dtMmr=Q0slN z9^-#%kIdjpwBf%FLh@yKv1H#X>-rXrM5UXU#qOj>_R0iLt=3L7b+3#wKBCgoJE>r= z93d-eHE8r^(T-)QY#UbSUai5Il zoZL>><@d{N*mybXLyrBjyIX`hjH(@wT^MAa19D{qGQI?mZ^JHiWyejb2iul6Hq5=x z`B066G7<%%sKG&5+uR;2-a(HXlr8!1TPSy82Q51&MKj3MaI%EB4oBK`Hubxx8`Mre z{Gn$4&FO5`^C%dzv+4$GG!DH>?Mmj&0Jes@ej;l#?!0rin#O-3$08DM$tN=22LF4{ zPvr#0cQ&%l2EN^aZvyc30KVM7rJu_Fz;`rV{Zxm-8-5U_4#`#wlhKW)eure!T8)4P z3$S&e^`6hMl+VG0KlFw>Z9F97Y}Z@SQGP#~MwbuCl*bSr;T-1pEX(ZWXCXmpaz&X9 zLtrX`$=M3rn?ij9hh-VR&)ANUAY*4Bi_pCnXc-31A z1dmY3=h%?^;;_tQ60=C@*iNCJ$#nDYhV3-)GntuNWPih5jY9)Au$lMK>gst+7T(+Y z1)9gNA(nj8+*^i)=`2>od`6VnJ=SIu(aXvWx`eUsYm9xKJfoln@DUb9bSzvM__rNo zwzA1{Bg~&K;^rf7T69=?KcE4_^aecfxvbU^A=TpG?sX2xY=8uO9dxUzeobDWv(bakvfZfBp zp%n$Vhlf$~qjE*emfvpEzI$Fx?&C!I{ap7=d^gxxGz3~a7(iqC^Qat9BOjS?F0ZMX zIOq%6Jov3hFgIQ>KoaAFN_m^&5o06H-^+Gx6P^A-K4bfA6FqWFmJBT100w>@{3hSs z5_~p2vwZfmV7EA01QJ5}si`il?{t9!uYk898*_gluijs#GF36;3e6#ho7#`d=i6#< zo^*vX>%YS(-AZlBWC~?`E8QvYgsi25%mm1i8vh?>?*U#_(fp6!d((SDNKZ&32_bj) z(jf_igeo9akf!vG(nLWKLPx}si!Y9X1w=%zq5;H+ydt2YVhboLNUtIYK>>-h|7UjZ zNlrrW_kRC*o;+voIlHs7yR$R1v$M0Bj~``stj|3EXVkX3K?auEvwMWbIbQ=c@s0^w zp+=&aYwF?VTA#uV_caAov8J*_QI%>+0O~yrb-_(lYOTmrbz+I8swK3nR8iFeJq3#m z_nEo$RjIvC9Trf2&UvxMKxu}L!GZw5dU(hlyPbOMv*S+F-S9r^OPhAv@5;weyonY2 zDmXf^+_JI<#S4!AxxH}n*kk`S%C;EIQPiO;wJ3UOOpYJyixMcet?qq+PizjufKv@nI7J2 z|0FuM#+tL;-8TIvdo;8i=TG*>Jj>QZ`%=iy_RF?U{~+&Q?6T|lV$3v{!`Y?kC|F0b zCC~YM5n9p~=E*TbTO0uodiM`3S22AHc=vjILH3D`Zi0yR#i>Wnvv1$L)w>Y#Xb8>u z#cuDN-_p5e%!n4BSUkoL!55>=f2UujId0#pRjl)U={`F0Kg=4$s@i8C9zAhUOg3`j@ zS-=M@kMprUZOv$~8eNG7=ewtYvC@B@9z9^6kObY)>OA_XkFzMM8pSDDXC_e2&I|uD81JY6d4!0TLuY-1J$6nx2cKjXA^=ga5me;P*Nz}Vi*ITh@O{T7g z?0NPIi$ln}`Y?T4tV~kD)(h(5L_im883?so zl;7^u4ZOwEo2-Yi$65=aMC>_@ij0HBN$URKY^O5c&hv6E#4Na6h$S)7E5KN9T*!Ot z#&FB-M`#X;*Etr!$F*=3G4LLiq$GEd!A8Ht9h!&Xb=Q$DABJ7MN2v1{j_DqM4%`ZI ztW(1)^q&QqRy1yi_5aKj%4dFJaX4R$yi6m|((xsIj)0w5!|3Is_GUinkjEaP{YUL_ znHYM{ziu@-vKsU=5%e=2i;q_o!vhFjlt94;-uu$2&M|u;>(DRM#lpzVi@r5S* zc)}i4DN8HRkD!^y?ASOBb&f%yg33b0$)&ASq1qLqqoUBscbMfDMgTJ?Wlc|lHJ^Gr zzuX@J^vic>&vAR-4p0n_9`|-`i>OLH`N~-xXSAjK*9Mq7h%LZuXr+>B z0@g-W)A_iir|XpqRR0fqT1cr{@2tjt&glGd=LH({hrNz<0nPjaXD0j6`ajUPu5|DZ zXzC4V@_BnW4LOfPmGw9+ql8)pKf&Q?*E9Sw-R1&|g{bjbzOX zztyfY-mT(3Zr8$j4&RPWLnRw4TegK4{m|gNpdm5htayzC`#8Q)w=DNf_)=}8t$)I6 z{PyNGQq9YvrdR9(ZKWq@=@omk{yR|wY!$SMdyya%SZBBh9YnPq-}w9I_}A{(zOEfe za{z#C>K$&R#`9zRSD4<0>sxwyQ}W;ToUCHwu>ANRVeRs?T)Z28mPg{yS5f)pJ0h?- zv{LUotoVx-{%wDRO)`JmpXpGR{DgLhIi3MA0LCM@J5tddSSc8!c^zJHCsS+ajx60B zkJIj}H4gMcYk8pKss7EtU}{iq55yUWR^|4rm~^8hZZ5SI?gGr7URNREUM#o&%=7af zY?wg_`^Ww@_TTTnhA0Ow(#zN2RDCQ75kt_32dL+DyCdPlB!pVN?$bQCfu(3j>yGe4 zoxOP@-W|E-)7*>sylJ^=H3)`)80Dl+#8jZF)N-=LvLc* zPN2;+Lmk{#3nKoO+pQ6HBZ)C4L^FqpiLjS=dfk zUuESpMK)Ik(iJ4;?x3wJ=rJ$xk8R^0C69OuZ@&F%rjN*t_!O$|@Fcwhq&n+Ui*qP_ z>m$ZnQz+Y4ti>1}^%WCy?67My9bbX-c>wTs45^Y1_ z%|4Nd7m$W;XtU#(2}5D1=930P@Eit%^>6rg;kBR`>rvVrA`)#Mzeux!L~q0w{r=SDR#RrRc-)CUxWum9zOZeD7SR~(`zX0BLM}tLnO<&;VA0oP2 z+o>usQ7(pvZn*siPV2W-x-e9v`2P9A|5D$VbTLeXQ}1ArUQ?wj`STS2QmxO~5Mt!P zS|S$aMCf;|=;>NwaM;tHRbyq{Pd93b=fXx*dyTE|a50AMxdF9BY%P-k_%l8=G~0{T zMu`64=+;Qlk*4nmZ&1s-8i=2WVk5+00|uL}na4xDv^d#lf7Ii!Z!5H3se4S)k z*&@dC`HiumVPASwMe_v;i>$<_CRneyVb!?}))UoW^`o#TQFNQZ8+`RB%t{t)44Vz! z2CltncN9qR2Y5aL)dZ>?E!u@OssK}0KAnjcO+t%v)v{%_+CvD# zNQfAb#Ah_Hfvo}=vB~Iux<5t~gonXykYC;g@~_Q@x)`n$aA#*JcM^on*O<3u7ng1?IwS-0i- zMdy0q1TC*G5~7M(vzQOmRlGhlE&%9%@(O*2kLhK@Z*?e71utWJ#};Ppw{DNggj;{& zMOpw53D5zf2GQ7f(Wq8&8&7X%DpV_@XYZ$V@wzc1Og%f34#rpX?66Sm(m$T!Y>Q$o zx$Sjo6&V_Y(YN<;>!YYBNqA+iEhs+`hou@&8}T;MQSS6=q!Z!0plmC;ixlX38l$)q z^j(rjG!EhzkaH^`xA?z8eqAH|5A{sGeZXQ(fJ;m$Z!w{~@eU~8tx?`b-zMD-xSZxB zi})7*SD4>uWIwDC*?ITc2W0aX%F&9-8 z2Xqy?kJU(M7im=*CNLK=cku(dqT(7WD%EAyRjbJ2qvqJNHCOarWg&A#|IrmqsIj7F zbeZh5sx7LkE9zQvMGsaMGFS9pU6H-UiV)5+O%%8}nCi8=bR7XT*O8_2o57#Z;D0A) z=ItZnuTkohQMDZp=sLbSTI0x^q3xL%87^e5D6p;~us3V0=u2JZ+iDdR>53NBT+!Of zLgtE^=!!TUP>mC+(sVitujEJQB>Wlj35%p~C91dQ7>}6)gxRUi`xe0Oqcz+*ebsWa!qB*5Iqk|4 zjVofLU{`90vPz|5Z_nl&ND+4NL_7c_-2uQt+H4o?;(_o8Y%Lu(mDg&L%^6EELcALN z4>W4C)yM@03#FPKNl%WXQ$jSs$@VxYCe?vrmg;x7k!MdqDA zEpmf;skv}+t6JUx)N6>aA?{`}eVxhFL@}C7J)BKS*0&IzYLNHOskv48j8BgQ0Qmwy zPE`TI*SmW-cZZhb<%n<_qtf^eP+r7ktfC1ws3ziVgj;hPh`f@kEyah{^#8&m)9~Tj zY)XG%N^g9ge##TOhR#;+IHHuVYoQ4M`AwW%AE{h&vwh;@r)XAz zc$+!W$A#$RjujKU)bK=0T}I!v!>qi&jkt@ux{D3xm)ly(VJt7>8P2zYA8TuK76+H? zXd`M_gC1JOeG~wE0$sRUpsmQ@+dA5bH+c}^xE43x1J9_a1t;s*idAR5+D>D;TgEH^DIU?BC{nJzSE$>LnHj7#BczxDX}r9+45m8^qjzW5e^ax2Z zrke1Dv*OnKL}%On1>}FfSa2^aY?01Sy(%}V)CR_fZdVmp`uQLfdRgrp4`tg#Uu~Vw z0}h<#@YSARgB%#e<-Du96C zeV%ygIY`8KR6v_ONM!X^&>sK)0qyUnfi57|fG*t{Bzo5`;_z?hAb8GZAPzTjbGQu? zMWAL)5f9VM!62^_Xg_!GSrBn;O%N&zu7n>f)FBCu+X2tMA+X5;H2->mCJzzn@R$p~ zo}yJl#H8Nn|Kl(~8vYnVdFS&NxPh`4)4z1jpgT7R{XaQ3p*B4_RK#Tj08eeb_j6g0 z=I~zL?x&}E`nha)zIr)4f=Y*qK--%6bZDr!X&p%ihlygQyVX2VQZ41*J#`!1RdmZ} z+B94wCL94;+%3v-kGalgt}s_rHalG$E=I?ULl*O@zy|%AC(BCBL>G?`#djH%V!LSg zzf^i1lyC%c_!v0Kr3|>|g~CU|k%e*$V)1KK`L#IvunGSXs3ahu9<_xL!`z^)ne z=rCFD5eMT!T74dy;mH7cCG(xFOvbFQWOq z4OF-3NviXJ=xnu>jD0|?w)%et=bQOJ=hLYaIYHzE{fafA;rN_D_fHVHjri4M6kqRQ zX;QY@QttmGh<>&E^m-+SFE-}$YaX;~f*24Jhz{r8EL(!mUAi|_p8nKoqF9Qc#u)B< zXzxVfkl!QgaWs%!>XaZGsE3=YHU!zp6}oHQTuhB7iD!9e)d~U_&4Cib4x6vlfK4o& znIuwUmI7%tjTTji8->hay8mI=U{Dlv>&`|u;e$_S35N2iGvOdVeV!JUifqiImX@G}s^vSkr@PZx!pFP#=o7Y(=} zUn1Xp+CE*3;hJwuCi$qy;tx#fu$Mn7-r*0QO{Q9pi43FZbxR5!6ILteaWJ)?A(FU? zMb~aMIl7Q0%n<3F=CP&&PRa|R*(%NFF|i0!Y4;+`lxLbLJyoUo*o&`gG98>DrnBv5 z9){{z7wrE%t0NsPr?HQV)K>Q+vksBv>FT8l^5$!xtFkDSYlc3wV5XRsT+X@(ySL-jDWnaB z&$x#g=OJc^asCy{EV$Lq5;@+`=z|c4b@wb0>0fHNAzSF;ERh#d%Bz4m=>Gzo?mW7H z@(M-6ELDK@yI#94(J`ojtR9|(PPYov1O#1b*nWOmK+6k7&wx@3#*L2@A0I+j3bCQP zaS=T-Tjb>3tuW@*s)ws5(s!xftnMbdx~jD9t42syw8p(Fee`iUKU<7(uolmO$vj-Y zdG>!tLW8mup;cmxVjZtC->J7>pNDJnO-oC(xOTpkWN7z}07;UUiF>^&LU(Ft0 z{E7z66;VuTUMQPDGv|t)se0Kk!&Dh_ey)UvkNx4%d2>YzzQ4qf$EP7VtLcG723wnb zQ=@$hy?80^cF|Z4;~vjb_U3R4X;roZEuJSF$xq@lpF!q6dlu=6esVjA;9k~wqMvPB zBsHEd?6S-<+s_$t{Sr(?Z61Z{^5{`;9V>KuZh)bn{|-*Yn%&cgdLSD6LtLpEuUw;D z^YzrjwqlbhR6buUvi){9Vj+k|3GexV*Me||LaYvR17u2IVVz&Hdx3b#!}o~Zw@ajl z7mIqC_}CFb^wdL^^3IU4%&$yBw4#HKU#FdmMWfih=tS;_lbC!Vn(wPTum3}}o)pBx z#2#9{wEjskoB06$IyIMamWY1!^oVx;0(}j(>tUkQ5tz>>0Fs5>cXLZVS|VaS`sOR& z(Madya`cqj)2{$4>*ND&eHcEXtZ<{(DptxzA!E7M&cU|C>14ErgHPXT3%6jn;K0wS zB{Ov*D0u-kOMRW9D_5}xCkT=&amSS? znOa%p5wDKBd&IkP6-d{BySa*AoT7#ICFDIjha#7XxwelM(ekC(j(&i)FBKh|cY6}* z9)inYxrC^{Pz`Z#c{mIQd=7soPO{I12NWMypT7qy#Hjr85$dFK2DN@p#NFM*`6ynm z^szKEMxiTO!rr;OgA290G}-Q}TM}NiC78ucSrzB0#8c(_*%bR9k$ew#y|Vy%dOiSf zoL2*I0|2fv3QxF4;r{`6g9hx$fT{I=L_)B0sGfRk`#3hOWZZwmPAgwF`#hAP)wK6{ z@lp#6NteGbRm9R%qh2I+Lojcu4++yGlhaO|Oc#;f#cI9wob_aQ$uA_rYz%JQl}iv21T19Xxs`>AA#+btq^^^766^8ba90U zx5kxty(HjmoS=T%K6{vky(|XU);(OZ^<~lC8c<|t#usN&@T;Pr^2MQF%a9uHsxN`qpWtUTM+Q7-@s;^7tR0 zN~czeuMLKTL%^#gb+?(3puAqMsOU*L0y!o@QznHRQKV>Bf}j;6rDDH)DVHqA4N+)|>+w8ypIyAfc2 zC5#Fd45+r3w7t5`WAIOyXr*kpIPov=yWOdR!T&=Ab*eRe>q8}vt%0FXqS8dJ)NRaI z#m0=J9M!1A$E|Ov5ZMr!tJ#SSleqhvLh_XIVn5HFvya{V=#Pu1K6mrb1z&uB3E-^bBbV(b96YOWd$60~S#6R3an@g?#E zy6tS1_u0ljqXEQqYg0aOx8rEqCm+++4I-sZ3Q$vda&OP`-pBOF2GKa8?d_jlR>fcC zY07KlU#HWkjba{?lPLQ?^bHs!_syHM`+bq(jU&gf=rhBoqQR-YG~#{HltEhW1kx=- zs&uy-B-HzwK-S)by@?FmNgauQEdab+sYn|O8Qj*hNkrK`m`KYviFui5-#932XJGZH zKm7`2niMum2or-gynT9+I(#6S#Wn*ZR@jbXphM9xBhS1G^!x{+FL&41=&rw~m0bBi zEVNl)rkR`J2!u9nKYxdA!+7y5G`H~tG$!u0mN@kdIa#LdnisnvV(Tj(312$&k*G!S zABh+Sy!=jp-BYb5z!5b9o?(pkxko5vi)hY2S>ZhJ2o2jJ^1_~&c7+z<-_XtfL+iJQ z@Sv;-c*WZaAsklG*(@TO&TN4LC1zbT_EY@+D?ZI>uZnrQ8mp(LtD$=OxE$)~A3Mv^w9kz=4$=_hNk5`AgOuK%H6@`0dve24d z;@m1ithVcA^x7w)jqPk1o%%#bYZOIn6RSgWRB>KMd%Bt}e&-c8H1AptuLzJ%W(YZ?eED$^1+lw{jTro#IQj z-7TekJ4N&4_gShz>b<6(p01VZ>Fs(&Jw0%nLBlW5!(Fg}W%Tg-6!vpW0!{crEKMGx zvT2Du5@}v^4p;AZh40}SqKaE_*ZP;DBtf`yWVxT2Dkrz!!5Gt;lY)cJJ$dMSBY;#~4;GDo$u|&4zjmNlJ$! zgH!2Ht5EN-@@l(vP7=FBV>ky7-6i7tq3S2@RCVg@RkN!gSM33yoKC|$_HyqG@NUsO zKD35@KS7Ww;q==s(K4*08Uo!*ntm;^tT_BW^cykUdu`4Y`XGmPeIsOgePqqVKOb$# za6i+G;%*IP?^vqyt+;7hzp|vxcVdGzZR!**pqKlTP3Z}y^mw}by=WN>-+cBWj}5bw z4fr&hT9=CCpdO}dUFpG6(biTr1~;|~m+kX0G-$WT2_9mc*hJa42htn6wc(W+b~gR7 zTPzCudUDnIG=moG5&evLer*z++9TAoe-mZ)Poi-@h`GrRq7Vn#XWe<60l*YuJ%)mQ z6vrBsF>^e78p_4Qf^4k2vyXnC|0uMrN39T7;5x;|+MDl#^TOaffFrA-myas9>oh&K zSM>2#KQ_|LpRvPzZm;lTt!@}_fhiVwbsf)f9XR`<>iFUgbqv&X)TTK5RQkn4dgEuYshL756t!~XByI^)cmY&d57^|F zPQ-~@kQeVV9D6pO!|ka2Ey?+dh(ko#b-#$-YzOoquYIC!C{p@f3EmX;b}gmseWD`P z{K-PS78yt*_lf)1PX2R$Q1A?GC+Dh-)j%scxKEo$Uk9d=V)lzv+nI@!w_mj7a%;KV z=-bO-_kF*}=MndX4e{CpI<;RstQ+5hhW@JihnGbs-TkwB0zLDq=&7?f=;W`Wvrc2* z`GBaKhPoP}E~8skxr?6an_qre| z4~k)lMe_mi2yWppVPCNZ>M(&0?Gw>)Ff9Xq0cLbEqROFe1&!AeAap=s$E#M(jSS_X ziaw}-5h-a7XDo$&jERR6H(nxw#vy#v_q zA5{C_u`&06A(>EPx@Wn$<3ZYWSfpn@zyi|E2*#SyqmVWWyGV*TA_jZKzGR&H2!BbP z`v|-+0stUk55jm#E0@>H4#No$bIJW9$p5GqR_l+_s_#D@L9>pEQ^|}ei@9&{)b>Z$mQdbF@k;j4 zCRb<@{+WfGha~)ir6DN)towOJJw05f@iaFAx8s}=)A{7Xv!_J7XYuKLAA0YU_|pq~ zd+@z<^Q=gu&rgdHo-p^}G{A4-97|FwC7coS`Q2d>XK}3J+!?WnKfFpe&Wcp}@^>+m zzs}^Z-|&Y{{9(Qq-evT`u~E^1zBwn#3d`Ytp*?Q`Tvt?Do5}w&y)Uas`?>y5X+E0d z=lZ=OzmMy*>HUd{{O}hty+5SVY_|7t{i@#=svp0oA6&7YYi~sXAJ?9W0=};ARa)Em zzcJ+VK#BtWoFICp;4dcP9L2Ybr1?@-+9ro z)(Wgmn2L9Riur!1-^Nm-3!=VP8caeb=;(5<2zum#NQ=eFq!!H1Hdj_}bY5F{_Op?3 zwx=_fHeC>@kqoE8CDpx7+BBBVUl8x%9K1y-fUU?Yd*ECKy&s zJ~5^LtI}Fw*{ssq&*p=Qw3llm(q^I>PAC5qcO_x48O@IO05bMR0Up57Esr} zL^~swyhE;fwEiz_Ra#mrShdM|NkrRl5B$i#qppbQR%`2$!+(o5 zR<>mg1?N3FTw8f3QNwcaU!FS`%7qGe#hu5RPdgRx%GbHQC)N2!G{Q|PJ^v9+DmGEa zYxxs0n#Os^v@Gaox~GQsgy|c6?F1^|ZARWv=Fv0)c3c}pr~ZLa;$Ld)uWPjZIEMbb zCe$syBUxCut6V!uRaw8H%4|iG2hBIK1gG z5aP+#o!qhPgUCkkf+0xmK zUbM=1FQEL{PRxZeRvMUzvjy}S3jit;{RU!_rX8sxd+c) z_&4%&r=H$2F=8mpe#0P?L9}Z3j(C@`8DtnV!)bwcC6;5VU}<422L`>YKxhn?Q??JV3a0)( zvZb#ZtD*F=k4)D{ec>aUCXGdjG5BYMM&UV9L0}F3h-C^V(D7(}}uANu_9L4Srd+(lXjx&!+*0KD9_`+R{ zZRpWJ*|u}`a2{%wOkS>LrgUSK*4k48Q(CArL@1tS_Wx`D67L|{)hdfDmKM&X`>+OL zJriUNl2$7cR=qh;*s)v)aY$F*ABx6}*Hmd?M$DN@8ab!tL?xb zYE(z&rF}Dq8>k!gl}c;IwbS(eQ(B)QqdX?}xl+>FH*}TN>RZw?Nyb@Q2dPZDGJloU zmHC+7dz#)`Razr`^M0IL4)BYyz1^F3Cd)&ipWub|XtcThi?p`;jVt*o1uQspg8Hh# zkFWR&b4gu!Ji~7Kn5ojdcCfk9RhrLH*j%Ydt1&LUhZ?2HcSFkVt8DonNDn?85=ma^ zvRUI&7`vR?v8~hh+ARV{P)pbyU}TBNhS+y}__lQDmiFbzuupM%$QE34E$erE=2P6W z*#My(9`aHLbcas!VvbV8&K=uO-W%oFa;NglXkVVB%a;wC;dR^5FKE~4GPAI*ldm#h zU1dX4;0w2Ao(elKk=jgZfDqn@@QNGEEVJu6KU#&|aZD@^n2U^eYI__07;Q#GsndMx z|1Hl`I?tQtJcVxH3<#B$wRy+Kc|0J0!>i^@raZ6_qq3&z1l;rgmgjw4+0%E=aD zm1F#gF-GmK@?IsgxIcT5tDf8v`$7^V)yxfM*Y9n-!!e{a6=uq)CLCyBR+Z05DxQ~z zvw#TuQtvQ$E@AY@;h=@5(v~>9O9?u;|cig(= z1I^O+Ef$XR0dOwJv5mzam&T#1+H#lWmk+}G6cxY??>pih_M|XEWtI~@dMxsB>&G{G(taT~)J{XiOdUhuOktTF?0oRRReEk)_h^nXBjrPZFAvZx zaRr|Gc2@)hbI8GgGuZ-EUWGnGy5XM4ZS`8j z(7L`p0k(ZTD7c|)&Ar&Yp^U9H1Z#gZn&+09JpF=cMnm~%FAr3)9gYFXvk|z@Tty92 z;6%Tx6ovfmDWG~PE~hH3F6lvU)R%d^4mYR~Zc$BhU>o56h5Tl?e`i;PJGuuo%aWaY zepoZy(wZj0i-7x0HMphK;O5ih#n0SuC~NGSK)F3Jw0_e!+U`l#|p=m&EzJsC#C~y zSU#8zxSvZ+2R=Ub1=#&*pmVs1o(|WV$nCZJyBnmaEI-7#YQLs3+iS3dNjW8OH>;`8 zIljkJ-*Y~*J9Tr&L4oVtU*0pm;KGd?&18#EM7kJmwY<;5cEo!~Q>%xP6Fs{`m(z2z zTh-UVU0jch~>%91>7hq}=}{5sZo;5$0>ADN?HZ|hbvC0oW@ zeRb&T9~#i}IdVwdSm!R-m-&1+$KIY{Hqb%YJqb|}}RVL1o*9%tu-0FD8Fdhi|jcal_;TU?!g|05LT!UL=d z|1PeHfB)Kt-e@g@sdt{t@GKgRPA$xn(eXvY-R)v_KF3$LYc<-%?0jRMtlOe^xVv2{ z2k!sjb}5FB0nx(X_ex=a*5F&w@G-#@(ppBNrs+8J&f?%ZAdBgz8(|U$Z<-rn5(lqU zyssh-ifa-F^ZMK-4#3HkI4EU3qNLfC`YaBryxh>NDjB47#r%Wy6NjLWH^fb~`SN`q zwujBy;7i-{^rRt~l{p|Ez+5!A1bW|O?s>O)=I$?mqV=F%(eEg6jf>`Iao_fm?_;?P=M>C=IVf?Tz*_FRZ)0LZTH}wuL%z8&G?h z5tIyFnW3_hwv;kE$g#e$`+TK~FQjbn@ zs_i%yC!OT>s`)&0K6tNomIr+_4|tZ=bdf{B0v5hdg#{=B*$7w@_zV%V0BClK1;DN9 zZh6|aeI4a>m7*gSsu|96(ALretxI;6&HQ0!l6AMY#d`_Zh>G>hr%aBlfcg&;$uXEn zPLUDc0XMv13+UKz59g(?OEz?s4Xnu)=R|m%b9ipTYmr_WWO*;^B6QL#(r2vZ+Usa~Q?kBQrv-)^k&y zAIRTgrSA901Zx33c#oWh%TQ0=Bkuv{%_`Lp$Z@tWX3$)~ z^}G;WsQO2IaFn~ZEcUM$>mSh$8r2r=JC#WhI4g`8mAi$wb8qSWK0Og z$33^OgZB0p^wS_%PP$R{VA;IE>uFe+VMUQV8(wT~t<(Z%b4zrXlieH5OPvK>(W=lj zDG>qfHREN{pyJhG@wImYjC)#^TDAo_V@ll`IpQ7+kwp#A1D~M>j>9&3EZm5V!bo|z z8h>$#bgUHo4u`1{0TppPeTW<%7}rgAR1BV4!TO>d-8)oHN!W!uxwT%QSFya2e38Wg z0A9dV+341n>Bdm$sNKqp8Af-(_iin2VLS34BA;#eFQ~l=!mEzj@}0D6h#cp)$X(k4 zU0Y*XGh9BK;HUwwd)+w^`iAksS-}x zJ4&9$HR>OamJK{HvUk(P(J~sFrT$}NT%a-3V57ZD8jg{{)}&GkylsBoQI(OZC4eH= zAR0VYN+wb!?CxC@3k@pAR`6B)|Be4EwEICBZd=oa4vocxuq0yO5?xCuZJaFj#4ot2 zjRW)SOA+Jc-Nxq}8arOD2kf8D{A9DRm+Nnp_I6#y z^Ai3mn4~)@=4x1F4c2|Pa`5(>Ami&`ANiH-;0{nj;^4nE(8;UOqIW1?(jO{dKhWn4nY zWKl;S{EH|R*BC=rq22GNEgFF$0%; ztubwwB$s-Aoey%39`Bt_6DG?99}JJxS=^YGPKGY>JjG0rt$d&!!dg6&?w=xu^YM}? zvPB^4jLL+Z=)xt%56P*%c*A`+hUPpZGio17(sOW|AEqys1V5F5mFCZF5gn9)3RUNY z@O6j{-|>j1@`q$fyvmle4gClE!_nq?o8VIvA8zra=2K;gpM|5F*j(2e(XgpfD#-|HJZKuU(J09aXHK((Y+8G4R#a8WrWIa%6N| zC(nu;uj(8#%sG0r3A@W{ZbcUCzySyo+BCU^V}SCnB)T|F_Vr4y$d#zx+pgu&!s)VG zt?;+q9xsr&tVkWtqf^u6s9Kj@RXt%o&!a()%E!X?81LQrU!yaR%Hd&~jMr`rZvox^ zm>eJee6`o3@^Cia*H@C?4B3vCLfvP`xR}bNh}8=rim~Ke1*JP#FGUh)Un(WrvJuJVgH3*wLOd`mIog(i4TU0o^rA zwg`K(S~j@%&XVK978|eKy@lJe3h{bewbwbcxKIwR-L2Z|I<2nIbLY|oWzLq_?lrpy z*6h3nQ|(6w&cT|8JFsxJUbC;5Ez@d6R|E80OWHFVWBt#YRmXZ)OX@sF4ytvi+WU7~ z(nok7wxim6DBpAC!0@%zUQdIfd)m7eE?|93HV#`{?JL?mkK0`BHQGE+4i4{D?R6c% zQiPK^U$vQ6YIkh&e7BuqhOCpUhg>b2ra{<6R)c#gm-f#`Q~z08tqXFwsom&>1v0eO zp=uxB#m5D5T-YbZdpB`BOHCKb(P68M*Y44sOzRfP8DX=G*Y4cVF&3c%23LFSpiPSa zq`-LX1`Kj!X^JNb8S}aFJ?l<0} zuyF$TtsMGpv78XL+4$zJZ!zLy%ZXtxR(m~`zI{?Y#j5Q#EPh$FeTYUbk*Q&$s%30O zFD{XJ;Kdq^pYsRu*O*S2RS}wOOpG1#6BO67$Ttgm6hG*ocfFk4Wvv=ZH zo47wiy;!}dQlS_KwYj=N@kIeE6e(f748ZPwNue{(g0VHO_SysXyo^@@n$v`xVdsxjRn0v0u@rN^x+nCrAYn z6}#4)7XC-}hW+efiL#&7vQ^8mr#aPMCI>~HT5TFhx9+m3IlZz>E)Dyy@y*@QPf@}1 zavr_@f(*4nt9xE937ceOajy+wG$r|VSb^~x`ZJ3#OqCbpv|5SAYd63P&FF&{%r710Z8Mc{yt?B&Ba!ZnCZYuk=I#+0Uwd~{Qt5={QEhh0Q81N+HYh~}f zDjy2#ZoGEakw}+cl~dq)jP{pj(1evT2ebICm00*E9yd-Ni7Epp6AN z2YynO5|>mf2D)A?2RFP>yMln#daHT0Vxy}SYhJQ!HMZVuzY)Fmx@?_*RYC~VgX%^a zunAr@-hAD(kieQTiqh7|zL95My`8o{gx?7VCuN!S{VEvd>ckMe|qt4nStGh?QcVbOsoLv>3RU^E($0I2Yg2svk7NAB*aU! z{T(?tJ*gtEhbsZ;>o1#n-%a3OH>3{hAlnZc-`qX;UPJm|om|?=wXFIwnO9rhu2SqJ z>Bf1xzD4>SqdX6e8#c~?yenUAlne7eZ!oV0W`@l!Nd-R4a29R6L`GUIALdz{OE%KI z@5u>i(<-X)a7{(}o*Jrvqf}=@&HpoQsTrby%JK#~a z;dVUEZqRuA46$X5{q*shueFh;Ht4R4z|2OHqY4Yi_5sY zEt|L?`!MhwqrQPxaWk7`(~)~DY@GzFNTS9YWl!6$3AAvdyn=fKX1*_<#UbvXO)|>s z2gen{_T<^%#u3@Ij5)5ut1(AkNs~9pyRo6Nb(2i&{j9BgHgBZ9V0S{zEls`}>a>K; zSSNgK7l&*>pcY`3+-iMkJ{XnvhOkhSBGn{y6(woSPQ z{8v2@<%C_2O18i!Y1_TF+SW(u=?|nUwm5T+#hGaJJ3AEH48Lb6pJ?#51P+i6}&Q&;j-ibquNRv47+xdT&ge z@Q7S|iLdMMbGb7gP$rEtn`LcVbS=8IS;jUZo9aw%{^#hu`q%?A#(U&*ZOYRyS=4wx zXJbzaT!)@XT|Sbrg|AjE7iBKD!c=aBDu>Pb95%bTJ*9CEF)V1_7!pNSYpcTIJ5?)i zSZ#u}TEQx^JkZG5#kfm==LiG)>!usndsTs5gf3A5>}?aUw-xc1S&EvHV~dP!SyHv! zAyc`b8%>12(IEUv$CliZ1zV(tHF6LTuRiH7i;`FVD}!ypdjZfeL+xosA8nPftd4Dk zg#kWo{tI@O&{ekxbku4k3Z{Y*CUhvDHAD?neVMO%6*@VG}Gs3om*|@ZBI1ECA^O*vbuRFs?HNyxn!3gkC{9_3?tA+)i zp1yDq8E7dlJc?5!W+1i9KtfDFLNt({{1s0DLeMU|0|>Y)JFuEzSj{lPO)$bWjIkAn z_!T;jb_5W($#85MGmtU}@?_0Fi-tv+fJA8^?^hs#-e?UNZ2<#Z!VKfE8AhB5Mx2Jx z@ufneOK_7#a{$4n7Yj-=knhYu5=}r7HISthh`^870T}SUISQMw8OFzE7^x;0g{c|{ z+iO<>&@qg4mHX+j!NY)9!heb}ej9*N+`Te91A*N&mnj;SQ3;2QkedK&wI8;PEiIkL z-P;BnRghuvI`cEYdI7Ks`52@kw5*PXh$iYQe|;l66%JwkXwhOv?;7aP^lPvav}U%q z^CVi}6`%jZC@A4OLH(ZxdM!DbilY>ey_R~h5LdV!#pI#p*T@jy8jgbhTT3O@%C1g$?HyTlb>{lY60 zMlxNcb>zQXq_r=68Z|m7M|j0KS4qb%(IaasN3PNKIoLq15W6^ksGI z^Joe_B>Vdp8HdcGY4Rc2n1&pYUR)6PACj%9?3DhA<7|iIxOx@2_X`|pfn4*#;)&I8 zPpo^At(MyJ!T9FCltzmV%cK^?^FNGro`m37h~4y^N3xx7Ko33+d)X=XF_2)R#8bY` zH1KtmFF%J4AC?ihBOtNn9|(1xgioaUfJ?}hRs--4)+VaTViSNPIpjDZn{g{7x57?i z&tbpjk5kf@-{H=)BT~f!=L2oy1x+|Dqk>0w#1U6-*K%MwAT^h|9F@(un@&g3yN9s! ze$e4a^#9C{L)&^e_eRloM`fBn_FjCjANlx(o^<1=%;yo?1(2!K{+R3+e6_aoB*cqC z-O`fYJ_eibwoLls7<^-VGwJLxnaAkh#PxBlOOL0AkIONCN#}(u7OLb9>g4Hog24^2apGnsqqrZLipQQVLm$}sBbS3WlX!q|jy4iTs zxVFu8&bGAv$&7rWf&6D_&h`fKD|2bfX&GC;HWOc=#s?9^R$Q;za1Id<^or-(ThOi3 zvVY1rc(56xG#csZBXBc?9{WvB<53S_)YZJK%Vbs_L3wB7K%?Jrx6~P#78GCE?<;fY zhclXBKBZRYQ1shFn9>JN$!IRWK7t1QF2@_?asCl)55C9L_IWw<_wTZi4Y+2Vl_|mI zwhhUlfoEl>Aj+!5A5n|W!d)yY1+U!hVhxn}? zT|Xxq`;_u*xmKI<&S45EgcGi4gwNEbS%1h;RQ#v(GD^1Kl98dsBMK|bLM8xFGu~bSfrbCY`zoQICcB8GBZ4?{?wVD)R`6EPWwyCh3QoA zm%PtF@9TQ>#$Ot}9-LXBmq(eGWO_hZ@{hjG6p-^r^=ZH*?Z3tI8S(5d>5Rb|zTaiI zWdP~xwdj?WjwtGMS%&%!Y2kbgWvA27%bKZi(av17Hhp|qTL8YHpuY_wG{*F!T9k98 zk_i219R@pixM?swa_NUFdhRY@01D@asL$WBp5Kwy&S9waLME;$maUCeZqK0a{+4aI zi`(id`^TgIW_EIfQ_>|Zn;W_>K50rHGo=rk(g#fGeWtY1irjVm zfcK!|;Jrso+XUF;`9~W{CgVb6-JHR+<{CQgH@NXZ#{OE5e!5oKaqH5l&UM*^J5JDp z*L8_F+H_sk^Q{-=oQoqoL?^GyJpWQd0~kx~0Vpr>eV$F5fU0PNP;gjlyd}>6x3dz*|9jj`rS^>Hek32OQ2}s5OMVZpplWidv7R zQMX%0O~XU!yr(0Jw%@|URK_Gb(sG1g0n$@ACGH32j4_X~}GqLXrp{-U&TTXrvLf$qN|+Uq;{BbOrM$!oyL|Z>p~0RyuX?a8wZM?z;4hheP!_(Du+JT2q=QN*qXb zz6M{yE$MWxXJreXrk6c+6+!fer$aH2Yr)ja3pmwIS52NqBfTndf<*Rm+{dVY9!$aB zx)mFP>0WP?cu8LhaDAoLkT__r-?Mu$B`aToV-%&FK5%}d7sL5e2my* zKDr%$>*!HX#r9N@Tz8$U6K>iB?8 zSfvew0tU@YQ420<4NwhB@>Po2zPfZMpt50ar(nC!(S;#o1<{~ukV@cyft3BX458vc zhaV4i41F936#k>R;4=Cn(2?g~Y)q2T)HKM^#-~V4l0aPc>?qJbeh#FaL1=Ah@^n4D zFhhdOB{4&S9i4UNHG%X@u%p0Rfx!$3cBBR=XP!%X2r)@Q9C_Mff}4IcnYx8II_dm~ zS`gxBqth^(hG0~t>;C#Wl_EncN9AR@Kh)76_{%Wo0u0$G#HHJr)RI<&Iyx10WV!BU zIPFa70#iEAl+HD!TbR;KP3cCaw8NCPo6?y&%~44cUFoI|sit(2DV< z)tIs2j=D@H*wYAij4(28N}`*{$RAozL2W%{aK%Aw#{;Yhe1kE3m~Pa*eKc|-9DQVb za^+~mn9`9*S8u?&DB2p~P}cR2{Yge@2+N)INgz5Iq4sv@_2^~FP>jHl}a&{oEEWO2?YgQAk(sy>}z%qXfq|TAAYT;=cIUmnLL5+VVKP?TbCZ#&q)( z$g(uU(bX8)YYCKIPm|>=Urm;a>uIt?KO{Pa1r!;L{y2e`k-d_qvImEI!cRuJIu^dv zGs!WA`xN{yN%svx^Cdef6#D@*HrbKS7#{SYca!yKeeJ^wk5~##adb6Q-Z&bWqBFkY zV^aP5AD5wlSj)feUPV7e7gHP$NcU3n*ZA8F3Nx@6A2CqtkB{-f{L>s-lIrM*8~!RA zv(S{DhjjIZ!LgvOV=6ZcLtR%lERw#e>qv)S3bZJtb19YAtrScns31)XrW4+J^&jK~ zo%7=~hceIXq4o8keV$8mL>Mv}A(7H6%O_FK^ePjbX@#CmcXUeLg;pA)@CDM5fT^?1S`RhMuegy=x|dx8dmKCITEuQM}0@0+=}JRr00>;}i*`)HPL}Ttnp_)}p1E z4rPavN$%OJ4Uu{9D{@rZ{i2&{O(yj;2_94+<2b+aesNr-m^ za;+yVlweCkv|^D;o1`O`jx=<58I$sI4D+;3dOi6t4qHP;tD*>Q??5-K)Fltc(N0HY zH>{6gjy9;*NT6p>#xPTQuql0?Dc#?cz8C50l=Md^ZEc{%#0?LU4fS+A>p_n+bYvK8 za&#QnB)rTzg4vZB90Q>u8&)CTVkY0LMvhJq$6^1hUeRN;xRFEc4=*HZQxJ_>;5Kcn zhY=gRjUDQ)HCAIjqwUQdwP|l-hn)$hqb|_(IL19K3xt#3L=#R^>e{5T)B-LQPNhv8 zf=j_-)l`d^D>mxf6l3CM`cvr9rj@f0w?H>_^j5;fMzPJ@!o^0znpM)Uhlc!1GYxqm z`8C%J0%$j{MBp=8-vS8y*xVr)UPlEli}oe6@;Qqcni^+d-J+6R!fxBbVK>QB)s1Ic zI6Adz%sPmh7dJ4ag(+R%l+G}v>(bEaLw7jFNMCuKGC=sYi~MAsehT zAV(>qM>N$*TAWkaH?R-o=-D%y3#+Bm1R9%*30IcFQJHSRnnL?-+q?F7DV<(2Vm= zAzBU0i|yE)KHZN-7dVu$_z(^4z+){PDZUEhZ*Ee-2{iMG7j(rY?TYS^~2%+4K-hwY4h~A7ymp$c!#AXzrmb+=+pbbMdlp@wxlXR3GGNn-D;v_@ zkq}m?V->NE)$k1NE=WK#?sK}Wh( zHC=Ec`f~AYR`E}3su7;xJjN)%W=(f=+oP^wnhBv_x>t$Jm+DY#4|Q*i)^mxObt+J=NA(@SWl7dj$c%z_6BHY(NwTO3?Hvls5FAN@P-J4IqLq)`bT z9Of3M={EI)EUj#5|Bga%61UObUTR3q8r2f(P-!o#ZhaF(Stply$u%`I?9vV^G%h5)N`0h#q55*7Z`hm;K$Ktm~y@P|_%GP!{Du zN#ot1EXsqD#=AjTlt(}Y(ei$35RT_nIcS)D1Be`nJu>>K^_0!H zPotmuP|qNYM#Jj~9;24mQz4=%vTs=}$8T|PWv&9e05d4fH??lk zs(QY4+0nMY+D7r}LWldSk>OV}(c5!a2KT`Mv*e=V)UoNMlrm8DlLsS6fZD!}eKfAe zVL)Rv`E{Xj1Jv-k6FchXfR$GP;1eeR`wRd+D)ee&(ZXTSpQ$$aW6>I*2Gy~T-%5yK zUC4c)8WHAewCG6yT*{Y}M0NwfiB15gm;leZJGStz zoxyR`a~>|q5rb4$ILovi1bHAID5Uj6+=G=}?)35?wS^py2nTALupk5aE$o$tJ3+5+ zB2cHMgVi>&N@EABkzoNw?|wk`+ojd}<0Nwm zZjHdCSqUilPEht-t-2xJ@~m%6M~0|tE`lnz(9 zT1bBgUOI=e75xGn7dOLkF&2T)932XmmCJ%i;lc)cWo1Aw)U(0#UO@7#^ZHVADQq8K}$|)Hhed+2GE(LIg zq7&(AfM=p!W`gpe+oUu{h7uGVtq-Q0Kf=ZF#&-6DQY5e+>mM2L=^a*b3SFbSnz;}28iEPCb%ltSneeoLb8ClJ3FB|nYMAMr8uGb=QFCR1b3i_XVt*IaJRKj8Tj_PIZl}z z$0=h>yZgAnTxe=2C^S(Ddh!$8BQ8Rud(tmg#b@?H9D zI>!60$Ezdq=v{hfhB^dmPT`Dm!7Wy*XpiF-DSoEzTK> zwb($Sx%TFa#ae89x8AW98{bVyFlQ_Tq`7KT^Sn&^!h7y|1-VyY0a~C<_W~AjomvK4 z=3I4x-%_XKVU^vlK{fo3B=F0Ntve(Q)+ghk@M6*1><7c zJT+Fcj|)G5Y3&529l-oBzB;Y8-lpU8)Mo?pozfTGMmTeKTGA-6CB5{V8o@)PfQYiMHi}LYaen-M@X9I(Tgok$9M}7C!u0@Y7 zQN3MG+Ym#i@Le^=2j?`bz~8Uq>b)gusQg6!?j=}L>OF%@Y=xML{|Fr2G@Od;b{!0} z7uDujS0$_o9y71gPXgyCu^$KK)G|jgkETKP&B>De$J>Coyv=$eBNq?qh1MkhBCUImzeLN5JM4-pjVcu zLpy*Al;T9vB7do%RBEM{!XJDV%pe(woy)WRA(=+j)l<>z)bVxn`LKwegBpDv7ph)B zyrEo~8o#7IoLC96sNe=|bjv(v%$Z`A=%n1=;gRm>FV>lc zFIRiC;O=CCdL@S?!z8u=9CjaKFG^BF{nR4}d&Y-$vy=3q8Ist+lNQ~ zgfV##$A64~;BI;ZNL{!WW(DItNH02wNJ;1-lW}^N>l6huSyXnIap@tbXhkDzRlFAm zOp*88ndEZzm)$^xL%Zn^!bKSBuBz| zkfkfs$T&YvbvmSJiMAcQ;5Xg)3Emn*FNk zt$h3sEqPU)9%mxc4UI8ELgH`(_sNPLQ)E9C-IyA!QRCSRvPPZb5~NcaonE7kN;rAi zVL0$;#M#Tjju;LocNE_$heIEv<8Ws-kLJ&#Y4Tb%GTs;tX$a(1gaeL_!(ko|2Uyxl zfhxYk7ft|d!ZFOvS68sS|~ zX0A4mgJV!#H>F`<{7?jioXh3b(Z8>$y=(=UEvWnJs+N@#bv;~9g$LuA zCf6z1Cbj+$P2ivc#zx!F4tjljE5NsOMQXhj-$rIjeVq$u)x zLmi$q3j8^>P_<9|h}`qwLvB*`%g0+IN&#xJfrn;ZO@w8OUCnR~2yxionFn5pnjKm6 z2Cj8zqW&hnF`4+7>-9`U$L3qDJ6Dpn-pQ1{iNKKJ+l&jBf`rQv4fMOREE

UPmmWi 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%0AReXG= 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

#BhW^S^Zy1MbDf>32|oc2s3@mLBn!r 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 z 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⋘?!`DVwm%7)ji0&I2CW_^`oP4YLXJ&kN$~M2beYL9}k%p)}?T7yy{|h z{s#_D%*Oj^@b<>ubiI!Hkgdyg)ifs_#$h1ZzVB;i(x`fBpc42o&8er3m%-ZbW}wH# z^s;n6a0{mMfNh4d$r$keDZIT$-H-$j95;~?K=3EDBS9S)m<2?2g0BL>(Q)?4(#0_N zGComVY3=48bT+Y~n^SsoH+`vnebv=Fst@!jT}RXTp@{hb7xe0@L00i{n6&!pc-CVt zl0y=tsKX_SOHzZ}eIdwL+;BKE`~2(FJ4uc4ffGbYQzxzW!E&owfeAiEE0WZj0bkX_ zdlD8i$za~`JT(jzUcKo|k{TJ2Yce&^@?eLx7J}@pe--Cf*Suy*tMT@-%8*82J)%_p|FQls7!lpXuuS@!ZyjS+6PcD9h_(y=lm$;dC zdatAoX=-ieEd)YKQ-cD>2Wx9l;0Y@%mYcyU((c6 z2jzM@y7Y@0PVJhj4Mxp;AJw4M@nvZ~o#M7yAg$CjdmG=C=4%JrXIcaTB-ZIJsVefiqW#yS6QO9sjvs}F*rYA z%xLqL6NVX=`q!Eo3dMJHprh*R6oGNc!nj=SsCHIrwV`^Q)I3CE!hA9|xeoaWi|BeM zwN3v)z?{`Ys|p4T3-UUJXi>n>f=zB%ahR6G*u(>ymKE4IGdAGiXRxV%y`_Q7V0x!B z_$-ySbXGgrW9_U%c3sqz@T>6HoP|L+fd!OL2iIa(YdZ*ayU>6xYIE13k(Pn0*@ZTD zQAcw~zpiR>Om*PA76%emoUu75$otw!Yhj@vxU?wj*BaX9vwzXz>bYJ@yVkU*t9m6H zn@?A0UBz~azTuqz9*>SWe;q5mwj0g}v(^lCZRvtJc{lHBfOZ}2GF{fNY6`maLAesp zq_`tA8QobqT8o7(<_2isWQ>yTMn3}UL2=J8$nzJ$mm^pA6>#5{a>qV^-!ad5U_0h5IUi^ z+DurCGw-a2LOTXzR-uuO11%8TrlKQCewZNB%z>&x?v;>TTwJ?t6)!13Mvv`Hw^op5dg!NHBs2!m#2i)Q; z17;Dw;P(AemI04<#Pvs|nO8Tj7 zmDc$b*I$i+LejUt8lbD$r_C90Lrtb+6Z*$5I2s=LO|*MQu`GB(=|DPTted3Do+h^K zNZ0$T9r(Gs0csr=nDNmNmU3?zH$e4wUH}s-YoNd45_Vus+B`t@4cL$OZ#*G9vAr$D zO2EpJJ|j$Nba?;-2rdW?R2#4qUjr$QOLqg++RjN9KsRaYI}YA7XP`Pe70q~Q2YD-) zQ|J_jxb#&T{6=%-QD588xOOBnNNH z?!%x4nQN_T=`B=`9huU9+Yeh6q%)FLrDgFoVF0`lP8eU_b^HiIQdH$;-z2Y)L z7P1dS>V1@)tt@iAYB^Y+KFC(!CSR$VM&u~Ih)S85qaZA9GD}4{ki=1mD^|qM^m>kx z5)`Q>wXwVe@jS42z6UFDnjU%~N9h$L)WHBE3uLrXplIVq-9{^I15Tjdj95m!Rt6+7 zZH&^ucHlmGYm^d}*~%E35@5bW$2_u%vy>=PbLH&! z;2y?b)?9;&nV37{UN8T6mJ%6mHQ=a$|02sM;QwJI37z~Ep^{3fI*ILtaJ`cw|E-e) z^iFp8#K=&ylZQ}a@sa=T3bA zShNZd{{Xj!rH)s+M5f1ToAE3^YjXr1lqE@)ibHHcu=voL@k&Qqo}JE)=Sgb^3HfV0 z#7@L~n4kpMI(4E}6BO-SJ(Cg~x10b{qIA+}67FUaJ`L%>1SQ!P*opp_pbU;r*9axL z6`&4iXL+gTChSLOx_cns#8?4hQ;68NlF*`b)u4toIkK;T4U~1%Q+R^WS1vlv|!(ytPHL@DAOdW z+AU*?CM#WAVA6L~tsr3bgYDF#;ue8-R7*REG>uCeyrWqr*`_G>`RLvAXF6Jx8C{=7 zPEoqp#CF;=MQPilh-FB@@FAQKFJS0Zzmsw732oq{J$ z3$p{z6nL8f9A}y`*?`~IfZvDSo~Ed-pY+45x;jmXp!D4Ou2lGGU02%!8Mx6BYA6gB zxsNLuRM2W1)1npPG4+l*g3B)M_6Ou{62BPi=k@5?ccJlc61A zhUeQYk?P=<;ALO{+W&bCY58NY2sBiGLh@ROLmcmJ9b(_n+Q*b&q<>jky3$ZRf%Job z!xG`6+A+a&@k!tAu2#>%?r}lX<#DBrft(&T&sB8daitsoA21VGxk&wII$;H)#8^2` zi;&7{-vTVJ&M=>SMf+zeX{~-mcb_R6poRbc#G+UVh*HQ8; zB|RXLO^nrY3R*V{w)uv%W|k6;*S=X;;t*kGDNjY@)lpqrK(Bxvy&l%ZVX%johyBOX z6Hh2woNzwvIIKIp`-GBRw;&Bu5gXyVb>GvrPbx=X3B2pRG*y>}BLA^`W0a zTPyU@Y$d{$u$IoxR+`#G8U;V4vJ=Js@<=iQey3c)+6*E+*C`jZ{8kK5Boqcz${B`0EqLb!5nn(RZ5uyQw^Md<|u7l zBGtZhXb!p$gD1WwM5-CdmY1-)F%7g84_*UDzsA*9cOhAyR#NMu;`OMwHH2(zQPSi= zqJh0yQ3#_^W>I5ZO{RrUE9piDGHH9N@Uh;c2DwV3%0)3*AO0KECs%0;z@E)j<|INL z!h(-gvtWEE9;Ocks~eSa5mXs)A&`{z9B(8~NphXt9N}3;=P8Xmj7dVv@|5A$8;;9) zijUR0({X36;$gMo0-5>BFZJ_{4j0-FwpTG^^Rd$s+ksjwP$pqNW8(s)GjCtpo6&Cz zVCPsvK?{+g$x^y+p%TJhY|Uu=LPfhd3gOHb!e&!%DIH#@TYErZ@hf~JFjWHSzj!9N zm1btpHzeIo+{AH>dO_@l`;5}rZm1g%twdj;Zk&#U7y$`|C9`ns{bnzxf@hQ{SLhi# z>Ets?M00Ffl;pUm>2KYjOsw)u&``E#WrIs%3YeOG3Tqy4+za&VLSfG;?VACA<&d+A z$66}RL8-U`h8zd&BL_>3Ehd`0c|^l2rbAnGA1!=VY37e+%X2X~=YwD~OUO&3Y_WO@2@N$jRZI2(cYu(=sir8!x~h7f#;WfD zI`Dyrq<)JPH&e{v{FP$d25dmAu~f7KUbGDeOfVqA*nq&s&JB8fF+h2j4lRbQJ=&MP zS*)a3CzAIP<+!bVd-{5b@@ya+6V1JCknOAXBCCp!pwBBIb?dj+iAA{{MP=*rO1>K? zj(1b)xKv3<#ZSIvrp&NM5oQ5j6?{Gk+qGbp=c4e2v4bHtd|pzDvG$pCBBI(-7{=fy zv{V@!^an%6pfj5`xbE+^B>OKB}+2P z4bA9GzS1D5Z!K{BMs-!?UEiw~OOQGYw+h5S;?A_-bd9PsZwh}L5P?Lsbk7aKnuauz zrn0w{Impc8Ih-r=__mqU^hG7ESz+dfNh-S^#=xM#?uVLbt&`>sfmU>r=7?=tg-ms_TI2v>bYM z!SUL4qC$NYwLu0kWu1Kc^Py&Kn#l%DSLS{G|HzxWTuF0j30ik(xf0;rzO6o$;8{`8 zPY*a-v0O=Q%6*SA`W}ll3#L*IhBC@jRm&{u`GP87PtB+kM6+H}QaxQNE2NHVA|mOB zmy{uHFtgQ{)b3>^oVjv2#`!}SS7%Vx%Ze7yVk1%pX3*)Eb*hJGelIKXK4j$&sgTmx zlVxEY!?_Amh>c%?7%ZsPS6LW5^4cO%UAI>COtJJI`3I z9o&MHei49h1|+$2V=EbUp*cknkbw03b*|rSd5r45qJ$4W^DJBKsy2-`vi0wJmGw_s zv0Iv|Pkabj3YK=ZpPIn-2C!_bXX_VcV5Rk|)G(jEL33YGf0e*0-@Pr_%!~l~lGE@hZ(u*XcEH z)x>~a$6;cw_2LCqSG`5=tW>mXbHD^z_DQFoRw}_h-&p>p44j2<20?QS2ME)vgP@Y{ zweV%JlTws0oxf_KQ-3H; zXv$i}y>3TUcX+VUmGbx?ie8PagH4Vmt6?qkuCIW8)pF>eogr42 zW7aYGDg)`NT(&t@)ny9~;E33cSV0DGMicCJW;*EUF2v@99Sjidi2P{~vqF30RPtE| zJ^{>ov7qbXg$>jC1?}*g z-_7vWrVC3KFy@vD#1#wIjk+ftOV=qcy0pgh1&0j=2Gdj3sbG5W{Hm7rXw5VPH5eO7 z%0&pqr(4p9ZSZ(`X`@maE7W7yH8+n%VNeR~{d7|m=1ieBXQ;Wm2&C_rLYZPUEQG*Ylus-M7fqEfB$256vLt9f_6YR*DJ(*x9+bM_`SCu+=Dy?wOB z>jAnG4cn|l>wXGa=W#aXd&<}fOU0X;m3p>Jtz+Tz)n?@+X3W@FZN}u!j`g7(Ta*RW z3qHyP6Kr3%U}S{T!mY|*4Li>VGj-}-<-WrkJ}U0ZEKs6NTGVS}B`pHpaeCl#oLyiJ zX+7Qeb`6Xk)G=xhFILwnYMau*Hl&3EjkmMfJas4>@4Tt>wOV)3@NG(j!~PbwiLJf# ze|GMGbZ7gsIYS%kxKoIIKil9`YPCywy1|8Za4^JU5*c&3&T*XFg?u<5_W3(XZrF5W z8Sk9UIMGzMxnuQiCD{tIFXwAuL7rP+ZI#s-`Bu=lcd=794<>N7BwW>98oqv4ncoId z4=*VFN_Ja8SRmNTG6dp>OEO1g-vqs|y`dM5f&9UHSS*5-lj>0Hu0kETi{5p>E$0fI zb13~nF*6!LG}e6Ad8b?RWwEM@sLy-Q8G1lqdQW-KF4W}0YKYFaHw!Xlg?vn1`k-xi zPz#NYU&Ni`&<=7S-;_Z^D1mIw4m%(g`MP}LqQ1ROe6vRhNBw^Pcm2UMcaM^V zyq9)>wjt;X6OIht`(6-x4=f%FK=c+|jH9T%rXb{^K6-DvCs0?Gb6sD$+*8;8+^=3v z^`F`c>;4S-eXr8gH9s>wm16fPIF0o@_1p(>;jxyAi%{7rkzZz0pP}#eD~f9&^N$Y>C=Dq309=bMCeh>r2A@Hu2dihY z<2J~W1Im}l*Ku43^|LXk6!o*JR#KyW_qCPlwa{Fz9+(+LIoJKj=b#c4?hMUUHlFB` zhL$_+pwh$^+>{*!&*KXD{)gbW@iD!ANEz>XH3yv?nE(&6-iMXIs78>Liu(c`8`Agm zfg>QVA$}MwoHO^Z(!*LxA0NhQzDmEN$cPzLEPpPOU$FdRdkpf)(i9)Q1NmIJy^4II zwn}}Kt+~wde@_AV#BY=3YXlN&faPU+;)vqq-4}WZFWeIB2tG%C=i(!1`w^u_J#4pV z>XS>sqmPm8L#18r>rYh|O|)I~eht<0;CM_EO*p4BoUworyw`-YE5nI3&k|oXIH3_S zoU0j5{H_6KHPK|>he}VDp1Z)qt-O<^;(78r3PH`%9HhXtAae(`JF2v55aENX?tuw& z>#l61PF2RxqN7S;v``}-*BycQ!)Szr<;>>khyf|o^n?=Zx7MK9+MQTO()V1ZJ7|hS z1dj%x;?wU;s5&6`F(tMMAUO3V`iG1-Wwpm_eJ<-%XvEB}q|lSclr{k2>|;6zoKxGd zohjCaE9*59mCqz9YII-_ zJ%x|99+FlcR|Ztti&8#Pd;+#D#9#xY5`d~X62Z-O@JC9I2L0;Sj^=OZO9N~i-3 zkZZ%*BD(XDGKz<$D~9GAhW&9G_pv!NZUyo!dhuhWRhav~G}5mnEk3G9Ag0cLw9=s^ zk4+;Np?*UToX|&O6cATzATFULJ##`IjXlsJ!A)u(4HM5T>GTPu4Z8O6jC)6;#Nb8$ zP?JxTezu4@H2V`n=Wwy9L9gGSyHEygn#D-awojDSaM78-x-ib3GqHzUch&xBfJUG> ztGVzzK2=&b1v-&+9b^j5x{hVu^n0>Gh{pO!uvAd=r`QUb-Hx956vWm|&|9A>X*{mE z*XksPV?=fPan)&tBiLjw<<0$~yvEV==5t=&H14DluH~hycGltVSRV7z$vE@`N4=bSZ8h1aj8FSI$v)}Y zE;`$GT+|`2^5F8dan=GCO!XWPm^G)Bt~`bpPAe%bPNLF-hVHWp;F@EInE(sZJ!4p8 z%!GK>&wEDDlV3o}g}VKP@*bz8N6@q{A$%LdJ8lGOFCMH9@3vXhhZl&<-&h@y`8>Qm z-T@+^|FNOlge-y)iS=wCveMdcZkUcp1jGGG2}3w^%+o8M>w5(Azf!sc#4yg%fHN3> zbI>K=j3%6hx~CbdT+}(Ms_>&tbl}J5YrTRNUt@RXHckCnNwR<09B8`!^cTP24OY9W z2yab{hAzjde;ytBT6vI<=Ibmss$e9=eFG!;kj6CP8)dw$V`Dn;jdI%7Kbcm4t29aw zY76-NnCjUfUUzGC8CM&wVBRt8sFqRxHMSu7=UXKjB_dG5iQ-^)LZ>*jmGDvA8>RwC zW`D^}z?xn}pVOT0^i8R>RrW5f9p>WnX>n*E2VVGIX~qKx($w7brkVacsoyJYJ#b## z#fnn|pMMX{8Qvskl#B#D?a5gw=^&v<9voOrEBwMPS!iM3YGMx2j#{Y#=M7i=Pt{hoZuK7e;%aJtY zyy8l~mMgE|QUWbu?Kx$E>+D_FqFh@J@0(Y(R0p!{wz@5Wm^6=?T!d}6p`QDZi^}u1 zYq6Tv?C||rdCltfv%~Iuh>zbHO7-ZS}C$+y}N%0KrvC9Ez_oieLB@Fg00 z1tN11i?*kJQ^v$0BuZHt<^x<~${^gZGh1md&G!<*rd}w%Mxh3@_6ii-E-{X`t|$-K zU@wD2SPH>D!=R;DhlTb}W7wL)ri#0NK!hIshcZCV`3`a(s$y3~_BO3JC*u8Fi0 zX0pOM(~;{lj1^Y4X~0*hGM84R$2=^?%x1VT>AE46&$p@XP{SLB=4 zxednfhNJnP%1Z9{R1{oSg~B5Hd+~JkF9Xr!^EV7*x+Uu`a7(sJwEtUcFpbMq4P}vi zOJMbKh!gp@;vOi}cm@rDa+nQckgnPvqM!a!619=!2K0;o#k*$4*ATGL1jVuD4)!;Z zYX>AsCt6-;@9j~Qt6F_4IHzIdU&jN{TmDPVIml^R`GDj?`)I3E&a-!whJJGrnB;gC zEH~bZUiKCtwuH!c;>AR(Each!4qEDM<2;357sp!P^B}3kWX^%a{uIkI)qW<(kwU(I; zn^mlJ70HmolF+cz@E6%5TG!SvV5*^$)>>O5h`TGA=aysBvjk_K|1{pE zIB$Ffzu~Y7zi{`0ANV)!%jDm`YkBy7z&ZuzEAzM&e4*vxTPfTME^2xBN?Z4WAD!}? z(DLY)znnGld=+=gzmj{K3~`3zcXzSYmiuj_TI#S=u-;a>4^qenAmm4!MstIkx@;+r zCXAPusjxXzJDdSSP|<=SKeZfnjK+*8M;)c81Ktc(GXixy{V#Pmd_9Gy6;}2~64JMV zm=wXv?nv+wK74>+5KD7DdY~(4Cq?#DeG83&If$9b_QzrM#LjN((9wArX;HKV)!7XigcHz+{79tn$Z%h~lX*YiJyP)#BdjV1?!FP`FL-}(_yudz=fCKH)mdFy!qh!3gi0%ertGeD_CiKU*@^qTC>{J-4n_x=z7eJJ;x0;AXUNN&BDIiD!XD%i~#a zlhd?yJCB3l@od&?i{r z+d9{w2_Zrkgs>UYU@>pT#CROT3_J!|$Ppr@g98nD1>NwNqcOC(OmjX;qqI=b*u4l0 zS-pUu`${M+3>7{$uTaN|Q1LxZP&uZCiDGMVdc0Z+4IrD>AS-%MtN8o|C~A>LQPJqx z=c*&A@1ON!Xk&yB*1sK}M~EeiU%W#dk41`btJf=0w`d2RO?b{mi-vA2v}b5J=&LC4 zcRdpo#lh-A`Y~FxxBf!jF(QIe?BW~ib_ag1vD&%>Io^sDzgTT20;ztCh;+OcCyK1L z`;7m#BnVe)WdDY@=n*_4@c_*Lxud!cxUsJdRu|u)pPGwEt$E0mjYX_A`E~>@9zb6A zTJkr)gNwzT>i~RGt0St;7y1={D+twu(*i}5H(ZaZ_TVYRQ>_@9K0_Ibh|*f_su%fC zh>H#TBkLo0M%Gefaa9q-(U9V9Lo0HH;_;~^ce|?G8!54=xEr}M{1$zL=L0-7!TIGc z4HND>5D)m%q$Kf6@)+csgJ(u9`Pck)FD6!Lbwt%QFyZP?zcm(N^l39uoa~1>8smwo zrLLZ})YV0+D;|3^JDXwH?aAUy^ZjAB=u14G-~s%F#z;a{3s!Ibslii~hLM3UcMFUt z0wlB$mzqyRsReju*HU^@Ev4ab(o!T?y)*zEJ6mGjTBp*<6w$(Z+hJ`bCRlMWtfaLF zsGG&hDYO-?zPi&|=v!CN^?m16E(t&db9-xH$9d>#B_>uYacyq(5-r+@ttnj^+@go@ z48X(OcZl)si}xTreehI6#=%r|7WuUmEo^6f=(F}BiYoTC^>R#Ui^X7Dt|f&z^4p12 ztF43f->a-%!iCT9fLluYQ^h?VaL?24sUpQ1NeLYUyH`~}{$N7zSF#=es}wu?%=b!< zSXEfXpg6Tx8>@7>gP6)E$h9R`WVdus8{gK$(3tUDaIHv3G2J#`Dt+Bi#8?pssH14_ z+J35`0OOXEG;zQcw|ev@pLEgR`UYjCix~f_mD`%w>SQbL26{PNvwEh{aTm}ATe6t z98%KBsvbIam&|U$fgy!`j=05c!Q`GPG6QVfg9b-WJ9DV+CKtgOM0FV6n3&3qT zU;_54D`vyDaumST=viJG&F&-`*n~H&=p?$j{Ql?-x-!o-*y>F;JBeXzO`eBQvIVAB zY^UL!MXb%&o91;Et$F;<*00-y$~z0+27?(DA-HW0?oq}O3M~i&j@Nb(9E2gUi_n}V zCwCEj0{V#ww~s|cu*Q_tC? z`a@TdSPhJ@BV2JUU|a@q?;;|t{j0;V=iwS~91Pasm>+J!;adqu->7=YIuxh8{u_#< ze}Q6%4ux&M7d7o7G~2O;j<}j&SfX_>u7sIjJVkT6>*!c>qd_wL-W|wj?+k|Hsb2W* z@@K{kIy*VJfy=dw8_U-mYG{3%ZuAk?TyBom{;fO76Ft^~n`xfrP5MHL*+N-;#elk< zj88aRH9w|>4Oa*K(N|2eg?dtUKXD%-ChY7d2G}N#Cinhgg!LPGxWDLT>oS_&>MsU? z;=0{0(yT;X?iWecv-H^gVvr|dlElH*l)LLVeRaQxsyCr|1r^6y)x>5M#;IdI!YH~W z`3D$BU0`jw-pN)iUWJ$WZMJdfI?s)k4GPSmXu4us zmBR^^!ozXg68dbQ2(~2!(D{KP-g=U}9}qb%19Nor;5O3-L^Hng)M z&x4+RNQ~v&W01SpNB6y5PB$JBy{rc*W4N(Ehl?KZJx76~Xg28f>Xm11FzqWe_x?&i z6_yBV2>cn`vP5rNdV3m> zCA!#7xRK`|(W~a*_rh+OHu%qxJzKPMEzDxODg)$S2~e8qSXg_P{d9m}3(ZE4Bh~wF z8}K|xQ%4Ey8r>l@^+-sFt%V!zaTP&-FsDjIFFv4?ZPoREdzR4~t+yfw{wM6~hiUE`ZY|91Nk@pp&2U}LOq27y`g+Y9eJ zLqnKrXc?^#{qpz8RfsWd9AJ#&#c}Iisu&N(I^NM>0_07XN09UGlZxFI;-W=Na^yV< z$;~gstiU+c^a;H@QBct3Nlx{~>NjJqrHn~pzTa`DPb}8sNdF|U#D8s#LTh5nmh4nlT*b$>(`VuT?Ei;(?lJd z1lc$ZNozSN#CE@xo}4azvSm-Cp)-VH^Rd!1GsFo5`{U0jIPNj=f%P})|Cm{Rjibxs zBEZ^qQ{7v%A5STe`!?P{t|m_cxtier)6X}nr$O-l4rwouI#YzWbhX@aY?~>(t$pr8 z;fIZihSgHhGqqGS7ip;wqs*CK;$>^X{lDUHdqTKa+x}VS7Wo-o-KBSDi^cwrAi;!{;f%OT z_dg~6^oy&J{+(m^9O&jL-+SDm-|<|;Q?t4`o*3$*-mC zz6&?$@mk6@`Nt8NClqUnf`7KVvXdke^S9Ru{!>b8pX5Ce2hpR zeX};`PaMn;@5Xhjkyq4`_a{dWm92H((%ctCtjn_%H)+B_rGew%i^A9Hzu@7je(+ed zsi4y3VxIppn@KMNi6njQzQLX@_Sh<^Yg8d{2}dpS304E^_?tWLF1$ zC*64+=>5J%@(Z+RwOHf#R*mFrYP&{^^nbBNa@U(wutvOS9Y^b4!^8+R0eNbzcs26s z0vOGMKzGf2(nnv^4l(J4V^(-6@;h2w4PNa$J#4ta1vjGG6z4YBWG1Bjstm?q8 zrXK6X$k5NsWFz;y8whC!nO*4lv{-Y>kgP7T1)?ExrtmX4IyY3o- zRL|RdFk=CIzCi@oTHm1a8$`DMm>Q+SZqU#-#F(J&W;)t6*VAA0)f-|*oe<-bcEH_= zIlNJPQRkacI{11b6v0hmK^XiNYKEx*cP->I=6yE{J_&f}4Zw0gZur zHf|OPb?aY8Phpxs;8KpU-F=Jj_0Kk1F>O4-*J=C~F~YBFjr2e1yDb>D*!P{xkkTj z6HnTD-=XnuitL~+Wd@!)`jO0jBnf zThLmY?-Rl{Zu{#0 zv2Ox>dqi}%HNH$SAByF+Q5JH1D7w1kxu}gMlI^JI)Y#&t`cK4eI3fvX{v0^%2i#OS zG{@>jjd3*bC`OMoTNBNlmit)*%ja(JNl66q*bPUh zNhjg?fU~kEMVbFMpWrjByd`X3g(T4f+tWd#QSo)E@$giNG-;3dmLbXU0 zx-mo#M!(L?XjJpS1)6k5O!A*wBR%B;{l@88HPVBS{|E83Uk5YYXz+Ks^Mjb|*U(Hh zs)rBZk4V0Ae|6v?Ui}E_bf!i!PDlPEmiz58lMM{Otaujk{4-{<(PX>x^!-_}*MC5b zbdU42sTiESwV7_fa*2XU#3{eK{j1{_ChQXEOrMy^@Y7+m=hD$qF|g4n#LLA#xibp4 zn>meov#3LvIOYGCnQTDan`IVyD6O%iHb03( zx^WJ&#;tzUQHOTf0Z1&@ zG=sKY6fOKR%x^|@*vq{ro??1ccQj42Jsx`B1f!(YV`zZjfHE{3NS+lD#N$J4a(vPklCH**^(z}mVjHi!Li=_Y-1Uv+?& zl=65`*x1HR>Dyu<{rA<#Fu9bzzAZiro^Pfz5jBp>wJN2(6=GyuEwd-f%x-`XR7#Vs zipK-eYNTH)xk$J`+;*a2xa`^}Hrt^jmru{TvKT^#!KV(kl=O@S5o9m2VQ!-d|GYb)lWG zW-7Xc=3W=E{(a5bjb6Bv(7V^M=33N9zu<_w0rnMiuD1b=6OuqGZ;A(NTVY4d+(zw~ z8#l!c|Ch~VW2}1=)9PE|nTXkkst@)z%x=J&IMNFhUKXML*=9+j!r)>We_IUo>sBKj zYRYYKD#*u7c7hf%euWs-Xt%ExvDTR$T<%qU=0FGkQ+(23FPO+4JiBXrMx2|!#Ot{h zH5!4hhc&kpjXGnkc-7dlJ`ADrG$^~>1!v~*E&FVSc66P8XPre1J=Ea(7o5souvUzMb&})KW&d75!*aRdOVtbSb}oFysqhuEVeFlm4PUEXcB6CITTW$f znPpwn?q=D)tQFqQJzhcI{Uz*!T~$9bhl{NmN}hGD-6OLKB_1}TTg}z=+%4{vSM{>9 zsQ=%>p6jL_L3Cp+LqPQm6JH%Gu&r^$;HM;tF}y!v{cJ*TA&Rw9bzxwd-D`#&T>Jc zPwz_NivBInb9$b5T!94%CX2@;S9|kWu;;?I?DI`@Uf^<=Wi1K=5V2I2mrzN75#v8&TIDR81hv13H`0a z!?PxEx`NKY#r|}Y4zTQszxRd%wu{Pgm>@~~@WC+t4^4)F-} z{^Uns+K{9_)#F|5vC4g}E}Y|POYaCexX9g=rtI}~4 z1qZn{=CvRn7knuSQ?tA{Qnq>0+NEF?ZdsLSA@!P85Mmwe%y7Z&Ig{b;;S0~7S&8(G zi|m=p!C)|5pAN9R^b!U?4_-l*za#X!Q=O{n`u%Og($hz?^dMi6Z{aWIN;P;OHXVKq7DTZ4S`=9}@M ze7MC!eqoy)Kwo>vy|&H)^kN;kx=DB3Im7BlN4)iWd+QW*!ta_|#`iR&u597jAp_GP z+BYx=S3AixtAozfm2G{3u;MvV1qal3Er8dUr;NB3U)!E%*compsw={}|-uXeiN*Eft^F$j^0g{%|9|R(B(P z@#Hn46Q0s1+JfWs*yQ{*9NreKQDu^);xMLMrjh;&Rd~t=Z8$$Nz)RYrVu1C`XvCaF zk-Vmez-GDaD8}y$Hs%%Ar{!KUuB}#HwnHYwS8rHBc?f}941toPR_ZaNqY8`yn9kT> zMS3~DPodwvWMUl<4B%*bV~VdQ6_0}e#v8V`D#jki<#edN4Dg=)eHEGdkUl@;7DPAe%NBv32B~xTie;zezlb{c z$XDSH_nnXYJfMw=tMIV-%~O=8stc~q*zYSdy$W;AWN5r4`z(3-$wAhqD9caAMYmB| zLwI684uJz+E~qh}s?3}G`wd((axA;~UegboA!yxG{<4ux zzDDcuw(GSvsadODNq#mex!^CG;HC_}0C@^F#*zTJ*=yd{x5y3A$~Ics)AB&M#iMWm zuGXvfDP;!9IR8S6cF$g2ty6sc+6sCiNG`GY_>p_C?ANim`q_hE#h8IsIM89i6`E=g z-;EPL5D^`!eEWh6Zq zBA<4vqn_^pxiV5VAQ(^rZPR*^XQ*r#T$nkkjas%tpNqwKm%N=`agsWO%9Sp4)J=}> zLS=!~UF#06fD4nUgD{WY0GBG;rUfQ9`sPxQ%?AiADQeje*zhKx9-g@yuvoUi<$LUyyczexoVa*}&f zKwq+q>W9h(wZn{v9u4KnHqmN!cL1RI_Qa?c20?r=P8w% zrW~ZmNZAyjS^GrF*K?y)yHh2b{>MtLe}I{9G`#YEEOWuB%=0Ld#mBpGV?~9PjfwB4 zYS5Mp!_24w@pmXl=|gRSwr*d;$6PK*Y@@O~##e1Kx8Rd2C->ZjcTRKFi$c8_$O{l_629f+2pM*Dqgw(nHg;27DYo+~Pg9%NMZe2o0m`XUX9 zm1BbQduH9+`3v+_tju*?{?;vAxhSNao@gXv^sK%$@Ki`U8_AaTYZ(~diH z=5YCi+QH`@*duvL(hV9_kDA(L7)8g)aJ?R#m+(ml9pBGU|2RxpC7V{o$v&XUyzGyI zD(?fu-Hm!SEOJ^z%t0SB{|w^!h-IgmTquWJqOcUiflFqsCUv+#K#=9%6Zeq6b z(XrZ*)KqJQWBAmDqu*(}BKrh*stwTyv+Ni|PS3=Ri~Gr2$iBFuces!Po8`r*Ghs&5 zRu+>^mS@d{1$ODQuz-Dc^+PHVvW5F(u5$n#NR;I{u&DwF;V z)`u9@6#BlY3~e2)KG#_zQAHNO<_*|P5`{&N_@4KWC=IS*3|C{?o+!O+?pcoM3tbrq2Hbra$&+6i@31{f}kNp$v`s+cm=0|1>?F zB=@;t%J(@+9h=D{SNz0n$Iav|c9&`{7c{iASBqhL)8v};>MN-0_vD!@JNomgdK6RS zQ!JxL$Bnz4{5=g#maDvO?S!fbPpV7{4lyUo=7|@p60``Fd`TnpheAv5cy%3%COG87 z$~Z>>olC=8$W9(_K$uyMCux?wp=;XbfV^mtdm#PLLaqR>n%+|O!PWI<>bEWB40|~k zzyd(+!BCIIx(C#=p(C2>9$W7zvL9~7#(RP+cvPU9@aQT%>t`)7O<96P;2?VEkBXIXf21> z;)P0hF6AD=>{IZB)@htAvfN+NE(WC!UMsQ?Ws}D-?|~a7aoQTO@%st z>x=XOcp$8@O~lXn8!V0-y4qE52vl5fcCVL;fZ&5ICX0>%1p;$ zc`mahRh`R<8KU|!MdT^)3R&CBz`)*(ReKGzzCcad%f!|}>ZS-j`@l*-dPOmZXwQT0 zARw|uLFUg*ub2y6$4uufr80Es4lQjjySdW0m^Q^{t%0_bQ}kPVxfec?9XiNZ`ZQHe zu@2|o?fmjDTx_p?glo6!T&|-Q`#!gd(mNoy{+13hwE;|bS1pj;Scl+EBqo6DTsNHV zbdV8kEEo%j+NC%Sw+2Qh^LMdGzf)E(@3gBW@5OUKq^m#s7#O!YBLCmizoUH6dYlS6 zLL7Pv*KEnC2ET0Pg9jj;kR>>CwC4P2QAd+snvAgJwWg#rOt1KNXmOfU74U-J1ng$dev zIY@K6$_XCpm_bFib6o2xCt2$sjM17XgE*M8Hijm5m(3dEt_oa&J6}g+G2SK5rdRCP zfnZEP8ml|}W=-XIcbSM&4mY~Xm_|i823#*8qbcWc#w@1-?R!Y!nyh;Ertv-GyVmPu z?5t0v%e@+bjj?P$hu?TGm?z2iLLe zegpsTs@n4rE^P+>765;aUNETy;wCW}$rH$@w`}Z*Yb4vK2s=RpbD!g>9kf_>ueEeJ8ki zp6VG#EBi_>_a*qZWCE>j9}r9j`^p%PKy|Gp?dx>1cfk^`*AFDI$YP0BKWncE0{J|X z2lTAQba4u~x*&jAT*R|@-P;<|)yi~587IM}uyXcysy6$za?80Kh(!M{V7&2)hw=!f z11lChAf)=d_R+ndCq9}gL^u4_NR$=Zcl~7F4!T8Jr~zno9V;rPI5j0g(^E8)STsVz zf~se9*SMHwI$8&|h4}sbW$UmHlPWYb>RjWq8AEN*X*$tgX7cHf`(>|=W=o$!>-+z0 zDfTqIH9&^Y_WNac*eV>}DFZlJMtf}5#dK`xdzwn`mzmyUdH38fs=m)#^9|{~0kUyx zp*~Z+=^}eoCyVUWJE^Jb+{qtl`v95Hz=2LO4$}2TwZJqR@EPYl2FUid_>V~$2y(W7 zrVf;?n=RgYlWaH}4LL;%9$g#@zQmEYi$k=F9!e2M!sJP@$6zch3aJ-OMZuxo^kYc9 zfY4T_4XOqs99x#pe}pc1V5@4%a+d~<9uLS6E4vX4l7zchDhA07ksBehunfK&?@BA8 zvDKLQ5$zo;PuF(^L@bq*LbqwPk5)Y>J2tQwC%D8Pmt|~yO*`gC&kd1r9;4$`%Ro%9QG;!Pbq{bRzzh$&ZuLWH z(R%;EE{#`%PObNkbE&`X7I|&(Pl2P*x}l(`IG!?8egG@b&SA3o2t-iphQ(%tSh2I( zEF0-+GZu3+FLI2QzQLxO-z}PsF4W;Q%N54nQ*OoGfKXf5aT@xN9O4Ssk~ZXcNM?s< z-m7|?T1@(UyTwDz7=X_BzGDrxE@C^ z<@z<3K*KQ_I!bQLEnI+YfGCUWr3@J0FT_Hufe_pU)M+E)Ch%p`5HfU!9!PO#VI4HT zbw#(&AARlgGqyMX_`u>m!47`900(IoSlnyYr;5Rglsv)I~S^z zNhBVjb=OnE>DO#IxobYNdR_jiGFn=;g2`d#&6B7f3nd+NKM6(%X1N@j`y3WdF@&I! z31Byn2~lB=)LgD|WU{EW$}?N^D#Kxw$Z^T6;CD8B2}aAF)_wHwXc-fmZ*uqdkk{ny zoG+^?f5B+^KI5u4Y4Aj{3*Q1kW7Y zZORlY`Y`#Ak!?e2?NsM2ls!hqh37NVXHNmPUX_4$XgnDI!#8047&#Qy%sXRbc!Oh% zS4gb$T`g)cK5JPq!3wGQSQ+3tawY6MYcm5wY1CNR3xqb zHWLP!36IGBHv4)y@CZb`N%Y+#u&QKJ-Epw0M75$p<79XDdg=@mpy;9garE&xhzfV{ zZ%JPoI!<=R$ASDY-I@@(VuB2Wk-7hP%ndm0jh7kiV$^2%dQgip8l%3`sY+bXY#R59 z3xLsGb=eNOR9WK=tw#4Y{cloP4z2cSuF$9n(tl!%dbed&-3$K5x=+7(vl5<}|6`e> zD8uTst@#o9XM)`9kHy~(WlIL6SIh%F%*3{v<5B3>%jv#}G9(6{GhvGdu@0RIT$?OMHoli~96=F= zQmeme6+Ssd_N+Jk1E^ph<0gS-mLe*eA{((-Kc#XLvi(Idr-BI2PMCSOC31>35`86w%IUG634Z(P^?h-(o*q z<~A4$ZS(>#Uk~fdc?;(zt(*>E1L(kX8Bzz{5WIuAhkl$c2iP9EP02H4Qu0B>UV$`u z6f)1o=(_581hcCPrrKm(8}%1Zk@x$+2D6S;Sc9GC1<>*tGR4;FHl3IuyNXc2Z-w^NWT~%qqwmA?<6|S9wBR zoQ_2^401lC@L^6GHs4R~imFN>2lDS22p=}=c^LT1*Tf;#iH_9Q9G;m{JFwj~s;*`C zf@ZwJeAI=1pZ&<)H+|1$7&oYBCP>jXL}QXUw(Ml;IZL*5aaZ4`xwBv=?S@X3bfWua z!7~2kEE$Y1>l~M7$sX2WEF`#JvV>a(VqNEBU8{!x)>(_kgsi$%X;Bv2rK}K)*cEgS zyz%2S(A-nj$}W{a$YIb+ucTKX>ISqHcl9=@Ps)?lBpNvzEC~tIQ1QYQOHLn+eDja9 z7Pko*?wTNwzcDX~*36cJfDd&9Rm_&c=L}2y-LSt6V=;ej@sx~hDAo3;;T%MXIEWIc zL9DB+LDKZ64&FCfXSXS zyR8WHq9{vW@I|A2Xz|nXJ{&Xs?rFKi{jWS^3#C7&$gubvRA)*Fw;@tHNePw3vweu^ z1p*{|l`CgM#O|LbL!zEsbBiK?pW>Mr6(wMUrEB1Kz4|5{@r1bn%KNi z5w>wl&Ki~pyh|>mSG+=gb7hj(^G+pt&6RyXu~*K8iWb`o^K>wG+Z4E7n>MdySSXG+-ngy-q96aZE)jx35@!3MT z+KREdwR)FRmo z+&mAyRp<=3bd2hT=1hw_xcNQGKRQ#y+Q<6y?8wz4FAB^xIMy@8$*A)>Fv~GB~7&S5i4jY2rWLT&mYDnuO}zwxN8cRzA2^FfNfd+5~cCogjA{(u2WE>mY;3oxDSLmdOy?Ev;92(=^tCkfGU?t>3kjE zFVp^f*X}O$7M5Klnyp=yeM<6i|L8w@`A13Rmy%zZt-JQ zFX_9e-(2s&6)R--27kiZUhLux9QqVo(0=n4vKQQAvR1&*jMyP7 z<0vtKv|v(WqG8it&w-NQTEH zsy{hpw}C2VLN6~tb>AZ0_@5?|Y+JYMdw|I!z2bdpzReay$4I6&3WI6KRpTF7U<`K1 zC;JcvG1Jx38Z-gjw5Y?{Q2Z-07Q$Q4S7bN~ZzbUw6))4oS7aNTr4em@MT!nB)m}|- zjVf%a7Hoo;RcWjVnHPAncHcLAlo)mKs`EHV?ypMitmbCT5Hj&qn7GD~ z+iNm5Y!ooh=gms~!qUXN)eh0;HB$$+rp(u5ni~u@?F;Cc*RWdm(Dv8l09>JAeO-3+ zK+jXufY#LYbs5E^A{$jh|9V}9rB%Y?I~1e~J5ePqAX!0D&BS2_mZCDfZqNegzUM)N z4q?9^M5u5q>R|8&e?Z4xm(2r;GU4CInaiO|x?vZl>2Kt@T8^vg?N>BswT$(uM{qdx z)QoVnZMAHYcy|R>3lcOtA)IfDcUXAu>MDESAL8xHBd}5fTgKki8u^HM>=0KauaOV& ze=eBOXXvXnGSjorG=&}{`&!xCcP-q2oWN3P&RRI7RvsaKowl!)9X%`ivxIJ}l>>9p znR1j$y>gq1-v&mow|6(!Z|mJ$|E(N_y#!-51aO}N+#6v{JhudJFT?XTzNMvC-0%Di zgua+SUbs(fI_Udxo!IiOZ^>TTb-UVD6;l=Jw?WpSqIJ>>USjAUTUq-ap!4fsHvmCc zFZ+gfgQE=3gi)}2W#M+(dR1toZR=&C_~&IOyiNxUGc6URSncU3kbwd>_3xk>9m!>b zj1PPxK(!+fE%H~>lL`Gq z*FwjS8{{#YXQ4UaKgJbVm;x45hbe#+)RE3?!W6jnk_IY+qLvy{Ae#M3o3&Q6xE-e{ z@H{o&EMtQ=!zD8cx5gAZoyi-t+cAE#j6rb81N6cc`2v*JhFj$sR-w1Tr|n((xIi{@ z#S+1te+5`m^D7g^b3*GCZ$d~K@CyxkQx3JIYVR2O@=e*6msRK{^52ehpZ&CYr)<#> z%jp_~hI2j{73+1zTCJ;0s6MlE*erOMfFd8^-t?*Wuc6B zy=t-e(~&~Cq8@O;te_O^;Z=Hgr)+I=dA|}%7v88HOMUjzZ#!kv6mFd7cx|Yv593X3 zsQQ}v?~(~|zwPD8R9F5ka;9IBPU(xHk|8=5Nb@rrV4XB>;7c_L~E= z)-BkG-<8wJ*fJQnlcv2b+u1Dp=&iS9)7<^4HcJb&S(*SO1JR{G3EvH!fyjLCIDf|= zv4^+zJrv&~;OpxAy*0kKH@-*XJ9gAJI)68u2{b|&T~E#O$n(X{zol|zX79O8J3L~8 zY`!~b-flSp(RxaD%fSu0gXz_Q+n6T5Y4W=6a|$1>cjT2sc*APSQh9rQDEY>aZm={< zhbFGob~a#_gdh{S0b>r#m4OVG4+FVn9XcE`w2`Njdb}s6+u*@^;5|8;9jx2$kzqj) zwR8^>Z1HHM2Ujg`pz(WTD=f5idt@)`J9K%EM36SUKwvEej?uV1*xgOn^W(JDUOBp% zk&oFP2e~T4#3<E52CB=rZ}dG< z_X0?q+k0Ow;CPVFfU>wh0@_bY_sa(>Z({;c;Gys3pqu;UNE;-=!3SW@N~Gm@L0&A0 zwW-~rZ_qi6%f`G!I(tBlv;IUqK9J3V^K9xu_@0+|;S7$he;`1-q-7t-5O;s@D@(zO zZ$ks=;0JOE}6ygg855~lJsI{aharN|@LUmgR?$T4){?L#u1PdCF+9mwQM^x(#F zSjKx@9fzj3qUqFkDfzIBbJyBFNy87z7~>d2%RdpJq(v_n!90gt`?_)B; z+%QXhhmw!U_WbWAloRjJJsqD`M`q9stJg zro|^@4&#_*%7EQ;^Mp(@|3wVoj-SYk+(P^H6g39GFN9TfBMtza$CBY4y^ByiJ`RGV z)v)oFfjO0fGhSsNndE~%n?Oznke9Foy!0hd#A|2*q;x*4!a#oVHp<|)9rMD%04(bGN=MeuhYGw!_=H<*9h8rQYN|vspJ2o?@!7|>n^G|DfdNr zT)s^Q?|8Jji=*dvb6vOcO=8T)iZvS&d;vd0=#z`T-sU4btf*fI*}z$rP+)~JAzi)6_N?2y(2#-a-HU2y?tT1Lgf8Q_*UH)LWh zM1lK;;eP-BIC~HHs*2`+_}-h|8|giP1jyaJ2|WSQ0FfrWO9`PUD2RYGA)%|NtB}G^K|kTtL*hLyhwLrb;{0ARpF=@BI{Ba5bp%T;yp#} zj)0qZp2x})6S07|o+lM#AMdISHv_{_MfY>B-ncoS1fu1AD*DxGZGKhQH{CO~-7b^c zq|x}IH*qe`PAzbHO>JP4<((aG*F?mf`qf$-_4%@fI?(EDSJE$5cY6FFcGqx>HHdD^7KAd>+d1|EKE8O& z+i3%U564Ed8PhA@NsapIy89dS&mn6|%TqCAJ8WI%9inO49%pFhVe6pS3rlZP!*lKF z>qFKQ-6C;`hW=)qoP?ooX|LMrW%rJ9A#05+TGFZCtOG6MqA2$W_6w@%@gvp_ehcgB zpl^>@rS+-S%JI3Fu~)W&FkpWI*sphDuX|t5BT;3|wbt4SCT&$`<2zwlkqUlX&=@}E z7)e$DjzJ_8o7{=2tX7WiZna-(f-Qp*Ol$ZsvVpA1ZTdFekij9aD(r|(M&u7`P7BR+ zxChKWNsCy7?V%DZ3Kn_TeL>@YA$=L?wI);W^$WRMt{0mQd_zS?tzikul7u*AzvRl}4PfmU5xr8)I*x zu26ZhyG<)pr()C=DtMg|PFhRCff>}P)+fMcPrjO8;|s~x_;uQL(mMDKsBTrqJniiw z>Qhg?W=QaKWi()v7W---u%~VoRwnl}-421XuTjGH*2%tlh__ZR(WO(?RRw@j$WV;z zs)JLoCF;5dx)AhZ5Nx&WqSt8HC2Jymxj)d4s!v-xBc536GuBff0r1o?YM!{#;w;?2 z9^!?Z7e`N8@N&y^iaKZQ$kT{5$BQ)L9Q7}VDe_qx@MQ9tV5<2QZVJVS1i)-)y(Xg4U?*e++YM~V-4RhuzSY(yLDkwyWg|9T zCLmmQHRV=AjX6Ohs&R_3ob1(T+$Q><8ano))c2w_jPftym}4oYWhbpcZYeGV^|*5* z=$N-UOjx&#K}|I<3yyp*ypTg!O9WTET^=ROz4t1P)J?RI6C z(jK&99JtpO&oGcD7(ucLcL44J!`h3PjG9dco7t23FvBrrux8U`>J~)gW3%TQ`fRt@ zJsIO^YG;Sh)1CKO*I{jUBt83=H5qeuEch#D&~3>Bx6oIA!7)D2afLkar$x7NP}&vi z7)y&&^w<@vquE}8_nSc{U@=GD!@?Yr$8rkxV@O)fDQ+3a!EMgAKWN0?Sn`M45S7Kc z65g^|SFMf5-4|s)j@aI;pYRH&zm?-b)DH%_f%|w?GkZ^btD1>Q-l}U^9xv&kt$9Ej zV#Ha=8VBxj>@C$YdIgSAZ_&EHtZ`6~T$}eKefbyEtneD^a7)t@^k9v(&CnFM?}F)q z(c)^OaPISXdoO5ETGR23zbE5Qc~yHm5|HNowK(mayCVkAX#8n2pN+J|>XMyuGXG=E z$tcrLyYKz(D#vBGh;{J*4!BVj2@?|(7X5qJWg7pF^&!M=JM@qB$vY~Oz1wQeEyvO! zBrv<5$UwcR=nbp}bjmEnIh7Ns4fIBa>W!c1&3_vl=dU;OILDFWrhgy>U$gpSe#T$J zamIz{KO+x|c>yi=%CC8eL%&7Q>}%E^dHP<*P8d|O>(Oj9U$<4yik~c^k0qx2%S=4p8t?3?rTK)fo1^o~^wpWBG3K9X zgojvee!Aj}hrr>}M__Dc``=PL)wv*xV-eD|^yTav_-hRF7XMiM&Q}cb5uSW|)d*kF zK71pqJ=jg>Z5^$r_L}T_=yhK)2?qCQKe3tbNc9s_avp)bn(=rDPu@9Y}mL~d(`4;&No%I(nmh^APGe8vj99{!BaK->x;4+z3 z_5Co??e7DZwHrbZ&mutd_xuGP@+~y^J+BD!w=^(Nq`Q5JS3w_mCD8MMq8K`{IY^|s zz2Gc1in;`e9_BB|9wY{PPDa+<7TWr*S483jq~YV)<{0Kd5iHPrT3|GuV_=CMjc-$4 z3W#(1ibC0I% z5RrUq{zBRlBC=iHzp)z^6cvSv-tek>GgKtP;(8!d+~r;lX9KN5FSxU7PUu>V$csG`0Nk#=BFt-QY5-XK(YDl{)A*o%87QT^>4=n zhd$>5tIspEFj9;Uo$vC##WVCzq!^`F5_)ST6d5Uo!UR1vQgo$vB1D#+mo40`2>tUI z#YBn(w>dAmViaO>srhZX7%j?fv1Ws@R>53k!j7-enyt4OC(L6&jWz{8o-W6T&LIxB z`W=U`>ak+5;#G)zV*xCs8Li+GG)IW| z$a2;*KtZjwIDBZT9~u+;0&T^|wCdtt@2E)ycVkP(dznzGe!Vs960Yz`6ixilaz7Ol z>RsxVC|ZP;72e&}o(e@v@8|F7iA0eEC*<4&kwHJBkhAe)pfwjR4zqVc=C>&%NhI9b zTklXol8B@u@xmi}b3x7VSQGR4vazos9qCMOL^=_U3C?llfdlBWLYygNJXRgQ%}7uk z>~{Y**yV+)ps|2Np>h2JT(GjD@- zt2)rx9~;pA+<^Ap+o1i4LObYoXooTEIJ!T@IR0gY*AzzQDLF+=M&n$$gi{bGQ zsUYpv9zIJ`(=aO0O^qz6y6|CD&%UEP-4gXPY&xU-w60Ly^e-#?NLBPwgB2m9Wm6+_ ztuDmA0#E5h4cD%T&2 z>xA+}YX#-wMGZp{8WbMUhH&|v_Ouc2Ya@D_@<-|ZHloAr%5UKEZK-iPg+$hEfY5&h z0&R|g^vPC0PA+V?B|ZNu5I+Uv;T&P-<~(y7AU6lD?r!#hAr%Q7MVN(AS+Stu_WXr=Sw$e##T?nA4)*t*N{7A>dtYI@FL3BKl8(_^jw4JP_4I^WKi1wY2iM{y|GC zm%wkeG%u>%9hF+z-SL(4`GxcOne+LH^SR&o{HUU;P~@3&r)$3%hPUHUq?K2$NQmTv?0Neljjc+44}`LY=J|(NECG&f-<(MbV|`o~~+UgZwM?NmR0$wswV<+p&wd zle@Zy1#Tam;FAg`51xyB@AuJ87JI9piWj?xP;V{#~tDo z9)y`CsKv?gjJ4oMeOJ+k>4AsxI2cwPd=7YG;nn1w;>Un|4Z7;djto7@dy%rFouPsr zz_V31@hG?F_xY#^CKl$c#+v#)MZa_tJ-8{GxvG{fRqZv~VeBgGF1`t}ZR%+t(0WyYKvC6@01E9TirLc7jsy47yj~*J zTvoB6mxwe+f3>P^xHw4o@&4*EI~WY^5`9wRJnSE0kE01B;->d=uqBii>dh-Cd2K8-BH9;0Es#jH5QxnM#l4YTi?RtK30q4i^QzPI==y61gYh zl26m8eZ-hRta|HUOs4Fkv*9|;R?SBTi3^q(f0{E`jI>z%>6gLcA@gzSI|P=T zO4=|){FGqIv|pd&q&s-Qq9@Dsc~p$u=3NoN3ABBv2xbo&c48h_MqdpTvLpb$j(W5I zK}J3Ox0YrLoyBq4kiKZhb6!iAXnD>V(x;KGf_0BQ#Qs9sI6kYfMa->p!!`o8IBD)M zfmlIqcDO|j7cGSwdY%nr$6+8|1P^yMnk|Y`?cp8bV(xO7F}ceRB0huYpzrv8PJay- z%ncSWsFtxa9pT22e@7G0x<>BwPcw#snL5H>9C7DIT;axW(8 z(O6T>%oV&10A~^aOhImJy;hn^v7_(S$kEP+#*7dt(T@NcJ5wEn;hgOTdYI5;yWK|p za3s>SgK_NXOWQ_@Ha-t=dB4&f+I=7K6gWy`G&LanH@0VQhwwX8G)kn#c;5!!d7iXx zl<010vy{$`5=#bE^W5p`S+@4X@xjWvzXmvPnnPN8n`+vjB^+a;q2aHg5o170`JfOU{d1t$ zMuyQx(8Do8J1N1zI^f<{3=1wm^RLU)w^(Qg#`w~-)3l&iJTL&AJpqPL-IJq;`(lXM zwJ*wQJKNb8?>>RfM%vifFKRo)+&#%1;~UY?u_88o0-B<%{XUMnk>-$IW1P>?+SA7| z63@iH!@{Y2tnjy(m(b3!;)Zz-eK1axGm&lNS&?e0X^uKwh^$(O3lL6|?Y>P=|SDU>ks0=Dia{`JH;D*jw85`0Xn# z#jqcN=sgPdaXB3>dcknFFnB^7prU(3gqK!(7k8R}j~Ekjw@dYx>Eb;?3!ul-^&#qZ zugGUVU+j3d8V&FAQMCGAF_zEM>TfzdPM#CRaAsqBY1~ASA@kAdV<22Do&>WowA{(Y zG#7hjV@E(J%*LW0r=1f;bDxKxI&-rZtBZ*ICy6fH*PbB36Fp2d7ndtfPXh_o_VqTJ zJxOH5n9vgLYvz0$>R9jR8E&+5lE`DKV^RMxdE6%!$3bFbLn%Aa9-4}pz_qJDXb<;^ zJ2^i)^x`DWePW0Q@_Ro-{q7f?{E<8czy0G-z#gX!_lr2Tv}zVA5Foc{Ag&p|Uu0Sp zH~#Hw?0|p|oJ3U~iX)fl{*9+FT0SUo$8u^uSxjLrxe0Y9EvFYJi*`8dy@d`<7E%1( z0;&sHPB$it?&gsd-KL0*X5Zu30$&Vt5@*nr2SiQ)*if1713jBMP8IE2@T;jP{-&F$ zRrN+w&G^Sa^c%s(>(A%f&P;PB$5b&a`W|#R_h$9-{2KOf(0lU`#Xl%kdR8ySaKAy@ z9~3s30g^n12C}Q2CbfpE;r~8ZE1pEn1dh>}%%D5;2rKU1VmWBf3t9>_w&%74U|Jigt?kB4_5; zFe>+;PHYjjJ`FTEj>0>%V7hpK2R3m!U70Sl^JvV87F5K~5Z;IbooQc5&1Q;LObYzr z0*#v~rWxCB+dOc#fE_;5zMqE95$%{hJ_Uj)kIC(d@U2l46Me;mhHiII6q$cx4 z5?8V8-(oSVoOEY5r4k)uF zVtj-~lp6Tn0RJBTppD_au~Ly5zYy6uBJnJ(n3rR`^T~=}F^ww~Gm{5uueer=qY!Cb zzte9M!r6#YG10fy8Ujz-1tN#H`aJEI>CFWq!nay?M!uU4ED*Ut)hx~yp#KYS$g|^8 zN?0heGPDA$&VBaTWjYG2kF~)QP~kRUqA)?THI0|fEtb-pg`%$?mW7$n|2!ReMfAf$ zYyk&7LW35GoZMGfS<<$U5%eADm$cuk-6lG=Xld0~Pa<908s|QC$9eSCB5{w6wRR3i z=H}=FbhIF$KX#5pDSUW!d~&{yd|O?UtOY0j8XPZr?*;U{=Fsf(`(Dm`N;8d*0ok6Sv(b8A1 zan3bzEK^gDkH>yRKQ9x@ES-BH0)l7}ALI*e3&JgeU>)NGsQU*!SMlZ};yE{O-1W%& zdPD;s7fqX?gStYDo}30}ct~01SGpM0t7Juf!gYH2anT~?Ehr$|5hpPDf(#we^k2I4 zxF8-Tb~+qO_9sNC{;QCG#Zs#$MQ&3ysvmxg{s!xHbB8!zjW(tVvpSH@G2H^I7fYgK^ft%9zS#*5&+GtQzlwLB674+uz|PinAzgV&EVSf4 zLUUGQd-@aFuv&C&`^{re=@2;v>mNk(HPsX&;#x6m0es%R2uIcz!X>H@c7E|!z$icBSI`pL|Fh|;9QO^U?Q5{Mu7*fLJZr&)2fI1iqRJzn zUzQb}OR4aAF`R`wE5LkYgq6h+^!oFn6<2!h%5B;No`1Vab6qQ??(0NzI5N*zCkA^| z!Rl8@2iA$OfSFKsHM>ese$C@lbi_TX!si8;yx`Er-z`ZGQQ>+q%;NJ<#k%#Pi`lQ% zfYNI|o!=k|>R#l`r<@nXxVje!^U3j|=*l_)YuLW?>7N%xTGrdJ&glk~Hx22nhV-k3 z^efbNqZpj9QhUXARX4{9q;*cq1d%s`_HPuQ>s$vXfL{`QomP*=A3{u`t5{6Vg-q(K z7*84dAhKL}oI*BJ0bozAV1r`gwVT_3UP~p5ApkahU?gr(`%l zSrp^Y{Fa%`fBUfVmDdC2mtys50%a;INT;i81;K2qWOKwl{{{ZQ+g0%1|4_jkm*&Pm zpH{0fUW``EenmWDkw9SMpJ0;!-t?*I*A;0 zDlHdqd$cI!N-d~VXWbZy>g3K&)?GKJZmD$OEtQ(%f>YrzZQd%LiGmkQzII~A7rK@i z?$$iJv5P=&ZWW8n#nk!@5Sh0Uz{UIM${V6}N#$5ukMaXyKn{#Z9Rc^ zi%lNOJ#nbllWs z;51K~Y)!#rAM=8pm&qOIcD9(_W@G-`Oqjr84f(*|j-hF7chb7;A|)XOsA+j3Z_Sgw zlLl=UEyELU{S>Yhe}U&IuZ-KyraS&47InnXzFA$bZ^~W!<~^v$Iz62N+vmPvzyeE#=rQ1(3->0N8sovDNLbPT!yySLpd#gTg2<}g0t`I4=fV^CRU5G`f^FjP6 zIpEp!dFhaF<61t$qcyf5Ooja@F>rtdIlJQs~^ zJPyT)`|cTf^L@xSs2gljv-gP&r}-ZUZ`%2R2&HT9i)aR%a67=x`PLBNsSN_2s}K2| zGs&`3wB?`7soTw@!kr>F-0iI$Vsm<`keTsAN1t!y{vBSn` zZ5^nwKa&Hpv>dXOMnwgt(#X7E&yazrUY8m?Tz^o&m!hS4Hx+y-;)bAV|JzladTZ6} z&cs!ZLe-pZf_dxVwD|Kb5Tq9Z`K3d8L6C&eCtr#VAz>~Eyjl_dmB=ughfu-SqS(`| z{S^vrPmZsJOj`=DOYq0;=8K%q1$Y{1HESZ>_*&esG}};dqf%@$H>rG(3#fJdmxlCb zhV;ku{WqdRVAn1+Y#oRRF;x#sZBB{bisXRT4B56&uWv;sOV4|8VY_fxlJBM5??g^u zzJ9C|WxejErQazVD|6}9^yPPASx7p77?J#u#(gh_=<|B;RNDW&(5Cq-DAQ&tb^k#u zO#XDLqDEGk_am*3l5Sp^L4W)pj<%>|W;o?EREjAD*=Ca|yXx!w*`Slz=2DX#T&8Z* zYZT0`7#u#=D*Ab8%HHu&>Xu23pyjCU1|uE^&wJ6itTH1$^zi+Dm${3-^p z)vuUN{3;p;Bc<++;4NQI$9alAs1O?m#7>l`bw~wuIVkRCyLiiCAmh2pF3vrv@1#CU z9~@N1(3gPeV^nicq*}T>KnaILCobp4hKsz&(UlXU(!5gl4yYmG)Oril+J`iL0AK2e$W4uIGY_AgGRod-o!EDXtj zUw~Ajii#yC1(_|$k5j^Fu`c_AR#)f?{IR6#j%?kWAi6rAU9_j0 zqZ6LScHvf>(_$7MZ*z4C`B;vzp&zvqv3sy zmS)Snm!qwEU!whJrTyTFeH>Y}1-u-xwt%-ILrW`De^W#LCWiMZNJDPGI+|-QVr$s$ z*7gxSREM{p3R4%RSQWUyQ84Xe(AkgorZpEuf*IGjUld(KG3&JT@`sppd@)q#i4=NC zH1}8ln-Ky)zSSX|23-8nfP4ID|B|EGxb*8sraoocbaU9sU$@uRs{!bF__-5jxobd;7>s!X_+R<1RnwP_DW z5Yk4f+C}^R5_cwn02s}U{Q()9yQ*vO4oU}2p{pXYW8S@2C>MXMigwVRo{k*n z?{>~-8$6AupB#n!UimdmHCNS&J8Hx%vpJz+*FU1r%*L%Eu;Z#?W#q+0+SkPUJbAvp zCSr_dgF0)`uiWhM{piLu(E>LLWL+1nYIjm6DWNoJ0(JM4O)@|*s;74Kh1L&dcN`V) zUL$WSuf;-7kLEFW0`0#Jhb3o?#^X_Xjoaz^HPO zRS~-MV$J%l{z}G}9jnjC<{8z@&=-R0Q$Y0(k5{`K3(@XE9Jfk=J@yDss?sQX_+iR5 z%XoF$`HLtprDB{}TFf!GMGt|-Ei%^97k=OtDQ=%{Bb~6w%L4VWO3Owb4i#{$HzpSh z^TtzIXaR(ln|*j6@^qKd{3Eq?m#vsI#(*?9&@kIQ9W>ir#<>IMTU2Z5B1BYlS-a^?Gz zzik42-OWf252zW-&=i6=aP14ECQ`Pq?BMN0>I0hRE7KHCn|)>Lqs6(VD>#ZjZW9}Zfry+-_zQD_BgCC?U?9s*@kode6gSoDKz80F3|k9?&G4Vfv!~oMx?Ly#{FRHbx>;;WsmP0xW;dVL zMsp8(;gZj8v9f>AYV9ZMf)>Y0q(^xMM_cj+SL~0KhvTE^BFp(M6;*cQ+`O)$TY~g6 zcie0!_>z`Z05=%kuhY^B;94!M0OG2nM99Z3gDSQr$}wh3yHOOHEOVPQHI!|lr4{c= zF}zRYvSHL`n8n@g%Yj!acKHNvFq_9#WTnbjbKbopxoN7#@mgBdSZsJd+VFmamR6V# zLwc9LPqf8rAidmJ9uAJxKC;?xaYP}lO#J&Rwlo1N4)|;YSEayzO!g)+(hNIFnmpFz z5yO`yT3W$asHOSxZHuFXON7w_p26N0>i`OEDz^so)V`~+=%yh4O(&YlHZ99dzqhpS z!A8&Ee{T}_LaoL=_io&b2(v}|Oz;ZoQj?55HBOHvx~rLN-s|LET(OyHsvh0ngWp#d z4fbHZQpO%0yTJ~}pgddkv^>MR)Fi3$)nkTx)EFY=a(v zD>F}s4?*sQO;Zrg8v$SW(!J7ndy5ybfsX0r22+y$PTK*8O}+3wm?8nE*?-IPl**H2 z%v0h7&VW><+4f_8`P(9mnGAWbe}&4@w8L+K|1Hn^sxpt;=P557ZLyae!zSdl4gaNO z#}%MIZ=a{S@PS}^Du(l{ArB9WZcJf^885K&OT)Q`aWjQJ#A~}G){XI6eT+I^<(*6( zqr3XkV;SdN_S!HA^=4|upeFp2)mXOJOsv^Im{pk+%<&{2LS_#54=t0uCyu1zk3o0H#tC((>V~@?8xOxq!;#;~nl<>NT;P69ON7kp zn|eF2{)u)rR~x~a0Jg0Q*!C`9U!`ydi6h;WwyK*<;q=R-9vJb zXaxhRa7tz``o0*5{02lUjY8>Pn~X2nYOFOK(6JCcf(7s+##(K7hfPMtW?}7nuiAUY zflalkm7=4gskoTh8K{30x=GPhca7{^35VKWNhQ~pD`9)rv;^=Mrc+BldN)&UYqS6r zGj)vCb`yks-@&W2YJHz54o;ILr}@{w{>eJ<-*~EvT@hleg&gJov-87`wI7zy>n-HD z%&)Sv4oARwbhwc|PfO7J!}aKM!dI_Y8Y;1LzCd*kgL?x1+LWv?sL?)jVy38*+a=} zlM(K4&&i@U+MvfU5m*al0tRm`FHCAhzqXOlUH{H(U{Ju<4&Xgz0R{`Rz)7cCSHr}z z0T&gh>8WPHR$#`V!_9Y7-?p+ZrUR>4UYHKJpG%t#d}!=ru=`U$XIEP_9e!;q_cYp$ zYMfM7X3CfLnqM&P`7N79n_&yfk`MX|R#rh~8F;EI&VTMrvV|P!AK?7rr+>la8;7!G zyI|bbR%|xC&BAu<3Z&`F8Oe$68>4DyRawVI9GWOcb_iQlP=ob^mTLkbjSCv6{Hw4i z`Y1;RyRUVtL3N|u;&=-)N49}OD_k65wrMZhS_bu|iS1=8_vZG8zoxHVku7NVr6hMt zPH*~!Ux(R8e@#0{=BU?ky({{4ka1>j6$jgvMGtk9qZ^0Y3!jHO1g1WRlip<9o@>nTMnYM0@)gYjL@H>3S?AVd9kxe z%*q#d*Rt|5X6362WaD;~#m**aIdBaSHwnzXvKV8b1i{%lL4by6g5Vw#T>yO4G|Qxk zg2By=_!~rlyAgkbD7Yc?cGVLFl`f)y5({K_N3i*NqZ@|Nb$u7;GUD@lVXnc}nNL+i zo8Vg7Lb=ro!9mf2Qrgf-j`r!)h1JpWv0cfxv;4-AwU`cfmbsSX#gx!Rj<Nz$yD3a+LWsx_F1Q1-v~_&2(N{y-A|0>}@GnMDx4Kk(Q~8=x|rrJYkL@ z%S@z=Vkx~RrQIp>l1sDgje){qQ*%3(#+2l4+Ri8y*P*ubPMI6>s#VpN&wgdQZT1WF z{hcyBU|wqll?B~-^64h;^;Qk^T|{%bNr!oJMU(Dwt2wZYr2%F}InRubsH%s|u!tTM z*i$}j$-^R~r`%IN&nPVqJF@nYhrHBOKSxXMl0}&5H=e0C(<@zPIy5+Kro*4Aw>)Ku z-bx95r080?7_PT>c7zkNzj^uo>UrPpPck3yGnp8( zmHKX4VLyuLC(}ZH?{|gH;qNT|&fxDf_3bCa0;n5^g^#Yn^P-g^n8*9cX6}%@b7)6D z*&eq%{?$*WnqQ>o{&H7{$!P#UrC~T| z9w1XJIsNHferENj!vo~bTOjn+Ai#@Z&p_GQE!uvPY6i;mpaIRCgyzHkLG8&lNXDC= zr(T2POmhY88zlR~SQkB57V<7@o*nL?gJown@Uh$E33`1n^o;vU==@-yl5!{I43QHp zc_sAn5ZT>~^I}6}7bhq0*qm~Q%F#{3?R}oc_(EtpIeB^Q_`-3GIr)%2*s(#d+m14d z4iA-~2x)(DsJz>MEqoE+!ptkOlQeXgY-@g;?89VhC;j|P9f!&y1aJR+^?!#CU(De$ z*)!b!!rwP>3HoTyC`-?-v~sxYjKY)IHGM7&*XS1zj<$)+yB5diD%135R5M&Q^)R)y zcm0>r?v_o0w0=>JjqZ-n9Nbqf6T-hh8`%9yAq)cVWU*hTC+?OuOTeeJ^KRKUsB$s- zQ(4};9N{^XFhXhv(Z>FBv(-!*H$rMha@bB^gk!R@B_h)u7$GwnjYzMZtRP*ReZv7w z)r_WQBV`%yq*nbP3Jir@!)WxKxOGQo4l)YD>TM@His=1{Mz6tpBE!mo>BvP>70 zxhW(*6hNG_u+p^KYM)wpl}2p}iJ>!NWLYL!{}Eb$3}(-xVcP7*ROQ+2=BU8HBJzp) z9R@2Tf-7#LEyZ$@|IE8oC(Xc9X-%nJsLfdUU{VThzE-+|TAH$*q?a>y4?Q=0=MIgP zwnoo3sYMOlV6`9m8roU;VE<@yXF5AZuJ~`*r8aQ{Sc95ZEL&nq+lfBo^-4}Y2*VWayxt>37pg$%{vgEy7v2=>`H5c52y<{H0LE4iIz#fkNTH4dm7tcQU zbFKR(?5{f8?n%k(LZj%+12QfF(?8`yFbe1!v5=Xgf6TvbGMTP(y69#;rB21#`U{#m z7525a$<7aimE^}ubYLoQew_jylsS#Gf=AL#*RihE3XewN;Sb7==7sd^gEBUL(p1zR zlz$x+Ay58wZ2n$HOzi7bex~cw=>W2rN6;S+%E1AnG)xP(@Tse}H4`=6J54rbNzu6# zt(+!T2Bhna3Cgeef|ApHqNv++nSwLFkV5{g=)vjGMlMm!blK4h%NSUQ!BS_)Viwag zWINvWR%YWw#~XBFhMey0+z9`OiXM{bjdGF|{qOdHG6nCIAF9D#la{oL3Rsly>_*i5 zzN-1>hh$2emhGk8=tx)_s@kfpfxReRT$)FbGi8boZqs2aq4(?Wo#uq(Jj#7o&I#$Rzjx-pL7zS>i$jF|+L^tII?j`mLIPc0!y{sz zoX%?=+k6=tUAN{idmw-@7MB~a=17Kujx|R-mClzwZ4Ao}Gw$$Cf{u<%mB~&W-OY4X zTWqkg<_I)gd@E0ej=l@0x%60x zoE$nwfA4Iu%q8DaIVN<3%lnXAnqMj>nsaG(iA-AMlh&R(FOYE|NiO-m!^ui?jah%~ z?6K|i2VP@S^h~MDqh}V%OgddEgUz^VXra8bB&K+snA~`j7h$(;@-nCS zVZMw@En_twW2~w9-$L3w=>oE_1HHRUjtqU!<$YQQYW|2E88*n}y)T+`?(=X-pFSen zhqTqdI!WLhg+D4MghcDFokRE~J@KfV8**iH{V4?{<1sY;N0-;jY4u|OvO|CE1adzG zESGabpVnVHtL)yM)-0F3ywK7P_Iux>^UGz6&Xxqh|BAJ^!gL>an@{i`!Umux1XafPs-Gg!!Oq#!<97qN%;b= z4pzvn2m@WTLWWuT=g>nd#Vl54fmRnRgtk4I|RE7qO4jX%54&s;br8 zoti^xA!`mPA)jrkkNtf5bfugW_NvS4QQ22$^9z1$>HNnbX)XSYR^mhH3O0M&k97O2 zI^eX-rF8pj`eBuP3hZanQy@~zPuR-By*9Jq4CWjd%(Cdar{wgIG?#+7wRp80o;Af- zAB<^l?X6#*n@h0@I*81m^$_1iX&zI<9vXc1(DhFgL9yFlCMQfzQL8c%Wn%wIF! z(ac|=b6j%BcI5kv92qfEe{UeOkajfx8M!i~mHy31W~V9nS-B`A$mKOOxo73_kkcET zs0S(IHSC{j3M zmR@{LPWDlLbgk@1Df)TL&oGy4AJeAi<&>~Lu`Ok^RBXoH+u#{~EokUEnFY0jr9GV1 z*2%#kJ6*EE0d*a;5!_b(0v5`T(1I7_N6CsKX=~(H60cCPOPR}zS**7ewna$3m8`fFzw%%$&Nln=t87>d-u zrgYavnS&V8k8T8-^Kj>^{4f=taMZk!+LC%c;R+3L0pZ`8R=y-hyGPs8x6_rEWb>@2 z!qt3O?}H^$X?uI-iJMN1U(JW6E)Wh<-%YYOYl^cNrcpVsLf+ctLe?(DK-Qb&sH`5w zVpvzLa4GiN`ugLxs$#~=*gm)9BTV>anHP`Mz$8e0*R>(I1P+kV;mw8x16GD>$>S9{ zIHE`gY9Q@KP()vmLtrk>dRsFWhqTjkIeQxiez(X8;W7GaLt)4UdoZ@&>zR-e4UGsoP{kpXcu>&Dh zW9*II#`OXEI-FJhMJ9XD+tg+oq~^ESpwS1Y66wz=q#RHoKDM#=zz%?sb@2Ap%$2F;oJ*_P`Q2P{Wy$!OtrJ?dnq%$;t z^wV3?p9XA~y&A>3Ib8_~uIk&=V659^+w^8WxUtLAw4JeIhXTI*bF@Et-ov#0NPiQX z5aG_;h{FCO`&wEi(D?tzE4T`3M1@>|OE~_hkdYoXZ0*2f?~lNi;r38{#;W*c%#*KC z-*;qBb1bcUM0)L?Khtmc?WbF_d0SW+2B{cwa0 zGVon#V}roUKsmV`t$SBS7L2xGyRrl~XR7_Oikmmd0!Vy%>Lj4;XJ~nd;d4)us|-!Q zM~2S@v-7B5JG%0&6cfvvnLF5Dh27{;s8*bQ1?e8&KJm@+qZ=-jn0+#ER%3wvjay;9 zd~-m)8EAUs*BlIjj}$6A#*0x@cpMcjx+g`eP!G|eS9pS+cu%%S(dt-isBeKGJs;`C zRP~-r49P@q>o$eskqFD6Lfnn)7S!CW-}uYadt$6`d-BoCeCLLbr!(_GWqkPbec8zJ zjD>!CU&geUY0-L<+rJOpx0LrRoFhJNT47BSuuE;kr&-vsq1yCQ3}t*EV@gWumz!oR zH`h>Zu2!zn^m~TA3U?^!gv~b>d16d7%34+*)@UQFMFv=lG+1S(^{MtAdi;N$B@FD( z8%|&=>I3U#1h(7&Y`I4M)uw0CC}^jQ=|J_%-EtpA^)sUOORu~%$gPZvLAGnvW0 zikj?|ojJ9D?%xX?52;DCZ?7B;_ilT?Bx?SVoW#jCNwnr8Ig^u-Nffb9F5;|z(ewLc z8K)|7JFQB+O8fT9wU!~)iZLI{7H;7ea9G6^-K7;iLlQ1;kvkqMoub$L`QVIbwv%ijH~Ks5y+o0;5bdMZCm^ zgJ)GSEHk%g z&im>;5@4^gp)qiVsltlP2qW4E}q{@oD6tG!poGP`;)UZ0yob13%1g}l|>;Yd+e-nS4X=g{xDjj1slEbEp}-F>9=p;b`lk&o}*Lw zb%ez|h=KsOdy++Sjx&;)Mk4OFz6aP!(@*WuUfs`84Te@-c`Qx&4%J1gYJShA7x<@- z`gvz6eT|>d*lu$vtW`E$H8SR@TN|kXH`z4claxAU#B~WA0XJdy(l9N`U8Y54L(?M4 zrLXnA+}{)eHnlYSfmM4#qUh7_Ws@*VZNCCn40wdSfb2iWM((q+?a3-NfKz6EXRZC3 zS^I8mroBk}YH0`8nIABiZ{ONZ4feyerFZM4EoG{V`*Zpm_k);RTD>vfH3$bDkABqq zM;Q@Qruc!e!?b$d4yT*n%ZQ%ts1MWB`2BzA&@$6yRj-kFVJZ1uM*6hS`;W{SLFv@t zUJq}|{7E*p#5SctKgq8`T4Je`h{eefs5iWvI9Ad6XLvh>{EJnG@%<{A@rzs*vd`r; zEJDA+NL^VB!$1{O3tkOued{lJ`es;^rAInF{i}Q`J;y#2*3BajU|`SMzIhdRJZI;F zlB3y`*_6Z4tPje;7RyX>9F*-7q2;8+T%nVLOLv?BV>TX3=<_y~8>O>?qReL~{*b(n zHKH1N;*jjaspC|22z%nADEzS0&X4m7BFjc256fx%eKUQ37^^~ri2n_4M0oK8b^Hz6 zgb+QP^ElamlRaXeXZ0G5VJsJFX%+d9kk-yFSkoxf;#kI13E<@({V>D0GMw)D}zqajr?ul6U7sa3&{ zTbsKL=MM8rHk%qP2Kg_3DS{>(l}YU?7w`77pMbDgihc9_`OWPwLw7y~li5k zeg*{{lWn*gA7jL=)a`-{rZ3M(Z+67_0fOZ5E+rY-KutSH)gTsHBoOm5l^dyEfndz}s)m-#$cp8;YCH8~-N z1Wxy~pMXTtFduEDA^nLVz0Z*T5NUm)=(hf$jcMd5Il!ZlP8*Fm^sUK0ma0z4 z&aBn3#Wpf&ET4r%$7>!Nz#AzAdI@-PoexX`h@-yrS*KZOJArB?f;*%H!ZM5Fc zw2xE6h*4-xzn#V~YQs}EzLopeH@Ew`0GOiyR4(orV?P0jr#h`U+0MxDu!hEW@EJ8c zSIK@xA%8N0a{qu^W}~w*OYg(hR&8wC%ruPc#teI@Deng(`k2-V{VyWyU3B!Z{lE6C zjA7{Up@edglILgrC zW6kNuKV%CFF!VbwQv!`G+TEPmpO@VN{>-Su8sUe|!v}0x3SK#Vz%teK1)rW*+-x<) zUr;o=h{j!zck7k^KnJREy5`^o*;3KgV9uCCuUCQRd~ilaaWlJw)5vPrxJyq<553@1 zTreWIa_n*g-kq%UceP9ku3S7i9$dsZ2D>vT{UR`KXTZ3%hB4pSc~K5EXVJNfvZ+Gg z2QvSuy4at(T#^y$Ej$1&$-(t7h*YTmbP1sPFoZ|M&16DV|7G-rR{&pcAR50 zT|^FU&|Qrv=dzrjXIV#EE~_l5s`6gpHh&8FOSL|v5y`*mGQ(HuFO~Tu?YW|3>TyL0 zf$u2!io9E==JaN?^onfDmA}TBHT2ey&)+i5uQJ)1V^0C?Mr2UV-^w$Kr|)T6@VCl1 zQNcg+w<5M7VKhI_7D>&n%3$w%n%Q4OS%fgTs@ND8eVL0kqUWzFGeJ{TUK`5mS5;#o z!YHOj*3#ZMdZGrjH>GwA%ZC+%WNXw^t)c^0(ZGOzWMgi^*VOtS+0^HBrhN>m?$I1~ z64#*}uj=0OkE;6xRWv&h9XX<>E$r#PC61kILh@g&@qJX|u`HSVZygj2*1xLpBNTx6 zYpU@*Lg|icGTr-;82eFhn~!P6wYqjAHq13Ss-zbyDb6Ul-3{rkhID5`y1_Ol;_gl*f5{&NE& z+R3(k;E;Gj_TWx>lzQD%C1%p&oR~*lZ>;{_W+=FT;>~(Va|lf~+X_52Fc)aM*_P&8 zoqTtaeGF=xL?_I)T))~HJEoDe==JOhrmwtg83=`HLu59_;&uAKVr%MiIl^8D3Tf7q z&RcAn%OPX?FST~F4dC|8rYGEN+FY1G-@Dn+K2_T>@^H6lLYeb#r(W*1o*u~GI+)hE z+d6SFHJDDi+tR(qCfZ*Feu&BAQC9*6Zx35fuHhoR?xAYHwP_xVlB!{NI;DBqYWrL? zp~;>$txXIukitq+bagkcH zzojnTbvQv9d)w}2)RTkgytisaP!P58L5b<=E}!K%;$Bw*Ff&ol z^D9ffN2xDe)94}Jx^_f2rk%d39f$(sr^+m&fqrPm7cuq}^psl~E%mEw$M^K5pX%I! zft28{(CQRO6vw;0j;na>ks`4idi{R%no`YP-_^j9%Q|&braedSl2MGRPqe6 z^bE9RnzMY`aalL60;-(vqZ~m4xq^)m?hc|%#sjWY5;tc%96iO zLx_nIf{9XFYsVClp|)-+Kf(`$+6q+~hSpGw3P-ZQyi9LQS3>JXrG`3&*)jv~wAhzm z$i}k@UTUSeVYY518(FqH8P0k``gucojUi2j^izhk-H?9LkX~*`KVnEPQE84dn&?<) z_)ua z@o-yTos0HPrjy~eJkI$IK3@RAbc?WQ;tK)FB5Y&zj3LQ%IKr04^z#%YN2)1G`%z%DLf%V5zB!df z+iErUVRR_M7DWf5ZA}?3O#f(GXFgp2IqasVY&1F2rs*tEjFj~>cZ#@kwRi+&-W1l7}@P~QYw(*P&S?2K+Z zHh~VO+p_)2^@$siNS`GrriN?a5>>gyRFr5-3o1*VuJi|!DtW%CExT@U`wi}Nw#l%{ z#q}qW{f-M1*xHsvIZ3v(oQL6?p%39~L;4{@dK%KMz2_T2Ym#geDJjC{!F>_!qY)%G z&x;!sM!#d#N)II4depULa02a5w&m0o`o+6GZK69;Y-8&3MxV#$(L~7<@IX-rRQYh!} z(mXYTCZ*Z>iWA7Jx8yQ$Wwt&*^o- z3D>nXRZ=sbOC-@BUQj)sZ)($4Fw%?OZCWRy9dxE?UD1art69By4hy`MrZls4OHMQ3 znc4uJ@6ylBY`Dh7WdGEY0+Vf>c(zt}VlTNR9XiuH?xcq_N zSvF0W=c^I&kEb!VI_Y+pw%C;ZFw$8XB$nu_lU7d;D$KNvr}7k=hfZK?VY+LOz)B1R zb}WN_&9rs!s$Pta2-iRts2^?~G(HQ%-jpLpKfJAkR%hAT2gbsAL}xO6W0wzg@z%15cHEoO_h;tg-3#u3}XZEUq>t)ysrv5k_H8&zg;5`&JYS3#82R*{XJ zL|dD7)7mD;rYhRd27Iu*txfP0hPkS(5;FbVsCm1(Y4{ZlZC5u9af5R^wLVBt)o6Cl z9aU1ZdxA&+lU7VN}M^ALHX&d-S7Rt@%x$KYsGCL|U6KJ8Fj?h-ilV4FJ`54{Xv99xA zMCz#6-$63xsxJ79y5(XzRwmz>Z7+mOzayIF4Ux{75dNms z1yI5@AV(CCX|%7v2&9Vwl3b_**+(M^F~PO+Z_%bg^iFy5N6MrC#p{Q{y52FXvRR#M zUHknfqHeg~GNj85>DLWuhatTgY1e6<8$h3RvW>;I8F%?fDAu_r5v>Mx$;NCLpVgka z{(rQ6cYIaF)Av0mofHz%6G$N>0RlODLMN0Yl+cUxA|!++AVmZb#DpdYA~_fQU3H79^lpKqUnTiU)=I$5Z)lEOZD*2rtV#oUT{;=Zd8`js^Y{5YU+uV zaDESCZev@c3zQ|_a9u0RAiu8F;#yK54ezRSls{`q>$)m!ywAdA(_(KwQE^w0?M$y~ zvTbb~vVXSv{3ntGnav#!zv zy(tMtQo1RRb5Fdip6Khv_fCk4?LJ*ru{a{#&aQ6fn6RQ&AbJOf63dn(=Q|0ke&Fy6+qBT~~m>EoV?zBSa3 zQoDoVE#sFifpqwX=JwL(@5_ed`Y~;fTTS*ucVhAvrJoDY&^{ zUjx3(g*KZLb?T=yRrdXcdrgs;p&vbNW!`3D_-6em*wzoQVm3OmsHeoAQV@zsg> zHk&sc>8I4o4zI2riC#5o;^qg`DCBz2ch4H-o$vYHsYZDh$M0?OZqKXg9{_NwkzusW z_GgLP`d4D$JCcPBk4!Il1-gWMJ{qN*@@*o0N}u;vT4nP?dn4CFW+vo4qR znV1`=W7g$Tj;Hxu$E?ex6cdxiOF#~W>Mb6Dp`NujRA|3LpEWTCP<^h^NR7Y*XyN#lvF? z0h9Kz1H}{%Z9gvMF`Nes$J$1IIG>yof$b~!^A1v4%Vk|@>mVg6sW1!vCg-sB?Sq?V zN7Tr(G>4BNpv6vqRbMM^c}ng;ECHom9g{XU;E>=t1&+B_x>EXJC8FJPs&)=zv=+66 zIMi16KDDiIHy1H@+#_H&qAgPBV5M#yleDXy1 zDrP;PLUS%uRan`TmJUIMKH3}Do9&JYk2+NNl~G}GjSBtdHjJmb3nh2*9jdrUP82j$ z>EK+ON7r|lTZkOsPLB;$nn`YmilDR(_t0y_Z*0k2HY!(ye;9ii|aX*Dz(Cbe6h|P&(KBy^VGbQ|U!i;O|gDu+iQ#v~9Su zPFlzLy9i@6`yu;rMAo#&{5Mzc#e5nx_Yuk~(hx432Fkgfq~qEPryP@#qO5n5%Wc4NqJK9@A%J)xoxKYmk!s zpvh9#oGdd?-PH><5pbQNM>9FYfT8Oq|D*ZQ9TgsRs1T>Xxx!@o3UwE(iqT3lIo6dD zGnC=k;A6SAfO=Y8aQU;CRa!4OoPxD23SGfHghRfguI8bhZ z17#deCE0t5p^mHf^U7=QQ{^%kq%R{a9;@lT44b0V_- zK$(xA;BGqg2;Ok4a1!3K>Chy+Wl-v5Wv1N8iCiZr1IS|vs%St9CZOtPrzqjFn-je` zMVTw%=;EU&^(C!&6s6uFzo{s-N;XRUI2EO)lQa!!17w;#4F#H$It7(j`Wg0&n zX@67kbYwXr8O65EKrw_(nSqMeQA{L&dX|nNB01=uL15NTO$-P-X@{ImH}M zyR&Fbki&nDGQ)p}_0dFkcW0|OTs{jIr?EnGQT`+15dEqh9-uNX_EJL+BPQ11%V+ts1`E&A~(WndJ90NEYaNZVX4nafB1 zcnHP(z8{P(g-#^8`%}hz#YZvZg73>KX|O~6!%=^rL;auAYx9+iAS`9~)DOXE>oZE6 zFnRqOs4>Q&#(30NGN~rAaFG9LWwPHvhvX;d{L{)%sg(ZnW=K$-%?@9O{6pijm8t%V z9MW6;Q%=E8dp=B^a}?h?Sq@)=Q7T6nG$MaImSzbDz^eLSEXn!f(Jvk&bBWF$k0n|k zLt{zKACDzk|8BiwiPpax!eRb+h)D~SXh;m^dVKDBC1w3mlN=^sJ+1Em8Em5ql*#^1 z4#@>~t?n#TeEmuvsX20(y9<@UAv#o5J+UBx90_d1D~9CrIN-SUa}^x9OqMsXZtifX zay&I!qzq)T&R(Q6ZRv!0X;F4pRB_0miqBESVuvbP-=&g8$_V)qrp96=NCsI9S**mV zCRzBSnim|Zc?s3@cc{kYF8yb*GCN3dNH4upjsSI3DU zy>VDX58?!CL?G_!Td9OeUlgoeiFKvk2`4rS$$7`|A89&iTbdQ9Y?YFfU5Loj+H-TS zV<*Lkr4QEB{CC+n@CS)FH?y{JdWN4fYP<2JHlW-%E!&~YS-Udh{L}SqLA{K>TLqSu zeA_2&tHNSi=kp%>A|2*W1wP&D#uWL&BP{6q8G6G?rZG3{ZnO3~YRv)#(Xn$VT+QzIOmGI=e|#=VDHf_#wbCjx@5ge=vP=?7LFy}P6&Wn4EcQ1- zyTv$HnLh@6UP=0yyWJM($yyJ9UJCPt6N0;Pn^yer3%har7$9w;XJ1r$dxdFrLTxY3 zQ*2kq*QSyem7VVBB|>@ybfrye6eS3q+iP>ZlmpK0i&Amu@L^jBm90^Fw~7adnE;Uw zBNsmb5a;2S1*=Ii!jj|LMjZ8uwgqd&*+^fc)8bXzveq>DB_%2zsfaE(Z ztbxfyXg~|d5Q%oYq_hK+&xKS$dFv%5UCwDlok-a|+JJUm7xQ*pT;^-xZWQWf+!bS> zqhV3Aa9DyPmZhyyD)PGCAAe&wG$HT@JAA-<^zh5dEI(f@9SumRq(1tehW?kntR&UV ziPeHGmD72Q=qB6-#~rXP@52uJT1D_BJY)HajuK?Q*N%Epgpf( zWjaPb^WP!5`--wvT0vXZDcSPmM=0)9CBk`yD-MF}BPD=FzN&c1K{sjAtIC{sV=$ja zU-e*;CQ(}$Z4JneXhY)$U9my{3$5mH53KIiv&SI00JJ5#)e! z@%UCn4tB^o4e3PDAEb;rdtu0xJliLMTsJ7uPFJ&PQ{xSanw=lr&{s=?Z)D%5h_v8jYxw~H z;iwAwUfgquT77)$hHn|Nt>rd+8=YhOGX-MW=v>>Mh!_Eby_C0++2Rkfwh)}SJ@VRc z+sG?sJqy64qlboL&wk#HmiSg=v$eW=J9}HDle4zZiB4}&0-f`tpYx+@8fTcLYufOc^*-lyryQejyRmZh1GZO$v0v}>f_8NH0t-@FsPY8+(KHP2 zOsq;z=xjZAu?-jBV(8sIL*~WcG|6u$+iUxRR%G1n#W&PA=bbL7ctdF=Nkyc-siY&G z{*!MiJvlV(n@X1SIyKs=ye-d6pzpRS56PnvsPS7$54mRo&3;RnD>q4?zurEq~s|RQRB8eB^yCXk<^MZ-c~w;0pWR`JY^i!e@BV) zTL?j#L79$!9-e1t*gHysT>Bb5^N!L}{<0UH_3>!*(p`7=zzGBIou^+EgubhMFT-;1 z=XRx&>x8l38wnKgo|5bbslt*92Xb;NJ=tDZOdU&K=c7xBV=3%CrH4~EvPHh8hEe-L zzMkNlE8hbIVU6kZdrF!Q2Ql0?@;3ESZPbZV!B{aXmX3jAU*Ie2xP_hafc96 zQYVLJ>9rlozz!xg6r0qr8~3f)Q^OX#-;Wy1bW+||A`9xI*htndjzc+*Yv>d0655Bi zsK;RLf*S|@yg&Hc``-(GovU=~7bS_B>{Mb6Y(uR3Ux2@OAB2OQN z5a$4W*1o!0X^gF6Goa4`^xyAPS_E#bFc>w&oO~O)SJFvB(3t35N;q~u+V4`fI>(@Y zBwni%AiYO-cPX9iQ4;8RpFT~cXFpbkTC^LDooc4+|0(T8?pETw?0S2l2L?wjER=q?_PQ*xYhqp^!x`kAsv_8Lu_4k`7W6Yc=|j6;wrizfQG(6M!)Zqi5e>memM z@Cs^j6t)&po5RXjB|BKv zoZ1*_fUaX8PA##W7`(?DsG|e@vN;$iOaNE0NCrx0rLCiVLLnUn`yv zQM!K(n))7*tsQA<60QAOS?SaiamX7TSK?b0eW5RPM*I~lb46Gni-3`0ENnmG+d^O^ z4JvAhsjpxeEVO;qhL#>z>NT>k@+1tSB?(n4p&p!vwZsd+6l3KC9XqZxiVM?v)UuG0 zUQve8sf6ad5pE%R7@BzWIMH^M>J}bAMgd5#o+!$ zuvAgXNmv8($0m2KIK!_QCzYNa`B@#!*AGrYdi;oHd<)^y>l@|KmOEo10OK;TMG*NR z3$Vz)_RpJCneD#q_~+%62Hiv#Y#7tPYKCqz2}H0EB`QVNGN-{8c{Okek19ZpOvWAZrWZ5|B=qNKR3cW!rnDS z91{=j0lPTe9lBq6rG7b!4Z5EV$N%3)`lP?#Bj3w~yY7l^o`N&b6rH4;EH>!pQt@SlJAr?BB2=HDMZwZuP%I zN>}>)TP4Ap{WJb6oWvtGx+B|JUPf&%D$S_(X{E{k31a5LUg9v-pv^(0H>R477|%1x zRtLm9NBhqxo8=M1=+;T40WJSY8F9b)(&37Mna7Vj7&GCZ@HlJlBD@wx;keU*g5!{mv$~eU$HQyz#z{l2{CF7{?-Q@Pp0IO%lE;Qpy(kwc1}4i zx42HPpH~v4J#_4RO%*CA_&(j5dyci*0m(YEuA$K8Iw-Wc(ERSF(B|4Jv^C5>)4oLq z6-%M@w-j0^x28h7>zb+1cEvr&b_#8T144q<<4PDumL{KLmNuk=3Avpv``?C~b=l(= zYwEH$z5yr`fE7!Z&55vdSp>F=qu^hm%hF{-mxbhr@rNV?UG^wt{t5%{FZATE%0UE^ zZvUGS?Cgdf8Y=A?dh|C3d|c^#Z?7II{r`uLbncpk4;!=q!@!{9fiA3#C;$?UGo10A77tzz=sV}0g@SP3)T3T_WQl~*g(=Bz{f`v`iF8*-ZPLo{H6ps zpZ(KBi2P^?P5n*jR6~P3(&=7|G%or7hmlC`oQ08`)-^CP?J6+x2*A}%J~!B)=2m6$ zxo3v-y$|F&ivPc0}E)QR*us>7)eZrLd%z7+0T$US=WhmC}Sq~`kP(Fi!gJZ z&!V}%Dp7C|TlcH7QC>5^Kvlt23sqf;=|9&TP_;hoUR24&wESa5p+~O6ZsH(*u7fSg zo<%Rg`~6f5Go6lKuW2^{!!3tZCCbF>WQ`3{7-wLFFv6+Yc4($3IP%fv&C6he8BEX z4gC!ZPLOsEe8KAAh?`2nz?vN-?EmoMbKOa*u@h4XKW|34u9fnlgzsXEJ<59;C`WqN zF?9MSJRp}}0gk7C6Ba-je=E-3!PY?G%DiRwAE=;dsrMrOXuSZT2k=tEyYQ~#Rc!(hRuFffBNUP@{rTehptm)g?~Mo zen%NA-KJA_l!W-!`+wtaf-+7k_-M(0gOUos><7iNpYb&0LHP~-RA-|a1X6CL z;u40Xjzj5Jf_T~J##CSp&Gt$~8SSY}83ihUd9WP2s2^a|UObRkV@~#g4$pJa5kXx6 zOD240?h6ap0>iRvO?wem7dAn6tr$mJDzS0Jwn7Ie!q%)5wTExe&ujT>$qdg3WCW6` zs1itGs;mJ6#v_D@1O^g&7^-F%?1>D+iVO6-EJEvI662N;2*s7yIAK$l1DU`vK^C>M z4KV6z-V6q;g*Cu<*#KiBqX6_H@pd<8gXxnmf9DB;wESq$22YS0;DV-$5&p-4@wf3HYY<>TM+`*9j z7XukvJ&^6R5-|A6NDO57{Rc8o@z=Im0GQL*;4jV=Ci88$9>$vPiz(Vk1aviR!Mx|k zxVs6BiJ$K?7P-1djz6FX##s1QjRgX#wkD9aPE;l~y|gD8lmW1HgFTrMB^mpv7;rBB=?JQ19xVqFu zbdtUM((5jwF`xZ&5z}k+bJk)pWw%5n6?AeHNmAT0ML$Q=r~tl!XV9hZfuTh(5`tmo ze^O3eup_#~=0@w>#KUr*4Rp&*M8MP>>Mj!GtUlD$U5s;s^4LKW$7zSVi07ldhyJK+ zo=e5SmuFiL@B}_`Ze|oHWgpQHH(!40CBmqik7&?+mwinp{KZ>y zcHxd??XQo^xt08Az98|x=)-YpT1PbJVZu!yXv7*Osj3UjaoOOw+G1H9n}=51$z7}L zd7aWQB55`cs;n*gce;od_fU83;#ph8MNH9)m++4j(0!YecCif4ShX%*Gt*8*Y8S8I z8BF=&Z9Og5y}zK3SK5|~bam^UKz?HhD}#Uop{R!q%UAaRd*YZes({`1KVlE)wXHpF>&~dCxj_O58fkI@4YCpm_zSlCQBUBhj z6qCtE`-anDOwWWdJrk=7((`TIlC)!-?qwL?dEwX77l&v^INjGsugd>;5*-W_kHwly z;K}zN+^w#k(C{G9u(n@yC!A#1AG9D5Ea7BdkT@$3ze2-ZM4G&yht6~4q#x*3u=qSK zH_JI$YXD$Q?YMsfEZ1(LUqeK5Im4MELq(XM{b+TPw6L+%BUG#kIx4iX_u&%-N-Nuo ze^6xE^+>uB3eqktTb4}mVWOpcRM6-!F}abuRtBC{22w2pdFq)VnUDz*ZeGLR?I z3d`IR=vtWQ5Oh6KEBn&?20mzgOAi+ve074wUIz0o@W!pQCR{`YCBsED6HFPL9m0Ev zR_qS$8N0`i`T z5ub6amJV98qx5D2V|5=_QQ3SoooXOD%kH4!SWy@3JSwS*okv5wh=!QaCX@QaiY89M zxQ~23a)qMN^Y9HbDY2?iF@$!+iarwb`#7QSv57eGzT9^^U5FF);f3K5FFN8rvhMMs zS^GmL5C;krzZm)(Z{AWUlJK~LCww}Z9Je=xA(XM#0 zLLTyFLDz=jQ%R0FL9UI(s2ESwnc`vlz}Yut*OqI`Pr6)w_pkLfmxN6CDaGneHXUeb zW6=`6h?s$qc~8)x#v(E~9M_UE>(<#hlE29)rzT)y=OJ`&!CfTv`1yr(C$}8iqE}Z8 zp9=FEMJ9-P$=(P%Uy987#U)!Yo8N}}12gd-%&puQmns=&)0vx8ySj3EB0)5jlYgQ& z6GTdQur>xeA(me>CVj5uZ+(=cCZa(I2Hurf09XcCfHCl!ojFi_6EVWGE4-{Nz&1A# zhvcv>G^weGc7>6-C5K#ZDw<_G!TY&*T1rI_R*@)|l!^fS7wP(UeeHJ`7A&<667kjO zPudw$GHeLCo`c0L11qg9$5m?skKW#`MJUbo6ReJ!Vo!n9HKr+qP}<4&_iCxqbG%U%OivL z!BTbv#ZqHcY>qZxnIv7{n%oB0xq)Q!vx;JMx8y)i`a>0QvfC&MN-{*+&k?|0#Q0QI zjS1A~G(DXpPD(qee>0K9;Y2%Vb2*zX(!GhsPt&euqLuVA{n<>ckRGM^&8>V2=ZkE! z@%N{`nFrgF?!$=!tKh>B<%E+b6Epwj0Dg$a5Ip#FId*Pq`fVa&Kno$V!#hA_XX6=DBKS?qmfsxs>`_D1jC=3HPIOU zN}z-KjcnG4R;Kv4VI%*^mg2V43b*Uj@vvK{+^djYXeF9-3(=zC*vsGPBE$5^!rZ8VE#A%s($+fkJathJ@LycOCc)4yN zJ=9w4bpx9TK8S+|QEf#Ci8i7)gd^<^EodWN-< zx*eb;cKs3I#zc4^GL3^;TLiAaih3mP<@clx&h_iphscdp26t(|8hIXu3_dr)<7)9S zZ&cht=<%7sv^t6y+3QCdgMY4cJSr_QD=o$LbV*Mdl?vtQgN~vXw#cOv5iB?Un!-{< zW@F59X5w<58(Ly7qI2oEZV&dtMP`fEje+awGCD?kQbdxc4q6G$c}47}TPaYb*HLV$ zs9#41Pj4M74|nM?8kQ<12gaah){t9Aun-_JRkX~`AJ-|Rq6-vqYqDo#abO=>I5Jkv?P)Qa-f%v`8%T` z10$WmBaQDM(SSNU(s*VoG#bs#DmAX?;^#4?Zp?ObZB1ZG1lv9PcqLDh!ZFqza8A{b z=Vq1}2MW1hMwwg1I}CX|3=x1B7S^k2MQwBzS_E~E@2x%;4!|*~889oYI36^^g7C#; zQpW zzjN;~f_?NMECRGVga>#l9?vEYb2Bg5jl?Clib*^YF~&&fy_<+F5!eEODvU&3Z4(Xa zEb3+B8Y>X8o}nSSj|?xN)nsU-8E>cF1;O8CVzdfzUi2V8?OS#$p1)(oee&KXe{Nbg zW7M*({Kw6@v+q|q0EvNu^|(W3a~O_*{=b+wuirHIX2-@`|+ zK9(nR%$Dnkt8yRjBDyt>GF?Tl!B}!0wc(Nho-6tZQsz2Ls;p%8JVh6}U?O_It4j(n zAh>BIn16hgT~Q<;vQKY?v}9Yw2n^+z^iCBe9bp;+zDhd5lE>uz6AVSX67XEbu(QwI zm#^Z?A#lcX&w}XyU@8Gjd}KhM2CKU@+BL=ws4xtHHJ4yP&`CdqEeg2Bmim=9s>`t; zx{Ap-w$?jcyf5XF)J+VK(_f>(-9+P{$5DJTevCGY&3k@DFLe{2%FPfnw7YnzUMP<; z;0w0PXYr>06nOLyqb2EMdZed#(WAKwWRdwhfL%5}<(9*me^C-5zc*3VqRg#=H+?DeBi%rra)cYZkR0m>@4JU9}0B5b( zC2uEb4~bTC(zo=*Lqd4dAZggajNR1r6t(*?J^Z5c?HdqNXJHckyF|{I< zP52G`D1I<9r9C)PVKf$%rGv$|$mstfljjg*vOPFcZggu`S~WzpkNowm`@(xD>KdD0-P=I;h!|8t0Nj*M?>9r?sE{x0Y7cbz~X67e)fEP!F6Q{WOnavfJA z+aIpWBER8K`4HV@xWI)iuG)TDIb4LeAB_da%HDx6qj>W(#fkIg+Us9P-whWt3xRaKT6EU=QtmuMpX=lfZM9vYilj@8UNnxvxqps0rU8tu7^>JOXxZr4< zi04+p)y9d5@~kMmFsFP&e&f)!l<^`Yw9f-7D54qT#V0HPvzWVzT1*hl61d%mJJ7!HLm%QioXBV(B*Sr<_b1gj2-?6Of`RN@?s`9(#Ev!n<-jS_8yCT1H z-cyu0QH0BWpV8A3#XO$yObE+JdIUz5bEG~ZG8h7c%Y8(&mcLJ-Cf-RRU2f=4e@zm}h63P{hb~SA)Ajh8rcM^& ze6l+W^NZJW7Km|re=;P4}pJvv#`bu9V1UXr~Orihl# zxm!{?Qtd~@Bp6k+yC0fLf-!@tj2&5DQr=XdxIj7G;zYkp74e+=>;rOl`I3C5ifqoZ z^8r~Rj0$lV`st}6fpfm{fSfkHvP9}PO?2TQolR?}iG-%tAgb^=_H$5aSi#`)^^34= zhn1Pv-@mZ2PWlR^zZhG$KAJV4jA}(rL{yibEvK?f)r+r%lGWMgf%jm~h5%*ENrcSyBXf&V-Tv?NsVCQw;Zp zB*}tciPPL2L3b!`CMf21SNeXYNOVGcB>HKlXh2OK7w(Z9dIvo3gDMxIm_==VN6B!g z(-ROj=J*q$5k2*|XvD#C!e@!tmmU``{5%cM^!MZ7#Kwn*%)}%Y#P2I>Mz>~(IQnXq zXoT}rH)e?>x$RwQJR7qKF=^6gi&W`1dUm$pNQnn#Lk#nz#3!IIe?XZ}h`Jn9C;JJZ zN*m}seno5@z|p)lJk&aBrRnfxK{UEWP-HkH>llP&E$L~icxOX7$<|rZzK|mZ=!Pn| z8Anm_94ueCyvX!QsTLeZKnJt@6v{do!t5KgV2+5z^0jpiK)*vL=7>=P^W7IjY2i;! z(65T+kr~g?CxMGd9J|?o6B&A%9*q^pa2g=+lx@Q6{5>4jn9RzQySAvzh|k=OQ;m8W zc*UY8MO-o{Q$J(vHh;%%7(T3LO!m8_UO6Y7VbD4c(JjiUreQRsHybm?#02=+bTeCZ zEpL*?ToE4N=}^GQD&Vz&jZ4saiXmO=RTwGIE^4G;-wWO%Q0eqMR5VXGQ~q4x5oAVt z%nY#&tdH|GHntURXivxIiU`>~magDG+|08vz{sOF2{p2+I&L!G27Qkm0gMJl&J*1m z*aZpY5w+sqrXrp$+g(zj{(MZ*QzDq*@ea`A6uVr?L^$1)r&3n)=X3nIT?4ydrg}wY z2+C9h(zPnWEi6xo`knLBKvL|FvdNL8puyPmeZeFsgR*u)TqhatY3%02nhi7=U1RCx zM@OEr$g5GuYDY7B@;V2R3S2B;0eR0Cp-y31>1yeMfA(g!l$jBuNeTY2G9rCnBp6x^3gWMwxu@t)xPm3OPa<>$z#)d|W1X6Ix z`;}HcEt;)bR;{*AAC6n?fC$Rfss_vn`#5lQ9QBFPAI-~T;I z%n|*~nD_ci6up@vR3jx;FVNozMqiujiKf8|M0+FQ2CZEnTDHVVUno1!JI_N(cm~X* zDpDU9j833+!wjbd?8!2KEVte!mxUs!Rv|AbEM0s>sS6>Fq#vc(3n34c^?)8ksjIOe z-upctcdtFwqN2NgX=K5#3&j9QLiC`;;v4Dr0>34&DLXxX?HWa9;7SwkN`FrY4(88@ z@$GV>Z3$Ykc|SEyCc|aK2^%zs+6H=G3R*JKT=ldfY}zbDniFJ3gchdSOGTuRMKpRymOHkl&hDMczbMLfHsTEW4UIFfPGAst!4 z!m$so6ui7b9P??e^>1Q?v77t_WSo9#lMoIH`kYuATK_Yq6qmdx{OeR^n%?ti!AdbF z5>W_#eitGv7IC(7bMuy+yA#{}b6i{-L~tq#ZKaUmi^1`WbpHaxFMzGdwLJ}gUUZOf zs`q&@lvTbrkgL`~y7jz>48^#e3bve;s}a%pV@g^j1`qiS-;D9~*2lM)$Co7#eSE#N zxiAJ4_kHmAo;+ZV@93)W#j+&R*;OJYzL}PV;>O^%zjts)8-x2XHOj@{9(u(bTw5|t z$Q4npARsU8b6S}zzV^k^)m&?sV2p6u=htcbuSuca$9I`L3ZB|i^Z+4aw1>=xU6wRhgZs6#Dt9Q8T}==2Lh;cZfVxUrb-V{;;klq{08 zZz+1U=;+tluI+P_wrwZ9_o`<-dVV#Q1rr6|(dVm0REW)6+lad^jNPtk4EU0|3etPP ziy~Cs;7!VlA}pzu%=p*s5{H1p9oUs%JE+d1nx*MM^Y}TVnQW}z8PPNkiMtfusHF#OZT8h- zCy~awQMu$G6k!kJJ9{gX?sfRS7cOY#_ZZY%y4&IVZkzU-RUQ%#OlCFf&#uH)k(q%_ zsHND6r~v?WB2Js%J8=Uy9lqbh{eD(?$Q-5D9KK((Xw644GTWan{Q!LrQXZkPy1r`28cO(sNA#D0)#g+bxQJ}NW& z)SczjjiSeg$5XpUT-@m@iFR`APD*@PJR>{pEcobUQA-N%{4!=MY^b_7E_9(H<~}Uw zS|UKqP}##asM#@J?m(#pL%ItTX#4^))fk z%7QDLUV|lY4PAastdpLnXI~fJ%R@h+fBt~=Y5sa~P>wQR9^N2^dtJ@MnIr636{e-Q z7989l-jm=xnz$$y`k~9WM4}u3ufA;}Dn$pwAK@BI3o3jVmMlIyTn%ofZ+2dKxX83jzg@! zLr>GcBaof`4p~(HZoMN8vHl$@xBlIUT7Do#v@oL(`@B_2D>d$hB|LS|G^~iM^0BZ! z9(H2m*)uQeV;WV0LA;i)15b576w{n@;hjUPJ`}TM+$Q1nk@%R6CI>$fn^<`D+$kQR z!U8ywLITFiCbm*+--%3kpS(+aJ3^RbBbL4QHR0Sqf*G1JzM#m{m6 zCFPU?PY>M*rjsG8=CuQ4ld(%R&4{U*;Y4}6MceS*tMqxDUnA}%E2SG^sdBf7O2}mr z9Kq)=AolXSPKHgxn%5U*8YK8WrrL#>G}S*Oh%!DAuCQ)Q_(c2y!%WvbVmsSs_J~Cd zbG$Skz^d=Gb;P7bMK+`vR(tp*!mWz6o)2i_r|_&u+C^V{D#B6t!l&X08+Eqt6^~P^ z0&MVj(tmb}5%lgpkwmLLg8e9?KsY;PV7O}Uhuvw_E~I-v8s{KKAT4Gi^^DvJ9`6{TlVE3&*&IQnhwSSNb=E72!>!3rHyn6-#dx*a=M z@9UoL`HZQuuSC5rMa(pTtY`>e#qp^YvI;F^mA;*-GvO!UKgG{1a5MjdZUgkg0g{QD z_8%8R3pO4D@g=|q(!?0=skV|BV}%YF%V&(GzD83E!C!FWbfJiJWvDZ8^G6|ud;Qm< zJ54_<0x0E#@TBz5;X^v{gz$3HGhtljoxmVfeuk`tCm?8T{!G++>7+<7a&|i@yo~BR zY4}Oe)X12B5*bTB7a0`ujcCjx-uD}Ei!p%_|BK%{o)Q=MJ^nlK1^-|BPP``NllHw3 z{Q2PbVk1KRkNW|x|M~H@hcGXJGN2^h2^$Jb>0WL3~nx#LZ5$AkL`vo2|Xmr9asP-gzoJA}6 ztenN`20Fp7fc@rKkx5g|pysKxwg}43Rag#bZ;@C)4S&W$-eNmFT`Z!J48q-9Ear1^ zTkKTarH4zfimjxTC8AR9y@j4H71?r*7XlH$!#8#dC7#3B{q+XVgD?s>FLLBB^_RK@ zJI;eC^PX!7>=h|Qo66wwiRKw-a%zWU<$tBC5H z&%|y+{pYbU$gTt6OjU~`?=Z5&F_hH@Jja6Au@qJmM;gk1sXvr|tW3v$6%kEwZ0%x< zDOse%YOG&!T@3F6D4*xRL(gNwi7ozV?@-upVx6@ef{W*W6Ri^C|AV;+C`yqt6Ofd| zr&NrAn#i?SA!pg#!8O?4q57A^Y{&>}FX7b8Q&fCOC~}j{#y~gu9bR{6cM96&@Ua-? zfY<2Q@383{Er`AhbG#qqxedBoO=GQOnxxJAi(3964ofr0?|1A|2VN0hq2n4Z622l% z*1_zrnf>d6&#%H7E^ppw$R_>&f`vv$!^hD;6+9=bu2-R|Q#Go7rDK1IUQywQItEN- z8JNl)vm(8M{V{;4e8$vE)aIIKE^-33WvCOwnH!yA95)R&7mtlRtQe5{ z2ArqYu8DyG==>6VWu%s27WUP z&~QUU@rQRnZ0)yE;ter?cb<7ne}_8DW7=dJy>LTJvy#u7$zI#2&P_3ZrMfLBe3>4_ zn_mk-P0asE^z7g4P-@eftfm8hi|66!(Z50@#5RQ+K#`M2 zUNimQEl}vCvo`wnB^Oi{CF2ZZ# zmIw)YK(4*Fu=|EwuT#Y>(SWa*xTh{~j%K$-To43`d%l6mOyh44DEIblc&|L5+@;$h zDG4nPe4(6T!PYKh0f7@^{~j*c0`xvSpj_WOA}IpplDQn1uvus0Sft{arDNM-rRi|3D-ezKt6HBX)BN&b|C2^7#pO zcUOvdizpTw|x`L8Dn0>oVS8GzYR9(4?7x|GloBqM#`#tc9z{X z#>+3_Dy^q6+E_;R=?1V4TKH1DFG6V$oPFMv$m`{h*Y^Q=7b36Zkk`e?o2^&e$*0<2 z`~))Jm|q11W^f1X)-w)3n0qQykoS^9-YbrIO+#`f@)kMdJ@*W#+UlJSglQZejLfGT zGXMC1ihCmO7Y=#9en8$7XqVZ3Bw8Tz2lknfcc)!m9UW%x8YAyEhrI9F z<+ZOj5_w-Y^JW6i`Veoj%dA&y?h*wc^J<5R=>d5?kaw9wUIZI+R^#Oxuky+gLGCW< z2D$4^%5zbdXU8LN31kra*ou1G#YpfS`)_O#fw5vAn?(YA%$p5(XU8~>`tut%DZruK z5QdTEZg7qL-&`ZeKCM`II17Q%>~n;+AJZWkAz!?a*>MGVicYwyWgcnRBH$J3DDBU6 z4xu02)TabY)_o9UQ(t~7n+`?DiDk#aQU31FZPE2PXITXnSn|B8%%@mF7;C3;NrR^BeP2$6v~ld%Lh5 z_Ihh|ovyn(6*Q@(dP~g_1bR)lX{*VJ*KIYW7#k;pYwMQwMc~>c=oAZHEGb+rc+^u( zmZS>>+q~4RlJrzTe;>6#k`rH{TE1$R1f1J3RT^v^GVnGBl?Hq0x=PbwCC&9!<8VFL zMqf496`VXb!;L=mRU@Pd`q@`aYnyL_7ixGIWG0*qfa$rAP0zu2*9SbsI8B4qrAq(e zBlJAbQ)!r=nk{`?@S~sVB+0|p(l2$?j_ngE>MkW%iwrek+vjBvgQ?JS ztCo`jAID-CAE(qnb#njiPwME#a*A_|@fa~|YUt!$7a^hiQ+AYKqt)8DblrH9+H-!O zdjl+m%n?%;R->D3jR@8ps7{k+(W5~su4^lB30D0jx$(;s7NVxRU_5(<(D)FwZ$k`a z%Mgop>+0Y#n3gKb+jk7+O8PlOJt%wCqD`Sd7Ea5D0_%^{j4<_s)~N24U_+$M@nZD& zX)oa&Dlei=8|1`wR+;|Hu3x5y!_{_{Yf~w9Rk)?o1>3?^H%WFTT~06fs;=5klAbN7 z7om=jlUXW5>jh3Qn)>=3b)-1gQ z+#9gf(m0xCM5_&FL+aLSsL+Cuw_A%z-P0_Rs}JOxDD5ESY?ReN9c=BgIzLxQ zi)K}!9mCu~TZ&b*2$nuJiIrfB2W&mx+G+iJMI}AqkbmC2`3o(Fgx`^WvP1r9$e-=d zKw*}-#uTBzXomt>_coAkUB~q;@(*yxKjeP-&8_02$e%t7H%FL+uJ^d-y#=ZO`UC}% z9UAC(Z~m$g%13_1A%8RE*I9oI4t~Vj+LRq zFJ3(hy%I^0a+4RSPDAyTh~741SB_oHOKKZ#6E@g^4L?)r@uj~)6%ExaDcY_oT#nU9 zJ?QjX#RxL(mh0{q&P~Ubsbom-}Y}+aVChe~iR3#hC zW2`@7E}JU#esH(X!1H;}43ncUGut>jz|R@kIE3QGT4b0u#Gy=qeHqvWqQMdMGK;J- zaas?DGI=PIUDeQ1yFyE?LXEWc4uxK`ZwRVwRYNP>Dl&B7T4}7cO>+!#Q( ziaJg9ew7|m)Siv8H}i+TE&uCOSM3idke3O+btx5>ZMF}Y;2y=54*GYg4V5WsI{p-) z9+T$NT>&AoOruF-)rf-5s`|1V{+hl$fU8{K?fXjAR)JF<;W@H%XrSCwBcJAKsB^w8 zstqMHSKsq{m_MIXzk0N)rCQeowKven_fE42`nsjsTDIv$5r=y;Db9CcKK;Ru}CTGhk&C-;eM;XM8~xIN_0a0*}_#@1?% z=V}u^GU5A{X0%bq#9}UYGzZ+coJg*lQZWMY*Hfe5aE)Q+?>hXrJGreo3ZUjhYcKUy z18GTHbueC2VlFTC!s>&RO%#b(gHxk~baw7py0n9)e*Fpcj zFVgsqD`Sm>4N)5HdqfGOE*-55Bpy=&Vd?v*qq=|!l2!jGV+f2h8BTfQsiu4s^gK;U zQKLZ%wg_64qSnPzQ3P!_o}%i}@f5W`iDcE))uxSyXPk~M1QP9@s*a*3T7Wqpp5^Sr zf>5eD*ZFF6Q~;%?sZDFGUI|w3mQwL+8p)iJW?N_wfYI#>Fg{JKD1{fe|MY8NShzV8Ae!=3J3)b-NWw6?1n6_BH7P5&|1 z1Cway)3L7VNGD7cD)MoH`9EEq&cW@{)flhj=L~2Lv040TirUiENy~$`mO*^=pQEt;K{+kd5Hz{5 zhe{q}uzSJ-aM1`AII5?b0?BxNPqnGseg%EqQ_aAu(hIMlD`-?N^&{yL1@^{zc#@v% zt)BIGWw}-UMC*`vTGj_TQ3&nrgQ37NuRiKz>0#>KS6wBySx&$7Rj11JmRHRzXKnd= zR_Em9^l?9Rjdy;=L9<^+s;5hT^Ipei_P^#`%H*W#?Ad{w|h>QvgAiZ_6(%nv(#sx`j8uD8?HobLt6)``r#rzYcP*m3{n&L zj^;sN3$XvM8>BXJ-+CV1g|0=p&$@(o7c9e@8I-cfuzk7?R`)A~_7NmD`oqkN2ok3P zpe{otONGz;ZTQ$)4pFr=x-nRt&>UHekQHNS@2Pkx?n#10sxsN0BnGN1LaoI<)Lag zNY-PR+Dk6QZK}i64suQ_qG9Sokny!*x;zXVGn2fBtBd%$>*4BS&V^|?P04M9+QscK zM(?n#BMlg#_LknFjU&`15T(B!q4q$$i_nqkW^AVH8L9T{*oQ{|UJ&fPyogO%`wbhAyMyoMyZrD_b1Y$RgQUiG#s_$s^ zF?8bqzR~4TYOqlugnqj!Ao53MsF`xNJ+v@GeP~ejcvx9s>(|vn-W$ZOK@nR4{#Lb( zxKFHPbG2I7?)jTE6Zv`h%`w%&C#F@iJxdt9K#elhti%m0!a!iGbb;muZIdae#=a4% zwt0h$b82ac?(}h{8YY#~sZ6ycuHA!`gU53791sAu53&)G@fWrtJ&xH2Hz{XQ|`E&@qJn z!b%y9SVh~XVlL`O`dsp+Q0iC+96?K1;FuIi*!Qmw2`4S5neHW+x&)e>o5cDn!o7PI zTpO#(vaxd|=RHDq$E#IA06@AC6I4A2Kr!|#;2AwZZ3frK_a>+ff&k5U*jX+(rRp}8 zgmLFzKc3%Q};*JvHX?aMy#NZ9#tn>uN_uU;CwE;m>#9E+=Tb-L&t7`^&=vI8bhQXY zzL}x6h^u2)P` z!+mGCL(90q!3|50OWuOh*C>iNonYK7$;Rro&(vFTayZB^5`zO`zlH^KD=c@BNf5WS+PLAGrJN0Kn zYdEGqvxAXS-WPcO-0s_9yKe{aOc{5a>pBm?egWm&aSouT=BaJCIqrIK!Jc_)6PYIn zce>Zog1_ct4XC9@#JGTz&&V%FomBn4m6qhFkNN1|vnAV~9FAydfy)Az?%Xb5wLfgL z(dLC}qu62?rmcx|SbsJq(i#2P50Ja({Xl;%RDYFhbY>BzL#|zkS#~9s>(9P=iKWzH zv3eOLVwPYcbg(NCV^^ZJ{#;ux(L#TA%4>%I#^$rYf4uqJ6#otIOTZ5_iG`+vwg5a^IZjGd8a5pO6evWPbb&&KfQ!RW0Ie}Q;L&5;t{g3;Sz6kGIX1DTuf zTxCKrskzNl^vhDU6C;Unc6hNtu3eTvFo_;95*J@!9axN$5$9o;d;^h6L3mZ3=o4tk zv+6_(!95oj+;|pN(WqmK%jqlpET})%pA8rev8%I*U7d}rI{9Xam1>8;T%MaO$k`ye@LqS|4`?gj**TC}Jg??jOVTVl z_I&k{YD66El=IUK|W zv;Yb!fzWsOMx4~`um?lMA~=!X&7 ztda*saOfmlEydz<$?N!+j>O5E@E2wp8|m6(T?PVILp^f)29-EcE0Qqqg~rJB4j%n9 z$#yJQX`5)NrI`aQbh%2`SKI2>kRun4U9jOd-`3ZEF)YSn8Nk%oh&1%5(UoNZg{-wLvE=&E*0r`6O=oIg2I16NL~13DTJK@- zIH;Za)y*4JycXxnINyw^qxuE^UXP`Dp18z)e*5v;%sX;$FERddm3i#A_JjJ8^>9;b zv6==>ou8XpQ3Fma`Wf2$K1MoWw66q11poE6+AKEAy!#Zt9@D#Qy`wUfg0+ zEN#%CTWroGT!zH@!Tf6y+kk3qwap8SSD%`oOJ;&5CWd4dQ~p+4D$~bN%rW|PtL@Q< zBEE~Li%}xAdI@AODX{GoFcOG`L2A%Z=A`KYA?!cK@fSa+|FQ zCdqQbsM&U#&7V7l7eZOKTRufox7)gU6dW>n(MQ{DnQ@M%ZqYIPJBojXC;eJJYhrpB z&s2O4CrmLD^pP#YlItNwF{aKjOb1{%nu>#OX~-a^O;>lj!+|WzPta_7;{)5odSe<^ z7t-6qZ&L+5vI9cet&Bd~Q6;1*{k#K0I%R|uQV3Q%^|?|hqKoOe6XL|aQ2g>ug1pcEV}k7Wb$2H)oYU{Bl5w?@eXyTEx_Eaox1CH^cYU~p$GHW zG&%V9NZEsVY??m8Z}ebZv?)&Z;4T?clmBH~h$Zkzn&BxLd1qq&J-RTA-tiPo{29RL zus`O~YnN>iRPHH!qISSreZ(FMAv2GR3golaPn+>9BOXiIOxn8()BaeMl{TZC`tOF# zxJk2j!)B!5G?=T+I5G4#ouc1%qdOXvRO^n}Gk zv^`-?l45WPOK-)et5{sdzsssvd=9@gB~hF#9=C*=9sr9wJwe?LKp~3O6^7HC1GYht zs4!UFkO3=j82;%^EVqH-h83v&1YJB}8ykkBi!T`UirQ zLJ*!~T=lsvf~V}7XV8JqZ8093=Aut#9kO+#xG!vNJkU%}YEfwGV%WejwBZX|ZdkB- ze5_7PM)jH!AE$1IY}7=zgEIkE_A+$+K92cfy9np;0PS+i2zzwz$I0t(m1SH^nTO#- z@6)owwm1$ir7QnlGtD?3c-XcK=CF%VH|Ba6nbArZw=b*A;hT>AU)sFPLm=S_w88_U zNAt#y#(*Al^7!%C@;WrN;#tu1ENq=Cnx2no(@xL9L^MKxh(uf!sZvugP1RQ$Kju^T z*S0X$NVbmc9;41*+qyur4qQPupF|lM?sQc5^6zt)y7J>_qmlX+Fvr>c-J!H2wr4T;I()=7G_;XA2rZCOkW-!N)3wnqTB z{u^87!yV9u_W0Ki|N7!zF{}cI0CtyWo6B=c`K;+^x_s7jG!@U9EyZO2QQLTnxrL^p zFVOX)P|;T?;22c&L_l>FoiXq>&8An6*?M6GpVJ?Qd(DKAT(9++9mNkx@$8B@XEx&xU%6fkx zpEZ6Rz_Ya8F7qP8r#QxZ57JvqaVa#>rBIep$i?K}b)5Q-ZJ0Fg$_ZOjBXl@O6HXv> zNSWh!`-IKkEH=)*MH}$Xu&?jSXN{J%cy{+B9VXLHCvCl$13aqz!qMVK+kea~$N6AL zw^>xbqOilkX32Rhav9I?bDP{$1bh937-$cn}mBV496AZiCL_eNMTl{d<62 zobj*aXy#d4Xq$fpQ71F%c++goqToUT?K^855|&d_T|OKNx(H@EPUD&@x&E*uVzr;!F+63;=8aTYjLU=WK1d z{X2y`TKNBHtV-|xWNSzn#kSPwSGwJzHQ-NYEFf|yJZ`d9ui?~@U#-{{8vP8w4q(LC z8S@?zY*ux!7wPX}Tgs4fR_maPFntIUVG4^l$f(1=5hlVEBK&Nm`r)@Ug{hqkQz#c0 z_Vf712on!Nv@nUsEt*bhiLEim9XP}g&V!)lHJ!u9UNh)6Mn%Ik6N11bSXKJoqT6zg z-e+TGE#9~ps;tOr0R($@(w(Rkw~YxJ*7iiT0M+dRiVmNj1(_1(bWJ#d(;dWqm-8O!w1H z-F^Zib$!$W^H{*<@l|{`%;Qx4 z(pH6q(l-}v@kUTt_Yp0qtak~!=k%a5#)v1yP%WO^Oh5l(8^tQh*5XM@`_;A#PVZV7 zxQTEQJzc;(eVKnFoJ3C-a8F;vZ`sp1QAST=q^pIK-KKLmDTDuT8B0>mWdyRQf}LOd zbQw#A{W_i7ruEB3`K-0A4A0u6*<4I8X)~>VUAFbNm}9jrN+|sIE^3~obGHkEY|nKR96?Q9x~!vwBkA@m>zTNziu09j=z=$UZZ8{378Otkys2{ zGQJBgl0&R&V633z8<^laTOAZbR!?<2R_t6sf2C(`*t$Zz=9EC3o|oc<7@?y&lYe8H z3F4K<;x!GwHSyApHZc;2*WDXfkvu~6ZemA8IHljL3aQY8H*Jj*rXjAFihr#5ljUDc zz$VCNO~A(CS&M&=o#ZBTA1kzSi1Go=z6Fc$A*r_z|J?SjEhWwxz+^gm7xOq6U#8!yn&!%-NAAIe|3&%tY_HXZM0aq;*1-cPYaZrr2`hVHd z(0@ti&|h<_`Y(}x&#&q~1;1tgnOaKop!eTTf1&@D(5=60Eod*#cy;~TR)=j58wQN@ z{Ex5Y)_?d>$&kADy&%`pinw@5m3UTQ#4#!C&%AtS7?Pox1BF{LI%UNg%LCek5` zn5NtCsG0?a4S2SnwBi;MdiEDv2z_W34WkbxOY{KJ(IaXBdgqwxTgL^fXv32R;Xk9> zVC6IPp-nLVhLum%hc@-_TXth%Eu$NYbSrPhK66je0z2U_ThP)l?t><{Ocd0gc#G=c zpV4`B<+Ij#wehT3`L$Sg(X9N#UIJ-O>u8-gXy?Co;;>Pgm0yEYd9E`F9dJc;vY;{E zf_IK=@D|RY0pcugF|)ftLAC})_6!M0&*O%d(W_fu3GiR~qFV_*iQ)fCB*K!?2# zo6zOl#m0X7^FYrIpoCV`6#cDHY7SkmDT0m48>CizMD_fHVy>iz{6tdBSBND3jx`;R zl9!SIXO>yLd*%l3=MO5zbKuYPzMp6mnww-K36EDx8)Lf$c9EF)T-u!ubjeSIH^C{@ za(PZ3gRWB0${D_yFt$zO5Cs~C3+7RaS|S+x0;$f8&?xHIB+kc-J&m=*q+l=5!X3b~ zWz6kQFdixPPTTMcMK|_sNWT7JSG^;~+7rg|C4r`$42Nx7{-Qhc(bF3)WW+PZ&aE*c zXzD02)u)-mg@2ZgBj~%@VnhuOnWxuJ?c1B$))9@&M`?5&5i+%i-P?FjT-;1!<@@7M z8qd7pd3=z*dj&~FcXZ%WlQ{N}+D~=_pCDa@B3~jmM5n{7OEbjRh=iv>WiueN=eBxjSo|!IptCo4sUhTPcyA; zf_&1607?RVyfT1|0&iC*Ob!dA1nGqRLEGwT64Y;WohZsX+|+|w<1oIZ_i%bGP%LQK z9~7j4`SQL&z43(@G*sP~Sd|!XMkYl>ibj+XB>YCVcP*$>Rop3Or{enF;B+l;^FI-A zn9pq2c4lek(fVZ?z1{PUF&BLwbCi2&UM(>;Sb(dpGG2;LQpROEo#FMwzIwMa4Uj4k z$0p?ZqML6~R#c4o+gmx zp~6kPzvD>bAH=)3oi5%v^=K0mBP^%6da=}KT$Lz$q6IFZJP6dYC=W1Np^I|qP#00I zM<*JJ``K_)EXes^NkNta(NbMvq#&1>)wf;0!C|qJio%Ie2(nsI8@FGwH0ehH&ozcH z8N#j$(+La?OS?Ozyh@l5Z+o$rx6Gi|LPf*&MyjN~ve)k4ugO9U{{Rv}#$&Ezj0G84 zPNAkvAtI`=l-z=Usf_FL(dxnx=$fG-I`l;#jfN45hS4gS1fVxmMVOJO1nj1uwjceg`X;7&>g=Ipe><(Q;% zZ4HmF4H&*#iExcd7WxNLL6q>ZSccGNQ6ep-oR>p0!~fYiQ>2;5Ja`jG_>8 z#Eax8v;*vlOqA@BBkn9-Kt`a(>>50pj>U_pC^Q04wf_rL*U{wP$O(17?LXscGn)D^ z6zB)8-`$`%p&i#4Kbl@^BwmP3Q2$s1y$^-n!}p>q^PGVcG)$bzo-9h~mM5y@|J(3^>ns?Iv1kuUTXbf4J zh%o_i`Xas&GlS7hM0X?x+Sx?(YBU*NIo`YvJ6`NatvKvqT8f+pEa5Pr9n{i;9%{&Y z)U>JSfPid5Q_IYBFwvJb5k+2-YyIq44E``D^8{0W@4ble>BZ#hVUO3YBUp( zmK&pJWg9V|MxhMEJk_D!Q`_cZqNVF0TG?E*z>=J)1%2CGbn`@p-um4rq=op%1CPJZ z@fKn!KONwwR`g~|F@b-+ivvyChbOcTU$zoioDbfr_Tx{jDYLbxA6jl(n5Zh1=e~U0 zl3FnaT~%!5-FkI4_V|J#+KT%0L2J>96V_YR_^xyo$vw>LD8MGjoXvlxQIHT(=26=7 zY9WG<0!nQy8c>lUY&so^NW@tU2`wQOREHQzW(5Vp>>>=glvcD6+2#}-!mi;6)gju5 zG)C#6{q##hKK-0FD78>4b%Da$iXIGcfHKAK*ndNh zcZ4{k4X5QD#gG=fVyqo=_1KsqpV_E-Y)rzlQ?P1li}jZ&I9cFaS2G%zjDgs$O|B;7 z8&Z?S%%+1-PKxv*bH(|C=I!U#ns9>#ZVr0g%wi3yQeXr9REv$8ridr7h?busgui?* zvmRr2)lw=+5zWJJ8t=_CtT?=b6$dP4&Ucv_sH7&HM57q3jW8gew8njV`0ljuh>qDT zT&3BaMB@+-ohX9ONS@?r*zWGadQ(5Z-ScM@;JkKlL> z&UG06@`>Xi`tL#b%Ut4t*9F>~D!w-tQEnOr@HleU?~Hd)utkS348Zo@z=T1JK8y?Q zEMlTjJ<_r3!{N(s^JD{3HQ+vj9Nxl)!mo)s6vk;DJ)m|SQ* zOinKJoM|wy&%<;%4h*cPF)$SQld7CzbIMJJwk7lsjUqt~m^im(btW2~aWg&ALqtb{ z5&%td1LET$EQ>2>a}RKuF;#JT7d`%vNKT7TUk3eY72b)AGP9vJGcvAS&Q6FdL?A+K zu&j#vhLjuJe|XR>s+}8Ak9>NHsm-~9s$OddadPi99-A{o(SvAZPZ1J)5#_nt&g1V9 z{4=_36dms=23sszw*_q0KN+HoJxIMoT7=!%Q_J71>H~-_2FDiJQT-ePcb zep$tZILMGY7mR*sF_32T5j}%1VlkXI6P(B2BQ6W$;6fj8A;{o@{>g<4eZhs8DlSkp zE)8;|}nC|4^XMe<^_F=ZbzJDN3uLk<^Q@H~x_t zT`yp)`irh!aq9NzMz?(OkQOJVXx*~teb;WmAYy<>Y@}6yCZluCHLKn^hH%vzK*t6k z!b3X&^{oa~6@u#`=sAG=2a2dj4Qk(ifx>;W1EF7N5m0S)12VMW0=+s=Y^%dmRY`*< z;aH+*jU%PmgG8t`4q4h)3=-kqLAWj>wE`MGNCbn#TyRvE4=0HXz*_QBf7&txaY~)R z!XJ1d2TMF(QSx9X9uJBhEP~O9;s1cAOvf`0H^zx3sg2a<)f=?`cc?mekQoJ42LP)& zmPN~X)h7^L=1$Cc9Z8S=WEmoInsY0w#5>5PT4Tb_AU|A^9}-g9UlZ?Q{5_0+hLR8K zL8U`PKT8AMIB(Ry8S*`%2g+3$=Xpb6oLf3&_YIgO!&|{P7n!gNfxVTbZ4bIT7AjvD zqt>5h$W}-XZHlI$CR>-@bCoSDLk)w<12;N3y{VKcXJ;77I**cv!-z6al@TTK93e(G z=a*GH30q#pMS~}XsKoc9mR&{9khA@mCp9;o!QX@UXYgcDclu+57-VUv@ucoL{hPs) z!QE-bSdkjh(aDF`T-=W|eKQ{kQ$^EjW6B@*@RKw&)%zzOS@| zA!o6_fGyz}{5^<&PPTNTKgNJ9IA+VSP2F|+Hz!-VX>4g%#g-**;<386&X#V>mWREf z)VfogTYIKIS87LDnOXe&oqj4A$syPS$j#8Cj5+ zwpFZgG0a9;O=7yTvwR5S_hN8ovXeVqHSYLm+{t(2&UmN}kTYu--Gz)WJ;G?w1^jkCVSM2tMgkN z$IEi6ya-1U)FrJ`f^bb(+9dIqFLF(U;;c^Q>$G>0NUVX}B&p28)OK`#lBiz;c}MWO zh;tL%pCZCMia1|Er$^)yvJ{NfpW-xVq(cF8xe3R`R!tVa1_+%bga1fmF-3Ib{1LKF z@V_nYOIFwYkk*)ff42$7=4izLSkG+3#N&?0Z+I= z`D;+f2O*)>)3NEIaSfzL$>7jFHAJfmsZV5G88QD%%k%p8!bt5q62?gQ)lu4Sm+z|{ z5zXyrRf-x7ZgS4$Zq2KD$I-z-c~J}>_$`?whFU`A zQHR;0k!9GsG;X#?LEiZM*#RHS&F2oUR*+ zT?#C+M*fqJQfbIs@d$EZM75_$Pl%uE9z<=f5F;OenC1pyb%zKDbc5JLgXfAFwYU;2 zl~^|Nk_hEIAwCb-2QTYd+fWJVB+?q22fE_A zlr09=owBhy)524zPmY)o@Q~a4zv*a>m>ba8?e%H;VWDVGujL96;N$jfHyzIv(*l0o zP`!o~)O#T?9d>&?pD_(eSS#f{4;Dbr@}lLX`@ju)6!l*uh9zv$p`*g9LBHSz-I1Xa zY1rkOt?N#8`xcQ*Jr|3<4Plg`*sNetQ#(?jRs1leErMfjx7WXUU@NzxWgTykV`akV zfIznohiTojXp5$Cd9Z8MP~QBYIzv97-7G3I?v^h-c~9;k0Y25hJ+U7xx^ zPnSsQzU}t9PeJ62EEc^Iwi>+~ zSB-yH*H`D?YTPdcS|8i2*Ut5E zgN7!(DkcS9e!qIdS7IT4+M9`E0^Hs&>_C@a5JPY|Wx(qqu*M{Sxv<{+ruMp5)oaOZ z%_~9*qO0-mNjK!pnU+NIStOzpG{*_&7F(^zFt;LpS`pTvx=C)|es53jKPv_{TyN;T zk=;pCzc4cALH$_T>Q=6+-u&(DwO%Q6dr$2(wG2G$_F+CgIJ>3(HaM%LZV)}%)0!n% zr<&{bzL`d40y09Ozw$B=3b^*yFgI{N%2mZc@|c@gua4U%IHhG`Y~2XA*Wb01T^8YC zymwI@N4x6%hiUp{=+<|tUT=9>45@qMz3S}AZbx3Af-R~vY;G3yLpN}QY9t0Wf~P3w zkiv|Bj6;g=qi@k`2B^Ni*ts3yCb7N=h(#o3B3Jt~npzbl3& zAo`Q&kPXb0V-LH5n;6}|7A$I+$SWpA4soSxk>+kiigAAsIO6a2`aoOF{_~=mYtZq2 zTg^oLNVzK^OE0&rE@HdoYx7Lb zXLpP`4tsz;p|9}EtB9{Pz+%mMkujzyK#k^9#~99);U8bx`Md}A2Vi56+(9H4Qj*jK zJ8sCEC-`OxuE=?96V9#h_J9*`&U|H+v1`eKSf(@INU>hTb%s&zpiTq^xwSDTLT+tj zEOLPpn>CBE`(!ULl#RuWirDvLPDL_3dBhy9=bh-qf4AFTH~S6a8Hs23Xh z;6}L%8$_f>XgV%G%-A4;C~Tu>Zds{NpIxFc&E6<(@=n*aUKEekg9DVd~%X%x2NJ<$Ub-<1}37yJN37Hlgtjt%Z77 zgBQiUv}wFSN%Y-jA#dwG6OU?8#J!r%Nsf>$Vx!s8NzkFKqA)(znGg%|TjYLYf_#S? z6E+oygogk1>lJ+UDB_Ds8*CG~mKqc2?QPgX*rhIFEN?caxM~OcXNq~t3n!hzRXeA* ziP&V^bhZr(&%9w??_FczxpcnPyB*=H`Pt}Q9%!57AUK4Qwu}AdpwGO(2|5l?bi zbz@?9#`IH4+ac`kmpe$jNb~jb4$;=g>}yHD{iy+3v96F$Q)Np^1gXk39X zj@1^&D&-XjbCDh!Trm~lm^*JEOt-4WmajkB{Yg#SDr^x#DW8b8mL;uO0h>|&C*llu z>(i9$z%Hh{w80_5>OmtX@Fq`PSH9;cq8F{)EgG|0j*P9+7w&IkgZ6$$_@}~ZMk0jh zo#Ji2rn7^J>)mz=dpvgDT-<7ymKbSTxFm~kz6GWw)KoE`9ff=*l6-U6nwVA3?KI{y zDBpJS-6hg-z#TYS(bK!c7i@=n#Zb51SiSy=9@#Cz`24J-ccvzAYv`@rykKlno5q0D zX_{)glA1>)yTx>d@L`Ba4?@gfh(OACUwBgP9ueY^x45tat=c1oFuTs;FtupS`@7e{ za&=6kulI>&jP7%ULKm_gMAy`b&V%yyink1-hqH3~#4tuVk6zs;?EIclo**PIkWCoF z7@=isom`uM)JcV6OO0}#*JJa!oG}H_&xK-+Pmg4zvOAg9o@R}NYg+xGr-%6?dVIfl zigPBI)N@flsoPaolwBER0~-G!c35On*8}37CFmLId{9hd0%y^-gAkExbn2jsh+vxv z>-ga|5D^E9NPI*A*U^{j*y<$Pxy>H7`*SfL*(AUETts<(+CsJMq-&oGq+&Oz{!!H7 z3-l^7|9_$NY8LM|+ND)7fnNPWykm)ZnwlPhM?uk3)cX+czc8tv&|8P#0PG0W%3v$b zZ_=$&w$myV8S|e8x>{}M+983%kxGfZh!U2q&JR>u8Bn)QLw7^ z11TI2#bcL7Jem}X%_40r*n0~9yAY^aQovzLR5iF8H2AcLZWW};ba{(BwRCx$4G9g~)|y4y zvT-Z^t_Jru<8Lu8;N3*)PK*Drj3$TBf-_ir8?)mk@wVMgU`sUa#$@&t!|t^nL#1a# zD{iOU=#E$1&K!#VS+t5u)$yjtdXTpjbtLJ}P4HK{ha4G}e->HZ+Gr!5e*aknE1zQ! zyBJFLWAH6nhf*9gbMx7oJqOnDGG_Z$+Km`ERa+k2Fqo3gig0Ja&;O-hylcT%eCcJ^ zf(0me0XP5tQ;h+x1@E+`)2;>I<$}0)*eJ*n_^eLq-z_y#rKoyXsM$FeQeXI&g1@>J zjIz*t*Mg66L2Tmxry757EohITBd!HA{-xl4*MfthD709l@d1-!flJL&)Wl#~UMyPF zC@>Uk867Paqxe%mFtscZ!C`W#5?;pcF*)nbOrVQ{{!PFshIRHN$|?~ZJOF%?@=LHY zzZ&cSSJ>1fI;q2+{0G=JuCNa$QLj>go4HcdZM3;mghW)sTU&=64?$VnqZM`x9=!-p z`d6t~Xbr*5%(-QvtrvW6iuwrcDHF~FB}eF1ndoa7I*PiT7t;aSNrHMy(5Qy=#3j*~ zLxT6vR!IB>k?R?vTDRS#vBfaU`!9(48rBQ+^97M$#3Nl>kpD%It6_08pe>~$Gz3@- zj@4`7!m&?V(vgc|WT0kM%I3nKu;xK`S5o^+2HDwk{k%vpNI6IAE{UlfC6z-P!2Efb zj(gOxzPt{4^epr!>*~|rLzm=Yp;76_Sa;%X0*i_k=Y&wNU&KBSAGJvV`Tr`~Yqa_{ zpgzBfW?aqtXz^sq{Z+)&M9S$_GMh2>|8DtJgmA9$Uqx!R$zLu0NV*V=UEx9;2$4Tx z17f-^?HXK2I^4!-*!L`}wSwIV6UFxJAh5RuLD3+HzfbT^m$sXqGrg@9U%)u5!?w!{ zn@kml;93tA!=rCCRa``1aSr&q16Owjo>bFXaY#oz35X8^aTE|Y(h*OponFxxPJv-3 z)&?vPAA-TXxYmi7zP&8!X9qrrr-mz@1}=CS7yrGi7NCUB#dU1&pF=by7^&g6T5YbszM2%etY;551Q!l>k#G_t(9R$8i3oZ+p z{ET^pb-v32XI5&d7Z*7Jsnu0cKS+77LS$RNEFu~pz)Dds&e!1!aqd1Fh>?2iN)=+9 zAH=WP_p^gH-2dKG@f?R`If-=os)%TtZmqba_t|9h*_WW>Su~}w-e;4$r&lECeKx7P zwc;@P>=IUzTm2?NvU@#PcD8HTzAk0^TDjkg|ye_&IC-TOmZ#veRpS_ zlTYFq@sRAl@4e;U?340uQ8r&MZ6IO72e=|Bt3ooVOe-)6_W-%VcXNfm;R1g{hsX4Q zD|`nX{vM)}$yn07^qZ&~fOOxkFfE%=jcX!uG;)G7Savh%NuBMCb43xGD%&a1HO4dA z$a zbg6erdTK=z^r=zblxNp$l4cw7B?vWCAcAkO!8iGm|7$#^6 zrY5Q(AL@d9ppKl+`_#gOPDZqv?>3h==Z{K4V=yCXm5pY{_XYa)DC*#YmHchOe6~<& z+K-I+nq*DD93^v!W0pfGupb5DQD7trOvJh;Cw1cI37c?@4D7Bc%1)iiMZ@g!%;&4B zn&62M_%2h$W|!)+7Nu9jqO?h-9>8%jG&9;1t&RiFJ45@Pz^r=pZ3Kd1y8J+T}4r>3!+#9QTco;uG7_8Rz5%7WFRV^zsTf*D9(kTI2Sx| zE_lo?c+3W#Y#=hbAc}WE6z_s4ULraO`5PaDtQGI+1R9O}90)mPl0?m|YUKF2)(Uy0 z1EMrO_IAvST~=CS)iPMe;!Y-+;1Vf&cRV{Pwf*~bQfcH((P+#x+&-%_u`4X(hgJB? zC!jZZ_!M(jfa}I{UE_Gxg+C<_ii92hKUI%70wZ!XQawN$kcpQ_uC0h7l%9E!!QE`lwHr^6p z**M@e8#4?hQ~R=-+1twwn%b|%nNf}g`OH`;&d+|Qe_xBxv}~W-_kAYyYyEpHFqiFe z`@YMh9x%#d1YdUF?R)lpllqxKfH!7i?zsWnGpXD4@9A8@pKjm(#Gz25JVwQ3H{8D8 zz_q`|_u9b!d-d;4N`E)0Zv%i^XO&z4(3R>yrB_UQXiR33;u+M(J_B-Qpd|u**a!4@>{o3 z-(pJH1tyC*eZ&psh)Esb0>kquWry8h4x7}67zQ0-eHhGONjGNwiXjf(m^RphjiUUl zyH(urqumJx=`P4{cAyXyiy^e&*^FraDn5^Fn?V#HJV9x?~0IG z)AVnpp*cIxNNhVF^{hk5Q#`$?-#yXLG9;3w-V;yxB_ z55k~idtyKRQBH@++wOrTmKf%m`kWdr5M%jAJG5M=uh%D#r-)6T9UT#)u znC(>4ti;>$5vWANydL0`-6o-qdR<@4cG)CxI$Uc(Y3rOSAHM zXh0=aE6{kk2B*M^CL*h8EksSJO=-PFiH%EAxAEamgoL~X$KvH&gGdJ8&{<6 zpfnFfrUxk>=GBnSOs*3|MG4_P7Qb+M!$avD{4o|x`Lvy81pU?0Sc`fQ$Dw`5HYdEH z2Y%fpUr*&-PV2tjQ|XOWfm@zR|7a|^;EW$1_rlyO=uA?ZzJSR=v#IR?@T0TIpC)-J zP3s?dxIMqqmZ4L(dtkzJaYjR$R;zZnxAEikTD5~?F)5V@KY{K44OP<<$fJ%-Af0hJ zaA_#gW#D~hl=Ajgx?=sNx3?1NI|Mt-ShU`Qv^S>dISD?L7o^nmC>n?B;IeP{*pLpU z#9ImU2?Ss%ZznFwNr<8_AEnPf(4PN1QvA8l{<4pfYL~5IaV~^|H<`G_UK=@~<9j#& zyBJfWo}g4j0+$ab~b$_U#q;xIv$!)57 z*7APYV3<2e=6 zUn>^Ui_Hf-qZ|Gzjj5%C_~DvW%+f&Xhkh$Rvp;X94XQ`8orfRw!;0DSstc% zwUAVQC9EMLgHnuE%o!%NP_884q})NXdWF95SJwIt(Gk9&Y3Oscl~&GM0V`@NH5=@j zgBoW-332#82`3QI%7V_RUKCnK$*U=+@GXct*2a*3pb|qr)=`@IOI6C{I(y|FUj?f>*)d4BiaK@Bn3ixn99!>oe_pSyOpvRWJpc z()ceG)>XRl1RU30OV-^IM}dC8<#5r6REF zKi04fHGJw;!z+{)q%^RE1k;EhC7pXfDq;p54}v0|Z0M?p(}y&yMZxtHIYF2Y2E0TM z)lno30g2HH01Lb+Ezluyw4U`7viR9Z*i8RlkCJmK0 zd*}G73UC%5!Ng#Lw2J6gQY$peSVJwv?OOJX8x(|D{+k$@zhlYactO@(0$R0PU%qO| z5zt@_+Bp1e@()((TS8-~QLqx_16u|R!5P#iSeb}TE*}RgaoqcBQMO+cl?E##Tj1wn z@S+$q0BsRQaLB>vVj)Vg+C6MM1`Sws>q!BUKj7%kzqenX=u-Braq4HX3mL@F2Ual?gri8$&4clb&ph*s8Ms2ehXDb zXV*}NgAiUdDZ%I?ij#7f64i&D$Py(ogU6Xn5awV!K*(BzG5pN>#})Baej_0eM$?(6 zD*?j{Oo!|+^KdBMS%<=P#7Tot7+>wu^kHeKD?5DjRuFS*@jhPY3JLV1acZ3qzHUAf^e&OFL z{5t^KyvEcck+mBOQUxZAoMFL&{O;bOPWRy$@cukJ@dappF<4xJF5|=Cz!<3nhP(_E zFX7*^KcIjBEyfT}GO7W+7O9AU)flYv+VTFnyqPFe{gRHOSgi*2H7m`b&uSS{`bL4i zOSCQu>U4;jL_^1G{eq+?$`jaF^+>eRjOxTF!^uLAPAwB7D3%Yo8n?S6b&6FQL}RAf1?=Vj0v6<@{s=I3(#4P- z9#baNqcyQ;>^KUJQx;j$F44+3WqEe!rCSt&e{S8BXLQr^cfb#HOC)aWa$UXU?MZ`X zV)TJ;t0DQa>+o*t-?s?MoI$+$TQU?)Plu5Q{u0b7u-29$(5#{JIK#t4AH^$m%?;>K zyfOsQQFtRICc7F_nz*#~7*4CXF-3}K3FO_36baIS@TF5ZUTUaIxx)WLxmuO97erWw z1>tbG5<-79Qj`G&oSl?_g+tjwOl+8P+NewTH(C=V*O~*=*YO()gB-?f48_S~)1J>- z*-GO?8HAfP^D5;wR=Nb6V%0~TrCPg`qO*;mncpIriV{e(5|r?0h@VzbtUAnDL`yXf zbwEX0k&m54;+rGuW{LrdnsjBBG)ZNKo#Q(+*}@_Vbb=Ds5yultVyh}@Y?LkxsaBd> zbP=U5q4Y24UvAN2if#fAh!fRKlnjp?4>g-EG*Oy+;%Uw(s^3%@6LR_%uD_PF>X*2o z+qm-hFywSmV&egNZWJU6m@z76!y^~e#-q0L7;i9WU>Kcfs!SYm;ReQToGr`LKrKm! zWObL@!tzW%auT-r+e@ugS>4uz{z<189@fK9xu5@f@UHgef%HZ*We(GRn|zxqV}r-I z6O6Vp6(3M;b0sbgfa926aKWA4Uv+wy(^t)v=gqsRe+%Vl#=IE0Vw6?s4PEKiC$JFK zRMC&{&={-!5Q4#^8~t@a|F^#;1Y@7r(U!_AUts2>SB*zfw^qu+AqW0&VUIqttA>72 z75Z$T|AgUP*z?&v7xrXfvI+LXw=PArRytWsi8Qvg5?-%j#)Elr zMxa`XPPQPHHT$I^BDZYxzjdE-Os2LI@%_+he`=Mk^kc)3te#S(8Wu$B*-F_6>F&HL zZ4!(V+wGPJy-V@TQ5vr8tl)il@PiW1VFOQUO)32Uh9^wo$#y}6P|ra0v4P0s@jnsO za3_ehk#{?zVQV!!xHr;L4bMG3MG8BE%Xp!dddu#RO~JT4BanJ2N*hbR09vRh!f$@r zEgDhBwA6F>eR-D95*k1!6lI)w1d`q=OK_&}s9g!Q)c>6>+m&9n9GqT9tu8jVD0+8C zt#;Ub!{#EVQaRh)th<`++)_ugo$s|#dYFHs-`Xg>kV2?^TO}PP{+YH)EAs@}+*ZlP zpB9PAVT)3SZYL@$!>_>C^tpPAoGn6we(j~{+`F``opQ16LS$UZwlVs&1>+}A%=>C$r^=NmBa^BLzpDHKehW5fv$|y?{ ze~L&|76$kLgokvcucvJ|zc#gfF`1WiXiPt*DoefXG)`;(A z6i(H0a=Q{?%nlhsh)borR0$y;eeI$sezE5;LE>jxx_OW$gKP`BD$^{cbJW4EG^Kt& zw{1>$x?-@8sf1&8C4|jqH>Dp-<1UQMU8J$#zer;dOQX+iO&SOKX(CgnyYeva)9bF_ zdLcjB*j-7%!0A`~tY!7n1t5z%KR2ptLa$SOYyQGFZ+wVl_wiTIn7*N=TxVe!!X`y<{&tM z)VL3XrBF9#veWmxqzg--K049O**|r9-9Wca*UXv3v&q0?YWF`o-6ZimXwD>}w+uvu zTA1T10M4{@y7XSdF8^v$sF^c~=XnE9jy8yK#q)qUJ45+>AxYp+uc=B~B=P&BuhPxe zQbX&uawG%{r!oDMF_@Fx(@&YpBGq4+gyG1F{>t~}rH30CM5LKWPZ5R^}Q1}Xb+vf!D) zio?9t(PoHJ(`?RgqzzTpnyr6&>$c*rVaj66vgQs~u9#2JBO?@hBUJLy-J4XlMBi^T z5UWjkCA>W6g@JQqom;eTMB8909--{8^zx?VBbAGm0B^^FQJ5_=f9rU5v~tpH8Sdp6 zGZsU0zfi2kPMF`Ng8x!ZrV^*US){)y$W*#mKJwJ;UC=mXH?C4VK2Et}N%M5<%~DpH z&8HlrCn&2d7MlkHz1#@*Xs|Et%)WTFX3_8r|EpOv`HU{uI$0CaZzn7LaN!&*TIgaU z^wq8vbLq+_hN(p=UIWvQj(6&f&8xonwmmS&7lYzer2!9(qY(DWZ&Ou%0!DNoaAM&BfdCGS4V#l_pSQFES=i@| zzT)D{o%b=j@~&gs)6fSGfE3c~1UR_F-3>e8@b8=kAm?i z@q4b49;TIeA0^`5N;J7dW1dqYc+zj7@}B>tZal6CdI#!_Emah`NZD*j{+o_1Qogm| z_o~H8c&xP+mgIiaP+EX8_h%;&&sE{*?oU#}DefiZ z3$FIcOGm}io3>S1(cQ(8}4}RWyLBRvE&uyDaKm+RVA8c zy`^}j>0G#Qy^_YeVVw-Dt_?l|n2~NUW6#S5TaUm>OXd6URiz0o1v&Am(lOjy_VN}K zYvESRrW0&lMO|N0hM~a9*Ob&St-yQ~xcgJ}7FL#N^-MMDY5lsg2gRnbK0MR%NcDlThMz~=fQ>OPda#5WAteUj^4J9SU zwd~U+8xJUf^`7$vv0xz z)}%gfDG8|>6Mwi?NrT)<4ns-Vp*r?&0MpA2rf-SXq+NgN9eVXGWvMyOk^44kvi87R z)@$1R4lF@k!rMT43yHBtw31#66L?6gwl?c z${h`Il<^LpTIMSqD2$(0 zK7;?>%U3@1H835b;cJv6?W-(N_?hD84|67WWV6)@s-&MjQ-tMvZSKlC5zax{tS)O| zvn(de?!Bj^*TqiCNR#Ik%+?K>&%1tb7_q@Rr9;FkHuXIA5S+bINuz&o_7EI2ZmofZ zlI8;^3f3vZ_)O!4NZ!Ze;Y2eLXl?*axQ=E$&@^&G)AX#?70YkxU6J#?vd40z8+BT* z%(Hgpw=C~Ju2;5cR9deT|8?I<Qp`l+a;;I>A3!Z;$dbo&m&@6 z1yMA);HkM$NeR=*Tz$EcBHi%B()Bod5VhD7SkwACW?a||INsgJiU5pNis11f6oJW4 z+zj#)5IdfGQHi&H25%$Vac8r#r=jFFRN-%DJ2dW7uD@NXMnRTN%B){2>G$udH|Yk< zjBHY-BY7)aLQqkbj&QY0gJu>e)2qIuR#ip67btP*&KiFErIMz*)i4V+K!uzz=K+)D z1~cij)^Fcm*Zb|2ZBUT)6u(`0n|@yn*+2G%1;@a*E7RqbyvjLC{B>%%L;0F>G44=4 zU@f{g>jv%m2j4xsg7$u_d}3Wvu1jm)CvY^DZsoMmp_~ju$s`yw!+kRbLx=JmD?U{U z;l8cv=al&w=D&3JUH6Wr2*>Zpp`UrY!?sIVWyYmO$9F4T+!UaI6`=7RrL!SgKVGP$ zq2D_Dp@0=&B#esehp%YG9;M$uC_n)#fOW6Z*-(Idpowxr6ZfNJB!`51l^z8I<@|!2(24z(%EQ6~1M_7vzSoA!Y7`okU=DK?T9i2fZsStma)mtuoBE$ORuYr<%cmVWFX1VL|h^{`K7YJ z(51qv_mVHElzT^sNG~_|@@;7)^>M3Y04gcNMMeh9A;5HXgL&u&t#>}A-@Z~l;^6da zb`hypbQf{v2wX%B!rMUl@Ed5rIqG_pU4(~vX{r=%=X8MKBD&rn|6_0w3u*rmsL6kh z!9^rrreohKKk#``4^_ZsxyW{rA={XVFH-u@&|@eit$ofBID|gOm1OF~n52LB{J63e zcNGK8-ZL~}jq%O!4z+7KU4!2rnnoP?Lu!O|4BV0y&VH|lv;To&U=O_E8AkGk)<0p| zeo&IaO)~5`ajudEf2H+Zsva*4howN@)u(koz%8J>t6N|k6M-Y}gpw4d;aCM65pFnQ zzSFGBYrp8$W%UVog&W;y>`4e%2Y$<5;m%2T1xcai6$}b@{iww16y7^qNl$%Qox%mj zb0|ArPyG*B)q#WA+qY@J3bm(EI=$!-A>0Nb1 z7o%FG^jf)cJwjqL)FMigB#Dvz#A>qrg!Vfz?)kBjI=W#@rEN2Hi73(kVg})k zp*NHn{6L3qq6J+p>nd@gSZ~S;x0IcRS=Yt1z-UOJ43Q}Bw&H2<{?(I}Kjl&5FG>{ky=!=k!oT4$ zFrtW9_PIS$zF$^p|A7xq;v62GGTT#Jfq5{&NIB6d4<_svHD$SRQBxKUuBEbkZn3{& zwuJpm13c{21`}X*9y5Erhus-oS70pibx=ctiTlv_XqlpOA zuwr+0GV{OCb)@zg$8$b*Z*!Q-aH0^Ql-^zpFFdcLaww(59CV2=KKrhc+PmRQ{z8i| zHaNm-*bz=aLuS^rKWg>@?ZsAa`gWO8kN)zrkFusk z9z-z~4x$Ez+Y|Npr08fR^>xECuux<0z7slw&xG5zSy1lv2>U$i41UY5BO%hh*$6>c zmUJ3*$ARHRgIL*>dVJ6tHEsQ*I=vt5)Ab_y1f@jTuSdu@!_{{fNHyP4r5HNWS>@Q$^^o1js1)OTJcN(o@GY>+F5X8#XNpI32s>ld^@{eG6_OY{R(v8RM)w|*i$Gk>%xDq|IVzZ&+ zqD_tMGmQ5xb?`_#nu_b#JyZ2&MxcTfJE~WZ4=V=#I*F(Un5AwoZ<3l|kFQwV|AL_^Q=DK>#DN5x&32o<5BO!`29lLY%m*0*xJJWCXe91 z!Am|5#?$C<70!T5oM!*iz%jd}y$jOCS=AX|(8@vfmh?+2d&gP~X*iYLWNU3#Eb~uG z9WwhHW3Gw&0S*Gcy{<%C zOoOOS6MHbXeJ8yt>>|<`r7ZlilFZwy^WSrqCT6qgZ(+~j@praj-)xCLPA%>B8zFji z=dl9Fb4ENvhUyB~sU@|s$1r0&U{t@S-XrYID6fs((}?Dd9VvlhA)Ye{8j-f9l+UH?CF0-AzvDLpw7vm4w*_WD29Lep`&4%H3 zrDb3TJ2E|(_&(1glC6E+<+VKPe~?*C-_lMxtXp6PRg=Kn*$(gCJW%2K}+dmgrcmZaE= zm{&6qscAxFNjygHx3DjZMDXFEcEo!_ju@X|d)J(hazv1$mUJV@UT^tM#fw%BwEI%y zj`n)AdM!rr@ETEp$p>?dp)r2it4cbVfMMPf*BU zyRck2p;`0=M|CAQ-`RePxikTn0@*uRnjEEwF7}x`uzS6Wy*}HY^1Mwf!uAF7?Iv(}Jn)|1-5$e4 zJVyE5?QKG};d3%-*!^Mk8Vc!pcl2>{3_)ZcC-kr%HO8e<*g_s+VMEQ0dqUW*QhrYe z+XDDMX)}N6X`=HvE#Si_8!u5y(ZsS27XOX^tI1rm<;Vr{MXd7pZ%FA zXpo=UuBQ~Z2WC~4W7feiUacs-4`gFjn%#>kulsw^V}0xmDeo8-UU7V~zx_mwg2h1p z6(X^Vnn6?PnF03I;lRHXFI@!D83f!tt{Jrc13|7Q0Nd8>1yDW$K)-fDMRgPVgBlS zIMLW+UnL#>K;x}Rj}ne-(|DVRc?rqezlPc;SnhSBtYP*I=HJ%W8g4h&M}4lM#Pv-; zX2#eNnkaou4~?+5(JNW9x033*RZ?HCWZ_}GlA;mzQ>etTX(SwvH_)33VaQZW4Q zQT8lrN0=<>f{$T>K#J1`qhY)99m!+Bkh&|mP_f*op z_p3Mf;8v}{tr#==!LSVbuo`i4Sq0gXcG7|jds~b35Pgzi?@2iW(di8{VF%vhr-w7` zlYI@?-)K)JyyO=09cQ2Be7lF9$*?Dy7tzP#*t&VDZ(^{G+YnUQ04JbOw{^$w!53)tGho|17I7H-T@7OW7*=M(H{5G+siZ3kU@ z8P=}dBzu}6UB6K7r2og-cZWrFHUIA}O`4+gBCw!@8vvQDe{;dyHwm!BkVFSfZvVDv>1W?=$!AE(?;p@Ar9rfAFxo_uNxv z=1e;?b3k3Y&gsECRF+dDh|U)*j9BU7=2Tf2(FPhRk_4=kJ~gQLGuhGO$S$co!tkqPHo^-(8%cC zbZ{l_Qw6J@P>ha;9y%pyGuSpmX{BooxFm3f5>qMp^AA0s#I04wZ@EV&r%jMO8aWN0 z33+jo_uiXtYqVsXRd9DEBrXGa#M^W%L+Ne`KS|wZE7SR>rq)(K@@ys;SG88^Z5mdC zI2;F;fkrT!pHy;<+o}0ex;R{az)mTdB<3)sxT+KIqm5FyGaIG+=R=)Roabtk;;MQa z&?#l^JSEk3&N28yn)JNV0&(;E%HbF*jA`lPln3=(BT!|&PB7|zjbKcVAE#+qx){5d z1&V=QY}cVS&s2hWk&o}E@C9~x7XA)2*iCjgYD&$P*EKkrypPkW1xhvx!#WEg&`#3P zg*6K_P)t4xv`-f4Txc`hT4Wb!6AwP1pEp(=;ulKIhCmw(Wn9D5+-!xYbb(@~n^P5E z#9W{=P>+QY7veXc;YuWZn1danHQ6i`FDjg-WIE?(pdE;-fy0BG7nL}tAaFO0Y2`s1 z*X@QSU|I_c&Mjeu%jQniNlg=hrAu`YI3S;*mf1yMA zNUtr^b@#A*TE1LqgRr!d%N5^(zE3O7t>VJ?Gz24DcFUCo%od*~?T3C^JIZ}VnHr87 zL1Wr#l=g@mJOyP`qqJtvf;AZ+%{0va@T_u_^{=~c*=62QI``esmzXLL0%w zyss17_7zGe%*~rC-mX+;+n5q6K0XhoH1&O*DH-VGvjF)I&+D4fRr=}$h`l}Jze<_F zV(2o$f^8Z*2p|_?kJheI58G9el&6o967rE-G zOn1mkV43MCKCk36ag3t7q{Jc$wf@Uc-a`-3z?YSg!I_=lp+p>122zB;LF`99C?EH- zvet-%?^l!@-rS{mR8C4v?F>w{2o_awtfk`mb(*wAY2^{GcEqd8kOxdYv*1L9j`XUM zna~yv+Y=^()QWE4z`q26ZC`Z6cyMl4AJ63k)n2c(_Cm&UyqbpIP}+q0uUBRm+w&Ac zsc5~jkLQu3&ja3{qpv|O|3=L>!Z8!JK|w(tgZkHQeU|gUsBN<}JvvLvS&vAvysY>! zgWag)^Q+tRS54-V6#g<4mQi}ogEuJy%r>CTk=j}DHi4R|srY|lN z`FzzEc={MGFaePo$`~hC$USYdy}wzR;NfglOX^rB{{nnEw#f%vs~N=Dl3SEa+{xK| zs}dB3Gv@Q6=BXv})PiW?R>d>?w+{b2zX)x9l?cdX1l-uF%rFf(NF%o?AK=#ChTE0d z3@Y(DZQKrq^e270T^Z(@#@!}U%IiSW<2#f9w$oBn1JuLIh~{H029#yjV#Xb%Rj{C7&vz(moCw|w4K6u5l{cAabE)|*CAL{@h$SsI3`9pbL)-kPTapGL zrYhjTi3{w2a6pC#Yy=th?cY){r9uwxQpWk;xPrG`t#pVPl^~A_nFOyZk}LbBsO@)Q zrfHAPbO*igx}xQJ@*LOF`5o{XUwd7Nu4BS@RzlU_6uKLPdX8S$t*pf5=fQc(>pb~A zbS6)UH8na$zvU@yoW?;|Yy8KuN6D$T*@8(SAFCMQ)!5vH=}z?d9%a6%{sHR!hJst8 z4Qi1f22BJouilq)6nP)6G0cv59Xgo<5Jjpzwir7&SZUTg&MK zI5M=6PrRx0jG1v68G^QLiLK9xh_!e&h=t|EE$eJryrrbnalt}&0I;0_*bhJu*>5Q? z7^jl=Ugd_V#eVv8ud)$^1z*Wm-qE!ow;eQaAN&BQP`6Kcm6q;NVyX9dKUbQtU-1bk zOTj1@p%@Xb%ycr5hr^?daiTT*m2Nl#`C-4((`g)BA(~|EdO&%F=`C}+wyRCWN3^YJ zir7b;-&Te-2c|EfuFYlq)xj<-LhvkuGZLB*7u(TGE*SGJxpLAzY|!oW`P^+qmx(CQ%b*6{!&!&v*t^P0M(nJE%JU5WGc@8ICAMA~JmVU%fzV1ofPG5orFRtJ zUC0#I0Ap1$zL`|r)%1t5{~cgf?R z5?XyqpB*Q!Th^w2kuKA!P@H$Y~pcDAxEc9eWM%f0w>J ztm^~_{CZbOO0Yoq@m-mhz`B=$*E8o@ik+Fvy;g%n@F5)%!)VJPZ0RSCDD!xTjIA{C z9VMpT#luzMaih2Tq~oEZzifUOr1hB_w+8loG47f+47JI4hBLEV@G$ z8<*ov3QmU|UX|vU%i(Au__Q)CFc2@KyMyMS8(C?t&`NXR$mvqCY$UXJsnhA;X;9p+ z1+?mf5*vm^4&7X3k#?Q#1exDgEF75axWqST#{0lbzLg{~Aul@eKG+{j$}?bpr|9q* z<#oo$=}q)Oo)Tk9h0V$QZxLKi8W$@1K3Y(j3%w;w5ocsd0e zb=CwA;i(@&f?fDjd4bDz zY}PW@P__e=oVL-E=ajfAzoG`zI(qY*@?pcAVD*E>sD-l^S#LQ(elj(4?R7CM+XP6jlKl*TY}L`Apx0&-zBwB32U1Pytp&T2(_oJ z2gK592^RmQhwa=$10GxIZ{~6lpa12}Rod9(a$bqa&cAB$Rj!* za~kEHS2}}d-8v7`sHjjU<%rfGxna`ChBT=U>l!*EVaPCm0{6HUzE~=9) z6;IIOFO*Q@V%qS9(g$+$*DsW=oPjp5QDp|2R)fiw4~chd`H%*b*x?McZEJJ~^Ka0n zG~TiOOQo+VK8wn~1fxGesb4AmO-@<#(pO4j<7PVfm6B^zPEH(_NZP#tZOyEP(45Ww`w|J)pJE>bA-WtF1z+ zH4)jFSL0jo{sjf4TAnG`@dI|S@ek_slM-9IVlOx(l6H%6*Kqk>>U{~q<5}ABlk&Z( z`Ram27nLZZ*D$byF*pI{|MW(Yl5T3gq@Z>&;N-0RG`vKK^W{&YpXpdpgz8PjxUkjJ zaJzs?l*L9Ig#}+yV!f9^#@I$$Oug`v$#(}mbxAp(LknTcI&=!FL5n?0j?gL`TNPS` zw&O%Avh(Ve?in$Sb-KR@T1m0pe@Vnz}LKZJ6^a$nH+gw zZ4-<(FIQ{x8ZG`A4mQ{AFjH5XL+H%Up#Q;?dQItJs-H%yu0d|jr8C!*KBgY26mVTh z@NaKHB2a%Y*FoUaJ-|#(n;`3kTvxK4=5GVKb7TGK=5@HaC$&ezVQAPM4bzZ9jj`DF%cNkzN7T5YuyE3?D8?J+%aL?y(=hcLTvevK|Qqzw4X zTj)U^j=s4}h_&k7s#;K-IPnGvH+4P2sA(DK(dFApqA7k01>8}3oBGV6ad(s` zQ|DQ<;trU>0@`;+DKNEojuLi>Kxaq;+;w#qFZf#Mox5l-lYYFb#QXQgg;zza45Hiv zW2Pw0q@rj@xf1K~2S(wq?QmCXxf0kBtoq}~D)_2QU57SeW7S1`%mRD`uBZfq?Rw7T zw7VRBiam6<91>(J1^)qc;sT}qp%fTbQN|M;AiJZz+LJ zuIiIy{8RD86)w&1E3+H+Peb)x=NsvOK0_5ARKMcYsTIIX;pjnW;4w~lDHZhbeWj%_ zlOEhxLVKZhF8>-=QKlXI7oAPz5_GZ{ImK+vmTuGE9y2*jb4XU{d6%_k)XU{Q0xM|T z17#5HxUcy69I!q^>05q=z@P_8V92|`QYcVwb6pik4 ztDb7DE>-djYW_e^h z=e|4cXm=7g&&|At^U4a>xzYEwpkCXl^qj-MMZN)I)ALH1b`3qiSZJFy&*bq34+AYb zD9RPcIY4Jz1vPeAh-4m?x;b%bX@6ryDP~YQ$f#9BDp~5GZU!R&=2g#FTJ9zW#c|mj zC}fG4Z0Sn47SMd@G8B-0R-ZJFwhgm9OD?sv`xk^=;lxZ+Qr=armQ$ z2<=dw1^HPES_6Y}n6aX06#l$`xF8pGG1t34?P0Irb6{IJUFY`LfKZ%4qABWc%jhQ$ z5z_Hu&HWS_UQSettM&65`uU<-Ki@#-qGnek8qj;5q85&|&v=UHfF)4(A~dO9Yj;T> z_>54%r}=t%;3FLmNc)|JFVzSXK5``oUIf$k;3%C+|gj;ZamXpxxzGp$qW~B*rVmwOb<1^*>h(Y`~ z#^G^H<>Q;y$KDQ)y(=H5*VW$+ba)(C`M9vI7(kYAF@zS@6CpfIGlz!F>xn;| z1Gq51WjAXAS*Y00Q{>MS=_`5_cn1j=lhLEVH$*IT3FeCVwwBTMmRU=qX>Ww+7lxJP zW;xZjjg^~~R^K*OE`>#k0oE2x99lG~Z1H?$3ulKG&Xq0xu597!(89N}#T2s`h1+J~ zS^^f#*6|dFwn}ANuPFPBxbnV+8O*t1Ws3!9;iIq0%if}(C`t@;4d81CG+5x3DD4$M zEtgINioOM}H4=ZCjCBgAiP-KGb~DS#Q)@g7W^z`Vr`A~eywsB}`inLwTO|S``1LF& zeJ0vx>rAxIOB?Dfjm<>}cNpQ&VT4165qh&3)@BI~%@Q1%CFsqH(TuJpiN~pL3lYlw z`a8Vf@9=^@ztEk|w-B9-bqfMpicz(E`Q8J|?jzcw8fa~g(2PW3DflQ^^f$RhX-6H6 zDLO@nwD9S7=p?*d8o!zYxtoQ;f)F(39NbHh4ZXBK)WW5<-*5rvGx+Udj&=d3t)ulR zBF1vlT1|T!U%a_!Ki|!J_N8)qFiq!gkTlQgC6LpHw$xU7WQbfwfYjm z^(!d!CFnO$IQB+GsruZSIP|7(PRC|r*LI?ZScO@?VFSH^A`rr!*r zH`8whsnYBVy;(t72QkHD3@8}YNepr}1{V}`6Zc%4abnS!4)hVtvyV*DNJbZNF!5R6 z2FXA@1IfSw36ommv90Gw&8gn^(2e5QdFNq!a0-9q&4NV z1>>-21nFp^amOr8TzJ}TQvVe+t*@BpQfSDjivz-LUP0vCPguM!!u-%o4b<)Wl&dF) z(iHseX3*q7C>`i0ngkb)hE-ew&GiWD^O$nUCjB$r>@V82i^ZI0VQrW@Y;@>dvFhjU zm5$!O5cb6S%NCof6)wU{v-FaO&DPM&$AoakH8Zto)8itXK6*^lL*mAT!Q%0@@#vWM z85WO@v9N~f+NvFEXVLbKvHvd3(L26HQ~Qh7MsK~-GyR1hxetRxX*xjoG=XI^;NSWg zgnqL0eqdb9+x*hd;D7|3^Bf-j9m_<18Bc zI68CV&PE%1&|8B5KdN`ze`6 z2tRv08VEnGtdllE#5r?qVVXWdr1X3_P~GALP6LmWZCYNKR$8@bb$J5Qj0Q`*lMvD4KuC&&q$zJ$?9*nCB5|aiJBQg?3imsmMj(zz>fty~X$Tg-Qx;H|2(Va}u z2G>LMnUDQ9k*>@T@pNmHh&IJ9r+{?vn(w1PMBqZYh&RnHqOx@H!kC-sI20I-3NGx} z(9807xyN^Xz;wqBi&Fn~sdOc#vQN|IN(A(cFwZrUh4UKVBkKkgLOU0CGQ7RnscRD0 z?7u?%_ZP}3rrN3-qYp=jcb@nt#1SJuTC{1R9cVDj+2y_-cxD$pe?RF2Y5>7({iBSw z02gM16CIx|9>?~2bEF7wY0m^nU+{n~j6Z_B74U6g@nV!BPbY zCiyh2m?1g>1$##cf72%uXxx0@V8$2`4X)~+E?y1Ht%;OZPM{CcMPuUtx|J?+M`Pal z?Lkh}aZt!O_`$gf4l3QbRdJBZIB10FSHl4|p+@y>`@m>?lXc}W+JwP@)MO!6x&AQTnF5yaSarU+zeLVy0#%~4*D99;fz)M6Ea5Bh>X0I z!|r)ijEq4 z8d}(Vq=;9W&L&K!`Ua`JlvYe()Hqk7hPjlfY)KW|JTp$ijj=D?ngBL+b_oSc6tC30 zN4lWxMC=hCx;0U3AC0;H+a6hK`rpw~H2I&=(z`~qEMHMhM@Lsh%SrU&xJP~*`zTtP z(BjFW)qlgoeDthu5my}#TPJIHXko|0y}1u)PPOr~Fn)DBAa#0%=0GNKg3FA~ zfMp0q@FHZzSRD=}Doqi$FyUOH4)Ptv7szAe1>@*EVos5bHh>i4AZ z_5KDfb(`hz9)g?V>r?nBDDZDQDcn5`UR8l>dN+q&T~a9q`i#-R8$@+y0=%o~>8AvR zTm~F!k_C0fkemY`BOZ5-uxMe#!)J;54CPsde}wXhiT^h!k9)S9Hl$aD@)q>r2<4+V zPO7fmc;(QVxgx2>qfpkM&gxFOVf;peVcbS0#=#f@qzs^YYd}W?d%ty z9}4r~a4Gb=OVLPqg##kp2_9S#MMXJ+FYKZ>MeE0MyrBQsC_b}N)69IPoL(JO6&D*P z;5(1cnkMG*F2<>j3-@f=xIlDs&d)TY&<%WwT?tX3Yi*tHvDT*Pz}y4&PC7d&<ADh&LXgud+oKRDh|UBNAE`W~N!ejw^jQF77B6!5|!~opQR|s1EW@skA6Z z1Uuy;8tl~^Vb(qz%Mo#a^VJ;Dws$3v*>T{MtvL=7mY37mkyU{_k=6TTE08hr(;1Hf z8M%RrMVjYyyqab``8>W@Jnq~FvwZ2HZxDx-FA*I8Da6-RAy1V1du55nV>M+kB17i_ z$ZT2)P>rHaOT`6fh2hIYvcDlf?R6iAgTS;A;bPxwUId!947_;{J-tk{Ho2;6n`H!X z9QHCXFtD&D&apCG(;`g+zM+{QDA9Z@E91f zOeJP_wn>b6mN~fUgm);O0idb{l8p;TvwKzB`|uwnrO;C=L=;NmzOq6bPuch@2nAI8 zH5;B_LtoryzY#(;A& zGQc1-5N=`=2N?!%j3v@+rsKIs_jeVKz5kkxE0{m};d6=45Kth1Fq5aq9O!{e+sPBoZ`C6%bycjx?Tvv-0 z97eiYB)~g|6--_&QnGEVx|Ht*(YeSAOUmi}p;h7YAuGgbR&)U`mqzIDfyu1xvk8Be z*=x{apHkzZuc}PsLwOsxn(&YiX_+fAwNQUkX$Dul9r~f6Y=gJb5l2LQeA0WwGB`hP2b{?aWA>NB;II* zOC1XC0l)yPmGx`RPe?sc0;;m*9o1V*-@PQ77+uJXM29$B>7f1(Z~a0uNHjG%(*IqgGx-oEKpuiQZ>$Gm+V&u1FUr4}!Xel@%3 z-l11s7V%@VKZlZqB#DwimI@14Kq|KRci{b6L^kG8f~}v>9SFqM=9_yiLq^mac$b6R zv4d)>(O4;mf}7xAf@sX=YXdlzxwIwPV;6C7%OYy@if9&sCu0zZFeL|P#ZHJA@xdD) zoJ`*?Gz-slirMvwgUio>`#s1mCsA$9t=S;JoHXLc{2m{s?`}sJKm~YJbcP-V^2~Zw zykOi(?(0Qpd>yP&SI5#cLX5OJ(bmBcl~L(4$i=M`)Mvd2Y~rexu)^%YXC`s#5;X6C zaQ1UQKdPVgoI`8YBj_e4j=o`?v8tD7?rz+cC&@Mx3v_V9)KL$Bg;;Zi%jaysM4!T$8x1`%w-(&PBCI+i}$AR4*v=Lulfe5jX|58fz3#^f`<=C~`f ztF99mu+k1Q?c!5|K!<;r;)mtfVVEMjD4Bw6LE*f+Y*UP`X^M4gnBv8aA}+iNH@SM% ziXk^WbYeU;+$6f!yeIymr#Fds@qQsBw6j6lXnZ!$5Nz&|8A2Ldf+4^_{ERMd5(!~i z<|b45(M6BKFLASIsT&+^d*8GxW|@_WaGyoxw0vOIjlE(NzB^bOJBK_<98PgjoNS9ob6X0^M#vF;vPDFDR?_Q8s@NhToEifpOs`b< zqHytgvXTZ1A(EVfXyR7U&_=N>hgi*yt)SOg4s9>sZjV@s+a~->sUs<6n`rDlkROAZ z5SYe>yT*fmqutw}tR+85UvCpzgS&UROWNVVaKo((n0UO4csDI0b-QR{fwru`IcD3l zW_Enr;`psp#e5P{9Q?{vT?}JESUR{heqF>i?Tg81xpff0 zB@m3vk<-DkGXRg#xK67pPZmc5%%xFB>2(q66oa{pn&;|oGR&q^uZ!+Tpz+=W7EiCmk)u6t?pAm zb>_E3Cs%jPNU65V;l+{aDKPyGxI)F{(xXCY8SQ&ZbjE@9huGhBcz$+~RBs^txkZFK z{q(86$Je~$;x)69bgeu5@DdT_oNG6}u0F1drF=5xW1Gi1yl_F^%ZrY9)TZJ2!V3}K z6Z1v9mnXLYQFAOl#2^)#epe53gBx5b30d^Uu!C2=iVs5%|GcXb*AcQ`1+!k%{9`iKDN5uW0M}Wk}^ZIB0J;^(zoP zOx>QKjRoR(Dp)~J_?R46L1k>c1N+Re#@4@L>&?nO-JhV^c_PJm>QsRC35xQkyNASK zqbuz_ECTAm%yB#wPX4%T?WU6f^y^{a$+yQG7DJu$Cubzmpm#;2bAETTLRs&M$7(~Z z9F048I~ZE1H#(aAIglGxO!$Z^(P7KGsE`jr3 zw)T}v#V5pk4=vSn2l&8r8hcW-(Q`*{(~grO7BqG4qzLh~M@e5_scQz^pQ1lciiz%p zd~whB@rFX0a!T~^wtvmc?pU#|S+Jk8_N?fX_;TVd=vW-qS%RdF*YFt%dM?vu2K>@| zyX;x$2-SZ(Rl{#bYxwODe$$cSk@o`Ce;@lJaw>IrU(EKZjX+{o4CLXb# zhO>jq5Ac2AfNkMe@KMfVy|h#hA#eR8C43-)+(Oh+_94)%QwYmw^r48LoDalA-kCQ( z5PMr}PBE?NklF9j)QFLpA(%0KeJUPG&9rzRsx0)aFys&pEddHp}Wyc@?#=Sq^+E z+E_P>wu)&#;21U6H`sWi!2g`M2Zz5weVOWhCR&<&pQO&8i4LaTlW4_f;<13+h|9Vk zZ8&eyas_JRB5#x0;1??U4D2xJ7YZm8*SQw*d9eiMi@^F;j#f+mrzk+U4N}awI=D;Mi z16pbz1dl5AH5_Kvfm$eEi#hBB|5}VP4Vyp%zY$-X8cv{u3*sr~ESv|j!`Nh)K&LJM z?_l)bic;eaYWkh%?2>PYY^<&=3i9LYDZdk4`9k?o=W#(*(D%Zt&g~P}P=hqB2loXx zqL$xd9~c@@=J(<$RvVaI6jJf`qJb?tn2X!6&2XChe-P>Q(Z&T-dfCFz<_9s_dDK(4AsTPj@?#C|N72`IrF~ellfdKBQTHCWb-2g=6kh8txN=Ka z#unzpMbf7~irU67`u<0eTdy$lL=)6%uK#YShmAaWtU=>w+(psRHwI-MoV7fqlNygoR?pMXi=u6uAwnIC z+y^cXVuJS^+qTk00RDQ#s%0U|y+|nWzMU#;?=!XWJklXG`D*yE!aHO_tqp^-;q8)m zj`}Wwzb1~>7l~9;y9@LazPd+h3~?1w7)NY=6gA?Bpk%~0s^Cj9A ziLfo&VT(*7_fnB*dVDNRD;2Hbjlo-cN<~wbkluIUs`{~11O_E{f~o^lYEED%&bFq1@0luQU@@w38c< zZOp^Uv=?5bc~``E<9k$mMMV05QHOpFlN>yV3HK1yy$Y>y2erE@TEz{H0CU1E(ct|& z8xBN$bxJv%@2IOm7A;#QMg594T!rn*5t9HiRn!FN-kjD50>JnBYGZr{vNh8J)~hIiFa%$Q^=iB( znlOLhyH;M{H{L6fo=3~w8-Z)|8`M_XwRpbOgBGQ=%h2Kul+a}9<#HHV6?ix?)GrsR18 z#I}Wc-O!O|03>b5+dvC%01wa7K0NdXn6G|W70gMQbma!joI*oUb9CDL7ZIa>ev(G~ zB4%Y<+T%jShaS5}rfH{sh@Ws*O9x@T!;m=1zV!D3)l{SgvqZBIMDk>W>L7@>sJ*@} zMtujE-W|XW^)?ZCE{2>nV_z*NXx8c|gYm{zxElCbM=kFX2V_76Zuz7>zls26QuKgw=vdcPXnpmzD``-o2 z>485yF1Ef_4`4C!sXi214&pBAZ>X>!>cij_WDTRNJTY0@;sK6x&<5TFC~QDovbqA( z;N1=7L8CZUteI}vIRd&3@+(2S2Y=D*UU2jbjo*jRrr*Vg_6Hqj2cpyxe23vKZ4gl; zSR*^~-#{BP%n381s5#rbD9t*)83BT<%&jI1A#vK~?HrDlH zCpD4b3i_}CsMLkw+SCqL-vBDVDZ)LcS5BQGZVCU;)%d{3Q6j7OPiJDH9#q-!wpbW3?+A8Xqw=%qVix)Y2x{l53GyJCvlHlUY%=d16EMs8d2g*^br?+Sm9%x*e2Z#t5G zx+~U1SX*k|iIe^?Pq8^#;^=1!6A1TEE=~pHc&f$Nm@znYU{<~v&kPnbjsHWW*t8?A z3&xx3dph`sh%lFS)rWZ#=Tf{cEX@$b0gKO;*Z2wD{X?{}zuZ!P`7pJ+ClrfyxS!x{ z=i#(N8wf}1uxiKF54Ap1yH@s@31a6%1wQHBPW$eO?4VYNds*y>Rp8*wg#UaY`FNqlX=~Izydu;`Hi0YODt~h2Y9>QNDarq z+$=~PO?I_XhhGHIPq#@SZ*?%f^UL<#435E4Xg_uPTZGx1Tf1rM-?|hU1E#f!*8MFy zvUWNS!(B#iTQIdHMMl-YqZs1VQN>jLHp@R=aoDb{R zuogRjNcMkLMjw;$>qdd=oMn({?D=)!@;hVMx(fN3e-t87Skux@l|prM0wFj?DLo6* z_oQ)^lfsO>6mF8)evvKID`0WFhE!H%`Z}vcw9h0%*&}6=$-xal@H?uu%I8+^>#cA@ zpp%?t3;}yjR=2va4`$l%zy<{TH5s|NINrGYLos)vO)Vq{xTo++;f;vUkx4F|EX z+^KcCRNRSnu96|W1oj2njt}>O>8u84T?>aa87iiskN=!(OQ&7rI`~|MxXPxXjntDo zn&WCPFD~nmi+FE29&R9aHyIg}(@?GZADl!&P87qC_^s0&V#NbxWZh&-SCp#2F+SCH zlc5dKvK($)n?AADF@~g$zR5Zar+3|CZ&Si>@~DOXA;W2CEjhwNi|}Bwe*@`ra!dfq zxfR2Qwh!G|nNhCcL~}}Zm%`L_2+eetjg7b~&|N+oXkfl&P-j@1rZczJ&I3QDiTLW42_BT0BWb;-jP_B~T=;DxQE`c}KW;7k$5RH>`2@iV z+RfHT@&CYr68fI9GkdLU0|)*rh3r}XjIf>O!cMET7J~TTZWmU&QW)7+1ccC zj@Ed~$Bci`Wp5d4#PLFHIl?dg5#X6WphdN1WA}tK9US)x_SKeu;O1$S@_b~wrr06; z5=@HQRZI$PrhlB)t+pbB-JD`CoL^lz*cALJO{**GyWTY9B%7lH{Fi8 zM|JDTrQJ>g)V!UFOECod)u720L(r9YLP7P5!1iCb|AW6VB`D);yR%@jwK0J)c2J&##F_5Y-2 z>yE&@UJ}x>e>p7v4|3?I1|AWv+Q%T;)Y&A0bFG7?9|9O+WwY%(1D9)JbG=QF!I38IcgEI_0a>Zw`VG=RY6 z&*?{KV}R^{`XI#tGTM7OLI`Zf2Cv~vE|#X`#ML58p!Bx+RE%%a;y~$JD;`ZN-6-z` z%GO;mw(d3vP)nk{)NQZB7WXhDLF$6^ywp)}Hx$Ji^&&%tR=99fle*d*fjx04K2?*t z2dQ0D>@%t_MMwXr&e18p5e^ zh>Q!EVp1<<8Y>z=_FkH9tZ-pj{CXJ0hsu5Mr~Mcz6M^}YVKUa#K9ppbj5alhqG4gO zleq(M!jyeI0P!VzEfqxvV0Lw74j-X~d%do|RxgyUhsmL)LCvUheHmW=n|L@GB2e%m z)L2mhwc|9iJ4>+2*D62}t1p*;lYiMpyXg2ld56n4!-CZ}yTMWhe7C-=L&s(*`;MZo z!)5<4oc5`q2)Vc6NCbRnJ9AVj=8T#UH!%0# zwVi2)X$JL*lp!949X5L-5q8o3!89XM26z^BDAd3At)MlLvbE<;+cs@qL0?D8E@7Y# zKih zbh%^yZCi|ti^!dv(Mp|CchjrCOlW+s7XI@(CV?`p|M^gzBBOlJ@5uc6R*XFw=x6?*{I$2Fc! z5>SCXzyq=61h0;=m0oEgHKWG~18t$BO=Lr(fl8am=-8HO)E8xXp-ziQLngmz)2U0) zE1xVbrlw7`cltM#jXdTh>p)HGOUs+e-X59O?@jyCPfcb2U`U24rN3LFa!^&3vz z6J+y<{AFMT??K_cjCpTuRTU^v!|2rn*^;4>#!&eJQGuFgkvV}5l@hv^AR~+~lY64n z>ie)5`IV+7%0&o!W9E=3{exHj1hWZ>n$>L5mc+O}N%fn_P;Xu(Zw_V$$Ei~@8O5m! z2AbSVnj`ojo7+p#o)auK4AuEX3H(YpJ)=F%Q6Q0f!<5^O*#!l=A+=TN8S zGTNh!7Q$@GiyTHXo68m^r!%y(xlF0egYfAf&%WnSDr+vK_M6SlPaaCLg=}2qx28jB zS_|17wXYAikV<>Jy$x@BVtQt0Xq#{@R@fk&b*H?2jcVw%x5&uC-9{Rr7sq&3G`N0DR`dx>WTus7~5ZLy<2Oia<+6^M852ceVGa@CO$^<2?E?MYe3>$1nO~;6MzF z3D^f-YEYY3f3evqlb;dcAMNERQ^(%4zr9SsojteO%gkQ=BhgPw^pmJBpcFvaX6Tv( z$_$-n-42?df$lGqfOn=e$S+@#oVP3kb;EgpOI{KvUug3P_dV z-lYg3&|p^w)}Iy9NNO!kj+TB6+_O!bJ!kUvQO*V2aeHxIINl4;@jIauc_Un!|GGig_2fv zk%8pjNv3lE#hgxZU}$=xdhfz*YG18wnsjhJcanoc-b+-!M!Wje+L_VrxR-k{YGppx zSq=>=G&gCd?nlFlCRGQ&FYeIl!?gm)zl%%{Eo`W+LZh#$HTo8fG?%xjOHbO_MGlQj zg$Zq5&{~~@*88fpK4@r!}^cm~!pWx*vwSsHgm03v@T%lSI~RKK_6h^$7vGvZedUnN12&=Uy*Z&&O6^Sm_wt zRz{T%MH=9oeis~h7+ z*WrVtf?^5kAn3a=^9ISiPJe)*On;|IfJ>sKqFD?r87v2J;&IatE2H;dt7r)ezYmsy zfv)O&s1kM&W(DLmsy{^Ts=o=HX>02O#s)Z+j)xW>1e4Ebc>8ZE9wL|GqM5NnrQ)39 ztRAEdLuC*<(|6u|sF?fGv7u6W&w{05W9ZLwumtk1hsg*N%Eh%GCPVxHEj@-Ug0Z4O z3s;s7gS+59Z5Sr)mrWFbq7O*S=e7L_Yv|+e5*ty|yZZmYp9;vJN%Ds(wxL#$eU`{|_TK z(MLv^{c&=Nv%w4TG_uL+Oa*9m!c4I$2 zTLRE#-_s+-KAHkKvl+fiw&o_$wJGw5$@3uXoC@#rpLA_1^Z}$5PLmdU_~5hCq*tB5 z*U-~Ljd)>^CegNOvI3`t8>XZEQ*?Mb_RVCvJY6mta?^l_ATyW3N^`TDj3c|3)4C{K zfEui^POrqna}6oX^%|e*cbo42mA(7nX*aDLTM-OmK8SWkbVHGwrD7o3P|p?~P2rr+ z9gV=o?Ax_kgknzBqY6)_R&$5@(3BaFm$+49h79bN1s#mlnD66YEcfZ8MF`tJ;}FIE zd7H!My@rbW(U`{(Tp`2%j~gl~`2T4`#UJD{Q?53irgbwVqKeEp{&ak%TwxqW-Dk;A zmr-dIU$3X1o`fy_Ob=T1lnkXUv*Z{v>VI@`p7QZ3@z&;Dq1NXCbbw=-M_fxV-w$(#=v=paQ>^ZCE zi@!amoQ4}=fZ;rmOZ|7yf7c5=(q%}d%eS2pt53b$GDH<0MiVAsR0 zrJgfo+)MMMpQ&MY3YaHb7?)GGd9eR((u{eshZ`(ABn%--@?l~K{WwpKGJZ?#=F2b} zD1Rua8I<(^N*rSXls*7uT{|cv7l87h5^&DprD&s8i|9gSEZJ5;_mpLQ>hEpg?>j|*gb z_m5(A&NGY}E(DN}g}qQFdpu?R6?*ELg))Zkg<2@LpltqEG-44>mRGS`8hq?a-J7v{ zkv!MjRb925eV|w(AIAeEtRW)k0}M#0#nDDJARm$eR0FdV8b^EDl`RvUUDc~H*%QkTGCi7KBIEc-V zsJ?Mj^Wh>K+e!1``bQd6^r4wyscfczA>DB!a@OCKCnlE*m3BoyesSK@8wmD&Z z)|~iVo91+f`Yi=dewr38g{!@5JKDNb_6Wg_2fxT4josZM&hVnYFM^d^IGfuWSPs?QpjCWa~ z{StfwP+-Uzn*mE_q04F*@==S)dpWQGillzaWlk_8;Yr9o`(yAnKBg`?M$?{?2^92< ze2&{d06x;@Eo+;f|E0}*YnwyQ$_@Y2PpZ~t+dn<7XYFF}3fVdcQ#n<`RLW@Tb25=G ztdLQCOzOF1c6Ov;m5r!kENli?t%*Z_@tG;a1S*aK#3$qTH|pau8Y>lO?E!W+6w0aF zN>JxGs#qx-#sV;Y%=&#(rTILWK!4A#MQEO zsG`pLhaSJBqpPJ7gca1(;RocND_b}fW`xy#q1#NFxZ|dmxA}vy7NcKPWftxxU?*OUNhxMk8)Fd-UmmA$n>I5v}uW=QBJ7o{p*J>DZ092T%a3PbZzzys+H0w*F7ldbIyq z7=Wi!MibY{BvaScv~{f<#NMs3c+EDI#k_-I$Z=IKZheY^UzFOludKM|Q^t!jqHYmR zOReNpXtsnQyGeaf`Wmm&ju+*2-c{UoHuYOqL)+nc+dZ^yoxC6FrJl{!=sW8Q`xA=p@NZyRuv_+;FgAWF35Xp5UMxM+= zYPd~48Q)UfvB=KowMIr3-)XS(p?;L48CBiqAE}~P?l##YHQyhb6?;SrkM9E?VSoJb z%`Y#vQ#06f%B;)^nA#4-jnSUF0$~+0VWGJ3b{S|25HxAKyy?_Z-9jUF$nT=GhhS=e za+n$){-|G#O9IHpoO7?TM!FM6Yxn8gP8ny$jWavn)~H;YK2v!K4yQ`H=*V+wM*+K} z8RrIYF(>bmk@}}myJW}qg@&6b&R!=Q6`3nbM67CCPG|h8PWmGVw(5SqRtlBulGjZF z!IQ7c;E-JH7$@F(jD!EhP+_@LGg75?W5sL2wEMbTVo_Y79?9J}xv9I8R_&G{d7lh5F6VB#KmAoWdO2NX;P_-8>ifud&kTdIp| zF$(y$0sX*pQZh=$qrD>vcF>47V52{_gI2sDM~;~9*xej-mxaGR`ut}(KFh}MORcE{ zue+-mt{7??52crfYKEc4R~u?Fb$U}qWDj%fW)Qj=hCev+iUEuPj?YHn_e}gjT5+I6 zFUM!&@%v=!N}p%f=luOz3W~Kjz6XX+tu}n8Fsyv7g-YL)bvqHO1w`BCd-_gXr;VP${Z>VKfw^W<<8|bpMT9;QtAEn)aEojnS zIjAkNgNj1|QjW?&1o0F5Z6eQE6Ea#^Cdf@l5Y5#$n)epa#=`6j-QO#Nvy;`4_Lp>1 z;NM<40RJ*~5Cx&j^^A(5D+ljs>nF$fUkBe}>xb6m%et6E8~tU}6=?roUtVo{*)|Cr zJK7)+XX}SGEOvGRubik;69g98`k{vVWZlGMHNf^V!UL+mY-7LItl*nWWB17(xIt^* zKG^|LUN}blW1nml15wscy?FFC#Z*IMV=Ee2F5rIF{j#&(_ISBQ zSP6?Bv0|}$Xmqo*mijj>eh2QrleFO-8OMX{#~{FAzS&Yo$0axw6M}6JHdad<2J!eG z2Kh=KU;xGi`L)vjz%50EoYxS4C8b)%>NQKmPR}Dbo8f(m)Qd@z~;Ip02;E)kp zTrXP_pakD-2Au`z=txMT87~-R9 zL!6_dM`X0;dk(MP;MarP)RQcv9bTV>*Ym2q{uZ@<4`ELJi8Sp!ISJ(ezI{)oxqJkZ z`zBvW8A@%B%DyHSBdt0rmxNz3+@({9l;4Wz6&6)+QL&ehx1wLadX#WX#+X8%qk+c| zKl?GwJ0|C}84$=?w;srH8EShG_IEKf40iIp;DvKihwod^{bu~}`E_k0H9js^p=RLW zH}l)Z#RVur44i7_5e7jnoWQzM!?)l&?M#)yB}?s(fiZu0T(k zD(R-%>)*k9P~--Wn|7W}f1i-Uo$6uz!%oV@^>01IO(OpQ>yiJDvhM(os_6dS-E0WkKNkoqKnanZt&vVvBwe~{ed?I7^e;&Wjx^PP--py^8kl)L&q&)jVhHSa1jR6;xN;C_>Okls zrG+-4vb~Uq@Z|E>mT8gVVf5LPNL^}BgMST=_^~so#y;@QQH=ZJUjz4oCoJV z^7dFf>9u{9`ZXWizd`r$pK*Sc*6*{tz>DdZ&mY1|qX^(Ub&IK(qnah?5Iy`K>eX>z zX`k+=;d{f=O`q(?6oJLt4?O3hYfjT#f#+>f4p2g&Y~i$ie=b= zY3%riA>o;2p}rI{D_f@6Mqi3(OcgKsIF-|flyunmpBj8pz`wf@7Df8CSy2F;RguX583i!X# zXDBaApzJSES?)xoGhnKGhQX719BKY&iqfOfVx0~Me{s(W6blH>qteTbh> zwd}+BP@btBmAT~ioh7E81C{yJqw*N`cFBBNas+zvnk{JTca{*}+(gBsH3Vh?F+9uMehbSlV9p}4+VFkB9mr8jc z=4zmlnq&W>({W(iT`JkQDkFaDbGrXCU~gApN3~)-My9IJYpHx*0l$UwxnEpy?%M~& z*qnTi;>`c0hDz*%v4po&$dRqZjmM`=B-dL$Px6)i?Rz=*qIKL{|e;mRQ- zIv)gKiS)|}OFuZ%HvJwBTJ!0N?=6#!r|H=DmUgY`-UZ$e+REZ^;3pVtAA=T71ucX~ zp=t=31Dpr8qMYfVO859LVyOGkJD;`)Yx1nk^!tsoUs;m$?sO`AV$&RH^SzZ4T zS7ugF&`FE6J!r{0&>v#oW9QgcBU9T-`9jqR>&ZZjYI>@qEnCR%CrfzLe80LeIn8vSGmZ36R0Z%5aP8fz0-$!M$H(o>Js^x{tsQxE4R z#$oH(sYmw|eUGgmgph-lsgYF@mBfmcoX;+@qF;!?L-$V>qA#HM$Xhl!1IGm-f!u|eqc=YFjB;!ML`pwDTId(F*99O})piqYr%DL{$LTc@JMmYvrHWPsjF}k^>7C zT$`O{!0GvCs#%VmzJwCXElrpRy^TgxA_SGYDpFV7Z+R8Gh@C5N1_-xR0POr~vYiN> zvGX@zMX;qogrb#kjwY;l36~XWmBd5^uO}v7lku!2hUt~cRoOSWbE9uj+F5Y0y^?9@ zSxa;Zt{AmD^OjDHx^YZX zoEiLQ+|im#>4Y+x(5D6G!kz-2s+d;5r}JkuA3mM$z~-#_=HV&X z$*lW(>JKOgpnLxE56hdLp|@@jZcqg-JYxx_p?_MsvJ!rBkWkh}i0goL{* z9UU#$kK2U|-GlG2m=nB0$?GpT+nlDRe_@}hHWohKJ9#|3Puu!v$NLvX2SydgdlifV zoZ8E#&3{??BOqnX3zpA}##d?EMYc0>7@k^}EJ5C5T;S%U>H8`9k|nI~o?r7foOT7nqBJXx!hH;0m_l5g<3JAdN56?!Ps*;yDKZ zI7FzFfF(He5lYTVN`M8-)4PYft{@T#XEC8uyFRV@uFs*)D4Nhy-*sjylI=7IQc8PA z%hnod*VRx)Ob=k7;n4s+xMHdA=b)4rkL*uC4RWZ*6^J|a8`8R~mMDt3Y6+>0i49SL z9Pn~Y3@^y9f_s>(0ep@D22k!*i<=&*WT=x>s4!j{uUew%@KsBVoR-Sv<@Uj~+HD`z zj7^z+Y%*|}gTE_un_!^8cc5o2mD3e)3=fTQ1#z;&X$m-ei9L~?xMs;VO*L!espOjF zF;hn~HMnj`cWYs09pHqaH4!-ey2WCgRJiXt?y;C69?-af{NuVzUcKVXX^yMj}>DTsF%DM?w|0?}@)6&U!fa=|{?8>=oz}8YD znuSy_88F=;D2P2ap^nMeS|2)CE|0C}XzV)V7cdzGtO{JT>=7MKdbq>qP!BLTLaRy< z)gG77gnujnHIrj1iQvoHov1bcSOh3@=|7giCSwe>y=_Tv_1HBOt43Ifv)ey-xo>oN zn40B#YSb(osuPVqS5UJmy~#lr_2YMx+-#P1rjTpY(Pp{Jr1!+qhY+S+4=f=8?n;bP zWt=K^EUoJyX6z@Db!a&TjjjQ@gT$)d=AExp`* zmCR?s6BoHg1R6VP&9zaR%Q1v0O)Hv9dZ;-gLTWjX*yCUX&}1n#|I7r<>82bcGaEtv z`93qqW0h|7#v0F6NhTZ_XX0E2iRg|rW*GQ4J$4UHw0?;+^qwWw;{bH(+fa3D#5@8JR?2fufOb%KqZneW zTlkq#tTnQJ!9^_NK9BsUN}mh(ps(dBLf{dL>u;_iJhBt`;qnl?g$1ekIrc#Xr6|Sb z=PrWVl%S*mv9k1c3_!@LKruN%dEO4i{!&Pkhe(XBQsH;Es*9ip;L%4@a<+r!1I^s6A1IBAn%+MuziXK$~FLna#9YG5{#e`N> zTAzeM&L}+ZRIv<(ZypHys~!WrM1!a*Kn6Hfz~h=;ViS9H_OBt{^o9202>98N;DJ{f z0_j2x5oW?)4{wnQv(94b;4Q|7q0pkrLdtuU-*nVlbQ@fy!40kt_j+wLX`fb;wgPF6 z^}*8|5Kb@oh+n%@X<$S(6^B)mHb@7|vDgrLt)}>`Uln*^)zl5DCarcg@N!`0cP!qm z)N~*84Yz&8c1x884ueg0p2q{#r0t>gz9PWXG_3G`EfHcAy7m7;HO0qOllBbK$T|p@ z^6{RmpSY2tgHgAd^3m0#g{j@Zx%QF2D6F^4t^mbOEash9Zi30dDeX6!5`>O-uS4$y zh)-Qzm9e9!RiJ2WTu4s`icd_-8c?ku5&Y!YCd#Ol*Xe27b(L3ffO)POkWV3v!vdei zT62_hbRnyn@=vN=sCfvcXUBZxYA=0k3liBaoIy0L21G-o=}(RisaLR|md;i0LoMo@ zW<#1|-8w>=Jw@ga(Z#Kpi4w)cdeo;yAtJ(*5lUM^#6T~skcLVr4gz{IHK29WusNDX zCfmx3a7E%g{^AyhO6&qd>G@DGiXQ_F6_as^_K7;$4)zWc?=-;XJgjZV0_CH+$Tg`JfJfTm|#}LbBBrQL*6c+A33F^J0J4Y}h9&=G@*e-ju8-+PQZ0 zw+9nARQO&!F~Y&$dx;_$ zf%x|&ieFv*m7aLhuz?uPuhk`q&Yu2C+>f z_okv@)C;ZP9bn3j#jT`Fgz{jXC%v_m%N1vHT$`q%gWEQEPaRg*gRLnj-#6sfOayqc zPt`T7O1juo)HQBZ6Z!UYGcnftiUDKFH>}eJ(QnN}TRd+Z*m=OI;BmDPQ|;O`Rf<<#COmVE<{fPoMUgGh<`ewuZbD}az_E|;HHD|?NCzLvLN zu_nBAP8HeAv!{w=mu*@RQ`1^>KUMT_`3QA;J`>)^CCi@SRg0Fi7CrphOs>l6;IXsT z;%WGmJMKqtL^4)}86jF=l5ug1U+i(o?*WLW`Ntj$@T=_v0xp4V#CE@5U#$um?`yOb z~>DmYBT7VEYUs`7sGvW~=%~kOQ z{o&BJAN)zK_w9{3Ukz4$8ovyrM z$G~0+Yb;%iL)_ZsaK+^(%G1RdEGG3=HnqqQ!~Ewvs@Q3LrhbJlQEZSxX+~lpLTY`)4>M|KqI~+4XaADqcwEdWk+Blj}oU z+Oq?0K!gVQmA_aOZ=43bMULMtr)0dz(_2jT|IjJe4rK&SCcr?ZnFbf9jB7tdER)hXW+c^+*iih!@ba&|w0eGZ_ z0RPGe5pME!qlF`oh9h?*pd6(cBLM~H@+d%=55Y`@^4%yvd4aAX(bV6SMvX=dN#+rN z(()-l33sJ_Pa*AJI`$Omoq_P9*8Avb)GMOhPXjbAqC5l8(`o%P_=T5U$KcmvR5}_! zY-2>YOOm73bI+odkCyZ2vtYRXCb#EMxR|CqhpHRtCjVMM6UO4#Bsw=1zXs6qF#xn} z8~~+4-cXxwG#-E=w462L0q6nk8!zTDqd!5+1>;jXLCl9o$cxY87Z$}ttc}MhYa9Um zJP~L$H`1+%;?;!{1)j=t3v5pZUjX=jpb_qWD6Ru_+vyt`knmj91$YX%38uiTfErF2 zJCWi2Ub7*7m!Wx7`CI$R^f9%338%y{r{o#5_9ZbUV1rZgC_9*dg-#h=kg<4@7!vTR zQ$}NCd^We)z<^;+83D+cw9|J;K!#JsKVbjWj0C5QQ;rO8r;J^WjK9Ik>5*H3jKU@L zhXkB(%9!b>QRtL0#*wkuDWj(&BgZMDxucD2r;HFsjZRJ(cOj!-lA4j%>!M)_Li(5C zj?;|V99m3!6rj~yMB-4N>e7P$#X12%jK|l-U^+Wl)TR-yi4>~8NHp~Wlc>ji$$ffe z5x51XT7iKkk0vx+}stBmD0>3pulP=F{*4y~K zmOQgEdEMM*{Q?TXlj?_J4D!_h?>tR3Y+)bpk|Yu*3;hQ{nk8m(0EpQrj?-nfnB;eUbR|HRpmAMs4o>%Pos!?6 zgLA}azt5eLGbwGZ7~JJ*IYbgj*^X$FnW`azA5kzUz93C((}HT3qaoU{X@8p!+G$SU z#9cZ+SG*ZK#F4JkFxS3IQ{NKL`=vVa>=X_3`fV{YD9Dkls{;Q1Z8660=BTPDuA#_x z#OR=tj$~bpIrRQJ;^h?e{RfydKzO+8%W6Z2#tQ=4TGzV%nWMJ78^fr>Jjgk7os!#e z?qGG8cEMvIFmr ztcofE%qe128>j%Z$rujO@~Fu;=~Ql5X>i6~g%8`p+@H)W>HeXB(SnNo) z_qiu3{c|C>8Eu;{M!SwjuBym1#oDOV0x>G)aYuPZ#vVM?g&X3KNpQ=c;_>wx)8z#M zH`5$N?V!u4#d{bIFGsR&IIx!A6JyLlFu!PXq&;$eZba45fPB3W>tVlB@~iaoLNUqz z6GyTg!vVKxIEgp>bDh#tZqqdqqXLFI((U~VzHKM99i1|u@mnNTz?19P2O@y--WM<9 zMy%Hd;sD%4ku=XF|DoZF#k;0}f9Td?G0NrrUUsql?OxYdUtn_kht_>4WDeeas%70! z2HE`apD|`I1x|x;BpX5E%Hd|x( zu2DHmfQUqN^(>b5bok-VsJ-+9H`q+G@%I$sEwK9n2cmc$ry6@MyFr^-kAD70_zXcH zxpFuROv8T8E`dKWyb;RbxWlbES}2{TK1)=bp4mV-+v)$_+7l1x$VVbXZDOLX3EWmK zhp$kzO%z#_1OK53scT}4u8DDIV$36&z@7E{|IkFZ*2I$tCs&@WYhpB-$bLi<%NiwveG~p%Yrjcti`C7NyRAXkm`M1ze?rJ4?luXonV3 zAJGEdZTh$4|9wk5SJ^^yT?=qk3L}lfFXd#&VmhpaQtCWW`5yNfTqIjh|8ZE#a&n;Nh z+jStI8fhv>U)DgGRkZ~?1^o~qRQQOx z2HJFxQz-KtWHpZ!k|Utx=U%AcXK2R?5m9erCtGYS5ODYbOa@<_wb8?-2HkLRQ-f~s zd5hSv_g9E^k$86NW6Z-mv>*u!9}8DX%k1=zK_TPl|Twgg}=jZU*&G8i^< zkDi12cOCMNOld_4E5+MJTjA!F;!UF#)}q~NF}*pSpq5H~JVQ|qoPWpRfPfcD0943j zV+`Ad*EK2{W}PZ#!lgakS}n{Pi11HE%kW*Fz(s6a?zXc%5kcNN_xO3x0Xrlb_o?W? zxbU+lt7+e-qABzf|9mP^A#*ohBg{FY!8L2QCOq@&GK;R>pzz8!>%OCO-{I=FCnCMM zOKlFVZ~+ zL_vg{yy5-AHlK+fUA+s;n_`rY;i{39NKpkCmn-ymfq2%`VFc|g5av!-Ms9aeA@Z5N z4-nsiL8UGx9}{wA$I=W$R#d1gvwkd%b85b&Va=imIT3^q^K(fGQrf+Qrsd0|nMzD$xM7 zQv$i=oDCIkn5mudMXDEWePb#4y_cdONzs@Cz_Shdap8~w6bg!x^*rw*pt z&@ogRuT>hXR-#6mg(t6U9>rzUW;0qjpsSFN3Z1nIDQbn*bE~%U3fO1+$QO^Er$cd` zi*1<>&@=#w)d1C00p-lE3aGap5a|Gsi|rL1peF(7F7xboR>cqFdmG;d@Q0RPIL(BO z;F^D3&DXxK=)N!MzRiE(2X>2U?Za+?VKz*u2Ou}pLN57t=;qTWjSs1OSb??V^D(uhE@*9yfbuTl1zBPeUD2r>Czp;xzx*{*r~$g#&Z zkrv-TE#R&WMuNRC$LFkDk?xjnw$a#aA_{iO^H$kh3@K^mA&0v-7g%)VlP&5DXjb)6pYJcZS1H9NaOF!jqbKN z#Xt(@Gz%vz%;0Rsz|~h436@UZ*ueg9JgIz-V=7?b0l z6*&qPYt?1}Ksn;-@IlG|__&=80ImSA4fUDop?+TW$U|u zEb{&8H_&PR<`Lu$kC@j{ebI}*v*)?nJ+V_T#VlVM^N*MC6kD|^K7c9i$a8(D>Ks1} zppH4t-rG_2K~?8?ue+^8z0->|gQw3J;7$hU@doAW62VOEc#S+kAMFCQ)2mf@r9x@3 zTg3NNr@suvO2EePQYljToEC~{JX}~|dcT1*{e71{Fy8Vt0Pe!@!j1?QYPi}N{vZ51 zYa@-_BjO`YqRV<+;mk{z94I+{U=M{W-wCq^2+Ode_i27fXdo1Tm-Yy&A7HVp+}TBi zRgk@r+U^yJ*z9-*;_vT8XieCT`Am+^-?sGuEwsf1`p{eQW1xxQdst7|#OW`Nlrr8Q|3Z z-itas3(kmG_r}WNBX%_LzVto~O%+rnnmzW5MjDzq`$Z@RTW(2<_lr7yM{iag#vIzW zU$k^-qI^Qe18`S?5$J#@h+Gz-WdD0+7UsIeG6YRF;J2BBB$nVMwa#?^fN0P1U{Mh(zORy7Y~hbI z!|5^nhPJiUylDFIAW(@W_ix1@yrPx$tw;*YRBuXJlwGVyOVz^YQeis&{K61K+gQ}LiQ%AY%QpD1RUG0?9NZK*5KTYEVeMyf-izMsARpNLbf)uo|_ zM40aqduiSuJulFkheSfSy{MOC>d{OttBjYqDf43j0|RI1>R2vZr$2d^tsT7Tkk?@m z0neiN!#G0rQpdxhcW^&PcXWz5w+jdaAgrzyrT!SYc34=9=PB_!Q9spb!5Y}d94`-B zu(Ye&n6m(zhdtVAu+e}$B7#2sPQ=uy;b;;>l=1o!4>T>Qkz^Y9 zSK-j3Vu~?bn|~dpS*B7NTq%B*?i7ni8naK-p(e*fj9+~xm~hZMCK@BIVQwAe3(PH( z4b#3q>Ha=3lzfhhSR+WpN$eev2p8&l9DAo6K45wh1e4%#VR0|!Ansdf{c)_hm#Or) zDCp%h%qmIEt*flU+N*Au?*Onm%y=~tYbP)3Bxr+Y1#QU7IzeS8M0}lBojTCq&qs`V zkn-SLJBbLQwZ}jr91t}Uk(Ygfc787!cr4>(rxC+2Q?8l3e*m7%otlCE_6Nu@O%%_k z>G>Z-Gc3TBKZt*wsUN637{aDX8H_{KVaZ_a)KA0ErwWFbe-!b4g;%Q%G4|F;(a1eW zX=lgB^u!;u?wDw&BE$f62%Xd;bdo)(!^rz5QOAFx6V$jr$nukrUQLw8V3jFFtjHDpp(f6BIs`ed5q+dj`PbLp> zZbN1ALHi<8ey_xU!Bk>!K9&+@+RzL)lJDMfK?Y>eci$ftb*F`(^zaXDCS5v*;#Kr2dj8^tzGONQf$bsbm9hRY0 zu{;ATKLCTR-``!%KLX28CE9^y3mujWQio-UXu>o^#V?ZPmS7?FacaTkJZ&ivEqp+Q z@cjEIUW++2^OR^@Sg%xcF=iB~=bMhcX-hFqxjb4!HTpHfn&{Vz_-|TMK{+C-pthk5 zsO`U86}6YnX{h1Cy@O(_>(mgebUk3F99eYfjGb~YL|`@;DgscBcgn$B;N(`33wBpS zl(nH#o z{UojlOOq>Eap|^FU&H3*{3xKB5h}SRMz#Q#j7?EI9NaVi%|6r-4|y1DWe3279#RQHan=cY8644SnNynhFu@Ky z{Ne-R^vpPuZLwWX!Q#U?FjA};Q1cS#+v{NE66nr#F~}5NO8st#J`TzELt1}BB)Qoj z6ysX%e3wwN-4JR_bC!$oe&0>x{-EZXm-yq=!kZ!{L?;@kEdY}iFFzpW^@BXXJDa*! zYJGT+x6q$AMZd;ipe@RYOwi2)On+jTZ5BOH#er1w?&LzU||HZG=U}0A+Q7w!uUPm1i`C>mfRL& z+zd4ob0+!PL{A<=w#ba5kv7r4PCZm&#acN2svE^_zK1`wP2AwO>6W7~f}tP3BRbaE z@<-L}H0q2-(?6%Q+_*^UaaRmu_*~@_ng11W^wV9D=13~yBz2m&z&idFO|$+LvmFJd za#8>_yeB;UlAW45LmlpkQ$apRc5%vDQP|=>y!h)Z1Vg0X>>Yp8diROu>VNQoc&1)K zHf)#M8{nb2PFCAF=p6XO8RE*Hfv1DmwembVDqTdX|aAKE0n$|RNNlFCjFGuui zuAk)%Ed*?a|Eqqit94ttXVD;N|F)IT5H}fZJXZL+n;c`rgI#~ROFYqLP~N109x}t! z`7|xTUvGpL7=s%;C2PB)6~yXj&>|~qJ8*f8fl@%Uh-8_ z)OE`DlFdvlE%ck0Oy-sT307ssS$e02j3rq^c6X%JQ`5%cot=9%WOUFzFfxv<;&8%& z#>QI?<|{MavOTxB0Fqy;^_q+8R`ZMCJdoB zeB?N;whGne(oG*}Ho8(sP1!gC#$tcyqe~L>Q}%+Y6fCB!nlb?1FfZ1Wt(&0sZq&|I zp9gKIUaKpcW>gwr7H%d$-G^_zx(@`cri>3M*uSiaf|mi95?8#6f`dNFSN0COc=ZOI zhn{G6sFv?Ax5by!9A8<;9sU?i;-QyXGJ}z?CF}B_apEs!)Hpykql>jR6V*-yh;_gKhKpSUThgEU&qI#?{TZJGfQF*1QbT5SyuM;};@&Mg3(6SZY8Q&KmI z_mlB;B458n=TLB&y+OzOFrbotvXjZH8?Ez`ZH+d%A&={xTB}h`-`5o2UGG zrTT#iK|36=<7*g->q1Yn2ZrJ_SHmU{nLH}-mocz58Uv(iX68Y=M~wpHTaNXE`^*8d zt7$@4@(q+7O~blUKmOajD=i6>>Fo6$CjV(2@rM!IT>$eN5e( z(>us8Wi+QPL9(sS#-B7ou$vWGF{h!ZKqsBdF+Y;Gv4vWU$qX)wR_N;vUYIt7;UX(JBxGZ9L`1d zt>{)l{$Zex-m%m%OvcBy$LR92j=R1E?}_ez3^f@y?AR&wO6Z+1ncxSQqX3g1Y-J2X zN@#zWwAibsDvKS}@syLky0L_!!ezpfjsZfKW?-FO2ZK?LZ$`=W<>9w^6XhTsR1QO9 zR%U8w;ijXd0xkO{Z&8X~ayW4I>Eg?HXK8u3wDLPxAkHn=4~sn|&cRE9bB~ZMT(;}{ zj`=!)>f{*=Lh0iGo~y+S=l(k4=`e7dM}hh1Ab&IC$_E|4;?4nZ5Z^XJhWPhBYiAJc zY?b>-%8!sk@LYCL3VBD$C{u28N{W=*aM9shq?`#0;&V~*Stg=|+YDj{Vw{duQbt&UixE@B8}sy9m{J-5!`KQApQ=4j(&;#LtSi%7 z_AA4(cBzp+0IXUc^*b77SVMka{ASFa$M|W!Jnj{~Jf+`XC)|N~FCvnDt1BBr{;63{ zCb{iF@;ME|b>d+R*VF6ugJ#+nTN6cR6I*ZjO4Z)vNoG|okNoz})ns&fb< ztG1~d%~k-esKA5cs{x+)JuOL)9fSV{4c1tq%AxiDzVJ?he8cF`7>rmW{7-(_9BD)l zhD15cV>Tu3fdc zI=+dtEJ>!+Og(`Svh$Cd?9x_}6bY|!gD!^6%hU#2D1EDI5cd534dsxUE;=BG-&b%!p!C3OdR3vqa=>TiPBF)pQr76f}{^x0M%V>mX%0Kh08J8P07H8I$E? zuz9a1%VflUSeq=PO>K_Tk!0CBx`fd*G*Jeji~Pn!DX3Bzh@3XAji_A{x#)>vKDe~F zSCL9aG>2!iw*2Ithj{Ry)|!%uSZ0`s7tz&rjl`Zr9yo;K`8UMsWAvVhP-tC zj|0bQ7``MG>nSTCjV3mi{rFhR;%3KbL?4WAb16&>kCA_hOiA)qC)xDJwBvzagPcdh z9U&0p9KT0^v7Bu8H24G^`kW@DNa;u(i&Yq!UO&-q zEkO`%RI`=LbEHQ9M5|gM^#G^7LH`Kp?|^fOo=cUI-ril?IM*??%ptcp zNj=)i5LW>HmY!}aKQjTp;C3>J&-I6zM=$r&z;-eYFF$k3;oi#FN3{Gs9cw2Wg@jbw z>R#&JR@QM1QU>&(W>&e^2S=P48^B!D2Cvl_(;$UiC=5!&U<6!Yc2m#eS$?E0>2k)y z8MS|;vUHi@%oEeuWi7W$?yBVdto_jwOifG`$-Ucc)+xrQ{C<+s6!oU)>$z&oB2Vf6suzcPyX}&G zS}=?H9|}9&uBb=}9puN%9qPxX_Yd?-2ieIvx%Cg!tmDJU@juXe22{#o%v14>{DDkajQE)gY#(TW!<2SealJtFBp4CX{DG_d3mBi^KWK6p_pDo0d4O zutzyMNMQb1THiy~^#c^W{NLz%I^RQDu_NByfxS4dVlP%`0d7-TPuZ|D>KTI!HZy`k z#9n;ugnHh^geWf9oJMVPsty3WIm?b;C%Bv0pvh5t0nf3Do=oaOTYAbkM(R{gdEXN< z37_hSF7mhx*4{x~0T8pu*h}JJaz0v;ddU{`7eiEj2InmQeHP^O0xDgy>&K8*@C@{0 z{Fi3+lGbWVU#_n7m0ogo1p2V!D>zI}vf8G0QBR^`$IYEM?nfML?G0L^cIHHH8Q%c& z^!e2XDYb!T67ckS>Y3Xxk=Po08*CT7thR>mLdUt7$DNPsBUhT|px|u$FLCkCpK1R) zL;YJLe;WQyr9b<~75)S9sS;qoV)54NVBwO!pean{{-MoJ$fAlJazHy_6OPfF{iJYC z4mw6h`e~{rb(`5sL#@zXZmrlM_S8dkv%ehRoVuQd4A532A1QeAbD;d5CoN%+Y+*b{ zLk7vZJ|L^?UCAQx40?Nz40XsWk;SxbkX*s#`wW&%jf=T_L`pK`R&_yE)=P!zp*$H} z%495R$b!?X>iAa(>nCXKAQ@eFW3aqrbU^QMl>Qnbn|a+l$|DLdS(-9ThLd%uT!7O} z{k}3(<{3XM#CNa}Ud@X#e#@-Go)ol2ZdqXNk}IlCpxs$mmM%x>e3o2@>z%I; zm$Av}0q4N+^{wbD*yu;~HRuQ(87}w0$w|qUA*PP|C_h_HuBkG&p6Vz?Y^7!+d+G>Mo|aEmEKz%E=fiaW zY59e7a-GAp^BI}poa}m-{Kv?74u<77S~Etz#=ll$;C2)?dRC4wIhIH4A^Kn}md8QX z(qMTUpr+%oJg$tz@>r~WFB^yDF`mD>Q1m$2f(ph%5X5{k7r3izdsLw{xeQ1Ib#eo4ctvbC&~%6@>uQSSVB!V z75+9+rW(2Hvu`~BnKQpA@21>5$X)fqfP3U$Q@`2e*(3jN^_y>3xaVI~zqLvE6W?kp z90KYk*{zKsLMgO@LB~#NXE0n%hkTTdmlVylr+#3B&a(`%K?ZozY?uJkYft-NFn^;9 zAPy;B2kG)lGAh>XC+J#X5Kx_L<5Yrug=1bV23#&bd_FavB*RSZ2dT>>`MfEuh;~kr zJxq;?$oFNb+IyIAe?~99ESDO~Dd-g_Ob3S1&{t#vJMpx?^B^TF)1+ux6&Iy!g+XbN zPD@^q(|G1wz`S()h8nyo+tw-jrYaqLcNd1o!)kj<6Fc93l{w-j%4XW}sto0&k_A5d zT!N;F@&1O+zbc!!yD9PI4~X(+yM@-wW&kX^)?&Xn)l&HW7vBB(0mjLY?ON}m~9IvZBu@&pVh_+U;S-lsjJASjk` z(k)*K;~}gms@?;nt^_yDO3*15(Du}TC$cqKSpkFa*=(b74m|XE_G3SAlK`h6b43Rm zQ~o9{h6S|XH5usJ+dc+-4!G(*H!PlM>mS;LdHYVYc+O|(~gD_3^o2!Xk>dF@_Hv@if#=R6eEBl#>fodW9r7G+J5 zAzsJ9`0(<&LRlMI2hqYQvT565gTW8G)cfqi_{3$jg-=H zm==^-N^Vo3kKRc2rpjh@RsZ?3_a3A)*{@kGM!cMmJ_B({adR|~M{V-MLms=xE5 z7kN?0bR53#Qs?O~AM{M7h0~?QgqNd^OqbH9rt(2!O({75#C3*@=iqHKWFJIdczcHI z>!7AR_R(K6WP1O^kJQzjr(fOtmUx-KZa}kTsW{x>Z*QnAv}Xt7pir?t&bxCPo+1P9 zX2ofSby)1s#Mj?+kXG|!BGmjMoR9I2G(#OVEzQ-?cbOsgIO^n?>-#E+j{Mwk zEg$#ftG?c9s+bME>_C^<0btFQc;s-SdFFy}rH%st?zM2Iir``F(l zt_B}vJ$*MvhP1r9_&OP3*f2v@Eu9FG1P5>kaX6On+S4?!`%Icz`zk9iOlPOLRFJ0E zDRQoC?Kp9Qv-n3T}Q9JB`pZrv;Hj^;b0bi z2dBr(f!)WE(nktBk_2goKWP2MXM3g;2 z_1=-Kd8u+{uYwbC^SSL+-mLY2`bzKG$I9hk(8G z<2y3LQ|+*O{sJ=3lg%5|!m=#y1U?U=GYvZYaxC3x(5yL@uF6u|v4D6vPY#XBn{H^O zWUqw)m4gvQ9WLuoW*nq@^Q5JQDy*@1w~gB5$@rY&=~!bNDR2tb*n=G3HP%oZBv50$ z_knJ!RX<}_(qFJ2Cb}65*>jWls;C~;)JMYVP%-^i(m#C|m@9yl4F=l)9U2hclny-^ zrY8`mRo-wcIu|DVSds~fY?L!h-%2*t*k}-iF}TRXd09suw6B2t&patuyd%+ zyRvJ4M(`;h=m7+O2MfUW^LRC@`{Xq?jI!w>8c(%E=kpQ1boWh)#K4#^P&h?5x#$Ke z8*nfNSJE+1+uxOSydS(@F|~B&T^Sr$4NowYyynYjuTk5yQ>ln1L`1`-5i3`kJ4#XGlL^Ajf$Zr-Oqi2cHt+L-Fs)sIXjB!P!dj1Jv@-R`s4WmN`se zH1s_gW_+Grc~1^;X{3BiKffpIL9t$z4XYbU-f@El930Xou7=I5j-G)-e5KK_`3jbe z20>%tIFCs~tKHOUp^RzRr~*Q?2g18TyUV33ZhwOT;?nh@$tz8!9!U|Qv}B=-&2hyb zm$_opdFA1F;z!0xz%lXZcyEy|&u$-paVpP{B9-0h6YZ6DfG>+~(p8jawO0w?@oK!e z{5m~&;JKy*sIk58Pd&U&Xs4^8nXLqP?B)aG@y1Fzj4S1FCgm(f@*Mb_Ck%!Kr=5Vp zd5vU1>Ipq8N5Adu9M>64##pc$5w2NfDobCETT4yTz;`wl263~}*PJP+nKoGnS zUqM~CqIyj_>^Ii{DA5$mbv_kkA+`p?P8f6 zy@PaXWgg~sKK?INr?$Wx;ZJuL%UvE=qp(~4LAyVcyQ2F(qK0b78&Q{*ek9*dh}Rdw zVO%nqmkpK^c4%~E9t~R}>v^CiY;sL$?h={eiUCihy-4=Hv#_FTbbX0zVA|S{qL<1y z8G}_C21{lCI+HM*RW=xU&szq(!!jAw0NM?7A5C+Zja9A>Z!tEGbNMf5&-rxo}dPXzho)#N&n<)xhNSN4` zvdN<^EQTBh8ity=NCz>6yFm?A$if(_Hn%Lc_h9w0XfBydOT&!QE+#>&>cDlK6B^IFG?X`e`QLpNpc z|LRV-)}5UYa!SMLofR^q{UiFsePcn?PH0t(reG5Iy6zHGH)BsNXOna;Y{b;`H&cL{ z5#zXs%)bOB&>x?`jp;IZtpsn1w<}gcu=-__Hp;Nlck*pc3s%AfY!%WdqTJY!ep)H5 z?qwIQ61U~I;}xnkw&A|RMdR} zbz=dk#MH0Ik}s{D zgOr`CAgx0gU!?`~{3S@0anNR;#W&y7c6&MdHpiwIk8~Djn=H^yv?5oQ0X%6}z8q*= zM|D1fjbbs4{0yFo-8a%ZpUL#di|^cobAVwpH^CY)us1C@W;v6D@95HJQ1HZUB+KWr zqj}1EcuQQj3retVnO)?+MjZDa(MO*{(_-96J5k)50`aINZydt*F$yD!Ptvdx~tAPT(kdNX0x1zQ*>3|FOlo9&$QuReMNRNhz?1?RgjaE>KyEggymnKM z4Klvw{PlKPQ_E_rt?h(O8)Tr%P^5phC!tF)q8vMSuOspX&%~Y?x)Jt97>VoBR=dGJ~?Z&W~vnvdi_8DFQ<}ljaEQmhe1a-@qr-@Q%@opn#U(YORucJBkR zL3p(GYS-$pTJ4^V#F=_(O%sVbtP6`opja7)i#*v*NOJ(->j3` z-{Gg)+opkcgUgEscUfKKeZVdDG%UDVUPH;rF|4uWL2h&9XCc}uIp>BUZcnz+mJ1!4 zpYcFOGlynI@%Qkf)_Ycb$9QH&nG7#4DGN8`Xbu;-@gQEN{7w*2IP?-1&OBwk z#{`WjKLZ>NfY$mNpsc;tdxn^-D9mnO74RABy_t9}fjf}>yNlY9>H?ce){liLnLCsh`C!b(OP0VJomrrQTbm=#T;zul_uc zHGqc}?qa0JEp6aBX`pzy?Zvfy$sG3~E7)Qr-!m%JHJC9aKjLsGe0py`~2R zwx*(2U8&19DH=9Ggg?Q(ssxqb0M)-Ls3Fv}5JrPq(cUC(ud>>HM>XKBZ|~nNG<=6_NJDpF zT)5t7Zq8KE+!{x{T~+Iyp&xdjx#PQJaMNkfcxEqahHc7iR@QyXQTIUAx_hYeP8s8| zq7#$XJhB#HsdDvB+_bTx>2Z$gN2^v}NjrARMxET&Jb2)~<}7Gpd9uOA))0>P2QvY} zZ`Q)*+Jw`vMR7y)N~i{XuMkn=Ty{9;Eu53QJdlxj=E>6)*Z8@l1^ux0uSh6 zr_-klTC}(fZ&ei)>tj4*@-ZEPO6p#^tKlA#+z}wT(?N3Edsh7Jj)dV+?R_c|?oGvS zv#UX2I-Gq71U@D^YUSDoeOY?RzV`r{VU}84^6#M|%!slvWgRq!M#P4qg1s`s7m9{d z;Gu;mEh6LBGGJK9J2(k&MrGrSD(?wY``~{9j7}^?eHsBF^tBD;m_~=1Av^A0Dj5ep z3S40NW4XuoT5^v!n+-+^L(e*qDc*+7{7R||e8ID=zBKV`+>~i?oR)kIF5ZWBeJ!&Z zegC#9WNIpZN1JHR@Do&r2%T1j_8i9|UIg4HANLy27%7uCB;TP``($bkwDcKJszlwn ztJ+UW(XhtpX#PeeP}CZrVq>#q8PsfgwOX5fc*N7*S+g5=7VIpz6}H1LoMk4%rZTLX z^b!mRyo%j)ZSWwRjW)KV%>D8e&u`q773f3>mF|~gOkUB{I zZQAlV%{d_ZnQ}j;vIBBZunnxQGgCI=bL#z#oL_TN8cP@up8b^ecj($TvPBpCXroMN z2=N15I|sfDysswf=?a%Y2gP2GhwfZem08%*s-MY7u+?Y5;4)hc>*PVWOg8?U@(;>R zIk4AqeA?ldeRiYf8qEHdfHr2T>bO9q6vs1r^OwcBDzCw!Q#SAMHD{^Un)6G0ui>M6 zvWvGeyp}=x#^N3kV*j4zt&ECRzrlQg#{k!rMOIrfRtblE1ePVGSP$ZuFqM z@u)Frws`w49ytc}SA+A1$hsV2^~Vq;KD*7$zvf> zxW$zQ!(6ph@P7XbLfC@`q~`meh1zHV%(U9VEKh2FSjIQi4JAM5$#?jeZ@f|8uwb#q zO%-I$wGa0^s9k2!oWnA#!#w1%irm0!9g6|t*(Pm@!;}w`FxH>(y2n_9+tS9mjyBel zt+w1@+F0+WKM%`#sc^Fgs%M~w|rG-&PxaN`Yi@+WP{%wZM|1E#(J-uo<1T2vf2QZEf8awY?fe! zXmpb4eRO^pcdL)qtrB#DY08A^n(c#bu@a-WiDH6}qrTZ4^y?9z53$05{`%X_=>OIp z?SL3opsy><_7aZvYWt@u`i-jVM^8KY^<6a`st)~E9zy@#Q5lf)Q<7mp;Um!B%-!m0 zM<3lNMK^q^YqqN${jdC#GEhZ5`UBAHQo!dE>6QHJ^f*Upto%o3cDs4d!eTkl*FN&v z2{nc870d9PEwI^WClmtIp1}N`#Q$+{tkkFDkS)Q1Tr$RL%h#uuBkgzm9}OdcKK%mH z{>Fc7D(DNZm>afIhI6l{xnr%oq3WA!qt`f`@gB>fV{&Ooah9Iqc1lAm&NN%Ef2hZC zIouWH@@Ug>*{O2KU6& z>hOA;v|oVY@RG_2S!2+;27L{T$lFnOm%&zq2{Akg-zL7(vlmgiH3``zf5&=S^1Vzo z-EK^$zL$}STMQsia{(;DV4L>%P5QW9?(w(tZqgnANdKvwdVKf7FmEOE5AYm;RWuuz zc0|fZ>i&ZaPrp1Jz1fIX?FwJD;^SdTd99oc0>zdzFf6dD_cEF(qZ2_Zaa5Lq{W330 zRmwI(dD)xte~@u$-)L3hP-PCP@RY(EslWi;KyOq#iz?G&S}TyS`QRyV96Y5sY*^}E zvz~l^l)=rG@yUyKt0KzIm6PKrc$r!6Ji7oAX9APvfI6Z=^_5wPyw#V}0jBgM&l$9FS*68FtW98K1s5 zTrl*f0Vjju%*7tTLHq~GV*%%-Kk1?JJ>Mfg75Pm2M<5vSpy|w>DQF)>XcD|5ntK04+|-#LL^Jt-qc7pJ#RRkE>5 z3(#^1_Y4QJ%HlOwkG;H+i?zR_mST*6)mb&#sXO%eU>$&6SUje)pH1?dCKN*rK) z1Xy1s8W#Kunp6TVWql;wKPkJwXQlH`GA`$7=m^vQeXt2CDO+hAPUSXeejZecSl{Ve zVVVbs7XacEK>P#}mjP3Ix@Ye3XkJ-`l`9JacP0I7sxl1=@F|o(it_5t$I?(a)k2)W z_)cHe8qy(L1aR`e5S*i0f@c*$M`&N7Dxd|eRY3g!Xa@k5pz@fRYNxKGZ;e!@p;JAP zx5b`ky@fcd81yga+@vqiN!-JD4j0RxE179hAB$-Jsj72BS{l;Q*Bs_(vg$v2=4ZLe z{N(0}ONMGarsK7Ab@0^Tx%hDE_KWOnoKFjX!POC>Z-0>kJOjYbyXJ4XNexcPH%#kR zQ~oL0JUykBvK$gxbX|0PsiCCR}pMd zr)7|7?rO4}mI;CO>CY0FACQ2}V6i`>38!U%Y0_$X^R%3tqbu?A%n!5P5bx)UK_zJY`&Vdf}L|fm!Cw>wQ=r#n{RA5mIzO^*J^6} zn;fSf#Ib-~-5@?z(Pq^_OxLIXe+DrcUEyi;!ZfNo^|ZEAasR*385wTeU)cE!d=_&+ zUMrc$cdh@bLhmv-ND2uPY93~-*zlCL_L#F{4%%lb_UTNFP2~wt zkp8_!NT0ZVm+B@M7GNh}%|T#_HrbdClpwB5NjWtrmHs(?P??)S(m4i>wtrbk!~0h? z4}+W=m4b5*U^PH6c${M}xv^(OG1Ixy5Wqo*%aRqfm6HEQ-Ist>RdxNJdjOdQ1QkR; zL>#~=N6taza&b0iOLGKqp3Nr5i(*=7$u(`gZ z4UzwE?Q$lfld+h{VVK0_H$)Id$g-z+2RyWN~tDAP4 zR(BAzy39m0xuI!xLtvv&04xSAK^kjzxuPs%I8i&zZkmH;H*GRByWL!{u7YU_rwJHb zr-8epfw^&4a^t?@W7&xT+_Gu-O%fR)GGC$h5ZB32Pw;bcu93zS#wdmpw7D>*U1U39 zmSn(ED;u-$#(XR@q^-tQET`IgDlLpz+=T#(qJvgHDr}6HCRh?JuRiKGI%}! zMm=6-f+`giG4QOq>>MHo{Yvu|t~CcKvC zA|cvSu}+FbAnr((x!eX2{dv5Sy^6ob%2oqg3?0Q_N;O))cnlbcmA7^Ha)@OY7`*9n zCHc{WGcfyyrg7DonCI(fn({Q+)d1fLD5NANyk#x*wy#^(wD7!6mO^;uZ3^%5lz$#8 zH4vY@X=O=FZ?6hX`kuK|NpI0tB`^owPM7!+Lw=>W9gt(9S2U-Um)OJT|uUgVM238+#46sZFvRX*q<K;wG|XW5y0|5^KMVWznEf>HEHpvQ_tVa^F(csS z@Y>m!JqAB|^&I*uoj%}8JpIgH&U0fQHMp0C}co9)Ofup7js{v>?9=F=5VL0Wb+qIS1nU z&REr(hU1;#Ct8S$ECpt7ynr1p&hiEjpzk&%$hq2R{gOVt7&Ful1*$Ohf54J}7CHGF zKr*%YE#^tXGTQMQ?DMflumTAsQc^`stB~XSuFwzo<>3d#LmsPVjzKvWp5Mq)NxLgz zhO`8W#3-(~M8!{PtJ6TpwJX~r?{Rcf?Y|T=@mC2vQqSg_>I45aMA!c$vtgi z#V>^NHD^dM1o~}?LxdR|A^G+Qrkh&$F%IF!Q~YIY{K?rzV=u>q zn?;l9l>m^1#9@EsdK^9qsu(k=Gnh%)R{#~xG&y4cK+1Hr51WgyAKw->&-6VeHBk3N z*@r!WuqWw{%h(1Xw>DrZ; zZcQr^Ay!UQrw# zjP^pK8&cvQF+B_)(5rvM1bU6>D0qDN`AQl_$Nq?klidPIu8fKEdRLP~AK^R)SED8d3+na za1$<8+<&J12yOPU6ix?>n=M-lBm6CeI0&SW7hBAp3KuCcS1Vf5$42Y3$T}5zQ{Lgo zQ(YFzZ?%Qx2o8mWF$0UX%*lsf4BgcDqM)0b+ny0=oYK?y4wghnqsT{k+u$v|#cm+B z(eNs4GP;6^8Iy8#Dvny=WMC?cU}D!%Q8bFw!O415h^Qb-K|+w_77W}Fu3~a>KMr4! zG+nzUCmiBpS4^3&Jx^VvU8g;%U8gVAt~1Qqb!Mu#MpVpNtG$@LPP@)YUM3Qn`=a(d zkLYj{MRmW3LVdYIwalc!w_=Q=Fj@-%#!`giodC-*WE~FvT^JEy85@3?{)6YYGq22WD{TZB zlWVBjyi5snGdIS=5&fZYARa!}9t;OIUsEP}RIu^J4mAG{G{K;R0(+9HBST^jXZ)L>93snxdhscaVBW7}^NwOn1d~B&Hk(4A#Pfj9E2qD1h({t&K7e z-jBnNGTZ{L_Tcu!WlW2iV4S20aoLz{M?*yN$>yYJ!cx!Z>yt-M; zT3&s?xhhQKdk9_Cqlou|mRDxtK9N^u(t)~p6*LifWt#N7rXtR2`pQ`u+O$RV6=oKh z>`;=gQ~PO}Hr5?dv#6c{4d1s#ZtEqw%81C5IC5N*ZQeYWp0?GpTx$~m!b}OnsGVJ# z7}Hu=cAzQOm74T#iu{wbked~;iqLa#UU$6WEE^&4d)*i zSXas`X{;@mWIdPZb#s}FTnd>wzSrh9C5Yo9a*4czT=M&YIJPli@M%g;+Tec+-r z?jtC(OhfN;k>EFADBSdknB?;{X=vT@{uCr_TE#v7zDCW7h-0P)+)#)(QHXk9`lHz2 z(JeQnmmx$e$s5$u9R*rTE8Ug0LGTt_kl(n~R z@`$LlHev@mw-(g-Aj)>IsooDG^?n##w;v9H%c4Gcroe`RI^z&$BH|RIK5I~)zV+$2 zm!iVQV3n6L5@wady_GOSDJ}F?VjB(vWw|v=3|$YqJFZTCc6?O?9rIS=++*>HU-^-H zeI+*NIW(hvg$Hy(g|iJ+a5qz5@$cibTN95TgXevMTn*sTw|M^VG<_>}lUKpSrYgS_ zKlacf!Bn`Yz9qv;>v!9`9YE41e8M~gG>TdJ zUVQo(+zRdq0>t}IG|aRU?~lFuaY1?`5HCwQ=;TKuTd{Q zB@`oYf}axY){w_6J;=_DE=6^*$R4*7WyiU>lC!0q>}n;1)VU=p`hR3+ZAvY_BF_&oRbQMQD&(m zTijf57K=f;G}m1kbuGfzaupUV_K?SlaE$QSFmvUt>QQAB?g#mNk$R#ohUV1MU+G|Y znCAK`ow4V3hrbf-@{14XiH7?t!413NmInT9xT@bZh^4lnHFd6w2D>+J5IvAcg-yElo3TZM;spy~VwoRHWG$LjIPh$%gw zfeErydZ3>e%^l@^n^J}&e$1!k4V4y}FO9H_RlQQa_Fqr?8!96VN664f36{I=qR>W4 z6S@5^QgJo4(p$eE8j_a`*kmDD3bz=nMz-8R?-i_LWrK`@n5@Md2ALL8e9iaW%jl&> zO52{Y#jsv8w4Va6H~+@E#_sJsEiN-!+;H-BS_j-B_M@!^CYyp8{X}eZY60xxjQ6WC zzp8GeL>ge*g%ZvVIG=$vd)kg1xa@q7<=$3P1_BM2E19cm|WwtIMLpN#%jyOcDQ}MnOs}yM%K>ZoyH|F~s(@euCU0klP`CJ_u(H z$Z;|g^IOgq4l_Bno^>)W@#nX*aG1#lU06h?L2n_hNhjfmwMX-J@5|KZeVO{aFH@iQW$N?3Ol{uR(>0GLeQh5gIarC~7S?Bdb;)&?yCnqu zhgqLSu6VZZr+mG#+&DHD7f^Pjg@2tj>PxdGa)kM}M+k4Gg->oI!e_27Zf=PLk{rR|XWt=w zj6?ckI*IiAa`@?3zi}*4_%MeIW<-b#RF05bHv=(m?BBw&3Mw374hAv2I$v_N?&oHDIGD|KqeiFD~TZgIgP|aI!zvd`;fL7YAL}?aNt9|c|!*+`xm=ZBFMxR#LX2uV}DkTNRnFZ*k z@TTo8$IJw%?=V@W6vc>!X_TcCH zOI7*7#;W&l4Euf9b4!xS}X4QIxML1vzu zh^;VO)Hl<6+m zcRu!+>{*e@AZNbsyO!Q-ql|6=x?#^m%p0w1P(>^jZ5I=0yoZ{S-(Sh@8l@~UV3S^Y zv~m^sx>_DwLp$3kxo$JU#3IxMI@Uo6U}a=#dqtJ^80koRC6uqfwpRx7HM)b+i?6dg zC{5g@1{O~D)u-u&4#0`8u%>)j)<0?z`L2U9*C!V~FD`oG5C>?Try}Oaj!KW9iYa@H zRbO1K&aRfc&dmg9i(EYCCi*&$_I6apIg5a<4=6oCM8G%%8ho~TRJG)N?o&8uh+I5Z z3!M0X(%(D_8RR>81J<}^Ovn8+yXRza?hCA&*YV=Y4h8CEJYskMaLv6-#z=9m z;i_Tc-UH#iGp6F6uZ2!t=8Um+f%=Ji_7dfl!5Q$i5T53S+lA>R?zMzC13jUP{&r!y zihC`cfg+5SP8{xec-qjxuNHc}lhV#3Pm%&fXM9ROcT&ds;M|PfRf&O*TFF!`^ zOS5X`if?5!l%Js4BsK{S)-1E?!I1#pvq`WEcFT&5pP&*5Rwz_^YI;A! zV{D-fsopo(e1iQtuw8zXvqW3ED7(9?Mnd^`$^ElZ+_U1hUd9S>uQ}*iS`)@K<0;&0 z-qBiG=((=SxMq5-Tvj6?n5JMnpqWt92yHx6lS?-x!n_gVm9_Urg~!b>OM6r{9Gsdf zD;VcvLAO=53;>Bu1X5u-!1t|DSvR}N7NLUd;ETsU8;gB}%728)mx3p-K1{24Kdw0K z>8AYrz!fBh_NaM+k$1V z%))4JGO$$)xV$91KZy4*cds(V=- zy!yG}Df;CZCD=V!s$%K%#|w1Ws5HqQ)k|?Uc-(@Lw;>{VX$d;*g_*usG5JTFQXKj= zzJ88hE`E;5UVO4nvX8uw&B+?vCnD_Q_|2iDI3>)<&6Z%G2?;jDhqm}d;OCg&5G_GB zy_`9;GEQks!%)mUV-ggD`(bQ-{tteiQ$al1Z3cf|Pu_i$`Js>F^?LkL@k6p{di688 z`um>{<+LRmWS8vseUNM@;&jEYt(NR3Way_X9Hh*5T929AZ>^&nlgER~Esu@Z&YX_l z_D!NwoqFJ_=!5=)(PRVgB@w^T9KxY)s~)RUw+nP>kgX)o3{l3w4O77oWt`k*8VylF zEq;L-t?kyry*5<2;r`}}SLj3h4w2trwCZT>(@(>co9+|w`f>c`XrJ8Zfx&3-=SQHy z8{&0a{37skEYy%ibqbY3h7mRWIFkDj`(gisANp~)=tq1H;B%13P7^8Hw)qtmxzZj#S} z=nx9*7?tV15f*DaQ$0%IZy5rqJXSg9z6JYvv+zr&q({(3eY6xrWk%rjO#Bk@bIf?% z0+F$8s9#@WH`Lw#z$O(xL~;{pI=u$CQ#;cCg^!=$cLYDjRL{<@lj=ij^pQRmVHe^D zpN5k#(w%JyijnSz53TVF!_P6nfm(vLA^A30Ce=^~kM#GzGrq#_6S|ay+Qa+iB-=<| zh}X~HXT}f7LNN8RtOP`23dxvPr`a3UCQD^gl_|2zJUZN8DKQ)(%M|4I;B*X3YxW1z zF)(GXd9-SfG7nwM-}d}treg4DkIiF!@ayrs*8ModW)@h(87Nb3;&%l<$0CHzty6?& zY2{2?&j-#?T6CJa0Om_h(pyDXEM|WhTQIAfGDx`nt(ZDA-fGkB7eZDQVWmSENAu<= zExlI(J($LHhK^!sRwC_~qr}R?Q|XsEN(Z@%5Bbbhnsf_nBJ`3y@~~Xv48`KFnt7`c zYO}iLtr~7<#_wkY)1=7Al~ofBD~dJ ztY*|lCXXW%du-3L#VwWOc}jvi)@--5JBG=v{t)E|lF@#7Z# z5i98YxJ!TBL;Lx0pZ<7&zMQW#m)EbN%k!0i5ASXR(}Yw_PsGA~2S1zf9D#+r-;LIS zN~3iO-c1%(K)PuHCNJ?kV|*jfvb#RO13(MghUcdud@E>%9;J;7lt{QjFuKv91xirV zq%>GNLj!Zn4YTD92vyAp3;R7>s`h!Ql5vNpx$0(q>>@a;BT5=sOg_ZpZTG zAFw5oZ4aIlN~ts{CB!lVE;x#UHUCxsn`t$E5uhVw`~`^3WnHFmQD8$e1 zB{bwwK!kZT^HIfQ)@t)HN^ZA}x(jMkI^`NQ!JanWhh+Xly7YWy^{8p5P{MNnqdK&f zQNtZjMljk;f-)jJ&)J4H(`?YX;G9<5(a&MBfctQuO?E^BU<7w;UOg=Zs50;BXr@YPQtw*yLDM9kV4YX#F(oQe_KBVAOyPf;;_t$7Q ziZ4=F&_bkOK?+V{k195p5W;UkLt`1cXcuh4V)2}8ux#3(Q-Z5Bis=oO)i5dnHGtNN znAVc6Q6je0iEo0QIy0$gmc?x*T%%*~fUzO*8f}N!0s0}&G^UGS7LOuxThE@RpBE~P z>sMF%rhfyJc`-xHq= zZ)unPT3}F(cfe|x&VgXM+XddPeIB3G%KgQjPrJ%dD{0B&P<>ycFCJGW!B;gdgBt&l ze7pV8zf-Qz{6j(Q==~>@j(*lw7>JmZ@Id6oK=>z=HvQdTDT|iOt=)Lu2t6T&MYP1* zJ}_?zv6M^LTZ&;JgJ@1;s$p{o!-U4eBK}#L_oUK1bkt%<aaEa<+!xP`L=2-^m?!<)1gb7h0EqqD|3!d>swZ^Y?Vom%)5G(xj2GhQ$ zl!OQ1w_!9>SncNc*HFsQD5V&zI)x_Kq8$yQu*FJbw|)p9NDWk`P5U%TD;Nh#gLA2V zlR#-ukl9mO)E88LiDIJn7b^qYb!u`E?}mmy*g=Sm-#$l6fZ_|{^o{Dd&O&GZ&<0wu z1Pf=F11(X8%5R$K;u2+|yxB}cmMZ=H;H^s2&4*>U!2e}fHod+SygKTA`fRE4qI>}J zt!0WyK4_#}e9bme=`t+G;XSV5bYq#~OF#YO;wE=Rg3FarUeEx-G?9l-pCH=5Txry^ z^kyZop)VV38KEPC)YJu-H=UYK5ly-J0 zH`P)OIE<82kfJS>dPwEPw4MQmVzR7I`gpQ7QrrG{gNCnA8V9`W5TWp@9^q(h1g-Gj zXc3-ph;Y~z;g#A5S`BbO1m`fqA;QbH2v2bY|F)MBT!k;3@+kI&<6g%XPD!$df-bDW z2K=gm&QcY<5v>H89e1JxKBKP?K(Bojo4V~4>VCFw*&xggSQSh*YQ0%pnR zZ7)y5VQ8EHq^^Aeb>fFzvWw4|ch)jrjm$YMj_*?^zPWDcPdXL=3D^oC67ZI~*_FOd z=FPBb&KVX$PwNgwl3$78QfbI3tTyBnIXN#b#_o4>l=8$T?-LJSR|MHE?KW7INuf~+CI!d$vVd$d-~vMWsVdCzIbp9$3wNPuE0)IR`0kV}`B(ygxD2R3GxOSPqAYd01QFQ0 zfzj$;kG*5~N5#QyRsV(nO-{a1VUodo?vns%R7XiVF%rKkPW~tSZ@%~(jLR>j`{TU_ zGMlw122xxk>KAG}H4d&Yk~Z|Nij$>uw=C1@>evk91mDeX%9o?64xy5`hljp8QzEvFUlDWNV%TiHZ@Cp{Zd z$p&R$=spA#%c9KmQl09IzSq{!kTfg}%&MU0(v+>vpuaR~Yf&QHGZVivRy_#Pr0tur zhH!cf&9f-Up8BH5noqIpB|f~jCi}95O^7P{VWY%?eFaG4JC^`R^D%O)6}d|QlT%Ta=tHpA|uu$Y=`R$i7reVTI~P2Mj- z@wjj)wSP&;kl&d?Kfa`dI)8bQ&moA9YMLELN*9Ctc3&Fu4`r3SsW08yqP#=KElP|$ zM!cL%WrWFgOZzWp`)I*G?URk*jSW6}_1^vn#yyotdi_hNPuiW~RGPO{=_?6vM%TCbI!!r5}*q4`erL4H0NfHs+?s~UojL^0R@QB9=@{gkzk zAf;(FhLsqVr9TV<|xtxmv}WVqR4uWXeO`nwKD7qffXv{Py5lG|U|T}AtM zDiIA4cTRVNL)>|BQu_IWU;^+NwjJtqBr!cgOJZiUlwOKYrAUUen;rpnj3_gsjp?Nk z0qNz@4byq&RVi3DXDz-*=-+pFr}yTgp0Pmdqwem=k}|80@_>3S0_Vg+6mMO**0{E%p_e>-4uV z%M+cIpWvz#{3cnk_cW)d)R0qr%4zW#NYj!cSEba+U@h~6& z?#Aj-@l6!^9K`);i2Gkr=v=48#gNoza$S}4-6y19jGLIw=?RKK_X>)EU_1}9C_%hZ z#4AI*a>P4}c;^tWG-3j}8}S6$*mXDJl_qGEs*{UZr>77^2-WBXt>s8>8hzQ(CDR=W z@E0<=V?I|Ce0}PW&O0mVv)8d`+Ibau>`|IGX>Du%Z7BKeq!iBOm@nIv!(SUex&Fux z`^+$*%3-pcBC^K?cISpQ!}N&N;Bp+Y>^CaG6p(QD5I&R_;F1Y;@; zn4uI)!NQb;Nvwu#JOsA6zk#B$(Slu=G3){69@&Ss?NmINqrOwAaa70g!5p=N#!(%I z0CUv3L!d54Wsb=lRm8L7xHgW;6!(`o>iU$sb5vJb$K8XY-qhQ&^qw5mT)JJVG4Awk zEsZK~ZA?GcF&;zPE&W_)_w;gjHYy(}S<9pQ<9UGK4?Ij*tjz8#rI(MycWxY1p2dvz z-iY`C2;VTh9F;HE8>jB~5PT0cYXQJN%Fn@%7Lb1Vukkr?yEUX=emXv<&5l~6Uv7u= z&+dX(3qPYZ+J%w6r$G8;T_6ga+!^Vgn}Pc_0QrOPJLlwi!t>_3=i*?&I-s*OYJj`Z z+Ggf#0DZF*z=@tcFfjdm_8?KaSsk?6G50(>9Y|2G-K-8;?dEhhrl0K)kbb^1|J8M_FbEw^9)b2r1J1F?&}9 zY;!w91VC7_Q!2{LR00|>?6*fjZ~lH)6x7>BR;Ms1?05$FVGWCN%B`eXFncPE=npyo z%{W37(2Rg6ju6BKQS- z3SY*wBjVM5=aD4R$&J(#;((}S8EWZP3$_ChR@6AYs(6dBDzVv=P?!5m%$C+} zhqOw8{uuckhG90hl0eS6;u@HK7dTD(GL@iuB}KiJ3)cT{P&%S6H2PC0tz$2b8jM~^ zFJvfQG^4Aw z$RYth6+hd%R=DqlUst<#&2g{b*U|1>2=2S!$D6#up!KF#_QPD|=wtNtex;LhY$fce zzkdfayyvk4J6kcu9>)Tc2}V0?7upDLz;@b&A88etgdn2QN)2I6CKJ{j>!#; zwBlXmIXUYZdE_V~ zLbID;o!h15r`&c(U%5$c>i|>4*^-~aC{XwSi^V*kyJRif2YV&4?UN7k#(|bavgM)c zbSp<$A%D7vr}b;x=qw-~tQzV3dzc+}I7clHDWUb&^4kcCI;1pdA9k)9OADA?!VuF5 z`Z~56YWZ_D#ljE|t^}(JM?+zlGC52-ni%T5lQtew`Z_(j=n9>TjSeO2A;m2By2wq} zns&agG`Va0f%n3Lrv7fiT@ z?~UmP6in`+2kKHz4RRGl>)WGK{-kfW0KVJ$mK^#v!O2o_g*N6Yed`M`c3#sZ%|A>f zxyn3wpkhG zj}`YYDAn27{IhQwZg)1ntG+@NCzQaB@I_-SUFVcjw!tZMH*^|)lrq)-k!ld3F zUi&Q3*a=mff-3%3oEVuu5?0Xrc$z(;EciIMaD=>6Np?82v+F+%a9lsP=rG!B3zL! zI3x6MC}7!8$W17qXJBEaZ0)KXR_(Hk`$REIZ&g<}fs5wg^lE^iYI8_>wK+7s8fYzl z*AV3>I{JUKAZEQJoQVL&sO{{|Tx+e#xY-53Ms3ScTUV$%YMXBry32&_>Vxh=H=qUg z#=>7h9J(_V-MJRs>F=_*co5bAuntoxS_Wy0meKMs*J;wBf2~O!6D-@)1Q;kdy^PaA zYu-o8ng82;c;7AOey5f**EZeQzu0ttOUs${z9?%I0yr3|H64g=Ht6C$noqRez373V zX^VSQ4B%QHW_CpJx75s5v3t{mSx|bN4E1q+?^+qNeuEd0ze4GC@~9#7{`bc`99zk; zyReaW-fE?h$60o$wiJ41?b&@*37((CGY$U<)916D?tHNU@hZYh%3j>FnS|^7V zy@+K-zAiFW6))AW`56ysR7$hSp}TP{e3I8OCx`aIy%CG4F1Vi09-Dsg$hh?U17J6~ z;Nr;%Ii>3ouppZNxs!mU$-axrBl;~aK7<+Z$@sQdVj8TROC6$|&z2C;kbWNE{d{A| z+7eoPn4P_ivv%Gpz$_yFltjOsQi9Brusi6O2VRcD%ac&Qp29SPcU)i|)ze)HaFk}z zPifMuaKl*m03QeD=B4@mPWBRhzYCFJAvQy5sMfYXra8Q~)8eI>z7cZU{PmF0M7@24qDlKuxGz@wgcPdD2*ooTw>H3pet?m@q4lie# z^o5a5cPR83Jq`Op37Ow)AlkTqZ45@DjWPGMZ{w}-F`^-Z9tedU2XFIAM+2O!!q|Q? z+mqzCtz%#D+-{iI900HyS~n%l4LF>IMz~nKz|PLMinp$TqT~Dqqjf#R7^lnjZtM&7 z3>)kpFd_}~78dj-Nm9(E!978Q8=%nkH&}~iW3g^NGQgIdkDD3OKW!Z^polgHV%aIB ze*`5Jpa{)R10A`c^vAnv7EpI8^%yQS;C;a$B#NAw#>zzQZo>UybF>4NnY$OvMv3Md zt@-}())Q>a5e>@!4kaCD$|*gF1=UHWoU&{zs^<1yT)qhFs@*~PMaCeg;Rh(^BKj#y zpr%j6A}MzzPF)S41!+oPbRb~YcD%Juo*kgF+}9?w+O;}atIycZ1sK?WhSS7C4+95d zddV&0| z;J4cW2n!sea&Oi=EldL;c6rRM%>=xeGZDa(1B%RXg`g6JfnZ@?E-D3Fmk(T5kZJ(P$6cnY)OIk7j__VXn$LUzxx|2EdBKgL-5&J^>3>1F1resG~V`d zJrAjS*&eMoZwJs=ZY)E0{&x{{`93X!J7QL(FEHz!keAsGwEhbohyMGb{I5xJvpovF z6E^4$TDg1k)wbTB;gltJuAKR-p++?~IB@~B}jq63~}4$o*rXCsyT%y6W3idScbHH zbNF5Wuu=$+0&mk*#Q-TTtTVw#{_u1)v5sUZ>~WL!F*r#K#Tgc(>{y!FItW_9^WbqS zp#o*TEqvV}5c6+7ZG^9E9rz*keX=@e_9W~~fjVeC)IsZ^4)T(`)*XtL^5$Z{-50D5 z3d3Y-tz<1sm8|EX=@uK+*+nkzI84Ca?~9k9{s9YG3ptT$2D%B37ZabkvEW&$?w0up z#`NbEDSbn{A^ifd?el(;wYl&qp}FO0&T5;02;oJuY0mA~^yeu?%0U%kUI^<-Oel zXkCbD?BA}6;4QT!kk941e4fTO31|hD&n5QqdG4RI=chu8F|ENpeg^WgJCiFFR3r{coylv;SIU&3|iUbL}e2V)7$* zh{;x?G5gkfu@3u1FP0^n|9eWN^61f6it#B{6AK+I(=O$8XY8KM@=-o#0dNz zqOm=X5w)L9 zHS8@44JE&5on4+<>-eBB-I#NU%xkDX=to3As4he+aH*lXs4cYzRsWq0=LYU=sd?ZLo< zSPiQ~2X|V8u%F!C2@E9v*TBFdH|_`qeuw@*fB_`?XJFv5d=&q000X_c-kZ_?e*pvW zsLZ{Ux%2s#zFID#M1p_V1TiJW2v!LQU?n#(zyc`2(@8>?svojG_*hoYVt)aYzo&w znI2)Veva*s=SNG{FW?CALN=``P@>E}cvo%kI>)+LUK+TD8Fm5eVPQjWH6R@OmSWZa zXIo)P3_VIAl<~!bfJh@?G;jd(uyvd!r-yAg`;1WHV95ZMuSH0w3_t|7JeKkeuz%wf z@`H>!>t*l~LkaA5u$*ANG`MZGSWd8CLMXMm%7ksj7B3Xs{WC^Rb8oxlCe8j0JWwE5mx+K-1%tgJBP;H{q?JpH~)LH7TIvCp-S zH7Qu2>BgBJy_>$mmc~>E2>$7h4#VwFAQz8}I?5c-1lxVE9)=6BoolTtN9qGRF>@4g zScRWzGv#ntPrzupA0^4Ro&FM3FxOqQ08#%P>j^&qqdMXuqfnB7TzDaf7lC*IsEAgq zR_dAO{>_cB`F}$r#Gq2PMqs?u7i$dM%i2ngy`c`)7g*8pcUkIiCii6@V_R!5@58k7 z!0md6-ha}Je;0l-v(3@{s^eooM|W<<+gq_#bAEf}N}<^H(kf`S-meMJos=LfwnR&a zF2o2f(q?Viq6ySW82$II;4r=KG5Yic2M4W+rc`m^ncqEd)T{j64o6)B@3Y5I&-3?t z;HWbk{vJ4LIgjeQC{-T*PtAHmnr*#dDz7Ah-HnC51dZb30CQ;T8%krdjpsVB+!FBX zscf!szbFTd{uebK!u-z615XSV3>y0d@>29#sjl(Rc5&(9(Ay%Mh=UJl9Z^oqd=2H4?$R_KqH@r9h{8bQA&d)s zP#B@`FguhQC`SZ@#zO?;QtK$kuGC;xdN?PxUPLQ!Ye552if${tiw4Bze+i2?nYKlo zhs;^Guj07rHMp-;oCIwV=QdPx@-|d+X>j4K+dz%^ub>(a5V=4#;~Y>8G8^}bj%x7j z&Zy>&poW(=H4Wj(E1>qc`$IKz07wL?iPKRHGW}Cj<1oV3e$S(87*_0{5WK53tDPc= zDg3Ue1_iK3HJ@Yo@$W=6o8V9TFD(81&!8GYrECJ7kvTi7xEHF4W`6oNLc5Xw8yexd zT_gP8L^blCG~@qyRP$K}F^~_ls=6b_KElu&`f> zvFUGEePec5%+ZjDhA;#kt%F2ZRx=Vo!gUZ!ssplN*{|zwL^y$DfNw=SfNc~=$o`@6 zW(_Kd1Q6hF%GeRvT%U6{WWy6EM`%-|*UnaIM`Xje?XMskblY8#%{cwoC_tM$Qx~`| zgZDiD%-fO8M|utZ3bLUd6>vLpZ8FWPP}(~$zKktmMyoO&=V-rbRR+m7=FnNI66LlF ztD5=Uv9;=^RSEQpWuosaRRy#Ea^oLL$L61$z?(Q26P*As+JY(gHcY`2Fa^gV=9%2S zN{er^H~yi#Y>=((sQpc4iQ6s42mO#>MFozYdx?|ppg+kMzo)Y|vHNJ%57eYeiN|Th zXfvDY8`SmQ|NvtPz`=cMcz&XJei4^xOCq5Ym7!@VJ+W|Hd$HM~@h|F5hxi;hcIH)(_LE_kE zI_#l_Bxgz~(U!MRn`63%%5e5j`M#5=4JX97I1#4TQnOx`6nJhFnU6%~2C3VMC6@_K zTQjBB4JLf+{;TZ)8-}A%Tw)SKI1N>?d~6G;eA%6NVAOHjRNt- zbAE66S-v@YndYPM^LfwXV@)kdXx&r2*rlD6VbtA(f7egjA}ZqSRdKewIjacy6(heC z#Q)eK{0W3-({Z@L^GwG<^ibS}W~dYC4^OpcZL@YnvnIM|%{m#)I@uY`+WijA+F5H> z12=0Jnl-|%SvzRWI(Rd^;H3t&7R?&ZL{i(VY2h4d5* zcBsno+N#vl{4zy4WZOp1mK*Nn3ACiXYI1pY!WF6@zcuYUP>Oeh*7Bnh zsELmn?J<8aCz+R+>rF#_)b^2^LctrBXNgnF5<6Pnyk$GgH{k}K2Ea)Un?O5#)DATV zO?jt$tqh}IeAFoSZpbCy6}oqdf5Ib}+WM*qZm^n^Ed7REpN1Ru z`>KPr?_v1fVM5b3Wb{)bv{xQ@W#(6#@JfqvZ73b~vqi}t3ObpH?>!o*5uPH+6L?iJ ziRK{!J>NiWsl|F{D81J}9jra<7)tg1Z4c{*(qudYh{$Ikzj%>K<(B1>mT`m22OWL zRzG;l(&;+AaDyS8oATl~ifX9Ni^hpt*sdIHasKHNt<=vrSjl6oi$)A$JOO`UJX3B% z^*?goY4maY%3pLv)2g;9*qb7~jE0Izc%M3)y z_m`|6@d)j;DPq48SF)pd~Lh*KSd&Jl#-A4QVf=JcvBC;^`UNnoTd>k5iszzg@)-Xd@l z8b7(dm-kS+V(k?~nf-aNI@6#8cC&zj4gOYJ*gF6TtS5Z}L zLE;Yk`4O5IqV{!LiuYW4+CIB!Kz3e;dfp%pc!UmzsU5oP?Ev?maJdQIX&R4XzdVgu ztKrsW^-*uj&Xw2o^J+9F*_`A9kKiPL7kB*H%9D8$24m)w+`%-m8Kh;yN9cuS>U;9G z$uuxr9oX434IKvmdd7%hd@&}{*Z(TyggsGons|k_ zJoFh;W+Z2^N<`yj&t|RRV;4iDjb+O>m*^UzT@9;CPiqlX^hoAHrvUe{di*lY zcj`Yot4l-8%$zV74M8biFT=g)SBP|OoVKH=Qx~D*-MoZlD zRYpXA+)F^X(z1FMmcDUaY8o$(2`HiG?PDWrWOkEoY7>JTHj%n@S53_ikLO4(BEfyQ zcN|P3M$*gOfpfZzB##(%tlVb;O^Z=ix>hhNZPS-7#$ZsSPoVmW+T3JB0==ah?|k$X z4jID_rOTAQce1QR>1KAWTe`VDZqMwe5%j2{w)3fwkht(7i)#M65A9dfRZfYh?w(GK zy0(Xe&yzkhSPDGNSz!*TM%Yr-8}r2x^pdJ3X~o^$hi<80xT5T7;vtyk#;TpPH%s+5 z$MD8YgqhX{{+K&AYC;WrsO_~tBl^(59%{VyVC+L1d#Ih{L*wbA9%@hRW%EAd(Nle( zLrocHcdA?S`LVax{FmW0tEW0pj{cS2=?M(le>`pMrFLzd$E-N#E68OW8>NHAitxQ2 z_G2rP$JTGX)M#_GWp~}6c@9AZ3e$!|pBpShF?TvDl?+NryyxLxN9Y-bcYOkK_PF|+#6M#2?Az7yV4&KM? zmRYeESheFo*aZwAPDX-M!FewSdo-jcOlntGG+#^0(LBn+Lv0}+OQ6dplv*6loelsm zJwm1g^=Yjv3*q=M0cE)`mTo1e;r?P?1b@9<^8rM8r^kn5=*vE8q!xN`0!{3V>U=(y zR`pf~_*YEFqyTHzT}$=Q{~SZV^j4qs6fIJSI=Cg!qkRAh)`;{QhfFeBcSug_mIC+l zvEBALO|Z|Y#6*AeK~7W0QfOZ_$iHF=LQk}-qHuh6T$ZT*t&kgB5Z8*ju5@#OT&h*!hwty`|wv zNQO*PN=Hi@%rG4#!{iOkWHJ{}DY`q`wItVtezY z{^s$TH#y?XV6CfPGXi4{rTs&JG20APTjS(Q%LaZoNPD*&@38a5vcyOkL)D>tJJm?H zhT8DsFb*51gQuwt>xBuxdqW!@&?A z8%>1>PzzJPjU#mgD6;Hfnmj^{Z=A`4_Y8)e4W?$t0ZMhCc?nIs(8UpIJ=5qDHoUqx z>vMQ>MHg1sdgMminjT5x9=X}|_VGIV!R&4$)g=b`=);sXN>$BZb!p5^JA7V?Pr>T) z!pGOLx@I~)wWkYPyl}*`0pcX)bj7uR_+Ih+wRj;mKzzrD8X(RaL^~f+;SVm>a^nPj z{SX@Ly+QQHLu!Vc@G!mpu-eOzOJ^Qd$Kl-N_|fV(+2vu{IvOx|FEEB9!-^YJ%dpl9 zhUMxkT(Jxw?=fn3UUYVh+Ol^#!sq8=@_qz>_z)m`r8&Jip`LJg$diuvJCw0(U~L)SWPFwQh}v6z zZWO)#i2A6Z9tDk6Z`$y&HL7l>S3&eM!~Sk0@Nom+1YAWMw9;_Y%z-py9B|ZcBeP!` zr_MFtpho8jYKr&i0kwHPrX6wjLzvp2TblHbRst;_$M!l?49FN)?Eu9{{ z9W5V2LbYfa3@2~O$Ac+iBGB^g0ofBLs`U+Wz(|@mNo{0)@ej;voNzQjt^qTHWm!c4 zf3H{R?;wHL={~;;!X!6NGF;k$^{j$io<%IlTAiZtMM;O+%Ra5c7wbT65MmzqqULWh z)kQQu7&J{96yn#E(PcLjdNbQQ0ny@MOKYKz(YmX(l$YHxQQhL&Do>gdW!VAFew^{M zv7_ZxsK)I_1E*o^N0+AqnU14AGt{nz9<+3Z8e!;0+i>ykW!WaVoRhGLLv#kLI=a(; zW~hUl_qKr_=oT~8Pvpp9ba5uQ#Eo~U`7E_t^G+SnBQ88T-7Q1ky>uHTZ|zGULx%1@LuYN0Xo2|Bx7xtz0v(+K;gub+5w%XVEb@wrImW;QjL2f{g`vhFg01I4mYF3lI44dwL;8f3eYUg zeX-FqK(cZIe4q}z33OQiNyaM32rryBi|RM?!em#>(-@b@8J{425#kpkekwFbsW`)f z<4;BW-H4y4$A20IlaYv@0w1e|Krm(rnv|Z?XxO7_fYWH;h1do?+c^!w&Fls}L+GtX z)%8K|B5pQ*$PZGsmn9qu#c*Rw%Vj!NtTy&b>|IM3#f^>D9%LEk8c6?Kq&AhMhLpWX zReXk4<^!;NP9(i>0F*Vqn zx3oJ>`E@cbb}rubwOMkWodmyzB39gZ#i_B>^(bOU#-^4eG+lT~l+YuDFTF&~8cE%2 zn|mpa^e|+c?skP8j^OA+8*weQCoan&a1$&tSdVfyrL?kme&~LQPJ^J99#m=D<7)4& zcQjGh!D%vVEsNhM66En`|Q9c)W(LPdEqD~t2tg@g7{E+ z=Es71po7dpPZiGQ{mYOTaYk!>Fghb2W(37IA+JI(Rz8<9md|_g32XG-*tr(9Z-rd=JC- zN%ee#>9-)U(^mKPwrreryTlGRL1Jram}i#(h;u(o={J~uU8c4%n8G%rh9=U|c{RU@ynpJ~=5?8Cf)HFr) zq@}CXNW-(VW3}3WmZhlAxW3jJ)lO+llb%-FWOrGq_Ar>wL(~`etjId6U(0aK$1`Vi zhVNmu&fg2gy}!8sRowfD`=9K>|6mvXTk)RH0(Z$ch5HmHptiA=aF3L)UBhd7+zsQs zm&FsPP1NWqBQ;1>`#4u{b;hNtZiYUY16Ovn3|Kt#-PQ)T&z@a2O!)YH17KwRN*Bws zc<*L#|LoIc{l)wJc>m?fhL%tD_v!HOdI0Ze?`k#EnX8{Y{%LiF!Teo+t=j+5ucvUe zRXdOG^=f}1?zL)vChoOre{2{2L%Z8Z79 zv~va1+Mc!Q+s^4IE+syr#yIcgyH}o3TWEJ5KBIOC;CF5-8(Xw%1B(dl^{o1j9((Ym zG^MenWX7}@e9d%21J+wS?cHa`4?9&3kG>gbkb!7CZq$~BdY?VpqrZ5+j~gogS+#Lj zv~8ql+ZOoj34UZt(w3Yp363%w?alo`ZJ$#E&A*G)GiN~?SNUG2rAy*HPRYjeMcX}K z&N*;Opci#or@n0X7k#l#9Wfq&H`1~LtnZ!Bnl2O> zz1Kg?E2HOURQ!LlSDtqxD(8MhcHZ;;&nZx?=vV zwZ%sc-#^p7XWH80u*3J`_%7O_1No)e+TzQ8x3xu{tu4qQfh|bDu`N7$(r0PvM){xp zvL{+p*XBHzlY%Fo!ekq|V<)^`MehSk7|OUAR}ehGk!OU4>;zgXO-;$GtA5M7+F z3$9z34K2j?OzEj8O94(eOm+Ca7T-m+uBz1hpX#IXhThpP{S)(4!%*7&vKrC57Z*-| z-=P{oVK5aq`DNrKaGUu+M!961;d}AkJ>xU+p3jqT$@mrb({dP`U_Hk9QLJWB%1!40 zoRcB>j{2&W5M)d;U3 z)L3XxM#@%dwhha(PbE;dZECj$fADl4=Vlc|$Uw-;vR+z1E4D#R{kw^_^7Y{aI=oF) z8yuIJjBgX9?Cf3Y;~u?cK7BhDE#NsRu;|%iwz-nFhIn~L z-P!T$U1`>SH9j^o5p%%pm;(k!!FNyRcq^L;@LX~`6SJ|kMSBk?go5_s1?@5LUfY#Q z_N#5WXNDieBohW01qrxfofup6El!Eoac~EeQ(_IHjm4g^a^(44sqX=`vmf$K!gQa5 zvTpr)PkQcv8YOq`O79#{TNz<1!e$0L!OKm}T3cTI_I8NklkV^HcqhGV6PI3LfWbe9UdMll5plp2!+3!``NinQHsc zOg-MUR4h+NC)82I`NdITrrN2E1QjW#EtVW%>}Rj6v+D5+x+hp0P|ts<5dn{f>O50d zRh;RP2dn+Qj7m&IC-NN3zstw>UjjO3MOq zZ|_B~XQ}Nwrs;157egJzIuaiui8}h(G6j0(K3K__=4TlKDBz&l!tf(02h~^{7ytM{ zwX^(i7s@!OnhbB!g@fuO`SD&fMSe@>nwLYrfQ5?^PRNGe;R~?kqM`N zS4+5S%GawMzCVNSl>e(CK)&9YqTUAV9>*wpC>YS&YP;@16RwjKg_)n^Zg~_Znmd7f zlChc_COMtkfzyfEt0Gk8X}hIx%bB6LN7&txJDoygS(-rdJL*#TXc(E_QG?``6Y1r5 z)NTQVIIZ3U&C8FkX(QmO35;;rF9Ct_%FcA_9rae^-Uz>zsY- zUDZXlt(t18fyW}L!68t2`b_F|NDYb2W6tnORxL-_!DHBNMFkusvqp31q#ahuJvgot zy>v*8G>ZgQBLN0WH7k+dw-Bp+21E{rQmV2IOxC~+xxsCwYp21yd8~_XqczhtzQ-I^ z3x`ScN*IHQI0ptR;kJ8BsE=XdEZ!gLF<9&uEx;_AJyD96m|3s11(-cp;n_7W8jEj( zyp`?f6Dg&kWpoxj@xJ=Vz=|YSSFIGDu60Vd)xLyI{e*FyD4~<sGl!wxUr+Hz)RBOWn~$j74es>C5jEOy3l8aVxk8ag)y{^#^vF>)+B=LB zTN{t5sww?3Ey351sx1wV(-%k82>IPux_nd}+h7OQobw|fkalVM=T~EC;xQ1T5Q z^$v|X!lq5|Ca7ENdDHu7Uglfj6-KL}0*Cuvm8?!TaHZkL)zB6q{U4Bifjwarw{}cl z=rw#dv#uC6m~7m0n1|Bm$JM9gU0+fC(`q+bmaBG@AL&T@bJY*D^*Gl36yTh@<_EHu ze5f`sm=js))1tK{$t~sU$-Xt5MPUAEL4vd7NmIHA&N9~F`$T-_1uIUlGlVB!*-oo9 z?wfJCnP?TX(t{51h9REB94n!*?UT$Mp?}lruVT z-9qV^kJN*8D>!dI4g6UB*6{yWdlR^v*4Lo^dJeZMpJ-e=Q(^?%=& z&xg-*@12=5XU?2+=FFKhGoO)ZpSe4(rl(Q+%+Chc`gF-=OmFK8(WAw2aS=i6?UAo8 zbSbFeN|%Wdu5@|ZE&W}j>vZYV(m|KDct*Q1(k1da)*!cXLsYn|*%7?m`ED8dBLi=@ zElq8A#eQ?cW*?im*JnI)A8Jue^|0(a@yP%suKS~2pRcigd!4>s;9r-99DsRQ(dX%B zY3u=WbI;*EhL2{Ku8Sbs0kdcD1-EtG>1lNNfVq`t#cRkP|Gl}Z5DB7wZ_YQ4qqEJ*)7g$LO6raD_=Q`ce` z4s5DoY{Q_1P|!(pYfsx?^hB4F=8frFkLs%S8IEx-6P}B8l`I6xjq$g0F9vywG9LE9 zSF2=`@LLM?`q`XjOr{ThHpka}1yyic?L%z3gMCqswSKldgWWI6-}J-J=I9tmY>INf zNDK3to#kSeebI~pPnpw#*2Bfc^tny55b4QN=5LKxDd4oZJ^TwNRo7`nHCL=|hoBUT zGRSPjL)(6FOTUivSZ*GxDxuUZ{UXwNUv@}QIqB|c^Yg|}=-D&o!9tk!?c^DAsNP%! z2FO1(H-Q?S<;^vCD)s)MxwfWibI&EaHTR3N=2Bxd*4!4f+x+Hv^9#m}^uu|yIYayQLaDiB;ByBaQY>Gbs-<*VNefHO79k*+ z&Xrjv$us)r-Xr3p`Z$cw3nawp%!k43uT5Ps^kcXw( zrL}?GrooZsxX|2r1gp^Mmur5i9yL&|V^@4+%3F~!r!FK;c^JJl!X-;Qx ziE4;gSPAVm$ej>Rw#sP4`czpUo>6tUQOs0xCj3jz(MGYA@L?*gH;Ti;s--wsNsqYR z7)usG>>(_TrFnwbOPCf*_t@{SSnA;+b`xHTr4kP@KOiU8!92fk6VICADbDf`y2V%z z_=wTfghO?#*J_I0yo9%-C_7wyAhg79gjgg5MA3~1krSh)k~-g=7&jtyV({G}Q)`RU zh24=97Ack_p+5?l<+pF1gCKm)P^=PUXCUSeAjt2LVwOGgnt#dsRZK!HdNoR{CqyLB ztSE6r*sSy?2LuU@R0(shHen{yO}JQ_X4M5@zK2z$OVuyL95>dm zXz`klurJ&yB#P_3g~%}LrUv3Ue<3c!I9mwlk~y_L;{lrdF|_k|s%atopju$?AHoGo+;qH{UoS(OQ%K^U~oE}#xr zB#E;NsKeRi{1ZC6H2s&HuWvThq8HkTl0cC(w~aU^tOlB=s~??bw$-4Nwjjy!8Z?dl z&a6S#*zbrM)V>`^lUsw9wiEM(b~UWtPm0k<i6(;tOJSfN;adI;fx6-%t3+%X)MO zBhF$JDTUS57P1(l8wRQ6&*l(qV3@e2=+`7m#+W5jwu{*zd$VTP^tMQB3*WBvjEO(3)Dc@B^otbPZaAX7BjBQLr&&2XY-LfHj`~>=5*I` zD&@4Kq;6;=at!u+l!}ptTeNwi*i5X*&W%>G@1LKt3l5?kDX`G-o`ux|Q*OHQ8={%# zC&OXYx}7!+bVLMTVLj!2ag%WPAzgl7d@Y$Hb$Kk9L5qP0QpKh-4OHC$mAe>CVAE?B zwqc^W>x@3t7d^z<2&OVepv0&&Tf`b}r1Bku!JHj-jWvyB;~I+xorX;o%WCj=LFR9X zga2cAC3#N~n+P}j$UH@SRt+ZXR7o@0$Af;fYl>(Qd>@i9RZOpeeo23%ipmFi6*4%;B%k6=ZFV{<9}I?&JnvAGY)uy$-yax zEwvRB=6(-Ov-m>X(Cfjt)uITODjm|+$IyyZGxRTOFA^Ji#o9g^?|PMbcR*us2tek9^0mBPEVxT0OU31W!|tlIJE`uG8L>=Ejw#MARq+&zTp-|t)9@@vSF*ZVw=ENm9v&6> z?P%9>u?>HywnAJky!0oPtPqo7`Wd{Gi6d`P6qXG~!z#)1&s@o$b3%AriP6`v(j&;I zetT@XfOL=#}tq z6P(g_>*;DG?nqMc7os%?AU!!46{IJPTq!o}`3ZCe>v6pdt4D7b3zE4oJ8b2p`Qi44 zJ(?bY^xF1@@gN)4NHpx>O7Rnqmr%j{B5^^2t^e?B-20tb#lR07nO$|YxB5J2bavIR zebi@qX_eSoWr~kRfGM1H;oT4yrr5qpd?SE&hK>_SUy7dzFp=jKiBa_Tmtsb3UMZ_^ z04n4aqcZkO&#V>~sl{`B)F#v2)#6yS?z3;XXl(2f^LMEmqgq&^X4xG=-v5QCbKdR9 z>!ja{O`oayU1#(Ux0}K!`76<182yJe<14X=(YKuG$&Q&-bB&3iLed{JsaV{fY-3WB z1Yo*e=2FwLAxDynf1v92bm(QF^foR1T6`^`xDWc_B3%6-LvcTljg=N~-|arGR(bBTe_Z5PAo zvyI{uVQVF&Z4%{rykP0D|5=be+$8=j^ur*uS!@<)QKloi>#)|L5;Wq&8n-?DwunhS zdx7{~LyEP<7Ev||zuu$~Tg7t$-`rHG$#ncaGA#_QOJlZ)HLDdH3L=%Ch5|6{{~|8d zc#}456Wi)Q$Y;CQF*#LPjtqI4O)-v*RtsE5s|ng@HFmprR%m>adhHM!*Mu5NQo1wH zE<%#;a_*(w1k~~9Gw0yxU zr>?eY^zuHjwQ%|_E!-!DMgEAQoHKJ=IrH#cI)rrJ{aQLz>=Q%fOs$1wIbQJL!B+G) zRFTQ>Q7JStw(M7x;ye2`i+uw`{*9&K+Xs}jUkr(yf}}rke3jeC>O28WtfC?N#YiEh zil*T=Izp@JkDR*7ZG=)g=dD=!c z`^7LUnEi(29y{!{)OrMijgP4%$eDbor8=is_#-qcx=X!42VvP=PLJBfZsl}B6w&JM z#qj7tI~q}sGym2RVVoC0cS&j57A8tp~*zV+ox- zD8?IClJN&IJxhs2enxhUP9M0vPj!2L-|c-I4gEpYcXfO3K37*nzz&(4DN)^Dm{wZ<8I z%!0ALbXc6>nVzdnwhLZ$XjK!N)@b$}-wO%Tx(_DZ%(M$d&wsvx`2aCSLy>So4x7p_1Jp|t!XJG#_8X}**DDI7PDOj20;nIJ9LLl zo4pCcZ_^k-%JAC%YbB{Mkk;BK#KA^kz^~RxKZ(^mll4Z-9ptbHpmA-cgQ`uCr+N%9 zrYQ3p#M`q^Kz4no=c99w$VX?F?4h->tnvYdRh^jngjl*pP0ol7MXcS&*k^K!fwuwg zFt7_vi_?{w?YMzmnA`DD13T^-%{wD*^Q*+^1#C8EQy0-joE7^w&|BmI6rBu+LeobM z10ol#;uAaDz@S*N)vxR8w?zYWi2SCC*gs_`h*mDVLUVV(p}>;(2*UTJFFz;#t{z^1 zsa*AfqchIX(({=2_}r!w=f(Eb`eJgzc1jI8Ln)>Be(4tVD#dKhbQLa5%&LkFhMG#d zSI9f(5zt{};x>EvzfaS-GR)&f-y-jFF(D1Cld4n1yUV(d1=_RgMj$6Q!t|rSWF%OiqrnUN0Bx7=v}>`8*YiT0>4# zZazwS{dcbQtq!0(3~Rh4U#yIz;9MZb$TyyKg} z~{uD0@o<0yZb$++5oI2bS(=1D2xn$?MaA2VU z??$YCnPStGsfgX^$!xzak8_rdPwp+WS6IP*SG0^n4diV_iR(7@NLp*AIG$+F=5C z$G!DmpQB#Yq{eXaEOvBE0dw-;9UX(9qIBhbER3ULigUX^+A(v_(Sd5xUZL+fn&mHj zpgMVm107u#0G(n}g^MmwojgIeqGG8yucmMH2Io}LA7D~*W||o9Q^+<9cj-kZCP8jk zDwmtal`SAQ)unJ}Pe@R~(Fz*{2TDym2cv-`^{*2_xq;Hts&{4|b{!*4$oYjX2TB%U z>{&{zAvFl}R#v?1Zn_RStJn1P2VPOMpoVls-PqaLM$>|%#30)hWSEaNfOgmv_B7n( zg?UXwo1+teZ>rJ;0Cg)G-BxH?>#8eq)PYI4$n0fmJUl6co;zR9v$}y*3#~ejHUHHe zVxng)CFy0F^bkj@oY662el6?Vn$l~=8hl?UQyBSh(G(x1;1IMg^$N8Ok<7tsom@0b zVe~y?ofRTkyoAux)}s+poTuP_itf~r4hScIw(hDcZ8K)AEw7}-7=sMoMsdaP3j!3G zO^>-3MmdXeeU}s8Xo{id&nnL4eKK23#J;K!>+u+Ak#B6VyOMYrV#Qqoa6|Nil9*jz z+A5@!Svx07`5vAF&g)8|)(JY)0E`IdiVGvcxe}w4F_z9uSFYle05KU(pq`I1;=LcO z=7!R0%?Y%#t3yK=+4!m%30ayG$Uj}W+K?D$!3i`DJoFKs-Gw9PN3D^Fqj-`j+$fS7 zNjn6;AL&6OX_Vi!<7)avRo#BlSPJ&DF-;MK+UblS)uWS*r443?exV-e(+Zu_vS2aRcXN-^fhJONI(i{o+4elwA$CB~&VWD*X=98nA651=6trS(W4qt@WdMcdP5aotK`13Tkxs;$* zU)`;GU$^Qnp!$m+;(Rr&`hjPtvbmJ(Ve8YAqBEp~Bs{dM8Vx)yqV7Hh&*=;wwwtaW zLmsP$+aXkK&(NR@DNL3WyU)H|oGy>kX1 zqY*8nhUlCElQOG|Yv)wLacT#I;mi)G3mt7C?PQcmSGu7P4wTb6Ctc~>g^F5A4H;$9 zl{PF9N9AA$fdL~ZSxznlLd(rk zLR*B^>`45V~wM9S>lpf5T&$m!;PE)!F_E9ltUI-TCFY~ z85o^=>&(zlx!(!zUD)DLUDgo|l}h#jm!^XuAgQgD8+do_i1OZGh%V@io+?9hI7K}y z(oir2s{AL0NIbdxi%OlxHU-bZtLhVPMW zegSn~>c0OoEp08OB98q~YbhxK2yhVv1598?Y@noFMA6~w6zEepl`#_{Dju_(4nd!0vr$S*xKT|Vcud%ck>}U31 z+9*)D%-&((svAL@Ddp@vDwcC6LdX^?(v8zEG=44XM;OaGIu2qcrnQ~F3@@77-jz{HLZ2(rWS|hP(MWnXxg7ri%1+t$24fBMnrvA zdI#Vg6&ILXvxQT=Q&8`D`eSON`U$ah6cd(Y%hB=KrHz!EgY~$v9Q$bZ(E&QzLu#n{ zQ#Q9J@1D|2o)%?Udu#umQlimkmoLiBh@jaoNpcI$K?U(jSyOJ?6z75CIBQQ7R;Amek#FktZgbTI8~crHM@3_-q19_H7cMRwb^klD7r-)QMiq$*30et)H! zZqRIB1JWt82X+z<*-wLdOFcY3G~A@`dP@l&@8jY3-qJ6sqoB=Gm`!NGzj=NP%~Tgh zLA>2j&}oqn(%7J__cUY0aA+G37H3xOhF1TjSp5H`Sm0=8liYH1# z$clBo?t4TPjwqPcc~CKIfMU-~#Ta~;im@nvKFMZFnI%j>W9}PP#@siqbcWHz8OBH_ z7*K0EjLU$5bN-}0E$mgNITsu4R18|sJxqN1KDv`Hoe;Y2qeFe9xdG|>H1izpyfdnS zFtx9=Lb(5(wMjoI%~Pn@OZl%z&DB-7TJ12YcJ842!JN`2ZAO6T>{?`dMJf>1?xoIy zq~}d(>Y6FmK1MG~e@h$Is8~SdL^mFi+*le!P9GF1Aw3kW-V@8~^ z*E;G|$;;?b(Pub~e@!|S{I`>bh2>nm$2w$))ZWu?-nVK?B2?eQiD6P*qlYbTINceJ zP!L=GXi9riYQ-N0y(t|M?(Mdk-;(MJKyd)p8$~v*0mXq>V!h&1W92VVLHrv~v`!c) zeQp#U?6Ri3BRy|Kfxft~NiUFxc)5!)UMtJOz3l}SjgpK;A$J!o9W7M_+D1X?W+LPc zCdY|MwDMi4sZetloqJd6CN!<0y}hMGA-Rff^p>utrYcvnT!f(TF+xzRddqYnfN7Je zoMgouLSTE05InBfcmJ1Sst}CZNzr4aC*o6;Wvno^|7n6}GZm@>71)7!Ow>iaC|W#L z>RP*?x>6=$#t(ahh01$k&|wb8p=&9yKnm+{3#z^}9$o<`>T=jPWf&;S;YntLX(@Bi z;N0Rtth%N+Gz5EqOiLJwHNrwugXH|btGgcTI zr0h!KWNn>wxp$}aIO!*22!)TAq(GbDb`;;MRleJ(yi0lGrO4EZY_x#g$#xO{aHWQ3 zG6xU7xwq*1Z)o{=DMM)UJ)IkmxlJ+aoei0&9q1V&pskbeTSrBmX^%XHI-2DPpn?0z zJVC-iZTf*|7h9-p^4d>BCPS3wUPPQu8X>91UL|7P%4&f}ZvIec~p-IySi zG<)IC3O*)4YjTvH14>!Y)>>p!p~==<)0*&F0J0iHbkQS@0;!HSHR|hIou2}8X?rDY z(WVmbOEIl_?0D~pW{j}9q?uF}Mb^E@l&kf!3tNYmqr<@{fYacMICO?AggZ6HiBtnB|c zVfyWBRhVAi|L?+d*@Ei+gD_=&rwWs@%}JPwS>gX7OdY2~n8e2j(_I=mrp zY3DvCVQR)|{|~}6ZSOw_)408=F!fvUs4(Tae}gdf#5Yx#_HR{%>G*9|VLB-PzZ0gs zt**j!s`n$p1W{LosZa4g3sVFsA4Qk5;Nq=VaRCQWr~_)yGja9bqfHcKZb#qHS(q50LY4fgfS zDun2-EgPO$wbNi&myK!EW0bkgO_}p{boolSQu(9_2pF%v@FZ+;188 z#j{<(eWBrXMgGCJD(?;bobz5GQ{=oMP~@+=e*^Cgz&Dlme%!3`UTLMB_jq@m6dkk!vqCp>3sO2;}*X7(2p`TO{F=e=gA%2|

^ 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

hoL4{%~Db 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 z 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»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 m-qvLg;r{r)6PEoLgCAq? Date: Fri, 19 Sep 2025 17:36:33 -0400 Subject: [PATCH 088/159] ICBM: disable hysteresis (#1260) * ICBM: disable hysteresis * notes --- .../car/intelligent_cruise_button_management/controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py index 0b0957b828..7ee7f3ea64 100644 --- a/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py +++ b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py @@ -16,7 +16,7 @@ State = custom.IntelligentCruiseButtonManagement.IntelligentCruiseButtonManageme SendButtonState = custom.IntelligentCruiseButtonManagement.SendButtonState ALLOWED_SPEED_THRESHOLD = 1.8 # m/s, ~4 MPH -HYST_GAP = 0.75 +HYST_GAP = 0.0 # currently disabled; TODO-SP: might need to be brand-specific INACTIVE_TIMER = 0.4 From ddf63701e8d4cd16045efe5638ca089ac9dc608c Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Fri, 19 Sep 2025 18:32:20 -0400 Subject: [PATCH 089/159] Speed Limit: Resolver (#1256) * init * some fixes * move * more * old navd helpers * bring back cereal * fix linting * more * add to cereal first * sp events * lint * implement in long plan * fixme-sp * refactor state machine * wrong state * start refactor controller * some type hints * init these * enable debug print * ui? ui! * print them out * fix spinner import * fix path * let's use gps chips directly for now * service missing * publish events * no nav for now * need to sub * no car state speed yet * missed event * Car: `CarStateSP` * fix tests * bring back car state speed limit * fix * use old controller for now * fix * fix source * type hints * none for now * formatting * more * create directory if does not exist * mypy my bt * policy param catch exceptions * handle all params with exceptions * more * single method * define types in init * rename * simpler op enabled check * more mypy stuff * rename * no need for brake pressed * don't reset if gas pressed * type hint all * type hint all * back to upstream * in another pr * no longer need data type * qlog * slc in another pr * use horizontal accuracy * use horizontal accuracy * set core affinity for all realtime processes * unused * sort * unused * type hint and slight cleanup * from old implementation * use directly * combine pm * slight more cleanup * type hints * even more type hint * Revert "slc in another pr" This reverts commit 3a6987e6 * Revert "in another pr" This reverts commit a29bccff12b9ed9d64efe7a5722bf614214002c4. * rebump * no need to check alive * use it directly * fix test * refactor * use gps data directly * quote...? * lint * fix tests * use CC.longActive * user confirm in another PR * rename * fix import * params fix * no more * fix * drop new state machine for now * more fixes * internalize output * unused * rearrange * auto draft * rename * this * no * no need * use existing * wrong cruise speed * fix * not used for now * Revert "not used for now" This reverts commit f0083d6241380e84ed259c402941fa2c78e03fdf. * some * use frames instead * split speed limit resolver out of slc * no need to pass sm * fix params * test init * use frame instead of time * track session * some tests * too limiting * bump * always reset state * end session if long_active but slc inactive at any given time * off * no warning in this PR * no speed factor engage type yet * wide open * no * introduce disabled, no longer transitions at inactive * fix tests * no more tempinactive * clean * rename * offset default > off * new tests, fixes controller * more tests * not really needed yet * lint * fix * some more tests * wrap * more * more * use vCruiseCluster for set speed * init better * finish it up * no * typo * one method state machine * refactor preactive timeout check * refactor new session check * directly return statuses * comments * v_target * refactor speed limit resolver * turn off debug * more resolver refactor * no longer needed * lint * more lint * fix * move around * fix events * update event * already happens while in enabled * add carstateSP * less * Speed Limit Control -> Speed Limit Assist * in another PR * more rename * overriding state * fix * make sure to return the correct type * just slr in this one * more * update * redundant * fix * fix * lint * fix * fix * match toggle * fix priority checks * fix combined source for picking 0 limit * no need to wrap * add speed limit offset to resolver * add speed limit offset * make sure it displays distance when higher * Revert "make sure it displays distance when higher" This reverts commit 15c6834d4e68e2ba8f717c9442ec8d4d269d2b83. * some rename * translations * unused for now * more * lint --------- Co-authored-by: nayan Co-authored-by: DevTekVE --- cereal/custom.capnp | 19 +++ common/params_keys.h | 5 + selfdrive/controls/plannerd.py | 6 +- .../test/longitudinal_maneuvers/plant.py | 8 +- selfdrive/ui/sunnypilot/SConscript | 2 + .../longitudinal/speed_limit/helpers.h | 35 ++++ .../speed_limit/speed_limit_policy.cc | 53 ++++++ .../speed_limit/speed_limit_policy.h | 55 +++++++ .../speed_limit/speed_limit_settings.cc | 112 +++++++++++++ .../speed_limit/speed_limit_settings.h | 53 ++++++ .../qt/offroad/settings/longitudinal_panel.cc | 29 ++++ .../qt/offroad/settings/longitudinal_panel.h | 3 + sunnypilot/mapd/live_map_data/debug.py | 11 +- .../controls/lib/longitudinal_planner.py | 13 ++ .../smart_cruise_control/vision_controller.py | 4 +- .../controls/lib/speed_limit/__init__.py | 8 + .../controls/lib/speed_limit/common.py | 21 +++ .../lib/speed_limit/speed_limit_resolver.py | 152 ++++++++++++++++++ .../lib/speed_limit/tests/__init__.py | 0 .../tests/test_speed_limit_resolver.py | 144 +++++++++++++++++ 20 files changed, 723 insertions(+), 10 deletions(-) create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.cc create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.h create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h create mode 100644 sunnypilot/selfdrive/controls/lib/speed_limit/__init__.py create mode 100644 sunnypilot/selfdrive/controls/lib/speed_limit/common.py create mode 100644 sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_resolver.py create mode 100644 sunnypilot/selfdrive/controls/lib/speed_limit/tests/__init__.py create mode 100644 sunnypilot/selfdrive/controls/lib/speed_limit/tests/test_speed_limit_resolver.py diff --git a/cereal/custom.capnp b/cereal/custom.capnp index c4b5464029..6527838097 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -145,6 +145,7 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { dec @0 :DynamicExperimentalControl; longitudinalPlanSource @1 :LongitudinalPlanSource; smartCruiseControl @2 :SmartCruiseControl; + speedLimit @3 :SpeedLimit; struct DynamicExperimentalControl { state @0 :DynamicExperimentalControlState; @@ -180,6 +181,23 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { } } + struct SpeedLimit { + resolver @0 :Resolver; + + struct Resolver { + speedLimit @0 :Float32; + distToSpeedLimit @1 :Float32; + source @2 :Source; + speedLimitOffset @3 :Float32; + } + + enum Source { + none @0; + car @1; + map @2; + } + } + enum LongitudinalPlanSource { cruise @0; sccVision @1; @@ -316,6 +334,7 @@ struct BackupManagerSP @0xf98d843bfd7004a3 { } struct CarStateSP @0xb86e6369214c01c8 { + speedLimit @0 :Float32; } struct LiveMapDataSP @0xf416ec09499d9d19 { diff --git a/common/params_keys.h b/common/params_keys.h index 80d12c6b95..a9408037a0 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -225,4 +225,9 @@ inline static std::unordered_map keys = { {"OsmStateTitle", {PERSISTENT, STRING}}, {"OsmWayTest", {PERSISTENT, STRING}}, {"RoadName", {CLEAR_ON_ONROAD_TRANSITION, STRING}}, + + // Speed Limit + {"SpeedLimitOffsetType", {PERSISTENT | BACKUP, INT, "0"}}, + {"SpeedLimitPolicy", {PERSISTENT | BACKUP, INT, "3"}}, + {"SpeedLimitValueOffset", {PERSISTENT | BACKUP, INT, "0"}}, }; diff --git a/selfdrive/controls/plannerd.py b/selfdrive/controls/plannerd.py index 60036c3082..8994fb7c08 100755 --- a/selfdrive/controls/plannerd.py +++ b/selfdrive/controls/plannerd.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 from cereal import car +from openpilot.common.gps import get_gps_location_service from openpilot.common.params import Params from openpilot.common.realtime import Priority, config_realtime_process from openpilot.common.swaglog import cloudlog @@ -16,10 +17,13 @@ def main(): CP = messaging.log_from_bytes(params.get("CarParams", block=True), car.CarParams) cloudlog.info("plannerd got CarParams: %s", CP.brand) + gps_location_service = get_gps_location_service(params) + ldw = LaneDepartureWarning() longitudinal_planner = LongitudinalPlanner(CP) pm = messaging.PubMaster(['longitudinalPlan', 'driverAssistance', 'longitudinalPlanSP']) - sm = messaging.SubMaster(['carControl', 'carState', 'controlsState', 'liveParameters', 'radarState', 'modelV2', 'selfdriveState'], + sm = messaging.SubMaster(['carControl', 'carState', 'controlsState', 'liveParameters', 'radarState', 'modelV2', 'selfdriveState', + 'liveMapDataSP', 'carStateSP', gps_location_service], poll='modelV2') while True: diff --git a/selfdrive/test/longitudinal_maneuvers/plant.py b/selfdrive/test/longitudinal_maneuvers/plant.py index b8c6adb436..e466472432 100755 --- a/selfdrive/test/longitudinal_maneuvers/plant.py +++ b/selfdrive/test/longitudinal_maneuvers/plant.py @@ -67,6 +67,9 @@ class Plant: lp = messaging.new_message('liveParameters') car_control = messaging.new_message('carControl') model = messaging.new_message('modelV2') + car_state_sp = messaging.new_message('carStateSP') + live_map_data_sp = messaging.new_message('liveMapDataSP') + gps_data = messaging.new_message('gpsLocation') a_lead = (v_lead - self.v_lead_prev)/self.ts self.v_lead_prev = v_lead @@ -133,7 +136,10 @@ class Plant: 'controlsState': control.controlsState, 'selfdriveState': ss.selfdriveState, 'liveParameters': lp.liveParameters, - 'modelV2': model.modelV2} + 'modelV2': model.modelV2, + 'carStateSP': car_state_sp.carStateSP, + 'liveMapDataSP': live_map_data_sp.liveMapDataSP, + 'gpsLocation': gps_data.gpsLocation} self.planner.update(sm) self.acceleration = self.planner.output_a_target self.speed = self.speed + self.acceleration * self.ts diff --git a/selfdrive/ui/sunnypilot/SConscript b/selfdrive/ui/sunnypilot/SConscript index 807bf02478..5c2680b299 100644 --- a/selfdrive/ui/sunnypilot/SConscript +++ b/selfdrive/ui/sunnypilot/SConscript @@ -54,6 +54,8 @@ lateral_panel_qt_src = [ longitudinal_panel_qt_src = [ "sunnypilot/qt/offroad/settings/longitudinal/custom_acc_increment.cc", + "sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.cc", + "sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc", ] network_src = [ diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h new file mode 100644 index 0000000000..84979a53af --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ +#pragma once + +enum class SpeedLimitOffsetType { + NONE, + FIXED, + PERCENT, +}; + +inline const QString SpeedLimitOffsetTypeTexts[]{ + QObject::tr("None"), + QObject::tr("Fixed"), + QObject::tr("Percent"), +}; + +enum class SpeedLimitSourcePolicy { + CAR_ONLY, + MAP_ONLY, + CAR_FIRST, + MAP_FIRST, + COMBINED, +}; + +inline const QString SpeedLimitSourcePolicyTexts[]{ + QObject::tr("Car\nOnly"), + QObject::tr("Map\nOnly"), + QObject::tr("Car\nFirst"), + QObject::tr("Map\nFirst"), + QObject::tr("Combined\nData") +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.cc new file mode 100644 index 0000000000..46f361a153 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.cc @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.h" + +SpeedLimitPolicy::SpeedLimitPolicy(QWidget *parent) : QWidget(parent) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(0, 0, 0, 0); + main_layout->setSpacing(0); + + // Back button + PanelBackButton *back = new PanelBackButton(tr("Back")); + connect(back, &QPushButton::clicked, [=]() { emit backPress(); }); + main_layout->addWidget(back, 0, Qt::AlignLeft); + + main_layout->addSpacing(10); + + ListWidgetSP *list = new ListWidgetSP(this); + + std::vector speed_limit_policy_texts{ + SpeedLimitSourcePolicyTexts[static_cast(SpeedLimitSourcePolicy::CAR_ONLY)], + SpeedLimitSourcePolicyTexts[static_cast(SpeedLimitSourcePolicy::MAP_ONLY)], + SpeedLimitSourcePolicyTexts[static_cast(SpeedLimitSourcePolicy::CAR_FIRST)], + SpeedLimitSourcePolicyTexts[static_cast(SpeedLimitSourcePolicy::MAP_FIRST)], + SpeedLimitSourcePolicyTexts[static_cast(SpeedLimitSourcePolicy::COMBINED)] + }; + speed_limit_policy = new ButtonParamControlSP( + "SpeedLimitPolicy", + tr("Speed Limit Source"), + "", + "", + speed_limit_policy_texts, + 250); + list->addItem(speed_limit_policy); + connect(speed_limit_policy, &ButtonParamControlSP::buttonClicked, this, &SpeedLimitPolicy::refresh); + + refresh(); + main_layout->addWidget(list); +}; + +void SpeedLimitPolicy::refresh() { + SpeedLimitSourcePolicy policy_param = static_cast(std::atoi(params.get("SpeedLimitPolicy").c_str())); + speed_limit_policy->setDescription(sourceDescription(policy_param)); +} + +void SpeedLimitPolicy::showEvent(QShowEvent *event) { + refresh(); + speed_limit_policy->showDescription(); +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.h new file mode 100644 index 0000000000..adeb115db9 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/ui.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" + +class SpeedLimitPolicy : public QWidget { + Q_OBJECT + +public: + explicit SpeedLimitPolicy(QWidget *parent = nullptr); + void refresh(); + void showEvent(QShowEvent *event) override; + +signals: + void backPress(); + +private: + Params params; + ButtonParamControlSP *speed_limit_policy; + + static QString sourceDescription(SpeedLimitSourcePolicy type = SpeedLimitSourcePolicy::CAR_ONLY) { + QString car_only = tr("⦿ Car Only: Use Speed Limit data only from Car"); + QString map_only = tr("⦿ Map Only: Use Speed Limit data only from OpenStreetMaps"); + QString car_first = tr("⦿ Car First: Use Speed Limit data from Car if available, else use from OpenStreetMaps"); + QString map_first = tr("⦿ Map First: Use Speed Limit data from OpenStreetMaps if available, else use from Car"); + QString combined = tr("⦿ Combined: Use combined Speed Limit data from Car & OpenStreetMaps"); + + if (type == SpeedLimitSourcePolicy::CAR_ONLY) { + car_only = "" + car_only + ""; + } else if (type == SpeedLimitSourcePolicy::MAP_ONLY) { + map_only = "" + map_only + ""; + } else if (type == SpeedLimitSourcePolicy::CAR_FIRST) { + car_first = "" + car_first + ""; + } else if (type == SpeedLimitSourcePolicy::MAP_FIRST) { + map_first = "" + map_first + ""; + } else { + combined = "" + combined + ""; + } + + return QString("%1
%2
%3
%4
%5") + .arg(car_only) + .arg(map_only) + .arg(car_first) + .arg(map_first) + .arg(combined); + } +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc new file mode 100644 index 0000000000..7508ea134c --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h" + +SpeedLimitSettings::SpeedLimitSettings(QWidget *parent) : QStackedWidget(parent) { + subPanelFrame = new QFrame(); + QVBoxLayout *subPanelLayout = new QVBoxLayout(subPanelFrame); + subPanelLayout->setContentsMargins(0, 0, 0, 0); + subPanelLayout->setSpacing(0); + + // Back button + PanelBackButton *back = new PanelBackButton(tr("Back")); + connect(back, &QPushButton::clicked, [=]() { emit backPress(); }); + subPanelLayout->addWidget(back, 0, Qt::AlignLeft); + + subPanelLayout->addSpacing(20); + + ListWidgetSP *list = new ListWidgetSP(this); + + auto *speedLimitBtnFrame = new QFrame(this); + auto *speedLimitBtnFrameLayout = new QGridLayout(); + speedLimitBtnFrame->setLayout(speedLimitBtnFrameLayout); + speedLimitBtnFrameLayout->setContentsMargins(0, 40, 0, 40); + speedLimitBtnFrameLayout->setSpacing(0); + + speedLimitPolicyScreen = new SpeedLimitPolicy(this); + + speedLimitSource = new PushButtonSP(tr("Customize Source")); + connect(speedLimitSource, &QPushButton::clicked, [&]() { + setCurrentWidget(speedLimitPolicyScreen); + speedLimitPolicyScreen->refresh(); + }); + connect(speedLimitPolicyScreen, &SpeedLimitPolicy::backPress, [&]() { + setCurrentWidget(subPanelFrame); + showEvent(new QShowEvent()); + }); + + speedLimitSource->setFixedWidth(720); + speedLimitBtnFrameLayout->addWidget(speedLimitSource, 0, 0, Qt::AlignLeft); + list->addItem(speedLimitBtnFrame); + + QFrame *offsetFrame = new QFrame(this); + QVBoxLayout *offsetLayout = new QVBoxLayout(offsetFrame); + + std::vector speed_limit_offset_texts{ + SpeedLimitOffsetTypeTexts[static_cast(SpeedLimitOffsetType::NONE)], + SpeedLimitOffsetTypeTexts[static_cast(SpeedLimitOffsetType::FIXED)], + SpeedLimitOffsetTypeTexts[static_cast(SpeedLimitOffsetType::PERCENT)] + }; + speed_limit_offset_settings = new ButtonParamControlSP( + "SpeedLimitOffsetType", + tr("Speed Limit Offset"), + "", + "", + speed_limit_offset_texts, + 500); + + offsetLayout->addWidget(speed_limit_offset_settings); + + speed_limit_offset = new OptionControlSP( + "SpeedLimitValueOffset", + "", + "", + "", + {-30, 30} + ); + offsetLayout->addWidget(speed_limit_offset); + + list->addItem(offsetFrame); + + connect(speed_limit_offset, &OptionControlSP::updateLabels, this, &SpeedLimitSettings::refresh); + connect(speed_limit_offset_settings, &ButtonParamControlSP::showDescriptionEvent, speed_limit_offset, &OptionControlSP::showDescription); + connect(speed_limit_offset_settings, &ButtonParamControlSP::buttonClicked, this, &SpeedLimitSettings::refresh); + + refresh(); + subPanelLayout->addWidget(list); + addWidget(subPanelFrame); + addWidget(speedLimitPolicyScreen); + setCurrentWidget(subPanelFrame); +} + +void SpeedLimitSettings::refresh() { + bool is_metric_param = params.getBool("IsMetric"); + SpeedLimitOffsetType offset_type_param = static_cast(std::atoi(params.get("SpeedLimitOffsetType").c_str())); + QString offsetLabel = QString::fromStdString(params.get("SpeedLimitValueOffset")); + + speed_limit_offset->setDescription(offsetDescription(offset_type_param)); + + if (offset_type_param == SpeedLimitOffsetType::PERCENT) { + offsetLabel += "%"; + } else if (offset_type_param == SpeedLimitOffsetType::FIXED) { + offsetLabel += QString(" %1").arg(is_metric_param ? "km/h" : "mph"); + } + + if (offset_type_param == SpeedLimitOffsetType::NONE) { + speed_limit_offset->setVisible(false); + } else { + speed_limit_offset->setVisible(true); + speed_limit_offset->setLabel(offsetLabel); + speed_limit_offset->showDescription(); + } +} + +void SpeedLimitSettings::showEvent(QShowEvent *event) { + refresh(); + speed_limit_offset->showDescription(); +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h new file mode 100644 index 0000000000..40ffead700 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/ui.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" + +class SpeedLimitSettings : public QStackedWidget { + Q_OBJECT + +public: + SpeedLimitSettings(QWidget *parent = nullptr); + void refresh(); + void showEvent(QShowEvent *event) override; + +signals: + void backPress(); + +private: + Params params; + QFrame *subPanelFrame; + PushButtonSP *speedLimitSource; + SpeedLimitPolicy *speedLimitPolicyScreen; + ButtonParamControlSP *speed_limit_offset_settings; + OptionControlSP *speed_limit_offset; + + static QString offsetDescription(SpeedLimitOffsetType type = SpeedLimitOffsetType::NONE) { + QString none_str = tr("⦿ None: No Offset"); + QString fixed_str = tr("⦿ Fixed: Adds a fixed offset [Speed Limit + Offset]"); + QString percent_str = tr("⦿ Percent: Adds a percent offset [Speed Limit + (Offset % Speed Limit)]"); + + if (type == SpeedLimitOffsetType::FIXED) { + fixed_str = "" + fixed_str + ""; + } else if (type == SpeedLimitOffsetType::PERCENT) { + percent_str = "" + percent_str + ""; + } else { + none_str = "" + none_str + ""; + } + + return QString("%1
%2
%3") + .arg(none_str) + .arg(fixed_str) + .arg(percent_str); + } +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc index df4a6077b5..205f64a0b2 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc @@ -8,6 +8,21 @@ #include "selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h" LongitudinalPanel::LongitudinalPanel(QWidget *parent) : QWidget(parent) { + setStyleSheet(R"( + #back_btn { + font-size: 50px; + margin: 0px; + padding: 15px; + border-width: 0; + border-radius: 30px; + color: #dddddd; + background-color: #393939; + } + #back_btn:pressed { + background-color: #4a4a4a; + } + )"); + main_layout = new QStackedLayout(this); ListWidget *list = new ListWidget(this, false); @@ -40,7 +55,21 @@ LongitudinalPanel::LongitudinalPanel(QWidget *parent) : QWidget(parent) { QObject::connect(uiState(), &UIState::offroadTransition, this, &LongitudinalPanel::refresh); + speedLimitSettings = new PushButtonSP(tr("Speed Limit"), 750, this); + connect(speedLimitSettings, &QPushButton::clicked, [&]() { + cruisePanelScroller->setLastScrollPosition(); + main_layout->setCurrentWidget(speedLimitScreen); + }); + list->addItem(speedLimitSettings); + + speedLimitScreen = new SpeedLimitSettings(this); + connect(speedLimitScreen, &SpeedLimitSettings::backPress, [=]() { + cruisePanelScroller->restoreScrollPosition(); + main_layout->setCurrentWidget(cruisePanelScreen); + }); + main_layout->addWidget(cruisePanelScreen); + main_layout->addWidget(speedLimitScreen); main_layout->setCurrentWidget(cruisePanelScreen); refresh(offroad); } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h index af89822595..8464150656 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h @@ -8,6 +8,7 @@ #pragma once #include "selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/custom_acc_increment.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" #include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" @@ -32,4 +33,6 @@ private: CustomAccIncrement *customAccIncrement = nullptr; ParamControl *SmartCruiseControlVision; ParamControl *intelligentCruiseButtonManagement = nullptr; + SpeedLimitSettings *speedLimitScreen; + PushButtonSP *speedLimitSettings; }; diff --git a/sunnypilot/mapd/live_map_data/debug.py b/sunnypilot/mapd/live_map_data/debug.py index da9f4d7771..794f2ef8ff 100644 --- a/sunnypilot/mapd/live_map_data/debug.py +++ b/sunnypilot/mapd/live_map_data/debug.py @@ -37,15 +37,14 @@ def live_map_data_sp_thread(): def live_map_data_sp_thread_debug(gps_location_service): - _sub_master = messaging.SubMaster(['carState', 'livePose', 'liveMapDataSP', 'longitudinalPlanSP', gps_location_service]) + _sub_master = messaging.SubMaster(['carState', 'livePose', 'liveMapDataSP', 'longitudinalPlanSP', 'carStateSP', gps_location_service]) _sub_master.update() v_ego = _sub_master['carState'].vEgo - long_spl = _sub_master['longitudinalPlanSP'].speedLimit - _policy = Policy.car_state_priority - _resolver = SpeedLimitResolver(_policy) - _speed_limit, _distance, _source = _resolver.resolve(v_ego, long_spl, _sub_master) - print(_speed_limit, _distance, _source, " <-> ", long_spl) + _resolver = SpeedLimitResolver() + _resolver.policy = Policy.car_state_priority + _resolver.update(v_ego, _sub_master) + print(_resolver.speed_limit, _resolver.distance, _resolver.source) def main(): diff --git a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py index f2358a2648..b4f4fe6d7c 100644 --- a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py +++ b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py @@ -9,6 +9,7 @@ from cereal import messaging, custom from opendbc.car import structs from openpilot.sunnypilot.selfdrive.controls.lib.dec.dec import DynamicExperimentalController from openpilot.sunnypilot.selfdrive.controls.lib.smart_cruise_control.smart_cruise_control import SmartCruiseControl +from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.speed_limit_resolver import SpeedLimitResolver from openpilot.sunnypilot.models.helpers import get_active_bundle DecState = custom.LongitudinalPlanSP.DynamicExperimentalControl.DynamicExperimentalControlState @@ -19,6 +20,7 @@ class LongitudinalPlannerSP: def __init__(self, CP: structs.CarParams, mpc): self.dec = DynamicExperimentalController(CP, mpc) self.scc = SmartCruiseControl() + self.resolver = SpeedLimitResolver() self.generation = int(model_bundle.generation) if (model_bundle := get_active_bundle()) else None self.source = Source.cruise @@ -36,6 +38,9 @@ class LongitudinalPlannerSP: def update_targets(self, sm: messaging.SubMaster, v_ego: float, a_ego: float, v_cruise: float) -> tuple[float, float]: self.scc.update(sm, v_ego, a_ego, v_cruise) + # Speed Limit Resolver + self.resolver.update(v_ego, sm) + targets = { Source.cruise: (v_cruise, a_ego), Source.sccVision: (self.scc.vision.output_v_target, self.scc.vision.output_a_target) @@ -75,4 +80,12 @@ class LongitudinalPlannerSP: sccVision.enabled = self.scc.vision.is_enabled sccVision.active = self.scc.vision.is_active + # Speed Limit + speedLimit = longitudinalPlanSP.speedLimit + resolver = speedLimit.resolver + resolver.speedLimit = float(self.resolver.speed_limit) + resolver.speedLimitOffset = float(self.resolver.speed_limit_offset) + resolver.distToSpeedLimit = float(self.resolver.distance) + resolver.source = self.resolver.source + pm.send('longitudinalPlanSP', plan_sp_send) diff --git a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/vision_controller.py b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/vision_controller.py index f12a00f23e..491b179039 100644 --- a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/vision_controller.py +++ b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/vision_controller.py @@ -102,7 +102,7 @@ class SmartCruiseControlVision: self.v_target = (_A_LAT_REG_MAX / max_curve) ** 0.5 def _update_state_machine(self) -> tuple[bool, bool]: - # ENABLED, ENTERING, TURNING, LEAVING + # ENABLED, ENTERING, TURNING, LEAVING, OVERRIDING if self.state != VisionState.disabled: # longitudinal and feature disable always have priority in a non-disabled state if not self.long_enabled or not self.enabled: @@ -163,7 +163,7 @@ class SmartCruiseControlVision: return enabled, active def _update_solution(self) -> float: - # DISABLED, ENABLED + # DISABLED, ENABLED, OVERRIDING if self.state not in ACTIVE_STATES: # when not overshooting, calculate v_turn as the speed at the prediction horizon when following # the smooth deceleration. diff --git a/sunnypilot/selfdrive/controls/lib/speed_limit/__init__.py b/sunnypilot/selfdrive/controls/lib/speed_limit/__init__.py new file mode 100644 index 0000000000..af14a87f0c --- /dev/null +++ b/sunnypilot/selfdrive/controls/lib/speed_limit/__init__.py @@ -0,0 +1,8 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" +LIMIT_ADAPT_ACC = -1. # m/s^2 Ideal acceleration for the adapting (braking) phase when approaching speed limits. +LIMIT_MAX_MAP_DATA_AGE = 10. # s Maximum time to hold to map data, then consider it invalid inside limits controllers. diff --git a/sunnypilot/selfdrive/controls/lib/speed_limit/common.py b/sunnypilot/selfdrive/controls/lib/speed_limit/common.py new file mode 100644 index 0000000000..7d219ac3bb --- /dev/null +++ b/sunnypilot/selfdrive/controls/lib/speed_limit/common.py @@ -0,0 +1,21 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" +from enum import IntEnum + + +class Policy(IntEnum): + car_state_only = 0 + map_data_only = 1 + car_state_priority = 2 + map_data_priority = 3 + combined = 4 + + +class OffsetType(IntEnum): + off = 0 + fixed = 1 + percentage = 2 diff --git a/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_resolver.py b/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_resolver.py new file mode 100644 index 0000000000..2a74a01d13 --- /dev/null +++ b/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_resolver.py @@ -0,0 +1,152 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" +import time + +import cereal.messaging as messaging +from cereal import custom +from openpilot.common.constants import CV +from openpilot.common.gps import get_gps_location_service +from openpilot.common.params import Params +from openpilot.common.realtime import DT_MDL +from openpilot.sunnypilot import PARAMS_UPDATE_PERIOD +from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit import LIMIT_MAX_MAP_DATA_AGE, LIMIT_ADAPT_ACC +from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.common import Policy, OffsetType + +SpeedLimitSource = custom.LongitudinalPlanSP.SpeedLimit.Source + +ALL_SOURCES = tuple(SpeedLimitSource.schema.enumerants.values()) + + +class SpeedLimitResolver: + limit_solutions: dict[custom.LongitudinalPlanSP.SpeedLimit.Source, float] + distance_solutions: dict[custom.LongitudinalPlanSP.SpeedLimit.Source, float] + v_ego: float + speed_limit: float + distance: float + source: custom.LongitudinalPlanSP.SpeedLimit.Source + speed_limit_offset: float + + def __init__(self): + self.params = Params() + self.frame = -1 + + self._gps_location_service = get_gps_location_service(self.params) + self.limit_solutions = {} # Store for speed limit solutions from different sources + self.distance_solutions = {} # Store for distance to current speed limit start for different sources + + self.policy = self.params.get("SpeedLimitPolicy", return_default=True) + self._policy_to_sources_map = { + Policy.car_state_only: [SpeedLimitSource.car], + Policy.map_data_only: [SpeedLimitSource.map], + Policy.car_state_priority: [SpeedLimitSource.car, SpeedLimitSource.map], + Policy.map_data_priority: [SpeedLimitSource.map, SpeedLimitSource.car], + Policy.combined: [SpeedLimitSource.car, SpeedLimitSource.map], + } + self.source = SpeedLimitSource.none + for source in ALL_SOURCES: + self._reset_limit_sources(source) + + self.is_metric = self.params.get_bool("IsMetric") + self.offset_type = self.params.get("SpeedLimitOffsetType", return_default=True) + self.offset_value = self.params.get("SpeedLimitValueOffset", return_default=True) + + def update_params(self): + if self.frame % int(PARAMS_UPDATE_PERIOD / DT_MDL) == 0: + self.policy = self.params.get("SpeedLimitPolicy", return_default=True) + self.is_metric = self.params.get_bool("IsMetric") + self.offset_type = self.params.get("SpeedLimitOffsetType", return_default=True) + self.offset_value = self.params.get("SpeedLimitValueOffset", return_default=True) + + def _get_speed_limit_offset(self) -> float: + if self.offset_type == OffsetType.off: + return 0 + elif self.offset_type == OffsetType.fixed: + return float(self.offset_value * (CV.KPH_TO_MS if self.is_metric else CV.MPH_TO_MS)) + elif self.offset_type == OffsetType.percentage: + return float(self.offset_value * 0.01 * self.speed_limit) + else: + raise NotImplementedError("Offset not supported") + + def _reset_limit_sources(self, source: custom.LongitudinalPlanSP.SpeedLimit.Source) -> None: + self.limit_solutions[source] = 0. + self.distance_solutions[source] = 0. + + def _get_from_car_state(self, sm: messaging.SubMaster) -> None: + self._reset_limit_sources(SpeedLimitSource.car) + self.limit_solutions[SpeedLimitSource.car] = sm['carStateSP'].speedLimit + self.distance_solutions[SpeedLimitSource.car] = 0. + + def _get_from_map_data(self, sm: messaging.SubMaster) -> None: + self._reset_limit_sources(SpeedLimitSource.map) + self._process_map_data(sm) + + def _process_map_data(self, sm: messaging.SubMaster) -> None: + gps_data = sm[self._gps_location_service] + map_data = sm['liveMapDataSP'] + + gps_fix_age = time.monotonic() - gps_data.unixTimestampMillis * 1e-3 + if gps_fix_age > LIMIT_MAX_MAP_DATA_AGE: + return + + speed_limit = map_data.speedLimit if map_data.speedLimitValid else 0. + next_speed_limit = map_data.speedLimitAhead if map_data.speedLimitAheadValid else 0. + + self._calculate_map_data_limits(sm, speed_limit, next_speed_limit) + + def _calculate_map_data_limits(self, sm: messaging.SubMaster, speed_limit: float, next_speed_limit: float) -> None: + gps_data = sm[self._gps_location_service] + map_data = sm['liveMapDataSP'] + + distance_since_fix = self.v_ego * (time.monotonic() - gps_data.unixTimestampMillis * 1e-3) + distance_to_speed_limit_ahead = max(0., map_data.speedLimitAheadDistance - distance_since_fix) + + self.limit_solutions[SpeedLimitSource.map] = speed_limit + self.distance_solutions[SpeedLimitSource.map] = 0. + + if 0. < next_speed_limit < self.v_ego: + adapt_time = (next_speed_limit - self.v_ego) / LIMIT_ADAPT_ACC + adapt_distance = self.v_ego * adapt_time + 0.5 * LIMIT_ADAPT_ACC * adapt_time ** 2 + + if distance_to_speed_limit_ahead <= adapt_distance: + self.limit_solutions[SpeedLimitSource.map] = next_speed_limit + self.distance_solutions[SpeedLimitSource.map] = distance_to_speed_limit_ahead + + def _get_source_solution_according_to_policy(self) -> custom.LongitudinalPlanSP.SpeedLimit.Source: + sources_for_policy = self._policy_to_sources_map[self.policy] + + if self.policy != Policy.combined: + # They are ordered in the order of preference, so we pick the first that's non-zero + for source in sources_for_policy: + if self.limit_solutions[source] > 0.: + return source + return SpeedLimitSource.none + + sources_with_limits = [(s, limit) for s, limit in [(s, self.limit_solutions[s]) for s in sources_for_policy] if limit > 0.] + if sources_with_limits: + return min(sources_with_limits, key=lambda x: x[1])[0] + + return SpeedLimitSource.none + + def _resolve_limit_sources(self, sm: messaging.SubMaster) -> tuple[float, float, custom.LongitudinalPlanSP.SpeedLimit.Source]: + """Get limit solutions from each data source""" + self._get_from_car_state(sm) + self._get_from_map_data(sm) + + source = self._get_source_solution_according_to_policy() + speed_limit = self.limit_solutions[source] if source else 0. + distance = self.distance_solutions[source] if source else 0. + + return speed_limit, distance, source + + def update(self, v_ego: float, sm: messaging.SubMaster) -> None: + self.v_ego = v_ego + self.update_params() + + self.speed_limit, self.distance, self.source = self._resolve_limit_sources(sm) + self.speed_limit_offset = self._get_speed_limit_offset() + + self.frame += 1 diff --git a/sunnypilot/selfdrive/controls/lib/speed_limit/tests/__init__.py b/sunnypilot/selfdrive/controls/lib/speed_limit/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sunnypilot/selfdrive/controls/lib/speed_limit/tests/test_speed_limit_resolver.py b/sunnypilot/selfdrive/controls/lib/speed_limit/tests/test_speed_limit_resolver.py new file mode 100644 index 0000000000..c02831d71a --- /dev/null +++ b/sunnypilot/selfdrive/controls/lib/speed_limit/tests/test_speed_limit_resolver.py @@ -0,0 +1,144 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" +import random +import time + +import pytest +from pytest_mock import MockerFixture + +from cereal import custom +from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit import LIMIT_MAX_MAP_DATA_AGE + +from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.speed_limit_resolver import SpeedLimitResolver, ALL_SOURCES +from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.common import Policy + +SpeedLimitSource = custom.LongitudinalPlanSP.SpeedLimit.Source + + +def create_mock(properties, mocker: MockerFixture): + mock = mocker.MagicMock() + for _property, value in properties.items(): + setattr(mock, _property, value) + return mock + + +def setup_sm_mock(mocker: MockerFixture): + cruise_speed_limit = random.uniform(0, 120) + live_map_data_limit = random.uniform(0, 120) + + car_state = create_mock({ + 'gasPressed': False, + 'brakePressed': False, + 'standstill': False, + }, mocker) + car_state_sp = create_mock({ + 'speedLimit': cruise_speed_limit, + }, mocker) + live_map_data = create_mock({ + 'speedLimit': live_map_data_limit, + 'speedLimitValid': True, + 'speedLimitAhead': 0., + 'speedLimitAheadValid': 0., + 'speedLimitAheadDistance': 0., + }, mocker) + gps_data = create_mock({ + 'unixTimestampMillis': time.monotonic() * 1e3, + }, mocker) + sm_mock = mocker.MagicMock() + sm_mock.__getitem__.side_effect = lambda key: { + 'carState': car_state, + 'liveMapDataSP': live_map_data, + 'carStateSP': car_state_sp, + 'gpsLocation': gps_data, + }[key] + return sm_mock + + +parametrized_policies = pytest.mark.parametrize( + "policy, sm_key, function_key", [ + (Policy.car_state_only, 'carStateSP', SpeedLimitSource.car), + (Policy.car_state_priority, 'carStateSP', SpeedLimitSource.car), + (Policy.map_data_only, 'liveMapDataSP', SpeedLimitSource.map), + (Policy.map_data_priority, 'liveMapDataSP', SpeedLimitSource.map), + ], + ids=lambda val: val.name if hasattr(val, 'name') else str(val) +) + + +@pytest.mark.parametrize("resolver_class", [SpeedLimitResolver]) +class TestSpeedLimitResolverValidation: + + @pytest.mark.parametrize("policy", list(Policy), ids=lambda policy: policy.name) + def test_initial_state(self, resolver_class, policy): + resolver = resolver_class() + resolver.policy = policy + for source in ALL_SOURCES: + if source in resolver.limit_solutions: + assert resolver.limit_solutions[source] == 0. + assert resolver.distance_solutions[source] == 0. + + @parametrized_policies + def test_resolver(self, resolver_class, policy, sm_key, function_key, mocker: MockerFixture): + resolver = resolver_class() + resolver.policy = policy + sm_mock = setup_sm_mock(mocker) + source_speed_limit = sm_mock[sm_key].speedLimit + + # Assert the resolver + resolver.update(source_speed_limit, sm_mock) + assert resolver.speed_limit == source_speed_limit + assert resolver.source == ALL_SOURCES[function_key] + + def test_resolver_combined(self, resolver_class, mocker: MockerFixture): + resolver = resolver_class() + resolver.policy = Policy.combined + sm_mock = setup_sm_mock(mocker) + socket_to_source = {'carStateSP': SpeedLimitSource.car, 'liveMapDataSP': SpeedLimitSource.map} + minimum_key, minimum_speed_limit = min( + ((key, sm_mock[key].speedLimit) for key in + socket_to_source.keys()), key=lambda x: x[1]) + + # Assert the resolver + resolver.update(minimum_speed_limit, sm_mock) + assert resolver.speed_limit == minimum_speed_limit + assert resolver.source == socket_to_source[minimum_key] + + @parametrized_policies + def test_parser(self, resolver_class, policy, sm_key, function_key, mocker: MockerFixture): + resolver = resolver_class() + resolver.policy = policy + sm_mock = setup_sm_mock(mocker) + source_speed_limit = sm_mock[sm_key].speedLimit + + # Assert the parsing + resolver.update(source_speed_limit, sm_mock) + assert resolver.limit_solutions[ALL_SOURCES[function_key]] == source_speed_limit + assert resolver.distance_solutions[ALL_SOURCES[function_key]] == 0. + + @pytest.mark.parametrize("policy", list(Policy), ids=lambda policy: policy.name) + def test_resolve_interaction_in_update(self, resolver_class, policy, mocker: MockerFixture): + v_ego = 50 + resolver = resolver_class() + resolver.policy = policy + + sm_mock = setup_sm_mock(mocker) + resolver.update(v_ego, sm_mock) + + # After resolution + assert resolver.speed_limit is not None + assert resolver.distance is not None + assert resolver.source is not None + + @pytest.mark.parametrize("policy", list(Policy), ids=lambda policy: policy.name) + def test_old_map_data_ignored(self, resolver_class, policy, mocker: MockerFixture): + resolver = resolver_class() + resolver.policy = policy + sm_mock = mocker.MagicMock() + sm_mock['gpsLocation'].unixTimestampMillis = (time.monotonic() - 2 * LIMIT_MAX_MAP_DATA_AGE) * 1e3 + resolver._get_from_map_data(sm_mock) + assert resolver.limit_solutions[SpeedLimitSource.map] == 0. + assert resolver.distance_solutions[SpeedLimitSource.map] == 0. From c55f40e77d90f2128b8d2fcf14e08c2728339021 Mon Sep 17 00:00:00 2001 From: Kumar <36933347+rav4kumar@users.noreply.github.com> Date: Fri, 19 Sep 2025 22:01:08 -0700 Subject: [PATCH 090/159] ui: Speed Limit Information (#995) * less for now * always on and fix conv * update api * missed * fix convert * only draw when decreasing, seems like a bug from mapd * use frame check, otherwise too jumpy * only update when mapd updates * count up and down * introduce toggle * more ui * slightly wider * desc * rename * slight cleanup * fix offset position * more vienna fix * fix ahead alignment * road name in another PR * cleanup * single place * adjust ahead distance display * cleanup * Near * bump it * cleanup logic --------- Co-authored-by: Jason Wen --- common/params_keys.h | 1 + common/util.h | 1 + .../longitudinal/speed_limit/helpers.h | 10 + .../speed_limit/speed_limit_settings.cc | 37 ++- .../speed_limit/speed_limit_settings.h | 16 ++ selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 213 +++++++++++++++++- selfdrive/ui/sunnypilot/qt/onroad/hud.h | 11 + selfdrive/ui/sunnypilot/ui.cc | 3 +- selfdrive/ui/sunnypilot/ui_scene.h | 1 + 9 files changed, 281 insertions(+), 12 deletions(-) diff --git a/common/params_keys.h b/common/params_keys.h index a9408037a0..6d60e2cfdd 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -227,6 +227,7 @@ inline static std::unordered_map keys = { {"RoadName", {CLEAR_ON_ONROAD_TRANSITION, STRING}}, // Speed Limit + {"SpeedLimitMode", {PERSISTENT | BACKUP, INT, "1"}}, {"SpeedLimitOffsetType", {PERSISTENT | BACKUP, INT, "0"}}, {"SpeedLimitPolicy", {PERSISTENT | BACKUP, INT, "3"}}, {"SpeedLimitValueOffset", {PERSISTENT | BACKUP, INT, "0"}}, diff --git a/common/util.h b/common/util.h index f46db4d9fa..6d28e3ccbc 100644 --- a/common/util.h +++ b/common/util.h @@ -36,6 +36,7 @@ const double MS_TO_KPH = 3.6; const double MS_TO_MPH = MS_TO_KPH * KM_TO_MILE; const double METER_TO_MILE = KM_TO_MILE / 1000.0; const double METER_TO_FOOT = 3.28084; +const double METER_TO_KM = 1. / 1000.0; #define ALIGNED_SIZE(x, align) (((x) + (align)-1) & ~((align)-1)) diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h index 84979a53af..55764372c4 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h @@ -33,3 +33,13 @@ inline const QString SpeedLimitSourcePolicyTexts[]{ QObject::tr("Map\nFirst"), QObject::tr("Combined\nData") }; + +enum class SpeedLimitMode { + OFF, + INFORMATION, +}; + +inline const QString SpeedLimitModeTexts[]{ + QObject::tr("Off"), + QObject::tr("Information"), +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc index 7508ea134c..2bacbace7c 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc @@ -20,16 +20,26 @@ SpeedLimitSettings::SpeedLimitSettings(QWidget *parent) : QStackedWidget(parent) subPanelLayout->addSpacing(20); - ListWidgetSP *list = new ListWidgetSP(this); - - auto *speedLimitBtnFrame = new QFrame(this); - auto *speedLimitBtnFrameLayout = new QGridLayout(); - speedLimitBtnFrame->setLayout(speedLimitBtnFrameLayout); - speedLimitBtnFrameLayout->setContentsMargins(0, 40, 0, 40); - speedLimitBtnFrameLayout->setSpacing(0); + ListWidgetSP *list = new ListWidgetSP(this, false); speedLimitPolicyScreen = new SpeedLimitPolicy(this); + std::vector speed_limit_mode_texts{ + SpeedLimitModeTexts[static_cast(SpeedLimitMode::OFF)], + SpeedLimitModeTexts[static_cast(SpeedLimitMode::INFORMATION)], + }; + speed_limit_mode_settings = new ButtonParamControlSP( + "SpeedLimitMode", + tr("Speed Limit Mode"), + "", + "", + speed_limit_mode_texts, + 385); + list->addItem(speed_limit_mode_settings); + + list->addItem(horizontal_line()); + list->addItem(vertical_space()); + speedLimitSource = new PushButtonSP(tr("Customize Source")); connect(speedLimitSource, &QPushButton::clicked, [&]() { setCurrentWidget(speedLimitPolicyScreen); @@ -41,8 +51,10 @@ SpeedLimitSettings::SpeedLimitSettings(QWidget *parent) : QStackedWidget(parent) }); speedLimitSource->setFixedWidth(720); - speedLimitBtnFrameLayout->addWidget(speedLimitSource, 0, 0, Qt::AlignLeft); - list->addItem(speedLimitBtnFrame); + list->addItem(speedLimitSource); + + list->addItem(vertical_space(0)); + list->addItem(horizontal_line()); QFrame *offsetFrame = new QFrame(this); QVBoxLayout *offsetLayout = new QVBoxLayout(offsetFrame); @@ -73,6 +85,7 @@ SpeedLimitSettings::SpeedLimitSettings(QWidget *parent) : QStackedWidget(parent) list->addItem(offsetFrame); + connect(speed_limit_mode_settings, &ButtonParamControlSP::buttonClicked, this, &SpeedLimitSettings::refresh); connect(speed_limit_offset, &OptionControlSP::updateLabels, this, &SpeedLimitSettings::refresh); connect(speed_limit_offset_settings, &ButtonParamControlSP::showDescriptionEvent, speed_limit_offset, &OptionControlSP::showDescription); connect(speed_limit_offset_settings, &ButtonParamControlSP::buttonClicked, this, &SpeedLimitSettings::refresh); @@ -86,9 +99,11 @@ SpeedLimitSettings::SpeedLimitSettings(QWidget *parent) : QStackedWidget(parent) void SpeedLimitSettings::refresh() { bool is_metric_param = params.getBool("IsMetric"); + SpeedLimitMode speed_limit_mode_param = static_cast(std::atoi(params.get("SpeedLimitMode").c_str())); SpeedLimitOffsetType offset_type_param = static_cast(std::atoi(params.get("SpeedLimitOffsetType").c_str())); QString offsetLabel = QString::fromStdString(params.get("SpeedLimitValueOffset")); + speed_limit_mode_settings->setDescription(modeDescription(speed_limit_mode_param)); speed_limit_offset->setDescription(offsetDescription(offset_type_param)); if (offset_type_param == SpeedLimitOffsetType::PERCENT) { @@ -104,9 +119,11 @@ void SpeedLimitSettings::refresh() { speed_limit_offset->setLabel(offsetLabel); speed_limit_offset->showDescription(); } + + speed_limit_mode_settings->showDescription(); + speed_limit_offset->showDescription(); } void SpeedLimitSettings::showEvent(QShowEvent *event) { refresh(); - speed_limit_offset->showDescription(); } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h index 40ffead700..ebffcf65e4 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h @@ -27,6 +27,7 @@ signals: private: Params params; QFrame *subPanelFrame; + ButtonParamControlSP *speed_limit_mode_settings; PushButtonSP *speedLimitSource; SpeedLimitPolicy *speedLimitPolicyScreen; ButtonParamControlSP *speed_limit_offset_settings; @@ -50,4 +51,19 @@ private: .arg(fixed_str) .arg(percent_str); } + + static QString modeDescription(SpeedLimitMode mode = SpeedLimitMode::OFF) { + QString off_str = tr("⦿ Off: Disables the Speed Limit functions."); + QString info_str = tr("⦿ Information: Displays the current road's speed limit."); + + if (mode == SpeedLimitMode::INFORMATION) { + info_str = "" + info_str + ""; + } else { + off_str = "" + off_str + ""; + } + + return QString("%1
%2") + .arg(off_str) + .arg(info_str); + } }; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index fb2a69c24b..923eb3bb81 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -27,6 +27,24 @@ void HudRendererSP::updateState(const UIState &s) { const auto ltp = sm["liveTorqueParameters"].getLiveTorqueParameters(); const auto car_params = sm["carParams"].getCarParams(); const auto lp_sp = sm["longitudinalPlanSP"].getLongitudinalPlanSP(); + const auto lmd = sm["liveMapDataSP"].getLiveMapDataSP(); + + is_metric = s.scene.is_metric; + float speedConv = is_metric ? MS_TO_KPH : MS_TO_MPH; + speedLimit = lp_sp.getSpeedLimit().getResolver().getSpeedLimit() * speedConv; + speedLimitOffset = lp_sp.getSpeedLimit().getResolver().getSpeedLimitOffset() * speedConv; + speedLimitMode = static_cast(s.scene.speed_limit_mode); + if (sm.updated("liveMapDataSP")) { + speedLimitAheadValid = lmd.getSpeedLimitAheadValid(); + speedLimitAhead = lmd.getSpeedLimitAhead() * speedConv; + speedLimitAheadDistance = lmd.getSpeedLimitAheadDistance(); + if (speedLimitAheadDistance < speedLimitAheadDistancePrev && speedLimitAheadValidFrame < 2) { + speedLimitAheadValidFrame++; + } else if (speedLimitAheadDistance > speedLimitAheadDistancePrev && speedLimitAheadValidFrame > 0) { + speedLimitAheadValidFrame--; + } + } + speedLimitAheadDistancePrev = speedLimitAheadDistance; static int reverse_delay = 0; bool reverse_allowed = false; @@ -41,7 +59,6 @@ void HudRendererSP::updateState(const UIState &s) { } reversing = reverse_allowed; - is_metric = s.scene.is_metric; // Handle older routes where vEgoCluster is not set v_ego_cluster_seen = v_ego_cluster_seen || car_state.getVEgoCluster() != 0.0; @@ -123,6 +140,12 @@ void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { if (standstillTimer) { drawStandstillTimer(p, surface_rect.right() / 12 * 10, surface_rect.bottom() / 12 * 1.53); } + + // Speed Limit + if (speedLimitMode != SpeedLimitMode::OFF) { + drawSpeedLimitSigns(p); + drawUpcomingSpeedLimit(p); + } } } @@ -311,3 +334,191 @@ void HudRendererSP::drawStandstillTimer(QPainter &p, int x, int y) { standstillElapsedTime = 0.0; } } + +void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { + QString speedLimitStr = speedLimit > 0 ? QString::number(std::nearbyint(speedLimit)) : "---"; + + // Offset display text + QString speedLimitSubText = ""; + if (speedLimitOffset != 0) { + speedLimitSubText = (speedLimitOffset > 0 ? "+" : "") + QString::number(std::nearbyint(speedLimitOffset)); + } + + // Position next to MAX speed box + const int sign_width = is_metric ? 200 : 172; + const int sign_x = is_metric ? 280 : 272; + const int sign_y = 45; + const int sign_height = 204; + QRect sign_rect(sign_x, sign_y, sign_width, sign_height); + + int alpha = 255; + + if (is_metric) { + // EU Vienna Convention style circular sign + QRect vienna_rect = sign_rect; + int circle_size = std::min(vienna_rect.width(), vienna_rect.height()); + QRect circle_rect(vienna_rect.x(), vienna_rect.y(), circle_size, circle_size); + + if (vienna_rect.width() > vienna_rect.height()) { + circle_rect.moveLeft(vienna_rect.x() + (vienna_rect.width() - circle_size) / 2); + } else if (vienna_rect.height() > vienna_rect.width()) { + circle_rect.moveTop(vienna_rect.y() + (vienna_rect.height() - circle_size) / 2); + } + + // White background circle + p.setPen(Qt::NoPen); + p.setBrush(QColor(255, 255, 255, alpha)); + p.drawEllipse(circle_rect); + + // Red border ring with color coding + QRect red_ring = circle_rect; + QColor ring_color = QColor(255, 0, 0, alpha); + + p.setBrush(ring_color); + p.drawEllipse(red_ring); + + // Center white circle for text + int ring_size = circle_size * 0.12; + QRect center_circle = red_ring.adjusted(ring_size, ring_size, -ring_size, -ring_size); + p.setBrush(QColor(255, 255, 255, alpha)); + p.drawEllipse(center_circle); + + // Speed value, smaller font for 3+ digits + int font_size = (speedLimitStr.size() >= 3) ? 70 : 85; + p.setFont(InterFont(font_size, QFont::Bold)); + QColor speed_color = QColor(0, 0, 0, alpha); + + p.setPen(speed_color); + p.drawText(center_circle, Qt::AlignCenter, speedLimitStr); + + // Offset value in small circular box + if (!speedLimitSubText.isEmpty()) { + int offset_circle_size = circle_size * 0.4; + int overlap = offset_circle_size * 0.25; + QRect offset_circle_rect( + circle_rect.right() - offset_circle_size/1.25 + overlap, + circle_rect.top() - offset_circle_size/1.75 + overlap, + offset_circle_size, + offset_circle_size + ); + + p.setPen(QPen(QColor(77, 77, 77, 255), 6)); + p.setBrush(QColor(0, 0, 0, alpha)); + p.drawEllipse(offset_circle_rect); + + p.setFont(InterFont(offset_circle_size * 0.45, QFont::Bold)); + p.setPen(QColor(255, 255, 255, alpha)); + p.drawText(offset_circle_rect, Qt::AlignCenter, speedLimitSubText); + } + } else { + // US/Canada MUTCD style sign + p.setPen(Qt::NoPen); + p.setBrush(QColor(255, 255, 255, alpha)); + p.drawRoundedRect(sign_rect, 32, 32); + + // Inner border with violation color coding + QRect inner_rect = sign_rect.adjusted(10, 10, -10, -10); + QColor border_color = QColor(0, 0, 0, alpha); + + p.setPen(QPen(border_color, 4)); + p.setBrush(QColor(255, 255, 255, alpha)); + p.drawRoundedRect(inner_rect, 22, 22); + + // "SPEED LIMIT" text + p.setFont(InterFont(40, QFont::DemiBold)); + p.setPen(QColor(0, 0, 0, alpha)); + p.drawText(inner_rect.adjusted(0, 10, 0, 0), Qt::AlignTop | Qt::AlignHCenter, tr("SPEED")); + p.drawText(inner_rect.adjusted(0, 50, 0, 0), Qt::AlignTop | Qt::AlignHCenter, tr("LIMIT")); + + // Speed value with color coding + p.setFont(InterFont(90, QFont::Bold)); + QColor speed_color = QColor(0, 0, 0, alpha); + + p.setPen(speed_color); + p.drawText(inner_rect.adjusted(0, 80, 0, 0), Qt::AlignTop | Qt::AlignHCenter, speedLimitStr); + + // Offset value in small box + if (!speedLimitSubText.isEmpty()) { + int offset_box_size = sign_rect.width() * 0.4; + int overlap = offset_box_size * 0.25; + QRect offset_box_rect( + sign_rect.right() - offset_box_size/1.5 + overlap, + sign_rect.top() - offset_box_size/1.25 + overlap, + offset_box_size, + offset_box_size + ); + + int corner_radius = offset_box_size * 0.2; + p.setPen(QPen(QColor(77, 77, 77, 255), 6)); + p.setBrush(QColor(0, 0, 0, alpha)); + p.drawRoundedRect(offset_box_rect, corner_radius, corner_radius); + + p.setFont(InterFont(offset_box_size * 0.45, QFont::Bold)); + p.setPen(QColor(255, 255, 255, alpha)); + p.drawText(offset_box_rect, Qt::AlignCenter, speedLimitSubText); + } + } +} + +void HudRendererSP::drawUpcomingSpeedLimit(QPainter &p) { + bool speed_limit_ahead = speedLimitAheadValid && speedLimitAhead > 0 && speedLimitAhead != speedLimit && speedLimitAheadValidFrame > 0; + if (!speed_limit_ahead) { + return; + } + + auto roundToInterval = [&](float distance, int interval, int threshold) { + int base = static_cast(distance / interval) * interval; + return (distance - base >= threshold) ? base + interval : base; + }; + + auto outputDistance = [&] { + if (is_metric) { + if (speedLimitAheadDistance < 50) return tr("Near"); + if (speedLimitAheadDistance >= 1000) return QString::number(speedLimitAheadDistance * METER_TO_KM, 'f', 1) + tr("km"); + + int rounded = (speedLimitAheadDistance < 200) ? std::max(10, roundToInterval(speedLimitAheadDistance, 10, 5)) : roundToInterval(speedLimitAheadDistance, 100, 50); + return QString::number(rounded) + tr("m"); + } else { + float distance_ft = speedLimitAheadDistance * METER_TO_FOOT; + if (distance_ft < 100) return tr("Near"); + if (distance_ft >= 900) return QString::number(speedLimitAheadDistance * METER_TO_MILE, 'f', 1) + tr("mi"); + + int rounded = (distance_ft < 500) ? std::max(50, roundToInterval(distance_ft, 50, 25)) : roundToInterval(distance_ft, 100, 50); + return QString::number(rounded) + tr("ft"); + } + }; + + QString speedStr = QString::number(std::nearbyint(speedLimitAhead)); + QString distanceStr = outputDistance(); + + // Position below current speed limit sign + const int sign_width = is_metric ? 200 : 172; + const int sign_x = is_metric ? 280 : 272; + const int sign_y = 45; + const int sign_height = 204; + + const int ahead_width = 170; + const int ahead_height = 160; + const int ahead_x = sign_x + (sign_width - ahead_width) / 2; + const int ahead_y = sign_y + sign_height + 10; + + QRect ahead_rect(ahead_x, ahead_y, ahead_width, ahead_height); + p.setPen(QPen(QColor(255, 255, 255, 100), 3)); + p.setBrush(QColor(0, 0, 0, 180)); + p.drawRoundedRect(ahead_rect, 16, 16); + + // "AHEAD" label + p.setFont(InterFont(40, QFont::DemiBold)); + p.setPen(QColor(200, 200, 200, 255)); + p.drawText(ahead_rect.adjusted(0, 4, 0, 0), Qt::AlignTop | Qt::AlignHCenter, tr("AHEAD")); + + // Speed value + p.setFont(InterFont(70, QFont::Bold)); + p.setPen(QColor(255, 255, 255, 255)); + p.drawText(ahead_rect.adjusted(0, 38, 0, 0), Qt::AlignTop | Qt::AlignHCenter, speedStr); + + // Distance + p.setFont(InterFont(40, QFont::Normal)); + p.setPen(QColor(180, 180, 180, 255)); + p.drawText(ahead_rect.adjusted(0, 110, 0, 0), Qt::AlignTop | Qt::AlignHCenter, distanceStr); +} diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.h b/selfdrive/ui/sunnypilot/qt/onroad/hud.h index 4c92835957..d76eb06060 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.h +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.h @@ -8,6 +8,7 @@ #pragma once #include "selfdrive/ui/qt/onroad/hud.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h" #include "selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h" class HudRendererSP : public HudRenderer { @@ -28,6 +29,8 @@ private: void drawStandstillTimer(QPainter &p, int x, int y); bool pulseElement(int frame); void drawSmartCruiseControlOnroadIcon(QPainter &p, const QRect &surface_rect, int x_offset, int y_offset, std::string name); + void drawSpeedLimitSigns(QPainter &p); + void drawUpcomingSpeedLimit(QPainter &p); bool lead_status; float lead_d_rel; @@ -63,4 +66,12 @@ private: bool smartCruiseControlVisionEnabled; bool smartCruiseControlVisionActive; int smartCruiseControlVisionFrame; + float speedLimit; + float speedLimitOffset; + bool speedLimitAheadValid; + float speedLimitAhead; + float speedLimitAheadDistance; + float speedLimitAheadDistancePrev; + int speedLimitAheadValidFrame; + SpeedLimitMode speedLimitMode = SpeedLimitMode::OFF; }; diff --git a/selfdrive/ui/sunnypilot/ui.cc b/selfdrive/ui/sunnypilot/ui.cc index 7b10929bc6..7f83e5ea79 100644 --- a/selfdrive/ui/sunnypilot/ui.cc +++ b/selfdrive/ui/sunnypilot/ui.cc @@ -20,7 +20,7 @@ UIStateSP::UIStateSP(QObject *parent) : UIState(parent) { "wideRoadCameraState", "managerState", "selfdriveState", "longitudinalPlan", "modelManagerSP", "selfdriveStateSP", "longitudinalPlanSP", "backupManagerSP", "carControl", "gpsLocationExternal", "gpsLocation", "liveTorqueParameters", - "carStateSP", "liveParameters" + "carStateSP", "liveParameters", "liveMapDataSP" }); // update timer @@ -53,6 +53,7 @@ void ui_update_params_sp(UIStateSP *s) { auto params = Params(); s->scene.dev_ui_info = std::atoi(params.get("DevUIInfo").c_str()); s->scene.standstill_timer = params.getBool("StandstillTimer"); + s->scene.speed_limit_mode = params.getBool("SpeedLimitMode"); } DeviceSP::DeviceSP(QObject *parent) : Device(parent) { diff --git a/selfdrive/ui/sunnypilot/ui_scene.h b/selfdrive/ui/sunnypilot/ui_scene.h index c941be675c..69cebd6d79 100644 --- a/selfdrive/ui/sunnypilot/ui_scene.h +++ b/selfdrive/ui/sunnypilot/ui_scene.h @@ -10,4 +10,5 @@ typedef struct UISceneSP : UIScene { int dev_ui_info = 0; bool standstill_timer = false; + int speed_limit_mode = 0; } UISceneSP; From bdb83b6be17f6663b9de97ebccb403ad8fd4751f Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 20 Sep 2025 01:40:51 -0400 Subject: [PATCH 091/159] ui: remove redundant code (#1262) --- selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 8 -------- 1 file changed, 8 deletions(-) diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index 923eb3bb81..47ba0590d1 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -17,7 +17,6 @@ void HudRendererSP::updateState(const UIState &s) { HudRenderer::updateState(s); const SubMaster &sm = *(s.sm); - const bool cs_alive = sm.alive("controlsState"); const auto cs = sm["controlsState"].getControlsState(); const auto car_state = sm["carState"].getCarState(); const auto car_control = sm["carControl"].getCarControl(); @@ -29,7 +28,6 @@ void HudRendererSP::updateState(const UIState &s) { const auto lp_sp = sm["longitudinalPlanSP"].getLongitudinalPlanSP(); const auto lmd = sm["liveMapDataSP"].getLiveMapDataSP(); - is_metric = s.scene.is_metric; float speedConv = is_metric ? MS_TO_KPH : MS_TO_MPH; speedLimit = lp_sp.getSpeedLimit().getResolver().getSpeedLimit() * speedConv; speedLimitOffset = lp_sp.getSpeedLimit().getResolver().getSpeedLimitOffset() * speedConv; @@ -60,12 +58,6 @@ void HudRendererSP::updateState(const UIState &s) { reversing = reverse_allowed; - // Handle older routes where vEgoCluster is not set - v_ego_cluster_seen = v_ego_cluster_seen || car_state.getVEgoCluster() != 0.0; - float v_ego = v_ego_cluster_seen ? car_state.getVEgoCluster() : car_state.getVEgo(); - speed = cs_alive ? std::max(0.0, v_ego) : 0.0; - speed *= is_metric ? MS_TO_KPH : MS_TO_MPH; - latActive = car_control.getLatActive(); steerOverride = car_state.getSteeringPressed(); From c248f307f86350e16734bb427a6a1c7750618b8a Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 20 Sep 2025 01:59:07 -0400 Subject: [PATCH 092/159] ui: Speed Limit Warning (#1263) * ui: Speed Limit Warning * missed * behind toggle * missed * reorder * fix type --- .../settings/longitudinal/speed_limit/helpers.h | 2 ++ .../longitudinal/speed_limit/speed_limit_settings.cc | 1 + .../longitudinal/speed_limit/speed_limit_settings.h | 10 +++++++--- selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 12 +++++++----- selfdrive/ui/sunnypilot/ui.cc | 2 +- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h index 55764372c4..22cdd8c631 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h @@ -37,9 +37,11 @@ inline const QString SpeedLimitSourcePolicyTexts[]{ enum class SpeedLimitMode { OFF, INFORMATION, + WARNING, }; inline const QString SpeedLimitModeTexts[]{ QObject::tr("Off"), QObject::tr("Information"), + QObject::tr("Warning"), }; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc index 2bacbace7c..6f48833611 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc @@ -27,6 +27,7 @@ SpeedLimitSettings::SpeedLimitSettings(QWidget *parent) : QStackedWidget(parent) std::vector speed_limit_mode_texts{ SpeedLimitModeTexts[static_cast(SpeedLimitMode::OFF)], SpeedLimitModeTexts[static_cast(SpeedLimitMode::INFORMATION)], + SpeedLimitModeTexts[static_cast(SpeedLimitMode::WARNING)], }; speed_limit_mode_settings = new ButtonParamControlSP( "SpeedLimitMode", diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h index ebffcf65e4..f83f450557 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h @@ -55,15 +55,19 @@ private: static QString modeDescription(SpeedLimitMode mode = SpeedLimitMode::OFF) { QString off_str = tr("⦿ Off: Disables the Speed Limit functions."); QString info_str = tr("⦿ Information: Displays the current road's speed limit."); + QString warning_str = tr("⦿ Warning: Provides a warning when exceeding the current road's speed limit."); - if (mode == SpeedLimitMode::INFORMATION) { + if (mode == SpeedLimitMode::WARNING) { + warning_str = "" + warning_str + ""; + } else if (mode == SpeedLimitMode::INFORMATION) { info_str = "" + info_str + ""; } else { off_str = "" + off_str + ""; } - return QString("%1
%2") + return QString("%1
%2
%3") .arg(off_str) - .arg(info_str); + .arg(info_str) + .arg(warning_str); } }; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index 47ba0590d1..71bdd92cab 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -328,7 +328,10 @@ void HudRendererSP::drawStandstillTimer(QPainter &p, int x, int y) { } void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { - QString speedLimitStr = speedLimit > 0 ? QString::number(std::nearbyint(speedLimit)) : "---"; + int speedLimitRounded = std::nearbyint(speedLimit); + bool overspeed = speedLimitRounded < std::nearbyint(speed) && speedLimitRounded > 0; + bool speedLimitWarningEnabled = speedLimitMode == SpeedLimitMode::WARNING; + QString speedLimitStr = speedLimit > 0 ? QString::number(speedLimitRounded) : "---"; // Offset display text QString speedLimitSubText = ""; @@ -344,6 +347,8 @@ void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { QRect sign_rect(sign_x, sign_y, sign_width, sign_height); int alpha = 255; + QColor red_color = QColor(255, 0, 0, alpha); + QColor speed_color = (speedLimitWarningEnabled && overspeed) ? red_color : QColor(0, 0, 0, alpha); if (is_metric) { // EU Vienna Convention style circular sign @@ -364,9 +369,8 @@ void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { // Red border ring with color coding QRect red_ring = circle_rect; - QColor ring_color = QColor(255, 0, 0, alpha); - p.setBrush(ring_color); + p.setBrush(red_color); p.drawEllipse(red_ring); // Center white circle for text @@ -378,7 +382,6 @@ void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { // Speed value, smaller font for 3+ digits int font_size = (speedLimitStr.size() >= 3) ? 70 : 85; p.setFont(InterFont(font_size, QFont::Bold)); - QColor speed_color = QColor(0, 0, 0, alpha); p.setPen(speed_color); p.drawText(center_circle, Qt::AlignCenter, speedLimitStr); @@ -424,7 +427,6 @@ void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { // Speed value with color coding p.setFont(InterFont(90, QFont::Bold)); - QColor speed_color = QColor(0, 0, 0, alpha); p.setPen(speed_color); p.drawText(inner_rect.adjusted(0, 80, 0, 0), Qt::AlignTop | Qt::AlignHCenter, speedLimitStr); diff --git a/selfdrive/ui/sunnypilot/ui.cc b/selfdrive/ui/sunnypilot/ui.cc index 7f83e5ea79..7b582a8341 100644 --- a/selfdrive/ui/sunnypilot/ui.cc +++ b/selfdrive/ui/sunnypilot/ui.cc @@ -53,7 +53,7 @@ void ui_update_params_sp(UIStateSP *s) { auto params = Params(); s->scene.dev_ui_info = std::atoi(params.get("DevUIInfo").c_str()); s->scene.standstill_timer = params.getBool("StandstillTimer"); - s->scene.speed_limit_mode = params.getBool("SpeedLimitMode"); + s->scene.speed_limit_mode = std::atoi(params.get("SpeedLimitMode").c_str()); } DeviceSP::DeviceSP(QObject *parent) : Device(parent) { From 55b7529ca4b6b4a7704dd3822109a54d9397b571 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 20 Sep 2025 05:23:02 -0400 Subject: [PATCH 093/159] ui: Road Name (#1265) --- .../qt/offroad/settings/visuals_panel.cc | 13 +++++-- selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 35 +++++++++++++++++++ selfdrive/ui/sunnypilot/qt/onroad/hud.h | 3 ++ selfdrive/ui/sunnypilot/ui.cc | 1 + selfdrive/ui/sunnypilot/ui_scene.h | 1 + 5 files changed, 50 insertions(+), 3 deletions(-) diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc index e19760f2e1..ca58282a3d 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc @@ -25,21 +25,28 @@ VisualsPanel::VisualsPanel(QWidget *parent) : QWidget(parent) { "BlindSpot", tr("Show Blind Spot Warnings"), tr("Enabling this will display warnings when a vehicle is detected in your blind spot as long as your car has BSM supported."), - "../assets/offroad/icon_monitoring.png", + "", false, }, { "RainbowMode", tr("Enable Tesla Rainbow Mode"), RainbowizeWords(tr("A beautiful rainbow effect on the path the model wants to take.")) + "
" + tr("It")+ " " + tr("does not") + " " + tr("affect driving in any way.") + "", - "../assets/offroad/icon_monitoring.png", + "", false, }, { "StandstillTimer", tr("Enable Standstill Timer"), tr("Show a timer on the HUD when the car is at a standstill."), - "../assets/offroad/icon_monitoring.png", + "", + false, + }, + { + "RoadName", + tr("Display Road Name"), + tr("Displays the name of the road the car is traveling on. The OpenStreetMap database of the location must be downloaded from the OSM panel to fetch the road name."), + "", false, }, }; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index 71bdd92cab..991710bbfa 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -32,7 +32,9 @@ void HudRendererSP::updateState(const UIState &s) { speedLimit = lp_sp.getSpeedLimit().getResolver().getSpeedLimit() * speedConv; speedLimitOffset = lp_sp.getSpeedLimit().getResolver().getSpeedLimitOffset() * speedConv; speedLimitMode = static_cast(s.scene.speed_limit_mode); + roadName = s.scene.road_name; if (sm.updated("liveMapDataSP")) { + roadNameStr = QString::fromStdString(lmd.getRoadName()); speedLimitAheadValid = lmd.getSpeedLimitAheadValid(); speedLimitAhead = lmd.getSpeedLimitAhead() * speedConv; speedLimitAheadDistance = lmd.getSpeedLimitAheadDistance(); @@ -138,6 +140,9 @@ void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { drawSpeedLimitSigns(p); drawUpcomingSpeedLimit(p); } + + // Road Name + drawRoadName(p, surface_rect); } } @@ -516,3 +521,33 @@ void HudRendererSP::drawUpcomingSpeedLimit(QPainter &p) { p.setPen(QColor(180, 180, 180, 255)); p.drawText(ahead_rect.adjusted(0, 110, 0, 0), Qt::AlignTop | Qt::AlignHCenter, distanceStr); } + +void HudRendererSP::drawRoadName(QPainter &p, const QRect &surface_rect) { + if (!roadName || roadNameStr.isEmpty()) return; + + // Measure text to size container + p.setFont(InterFont(40, QFont::Normal)); + QFontMetrics fm(p.font()); + + int text_width = fm.horizontalAdvance(roadNameStr); + int padding = 40; + int rect_width = text_width + padding; + + // Constrain to reasonable bounds + int min_width = 200; + int max_width = surface_rect.width() - 40; + rect_width = std::max(min_width, std::min(rect_width, max_width)); + + // Center at top of screen + QRect road_rect(surface_rect.width() / 2 - rect_width / 2, -6, rect_width, 60); + + p.setPen(Qt::NoPen); + p.setBrush(QColor(0, 0, 0, 120)); + p.drawRoundedRect(road_rect, 12, 12); + + p.setPen(QColor(255, 255, 255, 200)); + + // Truncate if still too long + QString truncated = fm.elidedText(roadNameStr, Qt::ElideRight, road_rect.width() - 20); + p.drawText(road_rect, Qt::AlignCenter, truncated); +} diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.h b/selfdrive/ui/sunnypilot/qt/onroad/hud.h index d76eb06060..073780bc10 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.h +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.h @@ -31,6 +31,7 @@ private: void drawSmartCruiseControlOnroadIcon(QPainter &p, const QRect &surface_rect, int x_offset, int y_offset, std::string name); void drawSpeedLimitSigns(QPainter &p); void drawUpcomingSpeedLimit(QPainter &p); + void drawRoadName(QPainter &p, const QRect &surface_rect); bool lead_status; float lead_d_rel; @@ -74,4 +75,6 @@ private: float speedLimitAheadDistancePrev; int speedLimitAheadValidFrame; SpeedLimitMode speedLimitMode = SpeedLimitMode::OFF; + bool roadName; + QString roadNameStr; }; diff --git a/selfdrive/ui/sunnypilot/ui.cc b/selfdrive/ui/sunnypilot/ui.cc index 7b582a8341..9acf844088 100644 --- a/selfdrive/ui/sunnypilot/ui.cc +++ b/selfdrive/ui/sunnypilot/ui.cc @@ -54,6 +54,7 @@ void ui_update_params_sp(UIStateSP *s) { s->scene.dev_ui_info = std::atoi(params.get("DevUIInfo").c_str()); s->scene.standstill_timer = params.getBool("StandstillTimer"); s->scene.speed_limit_mode = std::atoi(params.get("SpeedLimitMode").c_str()); + s->scene.road_name = params.getBool("RoadName"); } DeviceSP::DeviceSP(QObject *parent) : Device(parent) { diff --git a/selfdrive/ui/sunnypilot/ui_scene.h b/selfdrive/ui/sunnypilot/ui_scene.h index 69cebd6d79..768cc5d7a1 100644 --- a/selfdrive/ui/sunnypilot/ui_scene.h +++ b/selfdrive/ui/sunnypilot/ui_scene.h @@ -11,4 +11,5 @@ typedef struct UISceneSP : UIScene { int dev_ui_info = 0; bool standstill_timer = false; int speed_limit_mode = 0; + bool road_name = false; } UISceneSP; From 5f3821c1f9ce589d4bd37ae7fbc5ce6ad94fa825 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 20 Sep 2025 12:21:13 -0400 Subject: [PATCH 094/159] Longitudinal planner: expose custom vTarget and aTarget (#1267) --- cereal/custom.capnp | 2 ++ .../selfdrive/controls/lib/longitudinal_planner.py | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/cereal/custom.capnp b/cereal/custom.capnp index 6527838097..c4360ae311 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -146,6 +146,8 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { longitudinalPlanSource @1 :LongitudinalPlanSource; smartCruiseControl @2 :SmartCruiseControl; speedLimit @3 :SpeedLimit; + vTarget @4 :Float32; + aTarget @5 :Float32; struct DynamicExperimentalControl { state @0 :DynamicExperimentalControlState; diff --git a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py index b4f4fe6d7c..3e4dbd9ab2 100644 --- a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py +++ b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py @@ -24,6 +24,9 @@ class LongitudinalPlannerSP: self.generation = int(model_bundle.generation) if (model_bundle := get_active_bundle()) else None self.source = Source.cruise + self.output_v_target = 0. + self.output_a_target = 0. + @property def mlsim(self) -> bool: # If we don't have a generation set, we assume it's default model. Which as of today are mlsim. @@ -47,9 +50,8 @@ class LongitudinalPlannerSP: } self.source = min(targets, key=lambda k: targets[k][0]) - v_target, a_target = targets[self.source] - - return v_target, a_target + self.output_v_target, self.output_a_target = targets[self.source] + return self.output_v_target, self.output_a_target def update(self, sm: messaging.SubMaster) -> None: self.dec.update(sm) @@ -61,6 +63,8 @@ class LongitudinalPlannerSP: longitudinalPlanSP = plan_sp_send.longitudinalPlanSP longitudinalPlanSP.longitudinalPlanSource = self.source + longitudinalPlanSP.vTarget = float(self.output_v_target) + longitudinalPlanSP.aTarget = float(self.output_a_target) # Dynamic Experimental Control dec = longitudinalPlanSP.dec From 632b416f2ac130d0754efeebdea5588d89da5210 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 20 Sep 2025 14:22:10 -0400 Subject: [PATCH 095/159] ICBM: use `longitudinalPlanSP.vTarget` directly for evaluation (#1266) * ICBM: add SCC-V to v_targets list * Longitudinal planner: expose custom vTarget and aTarget * use the source directly --- selfdrive/selfdrived/selfdrived.py | 4 ++-- .../controller.py | 16 ++++------------ 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index 69dc51360b..170e184629 100755 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -96,7 +96,7 @@ class SelfdriveD(CruiseHelper): 'carOutput', 'driverMonitoringState', 'longitudinalPlan', 'livePose', 'liveDelay', 'managerState', 'liveParameters', 'radarState', 'liveTorqueParameters', 'controlsState', 'carControl', 'driverAssistance', 'alertDebug', 'userBookmark', 'audioFeedback', - 'modelDataV2SP'] + \ + 'modelDataV2SP', 'longitudinalPlanSP'] + \ self.camera_packets + self.sensor_packets + self.gps_packets, ignore_alive=ignore, ignore_avg_freq=ignore, ignore_valid=ignore, frequency=int(1/DT_CTRL)) @@ -444,7 +444,7 @@ class SelfdriveD(CruiseHelper): self.events.add(EventName.personalityChanged) self.experimental_mode_switched = False - self.icbm.run(CS, self.sm['carControl'], self.is_metric) + self.icbm.run(CS, self.sm['carControl'], self.sm['longitudinalPlanSP'], self.is_metric) def data_sample(self): _car_state = messaging.recv_one(self.car_state_sock) diff --git a/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py index 7ee7f3ea64..468e6f55b5 100644 --- a/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py +++ b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py @@ -49,19 +49,11 @@ class IntelligentCruiseButtonManagement: def v_cruise_equal(self) -> bool: return self.v_target == self.v_cruise_cluster - def update_calculations(self, CS: car.CarState) -> None: + def update_calculations(self, CS: car.CarState, LP_SP: custom.LongitudinalPlanSP) -> None: speed_conv = CV.MS_TO_KPH if self.is_metric else CV.MS_TO_MPH ms_conv = CV.KPH_TO_MS if self.is_metric else CV.MPH_TO_MS - v_cruise_ms = CS.vCruise * CV.KPH_TO_MS - # all targets in m/s - v_targets = { - LongitudinalPlanSource.cruise: v_cruise_ms - } - source = min(v_targets, key=lambda k: v_targets[k]) - v_target_ms = v_targets[source] - - self.v_target_ms_last = apply_hysteresis(v_target_ms, self.v_target_ms_last, HYST_GAP * ms_conv) + self.v_target_ms_last = apply_hysteresis(LP_SP.vTarget, self.v_target_ms_last, HYST_GAP * ms_conv) self.v_target = round(self.v_target_ms_last * speed_conv) self.v_cruise_min = get_minimum_set_speed(self.is_metric) @@ -123,13 +115,13 @@ class IntelligentCruiseButtonManagement: self.is_ready = ready and not button_pressed - def run(self, CS: car.CarState, CC: car.CarControl, is_metric: bool) -> None: + def run(self, CS: car.CarState, CC: car.CarControl, LP_SP: custom.LongitudinalPlanSP, is_metric: bool) -> None: if self.CP_SP.pcmCruiseSpeed: return self.is_metric = is_metric - self.update_calculations(CS) + self.update_calculations(CS, LP_SP) self.update_readiness(CS, CC) self.cruise_button = self.update_state_machine() From 2892dc05c8585ba316c9e5ac49744d75c9eced78 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 20 Sep 2025 16:20:22 -0400 Subject: [PATCH 096/159] mapd: use SubMaster polling to validate GPS status (#1268) --- sunnypilot/mapd/live_map_data/base_map_data.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sunnypilot/mapd/live_map_data/base_map_data.py b/sunnypilot/mapd/live_map_data/base_map_data.py index 536d7720b7..6c7679420a 100644 --- a/sunnypilot/mapd/live_map_data/base_map_data.py +++ b/sunnypilot/mapd/live_map_data/base_map_data.py @@ -4,12 +4,12 @@ Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. This file is part of sunnypilot and is licensed under the MIT License. See the LICENSE.md file in the root directory for more details. """ -import time from abc import abstractmethod, ABC from cereal import messaging from openpilot.common.gps import get_gps_location_service from openpilot.common.params import Params +from openpilot.common.realtime import DT_MDL from openpilot.sunnypilot.navd.helpers import Coordinate, coordinate_from_param @@ -18,7 +18,9 @@ class BaseMapData(ABC): self.params = Params() self.gps_location_service = get_gps_location_service(self.params) - self.sm = messaging.SubMaster(['livePose', 'carControl'] + [self.gps_location_service]) + gps_packets = [self.gps_location_service] + self.sm = messaging.SubMaster(['livePose'] + gps_packets, ignore_alive=gps_packets, ignore_avg_freq=gps_packets, + ignore_valid=gps_packets, poll='livePose') self.pm = messaging.PubMaster(['liveMapDataSP']) self.last_position = coordinate_from_param("LastGPSPosition", self.params) @@ -44,20 +46,22 @@ class BaseMapData(ABC): gps = self.sm[self.gps_location_service] # ignore the message if the fix is invalid - gps_ok = self.sm.updated[self.gps_location_service] or (time.monotonic() - self.sm.logMonoTime[self.gps_location_service] / 1e9) > 2.0 + gps_ok = self.sm.recv_frame[self.gps_location_service] > 0 and (self.sm.frame - self.sm.recv_frame[self.gps_location_service]) * DT_MDL < 2.0 if not gps_ok and self.sm['livePose'].inputsOK: - return None + return # livePose has these data, but aren't on cereal self.last_position = Coordinate(gps.latitude, gps.longitude) self.last_altitude = gps.altitude + return + def publish(self) -> None: speed_limit = self.get_current_speed_limit() next_speed_limit, next_speed_limit_distance = self.get_next_speed_limit_and_distance() mapd_sp_send = messaging.new_message('liveMapDataSP') - mapd_sp_send.valid = self.sm.all_checks(service_list=[self.gps_location_service, 'livePose']) + mapd_sp_send.valid = self.sm.all_checks(['livePose']) live_map_data = mapd_sp_send.liveMapDataSP live_map_data.speedLimitValid = bool(speed_limit > 0) From 629cfd845f1b6fd8723c915f025ba0c18e58a2a0 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 20 Sep 2025 17:23:24 -0400 Subject: [PATCH 097/159] ui: fix scrolling behavior in Speed Limit settings (#1269) * rename * ui: fix scrolling behavior in Speed Limit settings --- .../longitudinal/speed_limit/speed_limit_policy.cc | 5 ++++- .../settings/longitudinal/speed_limit/speed_limit_policy.h | 2 ++ .../longitudinal/speed_limit/speed_limit_settings.cc | 7 +++++-- .../longitudinal/speed_limit/speed_limit_settings.h | 2 ++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.cc index 46f361a153..764a8e0208 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.cc @@ -4,6 +4,7 @@ * This file is part of sunnypilot and is licensed under the MIT License. * See the LICENSE.md file in the root directory for more details. */ +#include #include "selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.h" @@ -38,8 +39,9 @@ SpeedLimitPolicy::SpeedLimitPolicy(QWidget *parent) : QWidget(parent) { list->addItem(speed_limit_policy); connect(speed_limit_policy, &ButtonParamControlSP::buttonClicked, this, &SpeedLimitPolicy::refresh); + speedLimitPolicyScroller = new ScrollViewSP(list, this); + main_layout->addWidget(speedLimitPolicyScroller); refresh(); - main_layout->addWidget(list); }; void SpeedLimitPolicy::refresh() { @@ -48,6 +50,7 @@ void SpeedLimitPolicy::refresh() { } void SpeedLimitPolicy::showEvent(QShowEvent *event) { + speedLimitPolicyScroller->verticalScrollBar()->setValue(0); refresh(); speed_limit_policy->showDescription(); } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.h index adeb115db9..219aa53c6e 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.h @@ -10,6 +10,7 @@ #include "selfdrive/ui/sunnypilot/ui.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h" #include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" class SpeedLimitPolicy : public QWidget { Q_OBJECT @@ -25,6 +26,7 @@ signals: private: Params params; ButtonParamControlSP *speed_limit_policy; + ScrollViewSP *speedLimitPolicyScroller; static QString sourceDescription(SpeedLimitSourcePolicy type = SpeedLimitSourcePolicy::CAR_ONLY) { QString car_only = tr("⦿ Car Only: Use Speed Limit data only from Car"); diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc index 6f48833611..eed0306ca0 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc @@ -31,7 +31,7 @@ SpeedLimitSettings::SpeedLimitSettings(QWidget *parent) : QStackedWidget(parent) }; speed_limit_mode_settings = new ButtonParamControlSP( "SpeedLimitMode", - tr("Speed Limit Mode"), + tr("Speed Limit"), "", "", speed_limit_mode_texts, @@ -43,10 +43,12 @@ SpeedLimitSettings::SpeedLimitSettings(QWidget *parent) : QStackedWidget(parent) speedLimitSource = new PushButtonSP(tr("Customize Source")); connect(speedLimitSource, &QPushButton::clicked, [&]() { + speedLimitScroller->setLastScrollPosition(); setCurrentWidget(speedLimitPolicyScreen); speedLimitPolicyScreen->refresh(); }); connect(speedLimitPolicyScreen, &SpeedLimitPolicy::backPress, [&]() { + speedLimitScroller->restoreScrollPosition(); setCurrentWidget(subPanelFrame); showEvent(new QShowEvent()); }); @@ -92,7 +94,8 @@ SpeedLimitSettings::SpeedLimitSettings(QWidget *parent) : QStackedWidget(parent) connect(speed_limit_offset_settings, &ButtonParamControlSP::buttonClicked, this, &SpeedLimitSettings::refresh); refresh(); - subPanelLayout->addWidget(list); + speedLimitScroller = new ScrollViewSP(list, this); + subPanelLayout->addWidget(speedLimitScroller); addWidget(subPanelFrame); addWidget(speedLimitPolicyScreen); setCurrentWidget(subPanelFrame); diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h index f83f450557..61c86f9208 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h @@ -12,6 +12,7 @@ #include "selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_policy.h" #include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" class SpeedLimitSettings : public QStackedWidget { Q_OBJECT @@ -26,6 +27,7 @@ signals: private: Params params; + ScrollViewSP *speedLimitScroller; QFrame *subPanelFrame; ButtonParamControlSP *speed_limit_mode_settings; PushButtonSP *speedLimitSource; From 569a9216db77e650ec55a3062724d7c881cab60e Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 20 Sep 2025 17:36:13 -0400 Subject: [PATCH 098/159] ui: only draw speed limit offset when speed limit is valid (#1270) --- selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index 991710bbfa..6805422393 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -333,15 +333,16 @@ void HudRendererSP::drawStandstillTimer(QPainter &p, int x, int y) { } void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { + bool speedLimitValid = speedLimit > 0; int speedLimitRounded = std::nearbyint(speedLimit); bool overspeed = speedLimitRounded < std::nearbyint(speed) && speedLimitRounded > 0; bool speedLimitWarningEnabled = speedLimitMode == SpeedLimitMode::WARNING; - QString speedLimitStr = speedLimit > 0 ? QString::number(speedLimitRounded) : "---"; + QString speedLimitStr = speedLimitValid ? QString::number(speedLimitRounded) : "---"; // Offset display text QString speedLimitSubText = ""; if (speedLimitOffset != 0) { - speedLimitSubText = (speedLimitOffset > 0 ? "+" : "") + QString::number(std::nearbyint(speedLimitOffset)); + speedLimitSubText = (speedLimitOffset > 0 ? "+" : "-") + QString::number(std::nearbyint(speedLimitOffset)); } // Position next to MAX speed box @@ -392,7 +393,7 @@ void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { p.drawText(center_circle, Qt::AlignCenter, speedLimitStr); // Offset value in small circular box - if (!speedLimitSubText.isEmpty()) { + if (!speedLimitSubText.isEmpty() && speedLimitValid) { int offset_circle_size = circle_size * 0.4; int overlap = offset_circle_size * 0.25; QRect offset_circle_rect( @@ -437,7 +438,7 @@ void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { p.drawText(inner_rect.adjusted(0, 80, 0, 0), Qt::AlignTop | Qt::AlignHCenter, speedLimitStr); // Offset value in small box - if (!speedLimitSubText.isEmpty()) { + if (!speedLimitSubText.isEmpty() && speedLimitValid) { int offset_box_size = sign_rect.width() * 0.4; int overlap = offset_box_size * 0.25; QRect offset_box_rect( From 2efe78a4ef16aab116a26a673f7764f421d686d4 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 20 Sep 2025 17:48:13 -0400 Subject: [PATCH 099/159] ICBM: allow button commands at all speeds (#1271) * ICBM: allow button commands at all speeds * use openpilot state --- .../car/intelligent_cruise_button_management/controller.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py index 468e6f55b5..1f491e0f58 100644 --- a/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py +++ b/sunnypilot/selfdrive/car/intelligent_cruise_button_management/controller.py @@ -108,9 +108,7 @@ class IntelligentCruiseButtonManagement: def update_readiness(self, CS: car.CarState, CC: car.CarControl) -> None: update_manual_button_timers(CS, self.cruise_button_timers) - allowed_speed = CS.vEgo > ALLOWED_SPEED_THRESHOLD - ready = CS.cruiseState.enabled and allowed_speed and not CC.cruiseControl.override and not CC.cruiseControl.cancel and \ - not CC.cruiseControl.resume + ready = CC.enabled and not CC.cruiseControl.override and not CC.cruiseControl.cancel and not CC.cruiseControl.resume button_pressed = any(self.cruise_button_timers[k] > 0 for k in self.cruise_button_timers) self.is_ready = ready and not button_pressed From 563ae654438d49abf711d89410430b98836fe64b Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sun, 21 Sep 2025 00:33:43 -0400 Subject: [PATCH 100/159] ui: Road Name param should be persistent (#1273) --- common/params_keys.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/params_keys.h b/common/params_keys.h index 6d60e2cfdd..e9ffcfc1fd 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -224,7 +224,7 @@ inline static std::unordered_map keys = { {"OsmStateName", {PERSISTENT, STRING, "All"}}, {"OsmStateTitle", {PERSISTENT, STRING}}, {"OsmWayTest", {PERSISTENT, STRING}}, - {"RoadName", {CLEAR_ON_ONROAD_TRANSITION, STRING}}, + {"RoadName", {PERSISTENT, STRING}}, // Speed Limit {"SpeedLimitMode", {PERSISTENT | BACKUP, INT, "1"}}, From d5a873ed8617cefd691509c9cc5dc4ec7ea42ff4 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sun, 21 Sep 2025 02:53:03 -0400 Subject: [PATCH 101/159] ui: generic check with ICBM param (#1274) --- .../qt/offroad/settings/longitudinal_panel.cc | 10 ++++++---- .../qt/offroad/settings/longitudinal_panel.h | 3 ++- selfdrive/ui/sunnypilot/qt/util.cc | 4 ++++ selfdrive/ui/sunnypilot/qt/util.h | 1 + 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc index 205f64a0b2..8faa907a6d 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc @@ -80,6 +80,7 @@ void LongitudinalPanel::showEvent(QShowEvent *event) { } void LongitudinalPanel::refresh(bool _offroad) { + auto icbm_available = false; auto cp_bytes = params.get("CarParamsPersistent"); auto cp_sp_bytes = params.get("CarParamsSPPersistent"); if (!cp_bytes.empty() && !cp_sp_bytes.empty()) { @@ -92,11 +93,12 @@ void LongitudinalPanel::refresh(bool _offroad) { has_longitudinal_control = hasLongitudinalControl(CP); is_pcm_cruise = CP.getPcmCruise(); - intelligent_cruise_button_management_available = CP_SP.getIntelligentCruiseButtonManagementAvailable(); + icbm_available = CP_SP.getIntelligentCruiseButtonManagementAvailable(); + has_intelligent_cruise_button_management = hasIntelligentCruiseButtonManagement(CP_SP); } else { has_longitudinal_control = false; is_pcm_cruise = false; - intelligent_cruise_button_management_available = false; + has_intelligent_cruise_button_management = false; } QString accEnabledDescription = tr("Enable custom Short & Long press increments for cruise speed increase/decrease."); @@ -108,7 +110,7 @@ void LongitudinalPanel::refresh(bool _offroad) { customAccIncrement->setDescription(onroadOnlyDescription); customAccIncrement->showDescription(); } else { - if (has_longitudinal_control || intelligent_cruise_button_management_available) { + if (has_longitudinal_control || icbm_available) { if (is_pcm_cruise) { customAccIncrement->setDescription(accPcmCruiseDisabledDescription); customAccIncrement->showDescription(); @@ -125,7 +127,7 @@ void LongitudinalPanel::refresh(bool _offroad) { } } - bool icbm_allowed = intelligent_cruise_button_management_available && !has_longitudinal_control; + bool icbm_allowed = has_intelligent_cruise_button_management && !has_longitudinal_control; intelligentCruiseButtonManagement->setEnabled(icbm_allowed && offroad); // enable toggle when long is available and is not PCM cruise diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h index 8464150656..1e26ea22fc 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h @@ -7,6 +7,7 @@ #pragma once +#include "selfdrive/ui/sunnypilot/qt/util.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/custom_acc_increment.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" @@ -24,7 +25,7 @@ private: Params params; bool has_longitudinal_control = false; bool is_pcm_cruise = false; - bool intelligent_cruise_button_management_available = false;; + bool has_intelligent_cruise_button_management = false;; bool offroad = false; QStackedLayout *main_layout = nullptr; diff --git a/selfdrive/ui/sunnypilot/qt/util.cc b/selfdrive/ui/sunnypilot/qt/util.cc index 2e066e88b5..eaf05942a9 100644 --- a/selfdrive/ui/sunnypilot/qt/util.cc +++ b/selfdrive/ui/sunnypilot/qt/util.cc @@ -123,3 +123,7 @@ std::optional loadCerealEvent(Params& params, const std:: return std::nullopt; } } + +bool hasIntelligentCruiseButtonManagement(const cereal::CarParamsSP::Reader &car_params_sp) { + return car_params_sp.getIntelligentCruiseButtonManagementAvailable() && Params().getBool("IntelligentCruiseButtonManagement"); +} diff --git a/selfdrive/ui/sunnypilot/qt/util.h b/selfdrive/ui/sunnypilot/qt/util.h index 4b9d615ce5..60a73615ba 100644 --- a/selfdrive/ui/sunnypilot/qt/util.h +++ b/selfdrive/ui/sunnypilot/qt/util.h @@ -23,3 +23,4 @@ std::optional getParamIgnoringDefault(const std::string ¶m_name, co QMap loadPlatformList(); QStringList searchFromList(const QString &query, const QStringList &list); std::optional loadCerealEvent(Params& params, const std::string& _param); +bool hasIntelligentCruiseButtonManagement(const cereal::CarParamsSP::Reader &car_params_sp); From 2fa66d6f4d37a371e048dfc6ab1ad564ff004222 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Mon, 22 Sep 2025 01:35:13 -0400 Subject: [PATCH 102/159] ui: include Speed Limit Offset for Speed Limit Warning (#1276) * ui: include Speed Limit Offset for Speed Limit Warning * fix --- selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index 6805422393..db6ca1952b 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -335,7 +335,8 @@ void HudRendererSP::drawStandstillTimer(QPainter &p, int x, int y) { void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { bool speedLimitValid = speedLimit > 0; int speedLimitRounded = std::nearbyint(speedLimit); - bool overspeed = speedLimitRounded < std::nearbyint(speed) && speedLimitRounded > 0; + int speedLimitFinalRounded = std::nearbyint(speedLimit + speedLimitOffset); + bool overspeed = speedLimitFinalRounded < std::nearbyint(speed) && speedLimitRounded > 0; bool speedLimitWarningEnabled = speedLimitMode == SpeedLimitMode::WARNING; QString speedLimitStr = speedLimitValid ? QString::number(speedLimitRounded) : "---"; From 005c6aed95eee2c2896601ed2d7a51e81e14383e Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Mon, 22 Sep 2025 08:54:16 -0400 Subject: [PATCH 103/159] ui: separate road name toggle param and bigger fonts (#1277) * ui: separate road name toggle param and bigger fonts * slightly lower --- common/params_keys.h | 3 ++- selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc | 2 +- selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 4 ++-- selfdrive/ui/sunnypilot/ui.cc | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/common/params_keys.h b/common/params_keys.h index e9ffcfc1fd..32a7695b3b 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -224,7 +224,8 @@ inline static std::unordered_map keys = { {"OsmStateName", {PERSISTENT, STRING, "All"}}, {"OsmStateTitle", {PERSISTENT, STRING}}, {"OsmWayTest", {PERSISTENT, STRING}}, - {"RoadName", {PERSISTENT, STRING}}, + {"RoadName", {CLEAR_ON_ONROAD_TRANSITION, STRING}}, + {"RoadNameToggle", {PERSISTENT, STRING}}, // Speed Limit {"SpeedLimitMode", {PERSISTENT | BACKUP, INT, "1"}}, diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc index ca58282a3d..10ead53774 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc @@ -43,7 +43,7 @@ VisualsPanel::VisualsPanel(QWidget *parent) : QWidget(parent) { false, }, { - "RoadName", + "RoadNameToggle", tr("Display Road Name"), tr("Displays the name of the road the car is traveling on. The OpenStreetMap database of the location must be downloaded from the OSM panel to fetch the road name."), "", diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index db6ca1952b..9409612f47 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -528,7 +528,7 @@ void HudRendererSP::drawRoadName(QPainter &p, const QRect &surface_rect) { if (!roadName || roadNameStr.isEmpty()) return; // Measure text to size container - p.setFont(InterFont(40, QFont::Normal)); + p.setFont(InterFont(46, QFont::DemiBold)); QFontMetrics fm(p.font()); int text_width = fm.horizontalAdvance(roadNameStr); @@ -541,7 +541,7 @@ void HudRendererSP::drawRoadName(QPainter &p, const QRect &surface_rect) { rect_width = std::max(min_width, std::min(rect_width, max_width)); // Center at top of screen - QRect road_rect(surface_rect.width() / 2 - rect_width / 2, -6, rect_width, 60); + QRect road_rect(surface_rect.width() / 2 - rect_width / 2, -4, rect_width, 60); p.setPen(Qt::NoPen); p.setBrush(QColor(0, 0, 0, 120)); diff --git a/selfdrive/ui/sunnypilot/ui.cc b/selfdrive/ui/sunnypilot/ui.cc index 9acf844088..fd7365821c 100644 --- a/selfdrive/ui/sunnypilot/ui.cc +++ b/selfdrive/ui/sunnypilot/ui.cc @@ -54,7 +54,7 @@ void ui_update_params_sp(UIStateSP *s) { s->scene.dev_ui_info = std::atoi(params.get("DevUIInfo").c_str()); s->scene.standstill_timer = params.getBool("StandstillTimer"); s->scene.speed_limit_mode = std::atoi(params.get("SpeedLimitMode").c_str()); - s->scene.road_name = params.getBool("RoadName"); + s->scene.road_name = params.getBool("RoadNameToggle"); } DeviceSP::DeviceSP(QObject *parent) : Device(parent) { From b64d5a0fa4df9ea130056d91cfe68d20f6b4d208 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Mon, 22 Sep 2025 09:39:22 -0400 Subject: [PATCH 104/159] liveMapDataSP: parse bearing from GPS (#1279) * simpler approach pls * fix --- .../mapd/live_map_data/base_map_data.py | 22 +++---------------- sunnypilot/mapd/live_map_data/osm_map_data.py | 17 +++++++++++--- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/sunnypilot/mapd/live_map_data/base_map_data.py b/sunnypilot/mapd/live_map_data/base_map_data.py index 6c7679420a..f386eab96b 100644 --- a/sunnypilot/mapd/live_map_data/base_map_data.py +++ b/sunnypilot/mapd/live_map_data/base_map_data.py @@ -9,8 +9,7 @@ from abc import abstractmethod, ABC from cereal import messaging from openpilot.common.gps import get_gps_location_service from openpilot.common.params import Params -from openpilot.common.realtime import DT_MDL -from openpilot.sunnypilot.navd.helpers import Coordinate, coordinate_from_param +from openpilot.sunnypilot.navd.helpers import coordinate_from_param class BaseMapData(ABC): @@ -23,8 +22,8 @@ class BaseMapData(ABC): ignore_valid=gps_packets, poll='livePose') self.pm = messaging.PubMaster(['liveMapDataSP']) + self.last_bearing = None self.last_position = coordinate_from_param("LastGPSPosition", self.params) - self.last_altitude = None @abstractmethod def update_location(self) -> None: @@ -42,20 +41,6 @@ class BaseMapData(ABC): def get_current_road_name(self) -> str: pass - def get_current_location(self) -> None: - gps = self.sm[self.gps_location_service] - - # ignore the message if the fix is invalid - gps_ok = self.sm.recv_frame[self.gps_location_service] > 0 and (self.sm.frame - self.sm.recv_frame[self.gps_location_service]) * DT_MDL < 2.0 - if not gps_ok and self.sm['livePose'].inputsOK: - return - - # livePose has these data, but aren't on cereal - self.last_position = Coordinate(gps.latitude, gps.longitude) - self.last_altitude = gps.altitude - - return - def publish(self) -> None: speed_limit = self.get_current_speed_limit() next_speed_limit, next_speed_limit_distance = self.get_next_speed_limit_and_distance() @@ -74,7 +59,6 @@ class BaseMapData(ABC): self.pm.send('liveMapDataSP', mapd_sp_send) def tick(self) -> None: - self.sm.update() - self.get_current_location() + self.sm.update(0) self.update_location() self.publish() diff --git a/sunnypilot/mapd/live_map_data/osm_map_data.py b/sunnypilot/mapd/live_map_data/osm_map_data.py index 1eaf76dc8d..c5187a8e04 100644 --- a/sunnypilot/mapd/live_map_data/osm_map_data.py +++ b/sunnypilot/mapd/live_map_data/osm_map_data.py @@ -5,9 +5,11 @@ This file is part of sunnypilot and is licensed under the MIT License. See the LICENSE.md file in the root directory for more details. """ import json +import math import platform from openpilot.common.params import Params +from openpilot.common.realtime import DT_MDL from openpilot.sunnypilot.mapd.live_map_data.base_map_data import BaseMapData from openpilot.sunnypilot.navd.helpers import Coordinate @@ -15,17 +17,26 @@ from openpilot.sunnypilot.navd.helpers import Coordinate class OsmMapData(BaseMapData): def __init__(self): super().__init__() - self.params = Params() self.mem_params = Params("/dev/shm/params") if platform.system() != "Darwin" else self.params def update_location(self) -> None: - if self.last_position is None or self.last_altitude is None: + gps = self.sm[self.gps_location_service] + gps_ok = self.sm.recv_frame[self.gps_location_service] > 0 and (self.sm.frame - self.sm.recv_frame[self.gps_location_service]) * DT_MDL < 2.0 + + if gps_ok: + self.last_bearing = gps.bearingDeg * 180/math.pi + self.last_position = Coordinate(gps.latitude, gps.longitude) + + if not gps_ok and self.sm['livePose'].inputsOK: + return + + if self.last_position is None: return params = { "latitude": self.last_position.latitude, "longitude": self.last_position.longitude, - "altitude": self.last_altitude, + "bearing": self.last_bearing, } self.mem_params.put("LastGPSPosition", json.dumps(params)) From 01a0ad496d7c78daafb2ff65f9fe17b6c221a1c6 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Mon, 22 Sep 2025 19:50:59 -0400 Subject: [PATCH 105/159] ui: more speed limit improvements (#1278) * ui: more speed limit improvements - show speed limit offset with last valid speed limit - show last valid speed limit if current speed limit is not valid * rename * round it * update logic * in its own var and 5 frames now * new offset vals * slightly more * apply suggestions --- selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 38 ++++++++++++++++-------- selfdrive/ui/sunnypilot/qt/onroad/hud.h | 5 ++++ 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index 9409612f47..33462e6202 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -31,6 +31,8 @@ void HudRendererSP::updateState(const UIState &s) { float speedConv = is_metric ? MS_TO_KPH : MS_TO_MPH; speedLimit = lp_sp.getSpeedLimit().getResolver().getSpeedLimit() * speedConv; speedLimitOffset = lp_sp.getSpeedLimit().getResolver().getSpeedLimitOffset() * speedConv; + speedLimitValid = speedLimit > 0; + speedLimitLastValid = speedLimitLast > 0; speedLimitMode = static_cast(s.scene.speed_limit_mode); roadName = s.scene.road_name; if (sm.updated("liveMapDataSP")) { @@ -38,7 +40,7 @@ void HudRendererSP::updateState(const UIState &s) { speedLimitAheadValid = lmd.getSpeedLimitAheadValid(); speedLimitAhead = lmd.getSpeedLimitAhead() * speedConv; speedLimitAheadDistance = lmd.getSpeedLimitAheadDistance(); - if (speedLimitAheadDistance < speedLimitAheadDistancePrev && speedLimitAheadValidFrame < 2) { + if (speedLimitAheadDistance < speedLimitAheadDistancePrev && speedLimitAheadValidFrame < SPEED_LIMIT_AHEAD_VALID_FRAME_THRESHOLD) { speedLimitAheadValidFrame++; } else if (speedLimitAheadDistance > speedLimitAheadDistancePrev && speedLimitAheadValidFrame > 0) { speedLimitAheadValidFrame--; @@ -46,6 +48,10 @@ void HudRendererSP::updateState(const UIState &s) { } speedLimitAheadDistancePrev = speedLimitAheadDistance; + if (speedLimitValid) { + speedLimitLast = speedLimit; + } + static int reverse_delay = 0; bool reverse_allowed = false; if (int(car_state.getGearShifter()) != 4) { @@ -333,17 +339,22 @@ void HudRendererSP::drawStandstillTimer(QPainter &p, int x, int y) { } void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { - bool speedLimitValid = speedLimit > 0; - int speedLimitRounded = std::nearbyint(speedLimit); - int speedLimitFinalRounded = std::nearbyint(speedLimit + speedLimitOffset); - bool overspeed = speedLimitFinalRounded < std::nearbyint(speed) && speedLimitRounded > 0; - bool speedLimitWarningEnabled = speedLimitMode == SpeedLimitMode::WARNING; - QString speedLimitStr = speedLimitValid ? QString::number(speedLimitRounded) : "---"; + bool hasSpeedLimit = speedLimitValid || speedLimitLastValid; + int speedLimitFinal = std::nearbyint(speedLimitValid ? speedLimit : speedLimitLast); + int speedLimitOffsetFinal = speedLimitFinal + std::nearbyint(speedLimitOffset); + bool overspeed = hasSpeedLimit && speedLimitOffsetFinal < std::nearbyint(speed); + bool speedLimitWarningEnabled = speedLimitMode == SpeedLimitMode::WARNING; // TODO-SP: update to include SpeedLimitMode::ASSIST + QString speedLimitStr = hasSpeedLimit ? QString::number(speedLimitFinal) : "---"; // Offset display text QString speedLimitSubText = ""; if (speedLimitOffset != 0) { - speedLimitSubText = (speedLimitOffset > 0 ? "+" : "-") + QString::number(std::nearbyint(speedLimitOffset)); + speedLimitSubText = (speedLimitOffset > 0 ? "" : "-") + QString::number(std::nearbyint(speedLimitOffset)); + } + + float speedLimitSubTextFactor = is_metric ? 0.5 : 0.6; + if (speedLimitSubText.size() >= 3) { + speedLimitSubTextFactor = 0.475; } // Position next to MAX speed box @@ -355,7 +366,8 @@ void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { int alpha = 255; QColor red_color = QColor(255, 0, 0, alpha); - QColor speed_color = (speedLimitWarningEnabled && overspeed) ? red_color : QColor(0, 0, 0, alpha); + QColor speed_color = (speedLimitWarningEnabled && overspeed) ? red_color : + (!speedLimitValid && speedLimitLastValid ? QColor(0x91, 0x9b, 0x95, 0xf1) : QColor(0, 0, 0, alpha)); if (is_metric) { // EU Vienna Convention style circular sign @@ -394,7 +406,7 @@ void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { p.drawText(center_circle, Qt::AlignCenter, speedLimitStr); // Offset value in small circular box - if (!speedLimitSubText.isEmpty() && speedLimitValid) { + if (!speedLimitSubText.isEmpty() && hasSpeedLimit) { int offset_circle_size = circle_size * 0.4; int overlap = offset_circle_size * 0.25; QRect offset_circle_rect( @@ -408,7 +420,7 @@ void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { p.setBrush(QColor(0, 0, 0, alpha)); p.drawEllipse(offset_circle_rect); - p.setFont(InterFont(offset_circle_size * 0.45, QFont::Bold)); + p.setFont(InterFont(offset_circle_size * speedLimitSubTextFactor, QFont::Bold)); p.setPen(QColor(255, 255, 255, alpha)); p.drawText(offset_circle_rect, Qt::AlignCenter, speedLimitSubText); } @@ -439,7 +451,7 @@ void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { p.drawText(inner_rect.adjusted(0, 80, 0, 0), Qt::AlignTop | Qt::AlignHCenter, speedLimitStr); // Offset value in small box - if (!speedLimitSubText.isEmpty() && speedLimitValid) { + if (!speedLimitSubText.isEmpty() && hasSpeedLimit) { int offset_box_size = sign_rect.width() * 0.4; int overlap = offset_box_size * 0.25; QRect offset_box_rect( @@ -454,7 +466,7 @@ void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { p.setBrush(QColor(0, 0, 0, alpha)); p.drawRoundedRect(offset_box_rect, corner_radius, corner_radius); - p.setFont(InterFont(offset_box_size * 0.45, QFont::Bold)); + p.setFont(InterFont(offset_box_size * speedLimitSubTextFactor, QFont::Bold)); p.setPen(QColor(255, 255, 255, alpha)); p.drawText(offset_box_rect, Qt::AlignCenter, speedLimitSubText); } diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.h b/selfdrive/ui/sunnypilot/qt/onroad/hud.h index 073780bc10..bae1c3b718 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.h +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.h @@ -11,6 +11,8 @@ #include "selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h" #include "selfdrive/ui/sunnypilot/qt/onroad/developer_ui/developer_ui.h" +constexpr int SPEED_LIMIT_AHEAD_VALID_FRAME_THRESHOLD = 5; + class HudRendererSP : public HudRenderer { Q_OBJECT @@ -68,7 +70,10 @@ private: bool smartCruiseControlVisionActive; int smartCruiseControlVisionFrame; float speedLimit; + float speedLimitLast; float speedLimitOffset; + bool speedLimitValid; + bool speedLimitLastValid; bool speedLimitAheadValid; float speedLimitAhead; float speedLimitAheadDistance; From ea6178e53ee291c51574c0a6b7eb441637ae6b12 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Mon, 22 Sep 2025 22:54:45 -0400 Subject: [PATCH 106/159] Smart Cruise Control: Map (SCC-M) (#1280) * init * more * a bit more * expose * bruh * some fixes * ui * lint * Update map_controller.py * add overriding * draw in orders --- cereal/custom.capnp | 17 ++ common/params_keys.h | 6 +- .../qt/offroad/settings/longitudinal_panel.cc | 8 + .../qt/offroad/settings/longitudinal_panel.h | 1 + selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 24 +- selfdrive/ui/sunnypilot/qt/onroad/hud.h | 3 + .../controls/lib/longitudinal_planner.py | 12 +- .../lib/smart_cruise_control/__init__.py | 9 + .../smart_cruise_control/map_controller.py | 261 ++++++++++++++++++ .../smart_cruise_control.py | 3 + .../tests/test_map_controller.py | 58 ++++ .../smart_cruise_control/vision_controller.py | 8 +- 12 files changed, 396 insertions(+), 14 deletions(-) create mode 100644 sunnypilot/selfdrive/controls/lib/smart_cruise_control/map_controller.py create mode 100644 sunnypilot/selfdrive/controls/lib/smart_cruise_control/tests/test_map_controller.py diff --git a/cereal/custom.capnp b/cereal/custom.capnp index c4360ae311..854988decf 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -162,6 +162,7 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { struct SmartCruiseControl { vision @0 :Vision; + map @1 :Map; struct Vision { state @0 :VisionState; @@ -173,6 +174,14 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { active @6 :Bool; } + struct Map { + state @0 :MapState; + vTarget @1 :Float32; + aTarget @2 :Float32; + enabled @3 :Bool; + active @4 :Bool; + } + enum VisionState { disabled @0; # System disabled or inactive. enabled @1; # No predicted substantial turn on vision range. @@ -181,6 +190,13 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { leaving @4; # Road ahead straightens. Start to allow positive acceleration. overriding @5; # System overriding with manual control. } + + enum MapState { + disabled @0; # System disabled or inactive. + enabled @1; # No predicted substantial turn on map range. + turning @2; # Actively turning. Managing acceleration to provide a roll on turn feeling. + overriding @3; # System overriding with manual control. + } } struct SpeedLimit { @@ -203,6 +219,7 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { enum LongitudinalPlanSource { cruise @0; sccVision @1; + sccMap @2; } } diff --git a/common/params_keys.h b/common/params_keys.h index 32a7695b3b..3faae9ce14 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -160,7 +160,6 @@ inline static std::unordered_map keys = { {"QuietMode", {PERSISTENT | BACKUP, BOOL, "0"}}, {"RainbowMode", {PERSISTENT | BACKUP, BOOL, "0"}}, {"ShowAdvancedControls", {PERSISTENT | BACKUP, BOOL, "0"}}, - {"SmartCruiseControlVision", {PERSISTENT | BACKUP, BOOL, "0"}}, {"StandstillTimer", {PERSISTENT | BACKUP, BOOL, "0"}}, // MADS params @@ -232,4 +231,9 @@ inline static std::unordered_map keys = { {"SpeedLimitOffsetType", {PERSISTENT | BACKUP, INT, "0"}}, {"SpeedLimitPolicy", {PERSISTENT | BACKUP, INT, "3"}}, {"SpeedLimitValueOffset", {PERSISTENT | BACKUP, INT, "0"}}, + + // Smart Cruise Control + {"MapTargetVelocities", {CLEAR_ON_ONROAD_TRANSITION, STRING}}, + {"SmartCruiseControlMap", {PERSISTENT | BACKUP, BOOL, "0"}}, + {"SmartCruiseControlVision", {PERSISTENT | BACKUP, BOOL, "0"}}, }; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc index 8faa907a6d..8987f38514 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc @@ -50,6 +50,13 @@ LongitudinalPanel::LongitudinalPanel(QWidget *parent) : QWidget(parent) { ""); list->addItem(SmartCruiseControlVision); + SmartCruiseControlMap = new ParamControl( + "SmartCruiseControlMap", + tr("Smart Cruise Control - Map"), + tr("Use map data to estimate the appropriate speed to drive through turns ahead."), + ""); + list->addItem(SmartCruiseControlMap); + customAccIncrement = new CustomAccIncrement("CustomAccIncrementsEnabled", tr("Custom ACC Speed Increments"), "", "", this); list->addItem(customAccIncrement); @@ -136,6 +143,7 @@ void LongitudinalPanel::refresh(bool _offroad) { customAccIncrement->refresh(); SmartCruiseControlVision->setEnabled(has_longitudinal_control || icbm_allowed); + SmartCruiseControlMap->setEnabled(has_longitudinal_control || icbm_allowed); offroad = _offroad; } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h index 1e26ea22fc..2fd15e955c 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h @@ -33,6 +33,7 @@ private: QWidget *cruisePanelScreen = nullptr; CustomAccIncrement *customAccIncrement = nullptr; ParamControl *SmartCruiseControlVision; + ParamControl *SmartCruiseControlMap; ParamControl *intelligentCruiseButtonManagement = nullptr; SpeedLimitSettings *speedLimitScreen; PushButtonSP *speedLimitSettings; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index 33462e6202..6da6baef3d 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -100,6 +100,8 @@ void HudRendererSP::updateState(const UIState &s) { longOverride = car_control.getCruiseControl().getOverride(); smartCruiseControlVisionEnabled = lp_sp.getSmartCruiseControl().getVision().getEnabled(); smartCruiseControlVisionActive = lp_sp.getSmartCruiseControl().getVision().getActive(); + smartCruiseControlMapEnabled = lp_sp.getSmartCruiseControl().getMap().getEnabled(); + smartCruiseControlMapActive = lp_sp.getSmartCruiseControl().getMap().getActive(); } void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { @@ -108,18 +110,28 @@ void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { // Smart Cruise Control int x_offset = -260; int y1_offset = -80; - // int y2_offset = -140; // reserved for 2 icons + int y2_offset = -140; + int y_scc_v = 0, y_scc_m = 0; + const int orders[2] = {y1_offset, y2_offset}; + int i = 0; + // SCC-V takes first order + if (smartCruiseControlVisionEnabled) y_scc_v = orders[i++]; + if (smartCruiseControlMapEnabled) y_scc_m = orders[i++]; + + // Smart Cruise Control - Vision bool scc_vision_active_pulse = pulseElement(smartCruiseControlVisionFrame); if ((smartCruiseControlVisionEnabled && !smartCruiseControlVisionActive) || (smartCruiseControlVisionActive && scc_vision_active_pulse)) { - drawSmartCruiseControlOnroadIcon(p, surface_rect, x_offset, y1_offset, "SCC-V"); + drawSmartCruiseControlOnroadIcon(p, surface_rect, x_offset, y_scc_v, "SCC-V"); } + smartCruiseControlVisionFrame = smartCruiseControlVisionActive ? (smartCruiseControlVisionFrame + 1) : 0; - if (smartCruiseControlVisionActive) { - smartCruiseControlVisionFrame++; - } else { - smartCruiseControlVisionFrame = 0; + // Smart Cruise Control - Map + bool scc_map_active_pulse = pulseElement(smartCruiseControlMapFrame); + if ((smartCruiseControlMapEnabled && !smartCruiseControlMapActive) || (smartCruiseControlMapActive && scc_map_active_pulse)) { + drawSmartCruiseControlOnroadIcon(p, surface_rect, x_offset, y_scc_m, "SCC-M"); } + smartCruiseControlMapFrame = smartCruiseControlMapActive ? (smartCruiseControlMapFrame + 1) : 0; // Bottom Dev UI if (devUiInfo == 2) { diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.h b/selfdrive/ui/sunnypilot/qt/onroad/hud.h index bae1c3b718..1e153f1548 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.h +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.h @@ -69,6 +69,9 @@ private: bool smartCruiseControlVisionEnabled; bool smartCruiseControlVisionActive; int smartCruiseControlVisionFrame; + bool smartCruiseControlMapEnabled; + bool smartCruiseControlMapActive; + int smartCruiseControlMapFrame; float speedLimit; float speedLimitLast; float speedLimitOffset; diff --git a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py index 3e4dbd9ab2..af5f5dbd7d 100644 --- a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py +++ b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py @@ -46,7 +46,8 @@ class LongitudinalPlannerSP: targets = { Source.cruise: (v_cruise, a_ego), - Source.sccVision: (self.scc.vision.output_v_target, self.scc.vision.output_a_target) + Source.sccVision: (self.scc.vision.output_v_target, self.scc.vision.output_a_target), + Source.sccMap: (self.scc.map.output_v_target, self.scc.map.output_a_target), } self.source = min(targets, key=lambda k: targets[k][0]) @@ -74,7 +75,7 @@ class LongitudinalPlannerSP: # Smart Cruise Control smartCruiseControl = longitudinalPlanSP.smartCruiseControl - # Vision Turn Speed Control + # Vision Control sccVision = smartCruiseControl.vision sccVision.state = self.scc.vision.state sccVision.vTarget = float(self.scc.vision.output_v_target) @@ -83,6 +84,13 @@ class LongitudinalPlannerSP: sccVision.maxPredictedLateralAccel = float(self.scc.vision.max_pred_lat_acc) sccVision.enabled = self.scc.vision.is_enabled sccVision.active = self.scc.vision.is_active + # Map Control + sccMap = smartCruiseControl.map + sccMap.state = self.scc.map.state + sccMap.vTarget = float(self.scc.map.output_v_target) + sccMap.aTarget = float(self.scc.map.output_a_target) + sccMap.enabled = self.scc.map.is_enabled + sccMap.active = self.scc.map.is_active # Speed Limit speedLimit = longitudinalPlanSP.speedLimit diff --git a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/__init__.py b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/__init__.py index e69de29bb2..271f49dcc2 100644 --- a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/__init__.py +++ b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/__init__.py @@ -0,0 +1,9 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" +from openpilot.common.constants import CV + +MIN_V = 20 * CV.KPH_TO_MS # Do not operate under 20 km/h diff --git a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/map_controller.py b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/map_controller.py new file mode 100644 index 0000000000..cd45870ef6 --- /dev/null +++ b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/map_controller.py @@ -0,0 +1,261 @@ +import json +import math +import platform + +from cereal import custom +from openpilot.common.params import Params +from openpilot.common.realtime import DT_MDL +from openpilot.selfdrive.car.cruise import V_CRUISE_UNSET +from openpilot.sunnypilot import PARAMS_UPDATE_PERIOD +from openpilot.sunnypilot.navd.helpers import coordinate_from_param, Coordinate +from openpilot.sunnypilot.selfdrive.controls.lib.smart_cruise_control import MIN_V + +MapState = VisionState = custom.LongitudinalPlanSP.SmartCruiseControl.MapState + +ACTIVE_STATES = (MapState.turning, MapState.overriding) +ENABLED_STATES = (MapState.enabled, *ACTIVE_STATES) + +R = 6373000.0 # approximate radius of earth in meters +TO_RADIANS = math.pi / 180 +TO_DEGREES = 180 / math.pi +TARGET_JERK = -0.6 # m/s^3 There's some jounce limits that are not consistent so we're fudging this some +TARGET_ACCEL = -1.2 # m/s^2 should match up with the long planner limit +TARGET_OFFSET = 1.0 # seconds - This controls how soon before the curve you reach the target velocity. It also helps + # reach the target velocity when inaccuracies in the distance modeling logic would cause overshoot. + # The value is multiplied against the target velocity to determine the additional distance. This is + # done to keep the distance calculations consistent but results in the offset actually being less + # time than specified depending on how much of a speed differential there is between v_ego and the + # target velocity. + + +def velocities_from_param(param: str, params: Params): + if params is None: + params = Params() + + json_str = params.get(param) + if json_str is None: + return None + + velocities = json.loads(json_str) + + return velocities + + +def calculate_accel(t, target_jerk, a_ego): + return a_ego + target_jerk * t + + +def calculate_velocity(t, target_jerk, a_ego, v_ego): + return v_ego + a_ego * t + target_jerk/2 * (t ** 2) + + +def calculate_distance(t, target_jerk, a_ego, v_ego): + return t * v_ego + a_ego/2 * (t ** 2) + target_jerk/6 * (t ** 3) + + +# points should be in radians +# output is meters +def distance_to_point(ax, ay, bx, by): + a = math.sin((bx-ax)/2)*math.sin((bx-ax)/2) + math.cos(ax) * math.cos(bx)*math.sin((by-ay)/2)*math.sin((by-ay)/2) + c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a)) + + return R * c # in meters + + +class SmartCruiseControlMap: + v_target: float = 0 + a_target: float = 0. + v_ego: float = 0. + a_ego: float = 0. + output_v_target: float = V_CRUISE_UNSET + output_a_target: float = 0. + + def __init__(self): + self.params = Params() + self.mem_params = Params("/dev/shm/params") if platform.system() != "Darwin" else self.params + self.enabled = self.params.get_bool("SmartCruiseControlMap") + self.long_enabled = False + self.long_override = False + self.is_enabled = False + self.is_active = False + self.state = MapState.disabled + self.v_cruise = 0 + self.target_lat = 0.0 + self.target_lon = 0.0 + self.frame = -1 + + self.last_position = coordinate_from_param("LastGPSPosition", self.mem_params) or Coordinate(0.0, 0.0) + self.target_velocities = velocities_from_param("MapTargetVelocities", self.mem_params) or [] + + def get_v_target_from_control(self) -> float: + if self.is_active: + return max(self.v_target, MIN_V) + + return V_CRUISE_UNSET + + def get_a_target_from_control(self) -> float: + return self.a_ego + + def update_params(self): + if self.frame % int(PARAMS_UPDATE_PERIOD / DT_MDL) == 0: + self.enabled = self.params.get_bool("SmartCruiseControlMap") + + def update_calculations(self) -> None: + self.last_position = coordinate_from_param("LastGPSPosition", self.mem_params) or Coordinate(0.0, 0.0) + lat = self.last_position.latitude + lon = self.last_position.longitude + + self.target_velocities = velocities_from_param("MapTargetVelocities", self.mem_params) or [] + + if self.last_position is None or self.target_velocities is None: + return + + min_dist = 1000 + min_idx = 0 + distances = [] + + # find our location in the path + for i in range(len(self.target_velocities)): + target_velocity = self.target_velocities[i] + tlat = target_velocity["latitude"] + tlon = target_velocity["longitude"] + d = distance_to_point(lat * TO_RADIANS, lon * TO_RADIANS, tlat * TO_RADIANS, tlon * TO_RADIANS) + distances.append(d) + if d < min_dist: + min_dist = d + min_idx = i + + # only look at values from our current position forward + forward_points = self.target_velocities[min_idx:] + forward_distances = distances[min_idx:] + + # find velocities that we are within the distance we need to adjust for + valid_velocities = [] + for i in range(len(forward_points)): + target_velocity = forward_points[i] + tlat = target_velocity["latitude"] + tlon = target_velocity["longitude"] + tv = target_velocity["velocity"] + if tv > self.v_ego: + continue + + d = forward_distances[i] + + a_diff = (self.a_ego - TARGET_ACCEL) + accel_t = abs(a_diff / TARGET_JERK) + min_accel_v = calculate_velocity(accel_t, TARGET_JERK, self.a_ego, self.v_ego) + + max_d = 0 + if tv > min_accel_v: + # calculate time needed based on target jerk + a = 0.5 * TARGET_JERK + b = self.a_ego + c = self.v_ego - tv + t_a = -1 * ((b**2 - 4 * a * c) ** 0.5 + b) / 2 * a + t_b = ((b**2 - 4 * a * c) ** 0.5 - b) / 2 * a + if not isinstance(t_a, complex) and t_a > 0: + t = t_a + else: + t = t_b + if isinstance(t, complex): + continue + + max_d = max_d + calculate_distance(t, TARGET_JERK, self.a_ego, self.v_ego) + else: + t = accel_t + max_d = calculate_distance(t, TARGET_JERK, self.a_ego, self.v_ego) + + # calculate additional time needed based on target accel + t = abs((min_accel_v - tv) / TARGET_ACCEL) + max_d += calculate_distance(t, 0, TARGET_ACCEL, min_accel_v) + + if d < max_d + tv * TARGET_OFFSET: + valid_velocities.append((float(tv), tlat, tlon)) + + # Find the smallest velocity we need to adjust for + min_v = 100.0 + target_lat = 0.0 + target_lon = 0.0 + for tv, lat, lon in valid_velocities: + if tv < min_v: + min_v = tv + target_lat = lat + target_lon = lon + + if self.v_target < min_v and not (self.target_lat == 0 and self.target_lon == 0): + for i in range(len(forward_points)): + target_velocity = forward_points[i] + tlat = target_velocity["latitude"] + tlon = target_velocity["longitude"] + tv = target_velocity["velocity"] + if tv > self.v_ego: + continue + + if tlat == self.target_lat and tlon == self.target_lon and tv == self.v_target: + return + + # not found so let's reset + self.v_target = 0.0 + self.target_lat = 0.0 + self.target_lon = 0.0 + + self.v_target = min_v + self.target_lat = target_lat + self.target_lon = target_lon + + def _update_state_machine(self) -> tuple[bool, bool]: + # ENABLED, TURNING + if self.state != MapState.disabled: + if not self.long_enabled or not self.enabled: + self.state = MapState.disabled + elif self.long_override: + self.state = MapState.overriding + + else: + # ENABLED + if self.state == MapState.enabled: + if self.v_cruise > self.v_target != 0: + self.state = MapState.turning + + # TURNING + elif self.state == MapState.turning: + if self.v_cruise <= self.v_target or self.v_target == 0: + self.state = MapState.enabled + + # OVERRIDING + elif self.state == MapState.overriding: + if not self.long_override: + if self.v_cruise > self.v_target != 0: + self.state = MapState.turning + else: + self.state = MapState.enabled + + # DISABLED + elif self.state == MapState.disabled: + if self.long_enabled and self.enabled: + if self.long_override: + self.state = MapState.overriding + else: + self.state = MapState.enabled + + enabled = self.state in ENABLED_STATES + active = self.state in ACTIVE_STATES + + return enabled, active + + def update(self, long_enabled: bool, long_override: bool, v_ego, a_ego, v_cruise) -> None: + self.long_enabled = long_enabled + self.long_override = long_override + self.v_ego = v_ego + self.a_ego = a_ego + self.v_cruise = v_cruise + + self.update_params() + self.update_calculations() + + self.is_enabled, self.is_active = self._update_state_machine() + + self.output_v_target = self.get_v_target_from_control() + self.output_a_target = self.get_a_target_from_control() + + self.frame += 1 diff --git a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/smart_cruise_control.py b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/smart_cruise_control.py index c66c2c392a..0f60621658 100644 --- a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/smart_cruise_control.py +++ b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/smart_cruise_control.py @@ -6,14 +6,17 @@ See the LICENSE.md file in the root directory for more details. """ import cereal.messaging as messaging from openpilot.sunnypilot.selfdrive.controls.lib.smart_cruise_control.vision_controller import SmartCruiseControlVision +from openpilot.sunnypilot.selfdrive.controls.lib.smart_cruise_control.map_controller import SmartCruiseControlMap class SmartCruiseControl: def __init__(self): self.vision = SmartCruiseControlVision() + self.map = SmartCruiseControlMap() def update(self, sm: messaging.SubMaster, v_ego: float, a_ego: float, v_cruise: float) -> None: long_enabled = sm['carControl'].enabled long_override = sm['carControl'].cruiseControl.override + self.map.update(long_enabled, long_override, v_ego, a_ego, v_cruise) self.vision.update(sm, long_enabled, long_override, v_ego, a_ego, v_cruise) diff --git a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/tests/test_map_controller.py b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/tests/test_map_controller.py new file mode 100644 index 0000000000..537f0033f0 --- /dev/null +++ b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/tests/test_map_controller.py @@ -0,0 +1,58 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" +import platform + +from cereal import custom +from openpilot.common.params import Params +from openpilot.common.realtime import DT_MDL +from openpilot.selfdrive.car.cruise import V_CRUISE_UNSET +from openpilot.sunnypilot.selfdrive.controls.lib.smart_cruise_control.map_controller import SmartCruiseControlMap + +MapState = VisionState = custom.LongitudinalPlanSP.SmartCruiseControl.MapState + + +class TestSmartCruiseControlMap: + + def setup_method(self): + self.params = Params() + self.mem_params = Params("/dev/shm/params") if platform.system() != "Darwin" else self.params + self.reset_params() + self.scc_m = SmartCruiseControlMap() + + def reset_params(self): + self.params.put_bool("SmartCruiseControlMap", True) + + # TODO-SP: mock data from gpsLocation + self.params.put("LastGPSPosition", "{}") + self.params.put("MapTargetVelocities", "{}") + + def test_initial_state(self): + assert self.scc_m.state == VisionState.disabled + assert not self.scc_m.is_active + assert self.scc_m.output_v_target == V_CRUISE_UNSET + assert self.scc_m.output_a_target == 0. + + def test_system_disabled(self): + self.params.put_bool("SmartCruiseControlMap", False) + self.scc_m.enabled = self.params.get_bool("SmartCruiseControlMap") + + for _ in range(int(10. / DT_MDL)): + self.scc_m.update(True, False, 0., 0., 0.) + assert self.scc_m.state == VisionState.disabled + assert not self.scc_m.is_active + + def test_disabled(self): + for _ in range(int(10. / DT_MDL)): + self.scc_m.update(False, False, 0., 0., 0.) + assert self.scc_m.state == VisionState.disabled + + def test_transition_disabled_to_enabled(self): + for _ in range(int(10. / DT_MDL)): + self.scc_m.update(True, False, 0., 0., 0.) + assert self.scc_m.state == VisionState.enabled + + # TODO-SP: mock data from modelV2 to test other states diff --git a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/vision_controller.py b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/vision_controller.py index 491b179039..d144178e93 100644 --- a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/vision_controller.py +++ b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/vision_controller.py @@ -8,19 +8,17 @@ import numpy as np import cereal.messaging as messaging from cereal import custom -from openpilot.common.constants import CV from openpilot.common.params import Params from openpilot.common.realtime import DT_MDL from openpilot.selfdrive.car.cruise import V_CRUISE_UNSET from openpilot.sunnypilot import PARAMS_UPDATE_PERIOD +from openpilot.sunnypilot.selfdrive.controls.lib.smart_cruise_control import MIN_V VisionState = custom.LongitudinalPlanSP.SmartCruiseControl.VisionState ACTIVE_STATES = (VisionState.entering, VisionState.turning, VisionState.leaving) ENABLED_STATES = (VisionState.enabled, VisionState.overriding, *ACTIVE_STATES) -_MIN_V = 20 * CV.KPH_TO_MS # Do not operate under 20 km/h - _ENTERING_PRED_LAT_ACC_TH = 1.3 # Predicted Lat Acc threshold to trigger entering turn state. _ABORT_ENTERING_PRED_LAT_ACC_TH = 1.1 # Predicted Lat Acc threshold to abort entering state if speed drops. @@ -73,7 +71,7 @@ class SmartCruiseControlVision: def get_v_target_from_control(self) -> float: if self.is_active: - return max(self.v_target, _MIN_V) + self.a_target * _NO_OVERSHOOT_TIME_HORIZON + return max(self.v_target, MIN_V) + self.a_target * _NO_OVERSHOOT_TIME_HORIZON return V_CRUISE_UNSET @@ -114,7 +112,7 @@ class SmartCruiseControlVision: # ENABLED if self.state == VisionState.enabled: # Do not enter a turn control cycle if the speed is low. - if self.v_ego <= _MIN_V: + if self.v_ego <= MIN_V: pass # If significant lateral acceleration is predicted ahead, then move to Entering turn state. elif self.max_pred_lat_acc >= _ENTERING_PRED_LAT_ACC_TH: From ecee67dd64b04eb06b32f6b9abae37afe63f8b99 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Mon, 22 Sep 2025 23:39:55 -0400 Subject: [PATCH 107/159] Locationd: reimplement `liveLocationKalman` and use position_geodetic in `liveMapDataSP` (#1275) * init * desc * llk welcome back * more * new param to write * update mapd * no migration * no refactor for now * exec * rename * bearing * fix test * lint --- cereal/log.capnp | 2 +- cereal/services.py | 1 + common/params_keys.h | 1 + selfdrive/test/process_replay/migration.py | 6 +- .../test/process_replay/process_replay.py | 2 +- sunnypilot/SConscript | 3 +- .../mapd/live_map_data/base_map_data.py | 13 +- sunnypilot/mapd/live_map_data/osm_map_data.py | 19 +- sunnypilot/selfdrive/locationd/.gitignore | 3 + sunnypilot/selfdrive/locationd/SConscript | 37 + sunnypilot/selfdrive/locationd/__init__.py | 0 sunnypilot/selfdrive/locationd/locationd.cc | 750 ++++++++++++++++++ sunnypilot/selfdrive/locationd/locationd.h | 100 +++ .../selfdrive/locationd/models/.gitignore | 1 + .../selfdrive/locationd/models/__init__.py | 0 .../selfdrive/locationd/models/car_kf.py | 180 +++++ .../selfdrive/locationd/models/constants.py | 92 +++ .../selfdrive/locationd/models/live_kf.cc | 122 +++ .../selfdrive/locationd/models/live_kf.h | 66 ++ .../selfdrive/locationd/models/live_kf.py | 242 ++++++ .../selfdrive/locationd/tests/.gitignore | 1 + .../selfdrive/locationd/tests/__init__.py | 0 .../locationd/tests/test_locationd.py | 89 +++ sunnypilot/system/sensord/.gitignore | 1 + sunnypilot/system/sensord/SConscript | 13 + .../system/sensord/sensors/bmx055_accel.cc | 85 ++ .../system/sensord/sensors/bmx055_accel.h | 41 + .../system/sensord/sensors/bmx055_gyro.cc | 92 +++ .../system/sensord/sensors/bmx055_gyro.h | 41 + .../system/sensord/sensors/bmx055_magn.cc | 258 ++++++ .../system/sensord/sensors/bmx055_magn.h | 64 ++ .../system/sensord/sensors/bmx055_temp.cc | 31 + .../system/sensord/sensors/bmx055_temp.h | 13 + sunnypilot/system/sensord/sensors/constants.h | 18 + .../system/sensord/sensors/i2c_sensor.cc | 50 ++ .../system/sensord/sensors/i2c_sensor.h | 51 ++ .../system/sensord/sensors/lsm6ds3_accel.cc | 250 ++++++ .../system/sensord/sensors/lsm6ds3_accel.h | 49 ++ .../system/sensord/sensors/lsm6ds3_gyro.cc | 233 ++++++ .../system/sensord/sensors/lsm6ds3_gyro.h | 45 ++ .../system/sensord/sensors/lsm6ds3_temp.cc | 37 + .../system/sensord/sensors/lsm6ds3_temp.h | 26 + .../system/sensord/sensors/mmc5603nj_magn.cc | 108 +++ .../system/sensord/sensors/mmc5603nj_magn.h | 37 + sunnypilot/system/sensord/sensors/sensor.h | 24 + sunnypilot/system/sensord/sensors_qcom2.cc | 179 +++++ .../system/sensord/tests/test_sensord.py | 251 ++++++ sunnypilot/system/sensord/tests/ttff_test.py | 48 ++ system/manager/process_config.py | 3 + 49 files changed, 3755 insertions(+), 23 deletions(-) create mode 100644 sunnypilot/selfdrive/locationd/.gitignore create mode 100644 sunnypilot/selfdrive/locationd/SConscript create mode 100644 sunnypilot/selfdrive/locationd/__init__.py create mode 100644 sunnypilot/selfdrive/locationd/locationd.cc create mode 100644 sunnypilot/selfdrive/locationd/locationd.h create mode 100644 sunnypilot/selfdrive/locationd/models/.gitignore create mode 100644 sunnypilot/selfdrive/locationd/models/__init__.py create mode 100755 sunnypilot/selfdrive/locationd/models/car_kf.py create mode 100644 sunnypilot/selfdrive/locationd/models/constants.py create mode 100644 sunnypilot/selfdrive/locationd/models/live_kf.cc create mode 100644 sunnypilot/selfdrive/locationd/models/live_kf.h create mode 100755 sunnypilot/selfdrive/locationd/models/live_kf.py create mode 100644 sunnypilot/selfdrive/locationd/tests/.gitignore create mode 100644 sunnypilot/selfdrive/locationd/tests/__init__.py create mode 100644 sunnypilot/selfdrive/locationd/tests/test_locationd.py create mode 100644 sunnypilot/system/sensord/.gitignore create mode 100644 sunnypilot/system/sensord/SConscript create mode 100644 sunnypilot/system/sensord/sensors/bmx055_accel.cc create mode 100644 sunnypilot/system/sensord/sensors/bmx055_accel.h create mode 100644 sunnypilot/system/sensord/sensors/bmx055_gyro.cc create mode 100644 sunnypilot/system/sensord/sensors/bmx055_gyro.h create mode 100644 sunnypilot/system/sensord/sensors/bmx055_magn.cc create mode 100644 sunnypilot/system/sensord/sensors/bmx055_magn.h create mode 100644 sunnypilot/system/sensord/sensors/bmx055_temp.cc create mode 100644 sunnypilot/system/sensord/sensors/bmx055_temp.h create mode 100644 sunnypilot/system/sensord/sensors/constants.h create mode 100644 sunnypilot/system/sensord/sensors/i2c_sensor.cc create mode 100644 sunnypilot/system/sensord/sensors/i2c_sensor.h create mode 100644 sunnypilot/system/sensord/sensors/lsm6ds3_accel.cc create mode 100644 sunnypilot/system/sensord/sensors/lsm6ds3_accel.h create mode 100644 sunnypilot/system/sensord/sensors/lsm6ds3_gyro.cc create mode 100644 sunnypilot/system/sensord/sensors/lsm6ds3_gyro.h create mode 100644 sunnypilot/system/sensord/sensors/lsm6ds3_temp.cc create mode 100644 sunnypilot/system/sensord/sensors/lsm6ds3_temp.h create mode 100644 sunnypilot/system/sensord/sensors/mmc5603nj_magn.cc create mode 100644 sunnypilot/system/sensord/sensors/mmc5603nj_magn.h create mode 100644 sunnypilot/system/sensord/sensors/sensor.h create mode 100644 sunnypilot/system/sensord/sensors_qcom2.cc create mode 100644 sunnypilot/system/sensord/tests/test_sensord.py create mode 100755 sunnypilot/system/sensord/tests/ttff_test.py diff --git a/cereal/log.capnp b/cereal/log.capnp index 7babd4d8b5..8925bca8ae 100644 --- a/cereal/log.capnp +++ b/cereal/log.capnp @@ -2684,7 +2684,7 @@ struct Event { lateralPlanDEPRECATED @64 :LateralPlan; navModelDEPRECATED @104 :NavModelData; uiPlanDEPRECATED @106 :UiPlan; - liveLocationKalmanDEPRECATED @72 :LiveLocationKalman; + liveLocationKalman @72 :LiveLocationKalman; liveTracksDEPRECATED @16 :List(LiveTracksDEPRECATED); onroadEventsDEPRECATED @68: List(Car.OnroadEventDEPRECATED); } diff --git a/cereal/services.py b/cereal/services.py index 17ac2e926d..67548bc79e 100755 --- a/cereal/services.py +++ b/cereal/services.py @@ -89,6 +89,7 @@ _services: dict[str, tuple] = { "carStateSP": (True, 100., 10), "liveMapDataSP": (True, 1., 1), "modelDataV2SP": (True, 20.), + "liveLocationKalman": (True, 20.), # debug "uiDebug": (True, 0., 1), diff --git a/common/params_keys.h b/common/params_keys.h index 3faae9ce14..5ba6b53108 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -152,6 +152,7 @@ inline static std::unordered_map keys = { {"IntelligentCruiseButtonManagement", {PERSISTENT | BACKUP , BOOL}}, {"InteractivityTimeout", {PERSISTENT | BACKUP, INT, "0"}}, {"IsDevelopmentBranch", {CLEAR_ON_MANAGER_START, BOOL}}, + {"LastGPSPositionLLK", {PERSISTENT, STRING}}, {"MaxTimeOffroad", {PERSISTENT | BACKUP, INT, "1800"}}, {"ModelRunnerTypeCache", {CLEAR_ON_ONROAD_TRANSITION, INT}}, {"OffroadMode", {CLEAR_ON_MANAGER_START, BOOL}}, diff --git a/selfdrive/test/process_replay/migration.py b/selfdrive/test/process_replay/migration.py index 33b363cfd9..74507197b6 100644 --- a/selfdrive/test/process_replay/migration.py +++ b/selfdrive/test/process_replay/migration.py @@ -28,7 +28,8 @@ MigrationFunc = Callable[[list[MessageWithIndex]], MigrationOps] # 3. product is the message type created by the migration function, and the function will be skipped if product type already exists in lr # 4. it must return a list of operations to be applied to the logreader (replace, add, delete) # 5. all migration functions must be independent of each other -def migrate_all(lr: LogIterable, manager_states: bool = False, panda_states: bool = False, camera_states: bool = False): +def migrate_all(lr: LogIterable, manager_states: bool = False, panda_states: bool = False, camera_states: bool = False, + live_location_kalman: bool = True): migrations = [ migrate_sensorEvents, migrate_carParams, @@ -37,7 +38,6 @@ def migrate_all(lr: LogIterable, manager_states: bool = False, panda_states: boo migrate_carOutput, migrate_controlsState, migrate_carState, - migrate_liveLocationKalman, migrate_liveTracks, migrate_driverAssistance, migrate_drivingModelData, @@ -51,6 +51,8 @@ def migrate_all(lr: LogIterable, manager_states: bool = False, panda_states: boo migrations.extend([migrate_pandaStates, migrate_peripheralState]) if camera_states: migrations.append(migrate_cameraStates) + if live_location_kalman: + migrations.append(migrate_liveLocationKalman) return migrate(lr, migrations) diff --git a/selfdrive/test/process_replay/process_replay.py b/selfdrive/test/process_replay/process_replay.py index 895204538f..9b6371dbb9 100755 --- a/selfdrive/test/process_replay/process_replay.py +++ b/selfdrive/test/process_replay/process_replay.py @@ -496,7 +496,7 @@ CONFIGS = [ pubs=[ "cameraOdometry", "accelerometer", "gyroscope", "liveCalibration", "carState" ], - subs=["livePose"], + subs=["liveLocationKalman", "livePose"], ignore=["logMonoTime"], should_recv_callback=MessageBasedRcvCallback("cameraOdometry"), tolerance=NUMPY_TOLERANCE, diff --git a/sunnypilot/SConscript b/sunnypilot/SConscript index 3aa302b92b..6b3856cb34 100644 --- a/sunnypilot/SConscript +++ b/sunnypilot/SConscript @@ -1,2 +1,3 @@ SConscript(['modeld/SConscript']) -SConscript(['modeld_v2/SConscript']) \ No newline at end of file +SConscript(['modeld_v2/SConscript']) +SConscript(['selfdrive/locationd/SConscript']) \ No newline at end of file diff --git a/sunnypilot/mapd/live_map_data/base_map_data.py b/sunnypilot/mapd/live_map_data/base_map_data.py index f386eab96b..25925937f5 100644 --- a/sunnypilot/mapd/live_map_data/base_map_data.py +++ b/sunnypilot/mapd/live_map_data/base_map_data.py @@ -6,8 +6,7 @@ See the LICENSE.md file in the root directory for more details. """ from abc import abstractmethod, ABC -from cereal import messaging -from openpilot.common.gps import get_gps_location_service +import cereal.messaging as messaging from openpilot.common.params import Params from openpilot.sunnypilot.navd.helpers import coordinate_from_param @@ -16,14 +15,12 @@ class BaseMapData(ABC): def __init__(self): self.params = Params() - self.gps_location_service = get_gps_location_service(self.params) - gps_packets = [self.gps_location_service] - self.sm = messaging.SubMaster(['livePose'] + gps_packets, ignore_alive=gps_packets, ignore_avg_freq=gps_packets, - ignore_valid=gps_packets, poll='livePose') + self.sm = messaging.SubMaster(['liveLocationKalman']) self.pm = messaging.PubMaster(['liveMapDataSP']) + self.localizer_valid = False self.last_bearing = None - self.last_position = coordinate_from_param("LastGPSPosition", self.params) + self.last_position = coordinate_from_param("LastGPSPositionLLK", self.params) @abstractmethod def update_location(self) -> None: @@ -46,7 +43,7 @@ class BaseMapData(ABC): next_speed_limit, next_speed_limit_distance = self.get_next_speed_limit_and_distance() mapd_sp_send = messaging.new_message('liveMapDataSP') - mapd_sp_send.valid = self.sm.all_checks(['livePose']) + mapd_sp_send.valid = self.sm['liveLocationKalman'].gpsOK live_map_data = mapd_sp_send.liveMapDataSP live_map_data.speedLimitValid = bool(speed_limit > 0) diff --git a/sunnypilot/mapd/live_map_data/osm_map_data.py b/sunnypilot/mapd/live_map_data/osm_map_data.py index c5187a8e04..0662e2d589 100644 --- a/sunnypilot/mapd/live_map_data/osm_map_data.py +++ b/sunnypilot/mapd/live_map_data/osm_map_data.py @@ -8,8 +8,8 @@ import json import math import platform +from cereal import log from openpilot.common.params import Params -from openpilot.common.realtime import DT_MDL from openpilot.sunnypilot.mapd.live_map_data.base_map_data import BaseMapData from openpilot.sunnypilot.navd.helpers import Coordinate @@ -20,15 +20,12 @@ class OsmMapData(BaseMapData): self.mem_params = Params("/dev/shm/params") if platform.system() != "Darwin" else self.params def update_location(self) -> None: - gps = self.sm[self.gps_location_service] - gps_ok = self.sm.recv_frame[self.gps_location_service] > 0 and (self.sm.frame - self.sm.recv_frame[self.gps_location_service]) * DT_MDL < 2.0 + location = self.sm['liveLocationKalman'] + self.localizer_valid = (location.status == log.LiveLocationKalman.Status.valid) and location.positionGeodetic.valid - if gps_ok: - self.last_bearing = gps.bearingDeg * 180/math.pi - self.last_position = Coordinate(gps.latitude, gps.longitude) - - if not gps_ok and self.sm['livePose'].inputsOK: - return + if self.localizer_valid: + self.last_bearing = math.degrees(location.calibratedOrientationNED.value[2]) + self.last_position = Coordinate(location.positionGeodetic.value[0], location.positionGeodetic.value[1]) if self.last_position is None: return @@ -36,9 +33,11 @@ class OsmMapData(BaseMapData): params = { "latitude": self.last_position.latitude, "longitude": self.last_position.longitude, - "bearing": self.last_bearing, } + if self.last_bearing is not None: + params['bearing'] = self.last_bearing + self.mem_params.put("LastGPSPosition", json.dumps(params)) def get_current_speed_limit(self) -> float: diff --git a/sunnypilot/selfdrive/locationd/.gitignore b/sunnypilot/selfdrive/locationd/.gitignore new file mode 100644 index 0000000000..11b9f127b2 --- /dev/null +++ b/sunnypilot/selfdrive/locationd/.gitignore @@ -0,0 +1,3 @@ +params_learner +paramsd +locationd diff --git a/sunnypilot/selfdrive/locationd/SConscript b/sunnypilot/selfdrive/locationd/SConscript new file mode 100644 index 0000000000..27cd4d5b40 --- /dev/null +++ b/sunnypilot/selfdrive/locationd/SConscript @@ -0,0 +1,37 @@ +Import('env', 'arch', 'common', 'messaging', 'rednose', 'transformations') + +loc_libs = [messaging, common, 'pthread', 'dl'] + +# build ekf models +rednose_gen_dir = 'models/generated' +rednose_gen_deps = [ + "models/constants.py", +] +live_ekf = env.RednoseCompileFilter( + target='live', + filter_gen_script='models/live_kf.py', + output_dir=rednose_gen_dir, + extra_gen_artifacts=['live_kf_constants.h'], + gen_script_deps=rednose_gen_deps, +) +car_ekf = env.RednoseCompileFilter( + target='car', + filter_gen_script='models/car_kf.py', + output_dir=rednose_gen_dir, + extra_gen_artifacts=[], + gen_script_deps=rednose_gen_deps, +) + +# locationd build +locationd_sources = ["locationd.cc", "models/live_kf.cc"] + +lenv = env.Clone() +# ekf filter libraries need to be linked, even if no symbols are used +if arch != "Darwin": + lenv["LINKFLAGS"] += ["-Wl,--no-as-needed"] + +lenv["LIBPATH"].append(Dir(rednose_gen_dir).abspath) +lenv["RPATH"].append(Dir(rednose_gen_dir).abspath) +locationd = lenv.Program("locationd", locationd_sources, LIBS=["live", "ekf_sym"] + loc_libs + transformations) +lenv.Depends(locationd, rednose) +lenv.Depends(locationd, live_ekf) diff --git a/sunnypilot/selfdrive/locationd/__init__.py b/sunnypilot/selfdrive/locationd/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sunnypilot/selfdrive/locationd/locationd.cc b/sunnypilot/selfdrive/locationd/locationd.cc new file mode 100644 index 0000000000..c42ab13f25 --- /dev/null +++ b/sunnypilot/selfdrive/locationd/locationd.cc @@ -0,0 +1,750 @@ +#include "sunnypilot/selfdrive/locationd/locationd.h" + +#include +#include + +#include +#include +#include + +using namespace EKFS; +using namespace Eigen; + +ExitHandler do_exit; +const double ACCEL_SANITY_CHECK = 100.0; // m/s^2 +const double ROTATION_SANITY_CHECK = 10.0; // rad/s +const double TRANS_SANITY_CHECK = 200.0; // m/s +const double CALIB_RPY_SANITY_CHECK = 0.5; // rad (+- 30 deg) +const double ALTITUDE_SANITY_CHECK = 10000; // m +const double MIN_STD_SANITY_CHECK = 1e-5; // m or rad +const double VALID_TIME_SINCE_RESET = 1.0; // s +const double VALID_POS_STD = 50.0; // m +const double MAX_RESET_TRACKER = 5.0; +const double SANE_GPS_UNCERTAINTY = 1500.0; // m +const double INPUT_INVALID_THRESHOLD = 0.5; // same as reset tracker +const double RESET_TRACKER_DECAY = 0.99995; +const double DECAY = 0.9993; // ~10 secs to resume after a bad input +const double MAX_FILTER_REWIND_TIME = 0.8; // s +const double YAWRATE_CROSS_ERR_CHECK_FACTOR = 30; + +// TODO: GPS sensor time offsets are empirically calculated +// They should be replaced with synced time from a real clock +const double GPS_QUECTEL_SENSOR_TIME_OFFSET = 0.630; // s +const double GPS_UBLOX_SENSOR_TIME_OFFSET = 0.095; // s +const float GPS_POS_STD_THRESHOLD = 50.0; +const float GPS_VEL_STD_THRESHOLD = 5.0; +const float GPS_POS_ERROR_RESET_THRESHOLD = 300.0; +const float GPS_POS_STD_RESET_THRESHOLD = 2.0; +const float GPS_VEL_STD_RESET_THRESHOLD = 0.5; +const float GPS_ORIENTATION_ERROR_RESET_THRESHOLD = 1.0; +const int GPS_ORIENTATION_ERROR_RESET_CNT = 3; + +const bool DEBUG = getenv("DEBUG") != nullptr && std::string(getenv("DEBUG")) != "0"; + +static VectorXd floatlist2vector(const capnp::List::Reader& floatlist) { + VectorXd res(floatlist.size()); + for (int i = 0; i < floatlist.size(); i++) { + res[i] = floatlist[i]; + } + return res; +} + +static Vector4d quat2vector(const Quaterniond& quat) { + return Vector4d(quat.w(), quat.x(), quat.y(), quat.z()); +} + +static Quaterniond vector2quat(const VectorXd& vec) { + return Quaterniond(vec(0), vec(1), vec(2), vec(3)); +} + +static void init_measurement(cereal::LiveLocationKalman::Measurement::Builder meas, const VectorXd& val, const VectorXd& std, bool valid) { + meas.setValue(kj::arrayPtr(val.data(), val.size())); + meas.setStd(kj::arrayPtr(std.data(), std.size())); + meas.setValid(valid); +} + + +static MatrixXdr rotate_cov(const MatrixXdr& rot_matrix, const MatrixXdr& cov_in) { + // To rotate a covariance matrix, the cov matrix needs to multiplied left and right by the transform matrix + return ((rot_matrix * cov_in) * rot_matrix.transpose()); +} + +static VectorXd rotate_std(const MatrixXdr& rot_matrix, const VectorXd& std_in) { + // Stds cannot be rotated like values, only covariances can be rotated + return rotate_cov(rot_matrix, std_in.array().square().matrix().asDiagonal()).diagonal().array().sqrt(); +} + +Localizer::Localizer(LocalizerGnssSource gnss_source) { + this->kf = std::make_unique(); + this->reset_kalman(); + + this->calib = Vector3d(0.0, 0.0, 0.0); + this->device_from_calib = MatrixXdr::Identity(3, 3); + this->calib_from_device = MatrixXdr::Identity(3, 3); + + for (int i = 0; i < POSENET_STD_HIST_HALF * 2; i++) { + this->posenet_stds.push_back(10.0); + } + + VectorXd ecef_pos = this->kf->get_x().segment(STATE_ECEF_POS_START); + this->converter = std::make_unique((ECEF) { .x = ecef_pos[0], .y = ecef_pos[1], .z = ecef_pos[2] }); + this->configure_gnss_source(gnss_source); +} + +void Localizer::build_live_location(cereal::LiveLocationKalman::Builder& fix) { + VectorXd predicted_state = this->kf->get_x(); + MatrixXdr predicted_cov = this->kf->get_P(); + VectorXd predicted_std = predicted_cov.diagonal().array().sqrt(); + + VectorXd fix_ecef = predicted_state.segment(STATE_ECEF_POS_START); + ECEF fix_ecef_ecef = { .x = fix_ecef(0), .y = fix_ecef(1), .z = fix_ecef(2) }; + VectorXd fix_ecef_std = predicted_std.segment(STATE_ECEF_POS_ERR_START); + VectorXd vel_ecef = predicted_state.segment(STATE_ECEF_VELOCITY_START); + VectorXd vel_ecef_std = predicted_std.segment(STATE_ECEF_VELOCITY_ERR_START); + VectorXd fix_pos_geo_vec = this->get_position_geodetic(); + VectorXd orientation_ecef = quat2euler(vector2quat(predicted_state.segment(STATE_ECEF_ORIENTATION_START))); + VectorXd orientation_ecef_std = predicted_std.segment(STATE_ECEF_ORIENTATION_ERR_START); + MatrixXdr orientation_ecef_cov = predicted_cov.block(STATE_ECEF_ORIENTATION_ERR_START, STATE_ECEF_ORIENTATION_ERR_START); + MatrixXdr device_from_ecef = euler2rot(orientation_ecef).transpose(); + VectorXd calibrated_orientation_ecef = rot2euler((this->calib_from_device * device_from_ecef).transpose()); + + VectorXd acc_calib = this->calib_from_device * predicted_state.segment(STATE_ACCELERATION_START); + MatrixXdr acc_calib_cov = predicted_cov.block(STATE_ACCELERATION_ERR_START, STATE_ACCELERATION_ERR_START); + VectorXd acc_calib_std = rotate_cov(this->calib_from_device, acc_calib_cov).diagonal().array().sqrt(); + VectorXd ang_vel_calib = this->calib_from_device * predicted_state.segment(STATE_ANGULAR_VELOCITY_START); + + MatrixXdr vel_angular_cov = predicted_cov.block(STATE_ANGULAR_VELOCITY_ERR_START, STATE_ANGULAR_VELOCITY_ERR_START); + VectorXd ang_vel_calib_std = rotate_cov(this->calib_from_device, vel_angular_cov).diagonal().array().sqrt(); + + VectorXd vel_device = device_from_ecef * vel_ecef; + VectorXd device_from_ecef_eul = quat2euler(vector2quat(predicted_state.segment(STATE_ECEF_ORIENTATION_START))).transpose(); + MatrixXdr condensed_cov(STATE_ECEF_ORIENTATION_ERR_LEN + STATE_ECEF_VELOCITY_ERR_LEN, STATE_ECEF_ORIENTATION_ERR_LEN + STATE_ECEF_VELOCITY_ERR_LEN); + condensed_cov.topLeftCorner() = + predicted_cov.block(STATE_ECEF_ORIENTATION_ERR_START, STATE_ECEF_ORIENTATION_ERR_START); + condensed_cov.topRightCorner() = + predicted_cov.block(STATE_ECEF_ORIENTATION_ERR_START, STATE_ECEF_VELOCITY_ERR_START); + condensed_cov.bottomRightCorner() = + predicted_cov.block(STATE_ECEF_VELOCITY_ERR_START, STATE_ECEF_VELOCITY_ERR_START); + condensed_cov.bottomLeftCorner() = + predicted_cov.block(STATE_ECEF_VELOCITY_ERR_START, STATE_ECEF_ORIENTATION_ERR_START); + VectorXd H_input(device_from_ecef_eul.size() + vel_ecef.size()); + H_input << device_from_ecef_eul, vel_ecef; + MatrixXdr HH = this->kf->H(H_input); + MatrixXdr vel_device_cov = (HH * condensed_cov) * HH.transpose(); + VectorXd vel_device_std = vel_device_cov.diagonal().array().sqrt(); + + VectorXd vel_calib = this->calib_from_device * vel_device; + VectorXd vel_calib_std = rotate_cov(this->calib_from_device, vel_device_cov).diagonal().array().sqrt(); + + VectorXd orientation_ned = ned_euler_from_ecef(fix_ecef_ecef, orientation_ecef); + VectorXd orientation_ned_std = rotate_cov(this->converter->ecef2ned_matrix, orientation_ecef_cov).diagonal().array().sqrt(); + VectorXd calibrated_orientation_ned = ned_euler_from_ecef(fix_ecef_ecef, calibrated_orientation_ecef); + VectorXd nextfix_ecef = fix_ecef + vel_ecef; + VectorXd ned_vel = this->converter->ecef2ned((ECEF) { .x = nextfix_ecef(0), .y = nextfix_ecef(1), .z = nextfix_ecef(2) }).to_vector() - converter->ecef2ned(fix_ecef_ecef).to_vector(); + + VectorXd accDevice = predicted_state.segment(STATE_ACCELERATION_START); + VectorXd accDeviceErr = predicted_std.segment(STATE_ACCELERATION_ERR_START); + + VectorXd angVelocityDevice = predicted_state.segment(STATE_ANGULAR_VELOCITY_START); + VectorXd angVelocityDeviceErr = predicted_std.segment(STATE_ANGULAR_VELOCITY_ERR_START); + + Vector3d nans = Vector3d(NAN, NAN, NAN); + + // TODO fill in NED and Calibrated stds + // write measurements to msg + init_measurement(fix.initPositionGeodetic(), fix_pos_geo_vec, nans, this->gps_mode); + init_measurement(fix.initPositionECEF(), fix_ecef, fix_ecef_std, this->gps_mode); + init_measurement(fix.initVelocityECEF(), vel_ecef, vel_ecef_std, this->gps_mode); + init_measurement(fix.initVelocityNED(), ned_vel, nans, this->gps_mode); + init_measurement(fix.initVelocityDevice(), vel_device, vel_device_std, true); + init_measurement(fix.initAccelerationDevice(), accDevice, accDeviceErr, true); + init_measurement(fix.initOrientationECEF(), orientation_ecef, orientation_ecef_std, this->gps_mode); + init_measurement(fix.initCalibratedOrientationECEF(), calibrated_orientation_ecef, nans, this->calibrated && this->gps_mode); + init_measurement(fix.initOrientationNED(), orientation_ned, orientation_ned_std, this->gps_mode); + init_measurement(fix.initCalibratedOrientationNED(), calibrated_orientation_ned, nans, this->calibrated && this->gps_mode); + init_measurement(fix.initAngularVelocityDevice(), angVelocityDevice, angVelocityDeviceErr, true); + init_measurement(fix.initVelocityCalibrated(), vel_calib, vel_calib_std, this->calibrated); + init_measurement(fix.initAngularVelocityCalibrated(), ang_vel_calib, ang_vel_calib_std, this->calibrated); + init_measurement(fix.initAccelerationCalibrated(), acc_calib, acc_calib_std, this->calibrated); + if (DEBUG) { + init_measurement(fix.initFilterState(), predicted_state, predicted_std, true); + } + + double old_mean = 0.0, new_mean = 0.0; + int i = 0; + for (double x : this->posenet_stds) { + if (i < POSENET_STD_HIST_HALF) { + old_mean += x; + } else { + new_mean += x; + } + i++; + } + old_mean /= POSENET_STD_HIST_HALF; + new_mean /= POSENET_STD_HIST_HALF; + // experimentally found these values, no false positives in 20k minutes of driving + bool std_spike = (new_mean / old_mean > 4.0 && new_mean > 7.0); + + fix.setPosenetOK(!(std_spike && this->car_speed > 5.0)); + fix.setDeviceStable(!this->device_fell); + fix.setExcessiveResets(this->reset_tracker > MAX_RESET_TRACKER); + fix.setTimeToFirstFix(std::isnan(this->ttff) ? -1. : this->ttff); + this->device_fell = false; + + //fix.setGpsWeek(this->time.week); + //fix.setGpsTimeOfWeek(this->time.tow); + fix.setUnixTimestampMillis(this->unix_timestamp_millis); + + double time_since_reset = this->kf->get_filter_time() - this->last_reset_time; + fix.setTimeSinceReset(time_since_reset); + if (fix_ecef_std.norm() < VALID_POS_STD && this->calibrated && time_since_reset > VALID_TIME_SINCE_RESET) { + fix.setStatus(cereal::LiveLocationKalman::Status::VALID); + } else if (fix_ecef_std.norm() < VALID_POS_STD && time_since_reset > VALID_TIME_SINCE_RESET) { + fix.setStatus(cereal::LiveLocationKalman::Status::UNCALIBRATED); + } else { + fix.setStatus(cereal::LiveLocationKalman::Status::UNINITIALIZED); + } +} + +VectorXd Localizer::get_position_geodetic() { + VectorXd fix_ecef = this->kf->get_x().segment(STATE_ECEF_POS_START); + ECEF fix_ecef_ecef = { .x = fix_ecef(0), .y = fix_ecef(1), .z = fix_ecef(2) }; + Geodetic fix_pos_geo = ecef2geodetic(fix_ecef_ecef); + return Vector3d(fix_pos_geo.lat, fix_pos_geo.lon, fix_pos_geo.alt); +} + +VectorXd Localizer::get_state() { + return this->kf->get_x(); +} + +VectorXd Localizer::get_stdev() { + return this->kf->get_P().diagonal().array().sqrt(); +} + +bool Localizer::are_inputs_ok() { + return this->critical_services_valid(this->observation_values_invalid) && !this->observation_timings_invalid; +} + +void Localizer::observation_timings_invalid_reset(){ + this->observation_timings_invalid = false; +} + +void Localizer::handle_sensor(double current_time, const cereal::SensorEventData::Reader& log) { + // TODO does not yet account for double sensor readings in the log + + // Ignore empty readings (e.g. in case the magnetometer had no data ready) + if (log.getTimestamp() == 0) { + return; + } + + double sensor_time = 1e-9 * log.getTimestamp(); + + // sensor time and log time should be close + if (std::abs(current_time - sensor_time) > 0.1) { + LOGE("Sensor reading ignored, sensor timestamp more than 100ms off from log time"); + this->observation_timings_invalid = true; + return; + } else if (!this->is_timestamp_valid(sensor_time)) { + this->observation_timings_invalid = true; + return; + } + + // TODO: handle messages from two IMUs at the same time + if (log.getSource() == cereal::SensorEventData::SensorSource::BMX055) { + return; + } + + // Gyro Uncalibrated + if (log.getSensor() == SENSOR_GYRO_UNCALIBRATED && log.getType() == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED) { + auto v = log.getGyroUncalibrated().getV(); + auto meas = Vector3d(-v[2], -v[1], -v[0]); + + VectorXd gyro_bias = this->kf->get_x().segment(STATE_GYRO_BIAS_START); + float gyro_camodo_yawrate_err = std::abs((meas[2] - gyro_bias[2]) - this->camodo_yawrate_distribution[0]); + float gyro_camodo_yawrate_err_threshold = YAWRATE_CROSS_ERR_CHECK_FACTOR * this->camodo_yawrate_distribution[1]; + bool gyro_valid = gyro_camodo_yawrate_err < gyro_camodo_yawrate_err_threshold; + + if ((meas.norm() < ROTATION_SANITY_CHECK) && gyro_valid) { + this->kf->predict_and_observe(sensor_time, OBSERVATION_PHONE_GYRO, { meas }); + this->observation_values_invalid["gyroscope"] *= DECAY; + } else { + this->observation_values_invalid["gyroscope"] += 1.0; + } + } + + // Accelerometer + if (log.getSensor() == SENSOR_ACCELEROMETER && log.getType() == SENSOR_TYPE_ACCELEROMETER) { + auto v = log.getAcceleration().getV(); + + // TODO: reduce false positives and re-enable this check + // check if device fell, estimate 10 for g + // 40m/s**2 is a good filter for falling detection, no false positives in 20k minutes of driving + // this->device_fell |= (floatlist2vector(v) - Vector3d(10.0, 0.0, 0.0)).norm() > 40.0; + + auto meas = Vector3d(-v[2], -v[1], -v[0]); + if (meas.norm() < ACCEL_SANITY_CHECK) { + this->kf->predict_and_observe(sensor_time, OBSERVATION_PHONE_ACCEL, { meas }); + this->observation_values_invalid["accelerometer"] *= DECAY; + } else { + this->observation_values_invalid["accelerometer"] += 1.0; + } + } +} + +void Localizer::input_fake_gps_observations(double current_time) { + // This is done to make sure that the error estimate of the position does not blow up + // when the filter is in no-gps mode + // Steps : first predict -> observe current obs with reasonable STD + this->kf->predict(current_time); + + VectorXd current_x = this->kf->get_x(); + VectorXd ecef_pos = current_x.segment(STATE_ECEF_POS_START); + VectorXd ecef_vel = current_x.segment(STATE_ECEF_VELOCITY_START); + const MatrixXdr &ecef_pos_R = this->kf->get_fake_gps_pos_cov(); + const MatrixXdr &ecef_vel_R = this->kf->get_fake_gps_vel_cov(); + + this->kf->predict_and_observe(current_time, OBSERVATION_ECEF_POS, { ecef_pos }, { ecef_pos_R }); + this->kf->predict_and_observe(current_time, OBSERVATION_ECEF_VEL, { ecef_vel }, { ecef_vel_R }); +} + +void Localizer::handle_gps(double current_time, const cereal::GpsLocationData::Reader& log, const double sensor_time_offset) { + bool gps_unreasonable = (Vector2d(log.getHorizontalAccuracy(), log.getVerticalAccuracy()).norm() >= SANE_GPS_UNCERTAINTY); + bool gps_accuracy_insane = ((log.getVerticalAccuracy() <= 0) || (log.getSpeedAccuracy() <= 0) || (log.getBearingAccuracyDeg() <= 0)); + bool gps_lat_lng_alt_insane = ((std::abs(log.getLatitude()) > 90) || (std::abs(log.getLongitude()) > 180) || (std::abs(log.getAltitude()) > ALTITUDE_SANITY_CHECK)); + bool gps_vel_insane = (floatlist2vector(log.getVNED()).norm() > TRANS_SANITY_CHECK); + + if (!log.getHasFix() || gps_unreasonable || gps_accuracy_insane || gps_lat_lng_alt_insane || gps_vel_insane) { + //this->gps_valid = false; + this->determine_gps_mode(current_time); + return; + } + + double sensor_time = current_time - sensor_time_offset; + + // Process message + //this->gps_valid = true; + this->gps_mode = true; + Geodetic geodetic = { log.getLatitude(), log.getLongitude(), log.getAltitude() }; + this->converter = std::make_unique(geodetic); + + VectorXd ecef_pos = this->converter->ned2ecef({ 0.0, 0.0, 0.0 }).to_vector(); + VectorXd ecef_vel = this->converter->ned2ecef({ log.getVNED()[0], log.getVNED()[1], log.getVNED()[2] }).to_vector() - ecef_pos; + float ecef_pos_std = std::sqrt(this->gps_variance_factor * std::pow(log.getHorizontalAccuracy(), 2) + this->gps_vertical_variance_factor * std::pow(log.getVerticalAccuracy(), 2)); + MatrixXdr ecef_pos_R = Vector3d::Constant(std::pow(this->gps_std_factor * ecef_pos_std, 2)).asDiagonal(); + MatrixXdr ecef_vel_R = Vector3d::Constant(std::pow(this->gps_std_factor * log.getSpeedAccuracy(), 2)).asDiagonal(); + + this->unix_timestamp_millis = log.getUnixTimestampMillis(); + double gps_est_error = (this->kf->get_x().segment(STATE_ECEF_POS_START) - ecef_pos).norm(); + + VectorXd orientation_ecef = quat2euler(vector2quat(this->kf->get_x().segment(STATE_ECEF_ORIENTATION_START))); + VectorXd orientation_ned = ned_euler_from_ecef({ ecef_pos(0), ecef_pos(1), ecef_pos(2) }, orientation_ecef); + VectorXd orientation_ned_gps = Vector3d(0.0, 0.0, DEG2RAD(log.getBearingDeg())); + VectorXd orientation_error = (orientation_ned - orientation_ned_gps).array() - M_PI; + for (int i = 0; i < orientation_error.size(); i++) { + orientation_error(i) = std::fmod(orientation_error(i), 2.0 * M_PI); + if (orientation_error(i) < 0.0) { + orientation_error(i) += 2.0 * M_PI; + } + orientation_error(i) -= M_PI; + } + VectorXd initial_pose_ecef_quat = quat2vector(euler2quat(ecef_euler_from_ned({ ecef_pos(0), ecef_pos(1), ecef_pos(2) }, orientation_ned_gps))); + + if (ecef_vel.norm() > 5.0 && orientation_error.norm() > 1.0) { + LOGE("Locationd vs ubloxLocation orientation difference too large, kalman reset"); + this->reset_kalman(NAN, initial_pose_ecef_quat, ecef_pos, ecef_vel, ecef_pos_R, ecef_vel_R); + this->kf->predict_and_observe(sensor_time, OBSERVATION_ECEF_ORIENTATION_FROM_GPS, { initial_pose_ecef_quat }); + } else if (gps_est_error > 100.0) { + LOGE("Locationd vs ubloxLocation position difference too large, kalman reset"); + this->reset_kalman(NAN, initial_pose_ecef_quat, ecef_pos, ecef_vel, ecef_pos_R, ecef_vel_R); + } + + this->last_gps_msg = sensor_time; + this->kf->predict_and_observe(sensor_time, OBSERVATION_ECEF_POS, { ecef_pos }, { ecef_pos_R }); + this->kf->predict_and_observe(sensor_time, OBSERVATION_ECEF_VEL, { ecef_vel }, { ecef_vel_R }); +} + +void Localizer::handle_gnss(double current_time, const cereal::GnssMeasurements::Reader& log) { + + if (!log.getPositionECEF().getValid() || !log.getVelocityECEF().getValid()) { + this->determine_gps_mode(current_time); + return; + } + + double sensor_time = log.getMeasTime() * 1e-9; + sensor_time -= this->gps_time_offset; + + auto ecef_pos_v = log.getPositionECEF().getValue(); + VectorXd ecef_pos = Vector3d(ecef_pos_v[0], ecef_pos_v[1], ecef_pos_v[2]); + + // indexed at 0 cause all std values are the same MAE + auto ecef_pos_std = log.getPositionECEF().getStd()[0]; + MatrixXdr ecef_pos_R = Vector3d::Constant(pow(this->gps_std_factor*ecef_pos_std, 2)).asDiagonal(); + + auto ecef_vel_v = log.getVelocityECEF().getValue(); + VectorXd ecef_vel = Vector3d(ecef_vel_v[0], ecef_vel_v[1], ecef_vel_v[2]); + + // indexed at 0 cause all std values are the same MAE + auto ecef_vel_std = log.getVelocityECEF().getStd()[0]; + MatrixXdr ecef_vel_R = Vector3d::Constant(pow(this->gps_std_factor*ecef_vel_std, 2)).asDiagonal(); + + double gps_est_error = (this->kf->get_x().segment(STATE_ECEF_POS_START) - ecef_pos).norm(); + + VectorXd orientation_ecef = quat2euler(vector2quat(this->kf->get_x().segment(STATE_ECEF_ORIENTATION_START))); + VectorXd orientation_ned = ned_euler_from_ecef({ ecef_pos[0], ecef_pos[1], ecef_pos[2] }, orientation_ecef); + + LocalCoord convs((ECEF){ .x = ecef_pos[0], .y = ecef_pos[1], .z = ecef_pos[2] }); + ECEF next_ecef = {.x = ecef_pos[0] + ecef_vel[0], .y = ecef_pos[1] + ecef_vel[1], .z = ecef_pos[2] + ecef_vel[2]}; + VectorXd ned_vel = convs.ecef2ned(next_ecef).to_vector(); + double bearing_rad = atan2(ned_vel[1], ned_vel[0]); + + VectorXd orientation_ned_gps = Vector3d(0.0, 0.0, bearing_rad); + VectorXd orientation_error = (orientation_ned - orientation_ned_gps).array() - M_PI; + for (int i = 0; i < orientation_error.size(); i++) { + orientation_error(i) = std::fmod(orientation_error(i), 2.0 * M_PI); + if (orientation_error(i) < 0.0) { + orientation_error(i) += 2.0 * M_PI; + } + orientation_error(i) -= M_PI; + } + VectorXd initial_pose_ecef_quat = quat2vector(euler2quat(ecef_euler_from_ned({ ecef_pos(0), ecef_pos(1), ecef_pos(2) }, orientation_ned_gps))); + + if (ecef_pos_std > GPS_POS_STD_THRESHOLD || ecef_vel_std > GPS_VEL_STD_THRESHOLD) { + this->determine_gps_mode(current_time); + return; + } + + // prevent jumping gnss measurements (covered lots, standstill...) + bool orientation_reset = ecef_vel_std < GPS_VEL_STD_RESET_THRESHOLD; + orientation_reset &= orientation_error.norm() > GPS_ORIENTATION_ERROR_RESET_THRESHOLD; + orientation_reset &= !this->standstill; + if (orientation_reset) { + this->orientation_reset_count++; + } else { + this->orientation_reset_count = 0; + } + + if ((gps_est_error > GPS_POS_ERROR_RESET_THRESHOLD && ecef_pos_std < GPS_POS_STD_RESET_THRESHOLD) || this->last_gps_msg == 0) { + // always reset on first gps message and if the location is off but the accuracy is high + LOGE("Locationd vs gnssMeasurement position difference too large, kalman reset"); + this->reset_kalman(NAN, initial_pose_ecef_quat, ecef_pos, ecef_vel, ecef_pos_R, ecef_vel_R); + } else if (orientation_reset_count > GPS_ORIENTATION_ERROR_RESET_CNT) { + LOGE("Locationd vs gnssMeasurement orientation difference too large, kalman reset"); + this->reset_kalman(NAN, initial_pose_ecef_quat, ecef_pos, ecef_vel, ecef_pos_R, ecef_vel_R); + this->kf->predict_and_observe(sensor_time, OBSERVATION_ECEF_ORIENTATION_FROM_GPS, { initial_pose_ecef_quat }); + this->orientation_reset_count = 0; + } + + this->gps_mode = true; + this->last_gps_msg = sensor_time; + this->kf->predict_and_observe(sensor_time, OBSERVATION_ECEF_POS, { ecef_pos }, { ecef_pos_R }); + this->kf->predict_and_observe(sensor_time, OBSERVATION_ECEF_VEL, { ecef_vel }, { ecef_vel_R }); +} + +void Localizer::handle_car_state(double current_time, const cereal::CarState::Reader& log) { + this->car_speed = std::abs(log.getVEgo()); + this->standstill = log.getStandstill(); + if (this->standstill) { + this->kf->predict_and_observe(current_time, OBSERVATION_NO_ROT, { Vector3d(0.0, 0.0, 0.0) }); + this->kf->predict_and_observe(current_time, OBSERVATION_NO_ACCEL, { Vector3d(0.0, 0.0, 0.0) }); + } +} + +void Localizer::handle_cam_odo(double current_time, const cereal::CameraOdometry::Reader& log) { + VectorXd rot_device = this->device_from_calib * floatlist2vector(log.getRot()); + VectorXd trans_device = this->device_from_calib * floatlist2vector(log.getTrans()); + + if (!this->is_timestamp_valid(current_time)) { + this->observation_timings_invalid = true; + return; + } + + if ((rot_device.norm() > ROTATION_SANITY_CHECK) || (trans_device.norm() > TRANS_SANITY_CHECK)) { + this->observation_values_invalid["cameraOdometry"] += 1.0; + return; + } + + VectorXd rot_calib_std = floatlist2vector(log.getRotStd()); + VectorXd trans_calib_std = floatlist2vector(log.getTransStd()); + + if ((rot_calib_std.minCoeff() <= MIN_STD_SANITY_CHECK) || (trans_calib_std.minCoeff() <= MIN_STD_SANITY_CHECK)) { + this->observation_values_invalid["cameraOdometry"] += 1.0; + return; + } + + if ((rot_calib_std.norm() > 10 * ROTATION_SANITY_CHECK) || (trans_calib_std.norm() > 10 * TRANS_SANITY_CHECK)) { + this->observation_values_invalid["cameraOdometry"] += 1.0; + return; + } + + this->posenet_stds.pop_front(); + this->posenet_stds.push_back(trans_calib_std[0]); + + // Multiply by 10 to avoid to high certainty in kalman filter because of temporally correlated noise + trans_calib_std *= 10.0; + rot_calib_std *= 10.0; + MatrixXdr rot_device_cov = rotate_std(this->device_from_calib, rot_calib_std).array().square().matrix().asDiagonal(); + MatrixXdr trans_device_cov = rotate_std(this->device_from_calib, trans_calib_std).array().square().matrix().asDiagonal(); + this->kf->predict_and_observe(current_time, OBSERVATION_CAMERA_ODO_ROTATION, + { rot_device }, { rot_device_cov }); + this->kf->predict_and_observe(current_time, OBSERVATION_CAMERA_ODO_TRANSLATION, + { trans_device }, { trans_device_cov }); + this->observation_values_invalid["cameraOdometry"] *= DECAY; + this->camodo_yawrate_distribution = Vector2d(rot_device[2], rotate_std(this->device_from_calib, rot_calib_std)[2]); +} + +void Localizer::handle_live_calib(double current_time, const cereal::LiveCalibrationData::Reader& log) { + if (!this->is_timestamp_valid(current_time)) { + this->observation_timings_invalid = true; + return; + } + + if (log.getRpyCalib().size() > 0) { + auto live_calib = floatlist2vector(log.getRpyCalib()); + if ((live_calib.minCoeff() < -CALIB_RPY_SANITY_CHECK) || (live_calib.maxCoeff() > CALIB_RPY_SANITY_CHECK)) { + this->observation_values_invalid["liveCalibration"] += 1.0; + return; + } + + this->calib = live_calib; + this->device_from_calib = euler2rot(this->calib); + this->calib_from_device = this->device_from_calib.transpose(); + this->calibrated = log.getCalStatus() == cereal::LiveCalibrationData::Status::CALIBRATED; + this->observation_values_invalid["liveCalibration"] *= DECAY; + } +} + +void Localizer::reset_kalman(double current_time) { + const VectorXd &init_x = this->kf->get_initial_x(); + const MatrixXdr &init_P = this->kf->get_initial_P(); + this->reset_kalman(current_time, init_x, init_P); +} + +void Localizer::finite_check(double current_time) { + bool all_finite = this->kf->get_x().array().isFinite().all() or this->kf->get_P().array().isFinite().all(); + if (!all_finite) { + LOGE("Non-finite values detected, kalman reset"); + this->reset_kalman(current_time); + } +} + +void Localizer::time_check(double current_time) { + if (std::isnan(this->last_reset_time)) { + this->last_reset_time = current_time; + } + if (std::isnan(this->first_valid_log_time)) { + this->first_valid_log_time = current_time; + } + double filter_time = this->kf->get_filter_time(); + bool big_time_gap = !std::isnan(filter_time) && (current_time - filter_time > 10); + if (big_time_gap) { + LOGE("Time gap of over 10s detected, kalman reset"); + this->reset_kalman(current_time); + } +} + +void Localizer::update_reset_tracker() { + // reset tracker is tuned to trigger when over 1reset/10s over 2min period + if (this->is_gps_ok()) { + this->reset_tracker *= RESET_TRACKER_DECAY; + } else { + this->reset_tracker = 0.0; + } +} + +void Localizer::reset_kalman(double current_time, const VectorXd &init_orient, const VectorXd &init_pos, const VectorXd &init_vel, const MatrixXdr &init_pos_R, const MatrixXdr &init_vel_R) { + // too nonlinear to init on completely wrong + VectorXd current_x = this->kf->get_x(); + MatrixXdr current_P = this->kf->get_P(); + MatrixXdr init_P = this->kf->get_initial_P(); + const MatrixXdr &reset_orientation_P = this->kf->get_reset_orientation_P(); + int non_ecef_state_err_len = init_P.rows() - (STATE_ECEF_POS_ERR_LEN + STATE_ECEF_ORIENTATION_ERR_LEN + STATE_ECEF_VELOCITY_ERR_LEN); + + current_x.segment(STATE_ECEF_ORIENTATION_START) = init_orient; + current_x.segment(STATE_ECEF_VELOCITY_START) = init_vel; + current_x.segment(STATE_ECEF_POS_START) = init_pos; + + init_P.block(STATE_ECEF_POS_ERR_START, STATE_ECEF_POS_ERR_START).diagonal() = init_pos_R.diagonal(); + init_P.block(STATE_ECEF_ORIENTATION_ERR_START, STATE_ECEF_ORIENTATION_ERR_START).diagonal() = reset_orientation_P.diagonal(); + init_P.block(STATE_ECEF_VELOCITY_ERR_START, STATE_ECEF_VELOCITY_ERR_START).diagonal() = init_vel_R.diagonal(); + init_P.block(STATE_ANGULAR_VELOCITY_ERR_START, STATE_ANGULAR_VELOCITY_ERR_START, non_ecef_state_err_len, non_ecef_state_err_len).diagonal() = current_P.block(STATE_ANGULAR_VELOCITY_ERR_START, + STATE_ANGULAR_VELOCITY_ERR_START, non_ecef_state_err_len, non_ecef_state_err_len).diagonal(); + + this->reset_kalman(current_time, current_x, init_P); +} + +void Localizer::reset_kalman(double current_time, const VectorXd &init_x, const MatrixXdr &init_P) { + this->kf->init_state(init_x, init_P, current_time); + this->last_reset_time = current_time; + this->reset_tracker += 1.0; +} + +void Localizer::handle_msg_bytes(const char *data, const size_t size) { + AlignedBuffer aligned_buf; + + capnp::FlatArrayMessageReader cmsg(aligned_buf.align(data, size)); + cereal::Event::Reader event = cmsg.getRoot(); + + this->handle_msg(event); +} + +void Localizer::handle_msg(const cereal::Event::Reader& log) { + double t = log.getLogMonoTime() * 1e-9; + this->time_check(t); + if (log.isAccelerometer()) { + this->handle_sensor(t, log.getAccelerometer()); + } else if (log.isGyroscope()) { + this->handle_sensor(t, log.getGyroscope()); + } else if (log.isGpsLocation()) { + this->handle_gps(t, log.getGpsLocation(), GPS_QUECTEL_SENSOR_TIME_OFFSET); + } else if (log.isGpsLocationExternal()) { + this->handle_gps(t, log.getGpsLocationExternal(), GPS_UBLOX_SENSOR_TIME_OFFSET); + //} else if (log.isGnssMeasurements()) { + // this->handle_gnss(t, log.getGnssMeasurements()); + } else if (log.isCarState()) { + this->handle_car_state(t, log.getCarState()); + } else if (log.isCameraOdometry()) { + this->handle_cam_odo(t, log.getCameraOdometry()); + } else if (log.isLiveCalibration()) { + this->handle_live_calib(t, log.getLiveCalibration()); + } + this->finite_check(); + this->update_reset_tracker(); +} + +kj::ArrayPtr Localizer::get_message_bytes(MessageBuilder& msg_builder, bool inputsOK, + bool sensorsOK, bool gpsOK, bool msgValid) { + cereal::Event::Builder evt = msg_builder.initEvent(); + evt.setValid(msgValid); + cereal::LiveLocationKalman::Builder liveLoc = evt.initLiveLocationKalman(); + this->build_live_location(liveLoc); + liveLoc.setSensorsOK(sensorsOK); + liveLoc.setGpsOK(gpsOK); + liveLoc.setInputsOK(inputsOK); + return msg_builder.toBytes(); +} + +bool Localizer::is_gps_ok() { + return (this->kf->get_filter_time() - this->last_gps_msg) < 2.0; +} + +bool Localizer::critical_services_valid(const std::map &critical_services) { + for (auto &kv : critical_services){ + if (kv.second >= INPUT_INVALID_THRESHOLD){ + return false; + } + } + return true; +} + +bool Localizer::is_timestamp_valid(double current_time) { + double filter_time = this->kf->get_filter_time(); + if (!std::isnan(filter_time) && ((filter_time - current_time) > MAX_FILTER_REWIND_TIME)) { + LOGE("Observation timestamp is older than the max rewind threshold of the filter"); + return false; + } + return true; +} + +void Localizer::determine_gps_mode(double current_time) { + // 1. If the pos_std is greater than what's not acceptable and localizer is in gps-mode, reset to no-gps-mode + // 2. If the pos_std is greater than what's not acceptable and localizer is in no-gps-mode, fake obs + // 3. If the pos_std is smaller than what's not acceptable, let gps-mode be whatever it is + VectorXd current_pos_std = this->kf->get_P().block(STATE_ECEF_POS_ERR_START, STATE_ECEF_POS_ERR_START).diagonal().array().sqrt(); + if (current_pos_std.norm() > SANE_GPS_UNCERTAINTY){ + if (this->gps_mode){ + this->gps_mode = false; + this->reset_kalman(current_time); + } else { + this->input_fake_gps_observations(current_time); + } + } +} + +void Localizer::configure_gnss_source(const LocalizerGnssSource &source) { + this->gnss_source = source; + if (source == LocalizerGnssSource::UBLOX) { + this->gps_std_factor = 10.0; + this->gps_variance_factor = 1.0; + this->gps_vertical_variance_factor = 1.0; + this->gps_time_offset = GPS_UBLOX_SENSOR_TIME_OFFSET; + } else { + this->gps_std_factor = 2.0; + this->gps_variance_factor = 0.0; + this->gps_vertical_variance_factor = 3.0; + this->gps_time_offset = GPS_QUECTEL_SENSOR_TIME_OFFSET; + } +} + +int Localizer::locationd_thread() { + Params params; + LocalizerGnssSource source; + const char* gps_location_socket; + if (params.getBool("UbloxAvailable")) { + source = LocalizerGnssSource::UBLOX; + gps_location_socket = "gpsLocationExternal"; + } else { + source = LocalizerGnssSource::QCOM; + gps_location_socket = "gpsLocation"; + } + + this->configure_gnss_source(source); + const std::initializer_list service_list = {gps_location_socket, "cameraOdometry", "liveCalibration", + "carState", "accelerometer", "gyroscope"}; + + SubMaster sm(service_list, {}, nullptr, {gps_location_socket}); + PubMaster pm({"liveLocationKalman"}); + + uint64_t cnt = 0; + bool filterInitialized = false; + const std::vector critical_input_services = {"cameraOdometry", "liveCalibration", "accelerometer", "gyroscope"}; + for (std::string service : critical_input_services) { + this->observation_values_invalid.insert({service, 0.0}); + } + + while (!do_exit) { + sm.update(); + if (filterInitialized){ + this->observation_timings_invalid_reset(); + for (const char* service : service_list) { + if (sm.updated(service) && sm.valid(service)){ + const cereal::Event::Reader log = sm[service]; + this->handle_msg(log); + } + } + } else { + filterInitialized = sm.allAliveAndValid(); + } + + const char* trigger_msg = "cameraOdometry"; + if (sm.updated(trigger_msg)) { + bool inputsOK = sm.allValid() && this->are_inputs_ok(); + bool gpsOK = this->is_gps_ok(); + bool sensorsOK = sm.allAliveAndValid({"accelerometer", "gyroscope"}); + + // Log time to first fix + if (gpsOK && std::isnan(this->ttff) && !std::isnan(this->first_valid_log_time)) { + this->ttff = std::max(1e-3, (sm[trigger_msg].getLogMonoTime() * 1e-9) - this->first_valid_log_time); + } + + MessageBuilder msg_builder; + kj::ArrayPtr bytes = this->get_message_bytes(msg_builder, inputsOK, sensorsOK, gpsOK, filterInitialized); + pm.send("liveLocationKalman", bytes.begin(), bytes.size()); + + if (cnt % 1200 == 0 && gpsOK) { // once a minute + VectorXd posGeo = this->get_position_geodetic(); + std::string lastGPSPosJSON = util::string_format( + "{\"latitude\": %.15f, \"longitude\": %.15f, \"altitude\": %.15f}", posGeo(0), posGeo(1), posGeo(2)); + params.putNonBlocking("LastGPSPositionLLK", lastGPSPosJSON); + } + cnt++; + } + } + return 0; +} + +int main() { + util::set_realtime_priority(5); + + Localizer localizer; + return localizer.locationd_thread(); +} diff --git a/sunnypilot/selfdrive/locationd/locationd.h b/sunnypilot/selfdrive/locationd/locationd.h new file mode 100644 index 0000000000..4d04492102 --- /dev/null +++ b/sunnypilot/selfdrive/locationd/locationd.h @@ -0,0 +1,100 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "cereal/messaging/messaging.h" +#include "common/transformations/coordinates.hpp" +#include "common/transformations/orientation.hpp" +#include "common/params.h" +#include "common/swaglog.h" +#include "common/timing.h" +#include "common/util.h" + +#include "sunnypilot/system/sensord/sensors/constants.h" +#define VISION_DECIMATION 2 +#define SENSOR_DECIMATION 10 +#include "sunnypilot/selfdrive/locationd/models/live_kf.h" + +#define POSENET_STD_HIST_HALF 20 + +enum LocalizerGnssSource { + UBLOX, QCOM +}; + +class Localizer { +public: + Localizer(LocalizerGnssSource gnss_source = LocalizerGnssSource::UBLOX); + + int locationd_thread(); + + void reset_kalman(double current_time = NAN); + void reset_kalman(double current_time, const Eigen::VectorXd &init_orient, const Eigen::VectorXd &init_pos, const Eigen::VectorXd &init_vel, const MatrixXdr &init_pos_R, const MatrixXdr &init_vel_R); + void reset_kalman(double current_time, const Eigen::VectorXd &init_x, const MatrixXdr &init_P); + void finite_check(double current_time = NAN); + void time_check(double current_time = NAN); + void update_reset_tracker(); + bool is_gps_ok(); + bool critical_services_valid(const std::map &critical_services); + bool is_timestamp_valid(double current_time); + void determine_gps_mode(double current_time); + bool are_inputs_ok(); + void observation_timings_invalid_reset(); + + kj::ArrayPtr get_message_bytes(MessageBuilder& msg_builder, + bool inputsOK, bool sensorsOK, bool gpsOK, bool msgValid); + void build_live_location(cereal::LiveLocationKalman::Builder& fix); + + Eigen::VectorXd get_position_geodetic(); + Eigen::VectorXd get_state(); + Eigen::VectorXd get_stdev(); + + void handle_msg_bytes(const char *data, const size_t size); + void handle_msg(const cereal::Event::Reader& log); + void handle_sensor(double current_time, const cereal::SensorEventData::Reader& log); + void handle_gps(double current_time, const cereal::GpsLocationData::Reader& log, const double sensor_time_offset); + void handle_gnss(double current_time, const cereal::GnssMeasurements::Reader& log); + void handle_car_state(double current_time, const cereal::CarState::Reader& log); + void handle_cam_odo(double current_time, const cereal::CameraOdometry::Reader& log); + void handle_live_calib(double current_time, const cereal::LiveCalibrationData::Reader& log); + + void input_fake_gps_observations(double current_time); + +private: + std::unique_ptr kf; + + Eigen::VectorXd calib; + MatrixXdr device_from_calib; + MatrixXdr calib_from_device; + bool calibrated = false; + + double car_speed = 0.0; + double last_reset_time = NAN; + std::deque posenet_stds; + + std::unique_ptr converter; + + int64_t unix_timestamp_millis = 0; + double reset_tracker = 0.0; + bool device_fell = false; + bool gps_mode = false; + double first_valid_log_time = NAN; + double ttff = NAN; + double last_gps_msg = 0; + LocalizerGnssSource gnss_source; + bool observation_timings_invalid = false; + std::map observation_values_invalid; + bool standstill = true; + int32_t orientation_reset_count = 0; + float gps_std_factor; + float gps_variance_factor; + float gps_vertical_variance_factor; + double gps_time_offset; + Eigen::VectorXd camodo_yawrate_distribution = Eigen::Vector2d(0.0, 10.0); // mean, std + + void configure_gnss_source(const LocalizerGnssSource &source); +}; diff --git a/sunnypilot/selfdrive/locationd/models/.gitignore b/sunnypilot/selfdrive/locationd/models/.gitignore new file mode 100644 index 0000000000..9ab870da89 --- /dev/null +++ b/sunnypilot/selfdrive/locationd/models/.gitignore @@ -0,0 +1 @@ +generated/ diff --git a/sunnypilot/selfdrive/locationd/models/__init__.py b/sunnypilot/selfdrive/locationd/models/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sunnypilot/selfdrive/locationd/models/car_kf.py b/sunnypilot/selfdrive/locationd/models/car_kf.py new file mode 100755 index 0000000000..9964cab973 --- /dev/null +++ b/sunnypilot/selfdrive/locationd/models/car_kf.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python3 +import math +import sys +from typing import Any + +import numpy as np + +from openpilot.common.constants import ACCELERATION_DUE_TO_GRAVITY +from openpilot.sunnypilot.selfdrive.locationd.models.constants import ObservationKind +from openpilot.common.swaglog import cloudlog + +from rednose.helpers.kalmanfilter import KalmanFilter + +if __name__ == '__main__': # Generating sympy + import sympy as sp + from rednose.helpers.ekf_sym import gen_code +else: + from rednose.helpers.ekf_sym_pyx import EKF_sym_pyx + + +i = 0 + +def _slice(n): + global i + s = slice(i, i + n) + i += n + + return s + + +class States: + # Vehicle model params + STIFFNESS = _slice(1) # [-] + STEER_RATIO = _slice(1) # [-] + ANGLE_OFFSET = _slice(1) # [rad] + ANGLE_OFFSET_FAST = _slice(1) # [rad] + + VELOCITY = _slice(2) # (x, y) [m/s] + YAW_RATE = _slice(1) # [rad/s] + STEER_ANGLE = _slice(1) # [rad] + ROAD_ROLL = _slice(1) # [rad] + + +class CarKalman(KalmanFilter): + name = 'car' + + initial_x = np.array([ + 1.0, + 15.0, + 0.0, + 0.0, + + 10.0, 0.0, + 0.0, + 0.0, + 0.0 + ]) + + # process noise + Q = np.diag([ + (.05 / 100)**2, + .01**2, + math.radians(0.02)**2, + math.radians(0.25)**2, + + .1**2, .01**2, + math.radians(0.1)**2, + math.radians(0.1)**2, + math.radians(1)**2, + ]) + P_initial = Q.copy() + + obs_noise: dict[int, Any] = { + ObservationKind.STEER_ANGLE: np.atleast_2d(math.radians(0.05)**2), + ObservationKind.ANGLE_OFFSET_FAST: np.atleast_2d(math.radians(10.0)**2), + ObservationKind.ROAD_ROLL: np.atleast_2d(math.radians(1.0)**2), + ObservationKind.STEER_RATIO: np.atleast_2d(5.0**2), + ObservationKind.STIFFNESS: np.atleast_2d(0.5**2), + ObservationKind.ROAD_FRAME_X_SPEED: np.atleast_2d(0.1**2), + } + + global_vars = [ + 'mass', + 'rotational_inertia', + 'center_to_front', + 'center_to_rear', + 'stiffness_front', + 'stiffness_rear', + ] + + @staticmethod + def generate_code(generated_dir): + dim_state = CarKalman.initial_x.shape[0] + name = CarKalman.name + + # Linearized single-track lateral dynamics, equations 7.211-7.213 + # Massimo Guiggiani, The Science of Vehicle Dynamics: Handling, Braking, and Ride of Road and Race Cars + # Springer Cham, 2023. doi: https://doi.org/10.1007/978-3-031-06461-6 + + # globals + global_vars = [sp.Symbol(name) for name in CarKalman.global_vars] + m, j, aF, aR, cF_orig, cR_orig = global_vars + + # make functions and jacobians with sympy + # state variables + state_sym = sp.MatrixSymbol('state', dim_state, 1) + state = sp.Matrix(state_sym) + + # Vehicle model constants + sf = state[States.STIFFNESS, :][0, 0] + + cF, cR = sf * cF_orig, sf * cR_orig + angle_offset = state[States.ANGLE_OFFSET, :][0, 0] + angle_offset_fast = state[States.ANGLE_OFFSET_FAST, :][0, 0] + theta = state[States.ROAD_ROLL, :][0, 0] + sa = state[States.STEER_ANGLE, :][0, 0] + + sR = state[States.STEER_RATIO, :][0, 0] + u, v = state[States.VELOCITY, :] + r = state[States.YAW_RATE, :][0, 0] + + A = sp.Matrix(np.zeros((2, 2))) + A[0, 0] = -(cF + cR) / (m * u) + A[0, 1] = -(cF * aF - cR * aR) / (m * u) - u + A[1, 0] = -(cF * aF - cR * aR) / (j * u) + A[1, 1] = -(cF * aF**2 + cR * aR**2) / (j * u) + + B = sp.Matrix(np.zeros((2, 1))) + B[0, 0] = cF / m / sR + B[1, 0] = (cF * aF) / j / sR + + C = sp.Matrix(np.zeros((2, 1))) + C[0, 0] = ACCELERATION_DUE_TO_GRAVITY + C[1, 0] = 0 + + x = sp.Matrix([v, r]) # lateral velocity, yaw rate + x_dot = A * x + B * (sa - angle_offset - angle_offset_fast) - C * theta + + dt = sp.Symbol('dt') + state_dot = sp.Matrix(np.zeros((dim_state, 1))) + state_dot[States.VELOCITY.start + 1, 0] = x_dot[0] + state_dot[States.YAW_RATE.start, 0] = x_dot[1] + + # Basic descretization, 1st order integrator + # Can be pretty bad if dt is big + f_sym = state + dt * state_dot + + # + # Observation functions + # + obs_eqs = [ + [sp.Matrix([r]), ObservationKind.ROAD_FRAME_YAW_RATE, None], + [sp.Matrix([u, v]), ObservationKind.ROAD_FRAME_XY_SPEED, None], + [sp.Matrix([u]), ObservationKind.ROAD_FRAME_X_SPEED, None], + [sp.Matrix([sa]), ObservationKind.STEER_ANGLE, None], + [sp.Matrix([angle_offset_fast]), ObservationKind.ANGLE_OFFSET_FAST, None], + [sp.Matrix([sR]), ObservationKind.STEER_RATIO, None], + [sp.Matrix([sf]), ObservationKind.STIFFNESS, None], + [sp.Matrix([theta]), ObservationKind.ROAD_ROLL, None], + ] + + gen_code(generated_dir, name, f_sym, dt, state_sym, obs_eqs, dim_state, dim_state, global_vars=global_vars) + + def __init__(self, generated_dir): + dim_state, dim_state_err = CarKalman.initial_x.shape[0], CarKalman.P_initial.shape[0] + self.filter = EKF_sym_pyx(generated_dir, CarKalman.name, CarKalman.Q, CarKalman.initial_x, CarKalman.P_initial, + dim_state, dim_state_err, global_vars=CarKalman.global_vars, logger=cloudlog) + + def set_globals(self, mass, rotational_inertia, center_to_front, center_to_rear, stiffness_front, stiffness_rear): + self.filter.set_global("mass", mass) + self.filter.set_global("rotational_inertia", rotational_inertia) + self.filter.set_global("center_to_front", center_to_front) + self.filter.set_global("center_to_rear", center_to_rear) + self.filter.set_global("stiffness_front", stiffness_front) + self.filter.set_global("stiffness_rear", stiffness_rear) + + +if __name__ == "__main__": + generated_dir = sys.argv[2] + CarKalman.generate_code(generated_dir) diff --git a/sunnypilot/selfdrive/locationd/models/constants.py b/sunnypilot/selfdrive/locationd/models/constants.py new file mode 100644 index 0000000000..6d328ce6f5 --- /dev/null +++ b/sunnypilot/selfdrive/locationd/models/constants.py @@ -0,0 +1,92 @@ +import os + +GENERATED_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), 'generated')) + +class ObservationKind: + UNKNOWN = 0 + NO_OBSERVATION = 1 + GPS_NED = 2 + ODOMETRIC_SPEED = 3 + PHONE_GYRO = 4 + GPS_VEL = 5 + PSEUDORANGE_GPS = 6 + PSEUDORANGE_RATE_GPS = 7 + SPEED = 8 + NO_ROT = 9 + PHONE_ACCEL = 10 + ORB_POINT = 11 + ECEF_POS = 12 + CAMERA_ODO_TRANSLATION = 13 + CAMERA_ODO_ROTATION = 14 + ORB_FEATURES = 15 + MSCKF_TEST = 16 + FEATURE_TRACK_TEST = 17 + LANE_PT = 18 + IMU_FRAME = 19 + PSEUDORANGE_GLONASS = 20 + PSEUDORANGE_RATE_GLONASS = 21 + PSEUDORANGE = 22 + PSEUDORANGE_RATE = 23 + ECEF_VEL = 35 + ECEF_ORIENTATION_FROM_GPS = 32 + NO_ACCEL = 33 + ORB_FEATURES_WIDE = 34 + + ROAD_FRAME_XY_SPEED = 24 # (x, y) [m/s] + ROAD_FRAME_YAW_RATE = 25 # [rad/s] + STEER_ANGLE = 26 # [rad] + ANGLE_OFFSET_FAST = 27 # [rad] + STIFFNESS = 28 # [-] + STEER_RATIO = 29 # [-] + ROAD_FRAME_X_SPEED = 30 # (x) [m/s] + ROAD_ROLL = 31 # [rad] + + names = [ + 'Unknown', + 'No observation', + 'GPS NED', + 'Odometric speed', + 'Phone gyro', + 'GPS velocity', + 'GPS pseudorange', + 'GPS pseudorange rate', + 'Speed', + 'No rotation', + 'Phone acceleration', + 'ORB point', + 'ECEF pos', + 'camera odometric translation', + 'camera odometric rotation', + 'ORB features', + 'MSCKF test', + 'Feature track test', + 'Lane ecef point', + 'imu frame eulers', + 'GLONASS pseudorange', + 'GLONASS pseudorange rate', + 'pseudorange', + 'pseudorange rate', + + 'Road Frame x,y speed', + 'Road Frame yaw rate', + 'Steer Angle', + 'Fast Angle Offset', + 'Stiffness', + 'Steer Ratio', + 'Road Frame x speed', + 'Road Roll', + 'ECEF orientation from GPS', + 'NO accel', + 'ORB features wide camera', + 'ECEF_VEL', + ] + + @classmethod + def to_string(cls, kind): + return cls.names[kind] + + +SAT_OBS = [ObservationKind.PSEUDORANGE_GPS, + ObservationKind.PSEUDORANGE_RATE_GPS, + ObservationKind.PSEUDORANGE_GLONASS, + ObservationKind.PSEUDORANGE_RATE_GLONASS] diff --git a/sunnypilot/selfdrive/locationd/models/live_kf.cc b/sunnypilot/selfdrive/locationd/models/live_kf.cc new file mode 100644 index 0000000000..7ef6be638e --- /dev/null +++ b/sunnypilot/selfdrive/locationd/models/live_kf.cc @@ -0,0 +1,122 @@ +#include "sunnypilot/selfdrive/locationd/models/live_kf.h" + +using namespace EKFS; +using namespace Eigen; + +Eigen::Map get_mapvec(const Eigen::VectorXd &vec) { + return Eigen::Map((double*)vec.data(), vec.rows(), vec.cols()); +} + +Eigen::Map get_mapmat(const MatrixXdr &mat) { + return Eigen::Map((double*)mat.data(), mat.rows(), mat.cols()); +} + +std::vector> get_vec_mapvec(const std::vector &vec_vec) { + std::vector> res; + for (const Eigen::VectorXd &vec : vec_vec) { + res.push_back(get_mapvec(vec)); + } + return res; +} + +std::vector> get_vec_mapmat(const std::vector &mat_vec) { + std::vector> res; + for (const MatrixXdr &mat : mat_vec) { + res.push_back(get_mapmat(mat)); + } + return res; +} + +LiveKalman::LiveKalman() { + this->dim_state = live_initial_x.rows(); + this->dim_state_err = live_initial_P_diag.rows(); + + this->initial_x = live_initial_x; + this->initial_P = live_initial_P_diag.asDiagonal(); + this->fake_gps_pos_cov = live_fake_gps_pos_cov_diag.asDiagonal(); + this->fake_gps_vel_cov = live_fake_gps_vel_cov_diag.asDiagonal(); + this->reset_orientation_P = live_reset_orientation_diag.asDiagonal(); + this->Q = live_Q_diag.asDiagonal(); + for (auto& pair : live_obs_noise_diag) { + this->obs_noise[pair.first] = pair.second.asDiagonal(); + } + + // init filter + this->filter = std::make_shared(this->name, get_mapmat(this->Q), get_mapvec(this->initial_x), + get_mapmat(initial_P), this->dim_state, this->dim_state_err, 0, 0, 0, std::vector(), + std::vector{3}, std::vector(), 0.8); +} + +void LiveKalman::init_state(const VectorXd &state, const VectorXd &covs_diag, double filter_time) { + MatrixXdr covs = covs_diag.asDiagonal(); + this->filter->init_state(get_mapvec(state), get_mapmat(covs), filter_time); +} + +void LiveKalman::init_state(const VectorXd &state, const MatrixXdr &covs, double filter_time) { + this->filter->init_state(get_mapvec(state), get_mapmat(covs), filter_time); +} + +void LiveKalman::init_state(const VectorXd &state, double filter_time) { + MatrixXdr covs = this->filter->covs(); + this->filter->init_state(get_mapvec(state), get_mapmat(covs), filter_time); +} + +VectorXd LiveKalman::get_x() { + return this->filter->state(); +} + +MatrixXdr LiveKalman::get_P() { + return this->filter->covs(); +} + +double LiveKalman::get_filter_time() { + return this->filter->get_filter_time(); +} + +std::vector LiveKalman::get_R(int kind, int n) { + std::vector R; + for (int i = 0; i < n; i++) { + R.push_back(this->obs_noise[kind]); + } + return R; +} + +std::optional LiveKalman::predict_and_observe(double t, int kind, const std::vector &meas, std::vector R) { + std::optional r; + if (R.size() == 0) { + R = this->get_R(kind, meas.size()); + } + r = this->filter->predict_and_update_batch(t, kind, get_vec_mapvec(meas), get_vec_mapmat(R)); + return r; +} + +void LiveKalman::predict(double t) { + this->filter->predict(t); +} + +const Eigen::VectorXd &LiveKalman::get_initial_x() { + return this->initial_x; +} + +const MatrixXdr &LiveKalman::get_initial_P() { + return this->initial_P; +} + +const MatrixXdr &LiveKalman::get_fake_gps_pos_cov() { + return this->fake_gps_pos_cov; +} + +const MatrixXdr &LiveKalman::get_fake_gps_vel_cov() { + return this->fake_gps_vel_cov; +} + +const MatrixXdr &LiveKalman::get_reset_orientation_P() { + return this->reset_orientation_P; +} + +MatrixXdr LiveKalman::H(const VectorXd &in) { + assert(in.size() == 6); + Matrix res; + this->filter->get_extra_routine("H")((double*)in.data(), res.data()); + return res; +} diff --git a/sunnypilot/selfdrive/locationd/models/live_kf.h b/sunnypilot/selfdrive/locationd/models/live_kf.h new file mode 100644 index 0000000000..e4b3e326b3 --- /dev/null +++ b/sunnypilot/selfdrive/locationd/models/live_kf.h @@ -0,0 +1,66 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +#include "generated/live_kf_constants.h" +#include "rednose/helpers/ekf_sym.h" + +#define EARTH_GM 3.986005e14 // m^3/s^2 (gravitational constant * mass of earth) + +using namespace EKFS; + +Eigen::Map get_mapvec(const Eigen::VectorXd &vec); +Eigen::Map get_mapmat(const MatrixXdr &mat); +std::vector> get_vec_mapvec(const std::vector &vec_vec); +std::vector> get_vec_mapmat(const std::vector &mat_vec); + +class LiveKalman { +public: + LiveKalman(); + + void init_state(const Eigen::VectorXd &state, const Eigen::VectorXd &covs_diag, double filter_time); + void init_state(const Eigen::VectorXd &state, const MatrixXdr &covs, double filter_time); + void init_state(const Eigen::VectorXd &state, double filter_time); + + Eigen::VectorXd get_x(); + MatrixXdr get_P(); + double get_filter_time(); + std::vector get_R(int kind, int n); + + std::optional predict_and_observe(double t, int kind, const std::vector &meas, std::vector R = {}); + std::optional predict_and_update_odo_speed(std::vector speed, double t, int kind); + std::optional predict_and_update_odo_trans(std::vector trans, double t, int kind); + std::optional predict_and_update_odo_rot(std::vector rot, double t, int kind); + void predict(double t); + + const Eigen::VectorXd &get_initial_x(); + const MatrixXdr &get_initial_P(); + const MatrixXdr &get_fake_gps_pos_cov(); + const MatrixXdr &get_fake_gps_vel_cov(); + const MatrixXdr &get_reset_orientation_P(); + + MatrixXdr H(const Eigen::VectorXd &in); + +private: + std::string name = "live"; + + std::shared_ptr filter; + + int dim_state; + int dim_state_err; + + Eigen::VectorXd initial_x; + MatrixXdr initial_P; + MatrixXdr fake_gps_pos_cov; + MatrixXdr fake_gps_vel_cov; + MatrixXdr reset_orientation_P; + MatrixXdr Q; // process noise + std::unordered_map obs_noise; +}; diff --git a/sunnypilot/selfdrive/locationd/models/live_kf.py b/sunnypilot/selfdrive/locationd/models/live_kf.py new file mode 100755 index 0000000000..e5626b8f28 --- /dev/null +++ b/sunnypilot/selfdrive/locationd/models/live_kf.py @@ -0,0 +1,242 @@ +#!/usr/bin/env python3 + +import sys +import os +import numpy as np + +from openpilot.sunnypilot.selfdrive.locationd.models.constants import ObservationKind + +import sympy as sp +import inspect +from rednose.helpers.sympy_helpers import euler_rotate, quat_matrix_r, quat_rotate +from rednose.helpers.ekf_sym import gen_code + +EARTH_GM = 3.986005e14 # m^3/s^2 (gravitational constant * mass of earth) + + +def numpy2eigenstring(arr): + assert(len(arr.shape) == 1) + arr_str = np.array2string(arr, precision=20, separator=',')[1:-1].replace(' ', '').replace('\n', '') + return f"(Eigen::VectorXd({len(arr)}) << {arr_str}).finished()" + + +class States: + ECEF_POS = slice(0, 3) # x, y and z in ECEF in meters + ECEF_ORIENTATION = slice(3, 7) # quat for pose of phone in ecef + ECEF_VELOCITY = slice(7, 10) # ecef velocity in m/s + ANGULAR_VELOCITY = slice(10, 13) # roll, pitch and yaw rates in device frame in radians/s + GYRO_BIAS = slice(13, 16) # roll, pitch and yaw biases + ACCELERATION = slice(16, 19) # Acceleration in device frame in m/s**2 + ACC_BIAS = slice(19, 22) # Acceletometer bias in m/s**2 + + # Error-state has different slices because it is an ESKF + ECEF_POS_ERR = slice(0, 3) + ECEF_ORIENTATION_ERR = slice(3, 6) # euler angles for orientation error + ECEF_VELOCITY_ERR = slice(6, 9) + ANGULAR_VELOCITY_ERR = slice(9, 12) + GYRO_BIAS_ERR = slice(12, 15) + ACCELERATION_ERR = slice(15, 18) + ACC_BIAS_ERR = slice(18, 21) + + +class LiveKalman: + name = 'live' + + initial_x = np.array([3.88e6, -3.37e6, 3.76e6, + 0.42254641, -0.31238054, -0.83602975, -0.15788347, # NED [0,0,0] -> ECEF Quat + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0]) + + # state covariance + initial_P_diag = np.array([10**2, 10**2, 10**2, + 0.01**2, 0.01**2, 0.01**2, + 10**2, 10**2, 10**2, + 1**2, 1**2, 1**2, + 1**2, 1**2, 1**2, + 100**2, 100**2, 100**2, + 0.01**2, 0.01**2, 0.01**2]) + + # state covariance when resetting midway in a segment + reset_orientation_diag = np.array([1**2, 1**2, 1**2]) + + # fake observation covariance, to ensure the uncertainty estimate of the filter is under control + fake_gps_pos_cov_diag = np.array([1000**2, 1000**2, 1000**2]) + fake_gps_vel_cov_diag = np.array([10**2, 10**2, 10**2]) + + # process noise + Q_diag = np.array([0.03**2, 0.03**2, 0.03**2, + 0.001**2, 0.001**2, 0.001**2, + 0.01**2, 0.01**2, 0.01**2, + 0.1**2, 0.1**2, 0.1**2, + (0.005 / 100)**2, (0.005 / 100)**2, (0.005 / 100)**2, + 3**2, 3**2, 3**2, + 0.005**2, 0.005**2, 0.005**2]) + + obs_noise_diag = {ObservationKind.PHONE_GYRO: np.array([0.025**2, 0.025**2, 0.025**2]), + ObservationKind.PHONE_ACCEL: np.array([.5**2, .5**2, .5**2]), + ObservationKind.CAMERA_ODO_ROTATION: np.array([0.05**2, 0.05**2, 0.05**2]), + ObservationKind.NO_ROT: np.array([0.005**2, 0.005**2, 0.005**2]), + ObservationKind.NO_ACCEL: np.array([0.05**2, 0.05**2, 0.05**2]), + ObservationKind.ECEF_POS: np.array([5**2, 5**2, 5**2]), + ObservationKind.ECEF_VEL: np.array([.5**2, .5**2, .5**2]), + ObservationKind.ECEF_ORIENTATION_FROM_GPS: np.array([.2**2, .2**2, .2**2, .2**2])} + + @staticmethod + def generate_code(generated_dir): + name = LiveKalman.name + dim_state = LiveKalman.initial_x.shape[0] + dim_state_err = LiveKalman.initial_P_diag.shape[0] + + state_sym = sp.MatrixSymbol('state', dim_state, 1) + state = sp.Matrix(state_sym) + x, y, z = state[States.ECEF_POS, :] + q = state[States.ECEF_ORIENTATION, :] + v = state[States.ECEF_VELOCITY, :] + vx, vy, vz = v + omega = state[States.ANGULAR_VELOCITY, :] + vroll, vpitch, vyaw = omega + roll_bias, pitch_bias, yaw_bias = state[States.GYRO_BIAS, :] + acceleration = state[States.ACCELERATION, :] + acc_bias = state[States.ACC_BIAS, :] + + dt = sp.Symbol('dt') + + # calibration and attitude rotation matrices + quat_rot = quat_rotate(*q) + + # Got the quat predict equations from here + # A New Quaternion-Based Kalman Filter for + # Real-Time Attitude Estimation Using the Two-Step + # Geometrically-Intuitive Correction Algorithm + A = 0.5 * sp.Matrix([[0, -vroll, -vpitch, -vyaw], + [vroll, 0, vyaw, -vpitch], + [vpitch, -vyaw, 0, vroll], + [vyaw, vpitch, -vroll, 0]]) + q_dot = A * q + + # Time derivative of the state as a function of state + state_dot = sp.Matrix(np.zeros((dim_state, 1))) + state_dot[States.ECEF_POS, :] = v + state_dot[States.ECEF_ORIENTATION, :] = q_dot + state_dot[States.ECEF_VELOCITY, 0] = quat_rot * acceleration + + # Basic descretization, 1st order intergrator + # Can be pretty bad if dt is big + f_sym = state + dt * state_dot + + state_err_sym = sp.MatrixSymbol('state_err', dim_state_err, 1) + state_err = sp.Matrix(state_err_sym) + quat_err = state_err[States.ECEF_ORIENTATION_ERR, :] + v_err = state_err[States.ECEF_VELOCITY_ERR, :] + omega_err = state_err[States.ANGULAR_VELOCITY_ERR, :] + acceleration_err = state_err[States.ACCELERATION_ERR, :] + + # Time derivative of the state error as a function of state error and state + quat_err_matrix = euler_rotate(quat_err[0], quat_err[1], quat_err[2]) + q_err_dot = quat_err_matrix * quat_rot * (omega + omega_err) + state_err_dot = sp.Matrix(np.zeros((dim_state_err, 1))) + state_err_dot[States.ECEF_POS_ERR, :] = v_err + state_err_dot[States.ECEF_ORIENTATION_ERR, :] = q_err_dot + state_err_dot[States.ECEF_VELOCITY_ERR, :] = quat_err_matrix * quat_rot * (acceleration + acceleration_err) + f_err_sym = state_err + dt * state_err_dot + + # Observation matrix modifier + H_mod_sym = sp.Matrix(np.zeros((dim_state, dim_state_err))) + H_mod_sym[States.ECEF_POS, States.ECEF_POS_ERR] = np.eye(States.ECEF_POS.stop - States.ECEF_POS.start) + H_mod_sym[States.ECEF_ORIENTATION, States.ECEF_ORIENTATION_ERR] = 0.5 * quat_matrix_r(state[3:7])[:, 1:] + H_mod_sym[States.ECEF_ORIENTATION.stop:, States.ECEF_ORIENTATION_ERR.stop:] = np.eye(dim_state - States.ECEF_ORIENTATION.stop) + + # these error functions are defined so that say there + # is a nominal x and true x: + # true x = err_function(nominal x, delta x) + # delta x = inv_err_function(nominal x, true x) + nom_x = sp.MatrixSymbol('nom_x', dim_state, 1) + true_x = sp.MatrixSymbol('true_x', dim_state, 1) + delta_x = sp.MatrixSymbol('delta_x', dim_state_err, 1) + + err_function_sym = sp.Matrix(np.zeros((dim_state, 1))) + delta_quat = sp.Matrix(np.ones(4)) + delta_quat[1:, :] = sp.Matrix(0.5 * delta_x[States.ECEF_ORIENTATION_ERR, :]) + err_function_sym[States.ECEF_POS, :] = sp.Matrix(nom_x[States.ECEF_POS, :] + delta_x[States.ECEF_POS_ERR, :]) + err_function_sym[States.ECEF_ORIENTATION, 0] = quat_matrix_r(nom_x[States.ECEF_ORIENTATION, 0]) * delta_quat + err_function_sym[States.ECEF_ORIENTATION.stop:, :] = sp.Matrix(nom_x[States.ECEF_ORIENTATION.stop:, :] + delta_x[States.ECEF_ORIENTATION_ERR.stop:, :]) + + inv_err_function_sym = sp.Matrix(np.zeros((dim_state_err, 1))) + inv_err_function_sym[States.ECEF_POS_ERR, 0] = sp.Matrix(-nom_x[States.ECEF_POS, 0] + true_x[States.ECEF_POS, 0]) + delta_quat = quat_matrix_r(nom_x[States.ECEF_ORIENTATION, 0]).T * true_x[States.ECEF_ORIENTATION, 0] + inv_err_function_sym[States.ECEF_ORIENTATION_ERR, 0] = sp.Matrix(2 * delta_quat[1:]) + inv_err_function_sym[States.ECEF_ORIENTATION_ERR.stop:, 0] = sp.Matrix(-nom_x[States.ECEF_ORIENTATION.stop:, 0] + true_x[States.ECEF_ORIENTATION.stop:, 0]) + + eskf_params = [[err_function_sym, nom_x, delta_x], + [inv_err_function_sym, nom_x, true_x], + H_mod_sym, f_err_sym, state_err_sym] + # + # Observation functions + # + h_gyro_sym = sp.Matrix([ + vroll + roll_bias, + vpitch + pitch_bias, + vyaw + yaw_bias]) + + pos = sp.Matrix([x, y, z]) + gravity = quat_rot.T * ((EARTH_GM / ((x**2 + y**2 + z**2)**(3.0 / 2.0))) * pos) + h_acc_sym = (gravity + acceleration + acc_bias) + h_acc_stationary_sym = acceleration + h_phone_rot_sym = sp.Matrix([vroll, vpitch, vyaw]) + h_pos_sym = sp.Matrix([x, y, z]) + h_vel_sym = sp.Matrix([vx, vy, vz]) + h_orientation_sym = q + h_relative_motion = sp.Matrix(quat_rot.T * v) + + obs_eqs = [[h_gyro_sym, ObservationKind.PHONE_GYRO, None], + [h_phone_rot_sym, ObservationKind.NO_ROT, None], + [h_acc_sym, ObservationKind.PHONE_ACCEL, None], + [h_pos_sym, ObservationKind.ECEF_POS, None], + [h_vel_sym, ObservationKind.ECEF_VEL, None], + [h_orientation_sym, ObservationKind.ECEF_ORIENTATION_FROM_GPS, None], + [h_relative_motion, ObservationKind.CAMERA_ODO_TRANSLATION, None], + [h_phone_rot_sym, ObservationKind.CAMERA_ODO_ROTATION, None], + [h_acc_stationary_sym, ObservationKind.NO_ACCEL, None]] + + # this returns a sympy routine for the jacobian of the observation function of the local vel + in_vec = sp.MatrixSymbol('in_vec', 6, 1) # roll, pitch, yaw, vx, vy, vz + h = euler_rotate(in_vec[0], in_vec[1], in_vec[2]).T * (sp.Matrix([in_vec[3], in_vec[4], in_vec[5]])) + extra_routines = [('H', h.jacobian(in_vec), [in_vec])] + + gen_code(generated_dir, name, f_sym, dt, state_sym, obs_eqs, dim_state, dim_state_err, eskf_params, extra_routines=extra_routines) + + # write constants to extra header file for use in cpp + live_kf_header = "#pragma once\n\n" + live_kf_header += "#include \n" + live_kf_header += "#include \n\n" + for state, slc in inspect.getmembers(States, lambda x: isinstance(x, slice)): + assert(slc.step is None) # unsupported + live_kf_header += f'#define STATE_{state}_START {slc.start}\n' + live_kf_header += f'#define STATE_{state}_END {slc.stop}\n' + live_kf_header += f'#define STATE_{state}_LEN {slc.stop - slc.start}\n' + live_kf_header += "\n" + + for kind, val in inspect.getmembers(ObservationKind, lambda x: isinstance(x, int)): + live_kf_header += f'#define OBSERVATION_{kind} {val}\n' + live_kf_header += "\n" + + live_kf_header += f"static const Eigen::VectorXd live_initial_x = {numpy2eigenstring(LiveKalman.initial_x)};\n" + live_kf_header += f"static const Eigen::VectorXd live_initial_P_diag = {numpy2eigenstring(LiveKalman.initial_P_diag)};\n" + live_kf_header += f"static const Eigen::VectorXd live_fake_gps_pos_cov_diag = {numpy2eigenstring(LiveKalman.fake_gps_pos_cov_diag)};\n" + live_kf_header += f"static const Eigen::VectorXd live_fake_gps_vel_cov_diag = {numpy2eigenstring(LiveKalman.fake_gps_vel_cov_diag)};\n" + live_kf_header += f"static const Eigen::VectorXd live_reset_orientation_diag = {numpy2eigenstring(LiveKalman.reset_orientation_diag)};\n" + live_kf_header += f"static const Eigen::VectorXd live_Q_diag = {numpy2eigenstring(LiveKalman.Q_diag)};\n" + live_kf_header += "static const std::unordered_map> live_obs_noise_diag = {\n" + for kind, noise in LiveKalman.obs_noise_diag.items(): + live_kf_header += f" {{ {kind}, {numpy2eigenstring(noise)} }},\n" + live_kf_header += "};\n\n" + + open(os.path.join(generated_dir, "live_kf_constants.h"), 'w').write(live_kf_header) + + +if __name__ == "__main__": + generated_dir = sys.argv[2] + LiveKalman.generate_code(generated_dir) diff --git a/sunnypilot/selfdrive/locationd/tests/.gitignore b/sunnypilot/selfdrive/locationd/tests/.gitignore new file mode 100644 index 0000000000..89f9ac04aa --- /dev/null +++ b/sunnypilot/selfdrive/locationd/tests/.gitignore @@ -0,0 +1 @@ +out/ diff --git a/sunnypilot/selfdrive/locationd/tests/__init__.py b/sunnypilot/selfdrive/locationd/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sunnypilot/selfdrive/locationd/tests/test_locationd.py b/sunnypilot/selfdrive/locationd/tests/test_locationd.py new file mode 100644 index 0000000000..c409f5b5a5 --- /dev/null +++ b/sunnypilot/selfdrive/locationd/tests/test_locationd.py @@ -0,0 +1,89 @@ +import pytest +import json +import random +import time +import capnp + +import cereal.messaging as messaging +from cereal.services import SERVICE_LIST +from openpilot.common.params import Params +from openpilot.common.transformations.coordinates import ecef2geodetic + +from openpilot.system.manager.process_config import managed_processes + + +class TestLocationdProc: + LLD_MSGS = ['gpsLocationExternal', 'cameraOdometry', 'carState', 'liveCalibration', + 'accelerometer', 'gyroscope', 'magnetometer'] + + def setup_method(self): + self.pm = messaging.PubMaster(self.LLD_MSGS) + + self.params = Params() + self.params.put_bool("UbloxAvailable", True) + managed_processes['locationd_llk'].prepare() + managed_processes['locationd_llk'].start() + + def teardown_method(self): + managed_processes['locationd_llk'].stop() + + def get_msg(self, name, t): + try: + msg = messaging.new_message(name) + except capnp.lib.capnp.KjException: + msg = messaging.new_message(name, 0) + + if name == "gpsLocationExternal": + msg.gpsLocationExternal.flags = 1 + msg.gpsLocationExternal.hasFix = True + msg.gpsLocationExternal.verticalAccuracy = 1.0 + msg.gpsLocationExternal.speedAccuracy = 1.0 + msg.gpsLocationExternal.bearingAccuracyDeg = 1.0 + msg.gpsLocationExternal.vNED = [0.0, 0.0, 0.0] + msg.gpsLocationExternal.latitude = float(self.lat) + msg.gpsLocationExternal.longitude = float(self.lon) + msg.gpsLocationExternal.unixTimestampMillis = t * 1e6 + msg.gpsLocationExternal.altitude = float(self.alt) + #if name == "gnssMeasurements": + # msg.gnssMeasurements.measTime = t + # msg.gnssMeasurements.positionECEF.value = [self.x , self.y, self.z] + # msg.gnssMeasurements.positionECEF.std = [0,0,0] + # msg.gnssMeasurements.positionECEF.valid = True + # msg.gnssMeasurements.velocityECEF.value = [] + # msg.gnssMeasurements.velocityECEF.std = [0,0,0] + # msg.gnssMeasurements.velocityECEF.valid = True + elif name == 'cameraOdometry': + msg.cameraOdometry.rot = [0.0, 0.0, 0.0] + msg.cameraOdometry.rotStd = [0.0, 0.0, 0.0] + msg.cameraOdometry.trans = [0.0, 0.0, 0.0] + msg.cameraOdometry.transStd = [0.0, 0.0, 0.0] + msg.logMonoTime = t + msg.valid = True + return msg + + def test_params_gps(self): + random.seed(123489234) + self.params.remove('LastGPSPositionLLK') + + self.x = -2710700 + (random.random() * 1e5) + self.y = -4280600 + (random.random() * 1e5) + self.z = 3850300 + (random.random() * 1e5) + self.lat, self.lon, self.alt = ecef2geodetic([self.x, self.y, self.z]) + + # get fake messages at the correct frequency, listed in services.py + msgs = [] + for sec in range(65): + for name in self.LLD_MSGS: + for j in range(int(SERVICE_LIST[name].frequency)): + msgs.append(self.get_msg(name, int((sec + j / SERVICE_LIST[name].frequency) * 1e9))) + + for msg in sorted(msgs, key=lambda x: x.logMonoTime): + self.pm.send(msg.which(), msg) + if msg.which() == "cameraOdometry": + self.pm.wait_for_readers_to_update(msg.which(), 0.1, dt=0.005) + time.sleep(1) # wait for async params write + + lastGPS = json.loads(self.params.get('LastGPSPositionLLK')) + assert lastGPS['latitude'] == pytest.approx(self.lat, abs=0.001) + assert lastGPS['longitude'] == pytest.approx(self.lon, abs=0.001) + assert lastGPS['altitude'] == pytest.approx(self.alt, abs=0.001) diff --git a/sunnypilot/system/sensord/.gitignore b/sunnypilot/system/sensord/.gitignore new file mode 100644 index 0000000000..e17675e254 --- /dev/null +++ b/sunnypilot/system/sensord/.gitignore @@ -0,0 +1 @@ +sensord diff --git a/sunnypilot/system/sensord/SConscript b/sunnypilot/system/sensord/SConscript new file mode 100644 index 0000000000..1222f0bfcd --- /dev/null +++ b/sunnypilot/system/sensord/SConscript @@ -0,0 +1,13 @@ +Import('env', 'arch', 'common', 'messaging') + +sensors = [ + 'sensors/i2c_sensor.cc', + 'sensors/lsm6ds3_accel.cc', + 'sensors/lsm6ds3_gyro.cc', + 'sensors/lsm6ds3_temp.cc', + 'sensors/mmc5603nj_magn.cc', +] +libs = [common, messaging, 'pthread'] +if arch == "larch64": + libs.append('i2c') +env.Program('sensord', ['sensors_qcom2.cc'] + sensors, LIBS=libs) diff --git a/sunnypilot/system/sensord/sensors/bmx055_accel.cc b/sunnypilot/system/sensord/sensors/bmx055_accel.cc new file mode 100644 index 0000000000..5db10c3b5b --- /dev/null +++ b/sunnypilot/system/sensord/sensors/bmx055_accel.cc @@ -0,0 +1,85 @@ +#include "sunnypilot/system/sensord/sensors/bmx055_accel.h" + +#include + +#include "common/swaglog.h" +#include "common/timing.h" +#include "common/util.h" + +BMX055_Accel::BMX055_Accel(I2CBus *bus) : I2CSensor(bus) {} + +int BMX055_Accel::init() { + int ret = verify_chip_id(BMX055_ACCEL_I2C_REG_ID, {BMX055_ACCEL_CHIP_ID}); + if (ret == -1) { + goto fail; + } + + ret = set_register(BMX055_ACCEL_I2C_REG_PMU, BMX055_ACCEL_NORMAL_MODE); + if (ret < 0) { + goto fail; + } + + // bmx055 accel has a 1.3ms wakeup time from deep suspend mode + util::sleep_for(10); + + // High bandwidth + // ret = set_register(BMX055_ACCEL_I2C_REG_HBW, BMX055_ACCEL_HBW_ENABLE); + // if (ret < 0) { + // goto fail; + // } + + // Low bandwidth + ret = set_register(BMX055_ACCEL_I2C_REG_HBW, BMX055_ACCEL_HBW_DISABLE); + if (ret < 0) { + goto fail; + } + + ret = set_register(BMX055_ACCEL_I2C_REG_BW, BMX055_ACCEL_BW_125HZ); + if (ret < 0) { + goto fail; + } + + enabled = true; + +fail: + return ret; +} + +int BMX055_Accel::shutdown() { + if (!enabled) return 0; + + // enter deep suspend mode (lowest power mode) + int ret = set_register(BMX055_ACCEL_I2C_REG_PMU, BMX055_ACCEL_DEEP_SUSPEND); + if (ret < 0) { + LOGE("Could not move BMX055 ACCEL in deep suspend mode!"); + } + + return ret; +} + +bool BMX055_Accel::get_event(MessageBuilder &msg, uint64_t ts) { + uint64_t start_time = nanos_since_boot(); + uint8_t buffer[6]; + int len = read_register(BMX055_ACCEL_I2C_REG_X_LSB, buffer, sizeof(buffer)); + assert(len == 6); + + // 12 bit = +-2g + float scale = 9.81 * 2.0f / (1 << 11); + float x = -read_12_bit(buffer[0], buffer[1]) * scale; + float y = -read_12_bit(buffer[2], buffer[3]) * scale; + float z = read_12_bit(buffer[4], buffer[5]) * scale; + + auto event = msg.initEvent().initAccelerometer2(); + event.setSource(cereal::SensorEventData::SensorSource::BMX055); + event.setVersion(1); + event.setSensor(SENSOR_ACCELEROMETER); + event.setType(SENSOR_TYPE_ACCELEROMETER); + event.setTimestamp(start_time); + + float xyz[] = {x, y, z}; + auto svec = event.initAcceleration(); + svec.setV(xyz); + svec.setStatus(true); + + return true; +} diff --git a/sunnypilot/system/sensord/sensors/bmx055_accel.h b/sunnypilot/system/sensord/sensors/bmx055_accel.h new file mode 100644 index 0000000000..4aea163c8b --- /dev/null +++ b/sunnypilot/system/sensord/sensors/bmx055_accel.h @@ -0,0 +1,41 @@ +#pragma once + +#include "sunnypilot/system/sensord/sensors/i2c_sensor.h" + +// Address of the chip on the bus +#define BMX055_ACCEL_I2C_ADDR 0x18 + +// Registers of the chip +#define BMX055_ACCEL_I2C_REG_ID 0x00 +#define BMX055_ACCEL_I2C_REG_X_LSB 0x02 +#define BMX055_ACCEL_I2C_REG_TEMP 0x08 +#define BMX055_ACCEL_I2C_REG_BW 0x10 +#define BMX055_ACCEL_I2C_REG_PMU 0x11 +#define BMX055_ACCEL_I2C_REG_HBW 0x13 +#define BMX055_ACCEL_I2C_REG_FIFO 0x3F + +// Constants +#define BMX055_ACCEL_CHIP_ID 0xFA + +#define BMX055_ACCEL_HBW_ENABLE 0b10000000 +#define BMX055_ACCEL_HBW_DISABLE 0b00000000 +#define BMX055_ACCEL_DEEP_SUSPEND 0b00100000 +#define BMX055_ACCEL_NORMAL_MODE 0b00000000 + +#define BMX055_ACCEL_BW_7_81HZ 0b01000 +#define BMX055_ACCEL_BW_15_63HZ 0b01001 +#define BMX055_ACCEL_BW_31_25HZ 0b01010 +#define BMX055_ACCEL_BW_62_5HZ 0b01011 +#define BMX055_ACCEL_BW_125HZ 0b01100 +#define BMX055_ACCEL_BW_250HZ 0b01101 +#define BMX055_ACCEL_BW_500HZ 0b01110 +#define BMX055_ACCEL_BW_1000HZ 0b01111 + +class BMX055_Accel : public I2CSensor { + uint8_t get_device_address() {return BMX055_ACCEL_I2C_ADDR;} +public: + BMX055_Accel(I2CBus *bus); + int init(); + bool get_event(MessageBuilder &msg, uint64_t ts = 0); + int shutdown(); +}; diff --git a/sunnypilot/system/sensord/sensors/bmx055_gyro.cc b/sunnypilot/system/sensord/sensors/bmx055_gyro.cc new file mode 100644 index 0000000000..4701c70d71 --- /dev/null +++ b/sunnypilot/system/sensord/sensors/bmx055_gyro.cc @@ -0,0 +1,92 @@ +#include "sunnypilot/system/sensord/sensors/bmx055_gyro.h" + +#include +#include + +#include "common/swaglog.h" +#include "common/util.h" + +#define DEG2RAD(x) ((x) * M_PI / 180.0) + + +BMX055_Gyro::BMX055_Gyro(I2CBus *bus) : I2CSensor(bus) {} + +int BMX055_Gyro::init() { + int ret = verify_chip_id(BMX055_GYRO_I2C_REG_ID, {BMX055_GYRO_CHIP_ID}); + if (ret == -1) return -1; + + ret = set_register(BMX055_GYRO_I2C_REG_LPM1, BMX055_GYRO_NORMAL_MODE); + if (ret < 0) { + goto fail; + } + // bmx055 gyro has a 30ms wakeup time from deep suspend mode + util::sleep_for(50); + + // High bandwidth + // ret = set_register(BMX055_GYRO_I2C_REG_HBW, BMX055_GYRO_HBW_ENABLE); + // if (ret < 0) { + // goto fail; + // } + + // Low bandwidth + ret = set_register(BMX055_GYRO_I2C_REG_HBW, BMX055_GYRO_HBW_DISABLE); + if (ret < 0) { + goto fail; + } + + // 116 Hz filter + ret = set_register(BMX055_GYRO_I2C_REG_BW, BMX055_GYRO_BW_116HZ); + if (ret < 0) { + goto fail; + } + + // +- 125 deg/s range + ret = set_register(BMX055_GYRO_I2C_REG_RANGE, BMX055_GYRO_RANGE_125); + if (ret < 0) { + goto fail; + } + + enabled = true; + +fail: + return ret; +} + +int BMX055_Gyro::shutdown() { + if (!enabled) return 0; + + // enter deep suspend mode (lowest power mode) + int ret = set_register(BMX055_GYRO_I2C_REG_LPM1, BMX055_GYRO_DEEP_SUSPEND); + if (ret < 0) { + LOGE("Could not move BMX055 GYRO in deep suspend mode!"); + } + + return ret; +} + +bool BMX055_Gyro::get_event(MessageBuilder &msg, uint64_t ts) { + uint64_t start_time = nanos_since_boot(); + uint8_t buffer[6]; + int len = read_register(BMX055_GYRO_I2C_REG_RATE_X_LSB, buffer, sizeof(buffer)); + assert(len == 6); + + // 16 bit = +- 125 deg/s + float scale = 125.0f / (1 << 15); + float x = -DEG2RAD(read_16_bit(buffer[0], buffer[1]) * scale); + float y = -DEG2RAD(read_16_bit(buffer[2], buffer[3]) * scale); + float z = DEG2RAD(read_16_bit(buffer[4], buffer[5]) * scale); + + auto event = msg.initEvent().initGyroscope2(); + event.setSource(cereal::SensorEventData::SensorSource::BMX055); + event.setVersion(1); + event.setSensor(SENSOR_GYRO_UNCALIBRATED); + event.setType(SENSOR_TYPE_GYROSCOPE_UNCALIBRATED); + event.setTimestamp(start_time); + + float xyz[] = {x, y, z}; + auto svec = event.initGyroUncalibrated(); + svec.setV(xyz); + svec.setStatus(true); + + return true; +} diff --git a/sunnypilot/system/sensord/sensors/bmx055_gyro.h b/sunnypilot/system/sensord/sensors/bmx055_gyro.h new file mode 100644 index 0000000000..489184bb18 --- /dev/null +++ b/sunnypilot/system/sensord/sensors/bmx055_gyro.h @@ -0,0 +1,41 @@ +#pragma once + +#include "sunnypilot/system/sensord/sensors/i2c_sensor.h" + +// Address of the chip on the bus +#define BMX055_GYRO_I2C_ADDR 0x68 + +// Registers of the chip +#define BMX055_GYRO_I2C_REG_ID 0x00 +#define BMX055_GYRO_I2C_REG_RATE_X_LSB 0x02 +#define BMX055_GYRO_I2C_REG_RANGE 0x0F +#define BMX055_GYRO_I2C_REG_BW 0x10 +#define BMX055_GYRO_I2C_REG_LPM1 0x11 +#define BMX055_GYRO_I2C_REG_HBW 0x13 +#define BMX055_GYRO_I2C_REG_FIFO 0x3F + +// Constants +#define BMX055_GYRO_CHIP_ID 0x0F + +#define BMX055_GYRO_HBW_ENABLE 0b10000000 +#define BMX055_GYRO_HBW_DISABLE 0b00000000 +#define BMX055_GYRO_DEEP_SUSPEND 0b00100000 +#define BMX055_GYRO_NORMAL_MODE 0b00000000 + +#define BMX055_GYRO_RANGE_2000 0b000 +#define BMX055_GYRO_RANGE_1000 0b001 +#define BMX055_GYRO_RANGE_500 0b010 +#define BMX055_GYRO_RANGE_250 0b011 +#define BMX055_GYRO_RANGE_125 0b100 + +#define BMX055_GYRO_BW_116HZ 0b0010 + + +class BMX055_Gyro : public I2CSensor { + uint8_t get_device_address() {return BMX055_GYRO_I2C_ADDR;} +public: + BMX055_Gyro(I2CBus *bus); + int init(); + bool get_event(MessageBuilder &msg, uint64_t ts = 0); + int shutdown(); +}; diff --git a/sunnypilot/system/sensord/sensors/bmx055_magn.cc b/sunnypilot/system/sensord/sensors/bmx055_magn.cc new file mode 100644 index 0000000000..00b35aa136 --- /dev/null +++ b/sunnypilot/system/sensord/sensors/bmx055_magn.cc @@ -0,0 +1,258 @@ +#include "sunnypilot/system/sensord/sensors/bmx055_magn.h" + +#include + +#include +#include +#include + +#include "common/swaglog.h" +#include "common/util.h" + +static int16_t compensate_x(trim_data_t trim_data, int16_t mag_data_x, uint16_t data_rhall) { + uint16_t process_comp_x0 = data_rhall; + int32_t process_comp_x1 = ((int32_t)trim_data.dig_xyz1) * 16384; + uint16_t process_comp_x2 = ((uint16_t)(process_comp_x1 / process_comp_x0)) - ((uint16_t)0x4000); + int16_t retval = ((int16_t)process_comp_x2); + int32_t process_comp_x3 = (((int32_t)retval) * ((int32_t)retval)); + int32_t process_comp_x4 = (((int32_t)trim_data.dig_xy2) * (process_comp_x3 / 128)); + int32_t process_comp_x5 = (int32_t)(((int16_t)trim_data.dig_xy1) * 128); + int32_t process_comp_x6 = ((int32_t)retval) * process_comp_x5; + int32_t process_comp_x7 = (((process_comp_x4 + process_comp_x6) / 512) + ((int32_t)0x100000)); + int32_t process_comp_x8 = ((int32_t)(((int16_t)trim_data.dig_x2) + ((int16_t)0xA0))); + int32_t process_comp_x9 = ((process_comp_x7 * process_comp_x8) / 4096); + int32_t process_comp_x10 = ((int32_t)mag_data_x) * process_comp_x9; + retval = ((int16_t)(process_comp_x10 / 8192)); + retval = (retval + (((int16_t)trim_data.dig_x1) * 8)) / 16; + + return retval; +} + +static int16_t compensate_y(trim_data_t trim_data, int16_t mag_data_y, uint16_t data_rhall) { + uint16_t process_comp_y0 = trim_data.dig_xyz1; + int32_t process_comp_y1 = (((int32_t)trim_data.dig_xyz1) * 16384) / process_comp_y0; + uint16_t process_comp_y2 = ((uint16_t)process_comp_y1) - ((uint16_t)0x4000); + int16_t retval = ((int16_t)process_comp_y2); + int32_t process_comp_y3 = ((int32_t) retval) * ((int32_t)retval); + int32_t process_comp_y4 = ((int32_t)trim_data.dig_xy2) * (process_comp_y3 / 128); + int32_t process_comp_y5 = ((int32_t)(((int16_t)trim_data.dig_xy1) * 128)); + int32_t process_comp_y6 = ((process_comp_y4 + (((int32_t)retval) * process_comp_y5)) / 512); + int32_t process_comp_y7 = ((int32_t)(((int16_t)trim_data.dig_y2) + ((int16_t)0xA0))); + int32_t process_comp_y8 = (((process_comp_y6 + ((int32_t)0x100000)) * process_comp_y7) / 4096); + int32_t process_comp_y9 = (((int32_t)mag_data_y) * process_comp_y8); + retval = (int16_t)(process_comp_y9 / 8192); + retval = (retval + (((int16_t)trim_data.dig_y1) * 8)) / 16; + + return retval; +} + +static int16_t compensate_z(trim_data_t trim_data, int16_t mag_data_z, uint16_t data_rhall) { + int16_t process_comp_z0 = ((int16_t)data_rhall) - ((int16_t) trim_data.dig_xyz1); + int32_t process_comp_z1 = (((int32_t)trim_data.dig_z3) * ((int32_t)(process_comp_z0))) / 4; + int32_t process_comp_z2 = (((int32_t)(mag_data_z - trim_data.dig_z4)) * 32768); + int32_t process_comp_z3 = ((int32_t)trim_data.dig_z1) * (((int16_t)data_rhall) * 2); + int16_t process_comp_z4 = (int16_t)((process_comp_z3 + (32768)) / 65536); + int32_t retval = ((process_comp_z2 - process_comp_z1) / (trim_data.dig_z2 + process_comp_z4)); + + /* saturate result to +/- 2 micro-tesla */ + retval = std::clamp(retval, -32767, 32767); + + /* Conversion of LSB to micro-tesla*/ + retval = retval / 16; + + return (int16_t)retval; +} + +BMX055_Magn::BMX055_Magn(I2CBus *bus) : I2CSensor(bus) {} + +int BMX055_Magn::init() { + uint8_t trim_x1y1[2] = {0}; + uint8_t trim_x2y2[2] = {0}; + uint8_t trim_xy1xy2[2] = {0}; + uint8_t trim_z1[2] = {0}; + uint8_t trim_z2[2] = {0}; + uint8_t trim_z3[2] = {0}; + uint8_t trim_z4[2] = {0}; + uint8_t trim_xyz1[2] = {0}; + + // suspend -> sleep + int ret = set_register(BMX055_MAGN_I2C_REG_PWR_0, 0x01); + if (ret < 0) { + LOGD("Enabling power failed: %d", ret); + goto fail; + } + util::sleep_for(5); // wait until the chip is powered on + + ret = verify_chip_id(BMX055_MAGN_I2C_REG_ID, {BMX055_MAGN_CHIP_ID}); + if (ret == -1) { + goto fail; + } + + // Load magnetometer trim + ret = read_register(BMX055_MAGN_I2C_REG_DIG_X1, trim_x1y1, 2); + if (ret < 0) goto fail; + ret = read_register(BMX055_MAGN_I2C_REG_DIG_X2, trim_x2y2, 2); + if (ret < 0) goto fail; + ret = read_register(BMX055_MAGN_I2C_REG_DIG_XY2, trim_xy1xy2, 2); + if (ret < 0) goto fail; + ret = read_register(BMX055_MAGN_I2C_REG_DIG_Z1_LSB, trim_z1, 2); + if (ret < 0) goto fail; + ret = read_register(BMX055_MAGN_I2C_REG_DIG_Z2_LSB, trim_z2, 2); + if (ret < 0) goto fail; + ret = read_register(BMX055_MAGN_I2C_REG_DIG_Z3_LSB, trim_z3, 2); + if (ret < 0) goto fail; + ret = read_register(BMX055_MAGN_I2C_REG_DIG_Z4_LSB, trim_z4, 2); + if (ret < 0) goto fail; + ret = read_register(BMX055_MAGN_I2C_REG_DIG_XYZ1_LSB, trim_xyz1, 2); + if (ret < 0) goto fail; + + // Read trim data + trim_data.dig_x1 = trim_x1y1[0]; + trim_data.dig_y1 = trim_x1y1[1]; + + trim_data.dig_x2 = trim_x2y2[0]; + trim_data.dig_y2 = trim_x2y2[1]; + + trim_data.dig_xy1 = trim_xy1xy2[1]; // NB: MSB/LSB swapped + trim_data.dig_xy2 = trim_xy1xy2[0]; + + trim_data.dig_z1 = read_16_bit(trim_z1[0], trim_z1[1]); + trim_data.dig_z2 = read_16_bit(trim_z2[0], trim_z2[1]); + trim_data.dig_z3 = read_16_bit(trim_z3[0], trim_z3[1]); + trim_data.dig_z4 = read_16_bit(trim_z4[0], trim_z4[1]); + + trim_data.dig_xyz1 = read_16_bit(trim_xyz1[0], trim_xyz1[1] & 0x7f); + assert(trim_data.dig_xyz1 != 0); + + perform_self_test(); + + // f_max = 1 / (145us * nXY + 500us * NZ + 980us) + // Chose NXY = 7, NZ = 12, which gives 125 Hz, + // and has the same ratio as the high accuracy preset + ret = set_register(BMX055_MAGN_I2C_REG_REPXY, (7 - 1) / 2); + if (ret < 0) { + goto fail; + } + + ret = set_register(BMX055_MAGN_I2C_REG_REPZ, 12 - 1); + if (ret < 0) { + goto fail; + } + + enabled = true; + return 0; + + fail: + return ret; +} + +int BMX055_Magn::shutdown() { + if (!enabled) return 0; + + // move to suspend mode + int ret = set_register(BMX055_MAGN_I2C_REG_PWR_0, 0); + if (ret < 0) { + LOGE("Could not move BMX055 MAGN in suspend mode!"); + } + + return ret; +} + +bool BMX055_Magn::perform_self_test() { + uint8_t buffer[8]; + int16_t x, y; + int16_t neg_z, pos_z; + + // Increase z reps for less false positives (~30 Hz ODR) + set_register(BMX055_MAGN_I2C_REG_REPXY, 1); + set_register(BMX055_MAGN_I2C_REG_REPZ, 64 - 1); + + // Clean existing measurement + read_register(BMX055_MAGN_I2C_REG_DATAX_LSB, buffer, sizeof(buffer)); + + uint8_t forced = BMX055_MAGN_FORCED; + + // Negative current + set_register(BMX055_MAGN_I2C_REG_MAG, forced | (uint8_t(0b10) << 6)); + util::sleep_for(100); + + read_register(BMX055_MAGN_I2C_REG_DATAX_LSB, buffer, sizeof(buffer)); + parse_xyz(buffer, &x, &y, &neg_z); + + // Positive current + set_register(BMX055_MAGN_I2C_REG_MAG, forced | (uint8_t(0b11) << 6)); + util::sleep_for(100); + + read_register(BMX055_MAGN_I2C_REG_DATAX_LSB, buffer, sizeof(buffer)); + parse_xyz(buffer, &x, &y, &pos_z); + + // Put back in normal mode + set_register(BMX055_MAGN_I2C_REG_MAG, 0); + + int16_t diff = pos_z - neg_z; + bool passed = (diff > 180) && (diff < 240); + + if (!passed) { + LOGE("self test failed: neg %d pos %d diff %d", neg_z, pos_z, diff); + } + + return passed; +} + +bool BMX055_Magn::parse_xyz(uint8_t buffer[8], int16_t *x, int16_t *y, int16_t *z) { + bool ready = buffer[6] & 0x1; + if (ready) { + int16_t mdata_x = (int16_t) (((int16_t)buffer[1] << 8) | buffer[0]) >> 3; + int16_t mdata_y = (int16_t) (((int16_t)buffer[3] << 8) | buffer[2]) >> 3; + int16_t mdata_z = (int16_t) (((int16_t)buffer[5] << 8) | buffer[4]) >> 1; + uint16_t data_r = (uint16_t) (((uint16_t)buffer[7] << 8) | buffer[6]) >> 2; + assert(data_r != 0); + + *x = compensate_x(trim_data, mdata_x, data_r); + *y = compensate_y(trim_data, mdata_y, data_r); + *z = compensate_z(trim_data, mdata_z, data_r); + } + return ready; +} + + +bool BMX055_Magn::get_event(MessageBuilder &msg, uint64_t ts) { + uint64_t start_time = nanos_since_boot(); + uint8_t buffer[8]; + int16_t _x, _y, x, y, z; + + int len = read_register(BMX055_MAGN_I2C_REG_DATAX_LSB, buffer, sizeof(buffer)); + assert(len == sizeof(buffer)); + + bool parsed = parse_xyz(buffer, &_x, &_y, &z); + if (parsed) { + + auto event = msg.initEvent().initMagnetometer(); + event.setSource(cereal::SensorEventData::SensorSource::BMX055); + event.setVersion(2); + event.setSensor(SENSOR_MAGNETOMETER_UNCALIBRATED); + event.setType(SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED); + event.setTimestamp(start_time); + + // Move magnetometer into same reference frame as accel/gryo + x = -_y; + y = _x; + + // Axis convention + x = -x; + y = -y; + + float xyz[] = {(float)x, (float)y, (float)z}; + auto svec = event.initMagneticUncalibrated(); + svec.setV(xyz); + svec.setStatus(true); + } + + // The BMX055 Magnetometer has no FIFO mode. Self running mode only goes + // up to 30 Hz. Therefore we put in forced mode, and request measurements + // at a 100 Hz. When reading the registers we have to check the ready bit + // To verify the measurement was completed this cycle. + set_register(BMX055_MAGN_I2C_REG_MAG, BMX055_MAGN_FORCED); + + return parsed; +} diff --git a/sunnypilot/system/sensord/sensors/bmx055_magn.h b/sunnypilot/system/sensord/sensors/bmx055_magn.h new file mode 100644 index 0000000000..7b1f7853d0 --- /dev/null +++ b/sunnypilot/system/sensord/sensors/bmx055_magn.h @@ -0,0 +1,64 @@ +#pragma once +#include + +#include "sunnypilot/system/sensord/sensors/i2c_sensor.h" + +// Address of the chip on the bus +#define BMX055_MAGN_I2C_ADDR 0x10 + +// Registers of the chip +#define BMX055_MAGN_I2C_REG_ID 0x40 +#define BMX055_MAGN_I2C_REG_PWR_0 0x4B +#define BMX055_MAGN_I2C_REG_MAG 0x4C +#define BMX055_MAGN_I2C_REG_DATAX_LSB 0x42 +#define BMX055_MAGN_I2C_REG_RHALL_LSB 0x48 +#define BMX055_MAGN_I2C_REG_REPXY 0x51 +#define BMX055_MAGN_I2C_REG_REPZ 0x52 + +#define BMX055_MAGN_I2C_REG_DIG_X1 0x5D +#define BMX055_MAGN_I2C_REG_DIG_Y1 0x5E +#define BMX055_MAGN_I2C_REG_DIG_Z4_LSB 0x62 +#define BMX055_MAGN_I2C_REG_DIG_Z4_MSB 0x63 +#define BMX055_MAGN_I2C_REG_DIG_X2 0x64 +#define BMX055_MAGN_I2C_REG_DIG_Y2 0x65 +#define BMX055_MAGN_I2C_REG_DIG_Z2_LSB 0x68 +#define BMX055_MAGN_I2C_REG_DIG_Z2_MSB 0x69 +#define BMX055_MAGN_I2C_REG_DIG_Z1_LSB 0x6A +#define BMX055_MAGN_I2C_REG_DIG_Z1_MSB 0x6B +#define BMX055_MAGN_I2C_REG_DIG_XYZ1_LSB 0x6C +#define BMX055_MAGN_I2C_REG_DIG_XYZ1_MSB 0x6D +#define BMX055_MAGN_I2C_REG_DIG_Z3_LSB 0x6E +#define BMX055_MAGN_I2C_REG_DIG_Z3_MSB 0x6F +#define BMX055_MAGN_I2C_REG_DIG_XY2 0x70 +#define BMX055_MAGN_I2C_REG_DIG_XY1 0x71 + +// Constants +#define BMX055_MAGN_CHIP_ID 0x32 +#define BMX055_MAGN_FORCED (0b01 << 1) + +struct trim_data_t { + int8_t dig_x1; + int8_t dig_y1; + int8_t dig_x2; + int8_t dig_y2; + uint16_t dig_z1; + int16_t dig_z2; + int16_t dig_z3; + int16_t dig_z4; + uint8_t dig_xy1; + int8_t dig_xy2; + uint16_t dig_xyz1; +}; + + +class BMX055_Magn : public I2CSensor{ + uint8_t get_device_address() {return BMX055_MAGN_I2C_ADDR;} + trim_data_t trim_data = {0}; + bool perform_self_test(); + bool parse_xyz(uint8_t buffer[8], int16_t *x, int16_t *y, int16_t *z); +public: + BMX055_Magn(I2CBus *bus); + int init(); + bool get_event(MessageBuilder &msg, uint64_t ts = 0); + int shutdown(); +}; diff --git a/sunnypilot/system/sensord/sensors/bmx055_temp.cc b/sunnypilot/system/sensord/sensors/bmx055_temp.cc new file mode 100644 index 0000000000..3932c66fa6 --- /dev/null +++ b/sunnypilot/system/sensord/sensors/bmx055_temp.cc @@ -0,0 +1,31 @@ +#include "sunnypilot/system/sensord/sensors/bmx055_temp.h" + +#include + +#include "sunnypilot/system/sensord/sensors/bmx055_accel.h" +#include "common/swaglog.h" +#include "common/timing.h" + +BMX055_Temp::BMX055_Temp(I2CBus *bus) : I2CSensor(bus) {} + +int BMX055_Temp::init() { + return verify_chip_id(BMX055_ACCEL_I2C_REG_ID, {BMX055_ACCEL_CHIP_ID}) == -1 ? -1 : 0; +} + +bool BMX055_Temp::get_event(MessageBuilder &msg, uint64_t ts) { + uint64_t start_time = nanos_since_boot(); + uint8_t buffer[1]; + int len = read_register(BMX055_ACCEL_I2C_REG_TEMP, buffer, sizeof(buffer)); + assert(len == sizeof(buffer)); + + float temp = 23.0f + int8_t(buffer[0]) / 2.0f; + + auto event = msg.initEvent().initTemperatureSensor(); + event.setSource(cereal::SensorEventData::SensorSource::BMX055); + event.setVersion(1); + event.setType(SENSOR_TYPE_AMBIENT_TEMPERATURE); + event.setTimestamp(start_time); + event.setTemperature(temp); + + return true; +} diff --git a/sunnypilot/system/sensord/sensors/bmx055_temp.h b/sunnypilot/system/sensord/sensors/bmx055_temp.h new file mode 100644 index 0000000000..02c48dc92c --- /dev/null +++ b/sunnypilot/system/sensord/sensors/bmx055_temp.h @@ -0,0 +1,13 @@ +#pragma once + +#include "sunnypilot/system/sensord/sensors/bmx055_accel.h" +#include "sunnypilot/system/sensord/sensors/i2c_sensor.h" + +class BMX055_Temp : public I2CSensor { + uint8_t get_device_address() {return BMX055_ACCEL_I2C_ADDR;} +public: + BMX055_Temp(I2CBus *bus); + int init(); + bool get_event(MessageBuilder &msg, uint64_t ts = 0); + int shutdown() { return 0; } +}; diff --git a/sunnypilot/system/sensord/sensors/constants.h b/sunnypilot/system/sensord/sensors/constants.h new file mode 100644 index 0000000000..c216f838a5 --- /dev/null +++ b/sunnypilot/system/sensord/sensors/constants.h @@ -0,0 +1,18 @@ +#pragma once + + +#define SENSOR_ACCELEROMETER 1 +#define SENSOR_MAGNETOMETER 2 +#define SENSOR_MAGNETOMETER_UNCALIBRATED 3 +#define SENSOR_GYRO 4 +#define SENSOR_GYRO_UNCALIBRATED 5 +#define SENSOR_LIGHT 7 + +#define SENSOR_TYPE_ACCELEROMETER 1 +#define SENSOR_TYPE_GEOMAGNETIC_FIELD 2 +#define SENSOR_TYPE_GYROSCOPE 4 +#define SENSOR_TYPE_LIGHT 5 +#define SENSOR_TYPE_AMBIENT_TEMPERATURE 13 +#define SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED 14 +#define SENSOR_TYPE_MAGNETIC_FIELD SENSOR_TYPE_GEOMAGNETIC_FIELD +#define SENSOR_TYPE_GYROSCOPE_UNCALIBRATED 16 diff --git a/sunnypilot/system/sensord/sensors/i2c_sensor.cc b/sunnypilot/system/sensord/sensors/i2c_sensor.cc new file mode 100644 index 0000000000..e29f98c721 --- /dev/null +++ b/sunnypilot/system/sensord/sensors/i2c_sensor.cc @@ -0,0 +1,50 @@ +#include "sunnypilot/system/sensord/sensors/i2c_sensor.h" + +int16_t read_12_bit(uint8_t lsb, uint8_t msb) { + uint16_t combined = (uint16_t(msb) << 8) | uint16_t(lsb & 0xF0); + return int16_t(combined) / (1 << 4); +} + +int16_t read_16_bit(uint8_t lsb, uint8_t msb) { + uint16_t combined = (uint16_t(msb) << 8) | uint16_t(lsb); + return int16_t(combined); +} + +int32_t read_20_bit(uint8_t b2, uint8_t b1, uint8_t b0) { + uint32_t combined = (uint32_t(b0) << 16) | (uint32_t(b1) << 8) | uint32_t(b2); + return int32_t(combined) / (1 << 4); +} + +I2CSensor::I2CSensor(I2CBus *bus, int gpio_nr, bool shared_gpio) : + bus(bus), gpio_nr(gpio_nr), shared_gpio(shared_gpio) {} + +I2CSensor::~I2CSensor() { + if (gpio_fd != -1) { + close(gpio_fd); + } +} + +int I2CSensor::read_register(uint register_address, uint8_t *buffer, uint8_t len) { + return bus->read_register(get_device_address(), register_address, buffer, len); +} + +int I2CSensor::set_register(uint register_address, uint8_t data) { + return bus->set_register(get_device_address(), register_address, data); +} + +int I2CSensor::init_gpio() { + if (shared_gpio || gpio_nr == 0) { + return 0; + } + + gpio_fd = gpiochip_get_ro_value_fd("sensord", GPIOCHIP_INT, gpio_nr); + if (gpio_fd < 0) { + return -1; + } + + return 0; +} + +bool I2CSensor::has_interrupt_enabled() { + return gpio_nr != 0; +} diff --git a/sunnypilot/system/sensord/sensors/i2c_sensor.h b/sunnypilot/system/sensord/sensors/i2c_sensor.h new file mode 100644 index 0000000000..6513db7934 --- /dev/null +++ b/sunnypilot/system/sensord/sensors/i2c_sensor.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include +#include +#include "cereal/gen/cpp/log.capnp.h" + +#include "common/i2c.h" +#include "common/gpio.h" + +#include "common/swaglog.h" +#include "sunnypilot/system/sensord/sensors/constants.h" +#include "sunnypilot/system/sensord/sensors/sensor.h" + +int16_t read_12_bit(uint8_t lsb, uint8_t msb); +int16_t read_16_bit(uint8_t lsb, uint8_t msb); +int32_t read_20_bit(uint8_t b2, uint8_t b1, uint8_t b0); + + +class I2CSensor : public Sensor { +private: + I2CBus *bus; + int gpio_nr; + bool shared_gpio; + virtual uint8_t get_device_address() = 0; + +public: + I2CSensor(I2CBus *bus, int gpio_nr = 0, bool shared_gpio = false); + ~I2CSensor(); + int read_register(uint register_address, uint8_t *buffer, uint8_t len); + int set_register(uint register_address, uint8_t data); + int init_gpio(); + bool has_interrupt_enabled(); + virtual int init() = 0; + virtual bool get_event(MessageBuilder &msg, uint64_t ts = 0) = 0; + virtual int shutdown() = 0; + + int verify_chip_id(uint8_t address, const std::vector &expected_ids) { + uint8_t chip_id = 0; + int ret = read_register(address, &chip_id, 1); + if (ret < 0) { + LOGD("Reading chip ID failed: %d", ret); + return -1; + } + for (int i = 0; i < expected_ids.size(); ++i) { + if (chip_id == expected_ids[i]) return chip_id; + } + LOGE("Chip ID wrong. Got: %d, Expected %d", chip_id, expected_ids[0]); + return -1; + } +}; diff --git a/sunnypilot/system/sensord/sensors/lsm6ds3_accel.cc b/sunnypilot/system/sensord/sensors/lsm6ds3_accel.cc new file mode 100644 index 0000000000..2857106944 --- /dev/null +++ b/sunnypilot/system/sensord/sensors/lsm6ds3_accel.cc @@ -0,0 +1,250 @@ +#include "sunnypilot/system/sensord/sensors/lsm6ds3_accel.h" + +#include +#include +#include + +#include "common/swaglog.h" +#include "common/timing.h" +#include "common/util.h" + +LSM6DS3_Accel::LSM6DS3_Accel(I2CBus *bus, int gpio_nr, bool shared_gpio) : + I2CSensor(bus, gpio_nr, shared_gpio) {} + +void LSM6DS3_Accel::wait_for_data_ready() { + uint8_t drdy = 0; + uint8_t buffer[6]; + + do { + read_register(LSM6DS3_ACCEL_I2C_REG_STAT_REG, &drdy, sizeof(drdy)); + drdy &= LSM6DS3_ACCEL_DRDY_XLDA; + } while (drdy == 0); + + read_register(LSM6DS3_ACCEL_I2C_REG_OUTX_L_XL, buffer, sizeof(buffer)); +} + +void LSM6DS3_Accel::read_and_avg_data(float* out_buf) { + uint8_t drdy = 0; + uint8_t buffer[6]; + + float scaling = 0.061f; + if (source == cereal::SensorEventData::SensorSource::LSM6DS3TRC) { + scaling = 0.122f; + } + + for (int i = 0; i < 5; i++) { + do { + read_register(LSM6DS3_ACCEL_I2C_REG_STAT_REG, &drdy, sizeof(drdy)); + drdy &= LSM6DS3_ACCEL_DRDY_XLDA; + } while (drdy == 0); + + int len = read_register(LSM6DS3_ACCEL_I2C_REG_OUTX_L_XL, buffer, sizeof(buffer)); + assert(len == sizeof(buffer)); + + for (int j = 0; j < 3; j++) { + out_buf[j] += (float)read_16_bit(buffer[j*2], buffer[j*2+1]) * scaling; + } + } + + for (int i = 0; i < 3; i++) { + out_buf[i] /= 5.0f; + } +} + +int LSM6DS3_Accel::self_test(int test_type) { + float val_st_off[3] = {0}; + float val_st_on[3] = {0}; + float test_val[3] = {0}; + uint8_t ODR_FS_MO = LSM6DS3_ACCEL_ODR_52HZ; // full scale: +-2g, ODR: 52Hz + + // prepare sensor for self-test + + // enable block data update and automatic increment + int ret = set_register(LSM6DS3_ACCEL_I2C_REG_CTRL3_C, LSM6DS3_ACCEL_IF_INC_BDU); + if (ret < 0) { + return ret; + } + + if (source == cereal::SensorEventData::SensorSource::LSM6DS3TRC) { + ODR_FS_MO = LSM6DS3_ACCEL_FS_4G | LSM6DS3_ACCEL_ODR_52HZ; + } + ret = set_register(LSM6DS3_ACCEL_I2C_REG_CTRL1_XL, ODR_FS_MO); + if (ret < 0) { + return ret; + } + + // wait for stable output, and discard first values + util::sleep_for(100); + wait_for_data_ready(); + read_and_avg_data(val_st_off); + + // enable Self Test positive (or negative) + ret = set_register(LSM6DS3_ACCEL_I2C_REG_CTRL5_C, test_type); + if (ret < 0) { + return ret; + } + + // wait for stable output, and discard first values + util::sleep_for(100); + wait_for_data_ready(); + read_and_avg_data(val_st_on); + + // disable sensor + ret = set_register(LSM6DS3_ACCEL_I2C_REG_CTRL1_XL, 0); + if (ret < 0) { + return ret; + } + + // disable self test + ret = set_register(LSM6DS3_ACCEL_I2C_REG_CTRL5_C, 0); + if (ret < 0) { + return ret; + } + + // calculate the mg values for self test + for (int i = 0; i < 3; i++) { + test_val[i] = fabs(val_st_on[i] - val_st_off[i]); + } + + // verify test result + for (int i = 0; i < 3; i++) { + if ((LSM6DS3_ACCEL_MIN_ST_LIMIT_mg > test_val[i]) || + (test_val[i] > LSM6DS3_ACCEL_MAX_ST_LIMIT_mg)) { + return -1; + } + } + + return ret; +} + +int LSM6DS3_Accel::init() { + uint8_t value = 0; + bool do_self_test = false; + + const char* env_lsm_selftest = std::getenv("LSM_SELF_TEST"); + if (env_lsm_selftest != nullptr && strncmp(env_lsm_selftest, "1", 1) == 0) { + do_self_test = true; + } + + int ret = verify_chip_id(LSM6DS3_ACCEL_I2C_REG_ID, {LSM6DS3_ACCEL_CHIP_ID, LSM6DS3TRC_ACCEL_CHIP_ID}); + if (ret == -1) return -1; + + if (ret == LSM6DS3TRC_ACCEL_CHIP_ID) { + source = cereal::SensorEventData::SensorSource::LSM6DS3TRC; + } + + ret = self_test(LSM6DS3_ACCEL_POSITIVE_TEST); + if (ret < 0) { + LOGE("LSM6DS3 accel positive self-test failed!"); + if (do_self_test) goto fail; + } + + ret = self_test(LSM6DS3_ACCEL_NEGATIVE_TEST); + if (ret < 0) { + LOGE("LSM6DS3 accel negative self-test failed!"); + if (do_self_test) goto fail; + } + + ret = init_gpio(); + if (ret < 0) { + goto fail; + } + + // enable continuous update, and automatic increase + ret = set_register(LSM6DS3_ACCEL_I2C_REG_CTRL3_C, LSM6DS3_ACCEL_IF_INC); + if (ret < 0) { + goto fail; + } + + // TODO: set scale and bandwidth. Default is +- 2G, 50 Hz + ret = set_register(LSM6DS3_ACCEL_I2C_REG_CTRL1_XL, LSM6DS3_ACCEL_ODR_104HZ); + if (ret < 0) { + goto fail; + } + + ret = set_register(LSM6DS3_ACCEL_I2C_REG_DRDY_CFG, LSM6DS3_ACCEL_DRDY_PULSE_MODE); + if (ret < 0) { + goto fail; + } + + // enable data ready interrupt for accel on INT1 + // (without resetting existing interrupts) + ret = read_register(LSM6DS3_ACCEL_I2C_REG_INT1_CTRL, &value, 1); + if (ret < 0) { + goto fail; + } + + value |= LSM6DS3_ACCEL_INT1_DRDY_XL; + ret = set_register(LSM6DS3_ACCEL_I2C_REG_INT1_CTRL, value); + +fail: + return ret; +} + +int LSM6DS3_Accel::shutdown() { + int ret = 0; + + // disable data ready interrupt for accel on INT1 + uint8_t value = 0; + ret = read_register(LSM6DS3_ACCEL_I2C_REG_INT1_CTRL, &value, 1); + if (ret < 0) { + goto fail; + } + + value &= ~(LSM6DS3_ACCEL_INT1_DRDY_XL); + ret = set_register(LSM6DS3_ACCEL_I2C_REG_INT1_CTRL, value); + if (ret < 0) { + LOGE("Could not disable lsm6ds3 acceleration interrupt!"); + goto fail; + } + + // enable power-down mode + value = 0; + ret = read_register(LSM6DS3_ACCEL_I2C_REG_CTRL1_XL, &value, 1); + if (ret < 0) { + goto fail; + } + + value &= 0x0F; + ret = set_register(LSM6DS3_ACCEL_I2C_REG_CTRL1_XL, value); + if (ret < 0) { + LOGE("Could not power-down lsm6ds3 accelerometer!"); + goto fail; + } + +fail: + return ret; +} + +bool LSM6DS3_Accel::get_event(MessageBuilder &msg, uint64_t ts) { + + // INT1 shared with gyro, check STATUS_REG who triggered + uint8_t status_reg = 0; + read_register(LSM6DS3_ACCEL_I2C_REG_STAT_REG, &status_reg, sizeof(status_reg)); + if ((status_reg & LSM6DS3_ACCEL_DRDY_XLDA) == 0) { + return false; + } + + uint8_t buffer[6]; + int len = read_register(LSM6DS3_ACCEL_I2C_REG_OUTX_L_XL, buffer, sizeof(buffer)); + assert(len == sizeof(buffer)); + + float scale = 9.81 * 2.0f / (1 << 15); + float x = read_16_bit(buffer[0], buffer[1]) * scale; + float y = read_16_bit(buffer[2], buffer[3]) * scale; + float z = read_16_bit(buffer[4], buffer[5]) * scale; + + auto event = msg.initEvent().initAccelerometer(); + event.setSource(source); + event.setVersion(1); + event.setSensor(SENSOR_ACCELEROMETER); + event.setType(SENSOR_TYPE_ACCELEROMETER); + event.setTimestamp(ts); + + float xyz[] = {y, -x, z}; + auto svec = event.initAcceleration(); + svec.setV(xyz); + svec.setStatus(true); + + return true; +} diff --git a/sunnypilot/system/sensord/sensors/lsm6ds3_accel.h b/sunnypilot/system/sensord/sensors/lsm6ds3_accel.h new file mode 100644 index 0000000000..2ac61c5a0f --- /dev/null +++ b/sunnypilot/system/sensord/sensors/lsm6ds3_accel.h @@ -0,0 +1,49 @@ +#pragma once + +#include "sunnypilot/system/sensord/sensors/i2c_sensor.h" + +// Address of the chip on the bus +#define LSM6DS3_ACCEL_I2C_ADDR 0x6A + +// Registers of the chip +#define LSM6DS3_ACCEL_I2C_REG_DRDY_CFG 0x0B +#define LSM6DS3_ACCEL_I2C_REG_ID 0x0F +#define LSM6DS3_ACCEL_I2C_REG_INT1_CTRL 0x0D +#define LSM6DS3_ACCEL_I2C_REG_CTRL1_XL 0x10 +#define LSM6DS3_ACCEL_I2C_REG_CTRL3_C 0x12 +#define LSM6DS3_ACCEL_I2C_REG_CTRL5_C 0x14 +#define LSM6DS3_ACCEL_I2C_REG_CTR9_XL 0x18 +#define LSM6DS3_ACCEL_I2C_REG_STAT_REG 0x1E +#define LSM6DS3_ACCEL_I2C_REG_OUTX_L_XL 0x28 + +// Constants +#define LSM6DS3_ACCEL_CHIP_ID 0x69 +#define LSM6DS3TRC_ACCEL_CHIP_ID 0x6A +#define LSM6DS3_ACCEL_FS_4G (0b10 << 2) +#define LSM6DS3_ACCEL_ODR_52HZ (0b0011 << 4) +#define LSM6DS3_ACCEL_ODR_104HZ (0b0100 << 4) +#define LSM6DS3_ACCEL_INT1_DRDY_XL 0b1 +#define LSM6DS3_ACCEL_DRDY_XLDA 0b1 +#define LSM6DS3_ACCEL_DRDY_PULSE_MODE (1 << 7) +#define LSM6DS3_ACCEL_IF_INC 0b00000100 +#define LSM6DS3_ACCEL_IF_INC_BDU 0b01000100 +#define LSM6DS3_ACCEL_XYZ_DEN 0b11100000 +#define LSM6DS3_ACCEL_POSITIVE_TEST 0b01 +#define LSM6DS3_ACCEL_NEGATIVE_TEST 0b10 +#define LSM6DS3_ACCEL_MIN_ST_LIMIT_mg 90.0f +#define LSM6DS3_ACCEL_MAX_ST_LIMIT_mg 1700.0f + +class LSM6DS3_Accel : public I2CSensor { + uint8_t get_device_address() {return LSM6DS3_ACCEL_I2C_ADDR;} + cereal::SensorEventData::SensorSource source = cereal::SensorEventData::SensorSource::LSM6DS3; + + // self test functions + int self_test(int test_type); + void wait_for_data_ready(); + void read_and_avg_data(float* val_st_off); +public: + LSM6DS3_Accel(I2CBus *bus, int gpio_nr = 0, bool shared_gpio = false); + int init(); + bool get_event(MessageBuilder &msg, uint64_t ts = 0); + int shutdown(); +}; diff --git a/sunnypilot/system/sensord/sensors/lsm6ds3_gyro.cc b/sunnypilot/system/sensord/sensors/lsm6ds3_gyro.cc new file mode 100644 index 0000000000..e881f3942a --- /dev/null +++ b/sunnypilot/system/sensord/sensors/lsm6ds3_gyro.cc @@ -0,0 +1,233 @@ +#include "sunnypilot/system/sensord/sensors/lsm6ds3_gyro.h" + +#include +#include +#include + +#include "common/swaglog.h" +#include "common/timing.h" +#include "common/util.h" + +#define DEG2RAD(x) ((x) * M_PI / 180.0) + +LSM6DS3_Gyro::LSM6DS3_Gyro(I2CBus *bus, int gpio_nr, bool shared_gpio) : + I2CSensor(bus, gpio_nr, shared_gpio) {} + +void LSM6DS3_Gyro::wait_for_data_ready() { + uint8_t drdy = 0; + uint8_t buffer[6]; + + do { + read_register(LSM6DS3_GYRO_I2C_REG_STAT_REG, &drdy, sizeof(drdy)); + drdy &= LSM6DS3_GYRO_DRDY_GDA; + } while (drdy == 0); + + read_register(LSM6DS3_GYRO_I2C_REG_OUTX_L_G, buffer, sizeof(buffer)); +} + +void LSM6DS3_Gyro::read_and_avg_data(float* out_buf) { + uint8_t drdy = 0; + uint8_t buffer[6]; + + for (int i = 0; i < 5; i++) { + do { + read_register(LSM6DS3_GYRO_I2C_REG_STAT_REG, &drdy, sizeof(drdy)); + drdy &= LSM6DS3_GYRO_DRDY_GDA; + } while (drdy == 0); + + int len = read_register(LSM6DS3_GYRO_I2C_REG_OUTX_L_G, buffer, sizeof(buffer)); + assert(len == sizeof(buffer)); + + for (int j = 0; j < 3; j++) { + out_buf[j] += (float)read_16_bit(buffer[j*2], buffer[j*2+1]) * 70.0f; + } + } + + // calculate the mg average values + for (int i = 0; i < 3; i++) { + out_buf[i] /= 5.0f; + } +} + +int LSM6DS3_Gyro::self_test(int test_type) { + float val_st_off[3] = {0}; + float val_st_on[3] = {0}; + float test_val[3] = {0}; + + // prepare sensor for self-test + + // full scale: 2000dps, ODR: 208Hz + int ret = set_register(LSM6DS3_GYRO_I2C_REG_CTRL2_G, LSM6DS3_GYRO_ODR_208HZ | LSM6DS3_GYRO_FS_2000dps); + if (ret < 0) { + return ret; + } + + // wait for stable output, and discard first values + util::sleep_for(150); + wait_for_data_ready(); + read_and_avg_data(val_st_off); + + // enable Self Test positive (or negative) + ret = set_register(LSM6DS3_GYRO_I2C_REG_CTRL5_C, test_type); + if (ret < 0) { + return ret; + } + + // wait for stable output, and discard first values + util::sleep_for(50); + wait_for_data_ready(); + read_and_avg_data(val_st_on); + + // disable sensor + ret = set_register(LSM6DS3_GYRO_I2C_REG_CTRL2_G, 0); + if (ret < 0) { + return ret; + } + + // disable self test + ret = set_register(LSM6DS3_GYRO_I2C_REG_CTRL5_C, 0); + if (ret < 0) { + return ret; + } + + // calculate the mg values for self test + for (int i = 0; i < 3; i++) { + test_val[i] = fabs(val_st_on[i] - val_st_off[i]); + } + + // verify test result + for (int i = 0; i < 3; i++) { + if ((LSM6DS3_GYRO_MIN_ST_LIMIT_mdps > test_val[i]) || + (test_val[i] > LSM6DS3_GYRO_MAX_ST_LIMIT_mdps)) { + return -1; + } + } + + return ret; +} + +int LSM6DS3_Gyro::init() { + uint8_t value = 0; + bool do_self_test = false; + + const char* env_lsm_selftest = std::getenv("LSM_SELF_TEST"); + if (env_lsm_selftest != nullptr && strncmp(env_lsm_selftest, "1", 1) == 0) { + do_self_test = true; + } + + int ret = verify_chip_id(LSM6DS3_GYRO_I2C_REG_ID, {LSM6DS3_GYRO_CHIP_ID, LSM6DS3TRC_GYRO_CHIP_ID}); + if (ret == -1) return -1; + + if (ret == LSM6DS3TRC_GYRO_CHIP_ID) { + source = cereal::SensorEventData::SensorSource::LSM6DS3TRC; + } + + ret = init_gpio(); + if (ret < 0) { + goto fail; + } + + ret = self_test(LSM6DS3_GYRO_POSITIVE_TEST); + if (ret < 0) { + LOGE("LSM6DS3 gyro positive self-test failed!"); + if (do_self_test) goto fail; + } + + ret = self_test(LSM6DS3_GYRO_NEGATIVE_TEST); + if (ret < 0) { + LOGE("LSM6DS3 gyro negative self-test failed!"); + if (do_self_test) goto fail; + } + + // TODO: set scale. Default is +- 250 deg/s + ret = set_register(LSM6DS3_GYRO_I2C_REG_CTRL2_G, LSM6DS3_GYRO_ODR_104HZ); + if (ret < 0) { + goto fail; + } + + ret = set_register(LSM6DS3_GYRO_I2C_REG_DRDY_CFG, LSM6DS3_GYRO_DRDY_PULSE_MODE); + if (ret < 0) { + goto fail; + } + + // enable data ready interrupt for gyro on INT1 + // (without resetting existing interrupts) + ret = read_register(LSM6DS3_GYRO_I2C_REG_INT1_CTRL, &value, 1); + if (ret < 0) { + goto fail; + } + + value |= LSM6DS3_GYRO_INT1_DRDY_G; + ret = set_register(LSM6DS3_GYRO_I2C_REG_INT1_CTRL, value); + +fail: + return ret; +} + +int LSM6DS3_Gyro::shutdown() { + int ret = 0; + + // disable data ready interrupt for gyro on INT1 + uint8_t value = 0; + ret = read_register(LSM6DS3_GYRO_I2C_REG_INT1_CTRL, &value, 1); + if (ret < 0) { + goto fail; + } + + value &= ~(LSM6DS3_GYRO_INT1_DRDY_G); + ret = set_register(LSM6DS3_GYRO_I2C_REG_INT1_CTRL, value); + if (ret < 0) { + LOGE("Could not disable lsm6ds3 gyroscope interrupt!"); + goto fail; + } + + // enable power-down mode + value = 0; + ret = read_register(LSM6DS3_GYRO_I2C_REG_CTRL2_G, &value, 1); + if (ret < 0) { + goto fail; + } + + value &= 0x0F; + ret = set_register(LSM6DS3_GYRO_I2C_REG_CTRL2_G, value); + if (ret < 0) { + LOGE("Could not power-down lsm6ds3 gyroscope!"); + goto fail; + } + +fail: + return ret; +} + +bool LSM6DS3_Gyro::get_event(MessageBuilder &msg, uint64_t ts) { + + // INT1 shared with accel, check STATUS_REG who triggered + uint8_t status_reg = 0; + read_register(LSM6DS3_GYRO_I2C_REG_STAT_REG, &status_reg, sizeof(status_reg)); + if ((status_reg & LSM6DS3_GYRO_DRDY_GDA) == 0) { + return false; + } + + uint8_t buffer[6]; + int len = read_register(LSM6DS3_GYRO_I2C_REG_OUTX_L_G, buffer, sizeof(buffer)); + assert(len == sizeof(buffer)); + + float scale = 8.75 / 1000.0; + float x = DEG2RAD(read_16_bit(buffer[0], buffer[1]) * scale); + float y = DEG2RAD(read_16_bit(buffer[2], buffer[3]) * scale); + float z = DEG2RAD(read_16_bit(buffer[4], buffer[5]) * scale); + + auto event = msg.initEvent().initGyroscope(); + event.setSource(source); + event.setVersion(2); + event.setSensor(SENSOR_GYRO_UNCALIBRATED); + event.setType(SENSOR_TYPE_GYROSCOPE_UNCALIBRATED); + event.setTimestamp(ts); + + float xyz[] = {y, -x, z}; + auto svec = event.initGyroUncalibrated(); + svec.setV(xyz); + svec.setStatus(true); + + return true; +} diff --git a/sunnypilot/system/sensord/sensors/lsm6ds3_gyro.h b/sunnypilot/system/sensord/sensors/lsm6ds3_gyro.h new file mode 100644 index 0000000000..686a6a7169 --- /dev/null +++ b/sunnypilot/system/sensord/sensors/lsm6ds3_gyro.h @@ -0,0 +1,45 @@ +#pragma once + +#include "sunnypilot/system/sensord/sensors/i2c_sensor.h" + +// Address of the chip on the bus +#define LSM6DS3_GYRO_I2C_ADDR 0x6A + +// Registers of the chip +#define LSM6DS3_GYRO_I2C_REG_DRDY_CFG 0x0B +#define LSM6DS3_GYRO_I2C_REG_ID 0x0F +#define LSM6DS3_GYRO_I2C_REG_INT1_CTRL 0x0D +#define LSM6DS3_GYRO_I2C_REG_CTRL2_G 0x11 +#define LSM6DS3_GYRO_I2C_REG_CTRL5_C 0x14 +#define LSM6DS3_GYRO_I2C_REG_STAT_REG 0x1E +#define LSM6DS3_GYRO_I2C_REG_OUTX_L_G 0x22 +#define LSM6DS3_GYRO_POSITIVE_TEST (0b01 << 2) +#define LSM6DS3_GYRO_NEGATIVE_TEST (0b11 << 2) + +// Constants +#define LSM6DS3_GYRO_CHIP_ID 0x69 +#define LSM6DS3TRC_GYRO_CHIP_ID 0x6A +#define LSM6DS3_GYRO_FS_2000dps (0b11 << 2) +#define LSM6DS3_GYRO_ODR_104HZ (0b0100 << 4) +#define LSM6DS3_GYRO_ODR_208HZ (0b0101 << 4) +#define LSM6DS3_GYRO_INT1_DRDY_G 0b10 +#define LSM6DS3_GYRO_DRDY_GDA 0b10 +#define LSM6DS3_GYRO_DRDY_PULSE_MODE (1 << 7) +#define LSM6DS3_GYRO_MIN_ST_LIMIT_mdps 150000.0f +#define LSM6DS3_GYRO_MAX_ST_LIMIT_mdps 700000.0f + + +class LSM6DS3_Gyro : public I2CSensor { + uint8_t get_device_address() {return LSM6DS3_GYRO_I2C_ADDR;} + cereal::SensorEventData::SensorSource source = cereal::SensorEventData::SensorSource::LSM6DS3; + + // self test functions + int self_test(int test_type); + void wait_for_data_ready(); + void read_and_avg_data(float* val_st_off); +public: + LSM6DS3_Gyro(I2CBus *bus, int gpio_nr = 0, bool shared_gpio = false); + int init(); + bool get_event(MessageBuilder &msg, uint64_t ts = 0); + int shutdown(); +}; diff --git a/sunnypilot/system/sensord/sensors/lsm6ds3_temp.cc b/sunnypilot/system/sensord/sensors/lsm6ds3_temp.cc new file mode 100644 index 0000000000..390f192a2d --- /dev/null +++ b/sunnypilot/system/sensord/sensors/lsm6ds3_temp.cc @@ -0,0 +1,37 @@ +#include "sunnypilot/system/sensord/sensors/lsm6ds3_temp.h" + +#include + +#include "common/swaglog.h" +#include "common/timing.h" + +LSM6DS3_Temp::LSM6DS3_Temp(I2CBus *bus) : I2CSensor(bus) {} + +int LSM6DS3_Temp::init() { + int ret = verify_chip_id(LSM6DS3_TEMP_I2C_REG_ID, {LSM6DS3_TEMP_CHIP_ID, LSM6DS3TRC_TEMP_CHIP_ID}); + if (ret == -1) return -1; + + if (ret == LSM6DS3TRC_TEMP_CHIP_ID) { + source = cereal::SensorEventData::SensorSource::LSM6DS3TRC; + } + return 0; +} + +bool LSM6DS3_Temp::get_event(MessageBuilder &msg, uint64_t ts) { + uint64_t start_time = nanos_since_boot(); + uint8_t buffer[2]; + int len = read_register(LSM6DS3_TEMP_I2C_REG_OUT_TEMP_L, buffer, sizeof(buffer)); + assert(len == sizeof(buffer)); + + float scale = (source == cereal::SensorEventData::SensorSource::LSM6DS3TRC) ? 256.0f : 16.0f; + float temp = 25.0f + read_16_bit(buffer[0], buffer[1]) / scale; + + auto event = msg.initEvent().initTemperatureSensor(); + event.setSource(source); + event.setVersion(1); + event.setType(SENSOR_TYPE_AMBIENT_TEMPERATURE); + event.setTimestamp(start_time); + event.setTemperature(temp); + + return true; +} diff --git a/sunnypilot/system/sensord/sensors/lsm6ds3_temp.h b/sunnypilot/system/sensord/sensors/lsm6ds3_temp.h new file mode 100644 index 0000000000..c314d456e8 --- /dev/null +++ b/sunnypilot/system/sensord/sensors/lsm6ds3_temp.h @@ -0,0 +1,26 @@ +#pragma once + +#include "sunnypilot/system/sensord/sensors/i2c_sensor.h" + +// Address of the chip on the bus +#define LSM6DS3_TEMP_I2C_ADDR 0x6A + +// Registers of the chip +#define LSM6DS3_TEMP_I2C_REG_ID 0x0F +#define LSM6DS3_TEMP_I2C_REG_OUT_TEMP_L 0x20 + +// Constants +#define LSM6DS3_TEMP_CHIP_ID 0x69 +#define LSM6DS3TRC_TEMP_CHIP_ID 0x6A + + +class LSM6DS3_Temp : public I2CSensor { + uint8_t get_device_address() {return LSM6DS3_TEMP_I2C_ADDR;} + cereal::SensorEventData::SensorSource source = cereal::SensorEventData::SensorSource::LSM6DS3; + +public: + LSM6DS3_Temp(I2CBus *bus); + int init(); + bool get_event(MessageBuilder &msg, uint64_t ts = 0); + int shutdown() { return 0; } +}; diff --git a/sunnypilot/system/sensord/sensors/mmc5603nj_magn.cc b/sunnypilot/system/sensord/sensors/mmc5603nj_magn.cc new file mode 100644 index 0000000000..12d438ebd1 --- /dev/null +++ b/sunnypilot/system/sensord/sensors/mmc5603nj_magn.cc @@ -0,0 +1,108 @@ +#include "sunnypilot/system/sensord/sensors/mmc5603nj_magn.h" + +#include +#include +#include + +#include "common/swaglog.h" +#include "common/timing.h" +#include "common/util.h" + +MMC5603NJ_Magn::MMC5603NJ_Magn(I2CBus *bus) : I2CSensor(bus) {} + +int MMC5603NJ_Magn::init() { + int ret = verify_chip_id(MMC5603NJ_I2C_REG_ID, {MMC5603NJ_CHIP_ID}); + if (ret == -1) return -1; + + // Set ODR to 0 + ret = set_register(MMC5603NJ_I2C_REG_ODR, 0); + if (ret < 0) { + goto fail; + } + + // Set BW to 0b01 for 1-150 Hz operation + ret = set_register(MMC5603NJ_I2C_REG_INTERNAL_1, 0b01); + if (ret < 0) { + goto fail; + } + +fail: + return ret; +} + +int MMC5603NJ_Magn::shutdown() { + int ret = 0; + + // disable auto reset of measurements + uint8_t value = 0; + ret = read_register(MMC5603NJ_I2C_REG_INTERNAL_0, &value, 1); + if (ret < 0) { + goto fail; + } + + value &= ~(MMC5603NJ_CMM_FREQ_EN | MMC5603NJ_AUTO_SR_EN); + ret = set_register(MMC5603NJ_I2C_REG_INTERNAL_0, value); + if (ret < 0) { + goto fail; + } + + // set ODR to 0 to leave continuous mode + ret = set_register(MMC5603NJ_I2C_REG_ODR, 0); + if (ret < 0) { + goto fail; + } + return ret; + +fail: + LOGE("Could not disable mmc5603nj auto set reset"); + return ret; +} + +void MMC5603NJ_Magn::start_measurement() { + set_register(MMC5603NJ_I2C_REG_INTERNAL_0, 0b01); + util::sleep_for(5); +} + +std::vector MMC5603NJ_Magn::read_measurement() { + int len; + uint8_t buffer[9]; + len = read_register(MMC5603NJ_I2C_REG_XOUT0, buffer, sizeof(buffer)); + assert(len == sizeof(buffer)); + float scale = 1.0 / 16384.0; + float x = (read_20_bit(buffer[6], buffer[1], buffer[0]) * scale) - 32.0; + float y = (read_20_bit(buffer[7], buffer[3], buffer[2]) * scale) - 32.0; + float z = (read_20_bit(buffer[8], buffer[5], buffer[4]) * scale) - 32.0; + std::vector xyz = {x, y, z}; + return xyz; +} + +bool MMC5603NJ_Magn::get_event(MessageBuilder &msg, uint64_t ts) { + uint64_t start_time = nanos_since_boot(); + // SET - RESET cycle + set_register(MMC5603NJ_I2C_REG_INTERNAL_0, MMC5603NJ_SET); + util::sleep_for(5); + MMC5603NJ_Magn::start_measurement(); + std::vector xyz = MMC5603NJ_Magn::read_measurement(); + + set_register(MMC5603NJ_I2C_REG_INTERNAL_0, MMC5603NJ_RESET); + util::sleep_for(5); + MMC5603NJ_Magn::start_measurement(); + std::vector reset_xyz = MMC5603NJ_Magn::read_measurement(); + + auto event = msg.initEvent().initMagnetometer(); + event.setSource(cereal::SensorEventData::SensorSource::MMC5603NJ); + event.setVersion(1); + event.setSensor(SENSOR_MAGNETOMETER_UNCALIBRATED); + event.setType(SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED); + event.setTimestamp(start_time); + + float vals[] = {xyz[0], xyz[1], xyz[2], reset_xyz[0], reset_xyz[1], reset_xyz[2]}; + bool valid = true; + if (std::any_of(std::begin(vals), std::end(vals), [](float val) { return val == -32.0; })) { + valid = false; + } + auto svec = event.initMagneticUncalibrated(); + svec.setV(vals); + svec.setStatus(valid); + return true; +} diff --git a/sunnypilot/system/sensord/sensors/mmc5603nj_magn.h b/sunnypilot/system/sensord/sensors/mmc5603nj_magn.h new file mode 100644 index 0000000000..9311631c06 --- /dev/null +++ b/sunnypilot/system/sensord/sensors/mmc5603nj_magn.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +#include "sunnypilot/system/sensord/sensors/i2c_sensor.h" + +// Address of the chip on the bus +#define MMC5603NJ_I2C_ADDR 0x30 + +// Registers of the chip +#define MMC5603NJ_I2C_REG_XOUT0 0x00 +#define MMC5603NJ_I2C_REG_ODR 0x1A +#define MMC5603NJ_I2C_REG_INTERNAL_0 0x1B +#define MMC5603NJ_I2C_REG_INTERNAL_1 0x1C +#define MMC5603NJ_I2C_REG_INTERNAL_2 0x1D +#define MMC5603NJ_I2C_REG_ID 0x39 + +// Constants +#define MMC5603NJ_CHIP_ID 0x10 +#define MMC5603NJ_CMM_FREQ_EN (1 << 7) +#define MMC5603NJ_AUTO_SR_EN (1 << 5) +#define MMC5603NJ_CMM_EN (1 << 4) +#define MMC5603NJ_EN_PRD_SET (1 << 3) +#define MMC5603NJ_SET (1 << 3) +#define MMC5603NJ_RESET (1 << 4) + +class MMC5603NJ_Magn : public I2CSensor { +private: + uint8_t get_device_address() {return MMC5603NJ_I2C_ADDR;} + void start_measurement(); + std::vector read_measurement(); +public: + MMC5603NJ_Magn(I2CBus *bus); + int init(); + bool get_event(MessageBuilder &msg, uint64_t ts = 0); + int shutdown(); +}; diff --git a/sunnypilot/system/sensord/sensors/sensor.h b/sunnypilot/system/sensord/sensors/sensor.h new file mode 100644 index 0000000000..ccf998d161 --- /dev/null +++ b/sunnypilot/system/sensord/sensors/sensor.h @@ -0,0 +1,24 @@ +#pragma once + +#include "cereal/messaging/messaging.h" + +class Sensor { +public: + int gpio_fd = -1; + bool enabled = false; + uint64_t start_ts = 0; + uint64_t init_delay = 500e6; // default dealy 500ms + + virtual ~Sensor() {} + virtual int init() = 0; + virtual bool get_event(MessageBuilder &msg, uint64_t ts = 0) = 0; + virtual bool has_interrupt_enabled() = 0; + virtual int shutdown() = 0; + + virtual bool is_data_valid(uint64_t current_ts) { + if (start_ts == 0) { + start_ts = current_ts; + } + return (current_ts - start_ts) > init_delay; + } +}; diff --git a/sunnypilot/system/sensord/sensors_qcom2.cc b/sunnypilot/system/sensord/sensors_qcom2.cc new file mode 100644 index 0000000000..f4ecc7fc21 --- /dev/null +++ b/sunnypilot/system/sensord/sensors_qcom2.cc @@ -0,0 +1,179 @@ +#include + +#include +#include +#include +#include +#include +#include + +#include "cereal/services.h" +#include "cereal/messaging/messaging.h" +#include "common/i2c.h" +#include "common/ratekeeper.h" +#include "common/swaglog.h" +#include "common/timing.h" +#include "common/util.h" +#include "sunnypilot/system/sensord/sensors/bmx055_accel.h" +#include "sunnypilot/system/sensord/sensors/bmx055_gyro.h" +#include "sunnypilot/system/sensord/sensors/bmx055_magn.h" +#include "sunnypilot/system/sensord/sensors/bmx055_temp.h" +#include "sunnypilot/system/sensord/sensors/constants.h" +#include "sunnypilot/system/sensord/sensors/lsm6ds3_accel.h" +#include "sunnypilot/system/sensord/sensors/lsm6ds3_gyro.h" +#include "sunnypilot/system/sensord/sensors/lsm6ds3_temp.h" +#include "sunnypilot/system/sensord/sensors/mmc5603nj_magn.h" + +#define I2C_BUS_IMU 1 + +ExitHandler do_exit; + +void interrupt_loop(std::vector> sensors) { + PubMaster pm({"gyroscope", "accelerometer"}); + + int fd = -1; + for (auto &[sensor, msg_name] : sensors) { + if (sensor->has_interrupt_enabled()) { + fd = sensor->gpio_fd; + break; + } + } + + uint64_t offset = nanos_since_epoch() - nanos_since_boot(); + struct pollfd fd_list[1] = {0}; + fd_list[0].fd = fd; + fd_list[0].events = POLLIN | POLLPRI; + + while (!do_exit) { + int err = poll(fd_list, 1, 100); + if (err == -1) { + if (errno == EINTR) { + continue; + } + return; + } else if (err == 0) { + LOGE("poll timed out"); + continue; + } + + if ((fd_list[0].revents & (POLLIN | POLLPRI)) == 0) { + LOGE("no poll events set"); + continue; + } + + // Read all events + struct gpioevent_data evdata[16]; + err = HANDLE_EINTR(read(fd, evdata, sizeof(evdata))); + if (err < 0 || err % sizeof(*evdata) != 0) { + LOGE("error reading event data %d", err); + continue; + } + + uint64_t cur_offset = nanos_since_epoch() - nanos_since_boot(); + uint64_t diff = cur_offset > offset ? cur_offset - offset : offset - cur_offset; + if (diff > 10*1e6) { // 10ms + LOGW("time jumped: %lu %lu", cur_offset, offset); + offset = cur_offset; + + // we don't have a valid timestamp since the + // time jumped, so throw out this measurement. + continue; + } + + int num_events = err / sizeof(*evdata); + uint64_t ts = evdata[num_events - 1].timestamp - cur_offset; + + for (auto &[sensor, msg_name] : sensors) { + if (!sensor->has_interrupt_enabled()) { + continue; + } + + MessageBuilder msg; + if (!sensor->get_event(msg, ts)) { + continue; + } + + if (!sensor->is_data_valid(ts)) { + continue; + } + + pm.send(msg_name.c_str(), msg); + } + } +} + +void polling_loop(Sensor *sensor, std::string msg_name) { + PubMaster pm({msg_name.c_str()}); + RateKeeper rk(msg_name, services.at(msg_name).frequency); + while (!do_exit) { + MessageBuilder msg; + if (sensor->get_event(msg) && sensor->is_data_valid(nanos_since_boot())) { + pm.send(msg_name.c_str(), msg); + } + rk.keepTime(); + } +} + +int sensor_loop(I2CBus *i2c_bus_imu) { + // Sensor init + std::vector> sensors_init = { + {new BMX055_Accel(i2c_bus_imu), "accelerometer2"}, + {new BMX055_Gyro(i2c_bus_imu), "gyroscope2"}, + {new BMX055_Magn(i2c_bus_imu), "magnetometer"}, + {new BMX055_Temp(i2c_bus_imu), "temperatureSensor2"}, + + {new LSM6DS3_Accel(i2c_bus_imu, GPIO_LSM_INT), "accelerometer"}, + {new LSM6DS3_Gyro(i2c_bus_imu, GPIO_LSM_INT, true), "gyroscope"}, + {new LSM6DS3_Temp(i2c_bus_imu), "temperatureSensor"}, + + {new MMC5603NJ_Magn(i2c_bus_imu), "magnetometer"}, + }; + + // Initialize sensors + std::vector threads; + for (auto &[sensor, msg_name] : sensors_init) { + int err = sensor->init(); + if (err < 0) { + continue; + } + + if (!sensor->has_interrupt_enabled()) { + threads.emplace_back(polling_loop, sensor, msg_name); + } + } + + // increase interrupt quality by pinning interrupt and process to core 1 + setpriority(PRIO_PROCESS, 0, -18); + util::set_core_affinity({1}); + + // TODO: get the IRQ number from gpiochip + std::string irq_path = "/proc/irq/336/smp_affinity_list"; + if (!util::file_exists(irq_path)) { + irq_path = "/proc/irq/335/smp_affinity_list"; + } + std::system(util::string_format("sudo su -c 'echo 1 > %s'", irq_path.c_str()).c_str()); + + // thread for reading events via interrupts + threads.emplace_back(&interrupt_loop, std::ref(sensors_init)); + + // wait for all threads to finish + for (auto &t : threads) { + t.join(); + } + + for (auto &[sensor, msg_name] : sensors_init) { + sensor->shutdown(); + delete sensor; + } + return 0; +} + +int main(int argc, char *argv[]) { + try { + auto i2c_bus_imu = std::make_unique(I2C_BUS_IMU); + return sensor_loop(i2c_bus_imu.get()); + } catch (std::exception &e) { + LOGE("I2CBus init failed"); + return -1; + } +} diff --git a/sunnypilot/system/sensord/tests/test_sensord.py b/sunnypilot/system/sensord/tests/test_sensord.py new file mode 100644 index 0000000000..dc5f93d97b --- /dev/null +++ b/sunnypilot/system/sensord/tests/test_sensord.py @@ -0,0 +1,251 @@ +import os +import pytest +import time +import numpy as np +from collections import namedtuple, defaultdict + +import cereal.messaging as messaging +from cereal import log +from cereal.services import SERVICE_LIST +from openpilot.common.gpio import get_irqs_for_action +from openpilot.common.timeout import Timeout +from openpilot.system.hardware import HARDWARE +from openpilot.system.manager.process_config import managed_processes + +BMX = { + ('bmx055', 'acceleration'), + ('bmx055', 'gyroUncalibrated'), + ('bmx055', 'magneticUncalibrated'), + ('bmx055', 'temperature'), +} + +LSM = { + ('lsm6ds3', 'acceleration'), + ('lsm6ds3', 'gyroUncalibrated'), + ('lsm6ds3', 'temperature'), +} +LSM_C = {(x[0]+'trc', x[1]) for x in LSM} + +MMC = { + ('mmc5603nj', 'magneticUncalibrated'), +} + +SENSOR_CONFIGURATIONS: list[set] = [ + BMX | LSM, + MMC | LSM, + BMX | LSM_C, + MMC| LSM_C, +] +if HARDWARE.get_device_type() == "mici": + SENSOR_CONFIGURATIONS = [ + LSM, + LSM_C, + ] + +Sensor = log.SensorEventData.SensorSource +SensorConfig = namedtuple('SensorConfig', ['type', 'sanity_min', 'sanity_max']) +ALL_SENSORS = { + Sensor.lsm6ds3: { + SensorConfig("acceleration", 5, 15), + SensorConfig("gyroUncalibrated", 0, .2), + SensorConfig("temperature", 0, 60), + }, + + Sensor.lsm6ds3trc: { + SensorConfig("acceleration", 5, 15), + SensorConfig("gyroUncalibrated", 0, .2), + SensorConfig("temperature", 0, 60), + }, + + Sensor.bmx055: { + SensorConfig("acceleration", 5, 15), + SensorConfig("gyroUncalibrated", 0, .2), + SensorConfig("magneticUncalibrated", 0, 300), + SensorConfig("temperature", 0, 60), + }, + + Sensor.mmc5603nj: { + SensorConfig("magneticUncalibrated", 0, 300), + } +} + + +def get_irq_count(irq: int): + with open(f"/sys/kernel/irq/{irq}/per_cpu_count") as f: + per_cpu = map(int, f.read().split(",")) + return sum(per_cpu) + +def read_sensor_events(duration_sec): + sensor_types = ['accelerometer', 'gyroscope', 'magnetometer', 'accelerometer2', + 'gyroscope2', 'temperatureSensor', 'temperatureSensor2'] + socks = {} + poller = messaging.Poller() + events = defaultdict(list) + for stype in sensor_types: + socks[stype] = messaging.sub_sock(stype, poller=poller, timeout=100) + + # wait for sensors to come up + with Timeout(int(os.environ.get("SENSOR_WAIT", "5")), "sensors didn't come up"): + while len(poller.poll(250)) == 0: + pass + time.sleep(1) + for s in socks.values(): + messaging.drain_sock_raw(s) + + st = time.monotonic() + while time.monotonic() - st < duration_sec: + for s in socks: + events[s] += messaging.drain_sock(socks[s]) + time.sleep(0.1) + + assert sum(map(len, events.values())) != 0, "No sensor events collected!" + + return {k: v for k, v in events.items() if len(v) > 0} + +@pytest.mark.tici +class TestSensord: + @classmethod + def setup_class(cls): + # enable LSM self test + os.environ["LSM_SELF_TEST"] = "1" + + # read initial sensor values every test case can use + os.system("pkill -f \\\\./sensord") + try: + managed_processes["sensord"].start() + cls.sample_secs = int(os.getenv("SAMPLE_SECS", "10")) + cls.events = read_sensor_events(cls.sample_secs) + + # determine sensord's irq + cls.sensord_irq = get_irqs_for_action("sensord")[0] + finally: + # teardown won't run if this doesn't succeed + managed_processes["sensord"].stop() + + @classmethod + def teardown_class(cls): + managed_processes["sensord"].stop() + + def teardown_method(self): + managed_processes["sensord"].stop() + + def test_sensors_present(self): + # verify correct sensors configuration + seen = set() + for etype in self.events: + for measurement in self.events[etype]: + m = getattr(measurement, measurement.which()) + seen.add((str(m.source), m.which())) + + assert seen in SENSOR_CONFIGURATIONS + + def test_lsm6ds3_timing(self, subtests): + # verify measurements are sampled and published at 104Hz + + sensor_t = { + 1: [], # accel + 5: [], # gyro + } + + for measurement in self.events['accelerometer']: + m = getattr(measurement, measurement.which()) + sensor_t[m.sensor].append(m.timestamp) + + for measurement in self.events['gyroscope']: + m = getattr(measurement, measurement.which()) + sensor_t[m.sensor].append(m.timestamp) + + for s, vals in sensor_t.items(): + with subtests.test(sensor=s): + assert len(vals) > 0 + tdiffs = np.diff(vals) / 1e6 # millis + + high_delay_diffs = list(filter(lambda d: d >= 20., tdiffs)) + assert len(high_delay_diffs) < 15, f"Too many large diffs: {high_delay_diffs}" + + avg_diff = sum(tdiffs)/len(tdiffs) + avg_freq = 1. / (avg_diff * 1e-3) + assert 92. < avg_freq < 114., f"avg freq {avg_freq}Hz wrong, expected 104Hz" + + stddev = np.std(tdiffs) + assert stddev < 2.0, f"Standard-dev to big {stddev}" + + def test_sensor_frequency(self, subtests): + for s, msgs in self.events.items(): + with subtests.test(sensor=s): + freq = len(msgs) / self.sample_secs + ef = SERVICE_LIST[s].frequency + assert ef*0.85 <= freq <= ef*1.15 + + def test_logmonottime_timestamp_diff(self): + # ensure diff between the message logMonotime and sample timestamp is small + + tdiffs = list() + for etype in self.events: + for measurement in self.events[etype]: + m = getattr(measurement, measurement.which()) + + # check if gyro and accel timestamps are before logMonoTime + if str(m.source).startswith("lsm6ds3") and m.which() != 'temperature': + err_msg = f"Timestamp after logMonoTime: {m.timestamp} > {measurement.logMonoTime}" + assert m.timestamp < measurement.logMonoTime, err_msg + + # negative values might occur, as non interrupt packages created + # before the sensor is read + tdiffs.append(abs(measurement.logMonoTime - m.timestamp) / 1e6) + + # some sensors have a read procedure that will introduce an expected diff on the order of 20ms + high_delay_diffs = set(filter(lambda d: d >= 25., tdiffs)) + assert len(high_delay_diffs) < 20, f"Too many measurements published: {high_delay_diffs}" + + avg_diff = round(sum(tdiffs)/len(tdiffs), 4) + assert avg_diff < 4, f"Avg packet diff: {avg_diff:.1f}ms" + + def test_sensor_values(self): + sensor_values = dict() + for etype in self.events: + for measurement in self.events[etype]: + m = getattr(measurement, measurement.which()) + key = (m.source.raw, m.which()) + values = getattr(m, m.which()) + + if hasattr(values, 'v'): + values = values.v + values = np.atleast_1d(values) + + if key in sensor_values: + sensor_values[key].append(values) + else: + sensor_values[key] = [values] + + # Sanity check sensor values + for sensor, stype in sensor_values: + for s in ALL_SENSORS[sensor]: + if s.type != stype: + continue + + key = (sensor, s.type) + mean_norm = np.mean(np.linalg.norm(sensor_values[key], axis=1)) + err_msg = f"Sensor '{sensor} {s.type}' failed sanity checks {mean_norm} is not between {s.sanity_min} and {s.sanity_max}" + assert s.sanity_min <= mean_norm <= s.sanity_max, err_msg + + def test_sensor_verify_no_interrupts_after_stop(self): + managed_processes["sensord"].start() + time.sleep(3) + + # read /proc/interrupts to verify interrupts are received + state_one = get_irq_count(self.sensord_irq) + time.sleep(1) + state_two = get_irq_count(self.sensord_irq) + + error_msg = f"no interrupts received after sensord start!\n{state_one} {state_two}" + assert state_one != state_two, error_msg + + managed_processes["sensord"].stop() + time.sleep(1) + + # read /proc/interrupts to verify no more interrupts are received + state_one = get_irq_count(self.sensord_irq) + time.sleep(1) + state_two = get_irq_count(self.sensord_irq) + assert state_one == state_two, "Interrupts received after sensord stop!" diff --git a/sunnypilot/system/sensord/tests/ttff_test.py b/sunnypilot/system/sensord/tests/ttff_test.py new file mode 100755 index 0000000000..a9cc16d707 --- /dev/null +++ b/sunnypilot/system/sensord/tests/ttff_test.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 + +import time +import atexit + +from cereal import messaging +from openpilot.system.manager.process_config import managed_processes + +TIMEOUT = 10*60 + +def kill(): + for proc in ['ubloxd', 'pigeond']: + managed_processes[proc].stop(retry=True, block=True) + +if __name__ == "__main__": + # start ubloxd + managed_processes['ubloxd'].start() + atexit.register(kill) + + sm = messaging.SubMaster(['ubloxGnss']) + + times = [] + for i in range(20): + # start pigeond + st = time.monotonic() + managed_processes['pigeond'].start() + + # wait for a >4 satellite fix + while True: + sm.update(0) + msg = sm['ubloxGnss'] + if msg.which() == 'measurementReport' and sm.updated["ubloxGnss"]: + report = msg.measurementReport + if report.numMeas > 4: + times.append(time.monotonic() - st) + print(f"\033[94m{i}: Got a fix in {round(times[-1], 2)} seconds\033[0m") + break + + if time.monotonic() - st > TIMEOUT: + raise TimeoutError("\033[91mFailed to get a fix in {TIMEOUT} seconds!\033[0m") + + time.sleep(0.1) + + # stop pigeond + managed_processes['pigeond'].stop(retry=True, block=True) + time.sleep(20) + + print(f"\033[92mAverage TTFF: {round(sum(times) / len(times), 2)}s\033[0m") diff --git a/system/manager/process_config.py b/system/manager/process_config.py index 92d5a4ef8c..b1a2fa6e13 100644 --- a/system/manager/process_config.py +++ b/system/manager/process_config.py @@ -173,6 +173,9 @@ procs += [ # mapd NativeProcess("mapd", Paths.mapd_root(), ["bash", "-c", f"{MAPD_PATH} > /dev/null 2>&1"], mapd_ready), PythonProcess("mapd_manager", "sunnypilot.mapd.mapd_manager", always_run), + + # locationd + NativeProcess("locationd_llk", "sunnypilot/selfdrive/locationd", ["./locationd"], only_onroad), ] if os.path.exists("./github_runner.sh"): From 1465e38c7bdd361895499b4d3be542a16ee19126 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Tue, 23 Sep 2025 10:11:52 -0400 Subject: [PATCH 108/159] SCC-M: overriding is an enabled state (#1281) --- .../controls/lib/smart_cruise_control/map_controller.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/map_controller.py b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/map_controller.py index cd45870ef6..c7f11a1bb2 100644 --- a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/map_controller.py +++ b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/map_controller.py @@ -12,8 +12,8 @@ from openpilot.sunnypilot.selfdrive.controls.lib.smart_cruise_control import MIN MapState = VisionState = custom.LongitudinalPlanSP.SmartCruiseControl.MapState -ACTIVE_STATES = (MapState.turning, MapState.overriding) -ENABLED_STATES = (MapState.enabled, *ACTIVE_STATES) +ACTIVE_STATES = (MapState.turning, ) +ENABLED_STATES = (MapState.enabled, MapState.overriding, *ACTIVE_STATES) R = 6373000.0 # approximate radius of earth in meters TO_RADIANS = math.pi / 180 From 082ea8119b39398bf6cc4ce309d9d785bcb8975b Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Wed, 24 Sep 2025 22:17:03 -0400 Subject: [PATCH 109/159] Speed Limit Resolver: abstract more speed limit attributes (#1284) * Speed Limit Resolver: abstract more speed limit attributes * update ui * lint --- cereal/custom.capnp | 5 +++++ selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 18 +++++++---------- selfdrive/ui/sunnypilot/qt/onroad/hud.h | 1 + .../controls/lib/longitudinal_planner.py | 5 +++++ .../lib/speed_limit/speed_limit_resolver.py | 20 +++++++++++++++++++ 5 files changed, 38 insertions(+), 11 deletions(-) diff --git a/cereal/custom.capnp b/cereal/custom.capnp index 854988decf..58628a193b 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -207,6 +207,11 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { distToSpeedLimit @1 :Float32; source @2 :Source; speedLimitOffset @3 :Float32; + speedLimitLast @4 :Float32; + speedLimitFinal @5 :Float32; + speedLimitFinalLast @6 :Float32; + speedLimitValid @7 :Bool; + speedLimitLastValid @8 :Bool; } enum Source { diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index 6da6baef3d..a3e31455a5 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -30,9 +30,11 @@ void HudRendererSP::updateState(const UIState &s) { float speedConv = is_metric ? MS_TO_KPH : MS_TO_MPH; speedLimit = lp_sp.getSpeedLimit().getResolver().getSpeedLimit() * speedConv; + speedLimitLast = lp_sp.getSpeedLimit().getResolver().getSpeedLimitLast() * speedConv; speedLimitOffset = lp_sp.getSpeedLimit().getResolver().getSpeedLimitOffset() * speedConv; - speedLimitValid = speedLimit > 0; - speedLimitLastValid = speedLimitLast > 0; + speedLimitValid = lp_sp.getSpeedLimit().getResolver().getSpeedLimitValid(); + speedLimitLastValid = lp_sp.getSpeedLimit().getResolver().getSpeedLimitLastValid(); + speedLimitFinalLast = lp_sp.getSpeedLimit().getResolver().getSpeedLimitFinalLast(); speedLimitMode = static_cast(s.scene.speed_limit_mode); roadName = s.scene.road_name; if (sm.updated("liveMapDataSP")) { @@ -48,10 +50,6 @@ void HudRendererSP::updateState(const UIState &s) { } speedLimitAheadDistancePrev = speedLimitAheadDistance; - if (speedLimitValid) { - speedLimitLast = speedLimit; - } - static int reverse_delay = 0; bool reverse_allowed = false; if (int(car_state.getGearShifter()) != 4) { @@ -351,12 +349,10 @@ void HudRendererSP::drawStandstillTimer(QPainter &p, int x, int y) { } void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { - bool hasSpeedLimit = speedLimitValid || speedLimitLastValid; - int speedLimitFinal = std::nearbyint(speedLimitValid ? speedLimit : speedLimitLast); - int speedLimitOffsetFinal = speedLimitFinal + std::nearbyint(speedLimitOffset); - bool overspeed = hasSpeedLimit && speedLimitOffsetFinal < std::nearbyint(speed); bool speedLimitWarningEnabled = speedLimitMode == SpeedLimitMode::WARNING; // TODO-SP: update to include SpeedLimitMode::ASSIST - QString speedLimitStr = hasSpeedLimit ? QString::number(speedLimitFinal) : "---"; + bool hasSpeedLimit = speedLimitValid || speedLimitLastValid; + bool overspeed = hasSpeedLimit && speedLimitFinalLast < std::nearbyint(speed); + QString speedLimitStr = hasSpeedLimit ? QString::number(std::nearbyint(speedLimitLast)) : "---"; // Offset display text QString speedLimitSubText = ""; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.h b/selfdrive/ui/sunnypilot/qt/onroad/hud.h index 1e153f1548..d77892fa2d 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.h +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.h @@ -77,6 +77,7 @@ private: float speedLimitOffset; bool speedLimitValid; bool speedLimitLastValid; + float speedLimitFinalLast; bool speedLimitAheadValid; float speedLimitAhead; float speedLimitAheadDistance; diff --git a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py index af5f5dbd7d..40d30100c5 100644 --- a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py +++ b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py @@ -96,6 +96,11 @@ class LongitudinalPlannerSP: speedLimit = longitudinalPlanSP.speedLimit resolver = speedLimit.resolver resolver.speedLimit = float(self.resolver.speed_limit) + resolver.speedLimitLast = float(self.resolver.speed_limit_last) + resolver.speedLimitFinal = float(self.resolver.speed_limit_final) + resolver.speedLimitFinalLast = float(self.resolver.speed_limit_final_last) + resolver.speedLimitValid = self.resolver.speed_limit_valid + resolver.speedLimitLastValid = self.resolver.speed_limit_last_valid resolver.speedLimitOffset = float(self.resolver.speed_limit_offset) resolver.distToSpeedLimit = float(self.resolver.distance) resolver.source = self.resolver.source diff --git a/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_resolver.py b/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_resolver.py index 2a74a01d13..f145b16c10 100644 --- a/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_resolver.py +++ b/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_resolver.py @@ -26,6 +26,9 @@ class SpeedLimitResolver: distance_solutions: dict[custom.LongitudinalPlanSP.SpeedLimit.Source, float] v_ego: float speed_limit: float + speed_limit_last: float + speed_limit_final: float + speed_limit_final_last: float distance: float source: custom.LongitudinalPlanSP.SpeedLimit.Source speed_limit_offset: float @@ -54,6 +57,21 @@ class SpeedLimitResolver: self.offset_type = self.params.get("SpeedLimitOffsetType", return_default=True) self.offset_value = self.params.get("SpeedLimitValueOffset", return_default=True) + def update_speed_limit_states(self) -> None: + self.speed_limit_final = self.speed_limit + self.speed_limit_offset + + if self.speed_limit > 0.: + self.speed_limit_last = self.speed_limit + self.speed_limit_final_last = self.speed_limit_final + + @property + def speed_limit_valid(self) -> bool: + return self.speed_limit > 0. + + @property + def speed_limit_last_valid(self) -> bool: + return self.speed_limit_last > 0. + def update_params(self): if self.frame % int(PARAMS_UPDATE_PERIOD / DT_MDL) == 0: self.policy = self.params.get("SpeedLimitPolicy", return_default=True) @@ -149,4 +167,6 @@ class SpeedLimitResolver: self.speed_limit, self.distance, self.source = self._resolve_limit_sources(sm) self.speed_limit_offset = self._get_speed_limit_offset() + self.update_speed_limit_states() + self.frame += 1 From 4c40be8b1f2a17d3fefdf3140573ca40ec1e1a92 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Thu, 25 Sep 2025 07:01:32 -0400 Subject: [PATCH 110/159] ui: always convert speedLimitFinalLast --- selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index a3e31455a5..c07825c97c 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -34,7 +34,7 @@ void HudRendererSP::updateState(const UIState &s) { speedLimitOffset = lp_sp.getSpeedLimit().getResolver().getSpeedLimitOffset() * speedConv; speedLimitValid = lp_sp.getSpeedLimit().getResolver().getSpeedLimitValid(); speedLimitLastValid = lp_sp.getSpeedLimit().getResolver().getSpeedLimitLastValid(); - speedLimitFinalLast = lp_sp.getSpeedLimit().getResolver().getSpeedLimitFinalLast(); + speedLimitFinalLast = lp_sp.getSpeedLimit().getResolver().getSpeedLimitFinalLast() * speedConv; speedLimitMode = static_cast(s.scene.speed_limit_mode); roadName = s.scene.road_name; if (sm.updated("liveMapDataSP")) { From 8ebe9b69afb24cd7d88a9459d5110b072c138ee4 Mon Sep 17 00:00:00 2001 From: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Date: Thu, 25 Sep 2025 07:11:51 -0700 Subject: [PATCH 111/159] bug: fix Speed Limit Resolver initialization (#1285) bug: fix speedlimitresolver init --- .../controls/lib/speed_limit/speed_limit_resolver.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_resolver.py b/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_resolver.py index f145b16c10..51fb8f6d64 100644 --- a/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_resolver.py +++ b/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_resolver.py @@ -57,6 +57,12 @@ class SpeedLimitResolver: self.offset_type = self.params.get("SpeedLimitOffsetType", return_default=True) self.offset_value = self.params.get("SpeedLimitValueOffset", return_default=True) + self.speed_limit = 0. + self.speed_limit_last = 0. + self.speed_limit_final = 0. + self.speed_limit_final_last = 0. + self.speed_limit_offset = 0. + def update_speed_limit_states(self) -> None: self.speed_limit_final = self.speed_limit + self.speed_limit_offset From db65937fc72644daf1485f3b11d82bccf5cac3dd Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Thu, 25 Sep 2025 19:15:36 -0400 Subject: [PATCH 112/159] Revert "ui: generic check with ICBM param" (#1286) Revert "ui: generic check with ICBM param (#1274)" This reverts commit d5a873ed8617cefd691509c9cc5dc4ec7ea42ff4. --- .../qt/offroad/settings/longitudinal_panel.cc | 10 ++++------ .../qt/offroad/settings/longitudinal_panel.h | 3 +-- selfdrive/ui/sunnypilot/qt/util.cc | 4 ---- selfdrive/ui/sunnypilot/qt/util.h | 1 - 4 files changed, 5 insertions(+), 13 deletions(-) diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc index 8987f38514..3e3977ff64 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.cc @@ -87,7 +87,6 @@ void LongitudinalPanel::showEvent(QShowEvent *event) { } void LongitudinalPanel::refresh(bool _offroad) { - auto icbm_available = false; auto cp_bytes = params.get("CarParamsPersistent"); auto cp_sp_bytes = params.get("CarParamsSPPersistent"); if (!cp_bytes.empty() && !cp_sp_bytes.empty()) { @@ -100,12 +99,11 @@ void LongitudinalPanel::refresh(bool _offroad) { has_longitudinal_control = hasLongitudinalControl(CP); is_pcm_cruise = CP.getPcmCruise(); - icbm_available = CP_SP.getIntelligentCruiseButtonManagementAvailable(); - has_intelligent_cruise_button_management = hasIntelligentCruiseButtonManagement(CP_SP); + intelligent_cruise_button_management_available = CP_SP.getIntelligentCruiseButtonManagementAvailable(); } else { has_longitudinal_control = false; is_pcm_cruise = false; - has_intelligent_cruise_button_management = false; + intelligent_cruise_button_management_available = false; } QString accEnabledDescription = tr("Enable custom Short & Long press increments for cruise speed increase/decrease."); @@ -117,7 +115,7 @@ void LongitudinalPanel::refresh(bool _offroad) { customAccIncrement->setDescription(onroadOnlyDescription); customAccIncrement->showDescription(); } else { - if (has_longitudinal_control || icbm_available) { + if (has_longitudinal_control || intelligent_cruise_button_management_available) { if (is_pcm_cruise) { customAccIncrement->setDescription(accPcmCruiseDisabledDescription); customAccIncrement->showDescription(); @@ -134,7 +132,7 @@ void LongitudinalPanel::refresh(bool _offroad) { } } - bool icbm_allowed = has_intelligent_cruise_button_management && !has_longitudinal_control; + bool icbm_allowed = intelligent_cruise_button_management_available && !has_longitudinal_control; intelligentCruiseButtonManagement->setEnabled(icbm_allowed && offroad); // enable toggle when long is available and is not PCM cruise diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h index 2fd15e955c..0b7f39c645 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal_panel.h @@ -7,7 +7,6 @@ #pragma once -#include "selfdrive/ui/sunnypilot/qt/util.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/custom_acc_increment.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" @@ -25,7 +24,7 @@ private: Params params; bool has_longitudinal_control = false; bool is_pcm_cruise = false; - bool has_intelligent_cruise_button_management = false;; + bool intelligent_cruise_button_management_available = false;; bool offroad = false; QStackedLayout *main_layout = nullptr; diff --git a/selfdrive/ui/sunnypilot/qt/util.cc b/selfdrive/ui/sunnypilot/qt/util.cc index eaf05942a9..2e066e88b5 100644 --- a/selfdrive/ui/sunnypilot/qt/util.cc +++ b/selfdrive/ui/sunnypilot/qt/util.cc @@ -123,7 +123,3 @@ std::optional loadCerealEvent(Params& params, const std:: return std::nullopt; } } - -bool hasIntelligentCruiseButtonManagement(const cereal::CarParamsSP::Reader &car_params_sp) { - return car_params_sp.getIntelligentCruiseButtonManagementAvailable() && Params().getBool("IntelligentCruiseButtonManagement"); -} diff --git a/selfdrive/ui/sunnypilot/qt/util.h b/selfdrive/ui/sunnypilot/qt/util.h index 60a73615ba..4b9d615ce5 100644 --- a/selfdrive/ui/sunnypilot/qt/util.h +++ b/selfdrive/ui/sunnypilot/qt/util.h @@ -23,4 +23,3 @@ std::optional getParamIgnoringDefault(const std::string ¶m_name, co QMap loadPlatformList(); QStringList searchFromList(const QString &query, const QStringList &list); std::optional loadCerealEvent(Params& params, const std::string& _param); -bool hasIntelligentCruiseButtonManagement(const cereal::CarParamsSP::Reader &car_params_sp); From 90adc18032732bc92320402ddf884730678e14ea Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Mon, 29 Sep 2025 19:18:52 -0400 Subject: [PATCH 113/159] MADS: enforce certain soft disable events by user when in motion (#1298) * MADS: enforce soft disable events by user when the vehicle is in motion * flipped --- sunnypilot/mads/mads.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sunnypilot/mads/mads.py b/sunnypilot/mads/mads.py index f16b688358..b75bd8ccda 100644 --- a/sunnypilot/mads/mads.py +++ b/sunnypilot/mads/mads.py @@ -102,12 +102,13 @@ class ModularAssistiveDrivingSystem: def update_events(self, CS: structs.CarState): if not self.selfdrive.enabled and self.enabled: - if self.events.has(EventName.doorOpen): - self.replace_event(EventName.doorOpen, EventNameSP.silentDoorOpen) - self.transition_paused_state() - if self.events.has(EventName.seatbeltNotLatched): - self.replace_event(EventName.seatbeltNotLatched, EventNameSP.silentSeatbeltNotLatched) - self.transition_paused_state() + if CS.standstill: + if self.events.has(EventName.doorOpen): + self.replace_event(EventName.doorOpen, EventNameSP.silentDoorOpen) + self.transition_paused_state() + if self.events.has(EventName.seatbeltNotLatched): + self.replace_event(EventName.seatbeltNotLatched, EventNameSP.silentSeatbeltNotLatched) + self.transition_paused_state() if self.events.has(EventName.wrongGear) and (CS.vEgo < 2.5 or CS.gearShifter == GearShifter.reverse): self.replace_event(EventName.wrongGear, EventNameSP.silentWrongGear) self.transition_paused_state() From dc0fd4ca96c239592ba68c6f4992a91fa3f9eee3 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Tue, 30 Sep 2025 13:13:45 -0400 Subject: [PATCH 114/159] Longitudinal: Speed Limit Assist (SLA) (#833) * formatting * more * create directory if does not exist * mypy my bt * policy param catch exceptions * handle all params with exceptions * more * single method * define types in init * rename * simpler op enabled check * more mypy stuff * rename * no need for brake pressed * don't reset if gas pressed * type hint all * type hint all * back to upstream * in another pr * no longer need data type * qlog * slc in another pr * use horizontal accuracy * use horizontal accuracy * set core affinity for all realtime processes * unused * sort * unused * type hint and slight cleanup * from old implementation * use directly * combine pm * slight more cleanup * type hints * even more type hint * Revert "slc in another pr" This reverts commit 3a6987e6 * Revert "in another pr" This reverts commit a29bccff12b9ed9d64efe7a5722bf614214002c4. * rebump * no need to check alive * use it directly * fix test * refactor * use gps data directly * quote...? * lint * fix tests * use CC.longActive * user confirm in another PR * rename * fix import * params fix * no more * fix * drop new state machine for now * more fixes * internalize output * unused * rearrange * auto draft * rename * this * no * no need * use existing * wrong cruise speed * fix * not used for now * Revert "not used for now" This reverts commit f0083d6241380e84ed259c402941fa2c78e03fdf. * some * use frames instead * split speed limit resolver out of slc * no need to pass sm * fix params * test init * use frame instead of time * track session * some tests * too limiting * bump * always reset state * end session if long_active but slc inactive at any given time * off * no warning in this PR * no speed factor engage type yet * wide open * no * introduce disabled, no longer transitions at inactive * fix tests * no more tempinactive * clean * rename * offset default > off * new tests, fixes controller * more tests * not really needed yet * lint * fix * some more tests * wrap * more * more * use vCruiseCluster for set speed * init better * finish it up * no * typo * one method state machine * refactor preactive timeout check * refactor new session check * directly return statuses * comments * v_target * refactor speed limit resolver * turn off debug * more resolver refactor * no longer needed * lint * more lint * fix * move around * fix events * update event * already happens while in enabled * add carstateSP * less * Speed Limit Control -> Speed Limit Assist * in another PR * more rename * overriding state * fix * make sure to return the correct type * sync with latest * housekeeping * use v cruise cluster instead * fix var * show it in UI! * actually show it * update event texts * todo * no override for now * wrong timer! * add vtarget and atarget * fix * handle no speed limit events * fix size * unused * skip preActive if init max speed was already reached * display last known speed limit and its state with SLA * pending event * much shorter disable guard * update events * convert max init for metric * fix even if unused atm * just use it * red for all * not disabled * rename * 10s pre active * kumar wants it higher, blame him * fix * pcm long only * some fixes * rename * use consolidate method to evaluate set speed status * init non pcm cruise * tests * disable non pcm long state machine for now * lint * lint * let the non PCM party begins * fix event * update event * use speed limit final last * only do direction checks if preActive * use resolver * use it directly * no longer applies * do it globally * non pcm long: adapting or pending unused * use button events instead of raw vals * need to initialize * move * what? * what #2??? * cst! * circular * slight fixes for tests * change up checks for user confirm * get buttonEvents at 100 hz and process for 20 hz consumption * get v cruise cluster from outer loop * Revert "get v cruise cluster from outer loop" This reverts commit be8068e8ab9b52c7e8e1b3f29e89f994b3e911df. * Revert "get buttonEvents at 100 hz and process for 20 hz consumption" This reverts commit a739d4d4379080fceffda8d7d080c0260519f144. * don't need * do not allow target speed confirm if inactive * do not allow preActive if no valid speed limit * gimme them arrow pls * less * descriptive direction * fix event * update cs in 100 hz * Revert "don't need" This reverts commit 1eec763be795e1269f2046f8fe65781b3abedd0a. * missed * wrong * stop * throw them to helpers class * property * hold speed behavior changes * abstract it * use converted to check last set speed change * Revert "do not allow target speed confirm if inactive" This reverts commit 9840e74e * pre active too short * slight fixes * fix tests * linty lint * speed limit changed hold timer for non pcm long * should be 0 * less loopy * some gates * special sauce for sla --------- Co-authored-by: nayan Co-authored-by: DevTekVE --- cereal/custom.capnp | 24 ++ selfdrive/car/card.py | 3 +- selfdrive/car/cruise.py | 7 + .../controls/lib/longitudinal_planner.py | 2 +- selfdrive/controls/plannerd.py | 3 +- selfdrive/selfdrived/selfdrived.py | 1 + selfdrive/ui/qt/onroad/hud.cc | 3 +- .../longitudinal/speed_limit/helpers.h | 2 + .../speed_limit/speed_limit_settings.cc | 3 +- .../speed_limit/speed_limit_settings.h | 10 +- selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 121 +++++- selfdrive/ui/sunnypilot/qt/onroad/hud.h | 9 +- .../selfdrive/assets/img_minus_arrow_down.png | 3 + .../selfdrive/assets/img_plus_arrow_up.png | 3 + sunnypilot/selfdrive/car/cruise_ext.py | 51 ++- .../controls/lib/longitudinal_planner.py | 42 +- .../smart_cruise_control.py | 5 +- .../controls/lib/speed_limit/__init__.py | 11 + .../controls/lib/speed_limit/common.py | 7 + .../controls/lib/speed_limit/helpers.py | 19 + .../lib/speed_limit/speed_limit_assist.py | 401 ++++++++++++++++++ .../tests/test_speed_limit_assist.py | 227 ++++++++++ sunnypilot/selfdrive/selfdrived/events.py | 77 +++- 23 files changed, 998 insertions(+), 36 deletions(-) create mode 100644 sunnypilot/selfdrive/assets/img_minus_arrow_down.png create mode 100644 sunnypilot/selfdrive/assets/img_plus_arrow_up.png create mode 100644 sunnypilot/selfdrive/controls/lib/speed_limit/helpers.py create mode 100644 sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_assist.py create mode 100644 sunnypilot/selfdrive/controls/lib/speed_limit/tests/test_speed_limit_assist.py diff --git a/cereal/custom.capnp b/cereal/custom.capnp index 58628a193b..c87ac0d2e0 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -148,6 +148,7 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { speedLimit @3 :SpeedLimit; vTarget @4 :Float32; aTarget @5 :Float32; + events @6 :List(OnroadEventSP.Event); struct DynamicExperimentalControl { state @0 :DynamicExperimentalControlState; @@ -201,6 +202,7 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { struct SpeedLimit { resolver @0 :Resolver; + assist @1 :Assist; struct Resolver { speedLimit @0 :Float32; @@ -214,17 +216,35 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { speedLimitLastValid @8 :Bool; } + struct Assist { + state @0 :AssistState; + enabled @1 :Bool; + active @2 :Bool; + vTarget @3 :Float32; + aTarget @4 :Float32; + } + enum Source { none @0; car @1; map @2; } + + enum AssistState { + disabled @0; + inactive @1; # No speed limit set or not enabled by parameter. + preActive @2; + pending @3; # Awaiting new speed limit. + adapting @4; # Reducing speed to match new speed limit. + active @5; # Cruising at speed limit. + } } enum LongitudinalPlanSource { cruise @0; sccVision @1; sccMap @2; + speedLimitAssist @3; } } @@ -267,6 +287,10 @@ struct OnroadEventSP @0xda96579883444c35 { pedalPressedAlertOnly @16; laneTurnLeft @17; laneTurnRight @18; + speedLimitPreActive @19; + speedLimitActive @20; + speedLimitChanged @21; + speedLimitPending @22; } } diff --git a/selfdrive/car/card.py b/selfdrive/car/card.py index 2e52c00827..34f0283ce4 100755 --- a/selfdrive/car/card.py +++ b/selfdrive/car/card.py @@ -71,7 +71,7 @@ class Car: def __init__(self, CI=None, RI=None) -> None: self.can_sock = messaging.sub_sock('can', timeout=20) - self.sm = messaging.SubMaster(['pandaStates', 'carControl', 'onroadEvents'] + ['carControlSP']) + self.sm = messaging.SubMaster(['pandaStates', 'carControl', 'onroadEvents'] + ['carControlSP', 'longitudinalPlanSP']) self.pm = messaging.PubMaster(['sendcan', 'carState', 'carParams', 'carOutput', 'liveTracks'] + ['carParamsSP', 'carStateSP']) self.can_rcv_cum_timeout_counter = 0 @@ -216,6 +216,7 @@ class Car: if can_rcv_valid and REPLAY: self.can_log_mono_time = messaging.log_from_bytes(can_strs[0]).logMonoTime + self.v_cruise_helper.update_speed_limit_assist(self.is_metric, self.sm['longitudinalPlanSP']) self.v_cruise_helper.update_v_cruise(CS, self.sm['carControl'].enabled, self.is_metric) if self.sm['carControl'].enabled and not self.CC_prev.enabled: # Use CarState w/ buttons from the step selfdrived enables on diff --git a/selfdrive/car/cruise.py b/selfdrive/car/cruise.py index c82287d2b1..9973862b85 100644 --- a/selfdrive/car/cruise.py +++ b/selfdrive/car/cruise.py @@ -53,6 +53,7 @@ class VCruiseHelper(VCruiseHelperSP): if not self.CP.pcmCruise or (not self.CP_SP.pcmCruiseSpeed and _enabled): # if stock cruise is completely disabled, then we can use our own set speed logic self._update_v_cruise_non_pcm(CS, _enabled, is_metric) + self.update_speed_limit_assist_v_cruise_non_pcm() self.v_cruise_cluster_kph = self.v_cruise_kph self.update_button_timers(CS, enabled) else: @@ -104,6 +105,12 @@ class VCruiseHelper(VCruiseHelperSP): if not self.button_change_states[button_type]["enabled"]: return + # Speed Limit Assist for Non PCM long cars. + # True: Disallow set speed changes when user confirmed the target set speed during preActive state + # False: Allow set speed changes as SLA is not requesting user confirmation + if self.update_speed_limit_assist_pre_active_confirmed(button_type): + return + long_press, v_cruise_delta = VCruiseHelperSP.update_v_cruise_delta(self, long_press, v_cruise_delta) if long_press and self.v_cruise_kph % v_cruise_delta != 0: # partial interval self.v_cruise_kph = CRUISE_NEAREST_FUNC[button_type](self.v_cruise_kph / v_cruise_delta) * v_cruise_delta diff --git a/selfdrive/controls/lib/longitudinal_planner.py b/selfdrive/controls/lib/longitudinal_planner.py index 139cdc06e7..53eca38356 100755 --- a/selfdrive/controls/lib/longitudinal_planner.py +++ b/selfdrive/controls/lib/longitudinal_planner.py @@ -146,7 +146,7 @@ class LongitudinalPlanner(LongitudinalPlannerSP): clipped_accel_coast_interp = np.interp(v_ego, [MIN_ALLOW_THROTTLE_SPEED, MIN_ALLOW_THROTTLE_SPEED*2], [accel_clip[1], clipped_accel_coast]) accel_clip[1] = min(accel_clip[1], clipped_accel_coast_interp) - # Get new v_cruise and a_desired from Smart Cruise Control + # Get new v_cruise and a_desired from Smart Cruise Control and Speed Limit Assist v_cruise, self.a_desired = LongitudinalPlannerSP.update_targets(self, sm, self.v_desired_filter.x, self.a_desired, v_cruise) if force_slow_decel: diff --git a/selfdrive/controls/plannerd.py b/selfdrive/controls/plannerd.py index 8994fb7c08..4565a9c047 100755 --- a/selfdrive/controls/plannerd.py +++ b/selfdrive/controls/plannerd.py @@ -24,10 +24,11 @@ def main(): pm = messaging.PubMaster(['longitudinalPlan', 'driverAssistance', 'longitudinalPlanSP']) sm = messaging.SubMaster(['carControl', 'carState', 'controlsState', 'liveParameters', 'radarState', 'modelV2', 'selfdriveState', 'liveMapDataSP', 'carStateSP', gps_location_service], - poll='modelV2') + poll='carState') while True: sm.update() + longitudinal_planner.sla.update_car_state(sm['carState']) if sm.updated['modelV2']: longitudinal_planner.update(sm) longitudinal_planner.publish(sm, pm) diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index 170e184629..a13c873fbe 100755 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -205,6 +205,7 @@ class SelfdriveD(CruiseHelper): if not self.CP.notCar: self.events.add_from_msg(self.sm['driverMonitoringState'].events) + self.events_sp.add_from_msg(self.sm['longitudinalPlanSP'].events) # Add car events, ignore if CAN isn't valid if CS.canValid: diff --git a/selfdrive/ui/qt/onroad/hud.cc b/selfdrive/ui/qt/onroad/hud.cc index 4cfa3d0e3c..d95fe5fd80 100644 --- a/selfdrive/ui/qt/onroad/hud.cc +++ b/selfdrive/ui/qt/onroad/hud.cc @@ -47,10 +47,11 @@ void HudRenderer::draw(QPainter &p, const QRect &surface_rect) { bg.setColorAt(1, QColor::fromRgbF(0, 0, 0, 0)); p.fillRect(0, 0, surface_rect.width(), UI_HEADER_HEIGHT, bg); - +#ifndef SUNNYPILOT if (is_cruise_available) { drawSetSpeed(p, surface_rect); } +#endif drawCurrentSpeed(p, surface_rect); p.restore(); diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h index 22cdd8c631..295072d1ef 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/helpers.h @@ -38,10 +38,12 @@ enum class SpeedLimitMode { OFF, INFORMATION, WARNING, + ASSIST, }; inline const QString SpeedLimitModeTexts[]{ QObject::tr("Off"), QObject::tr("Information"), QObject::tr("Warning"), + QObject::tr("Assist"), }; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc index eed0306ca0..5f12403a17 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc @@ -28,6 +28,7 @@ SpeedLimitSettings::SpeedLimitSettings(QWidget *parent) : QStackedWidget(parent) SpeedLimitModeTexts[static_cast(SpeedLimitMode::OFF)], SpeedLimitModeTexts[static_cast(SpeedLimitMode::INFORMATION)], SpeedLimitModeTexts[static_cast(SpeedLimitMode::WARNING)], + SpeedLimitModeTexts[static_cast(SpeedLimitMode::ASSIST)], }; speed_limit_mode_settings = new ButtonParamControlSP( "SpeedLimitMode", @@ -35,7 +36,7 @@ SpeedLimitSettings::SpeedLimitSettings(QWidget *parent) : QStackedWidget(parent) "", "", speed_limit_mode_texts, - 385); + 380); list->addItem(speed_limit_mode_settings); list->addItem(horizontal_line()); diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h index 61c86f9208..10c44aa98c 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h @@ -58,8 +58,11 @@ private: QString off_str = tr("⦿ Off: Disables the Speed Limit functions."); QString info_str = tr("⦿ Information: Displays the current road's speed limit."); QString warning_str = tr("⦿ Warning: Provides a warning when exceeding the current road's speed limit."); + QString assist_str = tr("⦿ Assist: Adjusts the vehicle's cruise speed based on the current road's speed limit when operating the +/- buttons."); - if (mode == SpeedLimitMode::WARNING) { + if (mode == SpeedLimitMode::ASSIST) { + assist_str = "" + assist_str + ""; + } else if (mode == SpeedLimitMode::WARNING) { warning_str = "" + warning_str + ""; } else if (mode == SpeedLimitMode::INFORMATION) { info_str = "" + info_str + ""; @@ -67,9 +70,10 @@ private: off_str = "" + off_str + ""; } - return QString("%1
%2
%3") + return QString("%1
%2
%3
%4") .arg(off_str) .arg(info_str) - .arg(warning_str); + .arg(warning_str) + .arg(assist_str); } }; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index c07825c97c..df1bc3c002 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -11,7 +11,10 @@ #include "selfdrive/ui/qt/util.h" -HudRendererSP::HudRendererSP() {} +HudRendererSP::HudRendererSP() { + plus_arrow_up_img = loadPixmap("../../sunnypilot/selfdrive/assets/img_plus_arrow_up", {105, 105}); + minus_arrow_down_img = loadPixmap("../../sunnypilot/selfdrive/assets/img_minus_arrow_down", {105, 105}); +} void HudRendererSP::updateState(const UIState &s) { HudRenderer::updateState(s); @@ -36,6 +39,8 @@ void HudRendererSP::updateState(const UIState &s) { speedLimitLastValid = lp_sp.getSpeedLimit().getResolver().getSpeedLimitLastValid(); speedLimitFinalLast = lp_sp.getSpeedLimit().getResolver().getSpeedLimitFinalLast() * speedConv; speedLimitMode = static_cast(s.scene.speed_limit_mode); + speedLimitAssistState = lp_sp.getSpeedLimit().getAssist().getState(); + speedLimitAssistActive = lp_sp.getSpeedLimit().getAssist().getActive(); roadName = s.scene.road_name; if (sm.updated("liveMapDataSP")) { roadNameStr = QString::fromStdString(lmd.getRoadName()); @@ -104,6 +109,13 @@ void HudRendererSP::updateState(const UIState &s) { void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { HudRenderer::draw(p, surface_rect); + + p.save(); + + if (is_cruise_available) { + drawSetSpeedSP(p, surface_rect); + } + if (!reversing) { // Smart Cruise Control int x_offset = -260; @@ -152,14 +164,39 @@ void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { } // Speed Limit - if (speedLimitMode != SpeedLimitMode::OFF) { - drawSpeedLimitSigns(p); - drawUpcomingSpeedLimit(p); + bool showSpeedLimit; + bool speed_limit_assist_pre_active_pulse = pulseElement(speedLimitAssistFrame); + + // Position speed limit sign next to set speed box + const int sign_width = is_metric ? 200 : 172; + const int sign_x = is_metric ? 280 : 272; + const int sign_y = 45; + const int sign_height = 204; + QRect sign_rect(sign_x, sign_y, sign_width, sign_height); + + if (speedLimitAssistState == cereal::LongitudinalPlanSP::SpeedLimit::AssistState::PRE_ACTIVE) { + speedLimitAssistFrame++; + showSpeedLimit = speed_limit_assist_pre_active_pulse; + drawSpeedLimitPreActiveArrow(p, sign_rect); + } else { + speedLimitAssistFrame = 0; + showSpeedLimit = speedLimitMode != SpeedLimitMode::OFF; + } + + if (showSpeedLimit) { + drawSpeedLimitSigns(p, sign_rect); + + // do not show during SLA's preActive state + if (speedLimitAssistState != cereal::LongitudinalPlanSP::SpeedLimit::AssistState::PRE_ACTIVE) { + drawUpcomingSpeedLimit(p); + } } // Road Name drawRoadName(p, surface_rect); } + + p.restore(); } void HudRendererSP::drawText(QPainter &p, int x, int y, const QString &text, QColor color) { @@ -348,10 +385,10 @@ void HudRendererSP::drawStandstillTimer(QPainter &p, int x, int y) { } } -void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { - bool speedLimitWarningEnabled = speedLimitMode == SpeedLimitMode::WARNING; // TODO-SP: update to include SpeedLimitMode::ASSIST +void HudRendererSP::drawSpeedLimitSigns(QPainter &p, QRect &sign_rect) { + bool speedLimitWarningEnabled = speedLimitMode >= SpeedLimitMode::WARNING; // TODO-SP: update to include SpeedLimitMode::ASSIST bool hasSpeedLimit = speedLimitValid || speedLimitLastValid; - bool overspeed = hasSpeedLimit && speedLimitFinalLast < std::nearbyint(speed); + bool overspeed = hasSpeedLimit && std::nearbyint(speedLimitFinalLast) < std::nearbyint(speed); QString speedLimitStr = hasSpeedLimit ? QString::number(std::nearbyint(speedLimitLast)) : "---"; // Offset display text @@ -365,13 +402,6 @@ void HudRendererSP::drawSpeedLimitSigns(QPainter &p) { speedLimitSubTextFactor = 0.475; } - // Position next to MAX speed box - const int sign_width = is_metric ? 200 : 172; - const int sign_x = is_metric ? 280 : 272; - const int sign_y = 45; - const int sign_height = 204; - QRect sign_rect(sign_x, sign_y, sign_width, sign_height); - int alpha = 255; QColor red_color = QColor(255, 0, 0, alpha); QColor speed_color = (speedLimitWarningEnabled && overspeed) ? red_color : @@ -573,3 +603,66 @@ void HudRendererSP::drawRoadName(QPainter &p, const QRect &surface_rect) { QString truncated = fm.elidedText(roadNameStr, Qt::ElideRight, road_rect.width() - 20); p.drawText(road_rect, Qt::AlignCenter, truncated); } + +void HudRendererSP::drawSpeedLimitPreActiveArrow(QPainter &p, QRect &sign_rect) { + const int sign_margin = 12; + const int arrow_spacing = sign_margin * 3; + int arrow_x = sign_rect.right() + arrow_spacing; + + int _set_speed = std::nearbyint(set_speed); + int _speed_limit_final_last = std::nearbyint(speedLimitFinalLast); + + // Calculate the vertical offset using a sinusoidal function for smooth bouncing + double bounce_frequency = 2.0 * M_PI / UI_FREQ; // 20 frames for one full oscillation + int bounce_offset = 20 * sin(speedLimitAssistFrame * bounce_frequency); // Adjust the amplitude (20 pixels) as needed + + if (_set_speed < _speed_limit_final_last) { + QPoint iconPosition(arrow_x, sign_rect.center().y() - plus_arrow_up_img.height() / 2 + bounce_offset); + p.drawPixmap(iconPosition, plus_arrow_up_img); + } else if (_set_speed > _speed_limit_final_last) { + QPoint iconPosition(arrow_x, sign_rect.center().y() - minus_arrow_down_img.height() / 2 - bounce_offset); + p.drawPixmap(iconPosition, minus_arrow_down_img); + } +} + +void HudRendererSP::drawSetSpeedSP(QPainter &p, const QRect &surface_rect) { + // Draw outer box + border to contain set speed + const QSize default_size = {172, 204}; + QSize set_speed_size = is_metric ? QSize(200, 204) : default_size; + QRect set_speed_rect(QPoint(60 + (default_size.width() - set_speed_size.width()) / 2, 45), set_speed_size); + + // Draw set speed box + p.setPen(QPen(QColor(255, 255, 255, 75), 6)); + p.setBrush(QColor(0, 0, 0, 166)); + p.drawRoundedRect(set_speed_rect, 32, 32); + + // Colors based on status + QColor max_color = QColor(0xa6, 0xa6, 0xa6, 0xff); + QColor set_speed_color = QColor(0x72, 0x72, 0x72, 0xff); + if (is_cruise_set) { + set_speed_color = QColor(255, 255, 255); + if (speedLimitAssistActive) { + set_speed_color = longOverride ? QColor(0x91, 0x9b, 0x95, 0xff) : QColor(0, 0xff, 0, 0xff); + max_color = longOverride ? QColor(0x91, 0x9b, 0x95, 0xff) : QColor(0x80, 0xd8, 0xa6, 0xff); + } else { + if (status == STATUS_DISENGAGED) { + max_color = QColor(255, 255, 255); + } else if (status == STATUS_OVERRIDE) { + max_color = QColor(0x91, 0x9b, 0x95, 0xff); + } else { + max_color = QColor(0x80, 0xd8, 0xa6, 0xff); + } + } + } + + // Draw "MAX" text + p.setFont(InterFont(40, QFont::DemiBold)); + p.setPen(max_color); + p.drawText(set_speed_rect.adjusted(0, 27, 0, 0), Qt::AlignTop | Qt::AlignHCenter, tr("MAX")); + + // Draw set speed + QString setSpeedStr = is_cruise_set ? QString::number(std::nearbyint(set_speed)) : "–"; + p.setFont(InterFont(90, QFont::Bold)); + p.setPen(set_speed_color); + p.drawText(set_speed_rect.adjusted(0, 77, 0, 0), Qt::AlignTop | Qt::AlignHCenter, setSpeedStr); +} diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.h b/selfdrive/ui/sunnypilot/qt/onroad/hud.h index d77892fa2d..043536bf4c 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.h +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.h @@ -31,9 +31,11 @@ private: void drawStandstillTimer(QPainter &p, int x, int y); bool pulseElement(int frame); void drawSmartCruiseControlOnroadIcon(QPainter &p, const QRect &surface_rect, int x_offset, int y_offset, std::string name); - void drawSpeedLimitSigns(QPainter &p); + void drawSpeedLimitSigns(QPainter &p, QRect &sign_rect); void drawUpcomingSpeedLimit(QPainter &p); void drawRoadName(QPainter &p, const QRect &surface_rect); + void drawSpeedLimitPreActiveArrow(QPainter &p, QRect &sign_rect); + void drawSetSpeedSP(QPainter &p, const QRect &surface_rect); bool lead_status; float lead_d_rel; @@ -86,4 +88,9 @@ private: SpeedLimitMode speedLimitMode = SpeedLimitMode::OFF; bool roadName; QString roadNameStr; + cereal::LongitudinalPlanSP::SpeedLimit::AssistState speedLimitAssistState; + bool speedLimitAssistActive; + int speedLimitAssistFrame; + QPixmap plus_arrow_up_img; + QPixmap minus_arrow_down_img; }; diff --git a/sunnypilot/selfdrive/assets/img_minus_arrow_down.png b/sunnypilot/selfdrive/assets/img_minus_arrow_down.png new file mode 100644 index 0000000000..250f640585 --- /dev/null +++ b/sunnypilot/selfdrive/assets/img_minus_arrow_down.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0f4a0bf26cfd2c64939759d43bee839aadfd017a6f74065095a27b03615e55a4 +size 26627 diff --git a/sunnypilot/selfdrive/assets/img_plus_arrow_up.png b/sunnypilot/selfdrive/assets/img_plus_arrow_up.png new file mode 100644 index 0000000000..14c1529da3 --- /dev/null +++ b/sunnypilot/selfdrive/assets/img_plus_arrow_up.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e451ff31e9b3f144822ab282b8e47cd5a603ca59ff94bd1849271181b86c6b1 +size 29220 diff --git a/sunnypilot/selfdrive/car/cruise_ext.py b/sunnypilot/selfdrive/car/cruise_ext.py index 716e3e1c93..3691c35972 100644 --- a/sunnypilot/selfdrive/car/cruise_ext.py +++ b/sunnypilot/selfdrive/car/cruise_ext.py @@ -6,18 +6,24 @@ See the LICENSE.md file in the root directory for more details. """ import numpy as np -from cereal import car +from cereal import car, custom from opendbc.car import structs +from openpilot.common.constants import CV from openpilot.common.params import Params from openpilot.sunnypilot.selfdrive.car.intelligent_cruise_button_management.helpers import get_minimum_set_speed +from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.speed_limit_assist import ACTIVE_STATES as SLA_ACTIVE_STATES +from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.helpers import compare_cluster_target ButtonType = car.CarState.ButtonEvent.Type +SpeedLimitAssistState = custom.LongitudinalPlanSP.SpeedLimit.AssistState CRUISE_BUTTON_TIMER = {ButtonType.decelCruise: 0, ButtonType.accelCruise: 0, ButtonType.setCruise: 0, ButtonType.resumeCruise: 0, ButtonType.cancel: 0, ButtonType.mainCruise: 0} V_CRUISE_MIN = 8 +V_CRUISE_MAX = 145 +V_CRUISE_UNSET = 255 def update_manual_button_timers(CS: car.CarState, button_timers: dict[car.CarState.ButtonEvent.Type, int]) -> None: @@ -32,11 +38,12 @@ def update_manual_button_timers(CS: car.CarState, button_timers: dict[car.CarSta button_timers[b.type.raw] = 1 if b.pressed else 0 - class VCruiseHelperSP: def __init__(self, CP: structs.CarParams, CP_SP: structs.CarParamsSP) -> None: self.CP = CP self.CP_SP = CP_SP + self.v_cruise_kph = V_CRUISE_UNSET + self.v_cruise_cluster_kph = V_CRUISE_UNSET self.params = Params() self.v_cruise_min = 0 self.enabled_prev = False @@ -47,6 +54,16 @@ class VCruiseHelperSP: self.enable_button_timers = CRUISE_BUTTON_TIMER + # Speed Limit Assist + self.sla_state = SpeedLimitAssistState.disabled + self.prev_sla_state = SpeedLimitAssistState.disabled + self.has_speed_limit = False + self.speed_limit_final_last = 0. + self.speed_limit_final_last_kph = 0. + self.prev_speed_limit_final_last_kph = 0. + self.req_plus = False + self.req_minus = False + def read_custom_set_speed_params(self) -> None: self.custom_acc_enabled = self.params.get_bool("CustomAccIncrementsEnabled") self.short_increment = self.params.get("CustomAccShortPressIncrement", return_default=True) @@ -89,3 +106,33 @@ class VCruiseHelperSP: return enabled and self.enabled_prev return enabled + + def update_speed_limit_assist(self, is_metric, LP_SP: custom.LongitudinalPlanSP) -> None: + resolver = LP_SP.speedLimit.resolver + self.has_speed_limit = resolver.speedLimitValid or resolver.speedLimitLastValid + self.speed_limit_final_last = LP_SP.speedLimit.resolver.speedLimitFinalLast + self.speed_limit_final_last_kph = self.speed_limit_final_last * CV.MS_TO_KPH + self.sla_state = LP_SP.speedLimit.assist.state + self.req_plus, self.req_minus = compare_cluster_target(self.v_cruise_cluster_kph * CV.KPH_TO_MS, + self.speed_limit_final_last, is_metric) + + @property + def update_speed_limit_final_last_changed(self) -> bool: + return self.has_speed_limit and bool(self.speed_limit_final_last_kph != self.prev_speed_limit_final_last_kph) + + def update_speed_limit_assist_pre_active_confirmed(self, button_type: car.CarState.ButtonEvent.Type) -> bool: + if self.sla_state == SpeedLimitAssistState.preActive or self.prev_sla_state == SpeedLimitAssistState.preActive: + if button_type == ButtonType.decelCruise and self.req_minus: + return True + if button_type == ButtonType.accelCruise and self.req_plus: + return True + + return False + + def update_speed_limit_assist_v_cruise_non_pcm(self) -> None: + if self.sla_state in SLA_ACTIVE_STATES and (self.prev_sla_state not in SLA_ACTIVE_STATES or + self.update_speed_limit_final_last_changed): + self.v_cruise_kph = np.clip(round(self.speed_limit_final_last_kph, 1), self.v_cruise_min, V_CRUISE_MAX) + + self.prev_sla_state = self.sla_state + self.prev_speed_limit_final_last_kph = self.speed_limit_final_last_kph diff --git a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py index 40d30100c5..ece2ff2419 100644 --- a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py +++ b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py @@ -7,22 +7,29 @@ See the LICENSE.md file in the root directory for more details. from cereal import messaging, custom from opendbc.car import structs +from openpilot.common.constants import CV +from openpilot.selfdrive.car.cruise import V_CRUISE_MAX from openpilot.sunnypilot.selfdrive.controls.lib.dec.dec import DynamicExperimentalController from openpilot.sunnypilot.selfdrive.controls.lib.smart_cruise_control.smart_cruise_control import SmartCruiseControl +from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.speed_limit_assist import SpeedLimitAssist from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.speed_limit_resolver import SpeedLimitResolver +from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP from openpilot.sunnypilot.models.helpers import get_active_bundle DecState = custom.LongitudinalPlanSP.DynamicExperimentalControl.DynamicExperimentalControlState -Source = custom.LongitudinalPlanSP.LongitudinalPlanSource +LongitudinalPlanSource = custom.LongitudinalPlanSP.LongitudinalPlanSource class LongitudinalPlannerSP: def __init__(self, CP: structs.CarParams, mpc): + self.events_sp = EventsSP() + self.resolver = SpeedLimitResolver() self.dec = DynamicExperimentalController(CP, mpc) self.scc = SmartCruiseControl() self.resolver = SpeedLimitResolver() + self.sla = SpeedLimitAssist(CP) self.generation = int(model_bundle.generation) if (model_bundle := get_active_bundle()) else None - self.source = Source.cruise + self.source = LongitudinalPlanSource.cruise self.output_v_target = 0. self.output_a_target = 0. @@ -39,15 +46,31 @@ class LongitudinalPlannerSP: return self.dec.mode() def update_targets(self, sm: messaging.SubMaster, v_ego: float, a_ego: float, v_cruise: float) -> tuple[float, float]: - self.scc.update(sm, v_ego, a_ego, v_cruise) + CS = sm['carState'] + v_cruise_cluster_kph = min(CS.vCruiseCluster, V_CRUISE_MAX) + v_cruise_cluster = v_cruise_cluster_kph * CV.KPH_TO_MS + + long_enabled = sm['carControl'].enabled + long_override = sm['carControl'].cruiseControl.override + + self.events_sp.clear() + + # Smart Cruise Control + self.scc.update(sm, long_enabled, long_override, v_ego, a_ego, v_cruise) # Speed Limit Resolver self.resolver.update(v_ego, sm) + # Speed Limit Assist + has_speed_limit = self.resolver.speed_limit_valid or self.resolver.speed_limit_last_valid + self.sla.update(long_enabled, long_override, v_ego, a_ego, v_cruise_cluster, self.resolver.speed_limit, + self.resolver.speed_limit_final_last, has_speed_limit, self.resolver.distance, self.events_sp) + targets = { - Source.cruise: (v_cruise, a_ego), - Source.sccVision: (self.scc.vision.output_v_target, self.scc.vision.output_a_target), - Source.sccMap: (self.scc.map.output_v_target, self.scc.map.output_a_target), + LongitudinalPlanSource.cruise: (v_cruise, a_ego), + LongitudinalPlanSource.sccVision: (self.scc.vision.output_v_target, self.scc.vision.output_a_target), + LongitudinalPlanSource.sccMap: (self.scc.map.output_v_target, self.scc.map.output_a_target), + LongitudinalPlanSource.speedLimitAssist: (self.sla.output_v_target, self.sla.output_a_target), } self.source = min(targets, key=lambda k: targets[k][0]) @@ -66,6 +89,7 @@ class LongitudinalPlannerSP: longitudinalPlanSP.longitudinalPlanSource = self.source longitudinalPlanSP.vTarget = float(self.output_v_target) longitudinalPlanSP.aTarget = float(self.output_a_target) + longitudinalPlanSP.events = self.events_sp.to_msg() # Dynamic Experimental Control dec = longitudinalPlanSP.dec @@ -104,5 +128,11 @@ class LongitudinalPlannerSP: resolver.speedLimitOffset = float(self.resolver.speed_limit_offset) resolver.distToSpeedLimit = float(self.resolver.distance) resolver.source = self.resolver.source + assist = speedLimit.assist + assist.state = self.sla.state + assist.enabled = self.sla.is_enabled + assist.active = self.sla.is_active + assist.vTarget = float(self.sla.output_v_target) + assist.aTarget = float(self.sla.output_a_target) pm.send('longitudinalPlanSP', plan_sp_send) diff --git a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/smart_cruise_control.py b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/smart_cruise_control.py index 0f60621658..4ca45202fc 100644 --- a/sunnypilot/selfdrive/controls/lib/smart_cruise_control/smart_cruise_control.py +++ b/sunnypilot/selfdrive/controls/lib/smart_cruise_control/smart_cruise_control.py @@ -14,9 +14,6 @@ class SmartCruiseControl: self.vision = SmartCruiseControlVision() self.map = SmartCruiseControlMap() - def update(self, sm: messaging.SubMaster, v_ego: float, a_ego: float, v_cruise: float) -> None: - long_enabled = sm['carControl'].enabled - long_override = sm['carControl'].cruiseControl.override - + def update(self, sm: messaging.SubMaster, long_enabled: bool, long_override: bool, v_ego: float, a_ego: float, v_cruise: float) -> None: self.map.update(long_enabled, long_override, v_ego, a_ego, v_cruise) self.vision.update(sm, long_enabled, long_override, v_ego, a_ego, v_cruise) diff --git a/sunnypilot/selfdrive/controls/lib/speed_limit/__init__.py b/sunnypilot/selfdrive/controls/lib/speed_limit/__init__.py index af14a87f0c..22ea75fe19 100644 --- a/sunnypilot/selfdrive/controls/lib/speed_limit/__init__.py +++ b/sunnypilot/selfdrive/controls/lib/speed_limit/__init__.py @@ -6,3 +6,14 @@ See the LICENSE.md file in the root directory for more details. """ LIMIT_ADAPT_ACC = -1. # m/s^2 Ideal acceleration for the adapting (braking) phase when approaching speed limits. LIMIT_MAX_MAP_DATA_AGE = 10. # s Maximum time to hold to map data, then consider it invalid inside limits controllers. + +# Speed Limit Assist constants +PCM_LONG_REQUIRED_MAX_SET_SPEED = { + True: (33.3333, 36.1111), # km/h, (120, 130) + False: (31.2928, 35.7632), # mph, (70, 80) +} + +CONFIRM_SPEED_THRESHOLD = { + True: 80, # km/h + False: 50, # mph +} diff --git a/sunnypilot/selfdrive/controls/lib/speed_limit/common.py b/sunnypilot/selfdrive/controls/lib/speed_limit/common.py index 7d219ac3bb..baf9328032 100644 --- a/sunnypilot/selfdrive/controls/lib/speed_limit/common.py +++ b/sunnypilot/selfdrive/controls/lib/speed_limit/common.py @@ -19,3 +19,10 @@ class OffsetType(IntEnum): off = 0 fixed = 1 percentage = 2 + + +class Mode(IntEnum): + off = 0 + information = 1 + warning = 2 + assist = 3 diff --git a/sunnypilot/selfdrive/controls/lib/speed_limit/helpers.py b/sunnypilot/selfdrive/controls/lib/speed_limit/helpers.py new file mode 100644 index 0000000000..40e8f653ff --- /dev/null +++ b/sunnypilot/selfdrive/controls/lib/speed_limit/helpers.py @@ -0,0 +1,19 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" + +from openpilot.common.constants import CV + + +def compare_cluster_target(v_cruise_cluster: float, target_set_speed: float, is_metric: bool) -> tuple[bool, bool]: + speed_conv = CV.MS_TO_KPH if is_metric else CV.MS_TO_MPH + v_cruise_cluster_conv = round(v_cruise_cluster * speed_conv) + target_set_speed_conv = round(target_set_speed * speed_conv) + + req_plus = v_cruise_cluster_conv < target_set_speed_conv + req_minus = v_cruise_cluster_conv > target_set_speed_conv + + return req_plus, req_minus diff --git a/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_assist.py b/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_assist.py new file mode 100644 index 0000000000..bb03a9eb1c --- /dev/null +++ b/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_assist.py @@ -0,0 +1,401 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" +import time + +from cereal import custom, car +from openpilot.common.params import Params +from openpilot.common.constants import CV +from openpilot.common.realtime import DT_MDL +from openpilot.sunnypilot import PARAMS_UPDATE_PERIOD +from openpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N +from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP +from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit import PCM_LONG_REQUIRED_MAX_SET_SPEED, CONFIRM_SPEED_THRESHOLD +from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.common import Mode +from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.helpers import compare_cluster_target +from openpilot.selfdrive.modeld.constants import ModelConstants + +ButtonType = car.CarState.ButtonEvent.Type +EventNameSP = custom.OnroadEventSP.EventName +SpeedLimitAssistState = custom.LongitudinalPlanSP.SpeedLimit.AssistState +SpeedLimitSource = custom.LongitudinalPlanSP.SpeedLimit.Source + +ACTIVE_STATES = (SpeedLimitAssistState.active, SpeedLimitAssistState.adapting) +ENABLED_STATES = (SpeedLimitAssistState.preActive, SpeedLimitAssistState.pending, *ACTIVE_STATES) + +DISABLED_GUARD_PERIOD = 0.5 # secs. +PRE_ACTIVE_GUARD_PERIOD = 15 # secs. Time to wait after activation before considering temp deactivation signal. +SPEED_LIMIT_CHANGED_HOLD_PERIOD = 1 # secs. Time to wait after speed limit change before switching to preActive. + +LIMIT_MIN_ACC = -1.5 # m/s^2 Maximum deceleration allowed for limit controllers to provide. +LIMIT_MAX_ACC = 1.0 # m/s^2 Maximum acceleration allowed for limit controllers to provide while active. +LIMIT_MIN_SPEED = 8.33 # m/s, Minimum speed limit to provide as solution on limit controllers. +LIMIT_SPEED_OFFSET_TH = -1. # m/s Maximum offset between speed limit and current speed for adapting state. +V_CRUISE_UNSET = 255 + +CRUISE_BUTTONS_PLUS = (ButtonType.accelCruise, ButtonType.resumeCruise) +CRUISE_BUTTONS_MINUS = (ButtonType.decelCruise, ButtonType.setCruise) +CRUISE_BUTTON_CONFIRM_HOLD = 0.5 # secs. + + +class SpeedLimitAssist: + _speed_limit_final_last: float + _distance: float + v_ego: float + a_ego: float + v_offset: float + + def __init__(self, CP): + self.params = Params() + self.CP = CP + self.frame = -1 + self.long_engaged_timer = 0 + self.pre_active_timer = 0 + self.speed_limit_changed_timer = 0 + self.is_metric = self.params.get_bool("IsMetric") + self.enabled = self.params.get("SpeedLimitMode", return_default=True) == Mode.assist + self.long_enabled = False + self.long_enabled_prev = False + self.is_enabled = False + self.is_active = False + self.output_v_target = V_CRUISE_UNSET + self.output_a_target = 0. + self.v_ego = 0. + self.a_ego = 0. + self.v_offset = 0. + self.target_set_speed_conv = 0 + self.prev_target_set_speed_conv = 0 + self.v_cruise_cluster = 0. + self.v_cruise_cluster_prev = 0. + self.v_cruise_cluster_conv = 0 + self.prev_v_cruise_cluster_conv = 0 + self._has_speed_limit = False + self._speed_limit = 0. + self._speed_limit_final_last = 0. + self.speed_limit_prev = 0. + self.speed_limit_final_last_conv = 0 + self.prev_speed_limit_final_last_conv = 0 + self._distance = 0. + self.state = SpeedLimitAssistState.disabled + self._state_prev = SpeedLimitAssistState.disabled + self.pcm_op_long = CP.openpilotLongitudinalControl and CP.pcmCruise + + self._plus_hold = 0. + self._minus_hold = 0. + self._last_carstate_ts = 0. + + # TODO-SP: SLA's own output_a_target for planner + # Solution functions mapped to respective states + self.acceleration_solutions = { + SpeedLimitAssistState.disabled: self.get_current_acceleration_as_target, + SpeedLimitAssistState.inactive: self.get_current_acceleration_as_target, + SpeedLimitAssistState.preActive: self.get_current_acceleration_as_target, + SpeedLimitAssistState.pending: self.get_current_acceleration_as_target, + SpeedLimitAssistState.adapting: self.get_adapting_state_target_acceleration, + SpeedLimitAssistState.active: self.get_active_state_target_acceleration, + } + + @property + def speed_limit_changed(self) -> bool: + return self._has_speed_limit and bool(self._speed_limit != self.speed_limit_prev) + + @property + def v_cruise_cluster_changed(self) -> bool: + return bool(self.v_cruise_cluster_conv != self.prev_v_cruise_cluster_conv) + + @property + def target_set_speed_confirmed(self) -> bool: + return bool(self.v_cruise_cluster_conv == self.target_set_speed_conv) + + def get_v_target_from_control(self) -> float: + if self._has_speed_limit: + if self.pcm_op_long and self.is_enabled: + return self._speed_limit_final_last + if not self.pcm_op_long and self.is_active: + return self._speed_limit_final_last + + # Fallback + return V_CRUISE_UNSET + + # TODO-SP: SLA's own output_a_target for planner + def get_a_target_from_control(self) -> float: + return self.a_ego + + def update_params(self) -> None: + if self.frame % int(PARAMS_UPDATE_PERIOD / DT_MDL) == 0: + self.is_metric = self.params.get_bool("IsMetric") + self.enabled = self.params.get("SpeedLimitMode", return_default=True) == Mode.assist + + def update_car_state(self, CS: car.CarState) -> None: + now = time.monotonic() + self._last_carstate_ts = now + + for b in CS.buttonEvents: + if not b.pressed: + if b.type in CRUISE_BUTTONS_PLUS: + self._plus_hold = max(self._plus_hold, now + CRUISE_BUTTON_CONFIRM_HOLD) + elif b.type in CRUISE_BUTTONS_MINUS: + self._minus_hold = max(self._minus_hold, now + CRUISE_BUTTON_CONFIRM_HOLD) + + def _get_button_release(self, req_plus: bool, req_minus: bool) -> bool: + now = time.monotonic() + if req_plus and now <= self._plus_hold: + self._plus_hold = 0. + return True + elif req_minus and now <= self._minus_hold: + self._minus_hold = 0. + return True + + # expired + if now > self._plus_hold: + self._plus_hold = 0. + if now > self._minus_hold: + self._minus_hold = 0. + return False + + def update_calculations(self, v_cruise_cluster: float) -> None: + speed_conv = CV.MS_TO_KPH if self.is_metric else CV.MS_TO_MPH + self.v_cruise_cluster = v_cruise_cluster + + # Update current velocity offset (error) + self.v_offset = self._speed_limit_final_last - self.v_ego + + self.speed_limit_final_last_conv = round(self._speed_limit_final_last * speed_conv) + self.v_cruise_cluster_conv = round(self.v_cruise_cluster * speed_conv) + + cst_low, cst_high = PCM_LONG_REQUIRED_MAX_SET_SPEED[self.is_metric] + pcm_long_required_max = cst_low if self._has_speed_limit and self.speed_limit_final_last_conv < CONFIRM_SPEED_THRESHOLD[self.is_metric] else \ + cst_high + pcm_long_required_max_set_speed_conv = round(pcm_long_required_max * speed_conv) + + self.target_set_speed_conv = pcm_long_required_max_set_speed_conv if self.pcm_op_long else self.speed_limit_final_last_conv + + @property + def apply_confirm_speed_threshold(self) -> bool: + # below CST: always require user confirmation + if self.v_cruise_cluster_conv < CONFIRM_SPEED_THRESHOLD[self.is_metric]: + return True + + # at/above CST: + # - new speed limit >= CST: auto change + # - new speed limit < CST: user confirmation required + return bool(self.speed_limit_final_last_conv < CONFIRM_SPEED_THRESHOLD[self.is_metric]) + + def get_current_acceleration_as_target(self) -> float: + return self.a_ego + + def get_adapting_state_target_acceleration(self) -> float: + if self._distance > 0: + return (self._speed_limit_final_last ** 2 - self.v_ego ** 2) / (2. * self._distance) + + return self.v_offset / float(ModelConstants.T_IDXS[CONTROL_N]) + + def get_active_state_target_acceleration(self) -> float: + return self.v_offset / float(ModelConstants.T_IDXS[CONTROL_N]) + + def _update_confirmed_state(self): + if self._has_speed_limit: + if self.v_offset < LIMIT_SPEED_OFFSET_TH: + self.state = SpeedLimitAssistState.adapting + else: + self.state = SpeedLimitAssistState.active + else: + self.state = SpeedLimitAssistState.pending + + def _update_non_pcm_long_confirmed_state(self) -> bool: + if self.target_set_speed_confirmed: + return True + + if self.state != SpeedLimitAssistState.preActive: + return False + + req_plus, req_minus = compare_cluster_target(self.v_cruise_cluster, self._speed_limit_final_last, self.is_metric) + + return self._get_button_release(req_plus, req_minus) + + def update_state_machine_pcm_op_long(self): + self.long_engaged_timer = max(0, self.long_engaged_timer - 1) + self.pre_active_timer = max(0, self.pre_active_timer - 1) + + # ACTIVE, ADAPTING, PENDING, PRE_ACTIVE, INACTIVE + if self.state != SpeedLimitAssistState.disabled: + if not self.long_enabled or not self.enabled: + self.state = SpeedLimitAssistState.disabled + + else: + # ACTIVE + if self.state == SpeedLimitAssistState.active: + if self.v_cruise_cluster_changed: + self.state = SpeedLimitAssistState.inactive + elif self.speed_limit_changed and self.apply_confirm_speed_threshold: + self.state = SpeedLimitAssistState.preActive + self.pre_active_timer = int(PRE_ACTIVE_GUARD_PERIOD / DT_MDL) + elif self._has_speed_limit and self.v_offset < LIMIT_SPEED_OFFSET_TH: + self.state = SpeedLimitAssistState.adapting + + # ADAPTING + elif self.state == SpeedLimitAssistState.adapting: + if self.v_cruise_cluster_changed: + self.state = SpeedLimitAssistState.inactive + elif self.speed_limit_changed and self.apply_confirm_speed_threshold: + self.state = SpeedLimitAssistState.preActive + self.pre_active_timer = int(PRE_ACTIVE_GUARD_PERIOD / DT_MDL) + elif self.v_offset >= LIMIT_SPEED_OFFSET_TH: + self.state = SpeedLimitAssistState.active + + # PENDING + elif self.state == SpeedLimitAssistState.pending: + if self._has_speed_limit: + if self.v_offset < LIMIT_SPEED_OFFSET_TH: + self.state = SpeedLimitAssistState.adapting + else: + self.state = SpeedLimitAssistState.active + + # PRE_ACTIVE + elif self.state == SpeedLimitAssistState.preActive: + if self.target_set_speed_confirmed: + self._update_confirmed_state() + elif self.pre_active_timer <= 0: + # Timeout - session ended + self.state = SpeedLimitAssistState.inactive + + # INACTIVE + elif self.state == SpeedLimitAssistState.inactive: + pass + + # DISABLED + elif self.state == SpeedLimitAssistState.disabled: + if self.long_enabled and self.enabled: + # start or reset preActive timer if initially enabled or manual set speed change detected + if not self.long_enabled_prev or self.v_cruise_cluster_changed: + self.long_engaged_timer = int(DISABLED_GUARD_PERIOD / DT_MDL) + + elif self.long_engaged_timer <= 0: + if self.target_set_speed_confirmed: + self._update_confirmed_state() + else: + self.state = SpeedLimitAssistState.preActive + self.pre_active_timer = int(PRE_ACTIVE_GUARD_PERIOD / DT_MDL) + + enabled = self.state in ENABLED_STATES + active = self.state in ACTIVE_STATES + + return enabled, active + + def update_state_machine_non_pcm_long(self): + self.long_engaged_timer = max(0, self.long_engaged_timer - 1) + self.pre_active_timer = max(0, self.pre_active_timer - 1) + self.speed_limit_changed_timer = max(0, self.speed_limit_changed_timer - 1) + + # ACTIVE, ADAPTING, PENDING, PRE_ACTIVE, INACTIVE + if self.state != SpeedLimitAssistState.disabled: + if not self.long_enabled or not self.enabled: + self.state = SpeedLimitAssistState.disabled + + else: + # ACTIVE + if self.state == SpeedLimitAssistState.active: + if self.v_cruise_cluster_changed: + self.state = SpeedLimitAssistState.inactive + + elif self.speed_limit_changed and self.apply_confirm_speed_threshold: + self.speed_limit_changed_timer = int(SPEED_LIMIT_CHANGED_HOLD_PERIOD / DT_MDL) + elif self.speed_limit_changed_timer <= 0: + self.state = SpeedLimitAssistState.preActive + self.pre_active_timer = int(PRE_ACTIVE_GUARD_PERIOD / DT_MDL) + + # PRE_ACTIVE + elif self.state == SpeedLimitAssistState.preActive: + if self._update_non_pcm_long_confirmed_state(): + self.state = SpeedLimitAssistState.active + elif self.pre_active_timer <= 0: + # Timeout - session ended + self.state = SpeedLimitAssistState.inactive + + # INACTIVE + elif self.state == SpeedLimitAssistState.inactive: + if self.speed_limit_changed: + self.speed_limit_changed_timer = int(SPEED_LIMIT_CHANGED_HOLD_PERIOD / DT_MDL) + elif self.speed_limit_changed_timer <= 0: + self.state = SpeedLimitAssistState.preActive + self.pre_active_timer = int(PRE_ACTIVE_GUARD_PERIOD / DT_MDL) + elif self._update_non_pcm_long_confirmed_state(): + self.state = SpeedLimitAssistState.active + + # DISABLED + elif self.state == SpeedLimitAssistState.disabled: + if self.long_enabled and self.enabled: + # start or reset preActive timer if initially enabled or manual set speed change detected + if not self.long_enabled_prev or self.v_cruise_cluster_changed: + self.long_engaged_timer = int(DISABLED_GUARD_PERIOD / DT_MDL) + + elif self.long_engaged_timer <= 0: + if self._update_non_pcm_long_confirmed_state(): + self.state = SpeedLimitAssistState.active + elif self._has_speed_limit: + self.state = SpeedLimitAssistState.preActive + self.pre_active_timer = int(PRE_ACTIVE_GUARD_PERIOD / DT_MDL) + else: + self.state = SpeedLimitAssistState.inactive + + enabled = self.state in ENABLED_STATES + active = self.state in ACTIVE_STATES + + return enabled, active + + def update_events(self, events_sp: EventsSP) -> None: + if self.state == SpeedLimitAssistState.preActive: + events_sp.add(EventNameSP.speedLimitPreActive) + + if self.state == SpeedLimitAssistState.pending and self._state_prev != SpeedLimitAssistState.pending: + events_sp.add(EventNameSP.speedLimitPending) + + if self.is_active: + if self._state_prev not in ACTIVE_STATES: + events_sp.add(EventNameSP.speedLimitActive) + + # only notify if we acquire a valid speed limit + # do not check has_speed_limit here + elif self._speed_limit != self.speed_limit_prev: + if self.speed_limit_prev <= 0: + events_sp.add(EventNameSP.speedLimitActive) + elif self.speed_limit_prev > 0 and self._speed_limit > 0: + events_sp.add(EventNameSP.speedLimitChanged) + + def update(self, long_enabled: bool, long_override: bool, v_ego: float, a_ego: float, v_cruise_cluster: float, speed_limit: float, + speed_limit_final_last: float, has_speed_limit: bool, distance: float, events_sp: EventsSP) -> None: + self.long_enabled = long_enabled + self.v_ego = v_ego + self.a_ego = a_ego + + self._has_speed_limit = has_speed_limit + self._speed_limit = speed_limit + self._speed_limit_final_last = speed_limit_final_last + self._distance = distance + + self.update_params() + self.update_calculations(v_cruise_cluster) + + self._state_prev = self.state + if self.pcm_op_long: + self.is_enabled, self.is_active = self.update_state_machine_pcm_op_long() + else: + self.is_enabled, self.is_active = self.update_state_machine_non_pcm_long() + + self.update_events(events_sp) + + # Update change tracking variables + self.speed_limit_prev = self._speed_limit + self.v_cruise_cluster_prev = self.v_cruise_cluster + self.long_enabled_prev = self.long_enabled + self.prev_target_set_speed_conv = self.target_set_speed_conv + self.prev_v_cruise_cluster_conv = self.v_cruise_cluster_conv + self.prev_speed_limit_final_last_conv = self.speed_limit_final_last_conv + + self.output_v_target = self.get_v_target_from_control() + self.output_a_target = self.get_a_target_from_control() + + self.frame += 1 diff --git a/sunnypilot/selfdrive/controls/lib/speed_limit/tests/test_speed_limit_assist.py b/sunnypilot/selfdrive/controls/lib/speed_limit/tests/test_speed_limit_assist.py new file mode 100644 index 0000000000..3b2716265d --- /dev/null +++ b/sunnypilot/selfdrive/controls/lib/speed_limit/tests/test_speed_limit_assist.py @@ -0,0 +1,227 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" +from cereal import custom + +from opendbc.car.car_helpers import interfaces +from opendbc.car.toyota.values import CAR as TOYOTA +from openpilot.common.constants import CV +from openpilot.common.params import Params +from openpilot.common.realtime import DT_MDL +from openpilot.selfdrive.car.cruise import V_CRUISE_UNSET +from openpilot.sunnypilot.selfdrive.car import interfaces as sunnypilot_interfaces +from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.common import Mode +from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit import PCM_LONG_REQUIRED_MAX_SET_SPEED +from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.speed_limit_assist import SpeedLimitAssist, \ + PRE_ACTIVE_GUARD_PERIOD, ACTIVE_STATES +from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP + +SpeedLimitAssistState = custom.LongitudinalPlanSP.SpeedLimit.AssistState + +ALL_STATES = tuple(SpeedLimitAssistState.schema.enumerants.values()) + +SPEED_LIMITS = { + 'residential': 25 * CV.MPH_TO_MS, # 25 mph + 'city': 35 * CV.MPH_TO_MS, # 35 mph + 'highway': 65 * CV.MPH_TO_MS, # 65 mph + 'freeway': 80 * CV.MPH_TO_MS, # 80 mph +} + + +class TestSpeedLimitAssist: + + def setup_method(self): + self.params = Params() + self.reset_custom_params() + self.events_sp = EventsSP() + CI = self._setup_platform(TOYOTA.TOYOTA_RAV4_TSS2) + self.sla = SpeedLimitAssist(CI.CP) + self.sla.pre_active_timer = int(PRE_ACTIVE_GUARD_PERIOD / DT_MDL) + self.pcm_long_max_set_speed = PCM_LONG_REQUIRED_MAX_SET_SPEED[self.sla.is_metric][1] # use 80 MPH for now + self.speed_conv = CV.MS_TO_KPH if self.sla.is_metric else CV.MS_TO_MPH + + def teardown_method(self, method): + self.reset_state() + + def _setup_platform(self, car_name): + CarInterface = interfaces[car_name] + CP = CarInterface.get_non_essential_params(car_name) + CP_SP = CarInterface.get_non_essential_params_sp(CP, car_name) + CI = CarInterface(CP, CP_SP) + sunnypilot_interfaces.setup_interfaces(CI, self.params) + return CI + + def reset_custom_params(self): + self.params.put("SpeedLimitMode", int(Mode.assist)) + self.params.put_bool("IsMetric", False) + self.params.put("SpeedLimitOffsetType", 0) + self.params.put("SpeedLimitValueOffset", 0) + + def reset_state(self): + self.sla.state = SpeedLimitAssistState.disabled + self.sla.frame = -1 + self.sla.last_op_engaged_frame = 0 + self.sla.op_engaged = False + self.sla.op_engaged_prev = False + self.sla._speed_limit = 0. + self.sla.speed_limit_prev = 0. + self.sla.last_valid_speed_limit_offsetted = 0. + self.sla._distance = 0. + self.events_sp.clear() + + def initialize_active_state(self, initialize_v_cruise): + self.sla.state = SpeedLimitAssistState.active + self.sla.v_cruise_cluster = initialize_v_cruise + self.sla.v_cruise_cluster_prev = initialize_v_cruise + self.sla.prev_v_cruise_cluster_conv = round(initialize_v_cruise * self.speed_conv) + + def test_initial_state(self): + assert self.sla.state == SpeedLimitAssistState.disabled + assert not self.sla.is_enabled + assert not self.sla.is_active + assert V_CRUISE_UNSET == self.sla.get_v_target_from_control() + + def test_disabled(self): + self.params.put("SpeedLimitMode", int(Mode.off)) + for _ in range(int(10. / DT_MDL)): + self.sla.update(True, False, SPEED_LIMITS['city'], 0, SPEED_LIMITS['highway'], SPEED_LIMITS['city'], SPEED_LIMITS['city'], True, 0, self.events_sp) + assert self.sla.state == SpeedLimitAssistState.disabled + + def test_transition_disabled_to_preactive(self): + for _ in range(int(3. / DT_MDL)): + self.sla.update(True, False, SPEED_LIMITS['city'], 0, SPEED_LIMITS['highway'], SPEED_LIMITS['city'], SPEED_LIMITS['city'], True, 0, self.events_sp) + assert self.sla.state == SpeedLimitAssistState.preActive + assert self.sla.is_enabled and not self.sla.is_active + + def test_preactive_to_active_with_max_speed_confirmation(self): + self.sla.state = SpeedLimitAssistState.preActive + self.sla.update(True, False, SPEED_LIMITS['city'], 0, self.pcm_long_max_set_speed, SPEED_LIMITS['highway'], + SPEED_LIMITS['highway'], True, 0, self.events_sp) + assert self.sla.state == SpeedLimitAssistState.active + assert self.sla.is_enabled and self.sla.is_active + assert self.sla.output_v_target == SPEED_LIMITS['highway'] + + def test_preactive_timeout_to_inactive(self): + self.sla.state = SpeedLimitAssistState.preActive + self.sla.update(True, False, SPEED_LIMITS['city'], 0, SPEED_LIMITS['highway'], SPEED_LIMITS['city'], SPEED_LIMITS['city'], True, 0, self.events_sp) + + for _ in range(int(PRE_ACTIVE_GUARD_PERIOD / DT_MDL)): + self.sla.update(True, False, SPEED_LIMITS['city'], 0, SPEED_LIMITS['highway'], SPEED_LIMITS['city'], SPEED_LIMITS['city'], True, 0, self.events_sp) + assert self.sla.state == SpeedLimitAssistState.inactive + + def test_preactive_to_pending_no_speed_limit(self): + self.sla.state = SpeedLimitAssistState.preActive + self.sla.update(True, False, SPEED_LIMITS['highway'], 0, self.pcm_long_max_set_speed, 0, 0, False, 0, self.events_sp) + assert self.sla.state == SpeedLimitAssistState.pending + assert self.sla.is_enabled and not self.sla.is_active + + def test_pending_to_active_when_speed_limit_available(self): + self.sla.state = SpeedLimitAssistState.pending + self.sla.update(True, False, SPEED_LIMITS['city'], 0, self.pcm_long_max_set_speed, SPEED_LIMITS['city'], SPEED_LIMITS['city'], True, 0, self.events_sp) + assert self.sla.state == SpeedLimitAssistState.active + + def test_pending_to_adapting_when_below_speed_limit(self): + self.sla.state = SpeedLimitAssistState.pending + self.sla.update(True, False, SPEED_LIMITS['city'] + 5, 0, self.pcm_long_max_set_speed, SPEED_LIMITS['city'], SPEED_LIMITS['city'], True, 0, self.events_sp) + assert self.sla.state == SpeedLimitAssistState.adapting + assert self.sla.is_enabled and self.sla.is_active + + def test_active_to_adapting_transition(self): + self.initialize_active_state(self.pcm_long_max_set_speed) + + self.sla.update(True, False, SPEED_LIMITS['highway'] + 2, 0, self.pcm_long_max_set_speed, SPEED_LIMITS['highway'], + SPEED_LIMITS['highway'], True, 0, self.events_sp) + assert self.sla.state == SpeedLimitAssistState.adapting + + def test_adapting_to_active_transition(self): + self.sla.state = SpeedLimitAssistState.adapting + self.sla.v_cruise_cluster_prev = self.pcm_long_max_set_speed + self.sla.prev_v_cruise_cluster_conv = round(self.pcm_long_max_set_speed * self.speed_conv) + + self.sla.update(True, False, SPEED_LIMITS['city'], 0, self.pcm_long_max_set_speed, SPEED_LIMITS['highway'], + SPEED_LIMITS['highway'], True, 0, self.events_sp) + assert self.sla.state == SpeedLimitAssistState.active + + def test_manual_cruise_change_detection(self): + self.sla.state = SpeedLimitAssistState.active + expected_cruise = SPEED_LIMITS['highway'] + self.sla.v_cruise_cluster_prev = expected_cruise + + different_cruise = SPEED_LIMITS['highway'] + 5 + self.sla.update(True, False, SPEED_LIMITS['city'], 0, different_cruise, SPEED_LIMITS['city'], SPEED_LIMITS['city'], True, 0, self.events_sp) + assert self.sla.state == SpeedLimitAssistState.inactive + + # TODO-SP: test lower CST cases + def test_rapid_speed_limit_changes(self): + self.initialize_active_state(self.pcm_long_max_set_speed) + speed_limits = [SPEED_LIMITS['highway'], SPEED_LIMITS['freeway']] + + for _, speed_limit in enumerate(speed_limits): + self.sla.update(True, False, speed_limit, 0, self.pcm_long_max_set_speed, speed_limit, speed_limit, True, 0, self.events_sp) + assert self.sla.state in ACTIVE_STATES + + def test_invalid_speed_limits_handling(self): + self.initialize_active_state(self.pcm_long_max_set_speed) + + invalid_limits = [-10, 0, 200 * CV.MPH_TO_MS] + + for invalid_limit in invalid_limits: + self.sla.update(True, False, SPEED_LIMITS['city'], 0, self.pcm_long_max_set_speed, invalid_limit, SPEED_LIMITS['city'], True, 0, self.events_sp) + assert isinstance(self.sla.output_v_target, (int, float)) + assert self.sla.output_v_target == V_CRUISE_UNSET or self.sla.output_v_target > 0 + + def test_stale_data_handling(self): + self.initialize_active_state(self.pcm_long_max_set_speed) + old_speed_limit = SPEED_LIMITS['city'] + + self.sla.update(True, False, SPEED_LIMITS['city'], 0, self.pcm_long_max_set_speed, 0, old_speed_limit, True, 0, self.events_sp) + assert self.sla.state in ACTIVE_STATES + assert self.sla.output_v_target == old_speed_limit + + def test_distance_based_adapting(self): + self.sla.state = SpeedLimitAssistState.adapting + self.sla.v_cruise_cluster_prev = self.pcm_long_max_set_speed + self.sla.prev_v_cruise_cluster_conv = round(self.pcm_long_max_set_speed * self.speed_conv) + + distance = 100.0 + current_speed = SPEED_LIMITS['freeway'] + target_speed = SPEED_LIMITS['highway'] + + self.sla.update(True, False, current_speed, 0, self.pcm_long_max_set_speed, target_speed, target_speed, True, distance, self.events_sp) + assert self.sla.state == SpeedLimitAssistState.adapting + assert self.sla.output_v_target == target_speed # TODO-SP: assert expected accel, need to enable self.acceleration_solutions + + def test_long_disengaged_to_disabled(self): + self.initialize_active_state(self.pcm_long_max_set_speed) + + self.sla.update(False, False, SPEED_LIMITS['city'], 0, self.pcm_long_max_set_speed, SPEED_LIMITS['city'], + SPEED_LIMITS['city'], True, 0, self.events_sp) + assert self.sla.state == SpeedLimitAssistState.disabled + assert self.sla.output_v_target == V_CRUISE_UNSET + + def test_maintain_states_with_no_changes(self): + """Test that states are maintained when no significant changes occur""" + test_states = [ + SpeedLimitAssistState.preActive, + SpeedLimitAssistState.pending, + SpeedLimitAssistState.active, + SpeedLimitAssistState.adapting + ] + + for state in test_states: + self.sla.state = state + self.sla.op_engaged = True + + initial_state = state + + self.sla.update(True, False, SPEED_LIMITS['city'], 0, self.pcm_long_max_set_speed, SPEED_LIMITS['city'], SPEED_LIMITS['city'], True, 0, self.events_sp) + + assert self.sla.state in ALL_STATES # Sanity check + + if initial_state == SpeedLimitAssistState.preActive: + assert self.sla.state in [SpeedLimitAssistState.preActive, SpeedLimitAssistState.active] + elif initial_state in ACTIVE_STATES: + assert self.sla.state in ACTIVE_STATES diff --git a/sunnypilot/selfdrive/selfdrived/events.py b/sunnypilot/selfdrive/selfdrived/events.py index 7c723397fb..7700550c2d 100644 --- a/sunnypilot/selfdrive/selfdrived/events.py +++ b/sunnypilot/selfdrive/selfdrived/events.py @@ -1,6 +1,10 @@ +import cereal.messaging as messaging from cereal import log, car, custom +from openpilot.common.constants import CV from openpilot.sunnypilot.selfdrive.selfdrived.events_base import EventsBase, Priority, ET, Alert, \ NoEntryAlert, ImmediateDisableAlert, EngagementAlert, NormalPermanentAlert, AlertCallbackType, wrong_car_mode_alert +from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit import PCM_LONG_REQUIRED_MAX_SET_SPEED, CONFIRM_SPEED_THRESHOLD +from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.helpers import compare_cluster_target AlertSize = log.SelfdriveState.AlertSize @@ -14,6 +18,49 @@ EventNameSP = custom.OnroadEventSP.EventName EVENT_NAME_SP = {v: k for k, v in EventNameSP.schema.enumerants.items()} +def speed_limit_adjust_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + speedLimit = sm['longitudinalPlanSP'].speedLimit.resolver.speedLimit + speed = round(speedLimit * (CV.MS_TO_KPH if metric else CV.MS_TO_MPH)) + message = f'Adjusting to {speed} {"km/h" if metric else "mph"} speed limit' + return Alert( + message, + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, 4.) + + +def speed_limit_pre_active_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + speed_conv = CV.MS_TO_KPH if metric else CV.MS_TO_MPH + speed_limit_final_last = sm['longitudinalPlanSP'].speedLimit.resolver.speedLimitFinalLast + speed_limit_final_last_conv = round(speed_limit_final_last * speed_conv) + + if CP.openpilotLongitudinalControl and CP.pcmCruise: + # PCM long + cst_low, cst_high = PCM_LONG_REQUIRED_MAX_SET_SPEED[metric] + pcm_long_required_max = cst_low if speed_limit_final_last_conv < CONFIRM_SPEED_THRESHOLD[metric] else cst_high + pcm_long_required_max_set_speed_conv = round(pcm_long_required_max * speed_conv) + speed_unit = "km/h" if metric else "mph" + alert_2_str = f"Manually change set speed to {pcm_long_required_max_set_speed_conv} {speed_unit} to activate" + else: + # Non PCM long + v_cruise_cluster = CS.vCruiseCluster * CV.KPH_TO_MS + + req_plus, req_minus = compare_cluster_target(v_cruise_cluster, speed_limit_final_last, metric) + arrow_str = "" + if req_plus: + arrow_str = "RES/+" + elif req_minus: + arrow_str = "SET/-" + + alert_2_str = f"Operate the {arrow_str} cruise control button to activate" + + return Alert( + "Speed Limit Assist: Activation Required", + alert_2_str, + AlertStatus.normal, AlertSize.mid, + Priority.LOW, VisualAlert.none, AudibleAlert.none, .1) + + class EventsSP(EventsBase): def __init__(self): super().__init__() @@ -148,5 +195,33 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = { "", AlertStatus.normal, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlert.none, 1.), - } + }, + + EventNameSP.speedLimitActive: { + ET.WARNING: Alert( + "Automatically adjusting to the posted speed limit", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, 5.), + }, + + EventNameSP.speedLimitChanged: { + ET.WARNING: Alert( + "Set speed changed", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, 5.), + }, + + EventNameSP.speedLimitPreActive: { + ET.WARNING: speed_limit_pre_active_alert, + }, + + EventNameSP.speedLimitPending: { + ET.WARNING: Alert( + "Automatically adjusting to the last speed limit", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, 5.), + }, } From 0f4828df824416fa0ff5bb6a3a7a21155e72838c Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Tue, 30 Sep 2025 13:39:11 -0400 Subject: [PATCH 115/159] ui: only longitudinal cars can use Speed Limit Assist (#1300) --- .../speed_limit/speed_limit_settings.cc | 26 +++++++++++++++++++ .../speed_limit/speed_limit_settings.h | 17 ++++++++++++ 2 files changed, 43 insertions(+) diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc index 5f12403a17..ff5d6221ce 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.cc @@ -108,6 +108,25 @@ void SpeedLimitSettings::refresh() { SpeedLimitOffsetType offset_type_param = static_cast(std::atoi(params.get("SpeedLimitOffsetType").c_str())); QString offsetLabel = QString::fromStdString(params.get("SpeedLimitValueOffset")); + bool has_longitudinal_control; + bool intelligent_cruise_button_management_available; + auto cp_bytes = params.get("CarParamsPersistent"); + auto cp_sp_bytes = params.get("CarParamsSPPersistent"); + if (!cp_bytes.empty() && !cp_sp_bytes.empty()) { + AlignedBuffer aligned_buf; + AlignedBuffer aligned_buf_sp; + capnp::FlatArrayMessageReader cmsg(aligned_buf.align(cp_bytes.data(), cp_bytes.size())); + capnp::FlatArrayMessageReader cmsg_sp(aligned_buf_sp.align(cp_sp_bytes.data(), cp_sp_bytes.size())); + cereal::CarParams::Reader CP = cmsg.getRoot(); + cereal::CarParamsSP::Reader CP_SP = cmsg_sp.getRoot(); + + has_longitudinal_control = hasLongitudinalControl(CP); + intelligent_cruise_button_management_available = CP_SP.getIntelligentCruiseButtonManagementAvailable(); + } else { + has_longitudinal_control = false; + intelligent_cruise_button_management_available = false; + } + speed_limit_mode_settings->setDescription(modeDescription(speed_limit_mode_param)); speed_limit_offset->setDescription(offsetDescription(offset_type_param)); @@ -125,6 +144,13 @@ void SpeedLimitSettings::refresh() { speed_limit_offset->showDescription(); } + if (has_longitudinal_control || intelligent_cruise_button_management_available) { + speed_limit_mode_settings->setEnableSelectedButtons(true, convertSpeedLimitModeValues(getSpeedLimitModeValues())); + } else { + speed_limit_mode_settings->setEnableSelectedButtons(true, convertSpeedLimitModeValues( + {SpeedLimitMode::OFF,SpeedLimitMode::INFORMATION, SpeedLimitMode::WARNING})); + } + speed_limit_mode_settings->showDescription(); speed_limit_offset->showDescription(); } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h index 10c44aa98c..f76f9bea2a 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/longitudinal/speed_limit/speed_limit_settings.h @@ -76,4 +76,21 @@ private: .arg(warning_str) .arg(assist_str); } + + static std::vector getSpeedLimitModeValues() { + std::vector values; + for (int i = static_cast(SpeedLimitMode::OFF); + i <= static_cast(SpeedLimitMode::ASSIST); ++i) { + values.push_back(static_cast(i)); + } + return values; + } + + static std::vector convertSpeedLimitModeValues(const std::vector &modes) { + std::vector values; + for (const auto& mode : modes) { + values.push_back(static_cast(mode)); + } + return values; + } }; From 85d2653fdac1145a31173131844509012d700bfd Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Tue, 30 Sep 2025 17:50:35 -0400 Subject: [PATCH 116/159] Speed Limit Assist: No Easter Eggs --- .../controls/lib/speed_limit/speed_limit_assist.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_assist.py b/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_assist.py index bb03a9eb1c..5d798949a9 100644 --- a/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_assist.py +++ b/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_assist.py @@ -54,7 +54,6 @@ class SpeedLimitAssist: self.frame = -1 self.long_engaged_timer = 0 self.pre_active_timer = 0 - self.speed_limit_changed_timer = 0 self.is_metric = self.params.get_bool("IsMetric") self.enabled = self.params.get("SpeedLimitMode", return_default=True) == Mode.assist self.long_enabled = False @@ -288,7 +287,6 @@ class SpeedLimitAssist: def update_state_machine_non_pcm_long(self): self.long_engaged_timer = max(0, self.long_engaged_timer - 1) self.pre_active_timer = max(0, self.pre_active_timer - 1) - self.speed_limit_changed_timer = max(0, self.speed_limit_changed_timer - 1) # ACTIVE, ADAPTING, PENDING, PRE_ACTIVE, INACTIVE if self.state != SpeedLimitAssistState.disabled: @@ -302,8 +300,6 @@ class SpeedLimitAssist: self.state = SpeedLimitAssistState.inactive elif self.speed_limit_changed and self.apply_confirm_speed_threshold: - self.speed_limit_changed_timer = int(SPEED_LIMIT_CHANGED_HOLD_PERIOD / DT_MDL) - elif self.speed_limit_changed_timer <= 0: self.state = SpeedLimitAssistState.preActive self.pre_active_timer = int(PRE_ACTIVE_GUARD_PERIOD / DT_MDL) @@ -318,8 +314,6 @@ class SpeedLimitAssist: # INACTIVE elif self.state == SpeedLimitAssistState.inactive: if self.speed_limit_changed: - self.speed_limit_changed_timer = int(SPEED_LIMIT_CHANGED_HOLD_PERIOD / DT_MDL) - elif self.speed_limit_changed_timer <= 0: self.state = SpeedLimitAssistState.preActive self.pre_active_timer = int(PRE_ACTIVE_GUARD_PERIOD / DT_MDL) elif self._update_non_pcm_long_confirmed_state(): From ae901d15624b0b5849e8b09a3a67180a5b611b5b Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Tue, 30 Sep 2025 20:17:53 -0400 Subject: [PATCH 117/159] ui: add Display settings panel (#1301) * init * onroad brightness control * new icon * update touch handlling * don't touch me * now i feel every touch * resolve review comments * tired of this shit * ugh * just panel for now * more --------- Co-authored-by: nayan --- selfdrive/ui/sunnypilot/SConscript | 1 + .../qt/offroad/settings/display_panel.cc | 29 +++++++++++++++++++ .../qt/offroad/settings/display_panel.h | 26 +++++++++++++++++ .../qt/offroad/settings/settings.cc | 2 ++ .../selfdrive/assets/offroad/icon_display.png | 3 ++ 5 files changed, 61 insertions(+) create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h create mode 100644 sunnypilot/selfdrive/assets/offroad/icon_display.png diff --git a/selfdrive/ui/sunnypilot/SConscript b/selfdrive/ui/sunnypilot/SConscript index 5c2680b299..a3c03ee03f 100644 --- a/selfdrive/ui/sunnypilot/SConscript +++ b/selfdrive/ui/sunnypilot/SConscript @@ -24,6 +24,7 @@ qt_src = [ "sunnypilot/qt/offroad/offroad_home.cc", "sunnypilot/qt/offroad/settings/developer_panel.cc", "sunnypilot/qt/offroad/settings/device_panel.cc", + "sunnypilot/qt/offroad/settings/display_panel.cc", "sunnypilot/qt/offroad/settings/lateral_panel.cc", "sunnypilot/qt/offroad/settings/longitudinal_panel.cc", "sunnypilot/qt/offroad/settings/max_time_offroad.cc", diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc new file mode 100644 index 0000000000..e980840a8c --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h" + +DisplayPanel::DisplayPanel(QWidget *parent) : QWidget(parent) { + main_layout = new QStackedLayout(this); + ListWidgetSP *list = new ListWidgetSP(this, false); + + sunnypilotScreen = new QWidget(this); + QVBoxLayout* vlayout = new QVBoxLayout(sunnypilotScreen); + vlayout->setContentsMargins(50, 20, 50, 20); + + sunnypilotScroller = new ScrollViewSP(list, this); + vlayout->addWidget(sunnypilotScroller); + main_layout->addWidget(sunnypilotScreen); +} + +void DisplayPanel::showEvent(QShowEvent *event) { + QWidget::showEvent(event); + refresh(); +} + +void DisplayPanel::refresh() { +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h new file mode 100644 index 0000000000..22e7303465 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" + +class DisplayPanel : public QWidget { + Q_OBJECT + +public: + explicit DisplayPanel(QWidget *parent = nullptr); + void showEvent(QShowEvent *event) override; + void refresh(); + +private: + QStackedLayout* main_layout = nullptr; + QWidget* sunnypilotScreen = nullptr; + ScrollViewSP *sunnypilotScroller = nullptr; + Params params; +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/settings.cc index 5415e75ea9..c712442df3 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/settings.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/settings.cc @@ -13,6 +13,7 @@ #include "selfdrive/ui/sunnypilot/qt/offroad/settings/developer_panel.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/models_panel.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/software_panel.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/sunnylink_panel.h" @@ -87,6 +88,7 @@ SettingsWindowSP::SettingsWindowSP(QWidget *parent) : SettingsWindow(parent) { PanelInfo(" " + tr("Steering"), new LateralPanel(this), "../../sunnypilot/selfdrive/assets/offroad/icon_lateral.png"), PanelInfo(" " + tr("Cruise"), new LongitudinalPanel(this), "../assets/icons/speed_limit.png"), PanelInfo(" " + tr("Visuals"), new VisualsPanel(this), "../../sunnypilot/selfdrive/assets/offroad/icon_visuals.png"), + PanelInfo(" " + tr("Display"), new DisplayPanel(this), "../../sunnypilot/selfdrive/assets/offroad/icon_display.png"), PanelInfo(" " + tr("OSM"), new OsmPanel(this), "../../sunnypilot/selfdrive/assets/offroad/icon_map.png"), PanelInfo(" " + tr("Trips"), new TripsPanel(this), "../../sunnypilot/selfdrive/assets/offroad/icon_trips.png"), PanelInfo(" " + tr("Vehicle"), new VehiclePanel(this), "../../sunnypilot/selfdrive/assets/offroad/icon_vehicle.png"), diff --git a/sunnypilot/selfdrive/assets/offroad/icon_display.png b/sunnypilot/selfdrive/assets/offroad/icon_display.png new file mode 100644 index 0000000000..547977f522 --- /dev/null +++ b/sunnypilot/selfdrive/assets/offroad/icon_display.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:614767308d435d165a9ab78e3eac22ee15697d94066df8200ef32afb33ef8d60 +size 5698 From 49e58a253220cc32d503ba06824201e6990456ef Mon Sep 17 00:00:00 2001 From: Nayan Date: Tue, 30 Sep 2025 21:06:11 -0400 Subject: [PATCH 118/159] Device: Driving Screen Off (#1252) * init * onroad brightness control * new icon * update touch handlling * don't touch me * now i feel every touch * resolve review comments * tired of this shit * ugh * translate * duplicate * fix * adjust * update param in the same function * flip * format * reorder --------- Co-authored-by: Jason Wen --- common/params_keys.h | 3 + selfdrive/ui/sunnypilot/SConscript | 6 +- .../display/onroad_screen_brightness.cc | 63 +++++++++++++++++++ .../display/onroad_screen_brightness.h | 42 +++++++++++++ .../qt/offroad/settings/display_panel.cc | 11 ++++ .../qt/offroad/settings/display_panel.h | 2 + .../ui/sunnypilot/qt/onroad/onroad_home.cc | 2 + selfdrive/ui/sunnypilot/ui.cc | 24 +++++++ selfdrive/ui/sunnypilot/ui.h | 1 + selfdrive/ui/sunnypilot/ui_scene.h | 3 + selfdrive/ui/ui.cc | 7 +++ 11 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.cc create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.h diff --git a/common/params_keys.h b/common/params_keys.h index 5ba6b53108..1056a3903e 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -157,6 +157,9 @@ inline static std::unordered_map keys = { {"ModelRunnerTypeCache", {CLEAR_ON_ONROAD_TRANSITION, INT}}, {"OffroadMode", {CLEAR_ON_MANAGER_START, BOOL}}, {"Offroad_TiciSupport", {CLEAR_ON_MANAGER_START, JSON}}, + {"OnroadScreenOffBrightness", {PERSISTENT | BACKUP, INT, "100"}}, + {"OnroadScreenOffControl", {PERSISTENT | BACKUP, BOOL}}, + {"OnroadScreenOffTimer", {PERSISTENT | BACKUP, INT, "0"}}, {"QuickBootToggle", {PERSISTENT | BACKUP, BOOL, "0"}}, {"QuietMode", {PERSISTENT | BACKUP, BOOL, "0"}}, {"RainbowMode", {PERSISTENT | BACKUP, BOOL, "0"}}, diff --git a/selfdrive/ui/sunnypilot/SConscript b/selfdrive/ui/sunnypilot/SConscript index a3c03ee03f..3f0e013d34 100644 --- a/selfdrive/ui/sunnypilot/SConscript +++ b/selfdrive/ui/sunnypilot/SConscript @@ -91,9 +91,13 @@ brand_settings_qt_src = [ "sunnypilot/qt/offroad/settings/vehicle/volkswagen_settings.cc", ] +display_panel_qt_src = [ + "sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.cc", +] sp_widgets_src = widgets_src + network_src -sp_qt_src = qt_src + lateral_panel_qt_src + vehicle_panel_qt_src + brand_settings_qt_src + longitudinal_panel_qt_src + osm_panel_qt_src +sp_qt_src = qt_src + lateral_panel_qt_src + vehicle_panel_qt_src + brand_settings_qt_src + \ + longitudinal_panel_qt_src + osm_panel_qt_src + display_panel_qt_src sp_qt_util = qt_util Export('sp_widgets_src', 'sp_qt_src', "sp_qt_util") diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.cc new file mode 100644 index 0000000000..3e9dc427bf --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.cc @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.h" + +OnroadScreenBrightnessControl::OnroadScreenBrightnessControl(const QString ¶m, const QString &title, + const QString &description, const QString &icon, + QWidget *parent) + : ExpandableToggleRow(param, title, description, icon, parent) { + auto *mainFrame = new QFrame(this); + auto *mainFrameLayout = new QGridLayout(); + mainFrame->setLayout(mainFrameLayout); + mainFrameLayout->setSpacing(0); + + onroadScreenOffTimer = new OptionControlSP( + "OnroadScreenOffTimer", + "", + "", + "", + {0, 11}, 1, true, &onroadScreenOffTimerOptions); + + onroadScreenBrightness = new OptionControlSP( + "OnroadScreenOffBrightness", + "", + "", + "", + {0, 100}, 10, true, nullptr, false); + + connect(onroadScreenOffTimer, &OptionControlSP::updateLabels, this, &OnroadScreenBrightnessControl::refresh); + connect(onroadScreenBrightness, &OptionControlSP::updateLabels, this, &OnroadScreenBrightnessControl::refresh); + onroadScreenOffTimer->setFixedWidth(280); + onroadScreenBrightness->setFixedWidth(280); + mainFrameLayout->addWidget(onroadScreenOffTimer, 0, 0, Qt::AlignLeft); + mainFrameLayout->addWidget(onroadScreenBrightness, 0, 1, Qt::AlignRight); + + addItem(mainFrame); + + refresh(); +} + +void OnroadScreenBrightnessControl::refresh() { + // Driving Screen Off Timer + int valTimer = std::atoi(params.get("OnroadScreenOffTimer").c_str()); + std::string labelTimer = ""; + labelTimer += "Delay"; + labelTimer += "
"; + labelTimer += (valTimer < 60 ? std::to_string(valTimer) + "s" : std::to_string(valTimer / 60) + "m"); + labelTimer += "
"; + onroadScreenOffTimer->setLabel(QString::fromStdString(labelTimer)); + + // Driving Screen Off Brightness + std::string valBrightness = params.get("OnroadScreenOffBrightness"); + std::string labelBrightness = ""; + labelBrightness += "Brightness"; + labelBrightness += "
"; + labelBrightness += (valBrightness == "0" ? " Screen Off" : valBrightness + "%"); + labelBrightness += "
"; + onroadScreenBrightness->setLabel(QString::fromStdString(labelBrightness)); +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.h new file mode 100644 index 0000000000..02335d1ce6 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.h @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/ui.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/expandable_row.h" + +static const QMap onroadScreenOffTimerOptions = { + {"0", "15"}, + {"1", "30"}, + {"2", "60"}, + {"3", "120"}, + {"4", "180"}, + {"5", "240"}, + {"6", "300"}, + {"7", "360"}, + {"8", "420"}, + {"9", "480"}, + {"10", "540"}, + {"11", "600"} +}; + +class OnroadScreenBrightnessControl : public ExpandableToggleRow { + Q_OBJECT + +public: + OnroadScreenBrightnessControl(const QString ¶m, const QString &title, const QString &desc, const QString &icon, + QWidget *parent = nullptr); + void refresh(); + +private: + Params params; + OptionControlSP *onroadScreenOffTimer; + OptionControlSP *onroadScreenBrightness; +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc index e980840a8c..b441021ff3 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc @@ -15,6 +15,16 @@ DisplayPanel::DisplayPanel(QWidget *parent) : QWidget(parent) { QVBoxLayout* vlayout = new QVBoxLayout(sunnypilotScreen); vlayout->setContentsMargins(50, 20, 50, 20); + // Onroad Screen Off/Brightness + onroadScreenBrightnessControl = new OnroadScreenBrightnessControl( + "OnroadScreenOffControl", + tr("Driving Screen Off: Non-Critical Events"), + tr("Turn off device screen or reduce brightness after driving starts. " + "It automatically brightens again when screen is touched or a critical event occurs."), + "", + this); + list->addItem(onroadScreenBrightnessControl); + sunnypilotScroller = new ScrollViewSP(list, this); vlayout->addWidget(sunnypilotScroller); main_layout->addWidget(sunnypilotScreen); @@ -26,4 +36,5 @@ void DisplayPanel::showEvent(QShowEvent *event) { } void DisplayPanel::refresh() { + onroadScreenBrightnessControl->refresh(); } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h index 22e7303465..1714c8a436 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h @@ -7,6 +7,7 @@ #pragma once +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" #include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" @@ -23,4 +24,5 @@ private: QWidget* sunnypilotScreen = nullptr; ScrollViewSP *sunnypilotScroller = nullptr; Params params; + OnroadScreenBrightnessControl *onroadScreenBrightnessControl = nullptr; }; diff --git a/selfdrive/ui/sunnypilot/qt/onroad/onroad_home.cc b/selfdrive/ui/sunnypilot/qt/onroad/onroad_home.cc index b26d1b828a..3f853e3363 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/onroad_home.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/onroad_home.cc @@ -25,8 +25,10 @@ void OnroadWindowSP::updateState(const UIStateSP &s) { void OnroadWindowSP::mousePressEvent(QMouseEvent *e) { OnroadWindow::mousePressEvent(e); + uiStateSP()->reset_onroad_sleep_timer(); } void OnroadWindowSP::offroadTransition(bool offroad) { OnroadWindow::offroadTransition(offroad); + uiStateSP()->reset_onroad_sleep_timer(); } diff --git a/selfdrive/ui/sunnypilot/ui.cc b/selfdrive/ui/sunnypilot/ui.cc index fd7365821c..6cbdeadf58 100644 --- a/selfdrive/ui/sunnypilot/ui.cc +++ b/selfdrive/ui/sunnypilot/ui.cc @@ -11,6 +11,16 @@ void UIStateSP::updateStatus() { UIState::updateStatus(); + + if (scene.started && scene.onroadScreenOffControl) { + auto selfdriveState = (*sm)["selfdriveState"].getSelfdriveState(); + if (selfdriveState.getAlertSize() != cereal::SelfdriveState::AlertSize::NONE && + selfdriveState.getAlertStatus() != cereal::SelfdriveState::AlertStatus::NORMAL) { + reset_onroad_sleep_timer(); + } else if (scene.onroadScreenOffTimer > 0) { + scene.onroadScreenOffTimer--; + } + } } UIStateSP::UIStateSP(QObject *parent) : UIState(parent) { @@ -55,6 +65,20 @@ void ui_update_params_sp(UIStateSP *s) { s->scene.standstill_timer = params.getBool("StandstillTimer"); s->scene.speed_limit_mode = std::atoi(params.get("SpeedLimitMode").c_str()); s->scene.road_name = params.getBool("RoadNameToggle"); + + // Onroad Screen Brightness + s->scene.onroadScreenOffBrightness = std::atoi(params.get("OnroadScreenOffBrightness").c_str()); + s->scene.onroadScreenOffControl = params.getBool("OnroadScreenOffControl"); + s->scene.onroadScreenOffTimerParam = std::atoi(params.get("OnroadScreenOffTimer").c_str()); + s->reset_onroad_sleep_timer(); +} + +void UIStateSP::reset_onroad_sleep_timer() { + if (scene.onroadScreenOffTimerParam >= 0 and scene.onroadScreenOffControl) { + scene.onroadScreenOffTimer = scene.onroadScreenOffTimerParam * UI_FREQ; + } else { + scene.onroadScreenOffTimer = -1; + } } DeviceSP::DeviceSP(QObject *parent) : Device(parent) { diff --git a/selfdrive/ui/sunnypilot/ui.h b/selfdrive/ui/sunnypilot/ui.h index 393f997cbd..55dd43ad52 100644 --- a/selfdrive/ui/sunnypilot/ui.h +++ b/selfdrive/ui/sunnypilot/ui.h @@ -61,6 +61,7 @@ public: return user.user_id.toLower() != "unregisteredsponsor" && user.user_id.toLower() != "temporarysponsor"; }); } + void reset_onroad_sleep_timer(); signals: void sunnylinkRoleChanged(bool subscriber); diff --git a/selfdrive/ui/sunnypilot/ui_scene.h b/selfdrive/ui/sunnypilot/ui_scene.h index 768cc5d7a1..7cfabb15c3 100644 --- a/selfdrive/ui/sunnypilot/ui_scene.h +++ b/selfdrive/ui/sunnypilot/ui_scene.h @@ -12,4 +12,7 @@ typedef struct UISceneSP : UIScene { bool standstill_timer = false; int speed_limit_mode = 0; bool road_name = false; + int onroadScreenOffBrightness, onroadScreenOffTimer = 0; + bool onroadScreenOffControl; + int onroadScreenOffTimerParam; } UISceneSP; diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 4cad883f7d..6bca2b7f7f 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -204,6 +204,13 @@ void Device::updateBrightness(const UIState &s) { brightness = 0; } + // Onroad Brightness Control +#ifdef SUNNYPILOT + if (awake && s.scene.started && s.scene.onroadScreenOffControl && s.scene.onroadScreenOffTimer == 0) { + brightness = s.scene.onroadScreenOffBrightness * 0.01 * brightness; + } +#endif + if (brightness != last_brightness) { if (!brightness_future.isRunning()) { brightness_future = QtConcurrent::run(Hardware::set_brightness, brightness); From f3ed57787050c330ca74c566dad2d7812753e7ba Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Tue, 30 Sep 2025 22:37:13 -0400 Subject: [PATCH 119/159] Longitudinal: reimplement Gas Interceptor (comma Pedal) support (#1290) * init * bump * bump * bump * recheck openpilot long availability * bump * bump * bump * bump * bump * just base for now * bump * bump * bump * bump * flipped * apparently it's yucky, reverting most * bump * need to add for toyota * should've been remove * flipped * bump * no way * fix * test sdsu distance * final tuning for pedal * bump --- cereal/custom.capnp | 1 + opendbc_repo | 2 +- selfdrive/car/tests/test_car_interfaces.py | 2 +- selfdrive/controls/controlsd.py | 2 +- selfdrive/controls/lib/longcontrol.py | 10 +++++--- selfdrive/controls/tests/test_longcontrol.py | 27 +++++++++++--------- selfdrive/selfdrived/selfdrived.py | 2 +- sunnypilot/selfdrive/car/car_specific.py | 10 ++++++-- 8 files changed, 35 insertions(+), 21 deletions(-) diff --git a/cereal/custom.capnp b/cereal/custom.capnp index c87ac0d2e0..674f109fc7 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -299,6 +299,7 @@ struct CarParamsSP @0x80ae746ee2596b11 { safetyParam @1 : Int16; # flags for sunnypilot's custom safety flags pcmCruiseSpeed @3 :Bool; intelligentCruiseButtonManagementAvailable @4 :Bool; + enableGasInterceptor @5 :Bool; neuralNetworkLateralControl @2 :NeuralNetworkLateralControl; diff --git a/opendbc_repo b/opendbc_repo index 52d50f9841..dfcfacb667 160000 --- a/opendbc_repo +++ b/opendbc_repo @@ -1 +1 @@ -Subproject commit 52d50f984191d63cf6a79398b21df2d2e3b9236e +Subproject commit dfcfacb667c6ff131d0e620c36e118f14a84dc4a diff --git a/selfdrive/car/tests/test_car_interfaces.py b/selfdrive/car/tests/test_car_interfaces.py index 7c7a563003..821767ee46 100644 --- a/selfdrive/car/tests/test_car_interfaces.py +++ b/selfdrive/car/tests/test_car_interfaces.py @@ -60,7 +60,7 @@ class TestCarInterfaces: # Test controller initialization # TODO: wait until card refactor is merged to run controller a few times, # hypothesis also slows down significantly with just one more message draw - LongControl(car_params) + LongControl(car_params, car_params_sp) if car_params.steerControlType == CarParams.SteerControlType.angle: LatControlAngle(car_params, car_params_sp, car_interface) elif car_params.lateralTuning.which() == 'pid': diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 3751efc87a..3601ae310e 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -58,7 +58,7 @@ class Controls(ControlsExt, ModelStateBase): self.pose_calibrator = PoseCalibrator() self.calibrated_pose: Pose | None = None - self.LoC = LongControl(self.CP) + self.LoC = LongControl(self.CP, self.CP_SP) self.VM = VehicleModel(self.CP) self.LaC: LatControl if self.CP.steerControlType == car.CarParams.SteerControlType.angle: diff --git a/selfdrive/controls/lib/longcontrol.py b/selfdrive/controls/lib/longcontrol.py index 6d4f922461..b8b00e2fb9 100644 --- a/selfdrive/controls/lib/longcontrol.py +++ b/selfdrive/controls/lib/longcontrol.py @@ -10,8 +10,11 @@ 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, +def long_control_state_trans(CP, CP_SP, active, long_control_state, v_ego, should_stop, brake_pressed, cruise_standstill): + # Gas Interceptor + cruise_standstill = cruise_standstill and not CP_SP.enableGasInterceptor + stopping_condition = should_stop starting_condition = (not should_stop and not cruise_standstill and @@ -45,8 +48,9 @@ def long_control_state_trans(CP, active, long_control_state, v_ego, return long_control_state class LongControl: - def __init__(self, CP): + def __init__(self, CP, CP_SP): self.CP = CP + self.CP_SP = CP_SP self.long_control_state = LongCtrlState.off self.pid = PIDController((CP.longitudinalTuning.kpBP, CP.longitudinalTuning.kpV), (CP.longitudinalTuning.kiBP, CP.longitudinalTuning.kiV), @@ -61,7 +65,7 @@ class LongControl: self.pid.neg_limit = accel_limits[0] self.pid.pos_limit = accel_limits[1] - self.long_control_state = long_control_state_trans(self.CP, active, self.long_control_state, CS.vEgo, + self.long_control_state = long_control_state_trans(self.CP, self.CP_SP, active, self.long_control_state, CS.vEgo, should_stop, CS.brakePressed, CS.cruiseState.standstill) if self.long_control_state == LongCtrlState.off: diff --git a/selfdrive/controls/tests/test_longcontrol.py b/selfdrive/controls/tests/test_longcontrol.py index ab50810d89..cf0ab24e0b 100644 --- a/selfdrive/controls/tests/test_longcontrol.py +++ b/selfdrive/controls/tests/test_longcontrol.py @@ -1,4 +1,4 @@ -from cereal import car +from cereal import car, custom from openpilot.selfdrive.controls.lib.longcontrol import LongCtrlState, long_control_state_trans @@ -8,49 +8,52 @@ class TestLongControlStateTransition: def test_stay_stopped(self): CP = car.CarParams.new_message() + CP_SP = custom.CarParamsSP.new_message() active = True current_state = LongCtrlState.stopping - next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1, should_stop=True, brake_pressed=False, cruise_standstill=False) assert next_state == LongCtrlState.stopping - next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1, should_stop=False, brake_pressed=True, cruise_standstill=False) assert next_state == LongCtrlState.stopping - next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1, should_stop=False, brake_pressed=False, cruise_standstill=True) assert next_state == LongCtrlState.stopping - next_state = long_control_state_trans(CP, active, current_state, v_ego=1.0, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=1.0, should_stop=False, brake_pressed=False, cruise_standstill=False) assert next_state == LongCtrlState.pid active = False - next_state = long_control_state_trans(CP, active, current_state, v_ego=1.0, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=1.0, should_stop=False, brake_pressed=False, cruise_standstill=False) assert next_state == LongCtrlState.off def test_engage(): CP = car.CarParams.new_message() + CP_SP = custom.CarParamsSP.new_message() active = True current_state = LongCtrlState.off - next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1, should_stop=True, brake_pressed=False, cruise_standstill=False) assert next_state == LongCtrlState.stopping - next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1, should_stop=False, brake_pressed=True, cruise_standstill=False) assert next_state == LongCtrlState.stopping - next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1, should_stop=False, brake_pressed=False, cruise_standstill=True) assert next_state == LongCtrlState.stopping - next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1, should_stop=False, brake_pressed=False, cruise_standstill=False) assert next_state == LongCtrlState.pid def test_starting(): CP = car.CarParams.new_message(startingState=True, vEgoStarting=0.5) + CP_SP = custom.CarParamsSP.new_message() active = True current_state = LongCtrlState.starting - next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=0.1, should_stop=False, brake_pressed=False, cruise_standstill=False) assert next_state == LongCtrlState.starting - next_state = long_control_state_trans(CP, active, current_state, v_ego=1.0, + next_state = long_control_state_trans(CP, CP_SP, active, current_state, v_ego=1.0, should_stop=False, brake_pressed=False, cruise_standstill=False) assert next_state == LongCtrlState.pid diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index a13c873fbe..4bc75021f7 100755 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -159,7 +159,7 @@ class SelfdriveD(CruiseHelper): self.mads = ModularAssistiveDrivingSystem(self) self.icbm = IntelligentCruiseButtonManagement(self.CP, self.CP_SP) - self.car_events_sp = CarSpecificEventsSP(self.CP, self.params) + self.car_events_sp = CarSpecificEventsSP(self.CP, self.CP_SP) CruiseHelper.__init__(self, self.CP) diff --git a/sunnypilot/selfdrive/car/car_specific.py b/sunnypilot/selfdrive/car/car_specific.py index 7e6f300d73..97ce26429c 100644 --- a/sunnypilot/selfdrive/car/car_specific.py +++ b/sunnypilot/selfdrive/car/car_specific.py @@ -18,9 +18,9 @@ GearShifter = structs.CarState.GearShifter class CarSpecificEventsSP: - def __init__(self, CP: structs.CarParams, params): + def __init__(self, CP: structs.CarParams, CP_SP: structs.CarParamsSP): self.CP = CP - self.params = params + self.CP_SP = CP_SP self.low_speed_alert = False @@ -42,4 +42,10 @@ class CarSpecificEventsSP: if self.low_speed_alert: events.add(EventName.belowSteerSpeed) + elif self.CP.brand == 'toyota': + if self.CP.openpilotLongitudinalControl: + if CS.cruiseState.standstill and not CS.brakePressed and self.CP_SP.enableGasInterceptor: + if events.has(EventName.resumeRequired): + events.remove(EventName.resumeRequired) + return events_sp From 92214b69d8e9045ea28e82c47debd1813a4af390 Mon Sep 17 00:00:00 2001 From: Nayan Date: Wed, 1 Oct 2025 12:37:10 -0400 Subject: [PATCH 120/159] feat: Green Traffic Light Alert (#1287) * init * fix * event * UI * events..for real * SP * ugh * toggles * read params first * stoopid it is * fix green light img * fix green light image. for real this time * move events to longitudinal_planner * move events to longitudinal_planner * move e2e alerts to separate class * green light alert only for this PR * fix * fixxxxxxx * blinky blink * blinky blink * slight cleanup * only used for params * a bit more * only when long is not engaged * too long * update description * always 3 seconds if not moving * initialize in constructor instead * less * rename * always init at 0 --------- Co-authored-by: Kumar <36933347+rav4kumar@users.noreply.github.com> Co-authored-by: Jason Wen --- cereal/custom.capnp | 6 ++ common/params_keys.h | 1 + .../qt/offroad/settings/visuals_panel.cc | 10 ++++ selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 55 +++++++++++++++++++ selfdrive/ui/sunnypilot/qt/onroad/hud.h | 8 +++ .../selfdrive/assets/images/green_light.png | 3 + .../controls/lib/e2e_alerts_helper.py | 50 +++++++++++++++++ .../controls/lib/longitudinal_planner.py | 10 +++- sunnypilot/selfdrive/selfdrived/events.py | 8 +++ 9 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 sunnypilot/selfdrive/assets/images/green_light.png create mode 100644 sunnypilot/selfdrive/controls/lib/e2e_alerts_helper.py diff --git a/cereal/custom.capnp b/cereal/custom.capnp index 674f109fc7..23e26a8ccb 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -149,6 +149,7 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { vTarget @4 :Float32; aTarget @5 :Float32; events @6 :List(OnroadEventSP.Event); + e2eAlerts @7 :E2eAlerts; struct DynamicExperimentalControl { state @0 :DynamicExperimentalControlState; @@ -246,6 +247,10 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { sccMap @2; speedLimitAssist @3; } + + struct E2eAlerts { + greenLightAlert @0 :Bool; + } } struct OnroadEventSP @0xda96579883444c35 { @@ -291,6 +296,7 @@ struct OnroadEventSP @0xda96579883444c35 { speedLimitActive @20; speedLimitChanged @21; speedLimitPending @22; + e2eChime @23; } } diff --git a/common/params_keys.h b/common/params_keys.h index 1056a3903e..b8cda83693 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -148,6 +148,7 @@ inline static std::unordered_map keys = { {"DevUIInfo", {PERSISTENT | BACKUP, INT, "0"}}, {"EnableCopyparty", {PERSISTENT | BACKUP, BOOL}}, {"EnableGithubRunner", {PERSISTENT | BACKUP, BOOL}}, + {"GreenLightAlert", {PERSISTENT | BACKUP, BOOL, "0"}}, {"GithubRunnerSufficientVoltage", {CLEAR_ON_MANAGER_START , BOOL}}, {"IntelligentCruiseButtonManagement", {PERSISTENT | BACKUP , BOOL}}, {"InteractivityTimeout", {PERSISTENT | BACKUP, INT, "0"}}, diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc index 10ead53774..07df99f726 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc @@ -49,6 +49,16 @@ VisualsPanel::VisualsPanel(QWidget *parent) : QWidget(parent) { "", false, }, + { + "GreenLightAlert", + tr("Green Traffic Light Alert (Beta)"), + QString("%1
" + "

%2


") + .arg(tr("A chime and on-screen alert will play when the traffic light you are waiting for turns green and you have no vehicle in front of you.")) + .arg(tr("Note: This chime is only designed as a notification. It is the driver's responsibility to observe their environment and make decisions accordingly.")), + "", + false, + }, }; // Add regular toggles first diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index df1bc3c002..d05822bb85 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -14,6 +14,11 @@ HudRendererSP::HudRendererSP() { plus_arrow_up_img = loadPixmap("../../sunnypilot/selfdrive/assets/img_plus_arrow_up", {105, 105}); minus_arrow_down_img = loadPixmap("../../sunnypilot/selfdrive/assets/img_minus_arrow_down", {105, 105}); + + int green_light_small_max = green_light_alert_small * 2 - 40; + int green_light_large_max = green_light_alert_large * 2 - 40; + green_light_alert_small_img = loadPixmap("../../sunnypilot/selfdrive/assets/images/green_light.png", {green_light_small_max, green_light_small_max}); + green_light_alert_large_img = loadPixmap("../../sunnypilot/selfdrive/assets/images/green_light.png", {green_light_large_max, green_light_large_max}); } void HudRendererSP::updateState(const UIState &s) { @@ -105,11 +110,15 @@ void HudRendererSP::updateState(const UIState &s) { smartCruiseControlVisionActive = lp_sp.getSmartCruiseControl().getVision().getActive(); smartCruiseControlMapEnabled = lp_sp.getSmartCruiseControl().getMap().getEnabled(); smartCruiseControlMapActive = lp_sp.getSmartCruiseControl().getMap().getActive(); + + greenLightAlert = lp_sp.getE2eAlerts().getGreenLightAlert(); } void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { HudRenderer::draw(p, surface_rect); + e2eAlertDisplayTimer = std::max(0, e2eAlertDisplayTimer - 1); + p.save(); if (is_cruise_available) { @@ -194,6 +203,18 @@ void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { // Road Name drawRoadName(p, surface_rect); + + // Green Light Alert + if (greenLightAlert) { + e2eAlertDisplayTimer = 3 * UI_FREQ; + } + + if (e2eAlertDisplayTimer > 0) { + e2eAlertFrame++; + drawE2eAlert(p, surface_rect); + } else { + e2eAlertFrame = 0; + } } p.restore(); @@ -666,3 +687,37 @@ void HudRendererSP::drawSetSpeedSP(QPainter &p, const QRect &surface_rect) { p.setPen(set_speed_color); p.drawText(set_speed_rect.adjusted(0, 77, 0, 0), Qt::AlignTop | Qt::AlignHCenter, setSpeedStr); } + +void HudRendererSP::drawE2eAlert(QPainter &p, const QRect &surface_rect) { + int size = devUiInfo > 0 ? green_light_alert_small : green_light_alert_large; + int x = surface_rect.center().x() + surface_rect.width() / 4; + int y = surface_rect.center().y() + 40; + x += devUiInfo > 0 ? 0 : 50; + y += devUiInfo > 0 ? 0 : 80; + QRect alertRect(x - size, y - size, size * 2, size * 2); + + QString alert_text = tr("GREEN\nLIGHT"); + + // Alert Circle + QPoint center = alertRect.center(); + QColor frameColor = pulseElement(e2eAlertFrame) ? QColor(255, 255, 255, 75) : QColor(0, 255, 0, 75); + p.setPen(QPen(frameColor, 15)); + p.setBrush(QColor(0, 0, 0, 190)); + p.drawEllipse(center, size, size); + + // Alert Text + QColor txtColor = pulseElement(e2eAlertFrame) ? QColor(255, 255, 255, 255) : QColor(0, 255, 0, 255); + p.setFont(InterFont(48, QFont::Bold)); + p.setPen(txtColor); + QFontMetrics fm(p.font()); + QRect textRect = fm.boundingRect(alertRect, Qt::TextWordWrap, alert_text); + textRect.moveCenter({alertRect.center().x(), alertRect.center().y()}); + textRect.moveBottom(alertRect.bottom() - alertRect.height() / 7); + p.drawText(textRect, Qt::AlignCenter, alert_text); + + // Alert Image + QPixmap &alert_img = devUiInfo > 0 ? green_light_alert_small_img : green_light_alert_large_img; + QPointF pixmapCenterOffset = QPointF(alert_img.width() / 2.0, alert_img.height() / 2.0); + QPointF drawPoint = center - pixmapCenterOffset; + p.drawPixmap(drawPoint, alert_img); +} diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.h b/selfdrive/ui/sunnypilot/qt/onroad/hud.h index 043536bf4c..b911167241 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.h +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.h @@ -36,6 +36,7 @@ private: void drawRoadName(QPainter &p, const QRect &surface_rect); void drawSpeedLimitPreActiveArrow(QPainter &p, QRect &sign_rect); void drawSetSpeedSP(QPainter &p, const QRect &surface_rect); + void drawE2eAlert(QPainter &p, const QRect &surface_rect); bool lead_status; float lead_d_rel; @@ -93,4 +94,11 @@ private: int speedLimitAssistFrame; QPixmap plus_arrow_up_img; QPixmap minus_arrow_down_img; + int green_light_alert_small = 250; + int green_light_alert_large = 300; + QPixmap green_light_alert_small_img; + QPixmap green_light_alert_large_img; + bool greenLightAlert; + int e2eAlertFrame; + int e2eAlertDisplayTimer = 0; }; diff --git a/sunnypilot/selfdrive/assets/images/green_light.png b/sunnypilot/selfdrive/assets/images/green_light.png new file mode 100644 index 0000000000..2da2c13a82 --- /dev/null +++ b/sunnypilot/selfdrive/assets/images/green_light.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3aa5ec9ac1daee6a549e62647d90bcaa66d2485f7df7f386ff902fcfb04c1716 +size 6583 diff --git a/sunnypilot/selfdrive/controls/lib/e2e_alerts_helper.py b/sunnypilot/selfdrive/controls/lib/e2e_alerts_helper.py new file mode 100644 index 0000000000..46657bd47c --- /dev/null +++ b/sunnypilot/selfdrive/controls/lib/e2e_alerts_helper.py @@ -0,0 +1,50 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" + +from cereal import messaging, custom + +from openpilot.common.params import Params +from openpilot.common.realtime import DT_MDL +from openpilot.sunnypilot import PARAMS_UPDATE_PERIOD +from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP + +TRIGGER_THRESHOLD = 30 + + +class E2EAlertsHelper: + def __init__(self): + self._params = Params() + self._frame = -1 + + self.green_light_alert = False + self.green_light_alert_enabled = self._params.get_bool("GreenLightAlert") + + def _read_params(self) -> None: + if self._frame % int(PARAMS_UPDATE_PERIOD / DT_MDL) == 0: + self.green_light_alert_enabled = self._params.get_bool("GreenLightAlert") + + self._frame += 1 + + def update(self, sm: messaging.SubMaster, events_sp: EventsSP) -> None: + self._read_params() + + if not self.green_light_alert_enabled: + return + + CS = sm['carState'] + CC = sm['carControl'] + + model_x = sm['modelV2'].position.x + max_idx = len(model_x) - 1 + has_lead = sm['radarState'].leadOne.status + + # Green light alert + self.green_light_alert = model_x[max_idx] > TRIGGER_THRESHOLD and \ + not has_lead and CS.standstill and not CS.gasPressed and not CC.enabled + + if self.green_light_alert: + events_sp.add(custom.OnroadEventSP.EventName.e2eChime) diff --git a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py index ece2ff2419..e45d748f3b 100644 --- a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py +++ b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py @@ -10,6 +10,7 @@ from opendbc.car import structs from openpilot.common.constants import CV from openpilot.selfdrive.car.cruise import V_CRUISE_MAX from openpilot.sunnypilot.selfdrive.controls.lib.dec.dec import DynamicExperimentalController +from openpilot.sunnypilot.selfdrive.controls.lib.e2e_alerts_helper import E2EAlertsHelper from openpilot.sunnypilot.selfdrive.controls.lib.smart_cruise_control.smart_cruise_control import SmartCruiseControl from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.speed_limit_assist import SpeedLimitAssist from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.speed_limit_resolver import SpeedLimitResolver @@ -30,6 +31,7 @@ class LongitudinalPlannerSP: self.sla = SpeedLimitAssist(CP) self.generation = int(model_bundle.generation) if (model_bundle := get_active_bundle()) else None self.source = LongitudinalPlanSource.cruise + self.e2e_alerts_helper = E2EAlertsHelper() self.output_v_target = 0. self.output_a_target = 0. @@ -53,8 +55,6 @@ class LongitudinalPlannerSP: long_enabled = sm['carControl'].enabled long_override = sm['carControl'].cruiseControl.override - self.events_sp.clear() - # Smart Cruise Control self.scc.update(sm, long_enabled, long_override, v_ego, a_ego, v_cruise) @@ -78,7 +78,9 @@ class LongitudinalPlannerSP: return self.output_v_target, self.output_a_target def update(self, sm: messaging.SubMaster) -> None: + self.events_sp.clear() self.dec.update(sm) + self.e2e_alerts_helper.update(sm, self.events_sp) def publish_longitudinal_plan_sp(self, sm: messaging.SubMaster, pm: messaging.PubMaster) -> None: plan_sp_send = messaging.new_message('longitudinalPlanSP') @@ -135,4 +137,8 @@ class LongitudinalPlannerSP: assist.vTarget = float(self.sla.output_v_target) assist.aTarget = float(self.sla.output_a_target) + # E2E Alerts + e2eAlerts = longitudinalPlanSP.e2eAlerts + e2eAlerts.greenLightAlert = self.e2e_alerts_helper.green_light_alert + pm.send('longitudinalPlanSP', plan_sp_send) diff --git a/sunnypilot/selfdrive/selfdrived/events.py b/sunnypilot/selfdrive/selfdrived/events.py index 7700550c2d..e9f4b29bae 100644 --- a/sunnypilot/selfdrive/selfdrived/events.py +++ b/sunnypilot/selfdrive/selfdrived/events.py @@ -224,4 +224,12 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = { AlertStatus.normal, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlert.none, 5.), }, + + EventNameSP.e2eChime: { + ET.PERMANENT: Alert( + "", + "", + AlertStatus.normal, AlertSize.none, + Priority.MID, VisualAlert.none, AudibleAlert.prompt, 0.1), + }, } From 225ce45d31d2fddf269f17c23c40b6ae5a95a524 Mon Sep 17 00:00:00 2001 From: Nayan Date: Thu, 2 Oct 2025 13:53:23 -0400 Subject: [PATCH 121/159] feat: Lead Departure Alert (#1302) * init * fix * event * UI * events..for real * SP * ugh * toggles * read params first * stoopid it is * fix green light img * fix green light image. for real this time * move events to longitudinal_planner * move events to longitudinal_planner * move e2e alerts to separate class * fix * fixxxxxxx * blinky blink * blinky blink * refactor * more refactor --------- Co-authored-by: Kumar <36933347+rav4kumar@users.noreply.github.com> Co-authored-by: Jason Wen --- cereal/custom.capnp | 1 + common/params_keys.h | 1 + .../qt/offroad/settings/visuals_panel.cc | 10 +++++++ selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 28 ++++++++++++------- selfdrive/ui/sunnypilot/qt/onroad/hud.h | 9 ++++-- .../selfdrive/assets/images/lead_depart.png | 3 ++ .../controls/lib/e2e_alerts_helper.py | 16 ++++++++--- .../controls/lib/longitudinal_planner.py | 1 + 8 files changed, 53 insertions(+), 16 deletions(-) create mode 100644 sunnypilot/selfdrive/assets/images/lead_depart.png diff --git a/cereal/custom.capnp b/cereal/custom.capnp index 23e26a8ccb..44b8bd69fa 100644 --- a/cereal/custom.capnp +++ b/cereal/custom.capnp @@ -250,6 +250,7 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 { struct E2eAlerts { greenLightAlert @0 :Bool; + leadDepartAlert @1 :Bool; } } diff --git a/common/params_keys.h b/common/params_keys.h index b8cda83693..0f5d9cf449 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -154,6 +154,7 @@ inline static std::unordered_map keys = { {"InteractivityTimeout", {PERSISTENT | BACKUP, INT, "0"}}, {"IsDevelopmentBranch", {CLEAR_ON_MANAGER_START, BOOL}}, {"LastGPSPositionLLK", {PERSISTENT, STRING}}, + {"LeadDepartAlert", {PERSISTENT | BACKUP, BOOL, "0"}}, {"MaxTimeOffroad", {PERSISTENT | BACKUP, INT, "1800"}}, {"ModelRunnerTypeCache", {CLEAR_ON_ONROAD_TRANSITION, INT}}, {"OffroadMode", {CLEAR_ON_MANAGER_START, BOOL}}, diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc index 07df99f726..7c1107d653 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/visuals_panel.cc @@ -59,6 +59,16 @@ VisualsPanel::VisualsPanel(QWidget *parent) : QWidget(parent) { "", false, }, + { + "LeadDepartAlert", + tr("Lead Departure Alert (Beta)"), + QString("%1
" + "

%2


") + .arg(tr("A chime and on-screen alert will play when you are stopped, and the vehicle in front of you start moving.")) + .arg(tr("Note: This chime is only designed as a notification. It is the driver's responsibility to observe their environment and make decisions accordingly.")), + "", + false, + }, }; // Add regular toggles first diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index d05822bb85..607e0cbbb5 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -15,10 +15,12 @@ HudRendererSP::HudRendererSP() { plus_arrow_up_img = loadPixmap("../../sunnypilot/selfdrive/assets/img_plus_arrow_up", {105, 105}); minus_arrow_down_img = loadPixmap("../../sunnypilot/selfdrive/assets/img_minus_arrow_down", {105, 105}); - int green_light_small_max = green_light_alert_small * 2 - 40; - int green_light_large_max = green_light_alert_large * 2 - 40; - green_light_alert_small_img = loadPixmap("../../sunnypilot/selfdrive/assets/images/green_light.png", {green_light_small_max, green_light_small_max}); - green_light_alert_large_img = loadPixmap("../../sunnypilot/selfdrive/assets/images/green_light.png", {green_light_large_max, green_light_large_max}); + int small_max = e2e_alert_small * 2 - 40; + int large_max = e2e_alert_large * 2 - 40; + green_light_alert_small_img = loadPixmap("../../sunnypilot/selfdrive/assets/images/green_light.png", {small_max, small_max}); + green_light_alert_large_img = loadPixmap("../../sunnypilot/selfdrive/assets/images/green_light.png", {large_max, large_max}); + lead_depart_alert_small_img = loadPixmap("../../sunnypilot/selfdrive/assets/images/lead_depart.png", {small_max, small_max}); + lead_depart_alert_large_img = loadPixmap("../../sunnypilot/selfdrive/assets/images/lead_depart.png", {large_max, large_max}); } void HudRendererSP::updateState(const UIState &s) { @@ -112,6 +114,7 @@ void HudRendererSP::updateState(const UIState &s) { smartCruiseControlMapActive = lp_sp.getSmartCruiseControl().getMap().getActive(); greenLightAlert = lp_sp.getE2eAlerts().getGreenLightAlert(); + leadDepartAlert = lp_sp.getE2eAlerts().getLeadDepartAlert(); } void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { @@ -204,13 +207,21 @@ void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { // Road Name drawRoadName(p, surface_rect); - // Green Light Alert - if (greenLightAlert) { + // Green Light & Lead Depart Alerts + if (greenLightAlert or leadDepartAlert) { e2eAlertDisplayTimer = 3 * UI_FREQ; } if (e2eAlertDisplayTimer > 0) { e2eAlertFrame++; + if (greenLightAlert) { + alert_text = tr("GREEN\nLIGHT"); + alert_img = devUiInfo > 0 ? green_light_alert_small_img : green_light_alert_large_img; + } + else if (leadDepartAlert) { + alert_text = tr("LEAD VEHICLE\nDEPARTING"); + alert_img = devUiInfo > 0 ? lead_depart_alert_small_img : lead_depart_alert_large_img; + } drawE2eAlert(p, surface_rect); } else { e2eAlertFrame = 0; @@ -689,15 +700,13 @@ void HudRendererSP::drawSetSpeedSP(QPainter &p, const QRect &surface_rect) { } void HudRendererSP::drawE2eAlert(QPainter &p, const QRect &surface_rect) { - int size = devUiInfo > 0 ? green_light_alert_small : green_light_alert_large; + int size = devUiInfo > 0 ? e2e_alert_small : e2e_alert_large; int x = surface_rect.center().x() + surface_rect.width() / 4; int y = surface_rect.center().y() + 40; x += devUiInfo > 0 ? 0 : 50; y += devUiInfo > 0 ? 0 : 80; QRect alertRect(x - size, y - size, size * 2, size * 2); - QString alert_text = tr("GREEN\nLIGHT"); - // Alert Circle QPoint center = alertRect.center(); QColor frameColor = pulseElement(e2eAlertFrame) ? QColor(255, 255, 255, 75) : QColor(0, 255, 0, 75); @@ -716,7 +725,6 @@ void HudRendererSP::drawE2eAlert(QPainter &p, const QRect &surface_rect) { p.drawText(textRect, Qt::AlignCenter, alert_text); // Alert Image - QPixmap &alert_img = devUiInfo > 0 ? green_light_alert_small_img : green_light_alert_large_img; QPointF pixmapCenterOffset = QPointF(alert_img.width() / 2.0, alert_img.height() / 2.0); QPointF drawPoint = center - pixmapCenterOffset; p.drawPixmap(drawPoint, alert_img); diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.h b/selfdrive/ui/sunnypilot/qt/onroad/hud.h index b911167241..cf840ee3d0 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.h +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.h @@ -94,11 +94,16 @@ private: int speedLimitAssistFrame; QPixmap plus_arrow_up_img; QPixmap minus_arrow_down_img; - int green_light_alert_small = 250; - int green_light_alert_large = 300; + int e2e_alert_small = 250; + int e2e_alert_large = 300; QPixmap green_light_alert_small_img; QPixmap green_light_alert_large_img; bool greenLightAlert; int e2eAlertFrame; int e2eAlertDisplayTimer = 0; + bool leadDepartAlert; + QPixmap lead_depart_alert_small_img; + QPixmap lead_depart_alert_large_img; + QString alert_text; + QPixmap alert_img; }; diff --git a/sunnypilot/selfdrive/assets/images/lead_depart.png b/sunnypilot/selfdrive/assets/images/lead_depart.png new file mode 100644 index 0000000000..6030ee67cf --- /dev/null +++ b/sunnypilot/selfdrive/assets/images/lead_depart.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:087db35bd469e85aefe3b45636f11ab3e8b55ceb7bc94ea059cfd9a69c2f338f +size 8914 diff --git a/sunnypilot/selfdrive/controls/lib/e2e_alerts_helper.py b/sunnypilot/selfdrive/controls/lib/e2e_alerts_helper.py index 46657bd47c..eedf8bccbb 100644 --- a/sunnypilot/selfdrive/controls/lib/e2e_alerts_helper.py +++ b/sunnypilot/selfdrive/controls/lib/e2e_alerts_helper.py @@ -22,17 +22,20 @@ class E2EAlertsHelper: self.green_light_alert = False self.green_light_alert_enabled = self._params.get_bool("GreenLightAlert") + self.lead_depart_alert = False + self.lead_depart_alert_enabled = self._params.get_bool("LeadDepartAlert") def _read_params(self) -> None: if self._frame % int(PARAMS_UPDATE_PERIOD / DT_MDL) == 0: self.green_light_alert_enabled = self._params.get_bool("GreenLightAlert") + self.lead_depart_alert_enabled = self._params.get_bool("LeadDepartAlert") self._frame += 1 def update(self, sm: messaging.SubMaster, events_sp: EventsSP) -> None: self._read_params() - if not self.green_light_alert_enabled: + if not (self.green_light_alert_enabled or self.lead_depart_alert_enabled): return CS = sm['carState'] @@ -41,10 +44,15 @@ class E2EAlertsHelper: model_x = sm['modelV2'].position.x max_idx = len(model_x) - 1 has_lead = sm['radarState'].leadOne.status + lead_vRel: float = sm['radarState'].leadOne.vRel # Green light alert - self.green_light_alert = model_x[max_idx] > TRIGGER_THRESHOLD and \ - not has_lead and CS.standstill and not CS.gasPressed and not CC.enabled + self.green_light_alert = (self.green_light_alert_enabled and model_x[max_idx] > TRIGGER_THRESHOLD + and not has_lead and CS.standstill and not CS.gasPressed and not CC.enabled) - if self.green_light_alert: + # Lead Departure Alert + self.lead_depart_alert = (self.lead_depart_alert_enabled and CS.standstill and model_x[max_idx] > 30 + and has_lead and lead_vRel > 1 and not CS.gasPressed) + + if self.green_light_alert or self.green_light_alert: events_sp.add(custom.OnroadEventSP.EventName.e2eChime) diff --git a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py index e45d748f3b..4c2443f253 100644 --- a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py +++ b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py @@ -140,5 +140,6 @@ class LongitudinalPlannerSP: # E2E Alerts e2eAlerts = longitudinalPlanSP.e2eAlerts e2eAlerts.greenLightAlert = self.e2e_alerts_helper.green_light_alert + e2eAlerts.leadDepartAlert = self.e2e_alerts_helper.lead_depart_alert pm.send('longitudinalPlanSP', plan_sp_send) From 4c4964a740aa5ea1f00d01ab17425cc8221e60b0 Mon Sep 17 00:00:00 2001 From: Nayan Date: Thu, 2 Oct 2025 14:42:15 -0400 Subject: [PATCH 122/159] Device: Wake for all visual alerts (#1309) this should do it --- selfdrive/ui/sunnypilot/qt/onroad/hud.cc | 2 ++ selfdrive/ui/sunnypilot/ui.cc | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc index 607e0cbbb5..21d66ffa99 100644 --- a/selfdrive/ui/sunnypilot/qt/onroad/hud.cc +++ b/selfdrive/ui/sunnypilot/qt/onroad/hud.cc @@ -210,6 +210,8 @@ void HudRendererSP::draw(QPainter &p, const QRect &surface_rect) { // Green Light & Lead Depart Alerts if (greenLightAlert or leadDepartAlert) { e2eAlertDisplayTimer = 3 * UI_FREQ; + // reset onroad sleep timer for e2e alerts + uiStateSP()->reset_onroad_sleep_timer(); } if (e2eAlertDisplayTimer > 0) { diff --git a/selfdrive/ui/sunnypilot/ui.cc b/selfdrive/ui/sunnypilot/ui.cc index 6cbdeadf58..7f4fc88235 100644 --- a/selfdrive/ui/sunnypilot/ui.cc +++ b/selfdrive/ui/sunnypilot/ui.cc @@ -14,8 +14,7 @@ void UIStateSP::updateStatus() { if (scene.started && scene.onroadScreenOffControl) { auto selfdriveState = (*sm)["selfdriveState"].getSelfdriveState(); - if (selfdriveState.getAlertSize() != cereal::SelfdriveState::AlertSize::NONE && - selfdriveState.getAlertStatus() != cereal::SelfdriveState::AlertStatus::NORMAL) { + if (selfdriveState.getAlertSize() != cereal::SelfdriveState::AlertSize::NONE) { reset_onroad_sleep_timer(); } else if (scene.onroadScreenOffTimer > 0) { scene.onroadScreenOffTimer--; From 09d165a85b596c3f0ce383af726a1d062ede11fb Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Thu, 2 Oct 2025 16:37:57 -0400 Subject: [PATCH 123/159] Tesla: MADS full support with VEHICLE bus harness (#1310) * Tesla: MADS full support with VEHICLE bus harness * bump * need new arg * uh * block cruise main for these cars still * continue to block tesla * oops * always allow for tesla --- opendbc_repo | 2 +- selfdrive/car/card.py | 2 +- .../offroad/settings/lateral/mads_settings.cc | 8 ++++-- .../offroad/settings/lateral/mads_settings.h | 11 +++++++- .../qt/offroad/settings/lateral_panel.cc | 8 ++++-- sunnypilot/mads/helpers.py | 28 +++++++++++++------ sunnypilot/mads/mads.py | 9 ++++-- 7 files changed, 50 insertions(+), 18 deletions(-) diff --git a/opendbc_repo b/opendbc_repo index dfcfacb667..bf0aba991a 160000 --- a/opendbc_repo +++ b/opendbc_repo @@ -1 +1 @@ -Subproject commit dfcfacb667c6ff131d0e620c36e118f14a84dc4a +Subproject commit bf0aba991acbe14dd164ddfc8cc272cebf794544 diff --git a/selfdrive/car/card.py b/selfdrive/car/card.py index 34f0283ce4..4c44e43281 100755 --- a/selfdrive/car/card.py +++ b/selfdrive/car/card.py @@ -124,7 +124,7 @@ class Car: self.CP.alternativeExperience = 0 # mads - set_alternative_experience(self.CP, self.params) + set_alternative_experience(self.CP, self.CP_SP, self.params) set_car_specific_params(self.CP, self.CP_SP, self.params) # Dynamic Experimental Control diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/mads_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/mads_settings.cc index 72e7a5c8cb..749bc9e3f3 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/mads_settings.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/mads_settings.cc @@ -52,12 +52,16 @@ void MadsSettings::updateToggles(bool _offroad) { ); auto cp_bytes = params.get("CarParamsPersistent"); - if (!cp_bytes.empty()) { + auto cp_sp_bytes = params.get("CarParamsSPPersistent"); + if (!cp_bytes.empty() && !cp_sp_bytes.empty()) { AlignedBuffer aligned_buf; + AlignedBuffer aligned_buf_sp; capnp::FlatArrayMessageReader cmsg(aligned_buf.align(cp_bytes.data(), cp_bytes.size())); + capnp::FlatArrayMessageReader cmsg_sp(aligned_buf_sp.align(cp_sp_bytes.data(), cp_sp_bytes.size())); cereal::CarParams::Reader CP = cmsg.getRoot(); + cereal::CarParamsSP::Reader CP_SP = cmsg_sp.getRoot(); - if (isBrandInList(CP.getBrand(), mads_limited_settings_brands)) { + if (madsLimitedSettings(CP, CP_SP)) { params.remove("MadsMainCruiseAllowed"); params.putBool("MadsUnifiedEngagementMode", true); params.put("MadsSteeringMode", std::to_string(static_cast(MadsSteeringMode::DISENGAGE))); diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/mads_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/mads_settings.h index af624865c7..9cf62a0ffe 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/mads_settings.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/mads_settings.h @@ -12,7 +12,16 @@ #include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" #include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" -const std::vector mads_limited_settings_brands = {"rivian", "tesla"}; +inline bool madsLimitedSettings(const cereal::CarParams::Reader &CP, const cereal::CarParamsSP::Reader &CP_SP) { + if (CP.getBrand() == "rivian") { + return true; + } + if (CP.getBrand() == "tesla") { + return !(CP_SP.getFlags() & 1); // 1 == TeslaFlagsSP.HAS_VEHICLE_BUS + } + + return false; +} enum class MadsSteeringMode { REMAIN_ACTIVE = 0, diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral_panel.cc index ae954d7539..59636ca5a5 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral_panel.cc @@ -134,12 +134,16 @@ void LateralPanel::updateToggles(bool _offroad) { } auto cp_bytes = params.get("CarParamsPersistent"); - if (!cp_bytes.empty()) { + auto cp_sp_bytes = params.get("CarParamsSPPersistent"); + if (!cp_bytes.empty() && !cp_sp_bytes.empty()) { AlignedBuffer aligned_buf; + AlignedBuffer aligned_buf_sp; capnp::FlatArrayMessageReader cmsg(aligned_buf.align(cp_bytes.data(), cp_bytes.size())); + capnp::FlatArrayMessageReader cmsg_sp(aligned_buf_sp.align(cp_sp_bytes.data(), cp_sp_bytes.size())); cereal::CarParams::Reader CP = cmsg.getRoot(); + cereal::CarParamsSP::Reader CP_SP = cmsg_sp.getRoot(); - if (isBrandInList(CP.getBrand(), mads_limited_settings_brands)) { + if (madsLimitedSettings(CP, CP_SP)) { madsToggle->setDescription(descriptionBuilder(STATUS_MADS_SETTINGS_LIMITED_COMPATIBILITY, MADS_BASE_DESC)); } else { madsToggle->setDescription(descriptionBuilder(STATUS_MADS_SETTINGS_FULL_COMPATIBILITY, MADS_BASE_DESC)); diff --git a/sunnypilot/mads/helpers.py b/sunnypilot/mads/helpers.py index 70b590a8b2..f9c4057bab 100644 --- a/sunnypilot/mads/helpers.py +++ b/sunnypilot/mads/helpers.py @@ -9,6 +9,10 @@ from openpilot.common.params import Params from opendbc.car import structs from opendbc.safety import ALTERNATIVE_EXPERIENCE from opendbc.sunnypilot.car.hyundai.values import HyundaiFlagsSP, HyundaiSafetyFlagsSP +from opendbc.sunnypilot.car.tesla.values import TeslaFlagsSP + + +MADS_NO_ACC_MAIN_BUTTON = ("rivian", "tesla") class MadsSteeringModeOnBrake: @@ -17,20 +21,25 @@ class MadsSteeringModeOnBrake: DISENGAGE = 2 -def get_mads_limited_brands(CP: structs.CarParams) -> bool: - return CP.brand in ("rivian", "tesla") +def get_mads_limited_brands(CP: structs.CarParams, CP_SP: structs.CarParamsSP) -> bool: + if CP.brand == 'rivian': + return True + if CP.brand == 'tesla': + return not CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS + + return False -def read_steering_mode_param(CP: structs.CarParams, params: Params): - if get_mads_limited_brands(CP): +def read_steering_mode_param(CP: structs.CarParams, CP_SP: structs.CarParamsSP, params: Params): + if get_mads_limited_brands(CP, CP_SP): return MadsSteeringModeOnBrake.DISENGAGE return params.get("MadsSteeringMode", return_default=True) -def set_alternative_experience(CP: structs.CarParams, params: Params): +def set_alternative_experience(CP: structs.CarParams, CP_SP: structs.CarParamsSP, params: Params): enabled = params.get_bool("Mads") - steering_mode = read_steering_mode_param(CP, params) + steering_mode = read_steering_mode_param(CP, CP_SP, params) if enabled: CP.alternativeExperience |= ALTERNATIVE_EXPERIENCE.ENABLE_MADS @@ -53,9 +62,12 @@ def set_car_specific_params(CP: structs.CarParams, CP_SP: structs.CarParamsSP, p # MADS Partial Support # MADS is currently partially supported for these platforms due to lack of consistent states to engage controls # Only MadsSteeringModeOnBrake.DISENGAGE is supported for these platforms - # TODO-SP: To enable MADS full support for Rivian/Tesla, identify consistent signals for MADS toggling - mads_partial_support = get_mads_limited_brands(CP) + # TODO-SP: To enable MADS full support for Rivian and most Tesla, identify consistent signals for MADS toggling + mads_partial_support = get_mads_limited_brands(CP, CP_SP) if mads_partial_support: params.put("MadsSteeringMode", 2) params.put_bool("MadsUnifiedEngagementMode", True) + + # no ACC MAIN button for these brands + if CP.brand in MADS_NO_ACC_MAIN_BUTTON: params.remove("MadsMainCruiseAllowed") diff --git a/sunnypilot/mads/mads.py b/sunnypilot/mads/mads.py index b75bd8ccda..21e7f7d3e7 100644 --- a/sunnypilot/mads/mads.py +++ b/sunnypilot/mads/mads.py @@ -10,7 +10,7 @@ from cereal import log, custom from opendbc.car import structs from opendbc.car.hyundai.values import HyundaiFlags from openpilot.common.params import Params -from openpilot.sunnypilot.mads.helpers import MadsSteeringModeOnBrake, read_steering_mode_param, get_mads_limited_brands +from openpilot.sunnypilot.mads.helpers import MadsSteeringModeOnBrake, read_steering_mode_param, MADS_NO_ACC_MAIN_BUTTON from openpilot.sunnypilot.mads.state import StateMachine, GEARS_ALLOW_PAUSED_SILENT State = custom.ModularAssistiveDrivingSystem.ModularAssistiveDrivingSystemState @@ -27,6 +27,7 @@ IGNORED_SAFETY_MODES = (SafetyModel.silent, SafetyModel.noOutput) class ModularAssistiveDrivingSystem: def __init__(self, selfdrive): self.CP = selfdrive.CP + self.CP_SP = selfdrive.CP_SP self.params = selfdrive.params self.enabled = False @@ -43,14 +44,16 @@ class ModularAssistiveDrivingSystem: if self.CP.brand == "hyundai": if self.CP.flags & (HyundaiFlags.HAS_LDA_BUTTON | HyundaiFlags.CANFD): self.allow_always = True + if self.CP.brand == "tesla": + self.allow_always = True - if get_mads_limited_brands(self.CP): + if self.CP.brand in MADS_NO_ACC_MAIN_BUTTON: self.no_main_cruise = True # read params on init self.enabled_toggle = self.params.get_bool("Mads") self.main_enabled_toggle = self.params.get_bool("MadsMainCruiseAllowed") - self.steering_mode_on_brake = read_steering_mode_param(self.CP, self.params) + self.steering_mode_on_brake = read_steering_mode_param(self.CP, self.CP_SP, self.params) self.unified_engagement_mode = self.params.get_bool("MadsUnifiedEngagementMode") def read_params(self): From dcd382ffb8ff924d7cf2417290dcb0ed32b79d72 Mon Sep 17 00:00:00 2001 From: DevTekVE Date: Fri, 3 Oct 2025 19:42:46 +0200 Subject: [PATCH 124/159] sunnylink: enhanced param keys fetch with data type (#1308) * refactor: enhance parameter handling and add new parameter retrieval method - Refactored `get_param_as_byte` for better modularity and added `_to_bytes` helper function. - Introduced `getParamsAllKeysV1` to retrieve all keys with enhanced metadata. * refactor: update parameter handling and response structure in sunnylink - Modified `_to_bytes` to accept `bytes` type for improved type consistency. - Adjusted response keys in `sunnylinkd` for clarity. * fix: update `get_param_as_byte` to use corrected method for default values - Replaced `get_default` with `get_default_value` for accurate param retrieval. - Ensures consistent handling of default parameter values. * refactor: remove redundant `None` check in `sunnylinkd.py` - Streamlined parameter iteration by eliminating unnecessary `None` validation. - Simplifies logic for constructing `params_dict`. * refactor: streamline `sunnylinkd` response by removing redundant `keys_v1` field - Simplified return structure by excluding unused `keys_v1` key. - Reduces response payload for improved efficiency. * refactor: split `getParamsAllKeys` into distinct functions for improved clarity - Added `getParamsAllKeysV1` to preserve original metadata-rich behavior. - Revised `getParamsAllKeys` to return a simplified list of parameter keys. * style: remove extraneous newline in `sunnylinkd.py` - Ensures consistent formatting and adheres to style guidelines. * Test --- sunnypilot/sunnylink/athena/sunnylinkd.py | 19 +++++++++++++++++- sunnypilot/sunnylink/utils.py | 24 +++++++++++++---------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/sunnypilot/sunnylink/athena/sunnylinkd.py b/sunnypilot/sunnylink/athena/sunnylinkd.py index 25a77c367b..d1b38d656f 100755 --- a/sunnypilot/sunnylink/athena/sunnylinkd.py +++ b/sunnypilot/sunnylink/athena/sunnylinkd.py @@ -178,12 +178,29 @@ def getParamsAllKeys() -> list[str]: return keys +@dispatcher.add_method +def getParamsAllKeysV1() -> dict[str, str]: + available_keys: list[str] = [k.decode('utf-8') for k in Params().all_keys()] + + params_dict: dict[str, list[dict[str, str | bool | int | None]]] = {"params": []} + for key in available_keys: + value = get_param_as_byte(key, get_default=True) + params_dict["params"].append({ + "key": key, + "type": int(params.get_type(key).value), + "default_value": base64.b64encode(value).decode('utf-8') if value else None, + }) + + return {"keys": json.dumps(params_dict.get("params", []))} + + @dispatcher.add_method def getParams(params_keys: list[str], compression: bool = False) -> str | dict[str, str]: params = Params() + available_keys: list[str] = [k.decode('utf-8') for k in Params().all_keys()] try: - param_keys_validated = [key for key in params_keys if key in getParamsAllKeys()] + param_keys_validated = [key for key in params_keys if key in available_keys] params_dict: dict[str, list[dict[str, str | bool | int]]] = {"params": []} for key in param_keys_validated: value = get_param_as_byte(key) diff --git a/sunnypilot/sunnylink/utils.py b/sunnypilot/sunnylink/utils.py index 91c0788795..70791c4ce4 100644 --- a/sunnypilot/sunnylink/utils.py +++ b/sunnypilot/sunnylink/utils.py @@ -60,21 +60,25 @@ def get_api_token(): print(f"API Token: {token}") -def get_param_as_byte(param_name: str, params=None) -> bytes | None: - """Get a parameter as bytes. Returns None if the parameter does not exist.""" - params = params or Params() # Use existing Params instance if provided - param = params.get(param_name) - if param is None: +def _to_bytes(value: bytes | None, param_type: ParamKeyType) -> bytes | None: + """Convert a parameter value to bytes based on its type.""" + if value is None: return None - param_type = params.get_type(param_name) if param_type == ParamKeyType.BYTES: - return bytes(param) - elif param_type == ParamKeyType.JSON: - return json.dumps(param).encode('utf-8') - return str(param).encode('utf-8') + return bytes(value) + if param_type == ParamKeyType.JSON: + return json.dumps(value).encode("utf-8") + return str(value).encode("utf-8") +def get_param_as_byte(param_name: str, params=None, get_default=False) -> bytes | None: + """Get a parameter as bytes. Returns None if the parameter does not exist.""" + params = params or Params() + value = params.get(param_name) if not get_default else params.get_default_value(param_name) + param_type = params.get_type(param_name) + return _to_bytes(value, param_type) + def save_param_from_base64_encoded_string(param_name: str, base64_encoded_data: str, is_compressed=False) -> None: """Save a parameter from bytes. Overwrites the parameter if it already exists.""" params = Params() From 1bfecbc9c2e81d0fb7879ba5502b401053824b09 Mon Sep 17 00:00:00 2001 From: DevTekVE Date: Fri, 3 Oct 2025 19:43:13 +0200 Subject: [PATCH 125/159] sunnylink: Enabled by default (#1312) Enable sunnylink by default --- common/params_keys.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/params_keys.h b/common/params_keys.h index 0f5d9cf449..0844fff2bf 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -192,7 +192,7 @@ inline static std::unordered_map keys = { {"SunnylinkCache_Users", {PERSISTENT, STRING}}, {"SunnylinkDongleId", {PERSISTENT, STRING}}, {"SunnylinkdPid", {PERSISTENT, INT}}, - {"SunnylinkEnabled", {PERSISTENT, BOOL}}, + {"SunnylinkEnabled", {PERSISTENT, BOOL, "1"}}, // Backup Manager params {"BackupManager_CreateBackup", {PERSISTENT, BOOL}}, From e999839a5715dbfadda42cace0aa50e01954bf30 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Fri, 3 Oct 2025 17:46:13 -0400 Subject: [PATCH 126/159] ui: replace `static_cast` with `std::nearbyint` for convert & rounding (#1313) * ui: replace `static_cast` with `std::nearbyint` for precise rounding * revert --- selfdrive/ui/sunnypilot/qt/widgets/controls.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/selfdrive/ui/sunnypilot/qt/widgets/controls.h b/selfdrive/ui/sunnypilot/qt/widgets/controls.h index 03cb461385..e9e1e4bb85 100644 --- a/selfdrive/ui/sunnypilot/qt/widgets/controls.h +++ b/selfdrive/ui/sunnypilot/qt/widgets/controls.h @@ -7,6 +7,7 @@ #pragma once +#include #include #include #include @@ -500,7 +501,7 @@ private: int getParamValueScaled() { const auto param_value = QString::fromStdString(params.get(key)); - return static_cast(param_value.toFloat() * 100); + return std::nearbyint(param_value.toFloat() * 100.0f); } void setParamValueScaled(const int new_value) { From 1e7fc15a040dca7f3a3e7143edb6333086d224ff Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Fri, 3 Oct 2025 18:24:24 -0400 Subject: [PATCH 127/159] Speed Limit Assist: Update state machine for PCM long cars (#1311) * Speed Limit Assist: Update state machine for PCM long cars * new test to catch this wrong transition * tldr --- .../lib/speed_limit/speed_limit_assist.py | 14 ++++++++------ .../tests/test_speed_limit_assist.py | 18 ++++++++++++++++-- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_assist.py b/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_assist.py index 5d798949a9..302d8cd14d 100644 --- a/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_assist.py +++ b/sunnypilot/selfdrive/controls/lib/speed_limit/speed_limit_assist.py @@ -247,11 +247,11 @@ class SpeedLimitAssist: # PENDING elif self.state == SpeedLimitAssistState.pending: - if self._has_speed_limit: - if self.v_offset < LIMIT_SPEED_OFFSET_TH: - self.state = SpeedLimitAssistState.adapting - else: - self.state = SpeedLimitAssistState.active + if self.target_set_speed_confirmed: + self._update_confirmed_state() + elif self.speed_limit_changed: + self.state = SpeedLimitAssistState.preActive + self.pre_active_timer = int(PRE_ACTIVE_GUARD_PERIOD / DT_MDL) # PRE_ACTIVE elif self.state == SpeedLimitAssistState.preActive: @@ -275,9 +275,11 @@ class SpeedLimitAssist: elif self.long_engaged_timer <= 0: if self.target_set_speed_confirmed: self._update_confirmed_state() - else: + elif self._has_speed_limit: self.state = SpeedLimitAssistState.preActive self.pre_active_timer = int(PRE_ACTIVE_GUARD_PERIOD / DT_MDL) + else: + self.state = SpeedLimitAssistState.pending enabled = self.state in ENABLED_STATES active = self.state in ACTIVE_STATES diff --git a/sunnypilot/selfdrive/controls/lib/speed_limit/tests/test_speed_limit_assist.py b/sunnypilot/selfdrive/controls/lib/speed_limit/tests/test_speed_limit_assist.py index 3b2716265d..d2c7a4716d 100644 --- a/sunnypilot/selfdrive/controls/lib/speed_limit/tests/test_speed_limit_assist.py +++ b/sunnypilot/selfdrive/controls/lib/speed_limit/tests/test_speed_limit_assist.py @@ -96,6 +96,12 @@ class TestSpeedLimitAssist: assert self.sla.state == SpeedLimitAssistState.preActive assert self.sla.is_enabled and not self.sla.is_active + def test_transition_disabled_to_pending_no_speed_limit_not_max_initial_set_speed(self): + for _ in range(int(3. / DT_MDL)): + self.sla.update(True, False, SPEED_LIMITS['highway'], 0, SPEED_LIMITS['city'], 0, 0, False, 0, self.events_sp) + assert self.sla.state == SpeedLimitAssistState.pending + assert self.sla.is_enabled and not self.sla.is_active + def test_preactive_to_active_with_max_speed_confirmation(self): self.sla.state = SpeedLimitAssistState.preActive self.sla.update(True, False, SPEED_LIMITS['city'], 0, self.pcm_long_max_set_speed, SPEED_LIMITS['highway'], @@ -120,12 +126,20 @@ class TestSpeedLimitAssist: def test_pending_to_active_when_speed_limit_available(self): self.sla.state = SpeedLimitAssistState.pending - self.sla.update(True, False, SPEED_LIMITS['city'], 0, self.pcm_long_max_set_speed, SPEED_LIMITS['city'], SPEED_LIMITS['city'], True, 0, self.events_sp) + self.sla.v_cruise_cluster_prev = self.pcm_long_max_set_speed + self.sla.prev_v_cruise_cluster_conv = round(self.pcm_long_max_set_speed * self.speed_conv) + + self.sla.update(True, False, SPEED_LIMITS['highway'], 0, self.pcm_long_max_set_speed, + SPEED_LIMITS['highway'], SPEED_LIMITS['highway'], True, 0, self.events_sp) assert self.sla.state == SpeedLimitAssistState.active def test_pending_to_adapting_when_below_speed_limit(self): self.sla.state = SpeedLimitAssistState.pending - self.sla.update(True, False, SPEED_LIMITS['city'] + 5, 0, self.pcm_long_max_set_speed, SPEED_LIMITS['city'], SPEED_LIMITS['city'], True, 0, self.events_sp) + self.sla.v_cruise_cluster_prev = self.pcm_long_max_set_speed + self.sla.prev_v_cruise_cluster_conv = round(self.pcm_long_max_set_speed * self.speed_conv) + + self.sla.update(True, False, SPEED_LIMITS['highway'] + 5, 0, self.pcm_long_max_set_speed, + SPEED_LIMITS['highway'], SPEED_LIMITS['highway'], True, 0, self.events_sp) assert self.sla.state == SpeedLimitAssistState.adapting assert self.sla.is_enabled and self.sla.is_active From 282a8b093ddb8f611d71bfee7bcde9e2e3281ee2 Mon Sep 17 00:00:00 2001 From: DevTekVE Date: Sat, 4 Oct 2025 07:42:44 +0200 Subject: [PATCH 128/159] Revert "sunnylink: enhanced param keys fetch with data type" (#1316) Revert "sunnylink: enhanced param keys fetch with data type (#1308)" This reverts commit dcd382ffb8ff924d7cf2417290dcb0ed32b79d72. --- sunnypilot/sunnylink/athena/sunnylinkd.py | 19 +---------------- sunnypilot/sunnylink/utils.py | 26 ++++++++++------------- 2 files changed, 12 insertions(+), 33 deletions(-) diff --git a/sunnypilot/sunnylink/athena/sunnylinkd.py b/sunnypilot/sunnylink/athena/sunnylinkd.py index d1b38d656f..25a77c367b 100755 --- a/sunnypilot/sunnylink/athena/sunnylinkd.py +++ b/sunnypilot/sunnylink/athena/sunnylinkd.py @@ -178,29 +178,12 @@ def getParamsAllKeys() -> list[str]: return keys -@dispatcher.add_method -def getParamsAllKeysV1() -> dict[str, str]: - available_keys: list[str] = [k.decode('utf-8') for k in Params().all_keys()] - - params_dict: dict[str, list[dict[str, str | bool | int | None]]] = {"params": []} - for key in available_keys: - value = get_param_as_byte(key, get_default=True) - params_dict["params"].append({ - "key": key, - "type": int(params.get_type(key).value), - "default_value": base64.b64encode(value).decode('utf-8') if value else None, - }) - - return {"keys": json.dumps(params_dict.get("params", []))} - - @dispatcher.add_method def getParams(params_keys: list[str], compression: bool = False) -> str | dict[str, str]: params = Params() - available_keys: list[str] = [k.decode('utf-8') for k in Params().all_keys()] try: - param_keys_validated = [key for key in params_keys if key in available_keys] + param_keys_validated = [key for key in params_keys if key in getParamsAllKeys()] params_dict: dict[str, list[dict[str, str | bool | int]]] = {"params": []} for key in param_keys_validated: value = get_param_as_byte(key) diff --git a/sunnypilot/sunnylink/utils.py b/sunnypilot/sunnylink/utils.py index 70791c4ce4..91c0788795 100644 --- a/sunnypilot/sunnylink/utils.py +++ b/sunnypilot/sunnylink/utils.py @@ -60,24 +60,20 @@ def get_api_token(): print(f"API Token: {token}") -def _to_bytes(value: bytes | None, param_type: ParamKeyType) -> bytes | None: - """Convert a parameter value to bytes based on its type.""" - if value is None: +def get_param_as_byte(param_name: str, params=None) -> bytes | None: + """Get a parameter as bytes. Returns None if the parameter does not exist.""" + params = params or Params() # Use existing Params instance if provided + param = params.get(param_name) + if param is None: return None - if param_type == ParamKeyType.BYTES: - return bytes(value) - if param_type == ParamKeyType.JSON: - return json.dumps(value).encode("utf-8") - return str(value).encode("utf-8") - - -def get_param_as_byte(param_name: str, params=None, get_default=False) -> bytes | None: - """Get a parameter as bytes. Returns None if the parameter does not exist.""" - params = params or Params() - value = params.get(param_name) if not get_default else params.get_default_value(param_name) param_type = params.get_type(param_name) - return _to_bytes(value, param_type) + if param_type == ParamKeyType.BYTES: + return bytes(param) + elif param_type == ParamKeyType.JSON: + return json.dumps(param).encode('utf-8') + return str(param).encode('utf-8') + def save_param_from_base64_encoded_string(param_name: str, base64_encoded_data: str, is_compressed=False) -> None: """Save a parameter from bytes. Overwrites the parameter if it already exists.""" From cca3be3a9682c5df0b542044a87f960e5d186b78 Mon Sep 17 00:00:00 2001 From: DevTekVE Date: Sat, 4 Oct 2025 10:08:08 +0200 Subject: [PATCH 129/159] relock after inplace metadrive update (#1321) relock after inplace metadrive update (#36256) * relock after inplace metadrive update * Revert "relock after inplace metadrive update" This reverts commit 18193ffe34b66085e18605e6c9289ddcd658844d. * just the hash (cherry picked from commit 4d53a26a06973a7d6fa4fef1e238a3bb9e64e67c) Co-authored-by: Armand du Parc Locmaria --- uv.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uv.lock b/uv.lock index 25d2b626cf..b871cc8da4 100644 --- a/uv.lock +++ b/uv.lock @@ -945,7 +945,7 @@ dependencies = [ { name = "yapf", marker = "platform_machine != 'aarch64' or sys_platform != 'linux'" }, ] wheels = [ - { url = "https://github.com/commaai/metadrive/releases/download/MetaDrive-minimal-0.4.2.4/metadrive_simulator-0.4.2.4-py3-none-any.whl", hash = "sha256:fbf0ea9be67e65cd45d38ff930e3d49f705dd76c9ddbd1e1482e3f87b61efcef" }, + { url = "https://github.com/commaai/metadrive/releases/download/MetaDrive-minimal-0.4.2.4/metadrive_simulator-0.4.2.4-py3-none-any.whl", hash = "sha256:d0afaf3b005e35e14b929d5491d2d5b64562d0c1cd5093ba969fb63908670dd4" }, ] [package.metadata] From 18abe218d9115ac2608a6c6aaf458896120b61c7 Mon Sep 17 00:00:00 2001 From: DevTekVE Date: Sat, 4 Oct 2025 18:19:16 +0200 Subject: [PATCH 130/159] ci: Disable homebrew cache for MacOS builds (#1322) * maybe Revert "fuck" This reverts commit cb072a73b1b44ac3abeb50196be0956f3b7a7e14. Revert "i dunno anymore" This reverts commit 4d3c84ecb0e7830a552237e824995bc255007a1b. i dunno anymore fuck * maybe * try to fix the pipelines --- .github/workflows/selfdrive_tests.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/selfdrive_tests.yaml b/.github/workflows/selfdrive_tests.yaml index 41d8156ca8..85b7c61e5a 100644 --- a/.github/workflows/selfdrive_tests.yaml +++ b/.github/workflows/selfdrive_tests.yaml @@ -115,7 +115,9 @@ jobs: - run: echo "CACHE_COMMIT_DATE=$(git log -1 --pretty='format:%cd' --date=format:'%Y-%m-%d-%H:%M')" >> $GITHUB_ENV - name: Homebrew cache uses: ./.github/workflows/auto-cache + if: false # disabling the cache for now because it is breaking macos builds... with: + save: false # No need save here if we manually save it later conditionally path: ~/Library/Caches/Homebrew key: brew-macos-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }} restore-keys: | @@ -136,6 +138,7 @@ jobs: - name: Getting scons cache uses: ./.github/workflows/auto-cache with: + save: false # No need save here if we manually save it later conditionally path: /tmp/scons_cache key: scons-${{ runner.arch }}-macos-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }} restore-keys: | From 520649b89361f9145818b019c6a659ad2a5f9f67 Mon Sep 17 00:00:00 2001 From: dzid26 Date: Sun, 5 Oct 2025 08:34:12 +0100 Subject: [PATCH 131/159] params: Fix loading delay on startup (#1297) params frame counter init make sure param_store.update gets processed on first call Co-authored-by: Jason Wen --- sunnypilot/selfdrive/controls/lib/param_store.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sunnypilot/selfdrive/controls/lib/param_store.py b/sunnypilot/selfdrive/controls/lib/param_store.py index 65a0175340..785fe9c8f0 100644 --- a/sunnypilot/selfdrive/controls/lib/param_store.py +++ b/sunnypilot/selfdrive/controls/lib/param_store.py @@ -22,7 +22,7 @@ class ParamStore: self.keys = universal_params + brand_params self._params = {} - self.frame = 0 + self.frame = -1 def update(self, params: Params) -> None: self.frame += 1 From 5a309daee6a1949eaf4ae0490ae9ec6fcfb3c152 Mon Sep 17 00:00:00 2001 From: dzid26 Date: Sun, 5 Oct 2025 08:38:49 +0100 Subject: [PATCH 132/159] docs: clarify pedal press (#1289) Co-authored-by: Jason Wen --- sunnypilot/mads/mads.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sunnypilot/mads/mads.py b/sunnypilot/mads/mads.py index 21e7f7d3e7..7eab55e6ea 100644 --- a/sunnypilot/mads/mads.py +++ b/sunnypilot/mads/mads.py @@ -61,6 +61,7 @@ class ModularAssistiveDrivingSystem: self.unified_engagement_mode = self.params.get_bool("MadsUnifiedEngagementMode") def pedal_pressed_non_gas_pressed(self, CS: structs.CarState) -> bool: + # ignore `pedalPressed` events caused by gas presses if self.events.has(EventName.pedalPressed) and not (CS.gasPressed and not self.selfdrive.CS_prev.gasPressed and self.disengage_on_accelerator): return True From 0e1de37281e7ab2958e1e0ae78d6999a1e0126c6 Mon Sep 17 00:00:00 2001 From: Nayan Date: Sun, 5 Oct 2025 21:18:03 -0400 Subject: [PATCH 133/159] Bug: Fix Lead Departure Alert Chime (#1328) make lead-alert ding again --- sunnypilot/selfdrive/controls/lib/e2e_alerts_helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sunnypilot/selfdrive/controls/lib/e2e_alerts_helper.py b/sunnypilot/selfdrive/controls/lib/e2e_alerts_helper.py index eedf8bccbb..0135b2806c 100644 --- a/sunnypilot/selfdrive/controls/lib/e2e_alerts_helper.py +++ b/sunnypilot/selfdrive/controls/lib/e2e_alerts_helper.py @@ -54,5 +54,5 @@ class E2EAlertsHelper: self.lead_depart_alert = (self.lead_depart_alert_enabled and CS.standstill and model_x[max_idx] > 30 and has_lead and lead_vRel > 1 and not CS.gasPressed) - if self.green_light_alert or self.green_light_alert: + if self.green_light_alert or self.lead_depart_alert: events_sp.add(custom.OnroadEventSP.EventName.e2eChime) From de64b99740e6473c9bece80ec3e4ed9825227f0e Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sun, 5 Oct 2025 23:41:31 -0400 Subject: [PATCH 134/159] Torque Lateral Control: customized settings (#1314) * init * use internal frame * exit early if toggle not enabled * ui init * ui: replace `static_cast` with `std::nearbyint` for precise rounding * revert * update title * handle live relaxed * fix * tweak ui * toggle behaviors * lint * Update torqued_ext.py * always update * make sure it's updated properly with offroad states * fix * make sure to initialize --------- Co-authored-by: nayan --- common/params_keys.h | 9 +++ selfdrive/controls/lib/latcontrol_torque.py | 4 + selfdrive/locationd/torqued.py | 10 ++- selfdrive/ui/sunnypilot/SConscript | 2 + .../lateral/neural_network_lateral_control.cc | 14 +++- .../lateral/neural_network_lateral_control.h | 3 +- .../torque_lateral_control_custom_params.cc | 58 +++++++++++++ .../torque_lateral_control_custom_params.h | 27 +++++++ .../torque_lateral_control_settings.cc | 81 +++++++++++++++++++ .../lateral/torque_lateral_control_settings.h | 36 +++++++++ .../qt/offroad/settings/lateral_panel.cc | 56 ++++++++++--- .../qt/offroad/settings/lateral_panel.h | 5 +- sunnypilot/selfdrive/car/interfaces.py | 28 +++++-- .../controls/lib/latcontrol_torque_ext.py | 6 +- .../lib/latcontrol_torque_ext_override.py | 34 ++++++++ sunnypilot/selfdrive/locationd/torqued_ext.py | 65 +++++++++++++++ 16 files changed, 414 insertions(+), 24 deletions(-) create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_custom_params.cc create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_custom_params.h create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_settings.cc create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_settings.h create mode 100644 sunnypilot/selfdrive/controls/lib/latcontrol_torque_ext_override.py create mode 100644 sunnypilot/selfdrive/locationd/torqued_ext.py diff --git a/common/params_keys.h b/common/params_keys.h index 0844fff2bf..11ec8da636 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -242,4 +242,13 @@ inline static std::unordered_map keys = { {"MapTargetVelocities", {CLEAR_ON_ONROAD_TRANSITION, STRING}}, {"SmartCruiseControlMap", {PERSISTENT | BACKUP, BOOL, "0"}}, {"SmartCruiseControlVision", {PERSISTENT | BACKUP, BOOL, "0"}}, + + // Torque lateral control custom params + {"CustomTorqueParams", {PERSISTENT | BACKUP , BOOL}}, + {"EnforceTorqueControl", {PERSISTENT | BACKUP, BOOL}}, + {"LiveTorqueParamsToggle", {PERSISTENT | BACKUP , BOOL}}, + {"LiveTorqueParamsRelaxedToggle", {PERSISTENT | BACKUP , BOOL}}, + {"TorqueParamsOverrideEnabled", {PERSISTENT | BACKUP, BOOL, "0"}}, + {"TorqueParamsOverrideFriction", {PERSISTENT | BACKUP, FLOAT, "0.1"}}, + {"TorqueParamsOverrideLatAccelFactor", {PERSISTENT | BACKUP, FLOAT, "2.5"}}, }; diff --git a/selfdrive/controls/lib/latcontrol_torque.py b/selfdrive/controls/lib/latcontrol_torque.py index ca9c3fde66..917fb233f4 100644 --- a/selfdrive/controls/lib/latcontrol_torque.py +++ b/selfdrive/controls/lib/latcontrol_torque.py @@ -48,6 +48,10 @@ class LatControlTorque(LatControl): self.lateral_accel_from_torque(-self.steer_max, self.torque_params)) def update(self, active, CS, VM, params, steer_limited_by_safety, desired_curvature, calibrated_pose, curvature_limited): + # Override torque params from extension + if self.extension.update_override_torque_params(self.torque_params): + self.update_limits() + pid_log = log.ControlsState.LateralTorqueState.new_message() if not active: output_torque = 0.0 diff --git a/selfdrive/locationd/torqued.py b/selfdrive/locationd/torqued.py index e0409957f5..57d53fdee3 100755 --- a/selfdrive/locationd/torqued.py +++ b/selfdrive/locationd/torqued.py @@ -11,6 +11,7 @@ from openpilot.common.filter_simple import FirstOrderFilter from openpilot.common.swaglog import cloudlog from openpilot.selfdrive.locationd.helpers import PointBuckets, ParameterEstimator, PoseCalibrator, Pose from openpilot.sunnypilot.livedelay.helpers import get_lat_delay +from openpilot.sunnypilot.selfdrive.locationd.torqued_ext import TorqueEstimatorExt HISTORY = 5 # secs POINTS_PER_BUCKET = 1500 @@ -50,9 +51,10 @@ class TorqueBuckets(PointBuckets): break -class TorqueEstimator(ParameterEstimator): +class TorqueEstimator(ParameterEstimator, TorqueEstimatorExt): def __init__(self, CP, decimated=False, track_all_points=False): - super().__init__() + ParameterEstimator.__init__(self) + TorqueEstimatorExt.__init__(self, CP) self.CP = CP self.hist_len = int(HISTORY / DT_MDL) self.lag = 0.0 @@ -82,6 +84,8 @@ class TorqueEstimator(ParameterEstimator): self.calibrator = PoseCalibrator() + TorqueEstimatorExt.initialize_custom_params(self, decimated) + self.reset() initial_params = { @@ -260,6 +264,8 @@ def main(demo=False): t = sm.logMonoTime[which] * 1e-9 estimator.handle_log(t, which, sm[which]) + TorqueEstimatorExt.update_use_params(estimator) + # 4Hz driven by livePose if sm.frame % 5 == 0: pm.send('liveTorqueParameters', estimator.get_msg(valid=sm.all_checks())) diff --git a/selfdrive/ui/sunnypilot/SConscript b/selfdrive/ui/sunnypilot/SConscript index 3f0e013d34..12c09c53f2 100644 --- a/selfdrive/ui/sunnypilot/SConscript +++ b/selfdrive/ui/sunnypilot/SConscript @@ -51,6 +51,8 @@ lateral_panel_qt_src = [ "sunnypilot/qt/offroad/settings/lateral/lane_change_settings.cc", "sunnypilot/qt/offroad/settings/lateral/mads_settings.cc", "sunnypilot/qt/offroad/settings/lateral/neural_network_lateral_control.cc", + "sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_custom_params.cc", + "sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_settings.cc", ] longitudinal_panel_qt_src = [ diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/neural_network_lateral_control.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/neural_network_lateral_control.cc index 0b66b83660..02ab810c57 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/neural_network_lateral_control.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/neural_network_lateral_control.cc @@ -10,14 +10,15 @@ NeuralNetworkLateralControl::NeuralNetworkLateralControl() : ParamControl("NeuralNetworkLateralControl", tr("Neural Network Lateral Control (NNLC)"), "", "") { setConfirmation(true, false); - updateToggle(); + updateToggle(offroad); } -void NeuralNetworkLateralControl::updateToggle() { +void NeuralNetworkLateralControl::updateToggle(bool _offroad) { QString statusInitText = "" + STATUS_CHECK_COMPATIBILITY + ""; QString notLoadedText = "" + STATUS_NOT_LOADED + ""; QString loadedText = "" + STATUS_LOADED + ""; + bool allowed = true; auto cp_bytes = params.get("CarParamsPersistent"); auto cp_sp_bytes = params.get("CarParamsSPPersistent"); if (!cp_bytes.empty() && !cp_sp_bytes.empty()) { @@ -31,7 +32,7 @@ void NeuralNetworkLateralControl::updateToggle() { if (CP.getSteerControlType() == cereal::CarParams::SteerControlType::ANGLE) { params.remove("NeuralNetworkLateralControl"); setDescription(nnffDescriptionBuilder(STATUS_NOT_AVAILABLE)); - setEnabled(false); + allowed = false; } else { QString nn_model_name = QString::fromStdString(CP_SP.getNeuralNetworkLateralControl().getModel().getName()); QString nn_fuzzy = CP_SP.getNeuralNetworkLateralControl().getFuzzyFingerprint() ? @@ -56,4 +57,11 @@ void NeuralNetworkLateralControl::updateToggle() { if (getDescription() != getBaseDescription()) { showDescription(); } + + bool enforce_torque_toggle = params.getBool("EnforceTorqueControl"); + setEnabled(_offroad && allowed && !enforce_torque_toggle); + + refresh(); + + offroad = _offroad; } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/neural_network_lateral_control.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/neural_network_lateral_control.h index df80fbf097..9e872b11e9 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/neural_network_lateral_control.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/neural_network_lateral_control.h @@ -20,10 +20,11 @@ public: NeuralNetworkLateralControl(); public slots: - void updateToggle(); + void updateToggle(bool _offroad); private: Params params; + bool offroad; // Status messages const QString STATUS_NOT_AVAILABLE = tr("NNLC is currently not available on this platform."); diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_custom_params.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_custom_params.cc new file mode 100644 index 0000000000..894fbc2ec4 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_custom_params.cc @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_custom_params.h" + +TorqueLateralControlCustomParams::TorqueLateralControlCustomParams(const QString ¶m, const QString &title, const QString &description, const QString &icon, QWidget *parent) + : ExpandableToggleRow(param, title, description, icon, parent) { + + QFrame *frame = new QFrame(this); + QGridLayout *frame_layout = new QGridLayout(); + frame->setLayout(frame_layout); + frame_layout->setSpacing(0); + + torqueLateralControlParamsOverride = new ParamControl( + "TorqueParamsOverrideEnabled", + tr("Manual Real-Time Tuning"), + tr("Enforces the torque lateral controller to use the fixed values instead of the learned values from Self-Tune. Enabling this toggle overrides Self-Tune values."), + "../assets/offroad/icon_blank.png", + this + ); + connect(torqueLateralControlParamsOverride, &ParamControl::toggleFlipped, this, &TorqueLateralControlCustomParams::refresh); + + torqueParamsOverrideLatAccelFactor = new OptionControlSP("TorqueParamsOverrideLatAccelFactor", tr("Lateral Acceleration Factor"), "", "", {1, 500}, 1, false, nullptr, true, false); + connect(torqueParamsOverrideLatAccelFactor, &OptionControlSP::updateLabels, this, &TorqueLateralControlCustomParams::refresh); + torqueParamsOverrideLatAccelFactor->setFixedWidth(280); + + torqueParamsOverrideFriction = new OptionControlSP("TorqueParamsOverrideFriction", tr("Friction"), "", "", {1, 100}, 1, false, nullptr, true, false); + connect(torqueParamsOverrideFriction, &OptionControlSP::updateLabels, this, &TorqueLateralControlCustomParams::refresh); + torqueParamsOverrideFriction->setFixedWidth(280); + + frame_layout->addWidget(torqueLateralControlParamsOverride, 0, 0, 1, 2); + QSpacerItem *spacer = new QSpacerItem(20, 40); + frame_layout->addItem(spacer, 1, 0, 1, 2); + frame_layout->addWidget(torqueParamsOverrideLatAccelFactor, 2, 0, Qt::AlignCenter); + frame_layout->addWidget(torqueParamsOverrideFriction, 2, 1, Qt::AlignCenter); + + addItem(frame); + + refresh(); +} + +void TorqueLateralControlCustomParams::refresh() { + bool torque_override_param = params.getBool("TorqueParamsOverrideEnabled"); + float laf_param = QString::fromStdString(params.get("TorqueParamsOverrideLatAccelFactor")).toFloat(); + const QString laf_unit = "m/s²"; + + float friction_param = QString::fromStdString(params.get("TorqueParamsOverrideFriction")).toFloat(); + + torqueParamsOverrideLatAccelFactor->setTitle(tr("Lateral Acceleration Factor") + "\n(" + (torque_override_param ? tr("Real-time and Offline") : tr("Offline Only")) + ")"); + torqueParamsOverrideFriction->setTitle(tr("Friction") + "\n(" + (torque_override_param ? tr("Real-time and Offline") : tr("Offline Only")) + ")"); + + torqueParamsOverrideLatAccelFactor->setLabel(QString::number(laf_param, 'f', 2) + " " + laf_unit); + torqueParamsOverrideFriction->setLabel(QString::number(friction_param, 'f', 2)); +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_custom_params.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_custom_params.h new file mode 100644 index 0000000000..8442bd0d48 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_custom_params.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/ui.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/expandable_row.h" + +class TorqueLateralControlCustomParams : public ExpandableToggleRow { + Q_OBJECT + +public: + TorqueLateralControlCustomParams(const QString ¶m, const QString &title, const QString &description, const QString &icon, QWidget *parent = nullptr); + void refresh(); + +private: + Params params; + ParamControl *torqueLateralControlParamsOverride; + OptionControlSP *torqueParamsOverrideFriction; + OptionControlSP *torqueParamsOverrideLatAccelFactor; +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_settings.cc new file mode 100644 index 0000000000..914ce7a939 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_settings.cc @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_settings.h" + +#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" + +TorqueLateralControlSettings::TorqueLateralControlSettings(QWidget *parent) : QWidget(parent) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(50, 20, 50, 20); + main_layout->setSpacing(20); + + // Back button + PanelBackButton *back = new PanelBackButton(); + connect(back, &QPushButton::clicked, [=]() { emit backPress(); }); + main_layout->addWidget(back, 0, Qt::AlignLeft); + + ListWidget *list = new ListWidget(this, false); + // param, title, desc, icon + std::vector> toggle_defs{ + { + "LiveTorqueParamsToggle", + tr("Self-Tune"), + tr("Enables self-tune for Torque lateral control for platforms that do not use Torque lateral control by default."), + "../assets/offroad/icon_blank.png", + }, + { + "LiveTorqueParamsRelaxedToggle", + tr("Less Restrict Settings for Self-Tune (Beta)"), + tr("Less strict settings when using Self-Tune. This allows torqued to be more forgiving when learning values."), + "../assets/offroad/icon_blank.png", + } + }; + + for (auto &[param, title, desc, icon] : toggle_defs) { + auto toggle = new ParamControlSP(param, title, desc, icon, this); + list->addItem(toggle); + toggles[param.toStdString()] = toggle; + } + + torqueLateralControlCustomParams = new TorqueLateralControlCustomParams( + "CustomTorqueParams", + tr("Enable Custom Tuning"), + tr("Enables custom tuning for Torque lateral control. Modifying Lateral Acceleration Factor and Friction below will override the offline values indicated in the YAML files within \"opendbc/car/torque_data\". " + "The values will also be used live when \"Manual Real-Time Tuning\" toggle is enabled."), + "../assets/offroad/icon_blank.png", + this); + list->addItem(torqueLateralControlCustomParams); + + QObject::connect(uiState(), &UIState::offroadTransition, this, &TorqueLateralControlSettings::updateToggles); + QObject::connect(toggles["LiveTorqueParamsToggle"], &ParamControlSP::toggleFlipped, [=](bool state) { + if (!state) { + params.remove("LiveTorqueParamsRelaxedToggle"); + toggles["LiveTorqueParamsRelaxedToggle"]->refresh(); + } + + updateToggles(offroad); + }); + + main_layout->addWidget(new ScrollViewSP(list, this)); +} + +void TorqueLateralControlSettings::showEvent(QShowEvent *event) { + updateToggles(offroad); +} + +void TorqueLateralControlSettings::updateToggles(bool _offroad) { + bool live_toggle = toggles["LiveTorqueParamsToggle"]->isToggled(); + + toggles["LiveTorqueParamsToggle"]->setEnabled(_offroad); + toggles["LiveTorqueParamsRelaxedToggle"]->setEnabled(_offroad && live_toggle); + + torqueLateralControlCustomParams->setEnabled(_offroad); + torqueLateralControlCustomParams->refresh(); + + offroad = _offroad; +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_settings.h new file mode 100644 index 0000000000..6254073dfe --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_settings.h @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/sunnypilot/ui.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_custom_params.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" + +class TorqueLateralControlSettings : public QWidget { + Q_OBJECT + +public: + explicit TorqueLateralControlSettings(QWidget *parent = nullptr); + + void showEvent(QShowEvent *event) override; + + signals: + void backPress(); + +public slots: + void updateToggles(bool _offroad); + +private: + Params params; + bool offroad; + std::map toggles; + + TorqueLateralControlCustomParams *torqueLateralControlCustomParams; +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral_panel.cc index 59636ca5a5..ac004e8856 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral_panel.cc @@ -75,6 +75,36 @@ LateralPanel::LateralPanel(SettingsWindowSP *parent) : QFrame(parent) { list->addItem(horizontal_line()); + // Customized Torque Lateral Control + torqueLateralControlToggle = new ParamControl( + "EnforceTorqueControl", + tr("Enforce Torque Lateral Control"), + tr("Enable this to enforce sunnypilot to steer with Torque lateral control."), + ""); + list->addItem(torqueLateralControlToggle); + + torqueLateralControlSettingsButton = new PushButtonSP(tr("Customize Params")); + torqueLateralControlSettingsButton->setObjectName("torque_btn"); + connect(torqueLateralControlSettingsButton, &QPushButton::clicked, [=]() { + sunnypilotScroller->setLastScrollPosition(); + main_layout->setCurrentWidget(torqueLateralControlWidget); + }); + QObject::connect(torqueLateralControlToggle, &ToggleControl::toggleFlipped, [=](bool state) { + torqueLateralControlSettingsButton->setEnabled(state); + nnlcToggle->updateToggle(offroad); + updateToggles(offroad); + }); + + torqueLateralControlWidget = new TorqueLateralControlSettings(this); + connect(torqueLateralControlWidget, &TorqueLateralControlSettings::backPress, [=]() { + sunnypilotScroller->restoreScrollPosition(); + main_layout->setCurrentWidget(sunnypilotScreen); + }); + list->addItem(torqueLateralControlSettingsButton); + + list->addItem(vertical_space(0)); + list->addItem(horizontal_line()); + // Neural Network Lateral Control nnlcToggle = new NeuralNetworkLateralControl(); list->addItem(nnlcToggle); @@ -86,12 +116,10 @@ LateralPanel::LateralPanel(SettingsWindowSP *parent) : QFrame(parent) { nnlcToggle->hideDescription(); } - nnlcToggle->updateToggle(); + nnlcToggle->updateToggle(offroad); + updateToggles(offroad); }); - toggleOffroadOnly = { - madsToggle, nnlcToggle, - }; QObject::connect(uiState(), &UIState::offroadTransition, this, &LateralPanel::updateToggles); sunnypilotScroller = new ScrollViewSP(list, this); @@ -100,6 +128,7 @@ LateralPanel::LateralPanel(SettingsWindowSP *parent) : QFrame(parent) { main_layout->addWidget(sunnypilotScreen); main_layout->addWidget(madsWidget); main_layout->addWidget(laneChangeWidget); + main_layout->addWidget(torqueLateralControlWidget); setStyleSheet(R"( #back_btn { @@ -120,7 +149,7 @@ LateralPanel::LateralPanel(SettingsWindowSP *parent) : QFrame(parent) { } void LateralPanel::showEvent(QShowEvent *event) { - nnlcToggle->updateToggle(); + nnlcToggle->updateToggle(offroad); updateToggles(offroad); } @@ -129,10 +158,7 @@ void LateralPanel::hideEvent(QHideEvent *event) { } void LateralPanel::updateToggles(bool _offroad) { - for (auto *toggle : toggleOffroadOnly) { - toggle->setEnabled(_offroad); - } - + bool torque_allowed = true; auto cp_bytes = params.get("CarParamsPersistent"); auto cp_sp_bytes = params.get("CarParamsSPPersistent"); if (!cp_bytes.empty() && !cp_sp_bytes.empty()) { @@ -148,12 +174,24 @@ void LateralPanel::updateToggles(bool _offroad) { } else { madsToggle->setDescription(descriptionBuilder(STATUS_MADS_SETTINGS_FULL_COMPATIBILITY, MADS_BASE_DESC)); } + + if (CP.getSteerControlType() == cereal::CarParams::SteerControlType::ANGLE) { + params.remove("EnforceTorqueControl"); + torque_allowed = false; + } } else { madsToggle->setDescription(descriptionBuilder(STATUS_MADS_CHECK_COMPATIBILITY, MADS_BASE_DESC)); + + params.remove("EnforceTorqueControl"); + torque_allowed = false; } + madsToggle->setEnabled(_offroad); madsSettingsButton->setEnabled(madsToggle->isToggled()); + torqueLateralControlToggle->setEnabled(_offroad && torque_allowed && !nnlcToggle->isToggled()); + torqueLateralControlSettingsButton->setEnabled(torqueLateralControlToggle->isToggled()); + blinkerPauseLateralSettings->refresh(); offroad = _offroad; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral_panel.h index 7b5e73fceb..88c4d401d0 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/lateral_panel.h @@ -15,6 +15,7 @@ #include "selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/mads_settings.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/neural_network_lateral_control.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/lane_change_settings.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/lateral/torque_lateral_control_settings.h" #include "selfdrive/ui/qt/util.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" #include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" @@ -35,7 +36,6 @@ private: QStackedLayout* main_layout = nullptr; QWidget* sunnypilotScreen = nullptr; ScrollViewSP *sunnypilotScroller = nullptr; - std::vector toggleOffroadOnly; bool offroad; ParamControl *madsToggle; @@ -45,6 +45,9 @@ private: LaneChangeSettings *laneChangeWidget = nullptr; NeuralNetworkLateralControl *nnlcToggle = nullptr; BlinkerPauseLateralSettings *blinkerPauseLateralSettings = nullptr; + ParamControl *torqueLateralControlToggle; + PushButtonSP *torqueLateralControlSettingsButton; + TorqueLateralControlSettings *torqueLateralControlWidget = nullptr; const QString MADS_BASE_DESC = tr("Enables independent engagements of Automatic Lane Centering (ALC) and Adaptive Cruise Control (ACC)."); diff --git a/sunnypilot/selfdrive/car/interfaces.py b/sunnypilot/selfdrive/car/interfaces.py index 55244caa57..ed0c11fb19 100644 --- a/sunnypilot/selfdrive/car/interfaces.py +++ b/sunnypilot/selfdrive/car/interfaces.py @@ -22,8 +22,18 @@ def log_fingerprint(CP: structs.CarParams) -> None: sentry.capture_fingerprint(CP.carFingerprint, CP.brand) -def _initialize_neural_network_lateral_control(CI: CarInterfaceBase, CP: structs.CarParams, CP_SP: structs.CarParamsSP, - params: Params = None, enabled: bool = False) -> None: +def _enforce_torque_lateral_control(CP: structs.CarParams, params: Params = None, enabled: bool = False) -> bool: + if params is None: + params = Params() + + if CP.steerControlType != structs.CarParams.SteerControlType.angle: + enabled = params.get_bool("EnforceTorqueControl") + + return enabled + + +def _initialize_neural_network_lateral_control(CP: structs.CarParams, CP_SP: structs.CarParamsSP, + params: Params = None, enabled: bool = False) -> bool: if params is None: params = Params() @@ -35,13 +45,12 @@ def _initialize_neural_network_lateral_control(CI: CarInterfaceBase, CP: structs if nnlc_model_name != "MOCK" and CP.steerControlType != structs.CarParams.SteerControlType.angle: enabled = params.get_bool("NeuralNetworkLateralControl") - if enabled: - CI.configure_torque_tune(CP.carFingerprint, CP.lateralTuning) - CP_SP.neuralNetworkLateralControl.model.path = nnlc_model_path CP_SP.neuralNetworkLateralControl.model.name = nnlc_model_name CP_SP.neuralNetworkLateralControl.fuzzyFingerprint = not exact_match + return enabled + def _initialize_intelligent_cruise_button_management(CP: structs.CarParams, CP_SP: structs.CarParamsSP, params: Params = None) -> None: if params is None: @@ -52,12 +61,19 @@ def _initialize_intelligent_cruise_button_management(CP: structs.CarParams, CP_S CP_SP.pcmCruiseSpeed = False +def _initialize_torque_lateral_control(CI: CarInterfaceBase, CP: structs.CarParams, enforce_torque: bool, nnlc_enabled: bool) -> None: + if nnlc_enabled or enforce_torque: + CI.configure_torque_tune(CP.carFingerprint, CP.lateralTuning) + + def setup_interfaces(CI: CarInterfaceBase, params: Params = None) -> None: CP = CI.CP CP_SP = CI.CP_SP - _initialize_neural_network_lateral_control(CI, CP, CP_SP, params) + enforce_torque = _enforce_torque_lateral_control(CP, params) + nnlc_enabled = _initialize_neural_network_lateral_control(CP, CP_SP, params) _initialize_intelligent_cruise_button_management(CP, CP_SP, params) + _initialize_torque_lateral_control(CI, CP, enforce_torque, nnlc_enabled) def initialize_params(params) -> list[dict[str, Any]]: diff --git a/sunnypilot/selfdrive/controls/lib/latcontrol_torque_ext.py b/sunnypilot/selfdrive/controls/lib/latcontrol_torque_ext.py index 6e134276e5..39525b3b8e 100644 --- a/sunnypilot/selfdrive/controls/lib/latcontrol_torque_ext.py +++ b/sunnypilot/selfdrive/controls/lib/latcontrol_torque_ext.py @@ -6,11 +6,13 @@ See the LICENSE.md file in the root directory for more details. """ from openpilot.sunnypilot.selfdrive.controls.lib.nnlc.nnlc import NeuralNetworkLateralControl +from openpilot.sunnypilot.selfdrive.controls.lib.latcontrol_torque_ext_override import LatControlTorqueExtOverride -class LatControlTorqueExt(NeuralNetworkLateralControl): +class LatControlTorqueExt(NeuralNetworkLateralControl, LatControlTorqueExtOverride): def __init__(self, lac_torque, CP, CP_SP, CI): - super().__init__(lac_torque, CP, CP_SP, CI) + NeuralNetworkLateralControl.__init__(self, lac_torque, CP, CP_SP, CI) + LatControlTorqueExtOverride.__init__(self, CP) def update(self, CS, VM, pid, params, ff, pid_log, setpoint, measurement, calibrated_pose, roll_compensation, desired_lateral_accel, actual_lateral_accel, lateral_accel_deadzone, gravity_adjusted_lateral_accel, diff --git a/sunnypilot/selfdrive/controls/lib/latcontrol_torque_ext_override.py b/sunnypilot/selfdrive/controls/lib/latcontrol_torque_ext_override.py new file mode 100644 index 0000000000..f07a7292c1 --- /dev/null +++ b/sunnypilot/selfdrive/controls/lib/latcontrol_torque_ext_override.py @@ -0,0 +1,34 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" + +from openpilot.common.params import Params + + +class LatControlTorqueExtOverride: + def __init__(self, CP): + self.CP = CP + self.params = Params() + self.enforce_torque_control_toggle = self.params.get_bool("EnforceTorqueControl") # only during init + self.torque_override_enabled = self.params.get_bool("TorqueParamsOverrideEnabled") + self.frame = -1 + + def update_override_torque_params(self, torque_params) -> bool: + if not self.enforce_torque_control_toggle: + return False + + self.frame += 1 + if self.frame % 300 == 0: + self.torque_override_enabled = self.params.get_bool("TorqueParamsOverrideEnabled") + + if not self.torque_override_enabled: + return False + + torque_params.latAccelFactor = float(self.params.get("TorqueParamsOverrideLatAccelFactor", return_default=True)) + torque_params.friction = float(self.params.get("TorqueParamsOverrideFriction", return_default=True)) + return True + + return False diff --git a/sunnypilot/selfdrive/locationd/torqued_ext.py b/sunnypilot/selfdrive/locationd/torqued_ext.py new file mode 100644 index 0000000000..084a82e941 --- /dev/null +++ b/sunnypilot/selfdrive/locationd/torqued_ext.py @@ -0,0 +1,65 @@ +""" +Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + +This file is part of sunnypilot and is licensed under the MIT License. +See the LICENSE.md file in the root directory for more details. +""" + +import numpy as np + +from cereal import car + +from openpilot.common.params import Params +from openpilot.common.realtime import DT_MDL +from openpilot.sunnypilot import PARAMS_UPDATE_PERIOD + +RELAXED_MIN_BUCKET_POINTS = np.array([0, 200, 300, 500, 500, 300, 200, 0]) + +ALLOWED_CARS = ['toyota', 'hyundai', 'rivian', 'honda'] + + + +class TorqueEstimatorExt: + def __init__(self, CP: car.CarParams): + self.CP = CP + self._params = Params() + self.frame = -1 + + self.enforce_torque_control_toggle = self._params.get_bool("EnforceTorqueControl") # only during init + self.use_params = self.CP.brand in ALLOWED_CARS and self.CP.lateralTuning.which() == 'torque' + self.use_live_torque_params = self._params.get_bool("LiveTorqueParamsToggle") + self.torque_override_enabled = self._params.get_bool("TorqueParamsOverrideEnabled") + self.min_bucket_points = RELAXED_MIN_BUCKET_POINTS + self.factor_sanity = 0.0 + self.friction_sanity = 0.0 + self.offline_latAccelFactor = 0.0 + self.offline_friction = 0.0 + + def initialize_custom_params(self, decimated=False): + self.update_use_params() + + if self.enforce_torque_control_toggle: + if self._params.get_bool("LiveTorqueParamsRelaxedToggle"): + self.min_bucket_points = RELAXED_MIN_BUCKET_POINTS / (10 if decimated else 1) + self.factor_sanity = 0.5 if decimated else 1.0 + self.friction_sanity = 0.8 if decimated else 1.0 + + if self._params.get_bool("CustomTorqueParams"): + self.offline_latAccelFactor = float(self._params.get("TorqueParamsOverrideLatAccelFactor", return_default=True)) + self.offline_friction = float(self._params.get("TorqueParamsOverrideFriction", return_default=True)) + + def _update_params(self): + if self.frame % int(PARAMS_UPDATE_PERIOD / DT_MDL) == 0: + self.use_live_torque_params = self._params.get_bool("LiveTorqueParamsToggle") + self.torque_override_enabled = self._params.get_bool("TorqueParamsOverrideEnabled") + + def update_use_params(self): + self._update_params() + + if self.enforce_torque_control_toggle: + if self.torque_override_enabled: + self.use_params = False + else: + self.use_params = self.use_live_torque_params + + self.frame += 1 From f28cea759d68670c655d901226456178a86c23f2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 6 Oct 2025 02:52:02 -0400 Subject: [PATCH 135/159] [bot] Update Python packages (#1250) Update Python packages Co-authored-by: github-actions[bot] --- docs/CARS.md | 9 ++++++--- opendbc_repo | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/CARS.md b/docs/CARS.md index dbc1dbcd74..25f84b389e 100644 --- a/docs/CARS.md +++ b/docs/CARS.md @@ -4,7 +4,7 @@ A supported vehicle is one that just works when you install a comma device. All supported cars provide a better experience than any stock system. Supported vehicles reference the US market unless otherwise specified. -# 334 Supported Cars +# 337 Supported Cars |Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|
Hardware Needed
 |Video|Setup Video| |---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:| @@ -83,7 +83,7 @@ A supported vehicle is one that just works when you install a comma device. All |Honda|Civic Hatchback 2017-18|Honda Sensing|openpilot available[1](#footnotes)|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Civic Hatchback 2019-21|All|openpilot available[1](#footnotes)|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Civic Hatchback 2022-24|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch B connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| -|Honda|Civic Hatchback Hybrid 2025|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch B connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| +|Honda|Civic Hatchback Hybrid 2025-26|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch B connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Civic Hatchback Hybrid (Europe only) 2023|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch B connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Civic Hybrid 2025|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch B connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Clarity 2018-21|Honda Sensing|openpilot|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Nidec connector + Honda Clarity Proxy Board
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| @@ -99,7 +99,9 @@ A supported vehicle is one that just works when you install a comma device. All |Honda|HR-V 2023-25|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch B connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Insight 2019-22|All|openpilot available[1](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Inspire 2018|All|openpilot available[1](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| +|Honda|N-Box 2018|All|openpilot available[1](#footnotes)|0 mph|11 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Odyssey 2018-20|Honda Sensing|openpilot|26 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Honda Nidec connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| +|Honda|Odyssey 2021-25|All|openpilot available[1](#footnotes)|0 mph|43 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Passport 2019-25|All|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Honda Nidec connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Pilot 2016-22|Honda Sensing|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Honda Nidec connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Honda|Pilot 2023-25|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Honda Bosch C connector
- 1 angled mount (8 degrees)
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| @@ -163,6 +165,7 @@ A supported vehicle is one that just works when you install a comma device. All |Kia|EV6 (without HDA II) 2022-24[6](#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 comma 3X
- 1 comma power v3
- 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 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Kia|Forte 2022-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 E connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| +|Kia|Forte Non-SCC 2019|No Smart Cruise Control (Non-SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Hyundai G connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Kia|K5 2021-24|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 A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Kia|K5 Hybrid 2020-22|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 A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Kia|K8 Hybrid (with HDA II) 2023[6](#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 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| @@ -259,7 +262,7 @@ A supported vehicle is one that just works when you install a comma device. All |Tesla[11](#footnotes)|Model 3 (with HW3) 2019-23[10](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Tesla A connector
- 1 USB-C coupler
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 long OBD-C cable (9.5 ft)
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Tesla[11](#footnotes)|Model 3 (with HW4) 2024-25[10](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Tesla B connector
- 1 USB-C coupler
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 long OBD-C cable (9.5 ft)
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Tesla[11](#footnotes)|Model Y (with HW3) 2020-23[10](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Tesla A connector
- 1 USB-C coupler
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 long OBD-C cable (9.5 ft)
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| -|Tesla[11](#footnotes)|Model Y (with HW4) 2024[10](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Tesla B connector
- 1 USB-C coupler
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 long OBD-C cable (9.5 ft)
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| +|Tesla[11](#footnotes)|Model Y (with HW4) 2024-25[10](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Tesla B connector
- 1 USB-C coupler
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 long OBD-C cable (9.5 ft)
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Toyota|Alphard 2019-20|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Toyota A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Toyota|Alphard Hybrid 2021|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
Parts- 1 Toyota A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| |Toyota|Avalon 2016|Toyota Safety Sense P|openpilot available[2](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
Parts- 1 Toyota A connector
- 1 comma 3X
- 1 comma power v3
- 1 harness box
- 1 mount
- 1 right angle OBD-C cable (1.5 ft)
Buy Here
||| diff --git a/opendbc_repo b/opendbc_repo index bf0aba991a..335e5da182 160000 --- a/opendbc_repo +++ b/opendbc_repo @@ -1 +1 @@ -Subproject commit bf0aba991acbe14dd164ddfc8cc272cebf794544 +Subproject commit 335e5da18219ebcb4d56ab81387b37f7adcae461 From aeaac2227411d041b7723cd8f448a78010d99bda Mon Sep 17 00:00:00 2001 From: DevTekVE Date: Tue, 7 Oct 2025 07:45:04 +0200 Subject: [PATCH 136/159] ci: refine PR search query to avoid querying whole github (#1330) * ci: refine PR search query to improve label handling in GitHub Action workflow - Replaced `label` with `search_query` for better flexibility. - Added support for multiple labels (`PR_LABEL` and `${PR_LABEL}-c3`). * ci: fix PR search query for proper label matching in workflow - Adjusted `label` query syntax to correctly handle multiple labels. * Update .github/workflows/sunnypilot-master-dev-prep.yaml --- .github/workflows/sunnypilot-master-dev-prep.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/sunnypilot-master-dev-prep.yaml b/.github/workflows/sunnypilot-master-dev-prep.yaml index 122755f2c4..4aafd4a4a4 100644 --- a/.github/workflows/sunnypilot-master-dev-prep.yaml +++ b/.github/workflows/sunnypilot-master-dev-prep.yaml @@ -118,8 +118,8 @@ jobs: run: | # Use GitHub API to get PRs with specific label, ordered by creation date PR_LIST=$(gh api graphql -f query=' - query($label:String!) { - search(query: $label, type:ISSUE, first:100) { + query($search_query:String!) { + search(query: $search_query, type:ISSUE, first:100) { nodes { ... on PullRequest { number @@ -149,7 +149,7 @@ jobs: } } } - }' -F label="is:pr is:open label:${PR_LABEL} draft:false sort:created-asc") + }' -F search_query="repo:${{ github.repository }} is:pr is:open label:${PR_LABEL},${PR_LABEL}-c3 draft:false sort:created-asc") PR_LIST=${PR_LIST//\'/} echo "PR_LIST=${PR_LIST}" >> $GITHUB_OUTPUT From 408d52d72ab06ca529afa317c107d96d58e9026c Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Tue, 7 Oct 2025 21:45:33 -0400 Subject: [PATCH 137/159] NNLC: ensure PID is always initialized properly (#1304) --- .../selfdrive/controls/lib/latcontrol_torque_ext_base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sunnypilot/selfdrive/controls/lib/latcontrol_torque_ext_base.py b/sunnypilot/selfdrive/controls/lib/latcontrol_torque_ext_base.py index 1965d50b51..609d2f78b6 100644 --- a/sunnypilot/selfdrive/controls/lib/latcontrol_torque_ext_base.py +++ b/sunnypilot/selfdrive/controls/lib/latcontrol_torque_ext_base.py @@ -58,7 +58,8 @@ class LatControlTorqueExtBase: self.torque_from_lateral_accel_in_torque_space = CI.torque_from_lateral_accel_in_torque_space() self._ff = 0.0 - self._pid = PIDController(0.0, 0.0, k_f=0.0) + self._pid = PIDController(self.torque_params.kp, self.torque_params.ki, + k_f=self.torque_params.kf) self._pid_log = None self._setpoint = 0.0 self._measurement = 0.0 From 0b826002e990129addfdd9acdaa9ca538781c84f Mon Sep 17 00:00:00 2001 From: Nayan Date: Tue, 7 Oct 2025 22:44:27 -0400 Subject: [PATCH 138/159] UI: Expandable Row - Fix margins (#1324) Expandable Row - Fix margins Co-authored-by: Jason Wen --- selfdrive/ui/sunnypilot/qt/widgets/expandable_row.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/ui/sunnypilot/qt/widgets/expandable_row.cc b/selfdrive/ui/sunnypilot/qt/widgets/expandable_row.cc index b918938d11..b22684a295 100644 --- a/selfdrive/ui/sunnypilot/qt/widgets/expandable_row.cc +++ b/selfdrive/ui/sunnypilot/qt/widgets/expandable_row.cc @@ -14,10 +14,10 @@ ExpandableToggleRow::ExpandableToggleRow(const QString ¶m, const QString &ti QObject::connect(this, &ExpandableToggleRow::toggleFlipped, this, &ExpandableToggleRow::toggleClicked); collapsibleWidget = new QFrame(this); - collapsibleWidget->setContentsMargins(0, 0, 0, 0); collapsibleWidget->setVisible(false); QVBoxLayout *collapsible_layout = new QVBoxLayout(); collapsibleWidget->setLayout(collapsible_layout); + collapsible_layout->setContentsMargins(0, 0, 0, 0); list = new ListWidgetSP(this, false); From 8050c56a436a27cd65b04308e53d944feef85988 Mon Sep 17 00:00:00 2001 From: Nayan Date: Tue, 7 Oct 2025 23:24:18 -0400 Subject: [PATCH 139/159] UI: OptionControlSP - Fix Inline Spacer (#1325) OptionControlSP - Fix Inline Spacer issue!! Co-authored-by: Jason Wen --- selfdrive/ui/sunnypilot/qt/widgets/controls.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/selfdrive/ui/sunnypilot/qt/widgets/controls.h b/selfdrive/ui/sunnypilot/qt/widgets/controls.h index e9e1e4bb85..e111ce2fb5 100644 --- a/selfdrive/ui/sunnypilot/qt/widgets/controls.h +++ b/selfdrive/ui/sunnypilot/qt/widgets/controls.h @@ -545,10 +545,8 @@ public: main_layout->removeWidget(title_label); hlayout->addWidget(title_label, 1); } - if (spacingItem != nullptr && main_layout->indexOf(spacingItem) != -1) { - main_layout->removeItem(spacingItem); - spacingItem = nullptr; - } + main_layout->removeItem(spacingItem); + spacingItem = nullptr; } label.setStyleSheet(label_enabled_style); From 014baf8e909af06cce71b718b00c20291ccf0577 Mon Sep 17 00:00:00 2001 From: Nayan Date: Wed, 8 Oct 2025 12:05:06 -0400 Subject: [PATCH 140/159] UI: Make Always Offroad more accessible (#1327) * UI: Make Always Offroad more accessible * conditional - based on offroad * no need to delete * account for always offroad --------- Co-authored-by: Jason Wen --- .../qt/offroad/settings/device_panel.cc | 17 ++++++++++++----- .../qt/offroad/settings/device_panel.h | 2 ++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.cc index 7e3d18bd81..d61630112b 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.cc @@ -80,7 +80,7 @@ DevicePanelSP::DevicePanelSP(SettingsWindowSP *parent) : DevicePanel(parent) { connect(maxTimeOffroad, &OptionControlSP::updateLabels, maxTimeOffroad, &MaxTimeOffroad::refresh); addItem(maxTimeOffroad); - toggleDeviceBootMode = new ButtonParamControlSP("DeviceBootMode", tr("Wake-Up Behavior"), "", "", {"Default", "Offroad"}, 375, true); + toggleDeviceBootMode = new ButtonParamControlSP("DeviceBootMode", tr("Wake-Up Behavior"), "", "", {"Default", "Offroad"}, 375, true); addItem(toggleDeviceBootMode); connect(toggleDeviceBootMode, &ButtonParamControlSP::buttonClicked, this, [=](int index) { @@ -129,9 +129,8 @@ DevicePanelSP::DevicePanelSP(SettingsWindowSP *parent) : DevicePanel(parent) { offroadBtn->setFixedWidth(power_layout->sizeHint().width()); QObject::connect(offroadBtn, &PushButtonSP::clicked, this, &DevicePanelSP::setOffroadMode); - QVBoxLayout *power_group_layout = new QVBoxLayout(); + power_group_layout = new QVBoxLayout(); power_group_layout->setSpacing(25); - power_group_layout->addWidget(offroadBtn, 0, Qt::AlignHCenter); power_group_layout->addLayout(power_layout); addItem(power_group_layout); @@ -143,7 +142,7 @@ DevicePanelSP::DevicePanelSP(SettingsWindowSP *parent) : DevicePanel(parent) { buttons["quietModeBtn"], }; - QObject::connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { + QObject::connect(uiState(), &UIState::offroadTransition, [=](bool _offroad) { for (auto btn : findChildren()) { bool always_enabled = std::find(always_enabled_btns.begin(), always_enabled_btns.end(), btn) != always_enabled_btns.end(); @@ -151,6 +150,8 @@ DevicePanelSP::DevicePanelSP(SettingsWindowSP *parent) : DevicePanel(parent) { btn->setEnabled(offroad); } } + offroad = _offroad; + updateState(); }); } @@ -201,7 +202,7 @@ void DevicePanelSP::updateState() { } bool offroad_mode_param = params.getBool("OffroadMode"); - offroadBtn->setText(offroad_mode_param ? tr("Exit Always Offroad") : tr("Always Offroad")); + offroadBtn->setText(offroad_mode_param ? tr("Exit Always Offroad") : tr("Enable Always Offroad")); offroadBtn->setStyleSheet(offroad_mode_param ? alwaysOffroadStyle : autoOffroadStyle); DeviceSleepModeStatus currStatus = DeviceSleepModeStatus::DEFAULT; @@ -216,4 +217,10 @@ void DevicePanelSP::updateState() { } else { interactivityTimeout->setLabel(timeoutValue + "s"); } + + if (offroad and not offroad_mode_param) { + power_group_layout->insertWidget(0, offroadBtn, 0, Qt::AlignHCenter); + } else { + AddWidgetAt(0, offroadBtn); + } } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.h index 899a942dae..1e86e72014 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.h @@ -34,6 +34,8 @@ private: ButtonParamControlSP *toggleDeviceBootMode; Brightness *brightness; OptionControlSP *interactivityTimeout; + QVBoxLayout *power_group_layout; + bool offroad; const QString alwaysOffroadStyle = R"( PushButtonSP { From a85f3ce11c38122674eda611c72e266df0b24048 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Wed, 8 Oct 2025 13:03:15 -0400 Subject: [PATCH 141/159] Device: Onroad Uploads button (#1332) --- common/params_keys.h | 1 + .../ui/sunnypilot/qt/offroad/settings/device_panel.cc | 4 ++++ system/manager/process_config.py | 8 +++++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/common/params_keys.h b/common/params_keys.h index 11ec8da636..b950f43341 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -162,6 +162,7 @@ inline static std::unordered_map keys = { {"OnroadScreenOffBrightness", {PERSISTENT | BACKUP, INT, "100"}}, {"OnroadScreenOffControl", {PERSISTENT | BACKUP, BOOL}}, {"OnroadScreenOffTimer", {PERSISTENT | BACKUP, INT, "0"}}, + {"OnroadUploads", {PERSISTENT | BACKUP, BOOL, "1"}}, {"QuickBootToggle", {PERSISTENT | BACKUP, BOOL, "0"}}, {"QuietMode", {PERSISTENT | BACKUP, BOOL, "0"}}, {"RainbowMode", {PERSISTENT | BACKUP, BOOL, "0"}}, diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.cc index d61630112b..b926960783 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.cc @@ -23,6 +23,7 @@ DevicePanelSP::DevicePanelSP(SettingsWindowSP *parent) : DevicePanel(parent) { {"regulatoryBtn", tr("Regulatory"), ""}, {"translateBtn", tr("Language"), ""}, {"resetParams", tr("Reset Settings"), ""}, + {"onroadUploadsBtn", tr("Onroad Uploads"), "OnroadUploads"} }; int row = 0, col = 0; @@ -75,6 +76,8 @@ DevicePanelSP::DevicePanelSP(SettingsWindowSP *parent) : DevicePanel(parent) { connect(buttons["resetParams"], &PushButtonSP::clicked, this, &DevicePanelSP::resetSettings); + connect(buttons["onroadUploadsBtn"], &PushButtonSP::clicked, buttons["onroadUploadsBtn"], &PushButtonSP::updateButton); + // Max Time Offroad maxTimeOffroad = new MaxTimeOffroad(); connect(maxTimeOffroad, &OptionControlSP::updateLabels, maxTimeOffroad, &MaxTimeOffroad::refresh); @@ -140,6 +143,7 @@ DevicePanelSP::DevicePanelSP(SettingsWindowSP *parent) : DevicePanel(parent) { poweroffBtn, offroadBtn, buttons["quietModeBtn"], + buttons["onroadUploadsBtn"], }; QObject::connect(uiState(), &UIState::offroadTransition, [=](bool _offroad) { diff --git a/system/manager/process_config.py b/system/manager/process_config.py index b1a2fa6e13..c5f20e511b 100644 --- a/system/manager/process_config.py +++ b/system/manager/process_config.py @@ -95,6 +95,12 @@ def is_stock_model(started, params, CP: car.CarParams) -> bool: def mapd_ready(started: bool, params: Params, CP: car.CarParams) -> bool: return bool(os.path.exists(Paths.mapd_root())) +def uploader_ready(started: bool, params: Params, CP: car.CarParams) -> bool: + if not params.get_bool("OnroadUploads"): + return only_offroad(started, params, CP) + + return always_run(started, params, CP) + def or_(*fns): return lambda *args: operator.or_(*(fn(*args) for fn in fns)) @@ -145,7 +151,7 @@ procs = [ PythonProcess("hardwared", "system.hardware.hardwared", always_run), PythonProcess("tombstoned", "system.tombstoned", always_run, enabled=not PC), PythonProcess("updated", "system.updated.updated", only_offroad, enabled=not PC), - PythonProcess("uploader", "system.loggerd.uploader", always_run), + PythonProcess("uploader", "system.loggerd.uploader", uploader_ready), PythonProcess("statsd", "system.statsd", always_run), PythonProcess("feedbackd", "selfdrive.ui.feedback.feedbackd", only_onroad), From 517020ffb6b6f9443360e9bb55c4dcc680e22e32 Mon Sep 17 00:00:00 2001 From: Nayan Date: Wed, 8 Oct 2025 13:51:31 -0400 Subject: [PATCH 142/159] UI: Move Brightness & Interactivity Timeout to Display Panel (#1326) * UI: Move Brightness & Interactivity Timeout to Display Panel * why Qt.. WHYY --------- Co-authored-by: Jason Wen --- .../qt/offroad/settings/brightness.cc | 4 +-- .../qt/offroad/settings/device_panel.cc | 23 ----------------- .../qt/offroad/settings/device_panel.h | 3 --- .../display/onroad_screen_brightness.cc | 1 + .../qt/offroad/settings/display_panel.cc | 25 +++++++++++++++++++ .../qt/offroad/settings/display_panel.h | 3 +++ 6 files changed, 31 insertions(+), 28 deletions(-) diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/brightness.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/brightness.cc index ffd3ce1d8b..e9bd13485a 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/brightness.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/brightness.cc @@ -25,8 +25,8 @@ const QMap Brightness::brightness_options = { Brightness::Brightness() : OptionControlSP( "Brightness", - tr("Brightness"), - tr("Overrides the brightness of the device."), + tr("Global Brightness"), + tr("Overrides the brightness of the device. This applies to both onroad and offroad screens. "), "../assets/offroad/icon_blank.png", {0, 11}, 1, true, &brightness_options) { diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.cc index b926960783..43e6067451 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.cc @@ -91,22 +91,6 @@ DevicePanelSP::DevicePanelSP(SettingsWindowSP *parent) : DevicePanel(parent) { updateState(); }); - interactivityTimeout = new OptionControlSP("InteractivityTimeout", tr("Interactivity Timeout"), - tr("Apply a custom timeout for settings UI." - "\nThis is the time after which settings UI closes automatically if user is not interacting with the screen."), - "", {0, 120}, 10, true, nullptr, false); - - connect(interactivityTimeout, &OptionControlSP::updateLabels, [=]() { - updateState(); - }); - - addItem(interactivityTimeout); - - // Brightness - brightness = new Brightness(); - connect(brightness, &OptionControlSP::updateLabels, brightness, &Brightness::refresh); - addItem(brightness); - addItem(device_grid_layout); // offroad mode and power buttons @@ -215,13 +199,6 @@ void DevicePanelSP::updateState() { } toggleDeviceBootMode->setDescription(deviceSleepModeDescription(currStatus)); - QString timeoutValue = QString::fromStdString(params.get("InteractivityTimeout")); - if (timeoutValue == "0" || timeoutValue.isEmpty()) { - interactivityTimeout->setLabel("Default"); - } else { - interactivityTimeout->setLabel(timeoutValue + "s"); - } - if (offroad and not offroad_mode_param) { power_group_layout->insertWidget(0, offroadBtn, 0, Qt::AlignHCenter); } else { diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.h index 1e86e72014..ce4acfc7cf 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.h @@ -8,7 +8,6 @@ #pragma once #include "selfdrive/ui/sunnypilot/qt/offroad/settings/max_time_offroad.h" -#include "selfdrive/ui/sunnypilot/qt/offroad/settings/brightness.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" #include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" @@ -32,8 +31,6 @@ private: PushButtonSP *offroadBtn; MaxTimeOffroad *maxTimeOffroad; ButtonParamControlSP *toggleDeviceBootMode; - Brightness *brightness; - OptionControlSP *interactivityTimeout; QVBoxLayout *power_group_layout; bool offroad; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.cc index 3e9dc427bf..8833ffa898 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.cc @@ -15,6 +15,7 @@ OnroadScreenBrightnessControl::OnroadScreenBrightnessControl(const QString ¶ auto *mainFrameLayout = new QGridLayout(); mainFrame->setLayout(mainFrameLayout); mainFrameLayout->setSpacing(0); + mainFrameLayout->setContentsMargins(0, 0, 0, 0); onroadScreenOffTimer = new OptionControlSP( "OnroadScreenOffTimer", diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc index b441021ff3..274e28cf82 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.cc @@ -24,6 +24,24 @@ DisplayPanel::DisplayPanel(QWidget *parent) : QWidget(parent) { "", this); list->addItem(onroadScreenBrightnessControl); + list->addItem(horizontal_line()); + + // Global Brightness + brightness = new Brightness(); + connect(brightness, &OptionControlSP::updateLabels, brightness, &Brightness::refresh); + list->addItem(brightness); + list->addItem(horizontal_line()); + + // Interactivity Timeout + interactivityTimeout = new OptionControlSP("InteractivityTimeout", tr("Interactivity Timeout"), + tr("Apply a custom timeout for settings UI." + "\nThis is the time after which settings UI closes automatically if user is not interacting with the screen."), + "", {0, 120}, 10, true, nullptr, false); + + connect(interactivityTimeout, &OptionControlSP::updateLabels, [=]() { + refresh(); + }); + list->addItem(interactivityTimeout); sunnypilotScroller = new ScrollViewSP(list, this); vlayout->addWidget(sunnypilotScroller); @@ -37,4 +55,11 @@ void DisplayPanel::showEvent(QShowEvent *event) { void DisplayPanel::refresh() { onroadScreenBrightnessControl->refresh(); + + QString timeoutValue = QString::fromStdString(params.get("InteractivityTimeout")); + if (timeoutValue == "0" || timeoutValue.isEmpty()) { + interactivityTimeout->setLabel("Default"); + } else { + interactivityTimeout->setLabel(timeoutValue + "s"); + } } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h index 1714c8a436..69b440c9d3 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/display_panel.h @@ -7,6 +7,7 @@ #pragma once +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/brightness.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/display/onroad_screen_brightness.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" #include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" @@ -25,4 +26,6 @@ private: ScrollViewSP *sunnypilotScroller = nullptr; Params params; OnroadScreenBrightnessControl *onroadScreenBrightnessControl = nullptr; + Brightness *brightness; + OptionControlSP *interactivityTimeout; }; From e8a39c4a74d8f2de8f394ee07366a9883ecf552d Mon Sep 17 00:00:00 2001 From: DevTekVE Date: Wed, 8 Oct 2025 21:01:33 +0200 Subject: [PATCH 143/159] Reapply "sunnylink: enhanced param keys fetch with data type" (#1317) Reapply "sunnylink: enhanced param keys fetch with data type" (#1316)" This reverts commit 282a8b093ddb8f611d71bfee7bcde9e2e3281ee2. Co-authored-by: Jason Wen --- sunnypilot/sunnylink/athena/sunnylinkd.py | 19 ++++++++++++++++++- sunnypilot/sunnylink/utils.py | 12 +++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/sunnypilot/sunnylink/athena/sunnylinkd.py b/sunnypilot/sunnylink/athena/sunnylinkd.py index 25a77c367b..d1b38d656f 100755 --- a/sunnypilot/sunnylink/athena/sunnylinkd.py +++ b/sunnypilot/sunnylink/athena/sunnylinkd.py @@ -178,12 +178,29 @@ def getParamsAllKeys() -> list[str]: return keys +@dispatcher.add_method +def getParamsAllKeysV1() -> dict[str, str]: + available_keys: list[str] = [k.decode('utf-8') for k in Params().all_keys()] + + params_dict: dict[str, list[dict[str, str | bool | int | None]]] = {"params": []} + for key in available_keys: + value = get_param_as_byte(key, get_default=True) + params_dict["params"].append({ + "key": key, + "type": int(params.get_type(key).value), + "default_value": base64.b64encode(value).decode('utf-8') if value else None, + }) + + return {"keys": json.dumps(params_dict.get("params", []))} + + @dispatcher.add_method def getParams(params_keys: list[str], compression: bool = False) -> str | dict[str, str]: params = Params() + available_keys: list[str] = [k.decode('utf-8') for k in Params().all_keys()] try: - param_keys_validated = [key for key in params_keys if key in getParamsAllKeys()] + param_keys_validated = [key for key in params_keys if key in available_keys] params_dict: dict[str, list[dict[str, str | bool | int]]] = {"params": []} for key in param_keys_validated: value = get_param_as_byte(key) diff --git a/sunnypilot/sunnylink/utils.py b/sunnypilot/sunnylink/utils.py index 91c0788795..585e460e9c 100644 --- a/sunnypilot/sunnylink/utils.py +++ b/sunnypilot/sunnylink/utils.py @@ -60,14 +60,20 @@ def get_api_token(): print(f"API Token: {token}") -def get_param_as_byte(param_name: str, params=None) -> bytes | None: +def get_param_as_byte(param_name: str, params=None, get_default=False) -> bytes | None: """Get a parameter as bytes. Returns None if the parameter does not exist.""" - params = params or Params() # Use existing Params instance if provided - param = params.get(param_name) + params = params or Params() + param = params.get(param_name) if not get_default else params.get_default_value(param_name) + if param is None: return None param_type = params.get_type(param_name) + return _to_bytes(param, param_type) + + +def _to_bytes(param: bytes, param_type: ParamKeyType) -> bytes | None: + """Convert a parameter value to bytes based on its type.""" if param_type == ParamKeyType.BYTES: return bytes(param) elif param_type == ParamKeyType.JSON: From f653566803c3a299977d273b0d127872d6bbf34f Mon Sep 17 00:00:00 2001 From: Kumar <36933347+rav4kumar@users.noreply.github.com> Date: Wed, 8 Oct 2025 14:39:14 -0700 Subject: [PATCH 144/159] mapd: Bump version `v1.11.0` -> `v1.12.0` (#1288) v1.12.0 Co-authored-by: Jason Wen --- third_party/mapd_pfeiferj/mapd | Bin 9371832 -> 9371832 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/third_party/mapd_pfeiferj/mapd b/third_party/mapd_pfeiferj/mapd index eb2372ceedb336ebe967067042d4c37c2204b71d..c8b50b0791d53427e32c287622e90be2dd2423f4 100755 GIT binary patch delta 1415289 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�|OqPqqrlDVHV>=J%Xo<3Xj52bF^^ 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%0DcOu$xR=AEo|YHfUcTq0+e8tmJ+P^Gbz*_ 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 z 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∓wl8dQFU z9>y~~6Ie<4ZF@g^FwsvRct-`*7Q#H%(wxsR*f3oUg4lG^FGQ&i7z_;YSWP^QxJSWa zaB!zLU1XB3{dwg(g~fq%bt}B4W1++q;)yjV8&8b<2T#mS;E9|@>FR#V;1A&23DOqF z49?dEmlCH!OGr1+5Y+CKq|N~1)(v_^vPrwlrs?W2h~3PJ-P4hefTw}+1Rs@>;CxKn z4)8UQhv^4e$DXid>vnp@TyIt<8tq$grkuXs3Y8X;qG=9%fre{+m@K1!c~ZNLy; zu8Hd}WtTG`p)1EdG{*(B6+&!+;SID*SB>B`6;L1KrPUnFF|{!SlBR6DD8adz$h&}q zSsb@_sdZsdUm>Mqj~n!=iOvZuLUcY#q49dK?%-?7s&8n;z~N0VDWu?f#VzU z$Jz?2fIUMmpm50`dk?}HS?THx>%OUX#v^;L!3{2B?e~`cPj`3d5_-LJ67?wb$i31*iOpXm!zvB z5Sw61?@W|U>75Gk@#?Y7+E|lXZasEsx~e@Y#w#Cgm9cOEyvcI^l2S}lNpRmw?~8!x z1xsWQg4Pg>kpB=Cqxdp-%`&XS(@)z&++mQmicvCy&EmVfW@dt}tE8iuby>RV2cM*> z>;GB^HwUeNap9lZg|Zj@NaAk;@;zdEpfVzEK#?;bU0nyU$&+`YvjFS>hL_etg0t%t zmiN9&O?~aFOvr=1JT+LAN_)fw+y3g!jYhlCL(HQ@y&m8IW*J$e)pH_1zc7yl=ZB62*i)4Ujh^_DBcoPPu?0LCy? z(WQ5;T|*ZWyab*F{X51Md{l4cjU{Elhjg?GZcJBSSiB+mtoM&7{Q?Yep3Cd4<~r6_ zz4LViY9`fk@c%xDB~wYLyOul!S_8xTf_KWfl(_3b?po6S7XGj^)d5|Eb|Wkn=Z~ZU z)$@md`T!85=V%h%)tBa9N_{sQUiygthYGc5anU8qK-tCsK>1Lf=9wbq45Q-uE? zZRY}KQ}zD;HDfr;IVU3uAxAeVX+%*j4XH#i6{QPCQFQq>m4v|=6qPQc)X_zzdrCEx z5{aRkN{mv`R~lVhx(>ON)coJi-s_pOW;c|6-~W2OKC@YSJ@51EwbyO0z4qSf;btGS zPha=WzJ}`LfaUAnN5MSC;p&RCzkJ=B1w(uMYmcAEBJ?efl|QwcJkr?IP)o`n#g(RJ@giG4|cb0loXsXf-35O<->Jl*!+SNEcZQx z>;1KVeq+DuuGWK(AZ{R)w zaM4JrH{dMKT^s;73oU#z3BJkZ+K=zjU@m1Wg4Ut7JUTipKV&x1l4sWS)?UTSj{sH+ zgOWSb%}e|{X2J3InZ`yfK1hP+a*E{no~#cUJEPU81f?T;8BrsNxFpN`K52I$#Cs<tVEKvHMjYlAJqKL%|=n#FX;p2Hulq$U1{ITdsZn!{*w)5hv17T=Ffty^V}^Jk@-GQiq`9{e#^ z1JuGJ*^&WXSs5X}z=iLL#C1d3vOhf`IgI_vOG2TBmvU{gW^UpJvhaFhS8*47yblar zBtP;CUvRVSkXzDA0?kFvGwG(T1HKH~QRp?KIdH4x4qn9_N;C$IK$aW#vbN81KWnvW z=Fd(y$2j1RG58Aoh!o6+KO}^XWBTzxN>b;7bDsUk2-Br>&exdU>z%^NPZ`m#vS@=>wM%zXEmQ-!8W- zz%710J#H>^octW4?I`kT^5B1m&E)2J09l1yAjT~M~H{$_o8`c$@^U-xk z!S(IjPZ@D3t66Q2GEfVgU44dM!CDmhE&uIt8nKV@rr_mt^N<71#^6fyBvNoI3+}&$ zOByr{O-7kl8BS^!M`PJB>iqwj)WVRBk5+rjXtO0LZ_iF z@^5K%xwS4pv)uoIYo_@*Q8qW-ta7rrFX(Ub($p!HH&{?xEafSRb_x#29BE?UdVxLCE0YIYr^mrPjxH ziTenxK{9r5%WW*cEuBZXt;NMfOpb`~4Msarz5gZ;{yGaTAZ{jl5=psr!K-aMtH)mW zdb()>H+bydI^3Bamv1QfKg}7U!gw_}(dkoJI}M|TbI?1n-G40$caff$XRL3Xi0h7e zqhQg`3Lf-=baR~J+j-awLW7ZV->5EK04-H6k$Fghj2#OT&lQhp-0_Wc)159}53hi$ z(g~!x*+G0@UAu!geeI{*iYQE6y_PWqgtKr$i}Q3+$-zD05Vl*w+r)i^enfI`4|PqB z28Y|OKHSQG)mF*Ebe=#?dS<@xxpmpjhICDKf|2JQj)7;0F`>uHdLW7uXSj=6-=7ke+=%y1ZO*fni9 z?GsyN6k6ZzByJvBf@EkczUi%^Y4!xEZF%5$&Bsr$Rqm%XZ0Yly;?I}t^v9nw zJ{#SrQ#Opg&biRR!3Kx1*829Bu|eXG)f`?ih?kwi+kt7F^;{n#b>kb0$oPsD5gmyR zMQ+6(xubH{XD&}SA3EF#q`w1AL(2WVhJR@ldYZ_W(c5SNYT!(5<=gV77w08_zW^Mw zd9sZ3YfvdtFr!Ebp$=cu^rL>LH*(KM#||>QIK8}FS1T2k&`diXkHX+(79QQgR>4gz zcsg;9AqlVXPNl-cS*xkbE7MInqgk!X&yeD6v=k|!l_iuC_cN04D_eOJ%36CR?sp&M z<=Qjlf0S+xhpVm3AEcL7KmD5|w=-O?E+0Z<8`K#EFBuC0bvf(fbkoss_$+MXs{CTM z>hNjS;hTti5Iuz+MefO;?$2?>D?H9wm2NHs9P^IPnE4p&A}`-#tKf4jcr$UkQO$3e zt3WPzj;%D>on(KKZbmrV`lLSu9f>Ng2QIhZo*-@E*Dtds z-7I#vuZXQ=@mu^u!Eame2I6)~{6;^E-C=gU75;EY+odwVtDKx@gw0W?3sUZfmOG8O z7tz~j;YQ}E&K$^URXcEN%=Mp?>qzq}jHIw_VXNQ`7JR@aF6B^r z)COfSZaWhRudQ`h281$#Em@mxcEN4$HzvmP#$W&%h7|mh1wT#PBJ?qOAN2#8bEd!8 zbb6sbgq2%hUAR`uS(k2(AD(o0E9rkneU2UP`>S*_+~F3Hei2%Sl-pA8D4qH}4G79b z!;m}Eu^<4>_=cNyfLqvh;tA4APQ1ic!R@WXUlI2s`UCAi(wOW0kKtZU#Qi2yt`ai7 zO*fA_SzPZ2zX58-R>7xR@Y%#&jIKgMkPDt>vsgO`vmxEQ?rLu;$BB9&{Cve;cg3Xvo=%h9PW2NQvU_K6GH`0w%~R@@r*Uopt1F(^txSFkUAGX{FiJOD`oQV5{O{+)S066#ibaN!&7Phc0 z#!wtCallVn@SnsT@G~6?Is{1}R&F25mG0TQ(*1#n3E@irE1??(7oed?J?0}e5<+W< z`vYZ^(c>Y>;#}KK)O^HmfEo_+!RBX%cYw9UY(x4i)DtO}x37BKM~I6r;LmdOHj*sX zv1jB1zdp;Y=d)8-`d&t-!ceC)M)vKeV^r zZn!;n+S{35(#^w87Hg+8*a3I54)3i~nkL-tR16ZZm=AYZ%S>%%)IG>${~z#+U!iVx9Rq-SG*B^*Zc|P$cc~Rg0Tdq5@VKi_q zUHW1xbLYby2G2}O2o)0dEP4rvZ|(@OBv4ZFccz=)9pC0*;|+`0s&70g>=l*JS|Wdu z1SmN4EDeBje@!>_MkI@N$}cP*L0yr8WqrCh{0ec!=smRSE2g)duBzV|GLVZWFH*C2 zrJGE^TFZA}Bz<7@ZAoxix(}{HTw^3*z>-umhL%HLDl3h&1YW=6jf=8>XOsaq=A~u^ zT5RFA7p@$?{9q#szKqBl(M?E)89EU=C(w>&?`ClCfM;Se8@-7%Cl0aP^zA%kjSfRH z!K*nD7f)9?U~ew+4<L19nt1G1MFd%f#$JMJO%j&NyH_b=|NLhtFlJ-197VEOB?D zr_szEbXBF3@C->#)LZHIfzo^GG>SMnPZnP?JHkNeqM=8qEhI+E}XTUlwN11^C}kWU!P zsml(9&3jH3e@J?{cwWs`xl=566LEEZ;g1(~(V}tfJ0{VrUA%s?GB_(~7Bc*uCdBUj zQ8VOm63u>KuCzPz5> zNctV<52WB4JS9R1)!of=6zBwWEXt=&71(-ZR`@w`P27%r3Zr4u+yQsOpdY#zDY&i$ zKS|t+Xc>A73AoULciVcUBdU_xVczkOtgzpc{@_0ti6P;7bNnqW_%L ziNlS-knl$JH1k$q}^AO$zF;6mb_MX#ed z$aOfw7PfL)7;!lBu&{Xrt`uUg^;&|#duSC>@L?AGD{<9ADMG+oWvDmT+|+Y#3_l;+Qe_DsB3#=9JpQv_!%94%YtkhU*l--{eh zJIlF}xDiM~JTYhsm^vLO@6x;+5jH88S_*C?YMs9ibGg`g%)#`u zm~V+IL%Y#VRM0lr`n7o6UyQDEk(n*RrnbXvT9aI6+}4sU$KyXOmTkc!h#ZgZK(`uXSDkma{lWHEl;p;F$TKD+#{v zZ^1k^8{o!{4x8={*URBJ9(QxV0|QxnEBk_3yeR)C1+53}GKh|5O>=vLH`drjJLow>}voYdyJ ztX0@d@VWlDVlD>Wpqs6NhieuSSGWGV zeq7iTJK*sxQoRe{>oHXD6bqh4++*lvG#k0#Iku6~EY58cHlI1%rKFby3oF?ww*ao> ze`p(#<*0Tv&D2CLcy++zthO{a4)_StOY7H)t%C2h4tFE2H|mF^xpuiRzq$5r0Z0~? z0mpkAGEO>7Y*L*Trh=p5peAqO0xVOQRLVUl+<@lxjooT@f2^+w%Mj4OmpdzFyofF+AdP70f=9PovtzY1N0l)K7u=Mc9Dtw2j_b6x2cis^xz zh;+@$%|ONF{Xpx01X+$gb9f= zI?+zRwNubca$z(8U5ym%-Ny$!iMXj~I+ACjb@i2$iB-1ReFapqxCrnw9+>|Sp28-b z^&YRXRql!0Dj;~T>RQ&F9S2TK_1@Lxg0pQFD>$oj*j(>CuBuO~f1=<->))6qaS`I5 z1VvSK5? z@(wz&9^X!N899N&%YgB-aFl^?&+vMr(4(z0<04jyGY-tZkp+dwAf9u z+!e%atxLZbsh4I_(C~8^_}K*!{T}sal=T^bveUVoaB`x<##GZAn-NIC)LAbl-eTX! z=yN0$(9MYjwgPHSl*YS<&2$GG=2?Gv{Ca@{enmb0Ce@t6ehHrhve+-;$wFRqM%X;> za6gA96>y`&T?WeQ_m*u=H9OhyCz=S{^*BFJtg?E9%_65*y)@V_6V(q$=0vG=xDjzj zq1Gr^CffRCB3@A~3jx22$9g50g;9rtxGTw4vzQE!5E@9_2s9SS?3g%gxXhGXD6kG| znJDcUHtXQV#FB6mHp0D!ZN;tcA1wGWBIl!b&|)MrrV1{!V0ndzv~jVs!e%#MEo=(@ z5Ic34$|51OM{XRCi!4|RTTZXAX_)udocO{4%jbOr9Lx#V;o?9}6!s3Ali=3$OpTE; z5tl;oqXSN(UwwS+Gn+okRQuDEKyo-L~3knJ7FvY{q&H`|Xdp4x>1lgcRJ^g5}-c4-o$dn#j?* zwWCj$R&1U@^N@0J z!pr|qIv?;o7WG6~DD85xnbDiPH*KkHinXxC&JUYyfVJ8UCA~cRcfHu*r3_<-*@b_% z5;q;qMvoy`AElQzWnNjM{%N%<1)MP^34R%ag=jHS@bwn_F>zm^fj_61AK4y88PWR* zro?ZEgu4r8@|hQI<#2b9UTQ~5L%1>PF^hF2gz6G`2x^OtMhy~oq~z5|M%>xxVide>7PA>B%QK{TDZMys zp7Oz-@uk?v49690m78Hlzqb(g>_O+JnV0y7Gy}_=Ihl?f{o$`ZB~jczY~}$bx@x2B0!X?X{AD#d04 zHk$EAG)glqk4`n?=r8p+JZH$C_TTf3IQC0u%eFAlgb!bL92ho#I)qN_5r@UwAVC`N z?v@~xwJ`BTue`Azm*kmE<94?4i*7*&;D;^=?bw*g7;fQe&j=QWN)80+NMkEAF^ zH5&ibrP{$+^GSsR}c1f%xweUoMB;ep96jb;PYr+04(+Eed0br zYmvO)&&|tR|0E^rLBh!{%EDd=Sn>o9sm~u-sOPz)Q0VA z6P9%qw_W4O`X$_WRgL4mf{OvS2!Q_~xAJw0HVWFBXI&jO-5l@;vTq`~4+YD_eB$0l z%aE*-a0}bCKn`dAhnY&a4UAle6853yQgMI$go+DdgyY)(>Lg`f6E?TQjd^|x2J$KO=?2|rUg4gDGLz;MQ*vxl4 z`KNjGcl}4~TITcq0oQAq_N8Mg2K*afZH^mpSXE`6amV5GJ^uhvH9^MBaR_ZcyM)NjN;JYNS@bl>*uP#!DWo#lE>lx zN#X2mMq=8a+VzT@9*Buk*@k?Wth_bqW{XeW{@GWWQ*1&%vsBuj)Gu8x5AYvytNo7pRX8-ZY;;kOn_dWJz4T28OVcZrxQT0|;9>0{r zZQ*de&NWU`cW4#hJ@&3R+cp5sA00NG0LSFC686--%Bic=yk4AQ5`Ajr)r)Hj8_Nsx zeU9Xz|GPZZ3{76G6~fJRxF>PMJy2i&$SW6up+t^C6Oc3+a;c%KtosBHeN5Qg2KZlf z2^E)ti5<;H*6lbpY#s%r^=O}(+Qg5I$25*ZD0YtWf0cWgJ+3I&;4VEdpS14(aq>D1K;O}d<`u^!O_#N0dN`Ma~$w0Y}TW#DCqD( zhtlGsmZ%apPQh>Slz%H-JuaO<$p@@`<^QTo6K$T&&2&_I=2mV?e-$K(|Z_f zb(+o76CkocXp7l}3bChylP{g0&Hm)UHEEaMxZ^D>!*ZPHw@-wz&yQ-Hbt~5_4q;D+ zQRRS7I)Fr-*^?S{gmUMAxgoB)(`gx^ep{6krJL zy<9eC2)QY*(tenGGQmddM)pmx=i}DI)W%$9J<`{Is3GI_u=(R(I^uuqwj+dwyyQp= z#=do>GKbXhj<9J9;qOXkm8UiFMbD9q;}Fh*@V{<&v+oR>%ba7olT55?xZO}(dzhWG zY%W*Kkt9-X%4^UO%vdm5t^a8jd6dK*kL5Lr7u>~)9Onp&_@Ot@G88=BgLkExuZjN- zRXD=fN*dSUfiYEPLD)R!aQDz3aK&YV4% zKmAb9<3Ysbq8pLUE|2N%XKisHi?i+xn@b(A+?Txd_f&H~wbbJ#9%+`>sM1=ck^mwb z#25!5@AMeQPd{6Mc=6BxqBMZW1#!QF=%2y^Js{q#K%9L@UZYCil`jh*3PH@dnR{4U zZftmRCPx9n%jSLg>PZoh*Lg0i1(w^EW;qN}3QVe8^b1<5vov`0SmYS873w{ZR z+I+!=!}o$_>1h=R$&N%UQ#JtfHDb>coD&llRm8+2IUbY}*9D}^!0IXp%10n0rhvI2-Q5OD{gImGt@ zE#fbQE<1q8NQ6zHgHSI%s6hPXKym_z7>LCVLd)%{3WSu~O0_39fXD{1+CgY(;Y&n& zDlPc|L=K2D2cceUszCh3i-G{607Pi=UkltX6$r`BN)@m$fG7fS$Yj3){`qkmvVrBEd2?$=jl#>2>=O?u!@!bKZBvqAUk6hRfyx>iiQgfZ-s`^E0X^{PN`k`MPepPQ^}f7dz(d@F$Qp5vPy-rid0 z0HO%QW(T3=Yj3S{08t7ebW5Oc$arjDTIVt#huxAaq@R<0?~kxIHUD;FRgq=z>jhhF#1kO? zudRHhARLJd4JQ&X9avKfU({=Ja&5>#a>$Z>;R$=MCz@{Gp;$bmsUO} zfG7rWgo98o_R`Ad1`s76dN>Fz|9ffW^8*O;Aa_9=gm@tpc`vPeK>(2fBJLp6i@mh+ zg#knsi2EIcX6Ig7`Jwkg3596uyCq;Tz}l`jtXkq=^r^~1LEm73^a zD_=nRI=3ZD(!Xt@w*{K$jEBN}Ak@2RJc6TObV!55y9^A^ts4fy?!Ac`kAJ}$?nJZ9 zyr!*luBGf)C$vDClcNWNLY zEXxmem90KLo&QMKTsbBAi0cy4cWcgrK`kn{as6UssP54$B|m$)d_HWByFCfs*pel`sL3%EU~`vsc*Y;8d_aSHk7yPuJR$ikOWWh){$fsj zF1xsh+qQsnd}E%w;;AA^NGV$>ladpi{e3ky61No{);9^%%5%s?lA2dcycjlDIF9~C z`dY2hOcY6}yN2I4z4-w`=mR2mpvbZ8L=o0-j_Kw1!1X@yZ@`^Az+anb=CT-z@{;A5 z(g=|L0@Pn@iMxhBEYg<{YM#lhStQ|Nw)reD&ArLz#?|9C9a0R}@TTw$=7b#ZRTzvB zBP0j`^S%rTpw&s?n~dxhE0-aHWQM$+dmX5!#Z-%yN)lAfX673LcL zA(=Ii{}=eVmO6^K+mPIpdCRT=$ymZf9DtZu6YgRElB4)I3R`hZ>`$_e%_r_{B;g~r z4S0%ub)xkmUInp^*$yT%-De4T1YH}P8E+Pr1v+d4WYF#X-c_(iP zmvxtAZ?TvFZVNB9G3St8R=EyhYq@b_KkF14OQd|m`f)S^^>J40wzX&bd!9KLuz82Z z3vhc2eu4BdE?&r19cH(L(EG%FBKrv&Xme|FM_g}ic`uR?ug6{Ldt3l`hyz}W;ZF2B zQgFh8r?%mNNF?EHwz=bs$w!(CE;sf*Z6(~8mzt%;q?dZMI?g{7yxM|)BCZ@ssKM&$ zZQLYX&6#(>awkTbsuIArJK)-+mpS2PY?b?m<#r(MOeCQ%TjBQI6S(jL#)E*h4b;j1 z0S-9g7thcL3-!qSSVrQFW+NNLGna+ULJ)fTZzkE2tN4(#gE-hC77+I_`W)TRx6(S^ z@)Fx)|JL6>`ZgPAYMsL3}`&|s6@_5c{Q7rVsKFv1{bSAqV-96?c!x58$q&|_k%o3%MmB(H`tifh$=N=CjSooSRJg0W>uCIo!8XWfG4D zp_s^zk%VlD_u9lCC*?IdCVOSrJPbn%yyU)o65}g}K_!$B`Zh6Rd;XzuJ#o317CDFY z116~_usR&c??_Wz$Fnq{Q-~XfBuru3z6T#$A`7%k$yRT(X0GB{ILDCFN$&Bv z2YcX_7W@E_PgwBtY+3gw>lQ$)2cb>-E9`k6El28_-4`k+F4oR>?MSwnRpfXr+q4&b z%H!z;$s7-k)#Q++**O4tgSAWxZpW5q5agEDXS}fjgl2dad$g5N*95^?3%R!#k507i zkzfD5Pxr`XCqFu>ly#<*@&z)VKW-8wy6X6kZIm}%c1PN z9!c1cxb|e0gmq*1A#F_woZFqO8%?r3W!*&f-Dxp@n{}V_`kFl-cibzodRF)4z>5Jd z`UeLt8CvPM>GIcBoa@B6lk?ImG9mlFbR_>DGNAH>iNJW@Q9j5ro3ZsT1lz9*n^PUaQS2Fm@{tgx@Mp2O0b%fo zX=W~xusLyLm%OG&WNqZ7QkZL1(avT&$<(}iiuXX=F%9Jj$p zuDG)t@GuKLleqJdgaK^FRGh$Mi*;ltzdGk{;$q5B+E36de1G^@k34E9p}^(6u22vxZqh=se=CM7N;{DF0!u zV34@m$By7n>SjI8`Y~)0fVGZ1hJl=x=h-T_(1Pa^_coFsujjlaan=yJHVCgdgk_{y zk9H#^%(8?#JF@x>%|$Pu%-hLx)SW}l-s)fT>I0xzWnpu`w4`Uhl3uP_QaUBMU&8gC znLm`sw&-Lugm-DUFZs)`Xa5aque7<@Tf(L_U_JRgu(=Rjg4E&7*5O^m9nzTsfO?~T zm#3Iw9z~YCyv4tijF%s+o$=1FIn(htj=}Ay04exVJFGf7i@OP^2kM60YLM}m|GGn+ zuZWd1cMCUIGe5zO^>NhfMC(%ncMruu314x*a?qJDHp0;6Wev9L(GHK{HxByP{V`p5 z$O#QagU~JA86uwP7oY|9p-rty#U^5^-|KPxhqu4v(NDRg8jGPGH1nboLJtxrp^&Yl zaSu8csH3?l5z_*&7R(+@wLQlQry?YjUf7?^Ryvy3h`aKOc&d4qe@NFo&8efA7JMqt zx=K!z0v_Uf%>Q@-0viEel%7%nX2j)zKl8vzt~*-EvRq!^6KVKeRQKk+)T=`zj=`T%@Wcdmq?6zc=SOj zQxaY78C^e7^zi7k6keR$oSDID5tE%rNz`t^%wVrXmxp=5h<)u1o+ zuQh;w^hHvtV`urLI@ji_f{Uw1Omup(#tk9;aC9?L@C*x{McixXeY66EDZlMeD-6>sMIFpQ-Z z%c)x9gHtn!>ww&knPy|(1ABGsuIc^|rYq?%jeCG~*0VlDUWtZ_nx#~F;x*r%5_K#i z95Leo$FR-EzdUSiLkXluyxDT+689@`?Npu;L<-(v!G{ue9O{NTAh{UUnVSOZuyFT>Ul@&;xlT^XH->x0G3tZ# zTz?Ok7Hp3nOP|KM)@mwSd4oyTei8FIU~L%(!@C~kA$7P04iG{siQ9_8r}3L8o=pub zB0B_DXg$^*w=5%Kwm3N<-wKscQC$obe6$72w?dacCMCj{rtEiLH7jfhavew4XmaXA zOv48}hyD8h_icHy$#t9ZBF$pkl$QWr4_FJEwzzw4%9;PxKEiFWiY-`M!mRxx=H3VY z3f_BD{@j^PQ(gq({Rb;G<(2MdmD-=wro5Q+;~w&JS2Fc6s;>^6wc^QMN=s@BGJGNX z-HI3E4YkiY_A-2LL%NfYEp3Soz4Ds%DC37SN&KFZcwc|40Q)TuC0fm--?>=&okoeb zMoi*v)AOTh)u23+BPZBp5X^SqA@!SI=<{1Z2OoDCYsb+-(I7Ctc*h*ZJ(|PwE zvtZxI2#8QxKVs(Fqo>n0N3p*r8i1tc$^o3}r8J=jh?|GrM@!J)6KR#_bY)yjht-ir zO2#PK>SiBAL2(@W0)q``3zAYL;4|4u8&*!-f!%QqY3|6$o)c)phGJL-_v;Gop?-1y zf?I(tFxD(*#x6rzJqqs@LOt9`ZNA7oxse>71?%uV=g^3G9I%FR(%0-k&v~|gvs=z@ zUv|oA2orx`V&&LLEi$oM;#f)Z@y2?-#ePX@#mVbpt(=pWd051hI=RyXVA;XE4xX(Z z#aQ2y&ejeDk< zR;UwdhXlN~vk%^8!CESEkBpd`0c+?*`t#9cND7(c&cXi9w28#siS9>Qx25!VXSfkN zDq>O!nex-(^)!iIL9Ze8Fw+Nx-X^XDNsy7XH~vr5*)*=fVPKjRCXZ8^`1R<>yZtxT zh&$Pd51Ws!zt;(xQZOet7@1*T!w;@iXA+O}{hO;vb9BV?1`*@eC6r?NJ^D!zc%mZ( z`6^!8nf~#F*}B&=l0g#WqdB|a6vFKfm*9^S>S1s!Iu7Bcm*X^35>k5*cO}w_Bay|t zPW?*9v4um7xsEh9AaOymC`CZj6L&g8RvxVGnjFlPmnWWSJ2L&K+Wc1Rn1~q#lgk$` z$o%nSc(*ys{ZbRXX8z5ao(kYR=x}77_W>9)9L_=3w-<=hAk*koW!hIHkhUwMRm8mE zbE&2Tc_8IA0Iw@JasT;$w`LN?x+;A8wgRyQ#9r^>3Oake#iVzMQ}uy zrY0VK_;0eQ5Kaq+lYSO006GTgDZJ8V(-h(gk%VX2Y7_65D*vx$Q`T`2(-|&xu$5=< zG6qt%ma)4X0#S%u&gD9YK}}bBWYRW5F1^eV!ovV z$vHk^o`XwK_QGz`*Xhkg3W7VpEBuGq&T%A>6VZd{cJx{wMuisqv<1J!-1$OEeenqq zbAz9A9$4C)E6z^gGq6dAr+V#93afW`Fenp)g-%w@A>mQ^yae4b_>b?TcT;L*V)2D} zO}l6Y<+O{Kk1*F>bTwu_qpgnlNNb*v&6OCEa9*O>MR`q|WuC~`!ufS6h_$kKp*hLC z{7nqHD6j6RXYyaZ8eP$RNLI#d_o$xag8JP-NmD5|BG0Wr&ATY?*b2uBNM7gBq~qt4 z>=HCYlk@XUsm+AY4aEH z8C4@1Iw{%ZBN6oBVEOr-+F=oGg+RGXCxDaQa#QE+=k`#Z2@tamAE@xfhI9 z=i4mieg|`z#k@e=LW_BuZO&x3%aIc3SLdIp&PAQMCUCgRNH6aFmo3K=_o_2hUqa{? zB5R!EALieIb5D+#MS!zBQ�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 z z7FQgoys@D9&;kE{SKi@?mG_~bnR$J@@;1Vd=BOo7PiW;GMBH#R6^%nud2^AJho=%M zZ_z9~aYNh_i%B1Sn}5DQ3f9V-J%EcCYKK}Nsk|jfz`YVGZ^0aHh#hcm(hoq_BIP#n zN`VQ?B5o0q@ah0tc@->hFHGkeO(`xc3Yx|@#tYjrGJc7^K?>H&TXSHVX@Df0#8%2g z;;GZhn?EmT?)JEH@gg)MLwnR2DOjsr`ZY|PKoXj>t*Y7;(LU0~o3dwv=4HTMPlNQQ zGf0!4%+~^ta;5Pg1X{AMO-&2##I`8*dZ*#pk@-RMt%FEh;Mi?fWP#&cOYjyr_Gh+B zyRsl?0{pVxWL`q5f#@crhBW3GyBP9Lw^TES_{Whqngr!MnI1>s-f5?_)aAcNp~ynI zXbyMM>QwUv`QA_9dYyuH9a$lS9e*Glt5B5PF;gLQ3a?2%=W+f=%b z*Jed6E(2WbfMulSRSa6D2FLo<8qH|2R402URhVE~IfySEgmmXVAp1%e5sa?kztSOd zQAG);@C!kcdUO1QuOrV^v|CYW{yl&k=0!)Rn&fNKObxW;aT*%O#Nq^Q$qPX~E^#vp zbnm$B$fT}vOu^XN#v`g9bh2(K)^x@iZNftQQUjEO5=%)J;`*TLP(S2aQ(~=QB*UL^ zx|oq=|0p>Sf;#6L6NO*o=L7?T~_#*+13G*c0dr%H(X5UoPq$`g*KhT035 z*d`@7|HYtL05@!h$IJ#Ym7@xjc+jU`$F&0WM%|J7P4qSPlB+L5l)Mx)pZW(ahiq;n z{U|gUC32S#_x^QJ#!>hqadnUCOZ*PLmf*sdgXVX~6F-vYH?$8Wf-?rEnJ_vL$!dA> z21BtOekrpa)<>p=)t3ZKHkYe9v3@<9?{g>rreEoJRh1aT!5A`r?07IgJeG-r^Us zsGGdrG?pHv_DJ{+xrHOKLKXuV#II_hJBy!ckGi46!|6@j0CWSAi9@p7kR6;kt)e{P zcp|Sb*a}#$gIef@DfsV&&iq)pdCLXyf`cd^>r^yD5l*3dx+K*+N&G^TSUuAdxaDxa z^pDx^g}g$hchTo4@u1BR#%j?KD6wp`uw_F_bIGd=`Z)&w#{I*o zkQeCOvlLFSIQ_MtIc{j&nf=If9l8xAg0IFC_YnU8N?ZbGx~+a%m`kez?hZKY6}q-= zDVj_EYfkkGUCKav>tx$xEk#n>q#Boj$p@4E_pjk*ngVi`cp<^S6>=5 zZ;-*S9u5B0(pb`tadjlqj|VdSOPyL!$a3pss5vZN9TFFX(Vx`|U*$z%X5T+LI||_h z2wLv@to!Fnrz}m{kNpx7z9^s`uFz9uUJsgXaGQ9kSyGMD<1QeomSu=(i`lu?&T9W8 z*0aXQ+HGZit(>YNIQb6eO_J(6LWxD`L-u`vB(#a`Xn98*llw-{%y2OOWX``>Qx4{} z|2d}c&7dj!pJQ@L7+SdX-+f&5K^=H;pcG6K2lFj1q`&&NdlA8GVc$;cVwq+*-MLt5 z8PHQ#xGZRTz}2=oVc_FvZyZ_rk%YgGe8jq+KRmnDTRbWIXT;wKl|BU%+t!meh#@Td zF9?-JUt-_Z8ZuPVn?G(JZks^_*WY%Xu8`B-dj&Nt5#nuT}nqbh0e3B1?{DiDhJuu7BW= z!zBNTiLw|CE26TY>-2;@+zn;4p0|mk8T`|knFJGaat>OkL$uGqm+id z<(~Ihd5pLrr~uuDWPY(eFwC(RHXVfzzY{d4!_}aRSxhFM#LBt+)%FdO?!n-$~o@ne7c|JF^pymjQnIz;QDY0dO3; z8>v5sTZ0!9_Z})mGV@(dbe(g2gL8dNEc^lO2H-H(N%)dXTTt4KaqwLh+=aLy zXe7F8QIeT8kcTU162H9EJ|masp*-FF5w@R*al$)>OGig`Xbc`lKo zpXE&%`Y|F2r2u{apwGS*k%m5;S;|(A_yucNL1)&yAYQ^swv%Efe|krD^rN7ufZ$#7 z$+?z2J5a6sI6+?&yNbBc=zerJs@ab*|E@emslm&U99mn*>ycclOFjvjBX0+2gP!DK z^65z~!Loy%WEq+d1ZBT55J?{ zikB!TJkbiZxS*8hHGrE~i?1fb-RKphV4Vlm{bnB5qHoY@6yi0_CMcated+M3?L{sMF_@+LNj0n+9Zyf1YxVaEq( z8ItCp6v_KpgO>QWliC30tzrHFU_BM`y0bJh-v}6(aI-A;pIY6X_9o{Cby$s^(u z<~IP`iy94$gLR70^Thpv4jIO;p``=4Grx&t3pf=|*=YhPoSHfqmcBMkKTExg5}`iZM-e-N{iSecIzRu# zyGh=%O4m8u%aV-@ZkoUg53}?~rhjkr+a4B>^BVk~El1Xl=6oA8ufmb%N`t7SHBh_d&C>3P5`YFwW;E_aH9uN?Sz!(8#y}+8XsGt+qyEnB?HSc<@h`oMs%A zdS142$%(8FnzJ0R9$CI)*d5les=5G0f@UQ9Zas<=MW3a>G9`nhH0^ zc4W*(GVMfJx5W*dW5HJtHv!E+_aVdjI(@qN?d?Z)dWF=*%@|m^F=*xk)=SrGq?fv| zoUI=COO`8jVbyI6a(%;2SvAosvovwyg?wwVe&#iI6BkwAVt$4z5_x_>`yB8m7JSrj zhTc&Gor%($$6LD@wzWIOzPnNq{gE4Tz}k9rC&M6g8&ZomTJZV2&^4F%#pqe&Hlr&n zSew!GEkUyvu2%*y_#M*UQI>2zVXNF7a4DWl!6R}9lCbj56z|;Saqjjw&BA*2Ntp=$ zM5!MYcky53I};bzxIGTuZ4JJ7MykmoUc%9ACrPVdJ#5Qbtm5-AhqQos3e2#VlJB{Z zR#vX-=`jDY%%_Qa9ZC2g*5LTj_1elTu;Oh&(+Y(8aTQ5k-Dte!bo6*hCLtgTAbn*K z>)EovS&xy~)wTys?@_Ti$B(WX^{$>Il^fFk=Ie>(m!KJq73%fGC7)exRi9z8&WT#* z#4ld?fS>xGga5`YgS*n<%11u=gybpLj60-~6Xdg$@_|nYiO)(DswE_^JZQE%%>Okf zlmZTnj(b-=(CN-la=n}I5T?>#Vxqy39n2tvtF6Y*l!^ICjr|2z-NGZqLB7wp#}*#( z#QfOoyT@c#2XPh%6U%5aoP|~iQ(_HH8r`@?8GHJO(Xyv@Ti3?3PVg_7l3H$!)Bj#Q zD%7dwS7v8;D^k1jtXZ z*-}|u#D7z@NRkKrB1GBiN*3*_ML(xoDtixcuei6e)YZ(Ozgk0 z?>`-Y{hc!N&*s&29T_-?eFbn<{2$m?4!7)o!M^-m^b`LN>??zNXf%Fr*pk!d3}8nq z`L7*2d)V`P5!+Nc6^RA%EP6pw5ejw(O#{GMZZ0MLe^PGlrIC+cqGKKVj|ryj37VGC z zPRo|3{%!64f*<|vq_*PafZuk`OzH%_DFJgt72JmG8%O*DXbM_#3{MvuGNL4R&4m^$ zFGk2{UhzI&YU4b~^YwGoIt&f`?P=3Nt}!J*{<4q*C;PvJlma=TAYS-pVfy2!7$v&y zP2xU5W#~&3FMJi}RunmhD5bjikD$o`%uRzAekOxfm&9huI#{UDmO5r~EKd>wRub_GM|G=&? zxNpPNa6*3ur8t#;AYwb3SzN^YQ)ZG=N3sO;_R5R6f6yYG#^QwPT$~g#yB+Qq z_iW+T^}s_dc$+|H%g@QP!;G^=)IMNePIAap9}_Q|W)#1TjzDUk+^7)(ClPlJ z>WJheZXLN5`$`h*D~DUh;dUpF*w=^c0sHQ@;5;I4K@t+|%TEcJQyk6+l1)U@klH7w zO!~)<5_i=f$!0Ozso&9Ga~hn|1pC6NA=Am>CR`XI2g-tg4|2aG$L<9^;e~+vj-ff+ zblZ{9S++n4L~aWj+9u%NYPP8sGB-Qcy~z=MguXJXHSse>%}jPajf#;R);uyw zr6B}9C2l85yMqZxY`1n~PymUud)bkzpBXQd^x+yIvktJ{fgi=>eC<{%R}3Qr-lVP` z4wFB5Lc$+>(R2Q&>@*NH$J!;ypJ2D9|ND~U^6WNpNXVQ$HvWqZ0J-;riycA}_MPti zqQ5exGw&VBASfC>WRzT{pR^>k#J&wB=AeFv#Rai4*o^}j-lMElBFOl5Y3Aiy^ z%60Y4#Qlc$AvI1;l8lPUR>OH@Og}7SR$7C}9yQhI*@V&YNG+CUYlMKjBsT!vj`ETF zMYW-}1gOE0S|Rg$9Bjstel{vX%GFl~TR)g;-Xxxvd5pO#wzBo;`q6^JLnhOXxXO?A2J>g?!^Ay< z79sb9*AhrPt7r6BZ#(1hQTu!NskhCV{#yC4mT zwpzavS9467IU3bQ=P_Em){YoQtnXyqCwY2P5DJ-r4)=J{w@2NOa!-TL3y3B#g2<_8 z7J9NzinqF+mX%xw?3I-xLZ%pSbuvnjZc59;DDL0;-IQP~sqN^4FIHO!VhxBE9)Oma zpM4&^j?^~BB_srn7|RnA)DksCi#yP*q7q9H-m}Di#3o;U*hk{rBSYrKJH6pnzgKZ_ zZmJnHCDn8zqk?bnxF#@@k?~82moW2@gU@;^1$;kXJxS`!Jcm2Ra(!QRs@j=(3C=97 z7c$=hPIP9Mul$d?1Y`Zq{TFAJfv7ei?#x1LdK@irY@1_kYc`HIdC_2W8JabWTfV-& zGe`N4c)ibPFuZL_>W9p!aKrvsI?vjyGslxro%w+U|2NKzghS>+!0OCt@D`xA9PaU! zd**nSHycm$Hl9CjLM2le4?}YL>pbhfE+9pIx}3;{A+y)<#5~f!$aAOpY}MdS7W@)% zTj?`Nkmq{tTbja_aK#{h*dZ?p_!u6!=~-Gv=2EoU0aFbn1Oj)mAPJICkFDFj`Plg2 zceqi=w1KPjpdsl`M{STAoCik=b6^UQG4w2&i`H@_i%J(BsfZo8T97uWdQj&i`m0EfN2#%v*znZQ~ENWtg&`vNBt*AktFIv{WL zK`uh#g~hf(ewCUmPdUOTgv>&Rdok&6Mq^N_xy)|{Kegc3i2MlsfWAVm#eJ+N1T3vp z-bo?zAz(dqdQM?S$qG1>QY-zTNEXkhwy%0PRLyBbNxo|ut{m=RCFm) za1b980yXbq#UykAYKy{5#L0QiKPQuHbrSGu{FQzNm)5)D_4HxVKZc$~%01U|-y`np zyQrr>@y7kVFt(mklDajQ0rKqB3p7B;YO>fRc6L4qGCS!Jx-rUVA5J=vh;rs8nK{^&dlns5xLTcVoXE6|n#@H+$`yOFP+&qjPh5ZT&EI)) zHSPe88Z#n03gROWTGbozlP%CW$VEsOsWWjGqD#?;s(aBPDaC>`~30es;)=BfGlsTC&}YZnxP_TnXHzaO?Pa&11~Ec$|FmeQwkU_-PA%!-7|`)vu^4xY&ZV z-=E(qWL8%JUgLv3?)-n{vdnf#0yx|{WPWly@e{z`&^`xDL6;Dy$*5<2)CkENesY7S z2A5jyf!7k?CQVN8a1`jtWR_wko_O8kn!v$aT$bSC{5B!e5^$o6Wk^=JC6=4$VQ(ge zT3nv!iF4@wRsrtmfZzTHur%7rHCy~PK~G&N+(Eu4{8mw2e6<69*Mbk`;&cmE7w1Q~ z*GY6S9vqJqctSn=ti$~luGf1xn2U20TpVu4g=b2w`R`;5SWq zd-`#X!O{TdZQ_IVK!X4$?=2ryu<~#@N@9|$#{uggnXlq{3k#V{zocWx?om$D6ovQZc z<^*pRb)q@1!kgO^9Lvc4mo8f|h_zK9b|`{oaHiK~tMmeDV*k7ZjF}oQh%(*mcMy9N z6I+&ONxpTzdZ`RV0|y~RL*^{hKh3|vlLooYzjq$X!L$XVCD+`;vOVZrr0s9EmJZ^U zqjhLCnlzXx&fMt9(e1aLNBz!Repk8=aKn0&SN&dw7EnW^U>PDH1a2j6DtZjfLT0ov z5l*py>%8jUfyjGejp_Upofk5_?up+hyg>RD=u4zrZ1T8=7P7uj;nmFL<&RTQi%WPa z*4+nxX73dA1+@GgAu|H7dZGjA<)fJAu~qQB7Tk-t%OB&U5#-}O(_>Q`4bKikm;s@> zpUUel^(Ez1N{FqzVDza6dM#xnf7SWH0VErN?$qR*!Q*^XU=DFFq7TtqXjYf_XG3?| z1JNblOm4`0?|A47(r-m6_jw26_gb1-a7Q9>FjCCjBc>{z<(*4(1+ELf|dp zzDB>IO{lOBi=Q*HErqauWB(gz4;3bvUBJsP37O!1@iX0)QG(uRBoc#ra_aOp_&wsj zLtD_eZcMLrZwYhv`XdcmtBWoRnUM}S^Z+hIc}T%pCO#!@A4-0ZC3zRpz`Ns;rT$V? z%1ysAWah)=B5;~_xLwF316aM-D)=IAj|n_-Zi*R1yo8(BrpLam%QqbM@!vu?T^#%5 zlfLI3#xTBv$&-9I)ctg0BR(PK+9ytxp!Su)&2hLd^zyl*;@qfw+1CTFD@rxrzMN#n zvojG~kkCx#^bMJ}9q?rG%%}1^7zdkymV5X)DdrjCm!cPuYjCs8^tN1!O98KSz-sY( z4p>J74`y&-g2CauklE>Q<>88W_|vEZzR6lF%L#r<{0}J66GaK&e87iHi}wS5Azyo-xTIw#Y2fWH)^h*z#a2_)yxhuD)>a5aKD%JmhUhDUN;Hjdj~V^mERVyny%! zh+7ODbhb=hF}_Pj2BjyB$?^tk2zfFt9xDF7l?cd zy^k_}u3W)-*``n{SSjEM&M~hc&vp#n$X1VeqyL-Uv&JMD0U``-P~~!+u^X=)UZZv4 zfRLFDRNL*EWRfCPo2^23Tj+PkRWofZv@6?5vDX{WsK{>?3=ElRRwNBKM%`GkF?}nzUy;h--_K z$f4GmZ}(0zBa#_Zyp|ES`}xC$EYjzoa}bv^ulaB5b5kc0w-7BuEx5}zcl*py6w2`6 zrXe$Vdi->^%}6#qsO)P zpsw2^<1WiC8{PQyBC>tt{H{EflWd!vY&Y9%-eb8@N#5_q`z`>s1IV!+C@14yRP*7u z;kQ~qQ{sA|>rh|R>I2Xkf3r$vFQXYyO}{D6LQxEV}@lMo2a zrhP`;Pz1Ra@3$_M=2z|5y zrFSLOw(#bVnd?}5<+vp8()tw{72LprxA9)$FT|%X>bZ}t`}xrl+Xm|OByax*fTNYZMlX!CJVAhH`0j3_hDqNsK%*k!Nr$qwnZo z^e6uN)(MrH(=`d#ywYJjUZZKz;*~v_#k}rGHPs%8A3KL7!CRuMKJkrEABwJfvP$i- zuP32&u?ubuU2gU{;HG2}a4QGAU9f;!tD-@-&rv zNRM1EMe@~=i}-SJZ}wIG>PVC~uC2vV3#G(_N7B&6;wPpbnZ}`q9WWga34soe(#W9! z=rZJ%#1__IZ8l7lVI#O|Z~^J>jq=Ydq!xFywNO6n@)Gf{qmMWhE_kOkSO-vx01t5t z{(wARq3Uzv+>0%D5^)cq1?VvpEf~OhL09_C{1DrMs>KCkLS};l-b999P_21!Fe4J4 zCk7FBJGu{zM?+vLH?+m?=_@xpj;FtHakxL6^*kB=L^+Se!TP1EUx>?moDMLmhoqqk zcjSUMKFO3O-0Vdr@X%yNyf$3HY5HqtlDUR_>fw_-d!_R!A@#1CkJUjku32 zVKrOlPO%uwbq?lhc5gt*Ps9(duf?oZHJR3;KaiePe~$^A^(50K(B06+)k%FgMa9`p^Aqf-N%4dq# z#FjM}9_--tHSVFRIH+kP5!Ay-QFAToP2$!f2|uz;K;;#N%wZ43t@@QDNl$|jkwq>Q zFMF9ype}Juk%X3P<0$XjGe!3?RO+DGk!03G)yzd~74^PFjVA6MB;g^p>Hcks99;1< z9#uJ*x$ItqRv^X52rMDc@EMjmKo_I)kbK8|(l8#0FJS!)>woP>l}~5dio>11rkWW} zo{`9M>l*!V)LleQSm^)C(pah;d2I1O$Xw$fW|FG+%xY#{9AWfH{UYMtLK2>iHMn+k zy>mD7XW@g4Jb?&HJmGzktU{k7J-UYWIE6Y@BhjWn>d~Dw5EGt$gLPScYevH)zE};`zK8A@hX8J%{w2Q530dyvgI$szAzo zntap<)k7te-MqXclTQn`)bj|;4oaKf-HM`G7F%n?3JEC-8K0n;cAI1KlYbFcZu*?i(Wa9F z?!Yxb4zm`SJ&(m23>h8ldNlu)QF)h@p1{hV!(4U;rH6aGqOkFeq}ZJM|K(-=A~?ex z&dKEOjQTp9<@Q+RP4flBFGff5gk9{5Ai3_hVh*ufr}bFNA7M@s+^}{ih?f@Fm1uha{{T#wx^&{Oflel`9uZso3e! zxlCYwI9@VuBI6zCKBN{`r|1v@ZFi=c_lPe=-S<>30yzmqATp1M?r_6iR%14hXFK{6 zDK`XH>Pn!9FMFI_3>39T?&UpV!FqYme=KC~^gDwdTGnU0oIKYcznFf116Aox{+qZW zV{U?tC7>>Hj=hjP52NQ5MKNt;k6nf#Cs6U%urKi&lD%vXNsCwH@zB}kR_EYVjIM za$3cqw#6M~%YHXX0Yj9g@ad45<8Wt@em*iU#JL0Q8YF>^i|M$chtMRHTTD?zQjC`H zscYE|K8J^pK06?bi#*v-i%gM=x{{Y zb0PBq;67enW7d)BM|8?daqznqyq35MRQqM7;GvT`#>;;0K7V+-$Ms333kH`z&)k2w zoh^3=>2F1gkhdO?^l+G< zNrsxQbN`Ff#WztO2!Xc5^+5wsU*vVkYWSxv&sGGz3P+aFv2wWAzs}O~qsg=cDVT3N zd*J?Wu=*96ji#YcZjzb8HzKMpOfh@xL_-A^E~kb8)-ti5^mX3krUxnaG0Uxo>vGU# zsQWV7#YvRlA|}A)0&X_Q_k@%Qx%)5wAY|@yEY^-rqqpMV?=83`aa~X^WcHQ3-klHNg{$@r3j-r`t9`JR#tm zk3(jQWAKNh{{|iXcAT3kKftN`mAGh~v_WiKY!45J)ocmqK6gsGV zBsqKq4F*!wDvN4O+*l;xKG}K(fvOYvK4j)Olv(VR!&<~vDdm>(4RLke_bH8KtCZSp zbAI3{6Bs>xr?FdZDBH4COfBj+A#f3KqmYCd-vYGY0f4_L@DNK)!QT~MXQloC9{7CfseK%o85eeO2Rml?!V^)p$ud6 zO8p%U6??B>Y6(9Q-b`u2GFlKXWRt!j zYK+vf#_W-%Dv-P}*)(Iv*(kApQjpN^DFVD3gTo${7nsR&ExH*g_*{Qq;DHZ$#DmtO zRme={i{=G<)NMHOFR0Oqcj%>NNkuAW>}yUOTPf!KQD2m5j`hbP-m%~<%&Q(|!7`{OFDERIjk%gL$gR3Pe`C~5Is4>#>l4l1eZil8%))Tv&! zP8C~&g)4QcbWh0q<#?hS>3gBR=s=&Zxdj)_O*Q%K7>ySG%6pcb;~zEuETPX|wl`$z zJ`z85ca!HKRD{%E&W41*BI4dcU!YG>lWr8P^YFivtrEv#Id|pzLZ&ldJ$K)d;U}~W zDY%ozH36AFvzK@Y`pFobG@@m8J^Q>m^#{+B9D~1mGbL(jk@&xAu|@Rc2Z?E%$IqlRMX*}=#fkybw`TX-oQ6_z^D|uzOn903$mji9&~Jb zftqs#Gi`znqK8Ec!vUX0o*w7|q~H;f3}3!Q+$U%! zT8D~@;@tf{H(H_Ka7vc>6mX80movALdm3~qQt*TRzQ8jK!e2zZgp`dbW{EuYvps%2 z`%_x_FTSOxW|=a$5id1&(B!)b4fVJjzufyQ@^=PaCGs8gJt{@#;Xj=}(5kyXwDSId zBtw_L6j#eKyBtrXt>U&7)j?`-iRHE=t^<cYoE~=t04yhh>@b z0Bb3}6X3(>5eIyzly(YRwa*w0LlT;^Eyfeeks2#o@$l!8B$#FTdIn4RCq&3_HdXI@ zwrVjgl!U+l;_{J%+u8n;CuHy{63Q|+I0la;{WEAGQtrK$yAn$_M)@cG3wEMbxpX*? zSep8bfA1p}f6Z@~)Xg%F1J>FRCB4+=dnGT1Ng@8pf>#r_4(&qQQLEc%k_P!@qRf^F ztsT*lqq5A)4!GKv+?}KPNWn>*V?tm6al?>=d)TgERA8+g84#l-C^*s}%Y5u`XOO-G zEl0|2tb;Er*6{8cI_xX%ecATM3&X7^LaTgF2)HLlSkx%Xd~VAPwS`?cztuD6%|MJV^M!HgqviUoq(%b@LDpAr)l5ffMum^Lg0AL zNlVlLjojwfWt|dKZe6^dgx=-n_$-t9XuR6>As33jlJDOso+_NpW zfVj!%Ni0rPg9`aWOd~&9lr9$Kp~ltwZaPf_W$%WAG1RaEmNcAY9x2n4x44i^s85@Ff#`pogfAWE)y zdg35PkmUP!sc?q z#f9CnOxE1^3Y9BKzYXm`YVdjT2i%%JQWnr%Xe4UJ@K!OyTVinM?lf#s{y21IlKBmA z!G&2S2XLO3mnRxz*noaS3VzOl>vOW3p&QXPNM6e=JJD|`YkuwjfEc_7ZvN$2raN4{ zcDzjb<>*TkRq*L{4B@Pwcrbx_qwZ)ZU3q<^vftJYZHgmTW|9s+W%uH`sbiCQRkXG=PvRsT_e?lAdk7T$dETG%bWyQFCKT3{(dwEDR{31ze?PP z=v(v!x|}kR$9Warbf;nan%_4iqq9tFzT$Z^RaKy8TLP>_J(6vax zZ7lc!;)>8x^c;H3X(z(Aut^)gl#FHLv&>k>!*7#*HLAWF|0_7xf(v(Z7lU3yi%^}( zJi93N&t2{xemfy9{*#uiY*Ln)0a(k#PSU5+4$!vRfT7!t4rZ!DD8$vNxu@LD5soP9_-!q@g8xGnhe%~RiK1pF^cOX zs2m!~YW*Z&c6a8_Pgl2kZ${<`vuw;293wSIm=yi;AwDtHLvKk9FTe^bNq&8K@&*r+ ze3(vNNb(6*@?JHlRxrCf`2b1Y1x}v`uxUgU=)@BhIKgSH|9f9gOhqv+^SNlW0Iq~ zfh&QrHp44l%e;p8H@U`qE%W@cOzmtoLL^Qs^UZX19K^-S^Rv}Wx68Goct$NAu z$LOGTd=RCh{_tQCH0_`XlT*TQlFf$VrAlbz)cJ=rO;4`&rVeSW63nKKtVQYSN~_$H z_%yf0>+SmHH(Z6v!T$1fWeEp6*uMzkJ0Uh6Aog33u@zO}Tae}RXVJ^fyz{6?=3Dqx zOUT&ccx^8C(DZLT8Dr1F^NQ~8Mk;{Utw6U#oD=uIqzY$3YTnxA*0hh1-s(Z>;&ip< z|3SVyc>jVotmPYk(N$tQN4fG1=H^Hs;l$|ZS)+r|oQWe-+N8dnu4+E#`@4HcW7V+x z^lU2lLGDe~98$q!qto8LqfR6rij$!*jYEv&DUv-0Vr|&i$V=RdwUMltwvk$tuCn1h zh>Zj)*MD@{(tGPhpt!{n?Y}aOQg|mETr`zo9L;`ABWFpvdh!23zG8Tn!y9(%Td7x2 z_cE|cS4ouG8)z1m9!qvO;?+@w-~o>4OBuoe2|(II>#p82i8F67m$x&w>*t;F;^i@`^9^}HUbwePgixH_Zqxpe|S`!`w6?MDUOm4D!CGi zHzvf_CbAJQ@2f~;DFiJnf~MR*3$z0X+?Nv5`$$L}PuvXf8jx2SbH;l@_2L;fbw#=w z6T=e`qR)UKI_@Auvmwe{N#7kqBs}3NKF=8k;n@RE_Nw%Vdc6{&ffmt)2O;XRExIn16IDg4 znd5}mI2Kt(=+5J%Imts*e+Vae6hl*crte4E9pR|Xperz@b*z@}@+u68i603%UBKfK z;)Q|iNy^s#$?ShC{ybfEgqL!QAt`kanH~qTfg#qJ5mETUbSgqu6=# z4OgRyn>F#}yaB(JcnQ;*C90|XqFJ?)7A(PRtjqa|ClGkG7F9xZM;!y6KhozN1&`?8 z8C#RHD8LOzIqDjala!z~_o6i}PExNuqR*+AtliB|tXj?TZ8js#QFjfJ^DKShVv!JD zdF!kN@e(?4?RJho$>fP!7VSEGSk=hS^n-AQ-ISc(ENQ`;z$oDx@18R|-BGK76F@Gm zo%6YYxKB z?&!T=p@l7L_JpT|yshc#K1<-$q+h@!^d;`3iG##70}^EOvaEXK;x}iG^&GhfE&f?Fk-a@#eF?7_5wspG zpO`Yk-1?p~_IQ;eJA+$k;`UtmG#BR+w1i?W6vk4!a_1^=H89Gou0{JTB~c9}UP4~< zr)iug^*4VO{+X__UhpX%B*{#$z@pggW>U@%#O(oTAxBjQd6X<)_XwKw$SGtnF z(s{kbpQ^1-`gYeRsFS&B(ISecE(y*hMD_*}26HW(i=hBh$8x=NNSxZ6gzP)h)dEZ4 zJ4oN>2L|h0O__~hK0(|JAYsOZ@v1J4#&4Ywk6t9+OoHrP>8ccB(>&*s@on%9FvOp@ zRD8ITxJ^L9cCMXqe&!%tkF~69E~5iBfvD`=>FW3weGTs>eQJiI&W`YpAzrG9mlC%M zYy#^+4~Y9~&pMUvNytUuq10;b-|6alh{Il96{_v1x3KJnTn+CVns?^L1l62)39Y%_ zL`#}fFfuJ7B~RU(uBJj{+GGb3h#6&DMAU`^N6e_dCK}3hSS2O@{Y<4sBVZ}KAHy5+ z@~RP}p8%!;Enq}V_ij2L61f5F2HQdAQ!J?fDe**YT<1{#yCi*FKvkXXmpr+SqZ)%J zfhqX|ns;Gc+&=gQdH7rW4mw8?^`fa+`!Uw$;+7Yqf4c(f*d6jeV? zd;yU6cRy<358M`Nfemj?azN!-ybH)9RkQe5i&$E!46#S@*x8BwWfI(H+GzEsN7ii( z#rjGp-mw^@q3)NV&Z#+0K%G3tpR;?9te=9_&YpD?4J$d6}M z4XEXn{P+=8HnEAyf4qtQ@j_T?zvTBKGWem^PG8wjV3`@x!yB)EWWRa{gi2P+p7;g`pS& zMXdf0&4${{#1FynT_p^MWoidg+0nhl8sv{7jR z^-(1hhh{{7zknZtp&mQnI%`LAn0;AhdO+Pu_SiBUh7A=$@gWq4X+v3ofI9lse``ZU zu-pX8VcJl3FrZ$mj75Y9nfp9?zcHjWYI%qZXzA zJcfJ6_D+bt`OL_pBj&j|Hxy9AAuv^aDv4xSbLz1a45f@3`N@O-uDgTqS1LT9psqc zBGR{f-M9N|DAxWeV<7ja47X%QHD&>{e5u0Iqx@^uR$4D#g8F)L)Y&$zc0 zF_wGgo1JxzPOLC;Hq_>^z7*o|hb3_2&?L^Q8&C@li}=uZQ%^rSpuUHgkSG6$dIeER zEun~uYjR?{gaXoUp$gxwH7p};NwmS2BkM$495*a2nmKxSl?XTMzu}U(iNAv62O+BO z&5wS-pW5~k8xz+HTno&kuc&hb)85(j1L|CO!Y&J+%<1EO%w zIiktlYEh_ruZ`T7QFL}Vpx#E{6v;r4fw(-ithIP2$PIX@w2KyuJo12tJm*noQ4BX)BeYg$J> z!#hLsde-DQ1$D4mFNF9#h)wto!e7BQAk9zAw5E46aW8S{4IEV$*yg?+Eo3)hA#IVx z6VXJCNNk9XItWqPuY7wBqJB1!=E<~pY8`~91w4`b;{xiHN{CunL}>>h>IP9}6DoN4(wDq#6OF);=YJQPTdr-6HXJ#|Koz;z{M$@@L?9!Qwepet@FIZ%b0I z5?=(|!*9)I@?wm>5Tb>Z5WQ~^vA(kpkqkKuPYFD!Cj``AmGG>#cslA8@4IgMvJJ+K?G92QWx+Hg{Oy?R+W-}XM+g(J;tjnQFS-(rc;-=Q$Rb=5`@TQ z2313_Nin6z+4nn!^d%?qaApbEne^G9H;^h^3$He##0YW4U>$G^+L;lCkfkDF&dC8a z2O?vSi?37ekuZySA5^SKh)&P~ZrvQOE~Sf=u%2`r=hS|5-7FYBsf1w@KW7-U6*&7a z$XF-($1!(>BBun@AF!BF;?Ly%@hE0uEf(EbI=x;>QfD=E)CHg;koK0tv|wgUPJyLN zQa0H_wHY~!G6Sm7+dgkk(qF~;*HErTy4y%6p3`a3l?`Fsmy+Zns<$wu2d0XbVa~jWL@P^&g2tdA3XyP-M z_e!s-7kD?FHY~*L)Wn&CnfA9<2t8WfZ64+k=bj!=lOSeL>ION*MKyBN5x^BVI^j)D zaXFU%)(7^hY*|{VW?OU-R6kfsJ%#jb!2n>&zRCL)XBBbZfIq=+Ku!fqxr16~PW)Fr zhi|MP+$s=JM-=&HaKdqpIW2B>rCFB~0WheSfdB*t)_t08@6eLofBL zfI0=i!Nj{IBybV4YLG}&>+OT3fcx#e~b7UGF-t{ z^+8+>@eP`I3~`SD2}_soiL2*uX@%@+;vA+}O_a6^s0S?G8RV0LU*~Jyh%it|wG*Q*-1Dx}ZchqHI5Xb={@CcT_d0V~^+9aa))DoeeU?SiM{ z)H`Iz9uQE?`2)A)hCO6DqM4%tzzF=av}&sEbmGnioxw5l<5d5aelOL8k(b!T2~qao z!<%yhE(hKeGP*<4%gJ;%J;(sAhPadb0r7l#mph1;a2HomvFZMdv2Em@>wIqvr~-)j zZ8tnX`sct3V0gP}-bT$Gb$W9rqO$qp91wn(RYbP)F29YAInP@+7Zsn5it`5s)H@KH z?l407hrx@$5MSl}rgLWt*3`k{;87s2lo#XGMcCH(Pq}WRJR)$(;0T`0B7T_+rC=8@ z#8FLr`DqY>XTelpe>riXHey4Zd0RjwzFTpiI+r}=Gbz&Q8VGMRW68+IkOOS_r&yuf+`z!b_)*nTlWGf$?fdsev ztx3Fu+FUC;^-VUbi9D&p0_uHBGYv^EyeC+^9pK3T?#_vhnppaExBHELa{Ha32sA%h z>bihbJwb1a<^quimeItG2NKTzJkfpEJ0CW$%DjKgn@&Y{1XRjWzv7H|QH!@bJO>sp z7|9vVcncm=o%6_F1Xfr)bkq_Y>QmJPEx<`2lZKfEM6x_7c=w#V&WY+~&HL##QEP#hEF?qER@AWxnD*B+piGa!Xfn5x0T8tBL0m`3pF*6*oc2Ot!L( zr#HHbmlO1hTgC^M+{Fw##Ks3_lfDnQR`S9po@a;V-A$ZxCOsWE68II;oENIKuY8+% z7V(w2_XgB_h{IlHcj`!d$k}9ciK7$VD|aDt-Wyq`RUSD$w?yegN@*0`Ob$c|VnhU| zKXJDL3CBd^-sc19AMh5B{BZt#0ks<%|QVym=c9G&FPOMs>Q@F1M=w%zeJoW zZVfbqH*ZXU^Q-(ev7S7?fGq%CuL_!I;s?*7M*%N_r-AL`T4#H`iZt5I5EqYQni*o_ z<4Q>X3)l*bz-MUQKx;=e08PMAcyST9*d225(nEn6X`mO8xb*&j>It#Y#3^KwM$wk5 zAvQ1N$p(#V;w79qC|(U?_G+o?tFj&ls3DcGTw$@?sm0qbOE8idVDx0MlGSqJ8sP}*&{!kNdKAQ>1_B_jinV=(Mvi?nzROc~?>e&I__|J^f z3Z4(BgylZ(lN}rt*O6UBz*;&bfVh81YiU%(Y)^yw+3tm-+?BKgp1+6cKN~Oq?U71}wHsnj5z3K6q{<+akkXm4cy#34JL*PWVMZN>EH|F{PVSrpP6dXc zjd#!ajyUH$=0QQdz8s~*0AO}oucJ!)&3hJV&TBP2`N_gJS-7`&PbH7=cIIk$$H41O zILs#UOCaG#uHzvNwX4`e3-LOLbCv{D^$&c3OC{g=kP65zbu`Ci!qpPj9Z0x}YbCsq zGDDobG@x2TY#e!iGTZ~k0z+&%h?EN`4Uo{9>tqDpLxYz}FAt1(dLwYj@_-s-@$UU7 zQFSCwaHUKwQGSs)$*U!&JCQkHFc<)4GM{6*v>y7gq7333QSpZ?YeQ_BK_^Hr13iHe zSe};%&RF82;6?B>$l?*!{SaLQamQ-n2fM|oE0U1-Bc9wo^fmD*8NLRkzz~0E%>xCXNn@2zhauMc_?-ucD*zH^MK`RZ zgA$&86ewJbM&ZeFZ=wj2Edw6_LzCv+bM_Ed^FoiNE>|&u*qRax7yxhHr);-@H%0TV zo0g=GCC@1UUax~{e1v<~k;ByfIxSB1;->jfN*6j3brYx7b@X=Q*XF-c@XXHw>P?Gy zD0%JygRb}9xD*R8yz-6MCyAc{3~vz%4X3lzI5CE}1mdqP;)fx963hZd6NdQAs}j^2 z;=cyw3n0}l;aNRBL2ZxWEm%!Wt?)JB3LGKh;Yd8TN&*|cD{3P9^MHEZBK{wo2^TRM z0B!)QW3kIYg`6}*4DGzKD>>jm^LZ-}AAVIB;Ax>S(;w!|aPq-H1TrdV06^mDp z9T2mLdlf7OZ5U14!?z;cotrlxN+J;VwIq(+eIQnBi1qFRe&*mWH0FHCBtE=hH?>lq zBg{sy4cG!Rb)cLV|4dRd-sMfJt_(o#tN85EP5T=&<_~|x2-*_3Y2AvicG?2B;$BA} zA@=P$@nwWa*+y@VYt>6Mq4S-PceY^N^CcE}+URf!BN! zZ@o6Dy9%RXc^~t45=c1c`3Xddrn#tNKTKT$2`{wna;8J0~%&_Rio z*k~eiJ*#k)5MN!1CiY7VZ)pr~5xh6R8+MDwu5|b!!}w=RCB&16n-1oHnZVvbpnmiE zB4ZQzUkB8~mcSKN>~+Tb(Qu?f^FU}f7)_{e0%~52#3Jw_5Ub(?37i@ua521JxB`3r zM;(U52NXE#TjqT&fp=p4_8uC$byQ(cn-<|839^aCR^x^*{EFZ92p&(88KZ zG_iLl@5T`SKQI9QVK1Euvka^iUa>#hDE=Zc{$fW}0ks-(N{BU6ogHh% z-v`uoOW>wBm%8L@2x0}6(*;^_zbW@@$42?f%5q{P&ia9|>Zbvomf68A0|sj zD~s65eXA1Hnc7w)i*eD$R<7WsSKC%Z@Z1jKeIghi9e6^A^H9Smt5lW*5q5%5}Zz#I_h#T z81w_%dBRuc@RT((L1k6*W=!O>@YP6P`g=g#0hdi>aU=UZs z%PfwoiLIQUH%&OfoIbP-x9X^Wsk?*LTu)xRS%8?q2$%M z8sf_}@e>?NQJ?tZz?1lAyXuN`)rn2CmiAu&@j0LGOMH?=-1iWOi)~_f!+*1R0p75v zjnEE0+01jk#T$7<6Bi_N3J^C206Fq|qBX84(Zuhas9632LD}-*;}iICU+8WyJ^83V6esH@zp5ap20H)W4~_ZJPK8 zZp2^dsH)&fX1;7qv|z)42y8TwnG{roU-+6hl{{JC0$_M)ToRnyiJJ(X1Ji)}*dM9l z^+d1f*+9|6E>f2y2UY#GKJkyQ#H+W+v>X`XOI=>&Y$vW}FNSrXHn8UtHf!GgnztY& zsCrtw5kq_?84dAOhd>-+tD|V*bWNO7HK-ngIPB$B{oor4@+{tgns+X7E5LWXoSy0{ z{;)S9chyiCr%4DQ%3Qaz}yhCwtO|#j~117D!JfUV8JH1_WXd}-sD6PUEdL?g z&ix0$B5{Rrv^#gR{tRKX?Kd z;t{#kl41=5q2seekyU*i`m{ovld85trJwcd{wGBqT?|%UD=uM>i)og!$${ID`-rOG~xDHU_3DLUFT+0&KBa1x`xeHpboHi z2TlA;Z)f6Hq(X}81=UiE_gd254DJP*H=^#*#IjB{iyQNS46Nl-7UtE2nc6l@N1Rtb zsJ@1{rI%NIK%Sq$dDoT`tIl4HIG+%=2OQm(6*LgeVu84oXE{yY(MJPJ@9wR^XB`t% zlh*qR%_Tzw+y{&%ZqdYnaY^cF;^%;I^LR;vnktyf^V)2VPSU1nHfk0&466C?hPA*8 z$x{r@h+O9rPt(L_^rMA>p5PL&{#H)X1Y!Z*R(mRz!=jENeMw_{Bg9QK@w=q|6#NE^ zz-9w=%j?k)xDs>&H}$}+7!|M8D!zrq9@ps}A5=d=Y*c(38K!~dzz`dknbjXca4)zM z?0JkO)1wpI)14>k{!%m?5`mjC82Y+=^(>+a$?($vrmDCa;vB7sO~h>l66BoOVMu%r z$hS^fk%J5FO~%!n98_H(4rxvNO+FdxRAqk4@Q&BKlfUED2ATI#tSZS#8J*8zjwL$i z88!-UCbk5wX}*yEos5}5_0xf6tf%%BvT_;WI+I6qtj-PpnI4-3)qU_DK#zwmBV1qn zf5_M(s2YCzuVrlG)-_y1;L6f^oOKiDqhmK>JH~FrY-CYkA@_FnlDP#!bi*$rgRLIN z{KVJgofcFNLt`3ZL(FS7`D9caOXHqO7(MmZk@d@8e^sXk)f}>Cy3|U=o~miO7?Hw0 zRde@Q32N;b{$jQG2nmmKfRc!n5AO;~Qzusxt9E(cCB$cNv;4F~IaMPVEqw2eDv>jS z>ev4V*$UvTUgFncjBMqi@jiZ~vK2QNmeMNRGN?|4B&-$JzG4B(Nrb~bb7fETkKfRL z0ol8fJw<1aJ#Nv~`{A6#nc6C-a^Y>Mc`rb$O03E|>C!f@imn1Q`&RF-`0i9iuoX+$}o85l+HruI{sXbo7>Cq1LT&vKGrNV^n3;C>fpm z*oD+%i^#-LHz%<~8vU*Du)2{pJZ@P9kpsZQC*05PNbx!|Mr`2bQSpxw_Z+axkx%}C z9<{H_>ib4@u;yDjfmBZG-AXh>f5B zg$%nu(hWXwdrf>iaqU4*&=u@Kh$0}onbuHeBDIs-E~pm4s~us)eJ%PrGTjD5;%kuj z6iw`1@TJ^4r6wPkKHYa^DT}@5OBs=fD^poPK3w4+Ha3?$>%dlvca7#f;YK!Wf=h4Y zx#4{N$R1Az&ku{l>-COL`D($PSaoLmpvvCpYvKmd-wqxDMqm`?_5g1Z_a68ZtOWLR zL+gvZ{gE!o>FL@g~qh`WGLE!5kSf*G)k27k*Lt5k+d<7iKCu}!4sWO9Y8|Dt=_yzMzOC`w+Y)$fn0x z>>4vp!(7x`hYa6!6qO)h4AQVOpG7GEF(Ap z*gO;ADS_vAc*F?Zuym|aXOplqFhs|Aw-UP(H}08u_2bj=<}*dUXBu(ufKR~+kd2*~Euaf^ zt7%8Sbqne9uMDbN;Wd5dI?`_jTY$T_^c9G;4{)jurHzAnU~LUr1ii8$&P7NmwV5X< z?iEyHE#gMxIRmr>BCzo4SJ9pGPEJr)65kh0za`1%jX;jq!{+?Q_qQ8i7l$!!f~YLi$R!tT!0Oq#KavcaRvvln}qB zagsWb&Hu)5Br@DDsD7{rP9a}Q(Avr``#A~meTXXn_Vj0XKv2c~=vT!H!&p&#gG4KU zluQILRq@ar^bcSqSOyBN<|yNZy!44bSfqWqlx(y7+|5CCH^jz)eNX!BUm5 zljl3ZpZF08#dii(gH1l+2-1H)Gf_Rj)zs!r&9{KKPeC^nxDZ8(9h+eI@<&C2sx5?J zFOw=@F-VS!_>PRGPE@g9RfEkHYfz!CK|4Z!T~?n~tDU=(=rK5yTb*}bqjW@u0X@fL`UlN(2#$>13v znh;*?Se;G8?EopGcy$BFDylch8YwGVuB}$))2pGog1Z@WZ1#!M$xsiR4GeK-(J3mP zP25{x1y~Av;EW9R!hq5y!lE=5u$SBbw@g(nVeEN=fHS)!Z z&y0BxoMjR0B3~jy%2R;!Uy`47X96pC;5-Sm2BJCP z-KtyD2;v^d!x>KG5BV(mOdkBoC%)hI-1#nySB$f099{RXewD1B5wD&n-y?i{(GasL zBEgwW+^gUNPz3DN(e2uXItdS(CZtrJIXDbU0Z zvB*;DKN<`n!((7GFcO=W+CIFSx8?3}R2FCn6z)1}2E_NrsUgRDFFDmZ*LzwkcqFJ= z|KV5N9MXRb8rJK&JjI6iPD_D?SEdTx?1%_wEI^anB4J#I+XcYBO$j4|Ij_Uc1%PFl#VsGMsZG z{PQO;60h`r)hQawA_=HAj(Z>#6&Fx%Dvx(f8RW2UK$WX_8k13abAV(w0(ZH@7g&15 z$^?#x)FNe3B@$<`Go&BH#@Kp5cs;`8aWw)zuLb^*xb#aC)G43|$Ps%0!rhHGgXP+c zb^CeiA>z``)72f}D#EcVa@O&oh3pF$^{ z(L~9!LA4BG6O1ORT;^-yL2g=_pzfl7$Bk+j$(s@66M4R&M)|Gh!0W)sl;sgS3FA5b z0n`WM88sRoBX&AMyM1G)CC>%bXn4iNETZt6kmX$RHMrbYVk6#Q5^84vk@?^S@DxxZ z@ywv*jeLxhCMy$D#@iOn463gnHo+A33-TE|ZOl!pu#|O9JY~(9#jxiue}dsgHFO z4zCl*E@T-Q4zU~wA8U>;goFPJh4gwt5j**BcTOUo1k*Vc!P{WxzOt>ec&1sOJeQ zJF{$VcG=7;Uwi8CkhhuFE?Q|!zneKfs4m*&^BR>sZSm6CczgB_M`r~PKLK&3S6uZR zgfdW=ZxKsxBjp`Wd85D$a&6&1QF}Gffe$EPIMShKEeNVj5Qn|w<%)d8B9=~JKZ-0S z`w6@K>~D}w>S39c{e7K%C2{h(yLWj}>O|z)Y(43#EuI~(q9+uwau%{T!s0dcyVl~x zLwgHEl~iyk`H!U6GZkzqV!f3=OUrdQ^^o&&P+bhK@i6DJTs?=f6ar&+?PORb`g)DX z8%gj!S7}$qO-m)D>H>?0kpdS(+lJ1IaLDDF(8ND-HN>rAiKA_*j;eE{X|RP*d=eL}*Lqa#xJ}Vhj~G>_!bEzOE{Yi= z7LoiZzA}9f9UW9f*)b~0e3gAd@KO@@u|a*Ti*mR+%F)E8d<76+ka##MN}y7s(@;dY zj#6J^PekH=b(9yQqcF*T=O_QIj`Cx4ln?K)Vnx&&$IQmtw zb=1(F?JJ7WQ69^GRVv;k1O3aUMa@q?M9znVoA z^Mi+71tkzH{09W(RgnKyP_?X4K}C@RRY4)?KS|Y{C6-Y_2eAqK4rJVA)p`6*;!-F0 zGy7smIg5j;g#4z&LGH_L`et0UdyS}DB_&qZ_SGbHJ~t#>)1OTAfO0lw*qUqH#%<{k z3f>N??GR_WsoCL3z8r815OGDYN4TVG~O`fDjc`F|nfj`!~ z)hDv&60`-UgRvJe=6T5z`20P3?%EJ%7YEg3h>i0-l8R<^U0qB@Lp;W7=uUUyOxV&Q zT03o2y;iy8f62;kjtK5$iJpJ}0cjfe2@*3jhTHra{>(3|aBy3~kZ1Z{!yJK0IAy%I;O$~8u zMO<$YvtlBlvWkd=$)9KC-$uju9~fxmU#;^GB~HSdB5zgV7 z1&k&lqKdJ44%tYY^9B3*E#huuxQ&6swOkEx7fn2cI0-LteE}F^;mzLbHBQ5uy_R)u zi?=w+q_!NQywM`QUK3|d=G6(14Vv)wn|mA>qkn0ctuOKBJPdL1m+ZN;hzF5J-W|;2 zY6Kpwc^4BW;Zv?FCo|`7OI#cyamiOfwbmj&hq{xE7~3r3shYUT;~sGa*EAr!#wK2i z(QwwfpsJCUpu*nM0qdG%=n8HIMq*~}B{(aH`yKoZK4I5*U-r`vIp5PnlewOXyB282 z`gKs<39)H*;;@@MK`#dkZ;|E|a`*QyEve!m#vry(|u^#d}k16zTSm>1t%;$x<8 zLJ4CW%~ElQVu@`Sn<)A=s9v{trRutqF9#UjO}w+{65mavg!{S1)?Mcq;&4e& zmBkQGA>VTrG4nMN9K-uwCA`CgH)2Vg2XRy0cr%*#oJ=x4E47H}i(TUSQ)$Pb6Ub)c zimizeF|DI$0}CPWn&DYb@`x)Q#5H16af~J&N90uS42X5bsoE8f<4rp0Z1Xl!br$gp z-h=cm7|@Deq|xl;%)sD?Y|3|x&cG{kS6X>zzY^&Ah;fE$6|9> zWf>cZSG_D^R}))(1eOBBJ74pLr?Wr`E(6&S{^@@stB|*`@HmXU3o&(< z_a~D$5SzL)$Jt#3Ej;iI)=h1t z%C_x_yT$bTsekd(0mNa~PN@d+h_O|D+86j&&0F_r{C{(9NH~-0cKo~9+v&;co!BAs z+Qkq*XKCVW(w`3o0i%h(H1XTStpS_CcR;Ex4GjzD>5>y6%7>UPg;ts_1 z2e*L2N0Tgx%gVB11kQ3osyW2`wi|9Ek9)2FSHt_F=6#*G)!=K;yD={?-o%Wq*>f;N zxA{l(Lsx2*km_m?|124Cx7)ZH;w74RH*v|)QycPdX|m^$eV|p~>N9CzH!*+A)ns3; zv$rJf0?-W%?XC}r)uY1fnDXXT4XN=K@Ac$)5)Uz$D|DVoaqhkZ=N=-b00~cXJ&-HP zJ|d(Ft@6$y{Q|HN7=eG(yywkg$N`3eTR;oEh3ASesg#$zmTfdqR6V4&S`xoOhIhe- zz!3kTi8m9sTjF2v&Th7y@=QHsF{YY-WJuM@@J%X6o~C{I=L}$o|I);l6W1RM2ZO*( zxE(o5R7Ug@bW%TUYlhUD2%M_bQjk&Ezx09FQWx89`hx?vLRr-|(?Dk)s=;s|gul7eM?I z#K!YHM5Y;_5E$Z#nz-5=gaxMqneDM%W!h{{;J2Rh3@IlRQkk`V7kn#u8DfpTJfiuChN`C_2wmaoTxaLwsKQU{yP$&WG3tTxG5|0ojPFAzq_-rxN!XSOwk( z9ckg+^q62~c2Zln4qwDo%I>JbqeFaG-6uA#vg%7d@gJJla+Q)@T28oLNKGbtn7<_$ zS9z3`eTU9|AXk}d*AP76`XTkQ#cNz;3y;@xl^o_H;jmm~Da2n`nbu*R@U-juj-8^@{S3qKP`#xCewKEC@?kDKoc(|?pv@K$VZ55 zSJ|b+dqgm;Hosv=rPc8@TxA}Qni2kK1PpN#O+1*mN5Kp*71*wFh&Cy4m77IxjY8@o zi}+*G%iQzVTn+E(ns*y z%-6)V;So)g!dr_c?<~#R5bd@Fqk*xB7tpZi-|4%6Pso60!BjAWrZJ=|8+FFj;|)!MU}J&HwbL+Zy9JWa@W=5I=w@g_5{z-Xd}*2MdZZ~|}f<`Jj^ zreY7R`^URgmv(-#`jjd*n#k@LQk|NLCQkHno4Px|9!0k8opv(Y_Dac{a*}VSukl+e z!S}$(l%-`lb1~01pa+nHP!{5Bb6Ziv)X-GjJs3MJI5(tTg*TPF2iT(MI?MxZQOs6J z6}Bkmbq=W;cn`<~Q`Q4+QHJm~9XZrr|YSP~ZUIvDE7y=NSAxr3c!F=!>=#R@90Yu>C z?qGpY!;UFzJ||~M*N|#|s_ze-clcru=n4$6*}M21aq;iswm>aVLSrojB5;pOyitgl zs0f^MNl5(yZ`hTIH$UwzQj9>{)}i!~lVkeG{7XYBsl~tR$|yhQO>3JleOYF=kb2{^ zf8UjrYF^Wo<-;3yhF^7bWsyqzGO4=*c4agS5!`fTsXg$sE&ZxH^sX#Yu`k=MyByt16Mx!TzgpE z);EPz?Q{I*UtzN~DTSdbCV}Gix7WG|irb)&E>MEmuljHIT4xRnsZT2r?a=pH*KG+! z({p`8zLj#z*5jY8?b>Fm^(gL*)B33s9n^uDqV9AbGAz%!IiwziCM?Ax1nYS_h4V>n zD$8uSo=n`aZ0@}I#$@;F1oo@+VQpc%&+&%)#qdt2hX}i@d`9JHkM|jmx1Otg89j^k z2Pbh5ACMrQJs2Bp(`r)@{gT`h@H4H&+f1#g@){V# zOcW1UvEt3}#H;OUO2(9x%Xg09DS@Z?`TJ^ottDTUrm0-vk=(%{^$-*xl1bRlHfmRr z1MQ;D(nT~6t0nLjcd?ogMXO{NwYNR{K-;LZHL>a8vu_Qly%+6Ee864Q{J3oUwznVV zxV$y|O{+x^pBz29^{6_PZLQALVweFzF{yi9`tS9Y7o)eVAtAL2Ufhp6%Kpb&tMg;@ zRtRy+Zik~cmbA=%d0TM>F~s4aA@y`OdoOW?J?VupipwPV5#9g2;)-GvR{-yym;DEd zD~>5&>TMylqQ`%rxRMy+Jcys^xnISV#waeI>ER?Oc8vCW(6Q5yT zq}a^8*kkY2R&R)8ELq(iQh&i4HWs&yOjVXTsu?g|?pW_fomIqr51eJJ_HkX!lR~!_ z`PeOwB~3Sak2}&I>>_>E@Q~U}%QHP`H}YHw`T@h+Uh|G1?$KooX{YnY6F}adHf!an zT4HelHRwM|AijeB-w@9x{UWdm7~(rLaT#&#-(!^zbO-rQ@K{seX<(1ujbL0$L1bh| zy#%odxn%g1UThdwc`lRT!`;R_s2I}7_Xit%^Y9^yU$DN ztR$`k`~>9e-LoF*O@oql%AOD35y_EQAM z&pwCRK#x41{iY{bvQcTSUA{y7UhXGR5T?j0ESYD;@Mh(OR4~Uab2GPSEg(D_bg6{c zoSbka_gv!WTgcs}2#yXOhf5KAYMvQUN}K6N)~jh#68v}X+GLInsX_mSqHaqVro+(0 zrB+Ht5oY(Lu?nN0p$OrRX=K=Tw(0D%?h2{((3qjoJtW;9O+NQ78tzTEdqbm$85)&9 zlYX^tqfe3a1uzf9O7jMB<~=cYkY??0$kEkhMt`|?ht#=sCz9p}_IF^4R{2oOf#RPjyL^nCd2dL42aRzt@>-%$}-b$1yqN&CB<;>jits;9!nXA=bZXNew=@#)J8(9V3 z=%@}%tQpP{I0wTSc8jJ|6_EpU1F=ddB<_8%9;^Xf`k0LXWn~lf6oOe+&m0$06D;2P zAFw70P6zuap&gOugNwn9iz|LvDo-oH5SKta*CLMn0F>R_-A`6gcnKB1SQT+=%>Bm@ z=iMLT>}G$^(gR_x14BTpCT0~Ss&T~U1Nokky>z@>&x57mX4o~V!ViR03B1P4rjuuG zgn!-!vBWTEG@A2@4 z%_!t>>aMZ_c%GW(37q>74Z{+66Lo$YUkln%iNJ9yC`3IrjUG`iai9LFAV%U+h_A4S zhw?IQDg^a~1Wnn-b~)mXCM!B;(bU5Z^$Ye7tKU z*H{%7#t599A5vp2-q@pvjKJ=96itUpLH5yvX&*-7Vu)X`i0?s|37`PPYGMg-M}5Q5 z6R z{*k~DqhGE@#hH(?fcS5TE8#7Kw|5M0WHuepOCYxH4ok%od0MfEf1$p2fP|0swTXJf zoeEk4zA{?zJBoW^9FTe}q#n13O?$qe5@N4CSKge9Vp>NYybItB>*sDIy;3(wudIaF zbV_}>C!Lb*fQmJ-aX^`qLh3_H;Dg#kg!X(W&8`sQpAU!l5P2h+QC1hP^R4(?eE5x& zbVMbZm`29i+6t&b=dx~6ypAeKzxYa z#`ll8PlVJsi&(m#Gb!mgAXXDSh?6epMy|14&<;H;F%^|Lg(ntx&7@!*D$0Mz zESMHj)%*FxUy<=wunokPdJl2V$Gk)fVu;I1v=1@7*-tX_Z}EBp(^1J5t61U#NW720 z>Zy=A4`MS;G~ZH8N2pldeZHj_u^tCYW87&j#MkU2@u3N9ds8E^@uuN|kcw!5DL=

gHmv$ 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�?@2X5K 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 ElCbw!jP!ealwMod!=5UNz%~Kohus|QZaAo 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%0Dp> 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